目录
游戏简介
屏幕中不断下落字母,判断按下这个字母的按键,得分;字母掉下去,扣分。
上面这句话中,我们要给蓝色背景的字定义一个结构体,然后一步步实现红色字的内容。
代码思路
1. 字母结构体
2. 初始化字母
3. 字母下落(到底失分)
4. 绘制屏幕
5. 判断按键(得分)
6. 音乐、背景(可加可不加)
准备素材
背景图:
(偷偷说一件事:我的这些背景图,都是在 Scratch 上截的)
音效也是在 Scratch 上导出的……
开始编写
1 预编译
#include <stdio.h>
#include <graphics.h>
#include <conio.h>
#include <time.h>
#include <mmsystem.h>
#pragma comment(lib, "winmm.lib") // 音乐
#define WIDTH 640
#define HEIGHT 480
#define MAX_LETTER 10
#define SPEED 2
2 字母结构体
x x坐标
y y坐标
speed 下落速度
ch 字母
struct Letter
{
int x;
int y;
char ch;
};
3 初始化字母
定义宏 MAX_LETTER 表示字母的数量。
定义 letter[MAX_LETTER] 表示所有字母的一维数组。
Letter letter[MAX_LETTER];
x坐标:25 ~ 615 的随机数
y坐标:-480 ~ 0 的随机数
字母:利用 ASCII码 取 A ~ Z 的随机数
// 初始化字母
void SetLetter()
{
for (int i = 0; i < MAX_LETTER; i++)
{
letter[i].x = rand() % (WIDTH - 50) + 25;
letter[i].y = rand() % HEIGHT - HEIGHT;
letter[i].ch = rand() % 26 + 'A';
}
}
4 字母下落
不断下落
只要增加每个字母的y坐标就行了。
for (int i = 0; i < MAX_LETTER; i++)
{
letter[i].y += SPEED;
}
掉到底下
判断字母的y坐标,如果大于屏幕高度,扣分,并且重新初始化这个字母。
if (letter[i].y >= HEIGHT)
{
score--;
letter[i].x = rand() % (WIDTH - 50) + 25;
letter[i].y = rand() % HEIGHT - HEIGHT;
letter[i].ch = rand() % 26 + 'A';
}
MoveLetter() 函数
// 移动字母
void MoveLetter()
{
for (int i = 0; i < MAX_LETTER; i++)
{
letter[i].y += SPEED;
if (letter[i].y >= HEIGHT)
{
score--;
letter[i].x = rand() % (WIDTH - 50) + 25;
letter[i].y = rand() % HEIGHT - HEIGHT;
letter[i].ch = rand() % 26 + 'A';
}
}
}
5 绘制屏幕
字母
setbkmode 函数设置字母背景的样子,这里用 TRANSPARENT 设为透明。
for (int i = 0; i < MAX_LETTER; i++)
{
settextstyle(50, 20, "HandelGothic BT");
setbkmode(TRANSPARENT);
outtextxy(letter[i].x, letter[i].y, letter[i].ch);
}
分数
sprintf_s 函数:格式化输出到一个字符数组里。
char text[20];
sprintf_s(text, "Score: %d", score);
settextstyle(50, 20, "Arial");
outtextxy(20, 20, text);
Draw() 函数
// 绘制屏幕
void Draw()
{
putimage(0, 0, &bk_img);
for (int i = 0; i < MAX_LETTER; i++)
{
settextstyle(50, 20, "HandelGothic BT");
setbkmode(TRANSPARENT);
outtextxy(letter[i].x, letter[i].y, letter[i].ch);
}
char text[20];
sprintf_s(text, "Score: %d", score);
settextstyle(50, 20, "Arial");
outtextxy(20, 20, text);
}
6 判断按键
// 用户输入
void GetKey()
{
if (_kbhit())
{
char input = _getch();
input = input - 'a' + 'A';
for (int i = 0; i < MAX_LETTER; i++)
{
if (input == letter[i].ch)
{
score++;
letter[i].x = rand() % (WIDTH - 50) + 25;
letter[i].y = rand() % HEIGHT - HEIGHT;
letter[i].ch = rand() % 26 + 'A';
}
}
}
}
7 音乐、背景
音乐
Playsound 函数:
BOOL PlaySound(LPCSTR pszSound, HMODULE hmod,DWORD fdwSound);
pszSound : 音乐文件路径,只能是 .wav 类型
hmod : 一般直接写 NULL ,不用管
fdwSound : 声音播放模式 ,常用:
SND_ASYNC 异步播放
SND_LOOP 循环播放
SND_NOSTOP 不打断原来的声音
在开始时 :PlaySound(".\\Bgm.wav", NULL, SND_ASYNC | SND_LOOP);
得分时:PlaySound(".\\Get.wav", NULL, SND_ASYNC | SND_NOSTOP);
按下空格 关闭 / 打开 音乐
if (input == ' ')
{
if (isMusic)
{
PlaySound(NULL, NULL, NULL);
isMusic = false;
}
else
{
PlaySound(".\\Bgm.wav", NULL, SND_ASYNC | SND_LOOP);
isMusic = true;
}
}
背景
主函数:loadimage(&bk_img, ".\\Background.png", WIDTH, HEIGHT, true);
Draw函数:putimage(0, 0, &bk_img);
Main函数
int main()
{
initgraph(WIDTH, HEIGHT);
srand(time(NULL));
loadimage(&bk_img, ".\\Background.png", WIDTH, HEIGHT, true);
PlaySound(".\\Bgm.wav", NULL, SND_ASYNC | SND_LOOP);
SetLetter();
BeginBatchDraw();
while (true)
{
Draw();
MoveLetter();
GetKey();
FlushBatchDraw();
Sleep(10);
}
EndBatchDraw();
closegraph();
return 0;
}
效果截图
完整代码
/*
* 项目名称:打字游戏
* 开发环境:vs2022 + easyx
* 作者:轩
* 代码长度:131 行
* 完成时间:2023.1.1
* 用时:1 小时
*/
#include <stdio.h>
#include <graphics.h>
#include <conio.h>
#include <time.h>
#include <mmsystem.h>
#pragma comment(lib, "winmm.lib")
#define WIDTH 640
#define HEIGHT 480
#define MAX_LETTER 10
#define SPEED 2
struct Letter
{
int x;
int y;
char ch;
};
IMAGE bk_img;
Letter letter[MAX_LETTER];
int score = 0; // 感谢 @ m0_74294396 提出的问题
bool isMusic = true;
// 初始化字母
void SetLetter()
{
for (int i = 0; i < MAX_LETTER; i++)
{
letter[i].x = rand() % (WIDTH - 50) + 25;
letter[i].y = rand() % HEIGHT - HEIGHT;
letter[i].ch = rand() % 26 + 'A';
}
}
// 绘制屏幕
void Draw()
{
putimage(0, 0, &bk_img);
for (int i = 0; i < MAX_LETTER; i++)
{
settextstyle(50, 20, "HandelGothic BT");
setbkmode(TRANSPARENT);
outtextxy(letter[i].x, letter[i].y, letter[i].ch);
}
char text[20];
sprintf_s(text, "Score: %d", score);
settextstyle(50, 20, "Arial");
outtextxy(20, 20, text);
}
// 移动字母
void MoveLetter()
{
for (int i = 0; i < MAX_LETTER; i++)
{
letter[i].y += SPEED;
if (letter[i].y >= HEIGHT)
{
score--;
letter[i].x = rand() % (WIDTH - 50) + 25;
letter[i].y = rand() % HEIGHT - HEIGHT;
letter[i].ch = rand() % 26 + 'A';
}
}
}
// 用户输入
void GetKey()
{
if (_kbhit())
{
char input = _getch();
if (input == ' ')
{
if (isMusic)
{
PlaySound(NULL, NULL, NULL);
isMusic = false;
}
else
{
PlaySound(".\\Bgm.wav", NULL, SND_ASYNC | SND_LOOP);
isMusic = true;
}
}
input = input - 'a' + 'A';
for (int i = 0; i < MAX_LETTER; i++)
{
if (input == letter[i].ch)
{
score++;
PlaySound(".\\Get.wav", NULL, SND_ASYNC | SND_NOSTOP);
letter[i].x = rand() % (WIDTH - 50) + 25;
letter[i].y = rand() % HEIGHT - HEIGHT;
letter[i].ch = rand() % 26 + 'A';
}
}
}
}
int main()
{
initgraph(WIDTH, HEIGHT);
srand(time(NULL));
loadimage(&bk_img, ".\\Background.png", WIDTH, HEIGHT, true);
PlaySound(".\\Bgm.wav", NULL, SND_ASYNC | SND_LOOP);
SetLetter();
BeginBatchDraw();
while (true)
{
Draw();
MoveLetter();
GetKey();
FlushBatchDraw();
Sleep(10);
}
EndBatchDraw();
closegraph();
return 0;
}
感谢 @ m0_74294396 提出的问题,已修改!