SDLでボンバーマン風ゲームを作ってみる6
こんにちは。
見てる人は少ないと思うが、久しぶりのブログ更新です。(´・∀・`)
今回は前回に引き続き、爆弾で壊せるコンテナの作成と、
同じく爆弾で殺せる敵を作ってみた。
本来なら、ブロックを崩すとアイテムが色々出てくるんですが
そこはまだ作ってません。
敵を全員殺しても残念ながらステージクリアにはなりません。(°ー°*)
そのうち時間を見て作りたいと思います。
サンプル画像
ソースコードはこちら
http://www.geocities.jp/finnissy/data/090901.zip
gfx.c
#include "gfx.h" #include "snd.h" #include "main.h" #include "game.h" #include "libttf.h" #include "routing.h" #include <stdio.h> #include <stdlib.h> #include <math.h> #define ID_BOMM (0x100) #define ID_BACK (0x200) #define ID_FIRE (0x300) #define ID_CONTAINER (0x400) #define ID_MONSTER (0x500) #define OVER_COUNT (3*(60)) //16ms * 240count = 4sec #define HUMAN_FRAME (4) #define MOVE_VALUE (1) #define TERRITORY (BLOCK_SIZE/8) #define NUM_ENEMY (8) /************************************************************/ /* 構造体変数宣言 */ /************************************************************/ typedef struct anime_list{ // 爆弾構造体 int x,y; int map_x,map_y; int id; int cnt; struct anime_list *next; } Bomm_List; typedef struct blit_info{ SDL_Surface *surface; //更新情報テーブル SDL_Rect r; int id; } Blit_Inof; static struct { SDL_Rect r; //前フレーム更新情報 int id; } old_draw[UPDATE_MAX]; static struct { SDL_Surface **arr; /* 爆風構造体 */ int frame,n; } bomm_img[MAX_LEVEL]; static struct { SDL_Surface **arr; /* コンテナ爆風構造体 */ int frame,n; } container_fire; static union { // 人間風ロボット SDL_Surface *arr[4*4]; struct { SDL_Surface *down[4]; SDL_Surface *left[4]; SDL_Surface *right[4]; SDL_Surface *up[4]; }; } humanoid; static struct { //矩形情報の合計 int now; int old; int front; int update; } numrect; static enum { // マップの定数 EMPTY = 0, FIELD_WALL, FIELD_STONE, FIELD_CONTAINER, FIELD_BOMM, FIELD_DEATH = 10, }; /************************************************************/ /* 変数宣言 */ /************************************************************/ static SDL_Surface *screen; //ウィンドウ画像ポインタ static SDL_Surface *back_buffer; //バックバッファー static SDL_Surface *play_map; //ゲームプレイ用バッファー 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 Bomm_List *fire_top; static Bomm_List *container_top; static Bomm_List *enemy_top; static Uint32 bomms = ID_BOMM; static Uint32 fires = ID_FIRE; static Uint32 containers = ID_CONTAINER; static Uint32 enemys = ID_MONSTER; static int text_id; static int enemy_frame; //enemy index 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 Blit_Inof now_draw[UPDATE_MAX]; static Blit_Inof front_draw[UPDATE_MAX]; /************************************************************/ /* 関数の定義 */ /************************************************************/ //----------------------private method----------------------// static void back_graund(SDL_Surface *surface,const char *path); static void set_block(void); static void set_enemy(void); static boolean bomm_load(void); static boolean container_fire_load(void); 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); static void back_draw(Blit_Inof *info,int now); static void blit_ttf(int x,int y,SDL_Surface *s); static void fire(int x,int y); static void fire_count(void); static void add_fire(int x, int y,int mapx,int mapy); static void del_fire(int id); static void fire_reset(void); static void fire_container(int x,int y); static void fire_count_container(void); static void add_fire_container(int x, int y,int mapx,int mapy); static void del_fire_container(int id); static void fire_container_reset(void); static void go_enemy(int x,int y); static void enemy_count(void); static void add_enemy(int x, int y,int mapx,int mapy); static void del_enemy(int id); static void enemy_reset(void); static mvdrc root_calc(int x, int y, Bomm_List *t); static boolean lock(SDL_Surface *s); static void unlock(SDL_Surface *s); static void set_alpha(SDL_Surface *s, Uint32 col); static Uint32 get_pixel(SDL_Surface *Surface, Sint32 X, Sint32 Y); static void fire_calc(int x,int y,int range,boolean flg); static int human_load(void); /************************************************/ /* Public Method */ /************************************************/ boolean init_gfx(void) { int i; const char *img_path[] = { //画像イメージのパス PATH_IMAGE01, PATH_IMAGE03, PATH_IMAGE04, PATH_IMAGE05, PATH_IMAGE06, PATH_IMAGE07, PATH_IMAGE08, PATH_IMAGE09, PATH_IMAGE10, PATH_IMAGE11, PATH_IMAGE12, }; 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; } /********************************/ /* バックバッファーの初期化 */ /********************************/ play_map = SDL_AllocSurface( screen->flags, screen->w, screen->h, screen->format->BitsPerPixel, screen->format->Rmask, screen->format->Gmask, screen->format->Bmask, screen->format->Amask ); if(play_map == NULL) { printf("Error get video memory"); return FALSE; } /********************************/ /* フォントの初期化 */ /********************************/ if( !ttf_init(screen,PATH_FONT,FONT_SIZE, blit_ttf) ){ printf("Error open fontimage"); return FALSE; } /************************************/ /* 画像の読み込み */ /************************************/ for(i = 0;i < PATH_IMAGE_MAX;i++) { images.arr[i] = SDL_LoadBMP(img_path[i]); if( !images.arr[i] ) return FALSE; } /* 透過色を設定する */ SDL_SetColorKey(images.wall2, SDL_SRCCOLORKEY, get_pixel(images.wall2,0,0)); SDL_SetColorKey(images.bomm1, SDL_SRCCOLORKEY, get_pixel(images.bomm1,0,0)); SDL_SetColorKey(images.bomm2, SDL_SRCCOLORKEY, get_pixel(images.bomm2,0,0)); SDL_SetColorKey(images.bomm3, SDL_SRCCOLORKEY, get_pixel(images.bomm3,0,0)); SDL_SetColorKey(images.bomm4, SDL_SRCCOLORKEY, get_pixel(images.bomm4,0,0)); SDL_SetColorKey(images.container1, SDL_SRCCOLORKEY, get_pixel(images.container1,0,0)); SDL_SetColorKey(images.container2, SDL_SRCCOLORKEY, get_pixel(images.container2,0,0)); SDL_SetColorKey(images.container3, SDL_SRCCOLORKEY, get_pixel(images.container3,0,0)); /************************/ /* 爆風の用意 */ /************************/ if( !bomm_load() ) return FALSE; /************************/ /* コンテナ爆風の用意 */ /************************/ if( !container_fire_load() ) return FALSE; /************************/ /* 人の用意 */ /************************/ if( !human_load() ) return FALSE; /************************/ /* 背景の用意 */ /************************/ back_graund(play_map,PATH_MAP01); /************************/ /* 背景の描画 */ /************************/ draw_scene(STATE_TITLE); return TRUE; } void quit_gfx(void) { int i; /********************************/ /* イメージ構造体を解放する */ /********************************/ for(i = 0; i < PATH_IMAGE_MAX; i++) //汎用画像構造体の開放 { if(images.arr[i] != NULL) SDL_FreeSurface(images.arr[i]); } for(i = 0; i < MAX_LEVEL; i++) //爆風画像構造体の開放 { int j; if(bomm_img[i].arr != NULL) { for(j = 0;j < sizeof(bomm_img[i].arr)/sizeof(bomm_img[i].arr[0]);j++) { if(bomm_img[i].arr[j] != NULL) SDL_FreeSurface(bomm_img[i].arr[j]); } free(bomm_img[i].arr); } } if(container_fire.arr != NULL) //コンテナ爆発画像構造体の開放 { for(i = 0; i < sizeof(container_fire.arr)/sizeof(container_fire.arr[0]); i++) { if(container_fire.arr[i] != NULL) SDL_FreeSurface(container_fire.arr[i]); } free(container_fire.arr); } for(i = 0; i < HUMAN_FRAME*4; i++) //人間画像構造体の開放 { if(humanoid.arr[i] != NULL) SDL_FreeSurface(humanoid.arr[i]); } /********************************/ /* フォントの開放 */ /********************************/ ttf_quit(); /********************************/ /* スクリーンの開放 */ /********************************/ if(screen != NULL) SDL_FreeSurface( screen ); } void draw_scene(gstate scene) { SDL_Rect r = {0,0,FRAME_WIDTH,FRAME_HEIGHT}; switch( scene ) { case STATE_TITLE: if(back_buffer != images.title) { back_buffer = images.title; SDL_BlitSurface(back_buffer,NULL,screen,NULL); push( &r ); } break; case STATE_PLAY: if(back_buffer != play_map) { back_buffer = play_map; //背景セット set_block(); //コンテナセット set_enemy(); SDL_BlitSurface(back_buffer,NULL,screen,NULL); push( &r ); } break; case STATE_END: //SDL_BlitSurface(back_buffer,NULL,screen,NULL); break; default: break; } } 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; 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; numrect.now++; } } void blit_text(int x,int y,Uint32 bc,Uint32 ec,const char *text,int id) { text_id = id; //必須。これが無いとまともに描画できない... ttf_put_grd(x,y,bc,ec,text); } void front_blit(int x,int y,SDL_Surface *surface,int id) { if(numrect.front < UPDATE_MAX) { int i = numrect.front; front_draw[i].r.x = x; front_draw[i].r.y = y; front_draw[i].r.w = surface->w; front_draw[i].r.h = surface->h; front_draw[i].surface = surface; front_draw[i].id = id; numrect.front++; } } void blit_human(int x,int y,int id,SDLKey key, int flg) { const int idx = flg % HUMAN_FRAME; switch( key ) { case SDLK_DOWN: blit(x, y, humanoid.down[idx], id); break; case SDLK_UP: blit(x, y, humanoid.up[idx], id); break; case SDLK_RIGHT:blit(x, y, humanoid.right[idx], id); break; case SDLK_LEFT: blit(x, y, humanoid.left[idx], id); break; default: break; } } 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; } boolean isdeath(int xt,int yt) { int x,xs; //surplus int y,ys; if(xt < 0 || xt >= FRAME_WIDTH || yt < 0 || yt >= FRAME_HEIGHT) return FALSE; x = xt / BLOCK_SIZE; y = yt / BLOCK_SIZE; xs = (xt % BLOCK_SIZE) > 0 ? 1 : 0; ys = (yt % BLOCK_SIZE) > 0 ? 1 : 0; /* printf("x % 32 = %d\n",x % BLOCK_SIZE); printf("y % 32 = %d\n",y % BLOCK_SIZE); printf("map[%d][%d] = %d\n",y,x,map[y][x]); printf("map[%d][%d] = %d\n",y,x+xs,map[y][x+xs]); printf("map[%d][%d] = %d\n",y+ys,x,map[y+ys][x]); printf("map[%d][%d] = %d\n",y+ys,x+xs,map[y+ys][x+xs]); */ if(map[y][x] >= FIELD_DEATH) return TRUE; else if(map[y][x+xs] >= FIELD_DEATH) return TRUE; else if(map[y+ys][x] >= FIELD_DEATH) return TRUE; else if(map[y+ys][x+xs] >= FIELD_DEATH) return TRUE; return FALSE; } boolean isenemy(int x,int y) { Bomm_List *t; t = enemy_top; while(t != NULL) { double f = pow(abs(x)-abs(t->x),2) + pow(abs(y)-abs(t->y),2); if(f <= pow(TERRITORY+TERRITORY,2)) return TRUE; t = t->next; } return FALSE; } void draw(void) { int i; back_draw(now_draw, numrect.now); back_draw(front_draw, numrect.front); /****************************/ /* 画像を描画 */ /****************************/ for(i = 0;i < numrect.now;i++) { SDL_Rect tmp = now_draw[i].r; push( &tmp ); if(now_draw[i].surface == back_buffer) { if(now_draw[i].surface && screen) SDL_BlitSurface(now_draw[i].surface, &tmp, screen, &tmp); else printf("draw error:image!\n"); } else { if(now_draw[i].surface && screen) SDL_BlitSurface(now_draw[i].surface, NULL, screen, &tmp); else printf("draw error:image!\n"); } } /****************************/ /* 爆風を描画 */ /****************************/ for(i = 0;i < numrect.front;i++) { SDL_Rect tmp = front_draw[i].r; push( &tmp ); if(front_draw[i].surface == back_buffer) { SDL_BlitSurface(front_draw[i].surface, &tmp, screen, &tmp); } else { SDL_BlitSurface(front_draw[i].surface, NULL, screen, &tmp); } } memset( now_draw, 0, sizeof(now_draw)); memset( front_draw, 0, sizeof(front_draw)); numrect.now = numrect.front = 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] == 0)||(map[y1][x1] >= FIELD_DEATH) ) { map[y1][x1] += FIELD_BOMM; printf("add_bomm\n"); add_bomm(x1,y1); add_func( bomm_count ); } } void death_effect(int x,int y) { fire_container(x,y); } boolean isfire(void) { return container_top == NULL; } /****************************************************/ /* private method */ /****************************************************/ static void back_draw(Blit_Inof *info,int now) { boolean flg; int i,j; if( !back_buffer || !screen ) return; /****************************/ /* 裏画面を描画 */ /****************************/ for(i = 0;i < now;i++) { flg = FALSE; for(j = 0;j < numrect.old;j++) //前フレームで描画した場所は裏画面を描画 { if(info[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 = info[i].r; //update the Rect Infomation flg = TRUE; break; } } if( !flg && (numrect.old < UPDATE_MAX)) //初登録のID { old_draw[numrect.old].r = info[i].r; old_draw[numrect.old].id = info[i].id; numrect.old++; } } } static void set_block(void) { int col,row; int block = (int)(WIDTH_SIZE*HEIGHT_SIZE*0.4); // 四隅は埋めない map[1][1] = map[1][2] = map[2][1] = -1; map[1][WIDTH_SIZE-2] = map[1][WIDTH_SIZE-3] = map[2][WIDTH_SIZE-2] = -1; map[HEIGHT_SIZE-2][1] = map[HEIGHT_SIZE-2][2] = map[HEIGHT_SIZE-3][1] = -1; map[HEIGHT_SIZE-3][WIDTH_SIZE-2] = map[HEIGHT_SIZE-2][WIDTH_SIZE-2] = map[HEIGHT_SIZE-2][WIDTH_SIZE-3] = -1; while( block ) { for(row = 1;row < HEIGHT_SIZE-1; row++) { for(col = 1;col < WIDTH_SIZE-1; col++) { if( !block ) //配置完了 goto CLEANUP; //ジャンプ if( !map[row][col] && rand() % 3 == 0) { SDL_Rect r; r.w = r.h = 0; r.x = col * BLOCK_SIZE; r.y = row * BLOCK_SIZE; map[row][col] = FIELD_CONTAINER; SDL_BlitSurface(images.container1,NULL,back_buffer,&r); block--; } } } } CLEANUP: #if 0 for(row = 0;row < HEIGHT_SIZE; row++) { for(col = 0;col < WIDTH_SIZE; col++) { if(map[row][col] == -1) map[row][col] = 0; } } #else map[1][1] = map[1][2] = map[2][1] = 0; map[1][WIDTH_SIZE-2] = map[1][WIDTH_SIZE-3] = map[2][WIDTH_SIZE-2] = 0; map[HEIGHT_SIZE-2][1] = map[HEIGHT_SIZE-2][2] = map[HEIGHT_SIZE-3][1] = 0; map[HEIGHT_SIZE-3][WIDTH_SIZE-2] = map[HEIGHT_SIZE-2][WIDTH_SIZE-2] = map[HEIGHT_SIZE-2][WIDTH_SIZE-3] = 0; #endif } static void set_enemy(void) { int col,row; int monster = NUM_ENEMY; boolean loop; // 四隅は埋めない map[1][1] = map[1][2] = map[2][1] = -1; map[1][WIDTH_SIZE-2] = map[1][WIDTH_SIZE-3] = map[2][WIDTH_SIZE-2] = -1; map[HEIGHT_SIZE-2][1] = map[HEIGHT_SIZE-2][2] = map[HEIGHT_SIZE-3][1] = -1; map[HEIGHT_SIZE-3][WIDTH_SIZE-2] = map[HEIGHT_SIZE-2][WIDTH_SIZE-2] = map[HEIGHT_SIZE-2][WIDTH_SIZE-3] = -1; loop = TRUE; while( monster ) { for(row = 1;row < HEIGHT_SIZE-1 && loop; row++) { for(col = 1;col < WIDTH_SIZE-1 && loop; col++) { if( !monster ) //配置完了 loop = FALSE; if( !map[row][col] && rand() % 3 == 0) { SDL_Rect r; r.w = r.h = 0; r.x = col * BLOCK_SIZE; r.y = row * BLOCK_SIZE; go_enemy(r.x,r.y); monster--; } } } } map[1][1] = map[1][2] = map[2][1] = 0; map[1][WIDTH_SIZE-2] = map[1][WIDTH_SIZE-3] = map[2][WIDTH_SIZE-2] = 0; map[HEIGHT_SIZE-2][1] = map[HEIGHT_SIZE-2][2] = map[HEIGHT_SIZE-3][1] = 0; map[HEIGHT_SIZE-3][WIDTH_SIZE-2] = map[HEIGHT_SIZE-2][WIDTH_SIZE-2] = map[HEIGHT_SIZE-2][WIDTH_SIZE-3] = 0; } static void blit_ttf(int x,int y,SDL_Surface *s) { blit(x,y,s,text_id); } 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 boolean bomm_load(void) { int i; const char *img = "bomm.bmp"; const char *txt = "info.txt"; FILE *fp_txt; for(i = 0;i < MAX_LEVEL;i++) { if(bomm_img[i].arr == NULL) { char path_img[255] = ""; char path_txt[255] = ""; char bnum[] = { '1'+i,'/','\0' }; int width; int frame; strncpy(path_img,PATH_BOMM,200); strncat(path_img,bnum,30); strncat(path_img,img,25); strncpy(path_txt,PATH_BOMM,200); strncat(path_txt,bnum,30); strncat(path_txt,txt,25); fp_txt = fopen(path_txt,"r"); if( fp_txt ) { SDL_Surface *surface = NULL; char tmp[10] = ""; fgets(tmp,10,fp_txt); width = atoi(tmp); fgets(tmp,10,fp_txt); frame = atoi(tmp); surface = SDL_LoadBMP(path_img); if(surface != NULL) { int num; int flg; const int w = width; const int h = width; /********************************/ /* ポインタ配列を取得 */ /********************************/ bomm_img[i].arr = (SDL_Surface**)malloc(sizeof(SDL_Surface*)*frame); if(bomm_img[i].arr == NULL) return FALSE; memset(bomm_img[i].arr,0,sizeof(SDL_Surface*)*frame); for(num = 0;num < frame;num++) { SDL_Rect r; r.x = num*w; r.y = 0; r.w = w; r.h = h; bomm_img[i].arr[num] = SDL_AllocSurface(screen->flags, w, h, screen->format->BitsPerPixel, screen->format->Rmask, screen->format->Gmask, screen->format->Bmask, screen->format->Amask ); if(bomm_img[i].arr[num] == NULL) return FALSE; flg = SDL_BlitSurface(surface, &r, bomm_img[i].arr[num], NULL);//画像転送 flg = SDL_SetColorKey(bomm_img[i].arr[num], SDL_SRCCOLORKEY,get_pixel(bomm_img[i].arr[num],0,0)); } if( surface ) SDL_FreeSurface( surface ); } else { return FALSE; } } else { return FALSE; } } } return TRUE; } static boolean container_fire_load(void) { const char *img = "container_fire.bmp"; const char *txt = "info.txt"; FILE *fp_txt; if(container_fire.arr == NULL) { char path_img[255] = ""; char path_txt[255] = ""; //char slash[] = { '1'+i,'/','\0' }; 拡張する際はこちら char slash[] = "/"; int width; int frame; strncpy(path_img,PATH_FIRE_CONTAINER,200); strncat(path_img,slash,30); strncat(path_img,img,25); strncpy(path_txt,PATH_FIRE_CONTAINER,200); strncat(path_txt,slash,30); strncat(path_txt,txt,25); fp_txt = fopen(path_txt,"r"); if(fp_txt != NULL) { SDL_Surface *surface = NULL; char tmp[10] = ""; fgets(tmp,10,fp_txt); width = atoi(tmp); fgets(tmp,10,fp_txt); frame = atoi(tmp); surface = SDL_LoadBMP(path_img); if(surface != NULL) { int num; int flg; const int w = width; const int h = width; /********************************/ /* ポインタ配列を取得 */ /********************************/ container_fire.arr = (SDL_Surface**)malloc(sizeof(SDL_Surface*)*frame); if(container_fire.arr == NULL) return FALSE; memset(container_fire.arr,0,sizeof(SDL_Surface*)*frame); for(num = 0;num < frame;num++) { SDL_Rect r; r.x = num*w; r.y = 0; r.w = w; r.h = h; container_fire.arr[num] = SDL_AllocSurface(screen->flags, w, h, screen->format->BitsPerPixel, screen->format->Rmask, screen->format->Gmask, screen->format->Bmask, screen->format->Amask ); if(container_fire.arr[num] == NULL) return FALSE; flg = SDL_BlitSurface(surface, &r, container_fire.arr[num], NULL);//画像転送 flg = SDL_SetColorKey(container_fire.arr[num], SDL_SRCCOLORKEY,get_pixel(container_fire.arr[num],0,0)); } if( surface ) SDL_FreeSurface( surface ); } else { return FALSE; } } else { return FALSE; } } return TRUE; } static int human_load(void) { FILE *fp; int i,w; int imgw; char tmp[10] = ""; SDL_Surface *t = SDL_LoadBMP(PATH_HUMAN); fp = fopen(PATH_TEXT01,"r"); if(!t || !fp) return FALSE; fgets(tmp,10,fp); imgw = atoi(tmp); for(i = w = 0;i < t->w/imgw; i++,w += imgw) { SDL_Rect r; humanoid.arr[i] = SDL_AllocSurface( t->flags, imgw, t->h, t->format->BitsPerPixel, t->format->Rmask, t->format->Gmask, t->format->Bmask, t->format->Amask ); if( !humanoid.arr[i] ) { printf("err humanoid\n"); continue; } r.h = t->h; r.w = imgw; r.x = w; r.y = 0; SDL_BlitSurface(t,&r,humanoid.arr[i],NULL); SDL_SetColorKey(humanoid.arr[i], SDL_SRCCOLORKEY,get_pixel(humanoid.arr[i],0,0)); } if(t != NULL) SDL_FreeSurface( t ); return TRUE; } 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 printf("Un Drawing\n"); } 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); else printf("Un Drawing\n"); } /****************************/ /* 爆弾時間切れ・誘発爆発 */ /****************************/ if((tmp->cnt == OVER_COUNT) || (map[tmp->map_y][tmp->map_x] >= FIELD_DEATH)) { Bomm_List *t = tmp; int x = t->map_x; int y = t->map_y; printf("bomm_clear\n"); printf("ID:%d\n",t->id); //clean_screen(tmp->x,tmp->y,BLOCK_SIZE,BLOCK_SIZE,tmp->id); //map[y][x] = map[y][x] & (~FIELD_BOMM); // フラグを落とす map[y][x] -= FIELD_BOMM; fire(t->x + BLOCK_SIZE/2 , t->y + BLOCK_SIZE/2); switch( get_level() ) { //効果音再生 case 1: play_se(effect.fire1); break; case 2: play_se(effect.fire2); break; default:break; } 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 { #if 0 free(tmp); bomm_top = NULL; #else bomm_top = tmp->next; free(tmp); #endif break; } } prev = tmp; tmp = tmp->next; } } //---------------------------------------------- static void fire(int x,int y) { int mx,my; mx = x/BLOCK_SIZE; my = y/BLOCK_SIZE; // map[y1][x1] = FIELD_BOMM; add_fire(x,y,mx,my); add_func( fire_count ); } static void fire_count(void) { Bomm_List *tmp; #if 1 int anim_rate = (FRAME_RATE/2); float interval = (FRAME_RATE/2/10.0f); #else int anim_rate = (FRAME_RATE/2); float interval = (FRAME_RATE/8.0f); #endif const int fire_level = get_level() - 1; tmp = fire_top; if(tmp == NULL) { del_func( fire_count ); //爆弾アニメーションを解除する fire_reset(); } else { do { if(++(tmp->cnt) < anim_rate) { //TODO 爆弾の画像を張る int i, cnt = tmp->cnt; for(i = 0;i < 10;i++) { if(cnt < interval*(i+1)) { int x = tmp->x - bomm_img[fire_level].arr[i]->w / 2; int y = tmp->y - bomm_img[fire_level].arr[i]->h / 2; front_blit(x,y,bomm_img[fire_level].arr[i],tmp->id); break; } } if(tmp->cnt == anim_rate/5) fire_calc(tmp->map_x, tmp->map_y, get_level(), TRUE); //爆風フラグをセット } if(tmp->cnt == 30) //爆風カウント時間切れ { Bomm_List *t = tmp; clean_screen(tmp->x,tmp->y, bomm_img[fire_level].arr[0]->w, bomm_img[fire_level].arr[0]->h, tmp->id ); tmp = tmp->next; //次の爆風へ fire_calc(t->map_x, t->map_y, get_level(), FALSE); //爆風リセット del_fire(t->id); } else { tmp = tmp->next; //次の爆風へ } } while(tmp != NULL); } } static void add_fire(int x, int y,int mapx,int mapy) { Bomm_List *bomm = (Bomm_List*)malloc(sizeof(Bomm_List)); if(bomm == NULL) return; memset(bomm,0,sizeof(Bomm_List)); bomm->id = fires; bomm->x = x; bomm->y = y; bomm->map_x = mapx; bomm->map_y = mapy; bomm->next = fire_top; fire_top = bomm; printf("id:%d\n",bomm->id); fires++; printf("fire num:%d",fires); } static void del_fire(int id) { Bomm_List *tmp; Bomm_List *prev; tmp = fire_top; prev = NULL; while(tmp != NULL) { if(tmp->id == id) { if(prev != NULL) { prev->next = tmp->next; free(tmp); break; } else { free(tmp); fire_top = NULL; break; } } prev = tmp; tmp = tmp->next; } } //---------------------------------------------- static void fire_container(int x,int y) { int mx,my; mx = x/BLOCK_SIZE; my = y/BLOCK_SIZE; add_fire_container(x,y,mx,my); add_func( fire_count_container ); } static void fire_count_container(void) { Bomm_List *tmp; int anim_rate = (FRAME_RATE/2); float interval = (FRAME_RATE/2/20.0f); tmp = container_top; if(tmp == NULL) { del_func( fire_count_container ); //コンテナ爆風アニメーションを解除する fire_container_reset(); } else { do { if(++(tmp->cnt) < anim_rate) { int i, cnt = tmp->cnt; for(i = 0;i < 20;i++) { if(cnt < interval*(i+1)) { int x = tmp->x; int y = tmp->y; front_blit(x, y, container_fire.arr[i], tmp->id); break; } } } if(tmp->cnt == anim_rate) //爆風カウント時間切れ { Bomm_List *t = tmp; SDL_Rect r = {0,0,0,0}; r.x = (tmp->x / BLOCK_SIZE) * BLOCK_SIZE; r.y = (tmp->y / BLOCK_SIZE) * BLOCK_SIZE; SDL_BlitSurface(images.back,NULL,back_buffer,&r); //裏画面に描画.アイテム出現? clean_screen( tmp->x,tmp->y,container_fire.arr[0]->w,container_fire.arr[0]->h,tmp->id ); tmp = tmp->next; //次の爆風へ del_fire_container(t->id); } else { tmp = tmp->next; //次の爆風へ } } while(tmp != NULL); } } static void add_fire_container(int x, int y,int mapx,int mapy) { Bomm_List *bomm = (Bomm_List*)malloc(sizeof(Bomm_List)); if(bomm == NULL) return; memset(bomm,0,sizeof(Bomm_List)); bomm->id = containers; bomm->x = x; bomm->y = y; bomm->map_x = mapx; bomm->map_y = mapy; bomm->next = container_top; container_top = bomm; printf("id:%d\n",bomm->id); containers++; printf("fire num:%d",containers); } static void del_fire_container(int id) { Bomm_List *tmp; Bomm_List *prev; tmp = container_top; prev = NULL; while(tmp != NULL) { if(tmp->id == id) { if(prev != NULL) { prev->next = tmp->next; free(tmp); break; } else { free(tmp); container_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; } static void fire_reset(void) { fires = ID_FIRE; } static void fire_container_reset(void) { containers = ID_CONTAINER; } static boolean lock(SDL_Surface *s) { if( SDL_MUSTLOCK(s) ) { if( SDL_LockSurface( s ) < 0) return FALSE; } return TRUE; } static void unlock(SDL_Surface *s) { if( SDL_MUSTLOCK(s) ) { SDL_UnlockSurface( s ); } } static void set_alpha(SDL_Surface *s, Uint32 col) { int x,y; int w,h; /* マスクする画像の幅、高さ */ SDL_PixelFormat *fmt = s->format; /* ピクセルフォーマットを取得 */ Uint8 bit_pxl = fmt->BitsPerPixel; /* 1ピクセルのビット数を算出 */ Uint8 byt_pxl = fmt->BytesPerPixel; /* 1ピクセルのバイト数を算出 */ Uint32 *pixels = s->pixels; /* ピクセルデータの先頭アドレス */ Uint16 width = s->w; Uint32 *msk_pxl; /* マスクするピクセルのアドレス */ /************************/ /* 排他制御 */ /************************/ if( !lock(s) ) return; y = 0; /* マスクする画像データの縦軸 */ h = s->h; /* マスクする画像データの高さ */ while( y < h ) { x = 0; /* マスクする画像データの横軸 */ w = s->w; /* マスクする画像データの幅 */ while( x < w ) { msk_pxl = pixels + (width*y) + (x); /* マスクするアドレスを取得 */ if( *(Uint32*)msk_pxl == col ) { *(Uint32*)msk_pxl = SDL_MapRGBA(fmt,0,0,0,0); } x++; /* 次の横軸にアクセスする */ } y++; /* 次の縦軸にアクセスする */ } /* カラー変更の終了 */ unlock(s); } static Uint32 get_pixel(SDL_Surface *Surface, Sint32 X, Sint32 Y) { Uint8 *bits; Uint32 Bpp; if (X<0) puts("SFONT ERROR: x too small in GetPixel. Report this to hogehoge"); if (X>=Surface->w) puts("SFONT ERROR: x too big in GetPixel. Report this to hogehoge"); Bpp = Surface->format->BytesPerPixel; bits = ((Uint8 *)Surface->pixels)+Y*Surface->pitch+X*Bpp; // Get the pixel (借り物ソースコード) switch(Bpp) { case 1: return *((Uint8 *)Surface->pixels + Y * Surface->pitch + X); break; case 2: return *((Uint16 *)Surface->pixels + Y * Surface->pitch/2 + X); break; case 3: { // Format/endian independent Uint8 r, g, b; r = *((bits)+Surface->format->Rshift/8); g = *((bits)+Surface->format->Gshift/8); b = *((bits)+Surface->format->Bshift/8); return SDL_MapRGB(Surface->format, r, g, b); } break; case 4: return *((Uint32 *)Surface->pixels + Y * Surface->pitch/4 + X); break; } return -1; } static void fire_calc(int x,int y,int range,boolean flg) { int x1,y1; int signe; boolean up, down, right, left; if(x < 1 || x > WIDTH_SIZE-1 || y < 1 || y > HEIGHT_SIZE-1) return; signe = (flg) ? 1 : -1; up = down = right = left = FALSE; /****************************/ /* bottom range fire */ /****************************/ for(y1 = y;y1 <= y+range; y1++) { if(y1 < HEIGHT_SIZE && !down) { if(map[y1][x] == FIELD_CONTAINER && flg) //下のコンテナ爆破 { down = TRUE; map[y1][x] = FIELD_DEATH * signe; fire_container(x * BLOCK_SIZE, y1 * BLOCK_SIZE); //コンテナ爆発!! } else if((map[y1][x] == FIELD_STONE) || (map[y1][x] == FIELD_WALL) && flg){ down = TRUE; } else { if((signe > 0) || (signe < 0 && map[y1][x] >= FIELD_DEATH)) map[y1][x] += FIELD_DEATH * signe; if(map[y1][x] < 0) map[y1][x] = 0; } } } /****************************/ /* up range fire */ /****************************/ for(y1 = y;y1 >= y-range; y1--) { if(y1 > 0 && !up) { if(map[y1][x] == FIELD_CONTAINER && flg) //上のコンテナ爆破 { SDL_Rect r = {0,0,0,0}; up = TRUE; map[y1][x] = FIELD_DEATH * signe; r.x = x * BLOCK_SIZE; r.y = y1 * BLOCK_SIZE; fire_container(r.x,r.y); //コンテナ爆発!! } else if((map[y1][x] == FIELD_STONE) || (map[y1][x] == FIELD_WALL) && flg){ up = TRUE; } else { if((signe > 0) || (signe < 0 && map[y1][x] >= FIELD_DEATH)) map[y1][x] += FIELD_DEATH * signe; if(map[y1][x] < 0) map[y1][x] = 0; } } } /****************************/ /* right range fire */ /****************************/ for(x1 = x;x1 <= x+range; x1++) { if(x1 < WIDTH_SIZE && !right) { if(map[y][x1] == FIELD_CONTAINER && flg) //右のコンテナ爆破 { SDL_Rect r = {0,0,0,0}; right = TRUE; map[y][x1] = FIELD_DEATH * signe; r.x = x1 * BLOCK_SIZE; r.y = y * BLOCK_SIZE; fire_container(r.x,r.y); //コンテナ爆発!! } else if((map[y][x1] == FIELD_STONE) || (map[y][x1] == FIELD_WALL) && flg){ right = TRUE; } else { if((signe > 0) || (signe < 0 && map[y][x1] >= FIELD_DEATH)) map[y][x1] += FIELD_DEATH * signe; if(map[y][x1] < 0) map[y][x1] = 0; } } } /****************************/ /* left range fire */ /****************************/ for(x1 = x;x1 >= x-range; x1--) { if(x1 > 0 && !left) { if(map[y][x1] == FIELD_CONTAINER && flg) //左のコンテナ爆破 { SDL_Rect r = {0,0,0,0}; left = TRUE; map[y][x1] = FIELD_DEATH * signe; r.x = x1 * BLOCK_SIZE; r.y = y * BLOCK_SIZE; fire_container(r.x,r.y); //コンテナ爆発!! } else if((map[y][x1] == FIELD_STONE) || (map[y][x1] == FIELD_WALL) && flg){ left = TRUE; } else { if((signe > 0) || (signe < 0 && map[y][x1] >= FIELD_DEATH)) map[y][x1] += FIELD_DEATH * signe; if(map[y][x1] < 0) map[y][x1] = 0; } } } } // monster code // // static void go_enemy(int x,int y) { int mx,my; mx = x/BLOCK_SIZE; my = y/BLOCK_SIZE; add_enemy(x,y,mx,my); add_func( enemy_count ); } static void enemy_count(void) { Bomm_List *tmp; mvdrc drc; //direction drc = MV_DOWN; tmp = enemy_top; if(tmp == NULL) { del_func( enemy_count ); //爆弾アニメーションを解除する enemy_reset(); } else { do { Uint8 idx; idx = (++tmp->cnt / (FRAME_RATE/8)) % 4; drc = routing_01(screenX, screenY, &tmp->x, &tmp->y, MOVE_VALUE); //敵のルートを計算,敵の移動 // 一時的に人間風の画像を使いまわしてる switch( drc ) { case MV_UP: blit(tmp->x,tmp->y,humanoid.up[idx],tmp->id); break; case MV_DOWN: blit(tmp->x,tmp->y,humanoid.down[idx],tmp->id); break; case MV_RIGHT: blit(tmp->x,tmp->y,humanoid.right[idx],tmp->id); break; case MV_LEFT: blit(tmp->x,tmp->y,humanoid.left[idx],tmp->id); break; default: break; } /****************************/ /* モンスター爆発 */ /****************************/ if( isdeath(tmp->x,tmp->y) ) { Bomm_List *t = tmp; int x = t->map_x; int y = t->map_y; printf("ID:%d\n",t->id); fire_container(tmp->x,tmp->y); play_se(effect.death); tmp = tmp->next; //次の怪物へ del_enemy(t->id); } else { tmp = tmp->next; //次の怪物へ } } while(tmp != NULL); } } static void add_enemy(int x, int y,int mapx,int mapy) { Bomm_List *bomm = (Bomm_List*)malloc(sizeof(Bomm_List)); if(bomm == NULL) return; memset(bomm,0,sizeof(Bomm_List)); bomm->id = enemys; bomm->x = x; bomm->y = y; bomm->map_x = mapx; bomm->map_y = mapy; bomm->next = enemy_top; enemy_top = bomm; printf("id:%d\n",bomm->id); enemys++; printf("enemy num:%d",enemys); } static void del_enemy(int id) { Bomm_List *tmp; Bomm_List *prev; tmp = enemy_top; prev = NULL; while(tmp != NULL) { if(tmp->id == id) { if(prev != NULL) { prev->next = tmp->next; free(tmp); break; } else { enemy_top = tmp->next; free(tmp); break; } } prev = tmp; tmp = tmp->next; } } static void enemy_reset(void) { enemys = ID_MONSTER; } |