现在的位置: 首页 > 综合 > 正文

基于Linux系统的SDL图形库记忆翻牌小游戏

2012年03月18日 ⁄ 综合 ⁄ 共 6700字 ⁄ 字号 评论关闭

步骤1显示图片

用二维数组来显示890×90的配对图片,用来翻转的;首先显示的是背景图片。定义一个二维数组pic[4][4] 来表示每张小图片存放的位置,数组里面存放07的数字,当前位置存放是0,就表示该位置要显示image0小图片。这样就可以显示所有小图片了。

步骤2 实现可以翻转

根据鼠标点击的位置,翻转指定的小图片,而且要自动的翻转回来,主要是鼠标的获取和定位;定义一个二维数组flag[mouse_y/90][mouse_x/90] 来标志有没有翻转,鼠标点击的坐标位置除以90就可以确定点击的是哪张小图片。

步骤3: 游戏逻辑翻转

所谓逻辑翻转就是根据游戏的规则翻转和不翻转图片,就是当鼠标点击次数为偶数时,判断前面的一张图片和当前这张图片是否相同,如果是相同的,这两张图片就不要翻转回背面,否则,就把这两张图片都翻转回背面。主要还是怎样判断两张图片是否相同,解决方法是根据一开始的二维数组pic[4][4]里面存放的数字是否是相同的来判断两张图片是否是相同的。直到所有的小图片都被翻转了游戏就结束。最后利用了SDL的强大功能弄了一个动画的界面来结束游戏。

下面是完整的代码:

#include "SDL/SDL.h"
#include "SDL/SDL_image.h"
#include <string>
#include <stdio.h>
#include <time.h>

const int SCREEN_WIDTH = 360;    //屏幕宽
const int SCREEN_HEIGHT =  360; //屏幕高
const int SCREEN_BPP = 32;          //屏幕像素

const int FRAMES_PER_SECOND = 10;

const int FOO_WIDTH = 90;    //小图片90*90
const int FOO_HEIGHT = 90;


SDL_Surface * foo = NULL;
SDL_Surface * screen = NULL;
SDL_Surface *image0 = NULL;
SDL_Surface *image1 = NULL;
SDL_Surface *image2 = NULL;
SDL_Surface *image3 = NULL;
SDL_Surface *image4 = NULL;
SDL_Surface *image5 = NULL;
SDL_Surface *image6 = NULL;
SDL_Surface *image7 = NULL;
SDL_Surface *Menu = NULL;
SDL_Surface *beginBg = NULL;
SDL_Surface * endBg = NULL;

SDL_Event  event;

//定义一个二维数组,用来保存图片索引

int pic[4][4];
bool flag[4][4]; //标记图像是否翻开

bool mousecheck; //记录鼠标点击状态
int pic_x, pic_y; //图片索引

int mouse_x;
int mouse_y; //鼠标点击位置

bool quit = false;
bool lock;

int GameState;//游戏当前状态
const int BEGIN = 0;//开始状态
const int RUN = 1;//运行状态
const int END = 2;//结束状态

SDL_Rect MenuRect[2];

SDL_Rect EndRect[2];
int end_y;

class Foo
{
private:
	int offSet;
	int velocity;
	int frame;

public:
	Foo();
	
	int handle_events();
	
	void show();
};

Foo Show;

Foo::Foo()
{
	offSet = 0;
	velocity = 0;
}
//读入图片
SDL_Surface *load_image(std::string filename)
{
	SDL_Surface * loadedImage = NULL;
	SDL_Surface * optimizedImage = NULL;
	loadedImage = IMG_Load(filename.c_str());

	if(loadedImage != NULL)
	{
		optimizedImage = SDL_DisplayFormat(loadedImage);
		SDL_FreeSurface(loadedImage);
		if(optimizedImage != NULL)
		{
			SDL_SetColorKey(optimizedImage, SDL_SRCCOLORKEY, \
				SDL_MapRGB(optimizedImage->format, 0, 0xF8, 0xF8));
		}
	}
	return optimizedImage;
}

//显示图片
void apply_surface(int x, int y, SDL_Surface *source, \
	SDL_Surface * destination,  SDL_Rect *clip = NULL)
{
	SDL_Rect offset;
	offset.x = x;
	offset.y = y;

	SDL_BlitSurface(source, clip, destination, &offset);
}

