📄 15-9.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 + -