前言
大一上学期学完C语言,做个打砖块小游戏练练手。
安装easyx图形库
编程环境:Visual Studio 2022
代码
首先引入相关头文件并对变量进行宏定义
#include <stdio.h>
#include <graphics.h>
#include <time.h>
#include <windows.h>
#define _CRT_SECURE_NO_WARNINGS //文件
#define WIDTH 100
#define HEIGHT 25
初始化地图(用二维数组)
int map[5][8];
void initMap()
{
for (int i = 0; i < 5; i++)
{
for (int j = 0; j < 8; j++)
{
map[i][j] = rand() % 4 + 1;
//0 待会消除砖块使用
}
}
}
画地图(调用easyx图形库中函数画砖块)
void drawMap()
{
setlinecolor(BLACK);
for (int i = 0; i < 5; i++)
{
for (int j = 0; j < 8; j++)
{
int x = WIDTH * j;
int y = HEIGHT * i;
switch(map[i][j])
{
case 0:
break;
case 1: //绿色
setfillcolor(GREEN);
fillrectangle(x, y, x + 100, y + 25); break;
case 2: //粉色
setfillcolor(RGB(199,96,199));
fillrectangle(x, y, x + 100, y + 25); break;
case 3: //浅蓝
setfillcolor(LIGHTBLUE);
fillrectangle(x, y, x + 100, y + 25); break;
case 4: //黄色
setfillcolor(RGB(255,255,128));
fillrectangle(x, y, x + 100, y + 25); break;
}
}
}
}
用结构体定义木板属性
struct Board
{
//木板的左上角坐标
int x;
int y;
//木板的宽度和高度
int w;
int h;
//木板的移动速度
int speed;
};
struct Board board = { 300,600 - 25,200,25,1};
绘制木板(同样调用easyx图形库函数)
void drawBoard()
{
setfillcolor(WHITE);
fillrectangle(board.x, board.y, board.x + board.w, board.y + board.h);
}
用获取异步键盘状态函数获取指定虚拟键的状态,进而操控木板左右移动
void KeyDown()
{
if (GetAsyncKeyState('A') || GetAsyncKeyState(VK_LEFT)&&board.x>0)
{
board.x -= board.speed;
}
if (GetAsyncKeyState('D') || GetAsyncKeyState(VK_RIGHT)&&board.x+board.w<WIDTH*8)
{
board.x += board.speed;
}
}
用结构体定义小球属性
struct Ball
{
//球的圆心
int x;
int y;
//球的半径
int r;
//移动x和y上的增量
int dx;
int dy;
};
struct Ball ball = { 400,400,15,5,-5 };
绘制小球
void drawBall()
{
setfillcolor(RED);
fillcircle(ball.x, ball.y,ball.r);
}
设置定时器控制小球移动速度
int Timer(int duration, int id)
{
static int startTime[10];
//静态变量会自动初始化为0,只会被初始化一次
//记录程序上一次结果
int endTime = clock(); //获取程序运行到当前位置的时间
if (endTime - startTime[id] > duration)
{
startTime[id] = endTime;
return 1;
}
return 0;
}
碰木板
int hitBoard()
{
if (ball.y + ball.r == board.y)
{
if (ball.x >= board.x && ball.x <= board.x + board.w)
{
return 1;
}
}
return 0;
}
碰砖块(数组中的值为0则打到砖块)
int hitBricks()
{
int j = ball.x / WIDTH;
int i = (ball.y - ball.r) / HEIGHT;
if (i < 5 && j < 8 && map[i][j] != 0)
{
map[i][j] = 0;
return 1;
}
return 0;
}
碰墙壁(调用碰木板和碰砖块的函数)
void hitWall()
{
if (ball.x + ball.r >= WIDTH * 8 || ball.x - ball.r <= 0) //撞左右墙壁
{
ball.dx = -ball.dx;
}
if (hitBoard() || hitBricks()||ball.y - ball.r <= 0) //撞上下墙壁
//if (ball.y+ball.r>=WIDTH*8)
{
ball.dy = -ball.dy;
}
ball.x += ball.dx;
ball.y += ball.dy;
}
计算得分(分数显示在控制台)
int Score()
{
int score = 0;
for (int i = 0; i < 5; i++)
{
for (int j = 0; j < 8; j++)
{
if (map[i][j] == 0)
{
score += 5;
}
}
}
return score;
}
游戏失败的情况
int die()
{
if (ball.y >=WIDTH * 8 - 15)
{
return 1;
}
return 0;
}
游戏成功结束
int gameOver()
{
for (int i = 0; i < 5; i++)
{
for (int j = 0; j < 8; j++)
{
if (map[i][j] != 0)
{
return 0;
}
}
}
return 1;
}
主函数
创建窗口
initgraph(WIDTH * 8, WIDTH * 6);
使用双缓冲地图防止闪屏
BeginBatchDraw(); //开始双缓冲绘图
别忘了结束双缓冲
EndBatchDraw(); //结束双缓冲
调整小球速度
if (Timer(20, 0))
hitWall();
游戏失败的弹窗
if (die())
{
closegraph;
printf("%d分,加油!", s);
MessageBox(NULL, TEXT("gameOver"), TEXT("gameOver"), MB_OK);
exit(0);
}
游戏成功的弹窗
if (gameOver())
{
closegraph;
printf("200分,真棒!");
MessageBox(NULL, TEXT("Congratulation!"), TEXT("gameOver"), MB_OK);
exit(0);
}
将分数存入文件(注意vs里使用文件要用安全函数或者添加宏定义)
FILE* file;
errno_t err = fopen_s(&file, "scoreinfo.txt", "a");
fprintf_s(file, "%d\n", s);
fclose(file);
主函数整体
int main()
{
srand((unsigned int)time(0));
initgraph(WIDTH * 8, WIDTH * 6);
initMap();
BeginBatchDraw(); //开始双缓冲绘图(防闪)
while (1)
{
cleardevice(); //刷新(清除屏幕)
drawMap();
drawBoard();
drawBall();
if (Timer(20, 0))
hitWall();
KeyDown();
int s = Score();
if (die())
{
closegraph;
printf("%d分,加油!", s);
MessageBox(NULL, TEXT("gameOver"), TEXT("gameOver"), MB_OK);
exit(0);
}
if (gameOver())
{
closegraph;
printf("200分,真棒!");
MessageBox(NULL, TEXT("Congratulation!"), TEXT("gameOver"), MB_OK);
exit(0);
}
FlushBatchDraw(); //显示画面
}
int s = Score();
FILE* file;
errno_t err = fopen_s(&file, "scoreinfo.txt", "a");
fprintf_s(file, "%d\n", s);
fclose(file);
EndBatchDraw(); //结束双缓冲
return 0;
}
总结
这个游戏制作的比较粗糙,我还要改进一下,加个菜单,再在碰砖块的时候加个音效。若大家有建议,欢迎提出。