一直想写图形方面的程序,又不想写窗口方面的,那种全是拖拉式控件,没什么
特别好玩地……,偶然间发现了SDL(Simple Directmedia Library)发现真是是我
想要地,呵呵,不像DirectX那样基于COM技术,我可不想为了写几个小程序就去
搞清烦透了的COM,最重要的是,我是LINUX系统,学COM没用场,呵呵……
最让人激动的是SDL竟然是跨平台的,WIN32下也可以用,这样,我在我的Gentoo
下写的程序完全就可以让别人在WIN32下编译运行了,真是PERFECT……
SDL是完全是C库,感觉蛮小地,很快就学会了……
只要会C,几乎一下午就可以写你自己的小游戏了(虽然这样,SDL算起来还是一个比较底层的库,你要自己控制所有的东西,一帧一帧的东西,你要全部自己来实现)……
虽然它是一个C库,但其它语言完全可以调用它……
下面是我在SDL网站上下的ALIENS游戏的自己重写,说我抄也无所谓了,
因为只要自己明白了其中的道理,都一样了(至少还花了一下午的写程序时间呀)……
算是SDL入门作品了(程序在Gentoo Linux 2006.1下SDL1.2.9编译运行通过,WIN32下没试,
没功夫去配置WIN下的SDL环境,网上很多这样的东西)
/***************************************************************************
* 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. *
***************************************************************************/
/*对ALIENS游戏的重写--初学SDL*/
#include <iostream>
#include <stdlib.h>
#include <SDL/SDL.h>
#include <SDL/SDL_mixer.h> //不是SDL标准包,但可很方便地操纵声频,几乎快成标准包了
using namespace std;
const int MAXALIENS = 50;
const int MAXSHOTS = 4;
const int MAXUPDATES = 2 * (MAXSHOTS + MAXALIENS + 1);
const int FPS = 25; //帧速
const int PLAYER_SPEED = 5;
const int SHOT_SPEED = 8;
const int ALIEN_SPEED = 8;
const int EXPLODE_TIME = 4;
enum
{
MUSIC_WAV,
SHOT_WAV,
EXPLODE_WAV,
NUM_WAVES
};
Mix_Chunk *sounds[NUM_WAVES]; //让枚举成为Index
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方便,把源,目的都打在一个结构中
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++) //Blit梆定
{
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在Updatesene()中
{
blit *update;
update = &blits[numupdates++]; //之后交给Updatescene()去Blit;
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;
//这两行其实只有UpdateRect才用到;Blit无用
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);
//BLit后的更新屏幕
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 = 0;
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)
{
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);
}
int
main (int argc, char *argv[])
{
if (SDL_Init (SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) //初始化
cout << "init error" << endl;
atexit (SDL_Quit);
if ((screen =
SDL_SetVideoMode (640, 480, 32,
SDL_HWSURFACE | SDL_DOUBLEBUF)) == NULL)
cout << "init video mode error" << endl;
SDL_WM_SetCaption ("aliens", "aliens");
/* 找开音频 */
if (Mix_OpenAudio (11025, AUDIO_U8, 1, 512) < 0)
{
fprintf (stderr,
"Warning: Couldn't set 11025 Hz 8-bit audio\n- Reason: %s\n",
SDL_GetError ());
}
srand (time (NULL));
LoadData ();
rungame ();
FreeData ();
Mix_CloseAudio ();
}
程序效果:
评论