前回、カーソルキーでキャラクタを動かすことをやりました。今回はそれにちょっと手を加えます。
ピクセル単位ではなく、歩数単位で可能範囲を指定します。
#include <SDL/SDL.h> #include <SDL/SDL_image.h> #define WINDOW_WIDTH 640 #define WINDOW_HEIGHT 480 #define BPP 32 #define CHAR_WIDTH 32 #define CHAR_HEIGHT 32 #define __WIDTH 20 #define __HEIGHT 15 int getpos(SDL_Rect *from, SDL_Rect *to){ to->x = from->x * CHAR_WIDTH; to->y = from->y * CHAR_HEIGHT; return 0; } int draw(SDL_Surface *image, SDL_Rect *rect1, SDL_Rect *rect2){ SDL_Rect window_rect = {0, 0, WINDOW_WIDTH, WINDOW_HEIGHT}; SDL_Surface *video_surface; SDL_Rect rect3; getpos(rect2, &rect3); video_surface = SDL_GetVideoSurface(); /* 背景色塗りつぶし */ SDL_FillRect(video_surface, &window_rect, SDL_MapRGB(video_surface->format, 0, 0, 0)); /* サーフェスの複写 */ SDL_BlitSurface(image, rect1, video_surface, &rect3); /* サーフェスフリップ */ SDL_Flip(video_surface); return 0; } int main(int argc, char* argv[]){ SDL_Surface* image; SDL_Rect rect, scr_rect, rect_tmp; SDL_Event event; int exit_prg = 0; SDL_Init(SDL_INIT_EVERYTHING); SDL_SetVideoMode(WINDOW_WIDTH, WINDOW_HEIGHT, BPP, SDL_HWSURFACE); /* 画像読み込み */ image = IMG_Load("sample.png"); /* 32x32の画像を用意します */ /* 画像の矩形情報設定 */ rect.x = 0; rect.y = 0; rect.w = image->w < CHAR_WIDTH ? image->w : CHAR_WIDTH; rect.h = image->h < CHAR_HEIGHT ? image->h : CHAR_HEIGHT; /* 画像配置位置情報の設定 */ scr_rect.x = 0; scr_rect.y = 0; /* 描画 */ draw(image, &rect, &scr_rect); rect_tmp = scr_rect; /* イベントループ */ while(exit_prg == 0){ if(SDL_PollEvent(&event)){ switch(event.type){ case SDL_KEYDOWN: switch(event.key.keysym.sym){ case SDLK_UP: rect_tmp.y -= 1; break; case SDLK_DOWN: rect_tmp.y += 1; break; case SDLK_RIGHT: rect_tmp.x += 1; break; case SDLK_LEFT: rect_tmp.x -= 1; break; case SDLK_ESCAPE: exit_prg = 1; break; default: break; } /* 移動可能範囲の判定 */ if(rect_tmp.x >= 0 && rect_tmp.x < __WIDTH && rect_tmp.y >= 0 && rect_tmp.y < __HEIGHT){ scr_rect = rect_tmp; /* 描画 */ draw(image, &rect, &scr_rect); } else { rect_tmp = scr_rect; } break; default: break; } } SDL_Delay(1); } SDL_FreeSurface(image); SDL_Quit(); return 0; }
こうすることにより、オブジェクト配置を2次元配列で管理できるようになり、楽になります。
次のプログラムでは(1,1)の位置を進入不可能にしてあります。ここに木や石など進入不可能なオブジェクトを描けば、「木(石)があるから、ここに移動できない」ということを表現できるようになります。
#include <SDL/SDL.h> #include <SDL/SDL_image.h> #define WINDOW_WIDTH 640 #define WINDOW_HEIGHT 480 #define BPP 32 #define CHAR_WIDTH 32 #define CHAR_HEIGHT 32 #define __WIDTH 20 #define __HEIGHT 15 char ObjectMatrix[__HEIGHT][__WIDTH]; int getpos(SDL_Rect *from, SDL_Rect *to){ to->x = from->x * CHAR_WIDTH; to->y = from->y * CHAR_HEIGHT; return 0; } int draw(SDL_Surface *image, SDL_Rect *rect1, SDL_Rect *rect2){ SDL_Rect window_rect = {0, 0, WINDOW_WIDTH, WINDOW_HEIGHT}; SDL_Surface *video_surface; SDL_Rect rect3; getpos(rect2, &rect3); video_surface = SDL_GetVideoSurface(); /* 背景色塗りつぶし */ SDL_FillRect(video_surface, &window_rect, SDL_MapRGB(video_surface->format, 0, 0, 0)); /* サーフェスの複写 */ SDL_BlitSurface(image, rect1, video_surface, &rect3); /* サーフェスフリップ */ SDL_Flip(video_surface); return 0; } int main(int argc, char* argv[]){ SDL_Surface* image; SDL_Rect rect, scr_rect, rect_tmp; SDL_Event event; int exit_prg = 0; memset(ObjectMatrix, 0x00, sizeof(ObjectMatrix)); ObjectMatrix[1][1] = 1; SDL_Init(SDL_INIT_EVERYTHING); SDL_SetVideoMode(WINDOW_WIDTH, WINDOW_HEIGHT, BPP, SDL_HWSURFACE); /* 画像読み込み */ image = IMG_Load("sample.png"); /* 32x32の画像を用意します */ /* 画像の矩形情報設定 */ rect.x = 0; rect.y = 0; rect.w = image->w < CHAR_WIDTH ? image->w : CHAR_WIDTH; rect.h = image->h < CHAR_HEIGHT ? image->h : CHAR_HEIGHT; /* 画像配置位置情報の設定 */ scr_rect.x = 0; scr_rect.y = 0; /* 描画 */ draw(image, &rect, &scr_rect); rect_tmp = scr_rect; /* イベントループ */ while(exit_prg == 0){ if(SDL_PollEvent(&event)){ switch(event.type){ case SDL_KEYDOWN: switch(event.key.keysym.sym){ case SDLK_UP: rect_tmp.y -= 1; break; case SDLK_DOWN: rect_tmp.y += 1; break; case SDLK_RIGHT: rect_tmp.x += 1; break; case SDLK_LEFT: rect_tmp.x -= 1; break; case SDLK_ESCAPE: exit_prg = 1; break; default: break; } /* 移動可能範囲の判定 */ if(rect_tmp.x >= 0 && rect_tmp.x < __WIDTH && rect_tmp.y >= 0 && rect_tmp.y < __HEIGHT && ObjectMatrix[rect_tmp.y][rect_tmp.x] == 0){ scr_rect = rect_tmp; /* 描画 */ draw(image, &rect, &scr_rect); } else { rect_tmp = scr_rect; } break; default: break; } } SDL_Delay(1); } SDL_FreeSurface(image); SDL_Quit(); return 0; }