SDL游戏编程5

软件和网站开发以及相关技术探讨
回复
rayfox
帖子: 39
注册时间: 2007-02-03 9:12

SDL游戏编程5

#1

帖子 rayfox » 2007-05-29 11:30

在游戏编程中可移动的人物,比如NGC和玩家控制的人物称为精灵。
今天我们就是要学习控制精灵的移动。
请看附件中的Player.bmp这个图片,纵向有4组图,分别对应上下左右的图组,每个图组中有3个小图,
分别对应行走的动画,只有不停的切换这3个小图就可以实现行走的动画。
看看代码。

代码: 全选

#include <SDL.h>
#include <stdio.h>
	
//用键盘控制精灵移动

int main(int argc, char ** argv)
{
	SDL_Surface * screen; //主表面
	SDL_Surface * image; //用来放MM-----的图片信息(像素)
	SDL_Surface * PlayerImage; //用来测试的图片
	SDL_Event     event;

	Uint32 BeginTicks, EndTicks;

	SDL_Rect PRect, BRect;	//PRect对应精灵的移动的小图位置(实现动画),BRect对应精灵在屏幕的位置。
	unsigned char PlayerStarts = 0;
	unsigned char PlayerIndex = 0;
	
	bool bAppRun = true;
	//初始化SDL
	if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) == -1) {
		fprintf(stderr, "SDL_Init %s\n", SDL_GetError());
		return -1;
	}
	
	//初始化成功设置退出要调用的函数SDL_Quit
	atexit(SDL_Quit);
	
	//创建一个640X480 16-bit 模式的主表面 16位可以让MM的效果好看一点
	screen = SDL_SetVideoMode(640, 480, 16, SDL_SWSURFACE);
	if (screen == NULL) {
		fprintf(stderr, "Couldn't set 640x480x8 video mode %s\n",
			SDL_GetError());
		return -1;
	}
	
	//读取MM图片信息,并创建一个表面,并把数据填入该表面中。
	image = SDL_LoadBMP("./mm.bmp"); //请在终端里运行该程序
	if (image == NULL) {
		fprintf(stderr, "Couldn't load MM, %s\n", SDL_GetError()); //遗憾你不能显示MM了,不过你可以用图片浏览程序看。
		return -1;
	}
	
	//读取player.bmp
	PlayerImage = SDL_LoadBMP("./player.bmp"); //请在终端里运行该程序
	if (image == NULL) {
		fprintf(stderr, "Couldn't load MM, %s\n", SDL_GetError()); //遗憾你不能显示MM了,不过你可以用图片浏览程序看。
		return -1;
	}
	
	//读取第一个像素
	Uint8 key = *((Uint8 *)PlayerImage->pixels);
	//设置色键
	SDL_SetColorKey(PlayerImage, SDL_SRCCOLORKEY, key);
	
	//有了MM的表面了,就可以显示了。
	//将MM的表面画在我们的主表面上,用MM来作为背景
	if (SDL_BlitSurface(image, NULL, screen, NULL) < 0) {
		//解释一下NULL,第一个是按照image的尺寸显示,第二个是默认显示。你也可以指定大小,不过要用到SDL_Rect你可以看一看帮助。 
		fprintf(stderr, "BlitSurface error: %s\n", SDL_GetError()); //看看提示吧
		return -1;
	}
	
	PRect.x = 0;	//初始化动画显示的图片。
	PRect.y = 0;
	PRect.w = 32;
	PRect.h = 48;

	BRect.x = 0;	//初始化精灵的位置。
	BRect.y = 0;
	BRect.w = 32;
	BRect.h = 48;
	//贴上测试用的表面
	if (SDL_BlitSurface(PlayerImage, &PRect, screen, &BRect) < 0) { 
		fprintf(stderr, "BlitSurface error: %s\n", SDL_GetError()); //看看提示吧
		return -1;
	}
	
	//好了更新显示画出MM
	SDL_UpdateRect(screen, 0, 0, image->w, image->h);
	
	BeginTicks = SDL_GetTicks();
	while (bAppRun) {
		//消息循环
		if (SDL_PollEvent(&event)) {
			switch (event.type) {
				case SDL_KEYDOWN:
					switch (event.key.keysym.sym) {
					case SDLK_ESCAPE:
						bAppRun = false;	//按下了ESC退出程序。
					break;
					case SDLK_UP:
						PlayerStarts = 1;	//向上移动。
						PlayerIndex  = 0;	//动画序号清零
					break;
					case SDLK_DOWN:
						PlayerStarts = 2;	//向下移动。
						PlayerIndex  = 0;	//动画序号清零
					break;
					case SDLK_LEFT:
						PlayerStarts = 3;	//向左移动
						PlayerIndex  = 0;	//动画序号清零
					break;
					case SDLK_RIGHT:
						PlayerStarts = 4;	//向右移动
						PlayerIndex  = 0;	//动画序号清零
					break;
					}
				break;
				case SDL_KEYUP:
					PlayerStarts = 0;	//按键松开。停止切换动画。
				break;
				case SDL_QUIT:
					bAppRun = false;
				break;
			}
		}
		EndTicks = SDL_GetTicks();

		if ((EndTicks - BeginTicks) > 50) {	//到了50MS
			BeginTicks = EndTicks;
			SDL_FillRect(screen, &BRect, 0); //清除以前的图片。

			if (PlayerStarts) {
				switch (PlayerStarts) {
				case 1:	//向上移动。
					if ((BRect.y - 5) > 0) { //要移动的位置是否到顶
						BRect.y -= 5;	//坐标减去5
					}
					else {
						BRect.y = 0; //设置位置在顶部。
					}
					PRect.x = PlayerIndex * 32; //使用序号计算该显示那个动画图片
					PRect.y = 144; //向上的图组
					PlayerIndex ++; //动画序号加1
					if (PlayerIndex > 2) PlayerIndex = 0; //循环显示动画
				break;
				case 2:
					//以下请大家自己分析。
					if ((BRect.y + BRect.h + 5) < screen->h) {
						BRect.y += 5;
					}
					else {
						BRect.y = screen->h - BRect.h;
					}
					PRect.x = PlayerIndex * 32;
					PRect.y = 0;
					PlayerIndex ++;
					if (PlayerIndex > 2) PlayerIndex = 0;
					break;
				case 3:
					if ((BRect.x - 5) > 0) {
						BRect.x -= 5;
					}
					else {
						BRect.x = 0;
					}
					PRect.x = PlayerIndex * 32;
					PRect.y = 48;
					PlayerIndex ++;
					if (PlayerIndex > 2) PlayerIndex = 0;
				break;
				case 4:
					if ((BRect.x + BRect.w + 5) < screen->w) {
						BRect.x += 5;
					}
					else {
						BRect.x = screen->w - BRect.w;
					}
					PRect.x = PlayerIndex * 32;
					PRect.y = 96;
					PlayerIndex ++;
					if (PlayerIndex > 2) PlayerIndex = 0;
				break;
				}
			}

			if (SDL_BlitSurface(image, NULL, screen, NULL) < 0) {
				//解释一下NULL,第一个是按照image的尺寸显示,第二个是默认显示。你也可以指定大小,不过要用到SDL_Rect你可以看一看帮助。 
				fprintf(stderr, "BlitSurface error: %s\n", SDL_GetError()); //看看提示吧
				return -1;
			}
			//贴上测试用的表面
			if (SDL_BlitSurface(PlayerImage, &PRect, screen, &BRect) < 0) { 
				fprintf(stderr, "BlitSurface error: %s\n", SDL_GetError()); //看看提示吧
				return -1;
			}
		}
		SDL_Flip(screen);
	}
	
	//退出了程序释放MM表面的资源
	SDL_FreeSurface(image);
	
	return 0;
}
makefile

