声明:此为大一下的程序设计综合课程设计,用C语言编写。本文作者认为,学好C语言是学好嵌入式和算法的重要基础。
在此之前请下载sdl2game库
目 录
一、 案例描述
1、总体描述
疯狂小车是一款能控制加速和停止并且有时钟附加背景能按喇叭和启动声音切换集一体的游戏。
2、基本功能描述
1)加速:按住“->”可以通过改变背景的移动速度以及车轮的转速,给人产生加速的感觉,松开时恢复原来的速度。
2)减速:按住“<-”可以通过改变背景的移动速度以及车轮的转速,给人产生减速的感觉,松开时恢复原来的速度
3)停止:按下空格可以停止。
4)启动声音:暂停后,再次按下空格后会响起汽车启动的声音。
5)上移:按住“上箭头”可以通过改变背景的移动速度以及车轮的转速,给人产生减速的感觉,松开时恢复原来的速度。
5)下移:按住“下箭头”可以通过改变背景的移动速度以及车轮的转速,给人产生减速的感觉,松开时恢复原来的速度。
3、附加功能描述
1)在汽车的左上角有一个时钟来显示时间。
2)为还原真实的移动效果,小车刚起步时只移动小车不移动背景,起步后只移动背景。
3)两个不同背景的衔接。
4)按住鼠标播放声音。
5)触碰到障碍物打印game over。
二、 界面设计
图1 主界面图
三、 模块化设计方案
- 框架结构描述
- 本系统采用单文件框架结构
表3.1 文件与函数构成
文件名 | 主要功能函数 | 参数和返回值 | 函数基本功能 |
Main.c | Setup() | 无参无返回值 | 初始化 |
checkCollision() | 小车的坐标,小车的长和宽 | 碰撞检测函数 | |
draw() | 参数为float stateTime | 界面绘图 | |
mousePress() | 无参无返回 | 鼠标事件处理 | |
keyDown() | 无参无返回 | 键盘事件处理 | |
keyUp() | 无参无返回 | 键盘事件处理 | |
close() | 无参无返回 | 程序结束时回收游戏资源. |
2、主函数调用各功能函数流程
图2主函数调用各功能函数流程图
四、 数据结构描述
#include "sdl2game.h"
#include <math.h>
#include <time.h>
Image *myroad1;
Image *scre;
Image *myroad2;
Image *car;
Image *wheel1;
Image *wheel2;
Image *obstacle;
int right=0;
int rights=640;
int angel=20;
int carx=-200;
int cary=78;
int flag=0;
Bool changepicture=FALSE;
Bool fast=FALSE;
Bool slow=FALSE;
Bool stop=FALSE;
Bool down=FALSE;
Bool up=FALSE;
Sound *horn;
Sound *eng;
// 定义障碍物的位置和尺寸
int obstacleX = 640;
int obstacleY = 200;
int obstacleWidth = 1;
int obstacleHeight = 1;
// 定义游戏状态变量
typedef enum {
PLAYING,
GAME_OVER
} GameState;
// 初始化游戏状态
GameState gameState = PLAYING;
void setup() // 初始化
void draw(float stateTime)// 界面绘图
void mousePress()鼠标处理事件
void keyDown() // 键盘事件处理函数
void keyup()// 键盘事件处理函数
void keydown()// 键盘事件处理函数
void close()// 程序结束时回收游戏资源
五、 算法设计
六、 程序运行结果
图片找不到了
七、 总结
1、工作时间
第一次课和一个星期天
背景图片、车子、轮子正确坐标的现实。
小车移动,车轮转动,键盘减速、加速控制、控制、通过空格键控制停车,启动。
第二次课和一个星期六
小车启动位置调整 ,小车背景和风景速度等调整,完成附加功能,进行系统调试。
2、分工情况
独自完成代码编写,以及撰写报告等工作。
3、心得体会
通过使用SDL2开发游戏,我深刻理解了游戏开发的复杂性和技术要求。SDL2提供了丰富的图形和输入处理功能,但在实际开发中,我们需要考虑到游戏的性能优化、资源管理和用户交互等方面。同时,我也遇到了一些困难和问题,但通过不断的尝试和学习,我逐渐掌握了解决问题的方法。总的来说,使用SDL2开发游戏是一次很有收获的经历,我对游戏开发产生了更大的兴趣。
附页(源代码附加注释)
请勿直接抄以免产生不可预知后果!!!!!
#include "sdl2game.h"
#include <math.h>
#include <time.h>
Image *myroad1;
Image *scre;
Image *myroad2;
Image *car;
Image *wheel1;
Image *wheel2;
Image *obstacle;
int right=0;
int rights=640;
int angel=20;
int carx=-200;
int cary=78;
int flag=0;
Bool changepicture=FALSE;
Bool fast=FALSE;
Bool slow=FALSE;
Bool stop=FALSE;
Bool down=FALSE;
Bool up=FALSE;
Sound *horn;
Sound *eng;
// 定义障碍物的位置和尺寸
int obstacleX = 640;
int obstacleY = 200;
int obstacleWidth = 1;
int obstacleHeight = 1;
// 定义游戏状态变量
typedef enum {
PLAYING,
GAME_OVER
} GameState;
// 初始化游戏状态
GameState gameState = PLAYING;
// 初始化
void setup()
{
size(640,200);
title("my idiot car");
myroad1=loadimage("image/myroad1.png");
myroad2=loadimage("image/myroad2.png");
car=loadimage("image/car.png");
obstacle=loadimage("image/obstacle.png");
wheel1=loadimage("image/wheel2.png");
wheel2=loadimage("image/wheel2.png");
horn=loadsound("sound/horn.wav");
eng=loadsound("sound/enginestart.mp3");
}
int main(int argc, char* args[])
{
SDL_Init(SDL_INIT_EVERYTHING);
IMG_Init(0);
Mix_Init(0);
TTF_Init();
_window = SDL_CreateWindow("MyTest", SDL_WINDOWPOS_UNDEFINED,SDL_WINDOWPOS_UNDEFINED,
_screenW, _screenH, SDL_WINDOW_OPENGL|SDL_WINDOW_HIDDEN);
_canvas = SDL_CreateRenderer(_window, -1, SDL_RENDERER_ACCELERATED|SDL_RENDERER_PRESENTVSYNC);
_font = TTF_OpenFont(_fontName, _fontSize);
Mix_OpenAudio( 44100, MIX_DEFAULT_FORMAT, 2, 2048 );
int i;
for (i=0; i<MAX_ANIM; i++)
{
_animations[i] = NULL;
}
SDL_ShowWindow(_window);
float deltaTime, delta;
unsigned int tick0, tick1;
SDL_Event event;
Bool quit = FALSE;
tick0 = SDL_GetTicks();
setup();
while( !quit )
{
if ( SDL_PollEvent( &event ) )
{
switch (event.type)
{
case SDL_QUIT :
quit = TRUE;
break;
case SDL_KEYDOWN :
key = event.key.keysym.sym;
keyPressed = TRUE;
keyDown();
if ( key == SDLK_ESCAPE )
{
quit = TRUE;
}
break;
case SDL_KEYUP:
keyPressed = FALSE;
keyUp();
break;
case SDL_MOUSEBUTTONDOWN :
mouseButton = event.button.button;
pmouseX = mouseX;
pmouseY = mouseY;
mouseX = event.button.x;
mouseY = event.button.y;
mousePressed = TRUE;
mouseDragged = FALSE;
mousePress();
break;
case SDL_MOUSEMOTION :
pmouseX = mouseX;
pmouseY = mouseY;
mouseX = event.motion.x;
mouseY = event.motion.y;
if (event.motion.state & SDL_BUTTON_LMASK || event.motion.state & SDL_BUTTON_RMASK)
{
mouseDragged = TRUE;
}
mouseMove();
break;
case SDL_MOUSEBUTTONUP :
pmouseX = mouseX;
pmouseY = mouseY;
mouseX = event.button.x;
mouseY = event.button.y;
mousePressed = FALSE;
mouseDragged = FALSE;
mouseRelease();
break;
default:
break;
}
}
internalRender(_duration);
tick1 = SDL_GetTicks();
delta = tick1 - tick0;
tick0 = SDL_GetTicks();
deltaTime = delta / 1000.0;
if (delta < 16.7)
{
SDL_Delay(17 - delta);
deltaTime = 0.016667;
}
_duration = _duration + deltaTime;
float fps = 1.0 / deltaTime + 0.5;
char info[20];
sprintf(info, "帧率FPS:%d", (int)fps);
SDL_RenderPresent(_canvas);
}
close();
if (_bgColor != NULL ) SDL_DestroyTexture(_bgColor);
if (_bgImage != NULL ) SDL_DestroyTexture(_bgImage);
if (_cursor != NULL) SDL_FreeCursor(_cursor);
if (_font != NULL) TTF_CloseFont( _font );
if (_bgMusic != NULL )
{
Mix_HaltMusic();
Mix_FreeMusic( _bgMusic );
}
for (i=0; i<_animCount; i++)
{
Animation* anim = _animations[i];
unloadanimation(anim);
_animations[i] = NULL;
}
SDL_DestroyRenderer(_canvas);
SDL_DestroyWindow(_window);
IMG_Quit();
Mix_Quit();
TTF_Quit();
SDL_Quit();
return 0;
}
附页(源代码附加注释)
#include "sdl2game.h"
#include <math.h>
#include <time.h>
Image *myroad1;
Image *scre;
Image *myroad2;
Image *car;
Image *wheel1;
Image *wheel2;
Image *obstacle;
int right=0;
int rights=640;
int angel=20;
int carx=-200;
int cary=78;
int flag=0;
Bool changepicture=FALSE;
Bool fast=FALSE;
Bool slow=FALSE;
Bool stop=FALSE;
Bool down=FALSE;
Bool up=FALSE;
Sound *horn;
Sound *eng;
// 定义障碍物的位置和尺寸
int obstacleX = 640;
int obstacleY = 200;
int obstacleWidth = 1;
int obstacleHeight = 1;
// 定义游戏状态变量
typedef enum {
PLAYING,
GAME_OVER
} GameState;
// 初始化游戏状态
GameState gameState = PLAYING;
// 初始化
void setup()
{
size(640,200);
title("my idiot car");
myroad1=loadimage("image/myroad1.png");
myroad2=loadimage("image/myroad2.png");
car=loadimage("image/car.png");
obstacle=loadimage("image/obstacle.png");
wheel1=loadimage("image/wheel2.png");
wheel2=loadimage("image/wheel2.png");
horn=loadsound("sound/horn.wav");
eng=loadsound("sound/enginestart.mp3");
}
// 碰撞检测函数
Bool checkCollision(int carX, int carY, int carWidth, int carHeight)
{
// 检测矩形碰撞
if (carX < obstacleX + obstacleWidth+right&&
carX + carWidth > obstacleX+right &&
carY < obstacleY + obstacleHeight &&
carY + carHeight > obstacleY)
{
return TRUE; // 发生碰撞
}
return FALSE; // 未发生碰撞
}
// 界面绘图
void draw(float stateTime)
{
// 获取车辆的位置和尺寸
int carX = carx;
int carY = cary;
int carWidth = 10;
int carHeight = 10;
srand(time(0));
if(right<=-640)
{
right=0;
}
else if(rights<=-1920)
{
rights=640;
}
else
{
if(stop==TRUE)
{
right=right-0;
rights=rights-0;
angel=(angel+0)%360;
}
else
{
if(carx>=150)//开始运行时,对小车的控制
{
carx=carx+0;
if(up==TRUE&&cary>78)
{
cary-=2;
}
if(down==TRUE&&cary<118)
{
cary+=2;
}
if(slow==FALSE)
{
right=right-4;
rights=rights-4;
angel=(angel+5)%360;
}
if(slow==TRUE)
{
right=right+10;
rights=rights+10;
angel=(angel-20)%360;
if(right>0)
right=-630;
else if(rights>630)
rights=-1270;
}
if(fast==FALSE)
{
right=right-4;
rights=rights-4;
angel=(angel+5)%360;
}
if(fast==TRUE)
{
right=right-10;
rights=rights-10;
angel=(angel+20)%360;
}
}
else //程序启动开始时
{
carx=carx+2;
angel=(angel+5)%360;
}
}
}
if(right==0) //障碍物
{
obstacleY=(rand()%50+100);
}
if (checkCollision(carX, carY, carWidth, carHeight))
{
gameState = GAME_OVER;
}
// 根据游戏状态执行相应的操作
if (gameState == PLAYING)
{
// 继续进行游戏
// printf("go");
// 绘制游戏场景和其他元素
}
else if (gameState == GAME_OVER)
{
printf("game over");
gameState == PLAYING;
}
image(myroad1,right,0);
image(myroad2,rights,0);
image(car,carx,cary);
image(wheel2,carx+29,cary+50);
image(wheel2,carx+167,cary+50);
imagerotated(wheel2,carx+167,cary+50,angel); //前轮
imagerotated(wheel2,carx+29,cary+50,angel); //后轮
image(obstacle,obstacleX+right,obstacleY);
color(0,0,200);
fillcircle(100,50,30);
float cx,cy;
int i;
color(255,255,255);
for(i=1; i<=12; i++)
{
cx=100+25*sin(30*i*1.0/180*3.14);
cy=50-25*cos(30*i*1.0/180*3.14);
if(i%3==0)
circle(cx,cy,5);
else
circle(cx,cy,3);
}
time_t now;
struct tm *tm_now;
int hour,minute,sec;
float hx,hy;
float mx,my;
float sx,sy;
time(&now);
tm_now=localtime(&now);
hour=tm_now->tm_hour;
minute=tm_now->tm_min;
sec=tm_now->tm_sec;
hx=100+15*sin(((hour+(minute*1.0/60))*30*1.0)/180*3.14);
hy=50-15*cos(((hour+(minute*1.0/60))*30*1.0)/180*3.14);
line(100,50,hx,hy);
mx=100+20*sin(minute*6*1.0/180*3.14);
my=50-20*cos(minute*6*1.0/180*3.14);
line(100,50,mx,my);
sx=100+25*sin(sec*6*1.0/180*3.14);
sy=50-25*cos(sec*6*1.0/180*3.14);
line(100,50,sx,sy);
}
// 鼠标事件处理
void mousePress()
{
playsound(horn);
}
void mouseMove()
{
}
void mouseRelease()
{
}