喵宅苑 MewoGarden × 技术宅社区II | Z站 Z Station 棒棒哒纯文字二次元技术社区

正文

SDL游戏编程(附教学网址,只有流程)更新至7.箭头

作者:scropioczn
[i=s] 本帖最后由 scropioczn 于 2013-6-29 13:38 编辑 由于本人留学党教程一路全英文,与国内术语不符的请指出莫吐槽……另外有不清楚的地方或者有问题当然踊跃举手啦~@@25!! 1发:1.架构 -> 6.第一次调试 6发:7.箭头 -> ?.第二次调试(规划) 教程传送门:SDL tutorial by Lazy Foo 以下正文。此强调本文所涉及的程序的执照是GNU GPL。 介绍: 最近新来技术宅社区,当然直奔编程版块没的说。两点吧。一点是太冷清…… 二是左算法右算法…… 不要被那些玩意儿塞满了,编程没点乐趣肿么搞下去?当初我也是闲着无聊去一个国外神论坛(下附链接)搜C++能干吗,然后找到了SDL的。所以我决定扩散SDL!各路大神求支持啊~ 简单介绍下吧。SDL即为Simple DirectMedia Layer。跟字面意思一样,这个API理念很简单,就是把图片啪地贴到屏幕上去……当然了,除了图像部分还包括了按键操作,时间,音效的处理,所以可以直接进行2D,伪3D(或2.5D吧?)游戏开发。所以像什么俄罗斯方块啊什么的都大丈夫~ 当然,如果你对3D游戏制作非常感兴趣(大概一般人都会感兴趣吧?),不用慌。SDL支持openGL,即为目前主流图像处理API。当然真正做3D游戏的话,还是用引擎比较方便哈~ 戳这里,SDL网站,包括doc,下载,示范什么的 戳这里,国外神论坛,英文好的来哈~ Dream.In.Code 已经练手编了两个程序,第一个是个一个算法的demonstration,另一个是真正的游戏~ 不过正好赶上一朋友生日,做了个特别版的…… 所以正好借此机会搞个普通的release版本。 所以嘛,这个游戏叫做Mastermind。中文翻译叫珠玑妙算。估计有些人应该玩过……当然原版是个桌游,要两个人,一个人设置答案,另一个人猜。我这里就不高那么烦了,设置答案的人就电脑吧。所以规则就是电脑随机生成一个组合,该组合由四个球组成。每个球有5种不同的颜色(在想后面可以搞个难度等级,改成6种或4种之类的)。一个组合中的球的颜色可以重合。然后用户来猜。输入是不同组合,然后电脑会根据你给出的组合来给予提示。提示由两个数字组成,中间以斜杠(/)相隔。第一个数字是表示与答案中的球颜色相同,并且在同一位置的球的个数;第二个数字表示的是与答案中仅仅颜色相同的球的个数。并且,答案中多出来同样颜色的球将不算在内。 比如,答案是: 绿回答是: 给出的提示就是:1 / 1 因为:一个红球位置正确,一个黄球颜色正确,而第一个红球则不计考虑。 好啦,终于介绍完啦,那么我们开始码代码吧~ 1.环境设定 所选IDE是Eclipse Juno。擦……刚上了下官网,发现新版本Kepler(v 4.3)已经发布……各位感兴趣可以下下来用用。编译器(compiler)当然是咱大GCC的minGW。 工程起名叫MastermindA。A是animated。原来做了个单纯算法,所以这个是动画版。 由于我不准备做声效,所以只要在library里面加上SDL以及image和ttf的就行了。 下面有附图。 2. 架构 经过GTGE(java上的一款比较容易的游戏编程API)的实践,以及两次练手,我总结出了一个SDL的基本框架。 首先创建mainGame.cpp(包括main),Variables.h(常用量),Types(typedef的各种),GHeader.h(所有的header文件都会在这边包括一遍,主要是为了在mainGame里面看着简洁=。=),和Core.h(架构核心,后面补上cpp)。 main先不着急,先放一边。先写Variables.h吧,就那么几个常量,后面可以再优化。 Variables.h [mw_shl_code=cpp,true]/* * Variables.h * * Created on: 2013-06-26 * Author: scropioczn * Description: This is the header file for general constants. * Version: */ #ifndef VARIABLES_H_ #define VARIABLES_H_ #include "SDL/SDL.h" #include "SDL/SDL_image.h" #include "SDL/SDL_ttf.h" //Screen specs #define SCREEN_WIDTH 1024 #define SCREEN_HEIGHT 720 #define SCREEN_BPP 32 //FPS and elapsed time #define FRAME_PER_SECOND 60 #define ELAPSED_TIME 17 //Color macro #define RED 11 #define YELLOW 12 #define BLUE 13 #define GREEN 14 #define PURPLE 15 #endif /* VARIABLES_H_ */ [/mw_shl_code] 在本程序中,暂时用到两个新定义的变量类型,一个是Stage(阶段),另一个是BallColor(球的颜色)。 Types.h [mw_shl_code=cpp,true]/* * Types.h * * Created on: 2013-06-27 * Author: scropioczn * Description: This is the header file for custom variable types. * Version: */ #ifndef TYPES_H_ #define TYPES_H_ #include "SDL/SDL.h" #include "SDL/SDL_image.h" #include "SDL/SDL_ttf.h" typedef enum { intro, tutorial1, tutorial2, game, end }Stage; typedef enum { red, yellow, blue, green, purple, colorless }BallColor; #endif /* TYPES_H_ */ [/mw_shl_code] Core.h [mw_shl_code=cpp,true]/* * Core.h * * Created on: 2013-06-27 * Author: scropioczn * Description: This is the header file for the core of the game. * Version: */ #ifndef CORE_H_ #define CORE_H_ #include "SDL/SDL.h" #include "SDL/SDL_image.h" #include "SDL/SDL_ttf.h" bool init(); bool update(); void render(); void cleanUp(); #endif /* CORE_H_ */[/mw_shl_code] 这就是我所总结的核心部分。第一个是初始化,第二个是更新,第三个是显示,第四个是运行完后的清理。更新的话简单来说就是游戏运行时一切除了显示部分的东西,笑。 然后是GHeader.h 以后每创建一个header file都加进来就好了。目前就只有三个。 [mw_shl_code=cpp,true]/* * GHeader.h * * Created on: 2013-06-27 * Author: scropioczn * Description: This is the general header file. * Version: */ #ifndef GHEADER_H_ #define GHEADER_H_ #include "SDL/SDL.h" #include "SDL/SDL_image.h" #include "SDL/SDL_ttf.h" #include "Variables.h" #include "Types.h" #include "Core.h" #endif /* GHEADER_H_ */ [/mw_shl_code] 最后在基本构架的最后,我们把main加上。main里面要定义个叫screen的SDL_Surface,就是最底层的窗口的那层。 mainGame.cpp [mw_shl_code=cpp,true]/* * mainGame.cpp * * Created on: 2013-06-26 * Author: scropioczn * Description: This is the source file containing main function of the game. * Version: pre-alpha */ //SDL libraries #include "SDL/SDL.h" #include "SDL/SDL_image.h" #include "SDL/SDL_ttf.h" //C/C++ libraries #include <string> //General header file #include "GHeader.h" //Object declarations SDL_Surface *screen; int main(int argc, char *args[]) { //Creating objects using dynamic memory. //Initialization if(init() == false) { return 1; } bool quit = false; while(quit == false) { //Update update(); //Render render(); } //Clean up cleanUp(); return 0; } [/mw_shl_code] 正如诸位所看到的,main里面会变得非常有条理。设计理念自认使用到了Abstraction,笑@@33!! 那么至此,主要框架就完成了(其实还差个Core.cpp……下次再搞,不打紧)。 3.时间帧数处理(框架的扩充) 游戏里很重要的一个环节就是fps。有了稳定的fps才能有流畅的游戏。 为了实现这一目标,建立Timer.h 与 Timer.cpp Timer.h [mw_shl_code=cpp,true]/* * Timer.h * * Created on: 2013-06-27 * Author: scropioczn * Description: This is the header file of the Timer class. * Version: */ #ifndef TIMER_H_ #define TIMER_H_ #include "SDL/SDL.h" #include "SDL/SDL_image.h" #include "SDL/SDL_ttf.h" class Timer { private: //timer variables int start_tick; //start time int cur_tick; //current time public: //Constructor and destructor Timer(); ~Timer(); //----------Gets-----------// //----------Sets-----------// void start(); //start timer void regulate(); //regulate fps }; #endif /* TIMER_H_ */[/mw_shl_code] 在Timer.h里面,两个变量:起始时间与当前时间。两个函数:开始时间与控制fps。 Timer.cpp [mw_shl_code=cpp,true]/* * Timer.cpp * * Created on: 2013-06-27 * Author: scropioczn * Description: This is the source file for the Timer class. * Version: */ //SDL libraries #include "SDL/SDL.h" #include "SDL/SDL_image.h" #include "SDL/SDL_ttf.h" //C/C++ libraries #include <string> //Own header file #include "Timer.h" //Linked header files #include "Variables.h" //external objects //external variables //Definitions Timer::Timer() { start_tick = 0; cur_tick = 0; } Timer::~Timer() { } void Timer::start() { start_tick = SDL_GetTicks(); } void Timer::regulate() { cur_tick = SDL_GetTicks(); if((cur_tick - start_tick) < ELAPSED_TIME) { SDL_Delay(ELAPSED_TIME - (cur_tick - start_tick)); } } [/mw_shl_code] 在Variables.h中规定的ELAPSED_TIME就是每帧的时间,就是1000/FRAME_PER_SECOND。 然后在GHeader.h里加上Timer.h。 接下来把Timer加入main里面。 mainGame.cpp [mw_shl_code=cpp,true]/* * mainGame.cpp * * Created on: 2013-06-26 * Author: scropioczn * Description: This is the source file containing main function of the game. * Version: pre-alpha */ //SDL libraries #include "SDL/SDL.h" #include "SDL/SDL_image.h" #include "SDL/SDL_ttf.h" //C/C++ libraries #include <string> //General header file #include "GHeader.h" //Object declarations Timer *timer; SDL_Surface *screen; int main(int argc, char *args[]) { //Creating objects using dynamic memory. timer = new Timer(); //Initialization if(init() == false) { return 1; } bool quit = false; while(quit == false) { timer->start(); //Update update(); //Render render(); timer->regulate(); } //Clean up cleanUp(); return 0; } [/mw_shl_code] 关于Timer的destructor,将会放到Core里面的cleanUp()函数中。这个在之后做Core.cpp的时候与其他object一起放进去。 4.公用函数(Utility functions) 每个SDL游戏都要用到的函数:显示图片(applySurface),装载图片(loadImage),和把背景设置为透明(setColorKey)(在lazy foo的教程里,第一个和第三个是在一起的,不过我分开来了,是以防图片背景色不同。) 创建Utility.h与Utility.cpp Utility.h [mw_shl_code=cpp,true]/* * Utility.h * * Created on: 2013-06-27 * Author: scropioczn * Description: This is the header file for declarations of utility functions. * Version: */ #ifndef UTILITY_H_ #define UTILITY_H_ #include "SDL/SDL.h" #include "SDL/SDL_image.h" #include "SDL/SDL_ttf.h" void applySurface(int x, int y, SDL_Surface *src, SDL_Surface *dest, SDL_Rect *clip); SDL_Surface *loadImage(std::string filename); void setColorKey(SDL_Surface *the_surface, Uint8 red, Uint8 green, Uint8 blue); #endif /* UTILITY_H_ */ [/mw_shl_code] Utility.cpp [mw_shl_code=cpp,true]/* * Utility.cpp * * Created on: 2013-06-27 * Author: scropioczn * Description: This is the source file which contains the definitions of the utility functions. * Version: */ //SDL libraries #include "SDL/SDL.h" #include "SDL/SDL_image.h" #include "SDL/SDL_ttf.h" //C/C++ libraries #include <string> //Own header file #include "Utility.h" //Linked header files //external objects //external variables //Definitions void applySurface(int x, int y, SDL_Surface *src, SDL_Surface *dest, SDL_Rect *clip) { SDL_Rect offset; offset.x = x; offset.y = y; SDL_BlitSurface(src, clip, dest, &offset); } SDL_Surface *loadImage(std::string filename) { SDL_Surface *loaded_image = NULL; SDL_Surface *optimized_image = NULL; loaded_image = IMG_Load(filename.c_str()); if (loaded_image != NULL) { optimized_image = SDL_DisplayFormat(loaded_image); SDL_FreeSurface(loaded_image); } return optimized_image; } void setColorKey(SDL_Surface *the_surface, Uint8 red, Uint8 green, Uint8 blue) { if (the_surface != NULL) { SDL_SetColorKey(the_surface, SDL_SRCCOLORKEY, SDL_MapRGB(the_surface->format, red, green, blue)); } } [/mw_shl_code] 5. 球们(Ball Class) 基本的每个SDL的必需都差不多搞定了,接下来我想了想还是先把球的class搞出来吧。 创建Ball.h 与 Ball.cpp Ball.h [mw_shl_code=cpp,true]/* * Ball.h * * Created on: 2013-06-27 * Author: scropioczn * Description: This is the header file of the Ball class. * Version: */ #ifndef BALL_H_ #define BALL_H_ #include "SDL/SDL.h" #include "SDL/SDL_image.h" #include "SDL/SDL_ttf.h" #include "Types.h" class Ball { private: //Ball structure struct theBall { SDL_Surface *ball_image; //SDL_Rect offset; BallColor color; } the_ball[5]; int ball_width; int ball_height; public: //Constructor and destructor Ball(); ~Ball(); //Load images int loadBalls(); //----------Gets-----------// //get the offsets of a ball int getBallWidth(); int getBallHeight(); //----------Sets-----------// //Set color void setColor(); //render void render(BallColor the_color, int x, int y); //alpha test void render(); }; #endif /* BALL_H_ */[/mw_shl_code] class中定义了一个结构体,因为一个球有两项属性:Surface和颜色。由于目前球的颜色只有5种,所以定义了5个instance。之后的两个变量是球的尺寸,根据图片来定。 由于在本程序中球只是在相应位置显示出来,没有移动之类的,所以只定义了render。两个get是取得球的尺寸。 最后一个render用于第一次调试,具体见下。 Ball.cpp [mw_shl_code=cpp,true]/* * Ball.cpp * * Created on: 2013-06-28 * Author: scropioczn * Description: This is the source file of the Ball class definitions. * Version: */ //SDL libraries #include "SDL/SDL.h" #include "SDL/SDL_image.h" #include "SDL/SDL_ttf.h" //C/C++ libraries #include <string> //Own header file #include "Ball.h" //Linked header files #include "Utility.h" //external objects extern SDL_Surface *screen; //external variables //Definitions Ball::Ball() { for (int i = 0; i < 5; i++) { the_ball.ball_image = NULL; //the_ball.offset = NULL; the_ball.color = colorless; } ball_height = 0; ball_width = 0; } Ball::~Ball() { for (int i = 0; i < 5; i++) { SDL_FreeSurface(the_ball.ball_image); } } int Ball::loadBalls() { the_ball[0].ball_image = loadImage("data/ball/red.png"); the_ball[1].ball_image = loadImage("data/ball/yellow.png"); the_ball[2].ball_image = loadImage("data/ball/blue.png"); the_ball[3].ball_image = loadImage("data/ball/green.png"); the_ball[4].ball_image = loadImage("data/ball/purple.png"); for (int c_b = 0; c_b < 5; c_b++) { setColorKey(the_ball[c_b].ball_image, 0xFF, 0xFF, 0xFF); } int i = 0; while (i < 5) { if (the_ball.ball_image == NULL) { return -1; } i++; } ball_width = the_ball[0].ball_image->w; ball_height = the_ball[0].ball_image->h; return 0; } void Ball::setColor() { the_ball[0].color = red; the_ball[1].color = yellow; the_ball[2].color = blue; the_ball[3].color = green; the_ball[4].color = purple; } int Ball::getBallWidth() { return ball_width; } int Ball::getBallHeight() { return ball_height; } void Ball::render(BallColor the_color, int x, int y) { switch (the_color) { case red: applySurface(x, y, the_ball[0].ball_image, screen, NULL); break; case yellow: applySurface(x, y, the_ball[1].ball_image, screen, NULL); break; case blue: applySurface(x, y, the_ball[2].ball_image, screen, NULL); break; case green: applySurface(x, y, the_ball[3].ball_image, screen, NULL); break; case purple: applySurface(x, y, the_ball[4].ball_image, screen, NULL); break; default: ; break; } void Ball::render() { for(int i = 0; i < 5; i ++) { applySurface(50 + 50 * i, 100, the_ball.ball_image, screen, NULL); } } }[/mw_shl_code] 6.第一次调试:球们是否能正常显示 为了测试能否正常显示我们定义的5个球,我们需要完善Core。 init里面先将SDL初始化,屏幕初始化加上,然后将球的初始化加上。 update里面先加上SDL_QUIT,否则程序关不了@100#,也就意味着要用到SDL_Event,在mainGame里定义event,然后在Core.cpp里面用extern。 render里面把Ball的第二个render()加上,别忘了翻转屏幕。 Core.cpp [mw_shl_code=cpp,true]/* * Core.cpp * * Created on: 2013-06-28 * Author: scropioczn * Description: This is the source file of the core functions. * Version: */ //SDL libraries #include "SDL/SDL.h" #include "SDL/SDL_image.h" #include "SDL/SDL_ttf.h" //C/C++ libraries #include <string> //Own header file #include "Core.h" //Linked header files #include "Variables.h" #include "Types.h" #include "Ball.h" #include "Timer.h" //external objects extern Timer *timer; extern Ball *ball; //external variables extern SDL_Surface *screen; extern SDL_Event event; //Definitions bool init() { //SDL general initialization if(SDL_Init(SDL_INIT_EVERYTHING) == -1) { return false; } //screen initialization screen = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_SWSURFACE); if(screen == NULL) { return false; } //window settings SDL_WM_SetCaption("Mastermind", NULL); //-------------------Loadings--------------------// //balls if(ball->loadBalls() == -1) { return false; } ball->setColor(); return true; } bool update() { while(SDL_PollEvent(&event)) { if(event.type == SDL_QUIT) { return false; } } return true; } void render() { //alpha test //screen set as a background SDL_FillRect(screen, &screen->clip_rect, SDL_MapRGB(screen->format, 0xFF, 0xFF, 0xFF)); //show balls ball->render(); SDL_Flip(screen); } void cleanUp() { delete timer; delete ball; SDL_FreeSurface(screen); SDL_Quit(); } [/mw_shl_code] 然后是更新后的mainGame.cpp mainGame.cpp [mw_shl_code=cpp,true]/* * mainGame.cpp * * Created on: 2013-06-26 * Author: scropioczn * Description: This is the source file containing main function of the game. * Version: alpha test 01 */ //SDL libraries #include "SDL/SDL.h" #include "SDL/SDL_image.h" #include "SDL/SDL_ttf.h" //C/C++ libraries #include <string> //General header file #include "GHeader.h" //Object declarations Timer *timer; Ball *ball; SDL_Surface *screen; SDL_Event event; int main(int argc, char *args[]) { //Creating objects using dynamic memory. timer = new Timer(); ball = new Ball(); //Initialization if(init() == false) { return 1; } bool quit = false; while(quit == false) { timer->start(); //Update if(update() == false) { quit = true; } //Render render(); timer->regulate(); } //Clean up cleanUp(); return 0; } [/mw_shl_code] 本人调试正常显示。所用的图片文件在附件里。 attach://205322.zip 【本内容已隐藏,回复后刷新可见哦】

回复

如果能尽快上手就好了

作者:拜占庭恋歌
=787=如果能尽快上手就好了
查看回复

挺感兴趣

作者:daxia9999
挺感兴趣,可以看看
查看回复

正在学习可视化

作者:feizhai
正在学习可视化,观摩一下大触的作品
查看回复

留着以后看

作者:Carlyle_3
不错,留着以后看
查看回复

貌似很牛

作者:mekami
貌似很牛B的养殖
查看回复

看到这个诶

作者:染绘
哟~看到这个诶~
查看回复

月夜猫妖回复给帖子:12707024

作者:月夜猫妖
看晕了
查看回复

我来支持了个

作者:封獣★ぬえ
查看回复
上一页
下一页
0%
站点地图友情链接:
喵宅苑
喵空间社区程序
喵宅苑 静态版
宅喵RPG地图编辑器
络合兔
Lanzainc
技术宅
小五四博客
莉可POI
Mithril.js
枫の主题社
Project1
午后少年
机智库
七濑胡桃
xiuno
幻想の日常
魂研社
Nothentai
0xffff
欲望之花
泽泽社长
淀粉月刊
HAYOU