前回、カーソルキーでキャラクタを動かすことをやりました。今回はそれにちょっと手を加えます。
ピクセル単位ではなく、歩数単位で可能範囲を指定します。
#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;
}