代码: 全选

t5: main.o
	g++ -o t5 main.o `sdl-config --libs`

main.o: main.cpp
	g++ -c main.cpp `sdl-config --cflags`
附件
t5.tar.gz
(120 KiB) 已下载 408 次
头像
titainium
帖子: 689
注册时间: 2006-12-02 12:25

#2

帖子 titainium » 2007-05-31 20:03

问个简单的问题SDL和OPENGL有什么区别?
Titainium
ai86soft
帖子: 3
注册时间: 2007-05-24 20:08

#3

帖子 ai86soft » 2007-06-02 0:13

貌似SDL和DirectShow很象!
twm
帖子: 19
注册时间: 2007-06-02 17:48

#4

帖子 twm » 2007-06-02 18:51

titainium 写了:问个简单的问题SDL和OPENGL有什么区别?
SDL主要提供的是低级的,夸平台的显卡支持(不用担心各种平台之间数据类型命名等问题),并且支持一些基本的事件,输入,输出或通过其他的lib实现网络,声音,读取不同格式的图形功能。并可以选择性的支持opengl。

你可以通过SDL制作简单的2D游戏,但是大多数的SDL画图渲染方式需要靠cpu来完成,所以3D游戏和需要大量alpha渲染的2D游戏很难通过SDL本身来实现(性能问题),而SDL通过对opengl的支持来弥补这个缺点。

