当前时区为 UTC + 8 小时



发表新帖 回复这个主题  [ 8 篇帖子 ] 
作者 内容
1 楼 
 文章标题 : SDL游戏编程5
帖子发表于 : 2007-05-29 11:30 

注册: 2007-02-03 9:12
帖子: 39
送出感谢: 0 次
接收感谢: 0 次
在游戏编程中可移动的人物,比如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]
被下载 360 次
页首
 用户资料  
 
2 楼 
 文章标题 :
帖子发表于 : 2007-05-31 20:03 
头像

注册: 2006-12-02 12:25
帖子: 689
送出感谢: 0 次
接收感谢: 0 次
问个简单的问题SDL和OPENGL有什么区别?


_________________
Titainium


页首
 用户资料  
 
3 楼 
 文章标题 :
帖子发表于 : 2007-06-02 0:13 

注册: 2007-05-24 20:08
帖子: 3
送出感谢: 0 次
接收感谢: 0 次
貌似SDL和DirectShow很象!


页首
 用户资料  
 
4 楼 
 文章标题 :
帖子发表于 : 2007-06-02 18:51 

注册: 2007-06-02 17:48
帖子: 19
送出感谢: 0 次
接收感谢: 0 次
titainium 写道:
问个简单的问题SDL和OPENGL有什么区别?

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

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

以上仅是本人对SDL和opengl的“区别”的观点。 :)


页首
 用户资料  
 
5 楼 
 文章标题 :
帖子发表于 : 2007-06-03 14:21 

注册: 2007-02-03 9:12
帖子: 39
送出感谢: 0 次
接收感谢: 0 次
这个是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图形接口


页首
 用户资料  
 
6 楼 
 文章标题 :
帖子发表于 : 2007-06-03 14:25 

注册: 2007-02-03 9:12
帖子: 39
送出感谢: 0 次
接收感谢: 0 次
twm 写道:
titainium 写道:
问个简单的问题SDL和OPENGL有什么区别?

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

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

以上仅是本人对SDL和opengl的“区别”的观点。 :)

这位兄弟对SDL还比较有研究.


页首
 用户资料  
 
7 楼 
 文章标题 :
帖子发表于 : 2007-06-05 12:45 
头像

注册: 2006-12-02 12:25
帖子: 689
送出感谢: 0 次
接收感谢: 0 次
谢了!


_________________
Titainium


页首
 用户资料  
 
8 楼 
 文章标题 :
帖子发表于 : 2007-06-05 14:23 

注册: 2006-07-10 17:40
帖子: 44
送出感谢: 0 次
接收感谢: 0 次
titainium 写道:
问个简单的问题SDL和OPENGL有什么区别?

2d是SDL库自己实现的,3d需要OPENGL来实现 2d跟directdraw基本相同 不过它可是夸平台的。


页首
 用户资料  
 
显示帖子 :  排序  
发表新帖 回复这个主题  [ 8 篇帖子 ] 

当前时区为 UTC + 8 小时


在线用户

正在浏览此版面的用户:没有注册用户 和 2 位游客


不能 在这个版面发表主题
不能 在这个版面回复主题
不能 在这个版面编辑帖子
不能 在这个版面删除帖子
不能 在这个版面提交附件

前往 :  
本站点为公益性站点,用于推广开源自由软件,由 DiaHosting VPSBudgetVM VPS 提供服务。
我们认为:软件应可免费取得,软件工具在各种语言环境下皆可使用,且不会有任何功能上的差异;
人们应有定制和修改软件的自由,且方式不受限制,只要他们自认为合适。

Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
简体中文语系由 王笑宇 翻译