//初始化图片索引的函数
void initIndex()
{
	srand(time(NULL));
	
	int k=0; 

	//初始化
	for(int i=0; i<4; i++)
	{
		for(int j=0; j<4; j++)
		{
			pic[i][j] = k++;
			k %= 8;
		}
	}


	//随机
	for(int i=0; i<4; i++)
	{
		for(int j=0; j<4; j++)
		{
			int x = rand()%4;
			int y = rand()%4;
			
			int temp = pic[i][j];
			pic[i][j] = pic[x][y];
			pic[x][y] = temp;
		}
	}


	//初始化为背面
	memset(flag, 0, sizeof(flag));

	mousecheck = true;
	pic_x = -1;
	lock = false;
	quit = false;
	end_y = 30;

	GameState = BEGIN;

	MenuRect[0].x = 0;
	MenuRect[0].y = 0;
	MenuRect[0].w= 125;
	MenuRect[0].h = 30;

	MenuRect[1].x = 0;
	MenuRect[1].y = 60;
	MenuRect[1].w= 125;
	MenuRect[1].h = 30;

	EndRect[0].x = 0;
	EndRect[0].y = 150;
	EndRect[0].w = 360;
	EndRect[0].h = 30;

	EndRect[1].x = 0;
	EndRect[1].y = 180;
	EndRect[1].w = 360;
	EndRect[1].h = 30;
		
}

bool init()
{
	if(SDL_Init(SDL_INIT_EVERYTHING) == -1)
	{
		return false;
	}
	screen = SDL_SetVideoMode( SCREEN_WIDTH, \
		                          SCREEN_HEIGHT, SCREEN_BPP, SDL_SWSURFACE);
	if( screen == NULL)
	{
		return false;
	}
	SDL_WM_SetCaption("Memory Game", NULL);

	return true;
}

bool load_files()
{
	beginBg = load_image("pic/begin.bmp");
	endBg = load_image("pic/end.bmp");
	Menu = load_image("pic/menu.bmp");
	foo = load_image("pic/bgimage.bmp");
	
	image0 = load_image("pic/image0.bmp");
	image1 = load_image("pic/image1.bmp");
	image2 = load_image("pic/image2.bmp");
	image3 = load_image("pic/image3.bmp");
	image4 = load_image("pic/image4.bmp");
	image5 = load_image("pic/image5.bmp");
	image6 = load_image("pic/image6.bmp");
	image7 = load_image("pic/image7.bmp");

	
	if( NULL ==  foo  || NULL == endBg || NULL == Menu || NULL == beginBg || NULL == image0         \
		|| NULL == image1 ||  NULL == image2 || NULL == image3 || NULL == image4            		\
		||  NULL == image5 || NULL == image6 || NULL == image7 )
	{
		return false;
	}
	
	return true;
}

void clean_up()
{
	SDL_FreeSurface(foo);
	SDL_FreeSurface(endBg);
	SDL_FreeSurface(image0);
	SDL_FreeSurface(image1);
	SDL_FreeSurface(image2);
	SDL_FreeSurface(image3);
	SDL_FreeSurface(image4);
	SDL_FreeSurface(image5);
	SDL_FreeSurface(image6);
	SDL_FreeSurface(image7);
	SDL_FreeSurface(Menu);
	SDL_FreeSurface(beginBg);
	
	SDL_Quit();
}

int Foo::handle_events()
{
	int x =0, y = 0;
	if(event.type == SDL_MOUSEMOTION)
	{
		//获取新鼠标偏移位置
		x = event.motion.x;
		y = event.motion.y;
		
		if(y>=250 && y<=280 && x>= 230 && x<355)
		{
			//第一项
			MenuRect[0].y = 30;
		}
		else if(y>=290 && y<=320 && x>= 230 && x<355)
		{
			//第二项
			MenuRect[1].y = 90;
		}
		else
		{
			MenuRect[0].y = 0;
			MenuRect[1].y = 60;
		}
	
		
	}
	//鼠标按键按下
	if( event.type == SDL_MOUSEBUTTONUP)
	{
		//如果鼠标左键已经放开
		if( event.button.button == SDL_BUTTON_LEFT)
		{
			//获取鼠标的偏移位置
			x = event.button.x;
			y = event.button.y;

			//如果鼠标在图片上
			if(GameState ==  BEGIN)
			{
				if(y>=250 && y<=280 && x>= 230 && x<355)
				{
					//第一项
					GameState = RUN;
				}
				else if(y>=290 && y<=320 && x>= 230 && x<355)
				{
					//第二项
					quit = true;
				}
			}
			else if(GameState == RUN)
			{
				if(lock && !flag[y/90][x/90]) //如果没翻开,那就翻开
				{
					flag[y/90][x/90] = true;
					mousecheck = !mousecheck; //变换当前状态

					mouse_x = x;
					mouse_y = y;

					lock = false;
					
				}
			}

		}
	}
}