以上仅是本人对SDL和opengl的“区别”的观点。 :)
rayfox
帖子: 39
注册时间: 2007-02-03 9:12

#5

帖子 rayfox » 2007-06-03 14:21

这个是SDL网上的原话.

代码: 全选

SDL是什么? SDL是一个自由的跨平台的多媒体开发包
适用于 游戏、游戏SDK、演示软件、模拟器、 MPEG播放器和其他应用软件。
SDL有哪些功能?
视频
设置8bpp或更高的任意色彩深度的视频模式。如果某个模式硬件不支持,可以选择转化为另一模式。 
直接写入线性的图像帧缓冲(framebuffer)。 
用颜色键值(colorkey)或者alpha混合属性创建surface。 
Surface的blit能自动的转化为目标格式。blit是优化过的,并能使用硬件加速。x86平台上有针对MMX优化过的blit。 
硬件加速的blit和fill(填充)操作,如果硬件支持的话。
事件
提供以下事件: 
应用程序的visibility发生改变 
键盘输入 
鼠标输入 
用户要求的退出 
每种事件都能通过SDL_EventState()关闭或者打开。 
事件经由用户指定的过滤函数再被加入到内部的事件队列。 
线程安全的事件队列。 
音频
设置8位和16位的音频,单声道或者立体声,如果格式硬件不支持,可以选择转换。 
由独立的线程执行音频部分,并提供用户回调(callback)机制。 
设计上考虑到了客户定制的软混音器,但实际上在例程中就包含了一个完整的音频/音乐输出库。 
CD音频
完整的CD音频控制API 
线程
简单的线程创建API 
用于同步的简单的二进制信号量(semaphores)  
定时器
读取已流逝的毫秒数。 
等待指定的毫秒数。 
设置一个10毫秒精度的周期性定时器。
字节序无关
侦测当前系统的字节序 
快速转换数据的函数 
读写指定字节序的数据 
SDL支持OpenGL图形接口
rayfox
帖子: 39
注册时间: 2007-02-03 9:12

#6

帖子 rayfox » 2007-06-03 14:25

twm 写了:
titainium 写了:问个简单的问题SDL和OPENGL有什么区别?
SDL主要提供的是低级的,夸平台的显卡支持(不用担心各种平台之间数据类型命名等问题),并且支持一些基本的事件,输入,输出或通过其他的lib实现网络,声音,读取不同格式的图形功能。并可以选择性的支持opengl。

你可以通过SDL制作简单的2D游戏,但是大多数的SDL画图渲染方式需要靠cpu来完成,所以3D游戏和需要大量alpha渲染的2D游戏很难通过SDL本身来实现(性能问题),而SDL通过对opengl的支持来弥补这个缺点。

以上仅是本人对SDL和opengl的“区别”的观点。 :)
这位兄弟对SDL还比较有研究.
头像
titainium
帖子: 689
注册时间: 2006-12-02 12:25

#7

帖子 titainium » 2007-06-05 12:45

谢了!
Titainium
dinghwy
帖子: 44
注册时间: 2006-07-10 17:40

#8

帖子 dinghwy » 2007-06-05 14:23

titainium 写了:问个简单的问题SDL和OPENGL有什么区别?
2d是SDL库自己实现的,3d需要OPENGL来实现 2d跟directdraw基本相同 不过它可是夸平台的。
回复