トップページに戻る / GCCページに戻る / SDL目次


7 キーで画像を動かすその2

前回、カーソルキーでキャラクタを動かすことをやりました。今回はそれにちょっと手を加えます。

ピクセル単位ではなく、歩数単位で可能範囲を指定します。

#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;
}

/

indexに戻る