void logic()
{

	 if(GameState == RUN && lock == false)
	{
		//判断是否翻开一对
		if(mousecheck) //双
		{
			if((pic_x != -1)&&(pic[pic_x][pic_y] != pic[mouse_y/90][mouse_x/90]) )
			{
				//取反?
				flag[pic_x][pic_y] = false;
				flag[mouse_y/90][mouse_x/90] = false;
			}
			
		}
		else//单数,记录位置
		{
			pic_x = mouse_y/90;
			pic_y = mouse_x/90;
		}

		lock = true;

		//判断是否全部翻开
		bool isopen = true;
		
		for(int i=0; i<4; i++)
		{
			for(int j=0; j<4; j++)
			{
				if(flag[i][j] == false) //有没有翻开的
				{
					isopen = false;
				}
			}
		}
		
		if(isopen) 
		{
			GameState = END;
		}
		
	}
	 else if(GameState == END)
	 {
		end_y += 30;
		if(end_y > 180)
		{
			end_y = 180;
			
			//quit = true;
		}

		EndRect[0].y = 180-end_y;
		EndRect[0].h = end_y;
	
		EndRect[1].h = end_y;
		
	 }
}


void Foo::show()
{
	if(GameState == BEGIN)//如果开始状态,显示开始图片
	{
		apply_surface(0, 0, beginBg, screen);

		for(int i=0; i<2; i++)
		{
			apply_surface(230,  250+i*40, Menu, screen, &MenuRect[i]);
		}
		
	}
	else if(GameState == RUN)
	{
			//遍历图像索引,在相应位置显示图像
		for(int i=0; i<4; i++)
		{
			for(int j=0; j<4; j++)
			{
				if(flag[i][j]) //翻开
				{
					switch(pic[i][j])
					{
						case 0: apply_surface(90*j,90*i, image0, screen); break;
						case 1: apply_surface(90*j,90*i, image1, screen); break;
						case 2: apply_surface(90*j,90*i, image2, screen); break;
						case 3: apply_surface(90*j,90*i, image3, screen); break;
						case 4: apply_surface(90*j,90*i, image4, screen); break;
						case 5: apply_surface(90*j,90*i, image5, screen); break;
						case 6: apply_surface(90*j,90*i, image6, screen); break;
						case 7: apply_surface(90*j,90*i, image7, screen); break;
					}
				}
				else//没翻开
				{
					apply_surface(90*j,90*i, foo, screen);
				}
				
			}
		}
	}
	else if(GameState == END)
	{
		//apply_surface(0, 0, endBg, screen);

		apply_surface(0, 0, endBg, screen, &EndRect[0]);
		apply_surface(0, 360-end_y, endBg, screen, &EndRect[1]);
	}
	
}

int main(int argc, char *args[])
{
	if( init() == false)
	{
		printf("init error...\n");
		return 1;
	}
	if( load_files() == false)
	{
		printf("load_files error...\n");
		return 1;
	}

	initIndex();  //初始化二维数组
	
    	while( quit == false )
    	{

		logic();
		
       	 	//While there's events to handle
        		while( SDL_PollEvent( &event ) )
        		{
           		 Show.handle_events();
            		//If the user has Xed out the window
            		if( event.type == SDL_QUIT )
           		 {
	             		   //Quit the program
	              		  quit = true;		
          		  }

			if(event.type == SDL_KEYDOWN)
			{
				switch(event.key.keysym.sym)
				{
					case SDLK_ESCAPE:
					{
						printf("escape button is pressed\n");
						quit = true;
						break;
					}
				}
			}
     
        		}        

        		Show.show();
		
	        //Update the screen
	        if( SDL_Flip( screen ) == -1 )
	        {
	            return 1;
	        }

		if(GameState == RUN)
			SDL_Delay(500);

		if(GameState == END)
			SDL_Delay(150);
			
		
	}

    //Clean up
    clean_up();

    return 0;
	
}

运行效果图片,请读者自行运行。

下载图片地址:http://download.csdn.net/detail/shiren_bod/4409888

【上篇】
【下篇】

抱歉!评论已关闭.