温州大学大一上,实验作业
#include <easyx.h>
#include <conio.h>
#include <graphics.h>
#include <windows.h>
#include <mmsystem.h>//多媒体设备接口
#pragma comment(lib, "winmm.lib")//加载多媒体设备接口库文件
#include <ctime>
#include<cmath>
#include <cstdlib>
#include <graphics.h>
#include <iostream>
#include<deque>
#include<utility>
#define WIDTH 1000
#define HEIGHT 800
// 记录水果坐标
double fruits_x[10], fruits_y[10];
//绘制刀刃痕迹
std::deque<std::pair<int, int> > mouth_xy;
//代表此时的界面
int op;
// 切水果的得分
int sum = 0, best = 0;
// 定义时间片的起始与终止
clock_t start, end, begin1, end1;
double times, times1;
// 一个初始的竖直速度
double vx1 = -1, vy1 = -1, vy[10]; // 水果的水平和竖直运动速度
double time_tick1 = 1; // 水果移动的时间量
double g = 0.0001;
//0是香蕉 1是苹果 2是芒果 4是西瓜 5是草莓
// 水果出现
int Fruit_1flag0 = 1; //香蕉banana的出现
int Fruit_1flag1 = 1; //苹果apple的出现
int Fruit_1flag2 = 1; //芒果peach的出现
int Fruit_1flag3 = 1; //西瓜sandia的出现
int Fruit_1flag4 = 1; //草莓basaha的出现
IMAGE img_mp; //菜单图片
IMAGE img_help; //帮助图
IMAGE img_about; //关于图
IMAGE img_bk; //背景图
IMAGE img_apple, img_apple_mask; // 苹果图片和遮罩图
IMAGE img_banana, img_banana_mask; // 香蕉图片和遮罩图
IMAGE img_melon, img_melon_mask; // 西瓜图片和遮罩图
IMAGE img_peach, img_peach_mask; // 桃子图片和遮罩图
IMAGE img_berry, img_berry_mask; // 草莓图片和遮罩图
//图片加载准备
void startUp() {
srand((unsigned int)time(NULL));
// 各项数据初始化
// 创建绘图界面和加载图片
initgraph(WIDTH, HEIGHT);
BeginBatchDraw();
loadimage(&img_help, _T("E:\\Visual Stdio_work\\Project1\\Project1\\resource\\help_background.jpg"), WIDTH, HEIGHT);
loadimage(&img_about, _T("E:\\Visual Stdio_work\\Project1\\Project1\\resource\\about_background.jpg"), WIDTH, HEIGHT);
loadimage(&img_mp, _T("E:\\Visual Stdio_work\\Project1\\Project1\\resource\\startbackground.jpg"), WIDTH, HEIGHT);
loadimage(&img_bk, _T("E:\\Visual Stdio_work\\Project1\\Project1\\resource\\background.jpg"), WIDTH + 20, HEIGHT + 20);
// 所有水果的图片与掩码图
loadimage(&img_apple, _T("E:\\Visual Stdio_work\\Project1\\Project1\\resource\\apple.bmp"));
loadimage(&img_apple_mask, _T("E:\\Visual Stdio_work\\Project1\\Project1\\resource\\apple_mask.bmp"));
loadimage(&img_banana, _T("E:\\Visual Stdio_work\\Project1\\Project1\\resource\\banana.bmp"));
loadimage(&img_banana_mask, _T("E:\\Visual Stdio_work\\Project1\\Project1\\resource\\banana_mask.bmp"));
loadimage(&img_melon, _T("E:\\Visual Stdio_work\\Project1\\Project1\\resource\\watermelon.bmp"));
loadimage(&img_melon_mask, _T("E:\\Visual Stdio_work\\Project1\\Project1\\resource\\watermelon_mask.bmp"));
loadimage(&img_peach, _T("E:\\Visual Stdio_work\\Project1\\Project1\\resource\\peach.bmp"));
loadimage(&img_peach_mask, _T("E:\\Visual Stdio_work\\Project1\\Project1\\resource\\peach_mask.bmp"));
loadimage(&img_berry, _T("E:\\Visual Stdio_work\\Project1\\Project1\\resource\\strawberry.bmp"));
loadimage(&img_berry_mask, _T("E:\\Visual Stdio_work\\Project1\\Project1\\resource\\strawberry_mask.bmp"));
}
//配置_音乐
void play_music(const char* music)
{
static int i = 0;
char cmd[100] = { 0 };
//打开音乐 alias 取别名
//字符串的拼接
sprintf_s(cmd, "open %s alias bgm%d", music, i);
mciSendString(cmd, NULL, 0, NULL);
//播放音乐 repeat 重复播放
sprintf_s(cmd, "play bgm%d", i);
mciSendString(cmd, NULL, 0, NULL);
i++;
}
//绘制发射的水果的位置
inline void drawFruitImage(int index, IMAGE* pmask, IMAGE* psource)
{
if (fruits_y[index] < HEIGHT && fruits_y[index] > -50)
{
putimage(fruits_x[index], fruits_y[index], pmask, SRCAND);
putimage(fruits_x[index], fruits_y[index], psource, SRCPAINT);
}
}
//读入最大分数
void best_rfp_score()
{
FILE* fp;
fopen_s(&fp, "resource/best_score.txt", "r");
char ss[50];
fgets(ss, 50, fp);
best = atoi(ss);
fclose(fp);
}
//写入最大分数
void best_wfp_score()
{
char ss[50];
if (sum > best)
{
best = sum;
FILE* fp;
fopen_s(&fp, "resource/best_score.txt", "w");
sprintf_s(ss, "%d", best);
fputs(ss, fp);
fclose(fp);
}
}
//加载分数 and 时间
void score()
{
setbkmode(TRANSPARENT);
int x = 400, y = 10, w = 250, h = 42;
char score[50], best_score[50], times_wast[50];
//把分数, best, times_wast转化成字符串
sprintf_s(score, "分数:%d", sum);
sprintf_s(best_score, "best: %d", best);
sprintf_s(times_wast, "%d:%d", (int)(60 - times1 / 100), (100 - (int)times1 % 100));
//当前的分数
settextcolor(BLACK);
setfillcolor(RGB(180, 200, 0));
int hspace = (w - textwidth(score) >> 1);
int vspace = (h - textheight(score) >> 1);
settextstyle(25, 25, _T(score));//设置字号、字体
fillrectangle(x, y, x + w, y + h);
outtextxy(x + hspace, y + vspace, score);
//最大分数
x = 750;
settextcolor(BROWN);
setfillcolor(RGB(180, 230, 230));
hspace = (w - textwidth(best_score) >> 1);
vspace = (h - textheight(best_score) >> 1);
fillrectangle(x, y, x + w, y + h);
outtextxy(x + hspace, y + vspace, best_score);
//剩余的时间
x = 50;
settextcolor(RED);
setfillcolor(RGB(180, 200, 230));
hspace = (w - textwidth(times_wast) >> 1);
vspace = (h - textheight(times_wast) >> 1);
fillrectangle(x, y, x + w, y + h);
outtextxy(x + hspace, y + vspace, times_wast);
}
//加载游戏中的画面
void show()
{
// 之所以每次都绘制背景图,是为了挡住前面的水果图
putimage(0, 0, &img_bk);
score();
// 以下显示水果,如果可以显示
//向左飞出的香蕉
if (Fruit_1flag0)
drawFruitImage(0, &img_banana_mask, &img_banana);
//向左飞出的苹果
if (Fruit_1flag1)
drawFruitImage(1, &img_apple_mask, &img_apple);
//向左飞出的芒果
if (Fruit_1flag2)
drawFruitImage(2, &img_peach_mask, &img_peach);
//向左飞出的西瓜
if (Fruit_1flag3)
drawFruitImage(3, &img_melon_mask, &img_melon);
//向左飞出的草莓
if (Fruit_1flag4)
drawFruitImage(4, &img_berry_mask, &img_berry);
Sleep(10);
FlushBatchDraw();
for(register int i = 0; i < 5; i ++)
if(fruits_y[i] > HEIGHT + 300)
if (fruits_y[0] > HEIGHT + 300)
Fruit_1flag0 = 0;
if (fruits_y[1] > HEIGHT + 300)
Fruit_1flag1 = 0;
if (fruits_y[2] > HEIGHT + 300)
Fruit_1flag2 = 0;
if (fruits_y[3] > HEIGHT + 300)
Fruit_1flag3 = 0;
if (fruits_y[4] > HEIGHT + 300)
Fruit_1flag4 = 0;
}
//加载刀刃和使水果消失
void updateWithInput(int &ans) {
ExMessage msg = { 0 };
if (peekmessage(&msg))
{
// 鼠标点击
if (msg.message == WM_MOUSEMOVE) {
//0是香蕉 126 50
//1是苹果 66 66
//2是芒果 62 59
//3是西瓜 98 85
//4是草莓 68 72
//实现鼠标划到就消失
//向左消失的水果
if (((msg.x - fruits_x[0] - 25) * (msg.x - fruits_x[0] - 25) + (msg.y - fruits_y[0] - 25) * (msg.y - fruits_y[0] - 25)) <= 3600)
{
if (Fruit_1flag0)
{
printf("切到了香蕉\n"), sum++;
}
Fruit_1flag0 = 0;
}
if (((msg.x - fruits_x[1] - 33) * (msg.x - fruits_x[1] - 33) + (msg.y - fruits_y[1] - 33) * (msg.y - fruits_y[1] - 33)) <= 3600)
{
if (Fruit_1flag1)
{
printf("切到了苹果\n"), sum++;
}
Fruit_1flag1 = 0;
}
if (((msg.x - fruits_x[2] - 35) * (msg.x - fruits_x[2] - 35) + (msg.y - fruits_y[2] - 35) * (msg.y - fruits_y[2] - 35)) <= 3600)
{
if (Fruit_1flag2)
{
printf("切到了芒果\n"), sum++;
}
Fruit_1flag2 = 0;
}
if (((msg.x - fruits_x[3] - 45) * (msg.x - fruits_x[3] - 45) + (msg.y - fruits_y[3] - 45) * (msg.y - fruits_y[3] - 45)) <= 3600)
{
if (Fruit_1flag3)
{
printf("切到了西瓜\n"), sum++;
}
Fruit_1flag3 = 0;
}
if (((msg.x - fruits_x[4] - 35) * (msg.x - fruits_x[4] - 35) + (msg.y - fruits_y[4] - 35) * (msg.y - fruits_y[4] - 35)) <= 3600)
{
if (Fruit_1flag4)
{
printf("切到了草莓\n"), sum++;
}
Fruit_1flag4 = 0;
}
//实现刀刃的代码
std::pair<int, int> tem;
tem.first = msg.x, tem.second = msg.y;
if (ans < 8)
{
mouth_xy.push_back(tem);
}
ans ++;
if (ans >= 8)
{
mouth_xy.push_back(tem);
mouth_xy.pop_front();
for (int i = 1; i < mouth_xy.size(); i++)
{
setlinecolor(WHITE);
setlinestyle(PS_SOLID, i);
line(mouth_xy[i].first, mouth_xy[i].second, mouth_xy[i - 1].first, mouth_xy[i - 1].second);
}
}
FlushBatchDraw();
}
else if (msg.message == WM_KEYDOWN)
{
printf("你按下了一个键\n");
switch (msg.vkcode)
{
case VK_ESCAPE:
op = 4;
printf("你按了Esc键\n");
break;
}
}
msg.message = 0;
}
}
//向左的水果的种类
void fruit_type_1()
{
int flag;
for (register int i = 0; i < 5; i++)
{
flag = rand() % 5;
switch (flag)
{
case 0:
Fruit_1flag0 = 1; //香蕉的出现
break;
case 1:
Fruit_1flag1 = 1; //苹果的出现
break;
case 2:
Fruit_1flag2 = 1; //芒果的出现
break;
case 3:
Fruit_1flag3 = 1; //西瓜的出现
break;
case 4:
Fruit_1flag4 = 1; //草莓的出现
break;
}
}
}
//向左水果初始的坐标
void fruit_start_xy_1()
{
// 给所有向左的图片定义一个初始位置
for (register int i = 0; i < 5; ++i)
{
fruits_x[i] = 800 - rand() % 600; // 中间部分
fruits_y[i] = HEIGHT + 100 + (rand() % 200); // 都不出现
vy[i] = -(30 + rand() % 15) / 100.0;
}
vx1 = pow(-1, rand() % 2) * (10 + rand() % 10) / 10.0;
}
//检查水果是否完毕
bool check_fruit1()
{
if (Fruit_1flag0) return false;
if (Fruit_1flag1) return false;
if (Fruit_1flag2) return false;
if (Fruit_1flag3) return false;
if (Fruit_1flag4) return false;
return true;
}
//发射水果
void updateWithoutInput()
{
if (check_fruit1())//通过时间判断,向右发射完毕
{
//开始发射向左的水果
fruit_type_1();
fruit_start_xy_1();
time_tick1 = 1;
}
for (register int i = 0; i < 5; i++)
{
fruits_x[i] += vx1; // 向左发射
fruits_y[i] += 1.1 * vy[i] * time_tick1;
}
for(register int i = 0; i < 5; i ++)
vy[i] += g * time_tick1;
time_tick1 ++;
}
//加载_菜单
void start_bk()
{
//绘制菜单背景
putimage(0, 0, &img_mp);
}
//加载_按键
void start_button(int x1, int y1)
{
//绘制按钮
int x, y, w, h, hspace, vspace;
setbkmode(TRANSPARENT);
settextcolor(BLACK);
//开始键
x = 580, y = 200, w = 400, h = 60;
if (x1 >= 580 && x1 <= 980 && y1 >= 200 && y1 <= 260)
{
setfillcolor(RGB(187, 198, 241));//鼠标悬停颜色
settextstyle(60, 50, _T("开始游戏"));//设置字号、字体
}
else
{
setfillcolor(RGB(210, 111, 130));//正常按钮颜色
settextstyle(50, 40, _T("开始游戏"));//设置字号、字体
}
fillrectangle(x, y, x + w, y + h);
hspace = (w - textwidth("开始游戏") >> 1);
vspace = (h - textheight("开始游戏")>> 1);
outtextxy(x + hspace, y + vspace, "开始游戏");
//帮住键
y = 300;
if (x1 >= 580 && x1 <= 980 && y1 >= 300 && y1 <= 360)
{
setfillcolor(RGB(187, 198, 241));
settextstyle(60, 50, _T("开始游戏"));//设置字号、字体
}
else
{
setfillcolor(RGB(210, 111, 130));//正常按钮颜色
settextstyle(50, 40, _T("开始游戏"));//设置字号、字体
}
fillrectangle(x, y, x + w, y + h);
hspace = (w - textwidth("帮 助") >> 1);
vspace = (h - textheight("帮 助") >> 1);
outtextxy(x + hspace, y + vspace, "帮 助");
//关于键
y = 400;
if (x1 >= 580 && x1 <= 980 && y1 >= 400 && y1 <= 460)
{
setfillcolor(RGB(187, 198, 241));
settextstyle(60, 50, _T("开始游戏"));//设置字号、字体
}
else
{
setfillcolor(RGB(210, 111, 130));//正常按钮颜色
settextstyle(50, 40, _T("开始游戏"));//设置字号、字体
}
fillrectangle(x, y, x + w, y + h);
hspace = (w - textwidth("关 于") >> 1);
vspace = (h - textheight("关 于") >> 1);
outtextxy(x + hspace, y + vspace, "关 于");
//退出键
y = 500;
if (x1 >= 580 && x1 <= 980 && y1 >= 500 && y1 <= 560)
{
setfillcolor(RGB(187, 198, 241));
settextstyle(60, 50, _T("开始游戏"));//设置字号、字体
}
else
{
setfillcolor(RGB(210, 111, 130));//正常按钮颜色
settextstyle(50, 40, _T("开始游戏"));//设置字号、字体
}
fillrectangle(x, y, x + w, y + h);
hspace = (w - textwidth("返回菜单") >> 1);
vspace = (h - textheight("返回菜单") >> 1);
outtextxy(x + hspace, y + vspace, "返回菜单");
}
//进行_跳转
int startOp()
{
int x = 0, y = 0;
//initgraph(WIDTH, HEIGHT, EX_SHOWCONSOLE);
//不断的处理消息
while (true)
{
//定义消息结构变量
ExMessage msg = { 0 };
//双缓冲
BeginBatchDraw();
//绘制菜单背景图和按钮
start_bk();
start_button(x, y);
//判断具体是什么消息
if (peekmessage(&msg))
{
//鼠标左键
if (msg.message == WM_LBUTTONDOWN)
{
printf("左键按下了\n");
if (msg.x >= 580 && msg.x <= 980 && msg.y >= 200 && msg.y <= 260)
{
//开始游戏
std::cout << "开始游戏\n";
return 1;
}
else if(msg.x >= 580 && msg.x <= 980 && msg.y >= 300 && msg.y <= 360)
{
//帮助
std::cout << "帮助\n";
return 2;
}
else if (msg.x >= 580 && msg.x <= 980 && msg.y >= 400 && msg.y <= 460)
{
//关于
std::cout << "关于\n";
return 3;
}
else if (msg.x >= 580 && msg.x <= 980 && msg.y >= 500 && msg.y <= 560)
{
//返回菜单
std::cout << "返回菜单\n";
return 4;
}
}
//鼠标移动
if (msg.message == WM_MOUSEMOVE)
{
x = msg.x, y = msg.y;
//printf("move_now_pos(%d %d)\n", msg.x, msg.y);
}
}
EndBatchDraw();
}
}
//跳转_帮助
int helpOp()
{
int x = 0, y = 0;
//initgraph(WIDTH, HEIGHT, EX_SHOWCONSOLE);
//不断的处理消息
while (true)
{
//定义消息结构变量
ExMessage msg = { 0 };
//双缓冲
BeginBatchDraw();
//绘制帮助背景图和按钮
putimage(0, 0, &img_help);
start_button(x, y);
//判断具体是什么消息
if (peekmessage(&msg))
{
//鼠标左键
if (msg.message == WM_LBUTTONDOWN)
{
if (msg.x >= 580 && msg.x <= 980 && msg.y >= 200 && msg.y <= 260)
{
//开始游戏
std::cout << "开始游戏\n";
return 1;
}
else if (msg.x >= 580 && msg.x <= 980 && msg.y >= 300 && msg.y <= 360)
{
//帮助
std::cout << "帮助\n";
return 2;
}
else if (msg.x >= 580 && msg.x <= 980 && msg.y >= 400 && msg.y <= 460)
{
//关于
std::cout << "关于\n";
return 3;
}
else if (msg.x >= 580 && msg.x <= 980 && msg.y >= 500 && msg.y <= 560)
{
//返回菜单
std::cout << "返回菜单\n";
return 4;
}
}
//鼠标移动
if (msg.message == WM_MOUSEMOVE)
{
x = msg.x, y = msg.y;
//printf("move_now_pos(%d %d)\n", msg.x, msg.y);
}
}
EndBatchDraw();
}
}
//跳转_关于
int aboutOp()
{
int x = 0, y = 0;
//initgraph(WIDTH, HEIGHT, EX_SHOWCONSOLE);
//不断的处理消息
while (true)
{
//定义消息结构变量
ExMessage msg = { 0 };
//双缓冲
BeginBatchDraw();
//绘制菜单背景图和按钮
putimage(0, 0, &img_about);
start_button(x, y);
//判断具体是什么消息
if (peekmessage(&msg))
{
//鼠标左键
if (msg.message == WM_LBUTTONDOWN)
{
if (msg.x >= 580 && msg.x <= 980 && msg.y >= 200 && msg.y <= 260)
{
//开始游戏
std::cout << "开始游戏\n";
return 1;
}
else if (msg.x >= 580 && msg.x <= 980 && msg.y >= 300 && msg.y <= 360)
{
//帮助
std::cout << "帮助\n";
return 2;
}
else if (msg.x >= 580 && msg.x <= 980 && msg.y >= 400 && msg.y <= 460)
{
//关于
std::cout << "关于\n";
return 3;
}
else if (msg.x >= 580 && msg.x <= 980 && msg.y >= 500 && msg.y <= 560)
{
//返回菜单
std::cout << "返回菜单\n";
return 4;
}
}
//鼠标移动
if (msg.message == WM_MOUSEMOVE)
{
x = msg.x, y = msg.y;
//printf("move_now_pos(%d %d)\n", msg.x, msg.y);
}
}
EndBatchDraw();
}
}
//游戏_结束
void gameOver() {
EndBatchDraw();
_getch();
closegraph();
}
//预处理水果
void init_fruit()
{
fruit_type_1();
fruit_start_xy_1();
sum = begin1 = 0;
start = clock();
play_music("resource/back_bgm.wav");
best_rfp_score();
}
//统计时间
void times_cost()
{
if (!begin1) begin1 = clock();
end1 = clock();
times1 = 100 * double(end1 - begin1) / CLOCKS_PER_SEC;
if (times1 > 6000) op = 4;
}
int main()
{
startUp();
init_fruit();
//play_back_music("resource/back_bgm.wav");
int ans = 0;
op = startOp();
while (true)
{
if (op == 1)
{
end = clock();
times = end - start;
//游戏中
updateWithoutInput();
show();
updateWithInput(ans);
best_wfp_score();
times_cost();
}
else if (op == 2)
{
ans = sum = begin1 = 0;
mouth_xy.clear();
//帮助
op = helpOp();
}
else if (op == 3)
{
ans = sum = begin1 = 0;
mouth_xy.clear();
//关于
op = aboutOp();
}
else if (op == 4)
{
ans = sum = begin1 = 0;
mouth_xy.clear();
//菜单
op = startOp();
}
end = clock();
if ((int)(double(end - start) / CLOCKS_PER_SEC * 10) % 237 == 0)
play_music("resource/back_bgm.wav");
}
//游戏_结束
gameOver();
return 0;
}