SDLでボン○ーマンを作ってみる3
今回は、爆弾を置いて爆弾が消えるまでの処理を追加。
サンプル画像
ソースコードはこちら
http://www.geocities.jp/finnissy/data/090719.zip
gfx.c
#include "gfx.h" #include "import.h" #include "libttf.h" #include <stdio.h> #define ID_BOMM (0x100) #define ID_BACK (0x200) #define OVER_COUNT (120) //16ms * 240count = 4sec // private method static void back_graund(SDL_Surface *surface,const char *path); static void push(SDL_Rect *r); static void bomm_count(void); static void add_bomm(int x, int y); static void del_bomm(int id); static void clean_screen(int x,int y,int w,int h,int id); static void bomm_reset(void); typedef struct bomm_list{ int x,y; int map_x,map_y; int id; int cnt; struct bomm_list *next; } Bomm_List; static SDL_Surface *screen; //ウィンドウ画像ポインタ static SDL_Surface *back_buffer; //バックバッファー static SDL_Rect rects[UPDATE_MAX]; //更新情報 static Uint32 fps_rate; //fps計算用 static Uint16 fps_cnt; //fpsカウント static Sint16 map[HEIGHT_SIZE][WIDTH_SIZE];//2次元表 static Bomm_List *bomm_top; static Uint32 bomms = ID_BOMM; static const int FPS_X = 0; static const int FPS_Y = 0; static const int FPS_W = FRAME_WIDTH/2; static const int FPS_H = FONT_SIZE; static const int FIELD_BOMM = 3; static const int FIELD_DEATH = 4; static struct { SDL_Rect r; //前フレーム更新情報 int id; } old_draw[UPDATE_MAX]; static struct { SDL_Surface *surface; SDL_Rect r; //更新情報テーブル int id; } now_draw[UPDATE_MAX]; static struct { //矩形情報の合計 int now; int old; int update; } numrect; boolean init_gfx(void) { if(screen != NULL) return TRUE; /****************************/ /* スクリーンの初期化 */ /****************************/ screen = SDL_SetVideoMode( FRAME_WIDTH,FRAME_HEIGHT,FRAME_BPP,INIT_FLAG_VIDEO ); if(screen == NULL) { printf("Error get video memory"); return FALSE; } /********************************/ /* バックバッファーの初期化 */ /********************************/ back_buffer = SDL_AllocSurface( screen->flags, screen->w, screen->h, screen->format->BitsPerPixel, screen->format->Rmask, screen->format->Gmask, screen->format->Bmask, screen->format->Amask ); if(back_buffer == NULL) { printf("Error get video memory"); return FALSE; } /********************************/ /* フォントの初期化 */ /********************************/ if( !ttf_init(screen,PATH_FONT,FONT_SIZE, NULL) ){ printf("Error open fontimage"); return FALSE; } /************************************/ /* 画像の読み込み */ /************************************/ //TODO:配列にまとめて代入 images.back = SDL_LoadBMP(PATH_IMAGE01); images.ball = SDL_LoadBMP(PATH_IMAGE02); images.wall1 = SDL_LoadBMP(PATH_IMAGE03); images.wall2 = SDL_LoadBMP(PATH_IMAGE04); images.bomm1 = SDL_LoadBMP(PATH_IMAGE05); images.bomm2 = SDL_LoadBMP(PATH_IMAGE06); images.bomm3 = SDL_LoadBMP(PATH_IMAGE07); images.bomm4 = SDL_LoadBMP(PATH_IMAGE08); if(!images.back || !images.ball || !images.wall1 || !images.wall2 || !images.bomm1 || !images.bomm2 || !images.bomm3 || !images.bomm4 ) { printf("Error open picture image"); return FALSE; } /* 透過色を設定する */ // TODO:マルチプラットフォーム対応なら // 画像からピクセル値を取得する方が良い SDL_SetColorKey(images.ball, SDL_SRCCOLORKEY, 0x000000); SDL_SetColorKey(images.wall2, SDL_SRCCOLORKEY, 0x000000); SDL_SetColorKey(images.bomm1, SDL_SRCCOLORKEY, 0x000000); SDL_SetColorKey(images.bomm2, SDL_SRCCOLORKEY, 0x000000); SDL_SetColorKey(images.bomm3, SDL_SRCCOLORKEY, 0x000000); SDL_SetColorKey(images.bomm4, SDL_SRCCOLORKEY, 0x000000); /************************/ /* 背景の用意 */ /************************/ back_graund(back_buffer,PATH_MAP01); // screen Blit Image SDL_BlitSurface(back_buffer,NULL,screen,NULL); rects[0].x = 0; rects[0].y = 0; rects[0].w = screen->w; rects[0].h = screen->h; numrect.update++; return TRUE; } void quit_gfx(void) { int i; const int img_size = sizeof(images.arr) / sizeof(SDL_Surface*); if(screen != NULL) SDL_FreeSurface( screen ); /* イメージ構造体を解放する */ for(i = 0; i < img_size; i++) { if(images.arr[i] != NULL) SDL_FreeSurface(images.arr[i]); } } void fps(int elapsed,int frame_rate) { if( !fps_cnt ) { fps_rate = SDL_GetTicks(); fps_cnt++; } else if(++fps_cnt >= FRAME_RATE) { Uint32 elapsed = SDL_GetTicks() - fps_rate; Uint32 fps = (Uint32)(1000.0f/((double)elapsed/(double)FRAME_RATE)); SDL_Rect r = { FPS_X,FPS_Y,FPS_W,FPS_H }; SDL_BlitSurface(back_buffer, &r, screen, &r); r = ttf_puta_color(FPS_X,FPS_Y,0xAABBFF,"FPS : %.2d",fps); push( &r ); fps_rate = 0; //60回分の処理時間をリセット fps_cnt = 0; //1秒間の処理回数カウントをリセット } } void blit(int x,int y,SDL_Surface *surface,int id) { if(numrect.now < UPDATE_MAX) { int i = numrect.now; #if 0 rects[i].x = x < 0 ? 0 : x%FRAME_WIDTH; rects[i].y = y < 0 ? 0 : y%FRAME_HEIGHT; rects[i].w = w % (FRAME_WIDTH - rects[i].x); rects[i].h = h % (FRAME_HEIGHT - rects[i].y); #else now_draw[i].r.x = x; now_draw[i].r.y = y; now_draw[i].r.w = surface->w; now_draw[i].r.h = surface->h; now_draw[i].surface = surface; now_draw[i].id = id; #endif numrect.now++; } } boolean map_calc(int x,int y, int state) { int x1 = x / BLOCK_SIZE; int y1 = y / BLOCK_SIZE; int x2 = (x + BLOCK_SIZE-1) / (BLOCK_SIZE); int y2 = (y + BLOCK_SIZE-1) / (BLOCK_SIZE); switch( state ) { case MV_LEFT: return (!map[y1][x1] && !map[y2][x1]); case MV_RIGHT: return (!map[y1][x2] && !map[y2][x2]); case MV_UP: return (!map[y1][x1] && !map[y1][x2]); case MV_DOWN: return (!map[y2][x1] && !map[y2][x2]); default: break; } printf("move start point\n"); return TRUE; } void draw(void) { boolean flg; int i,j; /****************************/ /* 裏画面を描画 */ /****************************/ for(i = 0;i < numrect.now;i++) { flg = FALSE; for(j = 0;j < numrect.old;j++) //前フレームで描画した場所は裏画面を描画 { if(now_draw[i].id == old_draw[j].id) { SDL_Rect tmp = old_draw[j].r; push( &tmp ); SDL_BlitSurface(back_buffer, &tmp, screen, &tmp); old_draw[j].r = now_draw[i].r; //update the Rect Infomation flg = TRUE; break; } } if( !flg && (numrect.old < UPDATE_MAX)) //初登録のID { old_draw[numrect.old].r = now_draw[i].r; old_draw[numrect.old].id = now_draw[i].id; numrect.old++; } } /****************************/ /* 画像を描画 */ /****************************/ for(i = 0;i < numrect.now;i++) { SDL_Rect tmp = now_draw[i].r; push( &tmp ); if(now_draw[i].surface == back_buffer) { SDL_BlitSurface(now_draw[i].surface, &tmp, screen, &tmp); } else { SDL_BlitSurface(now_draw[i].surface, NULL, screen, &tmp); } } memset( now_draw, 0, sizeof(now_draw)); numrect.now = 0; } void update(void) { /********************************************/ /* 与えられた矩形情報を元に画面の更新 */ /********************************************/ SDL_UpdateRects(screen, numrect.update, rects); /********************************************/ /* 矩形情報をクリアする */ /********************************************/ memset(rects,0,sizeof(rects)); numrect.update = 0; } void bomm_start(int x,int y) { int x1 = (x + (BLOCK_SIZE>>1)) / BLOCK_SIZE; int y1 = (y + (BLOCK_SIZE>>1)) / BLOCK_SIZE; if(map[y1][x1] != FIELD_BOMM) { map[y1][x1] = FIELD_BOMM; printf("add_bomm\n"); add_bomm(x1,y1); add_func( bomm_count ); } } /************************************************/ /* プライベートメソッド */ /************************************************/ static void back_graund(SDL_Surface *surface,const char *path) { FILE *fp; boolean flg; int x,y; fp = fopen(path,"r"); if(fp == NULL) { printf("Error Mapfile loading\n"); return; } flg = FALSE; for(y = 0;y < WIDTH_SIZE;y++) { for(x = 0;x < HEIGHT_SIZE;x++) { SDL_Rect r; int c; r.x = x*BLOCK_SIZE; r.y = y*BLOCK_SIZE; while(!isdigit(c = fgetc(fp)) && !feof(fp) && !ferror(fp)); if(feof(fp) || ferror(fp)) { flg = TRUE; break; } map[y][x] = c = c - '0'; switch( c ) { case 0: SDL_BlitSurface(images.back,NULL,surface, &r); break; case 1: SDL_BlitSurface(images.wall1,NULL,surface, &r); break; case 2: SDL_BlitSurface(images.back,NULL,surface, &r); SDL_BlitSurface(images.wall2,NULL,surface, &r); break; default : break; } } if( flg ) break; } fclose(fp); } static void push(SDL_Rect *r) { if(numrect.update < UPDATE_MAX) { int i = numrect.update; #if 0 rects[i].x = r->x < 0 ? 0 : r->x%FRAME_WIDTH; rects[i].y = r->y < 0 ? 0 : r->y%FRAME_HEIGHT; rects[i].w = r->w % (FRAME_WIDTH - rects[i].x); rects[i].h = r->h % (FRAME_HEIGHT - rects[i].y); #else rects[i] = (*r); #endif numrect.update++; } } static void bomm_count(void) { Bomm_List *tmp; int anim_rate = (FRAME_RATE/2); float interval = (FRAME_RATE/8.0f); tmp = bomm_top; if(tmp == NULL) { del_func( bomm_count ); //爆弾アニメーションを解除する bomm_reset(); } else { do { if(++(tmp->cnt) % FRAME_RATE < anim_rate) { int cnt = tmp->cnt % anim_rate; if(cnt < interval) blit(tmp->x,tmp->y,images.bomm1,tmp->id); else if(cnt < interval*2) blit(tmp->x,tmp->y,images.bomm2,tmp->id); else if(cnt < interval*3) blit(tmp->x,tmp->y,images.bomm3,tmp->id); else if(cnt < interval*4) blit(tmp->x,tmp->y,images.bomm4,tmp->id); } else { int cnt = tmp->cnt % anim_rate; if(cnt < interval) blit(tmp->x,tmp->y,images.bomm4,tmp->id); else if(cnt < interval*2) blit(tmp->x,tmp->y,images.bomm3,tmp->id); else if(cnt < interval*3) blit(tmp->x,tmp->y,images.bomm2,tmp->id); else if(cnt < interval*4) blit(tmp->x,tmp->y,images.bomm1,tmp->id); } if(tmp->cnt == OVER_COUNT) //爆弾カウント時間切れ { Bomm_List *t = tmp; printf("bomm_clear\n"); printf("ID:%d\n",t->id); clean_screen (tmp->x,tmp->y,BLOCK_SIZE,BLOCK_SIZE,tmp->id); map[tmp->map_y][tmp->map_x] = 0; tmp = tmp->next; //次の爆弾へ del_bomm(t->id); } else { tmp = tmp->next; //次の爆弾へ } } while(tmp != NULL); } } static void add_bomm(int x, int y) { Bomm_List *bomm = (Bomm_List*)malloc(sizeof(Bomm_List)); if(bomm == NULL) return; memset(bomm,0,sizeof(Bomm_List)); bomm->id = bomms; bomm->x = x*BLOCK_SIZE; bomm->y = y*BLOCK_SIZE; bomm->map_x = x; bomm->map_y = y; bomm->next = bomm_top; bomm_top = bomm; printf("id:%d\n",bomm->id); bomms++; printf("bomm num:%d",bomms); } static void del_bomm(int id) { Bomm_List *tmp; Bomm_List *prev; tmp = bomm_top; prev = NULL; while(tmp != NULL) { if(tmp->id == id) { if(prev != NULL) { prev->next = tmp->next; free(tmp); break; } else { free(tmp); bomm_top = NULL; break; } } prev = tmp; tmp = tmp->next; } } static void clean_screen(int x,int y,int w,int h,int id) { #if 0 SDL_Rect r; r.x = (x < 0) ? 0 : x%(back_buffer->w - x); r.y = (y < 0) ? 0 : y%(back_buffer->h - y); r.w = w; r.h = h; push( &r ); SDL_BlitSurface(back_buffer, &r, screen, &r); #else if(numrect.now < UPDATE_MAX) { int i = numrect.now; now_draw[i].r.x = (x < 0) ? 0 : x%FRAME_WIDTH; now_draw[i].r.y = (y < 0) ? 0 : y%FRAME_HEIGHT; now_draw[i].r.w = w; now_draw[i].r.h = h; now_draw[i].surface = back_buffer; now_draw[i].id = id; numrect.now++; } #endif } static void bomm_reset(void) { bomms = ID_BOMM; } |