掌叔
2008-06-10 09:23:18
摘自:[url]http://blog.sina.com.cn/vcbear[/url]
作者:vcbear
学习了如何装载位图和键盘控制后,我们就可以写个基本的小游戏了,下面是依据老外的文章照葫芦画瓢做的一个小游戏。下面是截图:左右光标键控制QQ移动,Enter键发子弹
[attach]90[/attach]
下面是完整的源码:
----------------------------------------------------------------------
/***************************************************************************
* Copyright (C) 2006 by xhh *
* huyinlin@XHH *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include
#include
#include "libnge.h"
#include
using namespace std;
const int MAXALIENS = 50;
const int MAXSHOTS = 4;
const int MAXUPDATES = 2 * (MAXSHOTS + MAXALIENS + 1);
const int FPS = 100; //帧速
const int PLAYER_SPEED = 5;
const int SHOT_SPEED = 8;
const int ALIEN_SPEED = 2;
const int EXPLODE_TIME = 4;
enum
{
MUSIC_WAV,
SHOT_WAV,
EXPLODE_WAV,
NUM_WAVES
};
Mix_Chunk *sounds[NUM_WAVES]; //音频数组
SDL_Surface *screen, *back; //屏幕和背景
typedef struct
{
int x, y; //游戏元素横纵坐标
int alive; //游戏元素生存状态
int faceing; //游戏元素方向
SDL_Surface *img; //游戏元素图象
} object;
object me; //玩家
object aliens[MAXALIENS]; //目标
object shots[MAXSHOTS]; //子弹
object explosion[MAXALIENS + 1]; //击中效果
SDL_Rect src[MAXUPDATES], dst[MAXUPDATES]; //各个分散的要更新的区域
int numupdates; //要更新的区域数目
int reloading;
typedef struct
{
SDL_Surface *img;
SDL_Rect *src, *dst;
} blit; //贴图结构
blit blits[MAXUPDATES];
SDL_Surface * LoadImg (const char *name) //装入图象
{
SDL_Surface *tmp, *ok;
if ((tmp = SDL_LoadBMP (name)) == NULL)
{
fprintf (stderr, "load %s error", name);
return NULL;
}
SDL_SetColorKey (tmp, SDL_SRCCOLORKEY | SDL_RLEACCEL,*(Uint8 *) tmp->pixels); //抠图处理
ok = SDL_DisplayFormat (tmp);
SDL_FreeSurface (tmp);
return ok;
}
void LoadData () //加载游戏元素
{
int i;
//游戏图象
me.img = LoadImg ("player.bmp");
aliens[0].img = LoadImg ("alien.bmp");
shots[0].img = LoadImg ("shot.bmp");
explosion[0].img = LoadImg ("explosion.bmp");
back = LoadImg ("back.bmp");
//游戏声音
sounds[MUSIC_WAV] = Mix_LoadWAV ("music.wav");
sounds[SHOT_WAV] = Mix_LoadWAV ("shot.wav");
sounds[EXPLODE_WAV] = Mix_LoadWAV ("explode.wav");
//各数组初始化
for (i = 1; i < MAXALIENS; i++)
{
aliens[i].img = aliens[0].img;
}
for (i = 1; i < MAXSHOTS; i++)
{
shots[i].img = shots[0].img;
}
for (i = 1; i < MAXALIENS + 1; i++)
{
explosion[i].img = explosion[0].img;
}
for (i = 0; i < MAXUPDATES; i++)
{
blits[i].src = &src[i];
blits[i].dst = &dst[i];
}
}
void FreeData () //释放游戏元素
{
SDL_FreeSurface (me.img);
SDL_FreeSurface (aliens[0].img);
SDL_FreeSurface (shots[0].img);
SDL_FreeSurface (explosion[0].img);
}
void drawobject (object * sprite) //游戏元素贴图准备
{
blit *update;
update = &blits[numupdates++];
update->img = sprite->img;
update->src->x = update->src->y = 0;
update->src->w = sprite->img->w;
update->src->h = sprite->img->h;
update->dst->x = sprite->x;
update->dst->y = sprite->y;
update->dst->w = sprite->img->w;
update->dst->h = sprite->img->h;
}
void eraseobject (object * sprite) //用背景盖掉object
{
blit *update;
update = &blits[numupdates++];
update->img = back;
update->src->x = sprite->x;
update->src->y = sprite->y;
update->src->w = sprite->img->w;
update->src->h = sprite->img->h;
update->dst->x = sprite->x;
update->dst->y = sprite->y;
update->dst->w = sprite->img->w;
update->dst->h = sprite->img->h;
}
void wait ()
{
static Uint32 next_tick = 0;
Uint32 this_tick;
this_tick = SDL_GetTicks ();
if (this_tick < next_tick)
SDL_Delay (next_tick - this_tick);
next_tick = this_tick + 1000 / FPS;
}
void Updatescene () //游戏元素贴图
{
int i;
for (i = 0; i < numupdates; i++)
{
SDL_BlitSurface (blits[i].img, blits[i].src, screen,blits[i].dst);
}
SDL_UpdateRects (screen, numupdates, dst);
numupdates = 0;
}
void creatalien () //创建目标
{
int i = 0;
for (i = 0; i < MAXALIENS; i++)
{
if (!aliens[i].alive)
break;
}
if (i == MAXALIENS)
return;
do
{
aliens[i].faceing = (rand () % 3) - 1;
}
while (aliens[i].faceing == 0); //方向就只有 1 和-1了
aliens[i].y = 10;
if (aliens[i].faceing < 0)
aliens[i].x = screen->w - aliens[i].img->w - 1;
else
aliens[i].x = 0;
aliens[i].alive = 1;
}
bool collision (object * sprite1, object * sprite2) //测试碰撞
{
if ((sprite1->y >= (sprite2->y + sprite2->img->h)) ||
(sprite1->x >= (sprite2->x + sprite2->img->w)) ||
(sprite2->y >= (sprite1->y + sprite1->img->h)) ||
(sprite2->x >= (sprite1->x + sprite1->img->w)))
{
return (false);
}
return (true);
}
void rungame () //启动游戏
{
int j, i;
SDL_Event event;
Uint8 *keys;
numupdates = 0;
SDL_BlitSurface (back, NULL, screen, NULL);
SDL_UpdateRect (screen, 0, 0, 0, 0);
me.x = (screen->w - me.img->w) / 2;
me.y = (screen->h - me.img->h) - 1;
me.alive = 1;
me.faceing = 0;
for (i = 0; i < MAXALIENS; i++)
aliens[i].alive = 0;
for (i = 0; i < MAXSHOTS; i++)
shots[i].alive = 0;
drawobject (&me);
creatalien ();
drawobject (&aliens[0]);
Updatescene ();
while (me.alive)
{
wait (); //一帧一帧地运行
while (SDL_PollEvent (&event))
if (event.type == SDL_QUIT)
return;
keys = SDL_GetKeyState (NULL);
if (keys[SDLK_ESCAPE])
return;
//在一帧里全部要更新
for (i = 0; i < MAXALIENS; i++)
if (aliens[i].alive)
eraseobject (&aliens[i]);
for (i = 0; i < MAXSHOTS; i++)
if (shots[i].alive)
eraseobject (&shots[i]);
for (i = 0; i < MAXALIENS + 1; i++)
if (explosion[i].alive)
eraseobject (&explosion[i]);
eraseobject (&me);
//explosion计时
for (i = 0; i < MAXALIENS + 1; i++)
{
if (explosion[i].alive)
explosion[i].alive--;
}
//新产生一个aliens
if ((rand () % FPS) == 0) //大约过FPS帧才产生一个,即一秒一个
creatalien ();
//产生shot
if (!reloading)
{
// if (keys[SDLK_SPACE] == SDL_PRESSED)
if (keys[SDLK_RETURN] == SDL_PRESSED)
{
for (i = 0; i < MAXSHOTS; i++)
if (!shots[i].alive)
break;
if (i != MAXSHOTS)
{
shots[i].x =
me.x + (me.img->w -
shots[i].img->w) / 2;
shots[i].y = me.y - shots[i].img->h;
shots[i].alive = 1;
Mix_PlayChannel (SHOT_WAV,
sounds[SHOT_WAV], 0);
}
}
}
reloading = (keys[SDLK_SPACE] == SDL_PRESSED);
//移动自己
me.faceing = 0;
if (keys[SDLK_RIGHT])
me.faceing++;
if (keys[SDLK_LEFT])
me.faceing--;
me.x += me.faceing * PLAYER_SPEED;
if (me.x < 0)
me.x = 0;
if (me.x > screen->w - me.img->w)
me.x = screen->w - me.img->w - 1;
//移动aliens
for (i = 0; i < MAXALIENS; i++)
{
if (aliens[i].alive)
{
aliens[i].x +=
aliens[i].faceing * ALIEN_SPEED;
if (aliens[i].x < 0)
{
aliens[i].x = 0;
aliens[i].faceing = 1;
aliens[i].y += aliens[i].img->h;
}
if (aliens[i].x >=
screen->w - aliens[i].img->w)
{
aliens[i].x =
screen->w - aliens[i].img->w -
1;
aliens[i].faceing = -1;
aliens[i].y += aliens[i].img->h;
}
}
}
//移动shot
for (i = 0; i < MAXSHOTS; i++)
{
if (shots[i].alive)
{
shots[i].y -= SHOT_SPEED;
if (shots[i].y < 0)
shots[i].alive = 0;
}
}
//测试碰撞
for (i = 0; i < MAXSHOTS; i++)
for (j = 0; j < MAXALIENS; j++)
{
if (shots[i].alive && aliens[j].alive&& collision (&shots[i], &aliens[j]))
{
shots[i].alive = 0;
aliens[j].alive = 0;
explosion[j].x = aliens[j].x;
explosion[j].y = aliens[j].y;
explosion[j].alive = EXPLODE_TIME;
Mix_PlayChannel (EXPLODE_WAV,sounds[EXPLODE_WAV],0);
}
}
for (i = 0; i < MAXALIENS; i++)
{
if (aliens[i].alive && me.alive&& collision (&me, &aliens[i]))
{
aliens[i].alive = 0;
me.alive = 0;
explosion[i].x = aliens[i].x;
explosion[i].y = aliens[i].y;
explosion[i].alive = EXPLODE_TIME;
explosion[MAXALIENS].x = me.x;
explosion[MAXALIENS].y = me.y;
explosion[MAXALIENS].alive = EXPLODE_TIME;
Mix_PlayChannel (EXPLODE_WAV,sounds[EXPLODE_WAV], 0);
}
}
//draw所有的东东
if (me.alive)
drawobject (&me);
for (i = 0; i < MAXALIENS; i++)
if (aliens[i].alive)
drawobject (&aliens[i]);
for (i = 0; i < MAXSHOTS; i++)
if (shots[i].alive)
drawobject (&shots[i]);
for (i = 0; i < MAXALIENS + 1; i++)
if (explosion[i].alive)
drawobject (&explosion[i]);
Updatescene ();
}
while (Mix_Playing (EXPLODE_WAV))
wait ();
Mix_HaltChannel (-1);
}
extern "C"
int main(int argc, char* argv[])
{
/* Initialize the SDL library */
if( SDL_Init(SDL_INIT_VIDEO) < 0 )
{
fprintf(stderr,"Couldn't initialize SDL: %s
", SDL_GetError());
exit(1);
}
/* Clean up on exit */
atexit(SDL_Quit);
/*
* Initialize the display in a 640x480 8-bit palettized mode,
* requesting a software surface
*/
screen = SDL_SetVideoMode(640, 480, 32, SDL_HWSURFACE | SDL_DOUBLEBUF);
if ( screen == NULL )
{
fprintf(stderr, "Couldn't set 640x480x8 video mode: %s
",SDL_GetError());
exit(1);
}
SDL_WM_SetCaption ("vcbear", "vcbear");
if (Mix_OpenAudio (11025, AUDIO_U8, 1, 512) < 0)
{
fprintf (stderr,"Warning: Couldn't set 11025 Hz 8-bit audio
- Reason: %s
",SDL_GetError ());
}
// srand(time(NULL));
LoadData ();
rungame ();
FreeData ();
Mix_CloseAudio ();
exit(0);
}