自機座標はx,y,敵座標はex,ey 自機弾丸座標はbx,by,敵弾丸座標はebx,ebyで拾えます/br ただし敵弾丸座標は正確ではないかもしれません /*自機生成*/ mySprite * my_chara_new (myAnimeArea *area, gchar *file, gint timeout) { mySprite *sprite = g_new0(mySprite, 10); sprite->anime_area = area; sprite->pixbuf = gdk_pixbuf_new_from_file(file, NULL); sprite->width = gdk_pixbuf_get_width(sprite->pixbuf); sprite->height = gdk_pixbuf_get_height(sprite->pixbuf); g_signal_connect(G_OBJECT(window), "key-press-event", G_CALLBACK(cb_key_press),(gpointer)sprite); g_signal_connect(G_OBJECT(window), "key-release-event", G_CALLBACK(cb_key_release),(gpointer)sprite); g_signal_connect(G_OBJECT(window), "delete_event", G_CALLBACK(cb_delete_event), (gpointer)sprite); sprite->timeout = g_timeout_add(chara_hayasa, (GSourceFunc)cb_sprite_timeout_chara, sprite);//gif動作速度 sprite->timeout = g_timeout_add(chara_hindo, (GSourceFunc)cb_update_sprite, sprite);//gif更新頻度 read_anime(sprite,"../images/animation_right.gif"); area->sprites = g_list_prepend(area->sprites, sprite); return sprite; } /*敵機生成*/ mySprite * my_enemy1_new (myAnimeArea *area, gchar *file, gint timeout) { mySprite *sprite = g_new0(mySprite, 10); sprite->anime_area = area; sprite->pixbuf = gdk_pixbuf_new_from_file(file, NULL); sprite->width = gdk_pixbuf_get_width(sprite->pixbuf); sprite->height = gdk_pixbuf_get_height(sprite->pixbuf); // スプライトの初期座標とベクトルの設定 GRand *rand = g_rand_new(); while((sprite->x = g_rand_int_range(rand, -(area->width/2), area->width/2)) == 0); sprite->x = 180; sprite->y = 90; //y座標の初期値 sprite->dx = 1; //動く方向の切片 sprite->dy = 0; g_rand_free(rand); sprite->timeout = g_timeout_add(50, (GSourceFunc)cb_sprite_timeout_enemy, sprite); sprite->timeout = g_timeout_add(100, (GSourceFunc)cb_update_sprite, sprite);//gif更新頻度 sprite->timeout = g_timeout_add(1500, (GSourceFunc)cb_sprite_timeout_enemybullet, sprite); //弾発射 g_signal_connect(G_OBJECT(window), "delete_event", G_CALLBACK(cb_delete_event), (gpointer)sprite); read_anime(sprite,"../images/enemy1.gif"); area->sprites = g_list_prepend(area->sprites, sprite); return sprite; } /*敵機生成2*/ mySprite * my_enemy2_new(myAnimeArea *area, gchar *file, gint timeout) { mySprite *sprite = g_new0(mySprite, 1); sprite->anime_area = area; sprite->pixbuf = gdk_pixbuf_new_from_file(file, NULL); sprite->width = gdk_pixbuf_get_width(sprite->pixbuf); sprite->height = gdk_pixbuf_get_height(sprite->pixbuf); // スプライトの初期座標とベクトルの設定 GRand *rand = g_rand_new(); while((sprite->x = g_rand_int_range(rand, -(area->width/2), area->width/2)) == 0); /* while((sprite->y = g_rand_int_range(rand, -(area->height/2), area->height/2)) == 0); */ /* while((sprite->dx = g_rand_int_range(rand, -5, 5)) == 0); */ /* while((sprite->dy = g_rand_int_range(rand, -5, 5)) == 0); */ sprite->x = 180; sprite->y = 90; sprite->dx = 1; sprite->dy = 0; /* int n = g_rand_int_range(rand,10, 40); */ /* g_rand_free(rand); */ /* sprite->timeout = g_timeout_add(n, */ /* (GSourceFunc)cb_sprite_timeout_enemy, */ /* sprite); */ //移動頻度 sprite->timeout = g_timeout_add(60, (GSourceFunc)cb_update_sprite, sprite);//gif更新頻度 g_signal_connect(G_OBJECT(window), "delete_event", G_CALLBACK(cb_delete_event), (gpointer)sprite); read_anime(sprite,"../images/enemy1.gif"); area->sprites = g_list_prepend(area->sprites, sprite); return sprite; } /*オブジェクト生成*/ mySprite * my_object_new (myAnimeArea *area, gchar *file, gint timeout) { mySprite *sprite = g_new0(mySprite, 1); sprite->anime_area = area; sprite->pixbuf = gdk_pixbuf_new_from_file(file, NULL); sprite->width = gdk_pixbuf_get_width(sprite->pixbuf); sprite->height = gdk_pixbuf_get_height(sprite->pixbuf); sprite->timeout = g_timeout_add(10, (GSourceFunc)cb_sprite_timeout_object, sprite); sprite->timeout = g_timeout_add(10, (GSourceFunc)cb_update_sprite, sprite);//gif更新頻度 g_signal_connect(G_OBJECT(window), "delete_event", G_CALLBACK(cb_delete_event), (gpointer)sprite); read_anime(sprite, file); printf("printLIFE\n"); area->sprites = g_list_prepend(area->sprites, sprite); return sprite; } /*自機弾生成*/ mySprite * my_bullet_new (myAnimeArea *area, gchar *file, gint timeout) { mySprite *sprite = g_new0(mySprite, 10); sprite->anime_area = area; sprite->pixbuf = gdk_pixbuf_new_from_file(file, NULL); sprite->width = gdk_pixbuf_get_width(sprite->pixbuf); sprite->height = gdk_pixbuf_get_height(sprite->pixbuf); if(rightFlag == true){ sprite->x = x + 40; sprite->y = y - 5; //y座標の初期値 sprite->dx = 1; //動く方向の切片 }else if (leftFlag == true){ sprite->x = x - 40; sprite->y = y - 5; //y座標の初期値 sprite->dx = -1; } sprite->dy = 0; sprite->timeout = g_timeout_add(dansoku, (GSourceFunc)cb_sprite_timeout_bullet, sprite); sprite->timeout = g_timeout_add(60, (GSourceFunc)cb_update_sprite, sprite);//gif更新頻度 g_signal_connect(G_OBJECT(window), "delete_event", G_CALLBACK(cb_delete_event), (gpointer)sprite); read_anime(sprite,"../images/tama.png"); area->sprites = g_list_prepend(area->sprites, sprite); return sprite; } /*敵機弾生成*/ mySprite * my_bullet_enemy_new (myAnimeArea *area, gchar *file, gint timeout) { mySprite *sprite = g_new0(mySprite, 10); sprite->anime_area = area; sprite->pixbuf = gdk_pixbuf_new_from_file(file, NULL); sprite->width = gdk_pixbuf_get_width(sprite->pixbuf); sprite->height = gdk_pixbuf_get_height(sprite->pixbuf); if(e_rightFlag == true){ sprite->x = ex + 40; sprite->y = ey - 5; //y座標の初期値 sprite->dx = 1; //動く方向の切片 }else if (e_leftFlag == true){ sprite->x = ex - 30; sprite->y = ey - 5; //y座標の初期値 sprite->dx = -1; } sprite->dy = 0; sprite->timeout = g_timeout_add(20, (GSourceFunc)my_enemybullet_move, sprite); sprite->timeout = g_timeout_add(60, (GSourceFunc)cb_update_sprite, sprite);//gif更新頻度 g_signal_connect(G_OBJECT(window), "delete_event", G_CALLBACK(cb_delete_event), (gpointer)sprite); read_anime(sprite,"../images/etama.png"); area->sprites = g_list_prepend(area->sprites, sprite); return sprite; } /*スプライト描写*/ static GdkPixbufAnimation * read_anime(mySprite *sprite, char *filename) { GdkPixbufAnimation *anim; GdkPixbufAnimationIter *iter; anim = gdk_pixbuf_animation_new_from_file(filename, NULL); sprite->iter = iter = gdk_pixbuf_animation_get_iter(anim, NULL); sprite->pixbuf = gdk_pixbuf_animation_iter_get_pixbuf(iter); return(anim); } /* スプライトを動かす (callback) */ static gint cb_sprite_timeout_chara(gpointer data) { my_sprite_move((mySprite *) data); return TRUE; } static gint cb_sprite_timeout_enemy(gpointer data) { my_enemy_move((mySprite *) data); return TRUE; } static gint cb_sprite_timeout_object(gpointer data) { my_object_move((mySprite *) data); return TRUE; } static gint cb_sprite_timeout_bullet(gpointer data) { my_bullet_move((mySprite *) data); return TRUE; } static gint cb_sprite_timeout_enemybullet(gpointer data) { my_enemybullet_move((mySprite *) data); my_bullet_enemy_new(area,"../images/tama.png",10); return TRUE; } /* ドローイングエリアにスプライト達を描く */ static void my_sprites_draw(myAnimeArea *area) { GList *sprites = area->sprites; /* gpointer sprite; */ while(sprites!=NULL) { /* sprite = sprites->data; */ my_sprite_draw((mySprite *) sprites->data); sprites = g_list_next(sprites); } } /* スプライト削除 */ void my_sprite_remove(mySprite *sprite) { if(sprite->timeout) g_source_remove(sprite->timeout); { myAnimeArea *area = sprite->anime_area; GList *sprites = area->sprites; area->sprites = g_list_remove_all(sprites,(gpointer) sprite); g_object_unref((gpointer)sprite->pixbuf); g_free((gpointer) sprite); } } void my_anime_area_remove(myAnimeArea *area) { GList *sprites = area->sprites; mySprite *sprite; while((sprite=(mySprite *)g_list_first(sprites))!=NULL) { my_sprite_remove(sprite); } if(area->timeout) g_source_remove(area->timeout); } /* ドローイングエリアにスプライトを描く */ static void my_sprite_draw(mySprite *sprite) { GtkWidget *drawing_area = (sprite->anime_area)->drawing_area; cairo_t *cr; cr = gdk_cairo_create(drawing_area->window); gdk_cairo_set_source_pixbuf(cr, sprite->pixbuf, sprite->x, sprite->y); cairo_paint(cr); cairo_destroy(cr); } /* ドローイングエリアを更新 */ static void my_anime_area_draw(myAnimeArea *area) { static GdkRectangle rect = {0, 0, 0, 0}; rect.width = area->width; rect.height = area->height; gdk_window_begin_paint_rect(area->drawing_area->window, &rect); /* セットしてある背景でドローイイングエリアをクリア */ if (area->bg_pixmap!=NULL) { gdk_window_clear(area->drawing_area->window); } /* ドローイングエリアにスプライト達を描く */ my_sprites_draw(area); /* ダブルバッファ処理の終了 */ gdk_window_end_paint(area->drawing_area->window); } /* タイムアウト */ static gint cb_anime_area_timeout(gpointer data) { my_anime_area_draw((myAnimeArea *)data); return TRUE; } /* エクスポーズイベント */ static gint cb_anime_area_expose(GtkWidget *widget, GdkEventExpose *event, gpointer data) { my_anime_area_draw((myAnimeArea *)data); return FALSE; } /* スプライト更新 */ static gint cb_update_sprite(gpointer data) { mySprite *anime = (mySprite *)data; /* スプライトの画像を更新する必要があるかチェック */ if(gdk_pixbuf_animation_iter_advance(anime->iter, NULL)) { /* 更新の必要があったら */ /* 新しいスプライトの画像をスプライト用ピクスバッファにコピー */ anime->pixbuf = gdk_pixbuf_animation_iter_get_pixbuf(anime->iter); /* ドローイングエリアを更新 */ my_anime_area_draw(anime->anime_area); } return TRUE; } /* configureイベントのコールバック */ static gint cb_anime_area_configure(GtkWidget *widget, GdkEventExpose *event, gpointer data) { myAnimeArea *area = (myAnimeArea *) data; /* ピックスマップをドローイングエリアの背景に設定 */ if (area->bg_pixmap!=NULL) { gdk_window_set_back_pixmap(widget->window, area->bg_pixmap, FALSE); } return FALSE; } /* スプライトが動く領域を生成 */ myAnimeArea * my_anime_area_new(gint width, gint height, GdkPixmap *back, gint timeout) { myAnimeArea *area = (myAnimeArea *) g_new0(myAnimeArea, 1); area->sprites = (gpointer) NULL; area->bg_pixmap = back; area->width = width; area->height = height; area->drawing_area = gtk_drawing_area_new(); gtk_widget_show(area->drawing_area); gtk_widget_set_size_request(GTK_WIDGET(area->drawing_area), area->width, area->height); /* configureイベントのコールバックを設定 ドローイングエリア生成時に背景を設定する */ gtk_widget_set_events(area->drawing_area, GDK_STRUCTURE_MASK); /* 最後の引数はコールバックの第3引数になる */ g_signal_connect(G_OBJECT(area->drawing_area), "configure_event", G_CALLBACK(cb_anime_area_configure), (gpointer)area); g_signal_connect(G_OBJECT(area->drawing_area), "expose_event", G_CALLBACK(cb_anime_area_expose), (gpointer)area); area->timeout = g_timeout_add(timeout, (GSourceFunc)cb_anime_area_timeout, (gpointer) area); return area; } /* キーボードコールバック関数 */ static gboolean cb_key_press(GtkWidget *widget, GdkEventKey *event, gpointer user_data) { mySprite *sprite = (mySprite *)user_data; if (event->keyval == 65361){ left = 1; leftFlag =true; rightFlag =false; read_anime(sprite,"../images/animation_run_left.gif"); /*左キー*/ } if (event->keyval == 65362){ if(x != 180 && leftFlag == true){ up = 1; read_anime(sprite,"../images/animation_jump_left.gif"); }else if(x != 180 && rightFlag == true){ up = 1; read_anime(sprite,"../images/animation_jump_right.gif"); }else if (x == 180 && rightFlag == true){ up = 0; x = 0; bgFlag++; gtk_main_quit(); /* 上キー */ } } if (event->keyval == 65363){ right = 1; leftFlag =false; rightFlag =true; read_anime(sprite,"../images/animation_run_right.gif"); /*右キー*/ } if (event->keyval == 65364){ down = 1; if(n == 0){ n++; }else if(n != 0){ n = 0; } /*下キー*/ } if (event->keyval == 122){ if(rightFlag == true){ read_anime(sprite,"../images/animation_attack_right.gif"); my_bullet_new(area,"../images/tama.png",100); }else if (leftFlag == true){ read_anime(sprite,"../images/animation_attack_left.gif"); my_bullet_new(area,"../images/tama.png",100); } printf("attack\n"); /*zキー*/ } return FALSE; } static gboolean cb_key_release(GtkWidget *widget, GdkEventKey *event, gpointer user_data) { mySprite *sprite = (mySprite *)user_data; if (event->keyval == 65361){ g_print("x = %f\n",x); left = 0; read_anime(sprite,"../images/animation_left.gif"); /*左キー離す*/ } if (event->keyval == 65362){ g_print("y = %f\n",y); up = 0; /*上キー離す*/ } if (event->keyval == 65363){ right = 0; g_print("x = %f\n",x); read_anime(sprite,"../images/animation_right.gif"); /*右キー離す*/ } if (event->keyval == 65364){ down = 0; g_print("y = %f\n",y); /*下キー離す*/ } if (event->keyval == 122){ if(rightFlag == true){ read_anime(sprite,"../images/animation_right.gif"); }else if (leftFlag == true){ read_anime(sprite,"../images/animation_left.gif"); } } return FALSE; } /* 自機移動 */ void my_sprite_move(mySprite *sprite) { /* mySprite *sprite = (mySprite *)user_data; */ /*横移動*/ if(left == 1){ vx -= ACCEL_X; if (vx < -MAX_SPEED){ vx = -MAX_SPEED; } }else if(right == 1){ vx += ACCEL_X; if (vx > MAX_SPEED){ vx = MAX_SPEED; } } else { if (vx < 0){ vx++; } else if (vx > 0){ vx--; } } x += (int)vx; /*画面内に収める*/ if(x<0) {x = 0; vx = 0;} else if (x > haikei_w-CHARA_SIZE){x = haikei_w-CHARA_SIZE; vx = 0;} /*ジャンプ*/ if (!jumpFlag) { if (up == 1) { vy = -JUMP_POWER; jumpFlag = true; printf("jumpFlag = true\n"); } }else{ vy++; y += vy; if (y > haikei_h-CHARA_SIZE - 10) { y = haikei_h-CHARA_SIZE - 10; jumpFlag = false; printf("jumpFlag = false\n"); if(leftFlag == true){ read_anime(sprite,"../images/animation_left.gif"); }else if (rightFlag == true){ read_anime(sprite,"../images/animation_right.gif"); } } } sprite->x = x; sprite->y = y; } /* 敵移動 */ void my_enemy_move(mySprite *sprite) { /* myAnimeArea *area = sprite->anime_area; */ int w = haikei_w; /* int h = haikei_h; */ ex = sprite->x, ey = sprite->y; edx = sprite->dx, edy = sprite->dy; gint width = sprite->width; /* gint height = sprite->height; */ /* スプライトの座標を更新 */ ex += edx; ey += edy; /* 端まで行ったら跳ね返す */ if(ex < 0) { ex += 0 - ex; edx = -edx; } if(ex > w - width) { ex += w - width - ex; edx = -edx; } if(ex < 130){ edx = -edx; } /* if(ey < 0) { ey += 0 - ey; edy = -edy; } */ /* if(ey > h - height) { ey += h - height - ey; edy = -edy; } */ sprite->x = ex; sprite->y = ey; sprite->dx = edx; sprite->dy = edy; } void my_object_move(mySprite *sprite) { gint ex = sprite->x, ey = sprite->y; gint edx = sprite->dx, edy = sprite->dy; /* HPバーの座標を設定 */ ex += edx; ey += edy; sprite->x = ex = HpBar_x; sprite->y = ey = HpBar_y; sprite->dx = edx; sprite->dy = edy; if(n == 0){ read_anime(sprite,"../images/LIFE0.png"); }else if (n==1){ read_anime(sprite,"../images/LIFE1.png"); } } /*弾削除*/ void bullet_remove(mySprite *self) { my_sprite_remove(self); } /*自機弾操作*/ void my_bullet_move(mySprite *sprite) { double bullet_x = 0,bullet_y = 0; double bullet_dx = 0, bullet_dy = 0; bullet_x = sprite->x, bullet_y = sprite->y; bullet_dx = sprite->dx, bullet_dy = sprite->dy; bullet_x += bullet_dx; bullet_y += bullet_dy; if(rightFlag == true && leftFlag == false){ if(bullet_x < 0) { bullet_x++; } }else if (leftFlag == true && rightFlag == true){ if(bullet_x < 0) { bullet_x--; } } sprite->x = bullet_x; sprite->y = bullet_y; sprite->dx = bullet_dx; sprite->dy = bullet_dy; bx = sprite->x; by = sprite->y; bdx = sprite->dx; bdy = sprite->dy; printf("bx = %f\n",bx); if(bx < 0 || bx > haikei_w){ bullet_remove(sprite); } } /*敵機弾操作*/ void my_enemybullet_move(mySprite *sprite) { ebx = sprite->x, eby = sprite->y; ebdx = sprite->dx, ebdy = sprite->dy; if(e_rightFlag == true && e_leftFlag == false){ ebx++; }else if (e_leftFlag == true && e_rightFlag == false){ ebx--; } ebx += ebdx; eby += ebdy; sprite->x = ebx; sprite->y = eby; sprite->dx = ebdx; sprite->dy = ebdy; } /*デリートイベント*/ static gint cb_delete_event(GtkWidget *widget, GdkEventExpose *event, gpointer data) { mySprite *sprite = (mySprite *)data; /* timeoutイベントを停止させる */ if(sprite->timeout) g_source_remove(sprite->timeout); printf("delete\n"); /* 続けてdestroyを実行 */ return FALSE; }