⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 15-9.c

📁 《linux应用开发技术详解》的配套代码
💻 C
字号:
#include <stdio.h>
#include <stdlib.h>
#include <SDL.h>
#include <SDL_image.h>

#define DIR_UP    0
#define DIR_LEFT  1
#define DIR_DOWN  2
#define DIR_RIGHT 3

SDL_Surface *screen;

typedef struct Sprite_t {    /* 精灵模型 */
  int width;
  int height;
  int x;
  int y;
  int ox;
  int oy;
  int dir;
  int subframe;
  int speed;
  int timer;   /* use to calculate subframe */
  SDL_Surface *image;
}Sprite_t;

typedef enum GameState {   /* 简单状态机 */
  GAME_RUNNING,
  GAME_OVER,
}GameState;

void Init_SDL()            /* SDL初始化 */
{
  if ( SDL_Init( SDL_INIT_VIDEO) < 0 ) {
    fprintf(stderr,"Can't init SDL: %s\n",SDL_GetError());
    exit(1);
  }
  screen = SDL_SetVideoMode(640, 480, 16, SDL_SWSURFACE);
  if ( screen == NULL ) {
    fprintf(stderr, "Error: %s\n",SDL_GetError());
    exit(1);
  }
  atexit(SDL_Quit);
}

void DrawSprite(SDL_Surface *surface,Sprite_t *sprite)  /* 绘制精灵的函数 */
{
  SDL_Rect src_rect,des_rect;
  sprite->subframe=sprite->timer/4;      /* 每计时4次就换下一个子帧 */
  src_rect.w=des_rect.w=sprite->width;
  src_rect.h=des_rect.h=sprite->height;
  src_rect.x=sprite->subframe*sprite->width;
  src_rect.y=sprite->dir*sprite->height;
  des_rect.x=sprite->x;
  des_rect.y=sprite->y;
  /* Draw sprite to new position */
  SDL_BlitSurface(sprite->image,&src_rect,surface,&des_rect);
}

void ClearSprite(SDL_Surface *surface,Sprite_t *sprite)  /* 擦除精灵的函数 */
{
  SDL_Rect mask;
  mask.w=sprite->width;
  mask.h=sprite->height;
  mask.x=sprite->ox;
  mask.y=sprite->oy;
  /* Clear sprite from the old position */
  SDL_FillRect(surface,&mask,SDL_MapRGB(surface->format,0,0,0));
}

Uint32 TimeLeft()   /* 用于调整延迟的函数,动画有相对固定的帧速率 */
{
  static Uint32 next_time=0;
  Uint32 now;
  now=SDL_GetTicks();
  if(next_time<=now){
    next_time=now+30;
    return(0);
  }
  return(next_time-now);
}

int main()
{
  GameState game_state;
  Sprite_t tank;              /* 定义坦克这个精灵 */
  Uint32 start_time,end_time;

  Init_SDL();
  tank.image=IMG_Load("tank.png");  /* 装入图片 */
  SDL_SetColorKey(tank.image,SDL_SRCCOLORKEY,SDL_MapRGB(tank.image->format,255,0,255)); /* 设置透明色 */
  tank.image=SDL_DisplayFormat(tank.image);  /* 转换成屏幕显示格式 */
  SDL_BlitSurface(tank.image,NULL,screen,&tank.image->clip_rect);  /* 将整图贴到屏幕左上角 */
  SDL_UpdateRect(screen,0,0,0,0);  /* 更新屏幕 */

  game_state=GAME_RUNNING;  /* 初始化各种参数 */
  tank.dir=DIR_RIGHT;
  tank.width=32;
  tank.height=32;
  tank.x=300;
  tank.y=200;
  tank.ox=tank.x;
  tank.oy=tank.y;
  tank.speed=3;
  tank.timer=0;
  start_time=SDL_GetTicks();
  srand(time(NULL));            /* 设置随机数种子 */

  while(game_state==GAME_RUNNING){         /* 动画主循环 */
    ClearSprite(screen,&tank);                    /* 清除旧精灵即坦克 */
    if((int)(100.0*rand()/(RAND_MAX)+1.0)<10){  /* 简单人工智能,坦克会自动转向 */
      tank.dir=(int)(4.0*rand()/(RAND_MAX+1.0));
    }
    if(tank.dir==DIR_UP)tank.y-=tank.speed;
    else if(tank.dir==DIR_DOWN)tank.y+=tank.speed;
    else if(tank.dir==DIR_LEFT)tank.x-=tank.speed;
    else if(tank.dir==DIR_RIGHT)tank.x+=tank.speed;
    DrawSprite(screen,&tank);                    /* 在新的位置绘出精灵即坦克 */
    tank.ox=tank.x;                             /* 重新记录精灵的“旧”位置 */
    tank.oy=tank.y;  
    SDL_UpdateRect(screen,0,0,0,0);              /* 更新屏幕 */
    SDL_Delay(TimeLeft());                     /* 延迟 */
    end_time=SDL_GetTicks();
    if(end_time-start_time>5000)game_state=GAME_OVER;  /* 超出时间就将状态机置为结束状态,退出动画 */
    tank.timer++;                    /* 记时器,每主循环一次便增1 */
    if(tank.timer>=8)tank.timer=0;
  }

  SDL_FreeSurface(tank.image);       /* 退出主循环后释放图片占用的绘图平面 */
  SDL_Delay(3000);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -