正文

SDL 入门试验2006-12-27 13:08:00

【评论】 【打印】 【字体: 】 本文链接:http://blog.pfan.cn/tonyhu/21988.html

分享到:

一直想写图形方面的程序,又不想写窗口方面的,那种全是拖拉式控件,没什么
特别好玩地……,偶然间发现了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 ();
}

程序效果:

阅读(6109) | 评论(3)


版权声明:编程爱好者网站为此博客服务提供商,如本文牵涉到版权问题,编程爱好者网站不承担相关责任,如有版权问题请直接与本文作者联系解决。谢谢!

评论

loading...
您需要登录后才能评论,请 登录 或者 注册