本帖最后由 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游戏的话,还是用引擎比较方便哈~
戳这里,国外神论坛,英文好的来哈~ 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