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

本帖最后由 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 *本站禁止HTML标签噢*

//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 *本站禁止HTML标签噢*

//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 *本站禁止HTML标签噢*

//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 *本站禁止HTML标签噢*

//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 *本站禁止HTML标签噢*

//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 *本站禁止HTML标签噢*

//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 *本站禁止HTML标签噢*

//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

本内容已隐藏,回复后刷新可见哦

拜占庭恋歌
如果能尽快上手就好了
展开Biu

=787=如果能尽快上手就好了

[查看全文]
daxia9999
挺感兴趣
展开Biu

挺感兴趣,可以看看

[查看全文]
feizhai
正在学习可视化
展开Biu

正在学习可视化,观摩一下大触的作品

[查看全文]
Carlyle_3
留着以后看
展开Biu

不错,留着以后看

[查看全文]
mekami
貌似很牛
展开Biu

貌似很牛B的养殖

[查看全文]
染绘
看到这个诶
展开Biu

哟~看到这个诶~

[查看全文]
月夜猫妖
封獣★ぬえ
我来支持了个
展开Biu

我来支持了个,人气这么冷,不科学啊@兰陵笑忘生

[查看全文]