界面设计

游戏界面和按钮设计

项目文件下载

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
#include <easyx.h>
#include <functional>
#include <string>
#include <vector>
#include <iostream>
#include <mmsystem.h>
#pragma comment(lib,"winmm.lib")

using namespace std;
wchar_t name[20];
int difficulty;
static int music_num = 1; // 记录音乐控制键的点击次数

// 控制音效
void controlsound()
{
++music_num;
if (music_num % 2 == 1)
{
mciSendString(L"play ./music/game_music.mp3 repeat", NULL, 0, NULL);
}
else
{
mciSendString(L"pause ./music/game_music.mp3", NULL, 0, NULL);
}
}

// 初始化数据
void init()
{

}

// 载入PNG图并去透明部分
void drawAlpha(IMAGE *picture, int picture_x, int picture_y) //x为载入图片的X坐标,y为Y坐标
{

// 变量初始化
DWORD *dst = GetImageBuffer(); // GetImageBuffer()函数,用于获取绘图设备的显存指针,EASYX自带
DWORD *draw = GetImageBuffer();
DWORD *src = GetImageBuffer(picture); //获取picture的显存指针
int picture_width = picture->getwidth(); //获取picture的宽度,EASYX自带
int picture_height = picture->getheight(); //获取picture的高度,EASYX自带
int graphWidth = getwidth(); //获取绘图区的宽度,EASYX自带
int graphHeight = getheight(); //获取绘图区的高度,EASYX自带
int dstX = 0; //在显存里像素的角标

// 实现透明贴图 公式: Cp=αp*FP+(1-αp)*BP , 贝叶斯定理来进行点颜色的概率计算
for (int iy = 0; iy < picture_height; iy++)
{
for (int ix = 0; ix < picture_width; ix++)
{
int srcX = ix + iy * picture_width; //在显存里像素的角标
int sa = ((src[srcX] & 0xff000000) >> 24); //0xAArrggbb;AA是透明度
int sr = ((src[srcX] & 0xff0000) >> 16); //获取RGB里的R
int sg = ((src[srcX] & 0xff00) >> 8); //G
int sb = src[srcX] & 0xff; //B
if (ix >= 0 && ix <= graphWidth && iy >= 0 && iy <= graphHeight && dstX <= graphWidth * graphHeight)
{
dstX = (ix + picture_x) + (iy + picture_y) * graphWidth; //在显存里像素的角标
int dr = ((dst[dstX] & 0xff0000) >> 16);
int dg = ((dst[dstX] & 0xff00) >> 8);
int db = dst[dstX] & 0xff;
draw[dstX] = ((sr * sa / 255 + dr * (255 - sa) / 255) << 16) //公式: Cp=αp*FP+(1-αp)*BP ; αp=sa/255 , FP=sr , BP=dr
| ((sg * sa / 255 + dg * (255 - sa) / 255) << 8) //αp=sa/255 , FP=sg , BP=dg
| (sb * sa / 255 + db * (255 - sa) / 255); //αp=sa/255 , FP=sb , BP=db
}
}
}
}

// 定义Button类,表示一个按钮
class Button
{
private:
int x; // 按钮左上角x坐标
int y; // 按钮左上角y坐标
int width; // 按钮宽度
int height; // 按钮高度
float scale; // 缩放比例,用于实现鼠标悬停效果
bool isMouseOver; // 表示鼠标是否在按钮上方
wstring text; // 按钮文本
function<void()> onClick; // 点击按钮触发的函数

public:

Button(int x, int y, int width, int height, const wstring &text, const function<void()> &onClick)
: x(x), y(y), width(width), height(height), text(text), onClick(onClick), scale(1.0f), isMouseOver(false)
{
}

// 检查鼠标是否在按钮上方
void checkMouseOver(int mouseX, int mouseY)
{
isMouseOver = (mouseX >= x && mouseX <= x + width && mouseY >= y && mouseY <= y + height);

if (isMouseOver) {
scale = 0.9f; // 鼠标悬停时缩放按钮
}
else {
scale = 1.0f; // 恢复按钮原始大小
}
}

// 检查鼠标点击是否在按钮内,并执行函数
bool checkClick(int mouseX, int mouseY)
{
if (mouseX >= x && mouseX <= x + width && mouseY >= y && mouseY <= y + height)
{
onClick(); // 执行按钮点击时的函数
isMouseOver = false;
scale = 1.0f;
return true;
}
return false;
}

// 绘制按钮
void draw()
{
int scaledWidth = width * scale; // 缩放后的按钮宽度
int scaledHeight = height * scale; // 缩放后的按钮高度
int scaledX = x + (width - scaledWidth) / 2; // 缩放后的按钮x坐标
int scaledY = y + (height - scaledHeight) / 2; // 缩放后的按钮y坐标

if (isMouseOver)
{
setlinecolor(RGB(0, 120, 215)); // 鼠标悬停时按钮边框颜色
setfillcolor(RGB(229, 241, 251)); // 鼠标悬停时按钮填充颜色

}
else
{
setlinecolor(RGB(255, 144, 126)); // 按钮边框颜色
setfillcolor(RGB(225, 225, 225)); // 按钮填充颜色
}

setlinestyle(PS_DASH | PS_ENDCAP_FLAT, 3); // 设置线条宽度和样式
fillroundrect(scaledX, scaledY, scaledX + scaledWidth, scaledY + scaledHeight, 50, 50); // 绘制按钮
settextcolor(GREEN); // 设置文本颜色为绿色
setbkmode(TRANSPARENT); // 设置文本背景透明
settextstyle(25 * scale, 0, _T("华文彩云")); // 设置文本大小和字体
//居中显示按钮文本
int textX = scaledX + (scaledWidth - textwidth(text.c_str())) / 2; // 计算文本在按钮中央的x坐标
int textY = scaledY + (scaledHeight - textheight(_T("幼圆"))) / 2; // 计算文本在按钮中央的y坐标
outtextxy(textX, textY, text.c_str()); // 在按钮上绘制文本
}
};

// 定义Widget类,表示一个简单的图形用户界面
class Widget
{
private:
wstring text_name = L"飞机大战"; // 标题文本
wstring set_name = L"游戏设置"; // 标题文本
wstring difficulty_name = L"游戏难度"; // 难度文本
wstring stop_name = L"游戏暂停"; // 暂停文本
wstring fail_name = L"游戏失败"; // 失败文本
wstring success_name = L"闯关成功"; // 失败文本
wstring rank_name = L"排行榜"; // 排行榜文本
wstring easy_name = L"简单模式排行榜"; // 简单排行榜文本
wstring medium_name = L"中等模式排行榜"; // 中等排行榜文本
wstring hard_name = L"地狱模式排行榜"; // 地狱排行榜文本
wstring author_name = L"制作组信息"; // 制作组文本
wstring rule_name = L"游戏玩法"; // 游戏玩法文本
RECT rect_name = { 320, 50, 480, 150 };
int text_x; // 文字的x坐标
int text_y; // 文字的y坐标
int width; // 宽度
int height; // 高度
int currentIndex; // 当前页面索引
vector<IMAGE *> pages; // 存储所有页面的图片指针
vector<vector<Button *>> buttons; // 存储每个页面上的按钮

// 添加一个页面
void addPage(IMAGE *page)
{
pages.push_back(page);
buttons.push_back({});
}

// 在指定页面上添加一个按钮
void addButton(int index, Button *button)
{
if (index >= 0 && index < buttons.size())
{
buttons[index].push_back(button);
}
}

// 设置当前显示的页面索引
void setCurrentIndex(int index)
{
if (index >= 0 && index < pages.size())
{
currentIndex = index;
}
}

// 处理鼠标点击事件
void mouseClick(int mouseX, int mouseY)
{
if (currentIndex >= 0 && currentIndex < buttons.size())
{
for (Button *button : buttons[currentIndex])
{
if (button->checkClick(mouseX, mouseY))
{
break;
}
}
}
}

// 处理鼠标移动事件
void mouseMove(int mouseX, int mouseY)
{
if (currentIndex >= 0 && currentIndex < buttons.size())
{
for (Button *button : buttons[currentIndex])
{
button->checkMouseOver(mouseX, mouseY);
}
}
}

// 绘制当前页面的内容
void draw()
{
if (currentIndex >= 0 && currentIndex < pages.size())
{
putimage(0, 0, pages[currentIndex]); // 在窗口中绘制当前页面的图片

if (currentIndex >= 0 && currentIndex < buttons.size())
{
for (Button *button : buttons[currentIndex])
{
button->draw(); // 绘制当前页面上的所有按钮
}
}
}
}

public:
Widget(int width, int height)
:width(width), height(height), currentIndex(-1)
{
}
~Widget() {}

void drawpage(wstring loc, wstring name)
{
IMAGE *page = new IMAGE(width, height);// 昵称界面的图片指针
loadimage(page, loc.c_str(), width, height, true);
putimage(0, 0, page);
setlinestyle(PS_DASH | PS_ENDCAP_FLAT, 3); // 设置线条宽度和样式
// 绘制标题
fillroundrect(rect_name.left, rect_name.top, rect_name.right, rect_name.bottom, 50, 50); // 绘制标题
settextcolor(GREEN); // 设置文本颜色为绿色
setbkmode(TRANSPARENT); // 设置文本背景透明
settextstyle(35, 0, _T("华文琥珀")); // 设置文本大小和字体
text_x = rect_name.left + (rect_name.right - rect_name.left - textwidth(name.c_str())) / 2;
text_y = rect_name.top + (rect_name.bottom - rect_name.top - textheight(name.c_str())) / 2;
outtextxy(text_x, text_y, name.c_str()); // 在按钮上绘制文本
getimage(page, 0, 0, width, height); // 将昵称页面的内容保存到图片中
addPage(page); // 添加昵称页面
}

void drawpage(wstring loc, wstring name, int)
{
IMAGE *page = new IMAGE(width, height);
loadimage(page, loc.c_str(), width, height, true);
putimage(0, 0, page);
// 绘制简单榜标题
RECT rect = { 220, 50, 580, 150 };
fillroundrect(rect.left, rect.top, rect.right, rect.bottom, 50, 50); // 绘制标题
settextcolor(GREEN); // 设置文本颜色为绿色
setbkmode(TRANSPARENT); // 设置文本背景透明
settextstyle(35, 0, _T("华文琥珀")); // 设置文本大小和字体
text_x = rect.left + (rect.right - rect.left - textwidth(name.c_str())) / 2;
text_y = rect.top + (rect.bottom - rect.top - textheight(name.c_str())) / 2;
outtextxy(text_x, text_y, name.c_str()); // 在按钮上绘制文本
fillroundrect(rect.left - 100, rect.top + 120, rect.right + 100, rect.bottom + 370, 50, 50); // 绘制标题
settextstyle(25, 0, _T("华文琥珀")); // 设置文本大小和字体
outtextxy(rect.left - 60, rect.top + 130, L"排名"); // 绘制排名
outtextxy(rect.left + 140, rect.top + 130, L"昵称"); // 绘制昵称
outtextxy(rect.left + 330, rect.top + 130, L"积分"); // 绘制积分
getimage(page, 0, 0, width, height); // 将页面的内容保存到图片中
addPage(page); // 添加暂停页面
}

// 初始化控件,创建图形环境,设置页面和按钮
void init()
{
initgraph(width, height);
BeginBatchDraw(); // 开始批量绘制, 批量绘制应该放在initgraph之后

// 0. 创建昵称界面
drawpage(L"./resource/page/name.jpg", text_name);

// 在昵称页面创建按钮input
Button *name_input = new Button(320, 200, 160, 60, L"输入游戏昵称", [&]() {
InputBox(name, 20, L"请输入游戏昵称"); // 点击按钮输入游戏昵称
});
addButton(0, name_input); // 将按钮input添加到昵称页面

// 在昵称页面创建按钮进入游戏
Button *name_enter = new Button(320, 310, 160, 60, L"进入游戏", [&]() {
setCurrentIndex(1);
});
addButton(0, name_enter); // 将按钮添加到昵称页面

// 在昵称页面创建按钮退出游戏
Button *name_exit = new Button(320, 420, 160, 60, L"退出游戏", [&]() {
closegraph();
exit(0);
});
addButton(0, name_exit); // 将按钮添加到昵称页面

// 1. 创建开始页面
drawpage(L"./resource/page/start.jpg", text_name);

// 在开始页面创建开始游戏按钮
Button *start_begin = new Button(320, 180, 150, 60, L"开始游戏", [&]() {
setCurrentIndex(2); // 进入游戏界面
});
addButton(1, start_begin); // 将按钮添加到页面

// 在开始页面创建游戏难度按钮
Button *start_difficulty = new Button(320, 260, 150, 60, L"游戏难度", [&]() {
setCurrentIndex(3); // 进入游戏难度界面
});
addButton(1, start_difficulty); // 将按钮添加到页面

// 在开始页面创建排行榜按钮
Button *start_rank = new Button(320, 340, 150, 60, L"排行榜", [&]() {
setCurrentIndex(4); // 进入排行榜界面
});
addButton(1, start_rank); // 将按钮添加到页面

// 在开始页面创建游戏设置按钮
Button *start_set = new Button(320, 420, 150, 60, L"游戏设置", [&]() {
setCurrentIndex(5); // 进入开始界面的游戏设置界面
});
addButton(1, start_set); // 将按钮添加到页面

// 在开始页面创建退出账号按钮
Button *start_exit = new Button(320, 500, 150, 60, L"退出账号", [&]() {
setCurrentIndex(0); // 返回昵称界面
});
addButton(1, start_exit); // 将按钮添加到页面

// 2. 创建游戏页面
IMAGE *page_game = new IMAGE(width, height);
loadimage(page_game, L"./resource/page/game.jpg", width + 400, height, true);
putimage(0, 0, page_game);

// 演示
// 加载图片:以CPP文件为起始位置
loadimage(page_game, L"./resource/icon/plane.png", 50, 50, true); // 战机
drawAlpha(page_game, 400, 580); // 载入PNG图并去透明部分
loadimage(page_game, L"./resource/icon/plane_bullet.png", 30, 30, true); // 战机子弹
drawAlpha(page_game, 410, 540); // 载入PNG图并去透明部分
loadimage(page_game, L"./resource/icon/enemy.png", 40, 40, true); // 敌机1
drawAlpha(page_game, 400, 50); // 载入PNG图并去透明部分
loadimage(page_game, L"./resource/icon/enemy_bullet.png", 30, 30, true); // 敌机子弹1
drawAlpha(page_game, 405, 100); // 载入PNG图并去透明部分
loadimage(page_game, L"./resource/icon/enemy.png", 40, 40, true); // 敌机2
drawAlpha(page_game, 350, 150); // 载入PNG图并去透明部分
loadimage(page_game, L"./resource/icon/enemy_bullet.png", 30, 30, true); // 敌机子弹2
drawAlpha(page_game, 355, 200); // 载入PNG图并去透明部分
loadimage(page_game, L"./resource/icon/enemy.png", 40, 40, true); // 敌机3
drawAlpha(page_game, 450, 70); // 载入PNG图并去透明部分
loadimage(page_game, L"./resource/icon/enemy_bullet.png", 30, 30, true); // 敌机子弹3
drawAlpha(page_game, 455, 120); // 载入PNG图并去透明部分
loadimage(page_game, L"./resource/icon/enemy.png", 40, 40, true); // 敌机4
drawAlpha(page_game, 200, 30); // 载入PNG图并去透明部分
loadimage(page_game, L"./resource/icon/enemy_bullet.png", 30, 30, true); // 敌机子弹4
drawAlpha(page_game, 205, 80); // 载入PNG图并去透明部分
loadimage(page_game, L"./resource/icon/item.png", 40, 40, true); // 道具
drawAlpha(page_game, 200, 320); // 载入PNG图并去透明部分
loadimage(page_game, L"./resource/icon/item.png", 40, 40, true); // 道具
drawAlpha(page_game, 600, 220); // 载入PNG图并去透明部分
loadimage(page_game, L"./resource/icon/score.png", 40, 60, true); // 计分板
drawAlpha(page_game, 15, 15); // 载入PNG图并去透明部分
loadimage(page_game, L"./resource/icon/life.png", 40, 40, true); // 血量
drawAlpha(page_game, 10, 590); // 载入PNG图并去透明部分
fillroundrect(60, 25, 130, 65, 20, 50); // 分数显示
fillroundrect(50, 590, 120, 630, 20, 50); // 血量显示
getimage(page_game, 0, 0, width, height); // 将页面的内容保存到图片中
addPage(page_game); // 添加游戏页面

// 在游戏页面创建暂停按钮
Button *game_stop = new Button(730, 25, 60, 50, L"暂停", [&]() {
setCurrentIndex(6); // 进入暂停界面
});
addButton(2, game_stop); // 将按钮添加到页面

// 3. 创建游戏难度页面
drawpage(L"./resource/page/difficulty.jpg", difficulty_name);

// 在游戏难度页面创建简单按钮
Button *difficulty_easy = new Button(320, 200, 160, 60, L"简单", [&]() {
difficulty = 1; // 难度设置为简单
});
addButton(3, difficulty_easy); // 将按钮添加到页面
// 在游戏难度页面创建中等按钮
Button *difficulty_medium = new Button(320, 310, 160, 60, L"中等", [&]() {
difficulty = 2; // 难度设置为中等
});
addButton(3, difficulty_medium); // 将按钮添加到页面
// 在游戏难度页面创建地狱按钮
Button *difficulty_hard = new Button(320, 420, 160, 60, L"地狱", [&]() {
difficulty = 3; // 难度设置为地狱
});
addButton(3, difficulty_hard); // 将按钮添加到页面
// 在游戏难度页面创建返回按钮
Button *difficulty_exit = new Button(320, 530, 160, 60, L"返回开始界面", [&]() {
setCurrentIndex(1); // 返回开始界面
});
addButton(3, difficulty_exit); // 将按钮添加到页面

// 4. 创建排行榜页面
drawpage(L"./resource/page/rank.jpg", rank_name);

// 在排行榜页面创建简单按钮
Button *rank_easy = new Button(320, 200, 160, 60, L"简单榜", [&]() {
setCurrentIndex(7); // 进入简单排行榜
});
addButton(4, rank_easy); // 将按钮添加到页面
// 在排行榜页面创建中等按钮
Button *rank_medium = new Button(320, 310, 160, 60, L"中等榜", [&]() {
setCurrentIndex(8); // 进入中等排行榜
});
addButton(4, rank_medium); // 将按钮添加到页面
// 在排行榜页面创建地狱按钮
Button *rank_hard = new Button(320, 420, 160, 60, L"地狱榜", [&]() {
setCurrentIndex(9); // 进入地狱排行榜
});
addButton(4, rank_hard); // 将按钮添加到页面
// 在排行榜页面创建返回按钮
Button *rank_exit = new Button(320, 530, 160, 60, L"返回开始界面", [&]() {
setCurrentIndex(1); // 返回开始界面
});
addButton(4, rank_exit); // 将按钮添加到页面

// 5. 游戏设置界面
drawpage(L"./resource/page/set.jpg", set_name);

// 在开始界面的设置界面页面创建音效按钮
Button *setinstart_music = new Button(320, 200, 160, 60, L"打开/关闭音效", [&]() {
controlsound(); // 控制音效
});
addButton(5, setinstart_music); // 将按钮添加到页面
// 在开始界面的设置界面页面创建游戏玩法按钮
Button *setinstart_rule = new Button(320, 310, 160, 60, L"游戏玩法", [&]() {
setCurrentIndex(11); // 进入游戏玩法
});
addButton(5, setinstart_rule); // 将按钮添加到页面
// 在开始界面的设置界面页面创建制作组信息按钮
Button *setinstart_author = new Button(320, 420, 160, 60, L"制作组信息", [&]() {
setCurrentIndex(10); // 进入制作组信息界面
});
addButton(5, setinstart_author); // 将按钮添加到页面
// 在开始界面的设置界面页面创建返回按钮
Button *setinstart_exit = new Button(320, 530, 160, 60, L"返回开始界面", [&]() {
setCurrentIndex(1); // 返回开始界面
});
addButton(5, setinstart_exit); // 将按钮添加到页面

// 6. 创建暂停界面
drawpage(L"./resource/page/stop.jpg", stop_name);

// 在暂停页面创建继续游戏按钮
Button *stop_continue = new Button(320, 200, 160, 60, L"继续游戏", [&]() {
setCurrentIndex(2); // 返回游戏界面
});
addButton(6, stop_continue); // 将按钮添加到页面
// 在暂停页面创建重新开始按钮
Button *stop_restart = new Button(320, 310, 160, 60, L"重新开始", [&]() {
setCurrentIndex(2); // 初始化数据并返回游戏界面
});
addButton(6, stop_restart); // 将按钮添加到页面
// 在暂停页面创建音效按钮
Button *stop_music = new Button(320, 420, 160, 60, L"打开/关闭音效", [&]() {
controlsound(); // 设置音效
});
addButton(6, stop_music); // 将按钮添加到页面
// 在暂停界面创建返回开始界面按钮
Button *stop_exit = new Button(320, 530, 160, 60, L"返回开始界面", [&]() {
setCurrentIndex(1); // 返回开始界面
});
addButton(6, stop_exit); // 将按钮添加到页面

// 7. 简单榜
drawpage(L"./resource/page/easy.jpg", easy_name, 0);

// 在简单榜界面创建返回排行榜界面按钮
Button *easy_exit = new Button(320, 530, 160, 60, L"返回排行榜", [&]() {
setCurrentIndex(4); // 返回排行榜界面
});
addButton(7, easy_exit); // 将按钮添加到页面

// 8. 中等榜
drawpage(L"./resource/page/medium.jpg", medium_name, 0);

// 在中等榜界面创建返回排行榜界面按钮
Button *medium_exit = new Button(320, 530, 160, 60, L"返回排行榜", [&]() {
setCurrentIndex(4); // 返回排行榜界面
});
addButton(8, medium_exit); // 将按钮添加到页面

// 9. 地狱榜
drawpage(L"./resource/page/hard.jpg", hard_name, 0);

// 在地狱榜界面创建返回排行榜界面按钮
Button *hard_exit = new Button(320, 530, 160, 60, L"返回排行榜", [&]() {
setCurrentIndex(4); // 返回排行榜界面
});
addButton(9, medium_exit); // 将按钮添加到页面

// 10. 制作组
IMAGE *page_author = new IMAGE(width, height);
loadimage(page_author, L"./resource/page/author.jpg", width, height, true);
putimage(0, 0, page_author);
// 绘制制作组标题
RECT rect_author = { 220, 50, 580, 150 };
fillroundrect(rect_author.left, rect_author.top, rect_author.right, rect_author.bottom, 50, 50); // 绘制标题
settextcolor(GREEN); // 设置文本颜色为绿色
setbkmode(TRANSPARENT); // 设置文本背景透明
settextstyle(35, 0, _T("华文琥珀")); // 设置文本大小和字体
text_x = rect_author.left + (rect_author.right - rect_author.left - textwidth(author_name.c_str())) / 2;
text_y = rect_author.top + (rect_author.bottom - rect_author.top - textheight(author_name.c_str())) / 2;
outtextxy(text_x, text_y, author_name.c_str()); // 在按钮上绘制文本
fillroundrect(rect_author.left - 100, rect_author.top + 120, rect_author.right + 100, rect_author.bottom + 370, 50, 50); // 绘制标题
settextstyle(28, 0, _T("华文彩云")); // 设置文本大小和字体
outtextxy(rect_author.left - 40, rect_author.top + 130, L"成员"); // 绘制昵称
outtextxy(rect_author.left + 220, rect_author.top + 130, L"负责部分"); // 绘制简介
settextstyle(25, 0, _T("华光行楷_CNKI")); // 设置文本大小和字体
settextcolor(RGB(49, 128, 87)); // 设置文本颜色
outtextxy(rect_author.left - 40, rect_author.top + 170, L"邓钦予"); // 绘制昵称
outtextxy(rect_author.left - 40, rect_author.top + 200, L"何宁"); // 绘制昵称
outtextxy(rect_author.left - 40, rect_author.top + 230, L"祖培宏"); // 绘制昵称
outtextxy(rect_author.left - 40, rect_author.top + 260, L"李丰任"); // 绘制昵称
outtextxy(rect_author.left - 40, rect_author.top + 290, L"杨永山泰"); // 绘制昵称
outtextxy(rect_author.left - 40, rect_author.top + 320, L"千反田"); // 绘制昵称
outtextxy(rect_author.left - 40, rect_author.top + 350, L"苏子乔"); // 绘制昵称
outtextxy(rect_author.left - 40, rect_author.top + 380, L"沈兴满"); // 绘制昵称
outtextxy(rect_author.left - 40, rect_author.top + 410, L"阿聪"); // 绘制昵称
outtextxy(rect_author.left - 40, rect_author.top + 440, L"岳永"); // 绘制昵称
outtextxy(rect_author.left + 160, rect_author.top + 170, L"游戏界面设计"); // 绘制简介
outtextxy(rect_author.left + 160, rect_author.top + 200, L"游戏BOSS生成和运行逻辑"); // 绘制简介
outtextxy(rect_author.left + 160, rect_author.top + 230, L"游戏功能流程图整理"); // 绘制简介
outtextxy(rect_author.left + 160, rect_author.top + 260, L"子弹设计和代码整合"); // 绘制简介
outtextxy(rect_author.left + 160, rect_author.top + 290, L"子弹设计和代码整合"); // 绘制简介
outtextxy(rect_author.left + 160, rect_author.top + 320, L"敌机生成和运行逻辑"); // 绘制简介
outtextxy(rect_author.left + 160, rect_author.top + 350, L"数据保存加载和排行榜制作"); // 绘制简介
outtextxy(rect_author.left + 160, rect_author.top + 380, L"游戏音效设置"); // 绘制简介
outtextxy(rect_author.left + 160, rect_author.top + 410, L"玩家战机生成和运行逻辑"); // 绘制简介
outtextxy(rect_author.left + 160, rect_author.top + 440, L"道具生成和运行逻辑"); // 绘制简介
getimage(page_author, 0, 0, width, height); // 将页面的内容保存到图片中
addPage(page_author); // 添加制作组信息页面
// 在制作组界面创建返回按钮
Button *author_exit = new Button(320, 540, 160, 60, L"返回设置", [&]() {
setCurrentIndex(5); // 返回设置界面
});
addButton(10, author_exit); // 将按钮添加到页面

// 11. 游戏玩法说明
IMAGE *page_rule = new IMAGE(width, height);
loadimage(page_rule, L"./resource/page/rule.jpg", width, height, true);
putimage(0, 0, page_rule);
// 绘制玩法标题
RECT rect_rule = { 220, 50, 580, 150 };
fillroundrect(rect_rule.left, rect_rule.top, rect_rule.right, rect_rule.bottom, 50, 50); // 绘制标题
settextcolor(GREEN); // 设置文本颜色为绿色
setbkmode(TRANSPARENT); // 设置文本背景透明
settextstyle(35, 0, _T("华文琥珀")); // 设置文本大小和字体
text_x = rect_rule.left + (rect_rule.right - rect_rule.left - textwidth(rule_name.c_str())) / 2;
text_y = rect_rule.top + (rect_rule.bottom - rect_rule.top - textheight(rule_name.c_str())) / 2;
outtextxy(text_x, text_y, rule_name.c_str()); // 在按钮上绘制文本
fillroundrect(rect_rule.left - 80, rect_rule.top + 120, rect_rule.right + 80, rect_rule.bottom + 370, 50, 50); // 绘制标题
settextstyle(25, 0, _T("华文琥珀")); // 设置文本大小和字体
settextcolor(RGB(49, 128, 87)); // 设置文本颜色为黑色
outtextxy(rect_rule.left - 40, rect_rule.top + 140, L"↑↓←→控制战机移动");
outtextxy(rect_rule.left - 40, rect_rule.top + 180, L"首页可以设置游戏难度");
outtextxy(rect_rule.left - 40, rect_rule.top + 220, L"昵称页面可以设置玩家昵称");
outtextxy(rect_rule.left - 40, rect_rule.top + 260, L"战机自动发射子弹");
outtextxy(rect_rule.left - 40, rect_rule.top + 300, L"击毁敌机分数增加, 被敌机击中生命值减少");
outtextxy(rect_rule.left - 40, rect_rule.top + 340, L"击毁BOSS游戏胜利, 生命值小于0游戏结束");
outtextxy(rect_rule.left - 40, rect_rule.top + 380, L"获得道具可以随机增加生命或子弹伤害");
outtextxy(rect_rule.left - 40, rect_rule.top + 420, L"游戏界面右上角可以暂停游戏");
getimage(page_rule, 0, 0, width, height); // 将页面的内容保存到图片中
addPage(page_rule); // 添加玩法信息页面
// 在玩法界面创建返回按钮
Button *rule_exit = new Button(320, 540, 160, 60, L"返回设置", [&]() {
setCurrentIndex(5); // 返回设置界面
});
addButton(11, rule_exit); // 将按钮添加到页面

// 12. 失败界面
IMAGE *page_fail = new IMAGE(width, height);
loadimage(page_fail, L"./resource/page/fail.jpg", width, height, true);
putimage(0, 0, page_fail);
// 绘制玩法标题
RECT rect_fail = { 220, 50, 580, 150 };
fillroundrect(rect_fail.left, rect_fail.top, rect_fail.right, rect_fail.bottom, 50, 50); // 绘制标题
settextcolor(GREEN); // 设置文本颜色为绿色
setbkmode(TRANSPARENT); // 设置文本背景透明
settextstyle(35, 0, _T("华文琥珀")); // 设置文本大小和字体
text_x = rect_fail.left + (rect_fail.right - rect_fail.left - textwidth(fail_name.c_str())) / 2;
text_y = rect_fail.top + (rect_fail.bottom - rect_fail.top - textheight(fail_name.c_str())) / 2;
outtextxy(text_x, text_y, fail_name.c_str()); // 在按钮上绘制文本
fillroundrect(rect_fail.left, rect_fail.top + 120, rect_fail.right, rect_fail.bottom + 60, 50, 50); // 绘制安慰
settextstyle(25, 0, _T("华文琥珀")); // 设置文本大小和字体
outtextxy(rect_fail.left + 90, rect_fail.top + 130, L"别走,决战到天亮!"); // 绘制失败安慰
getimage(page_fail, 0, 0, width, height); // 将页面的内容保存到图片中
addPage(page_fail); // 添加失败页面
// 在失败页面创建音效设置按钮
Button *fail_music = new Button(320, 250, 160, 60, L"打开/关闭音效", [&]() {
controlsound(); // 音效设置
});
addButton(12, fail_music); // 将按钮添加到页面
// 在失败页面创建再次挑战按钮
Button *fail_restart = new Button(320, 360, 160, 60, L"再次挑战", [&]() {
setCurrentIndex(2); // 初始化数据并返回游戏界面
});
addButton(12, fail_restart); // 将按钮添加到页面
// 在失败页面创建返回按钮
Button *fail_exit = new Button(320, 470, 160, 60, L"返回开始界面", [&]() {
setCurrentIndex(1); // 初始化数据并返回游戏界面
});
addButton(12, fail_exit); // 将按钮添加到页面

// 13. 成功界面
IMAGE *page_success = new IMAGE(width, height);
loadimage(page_success, L"./resource/page/success.jpg", width + 150, height, true);
putimage(0, 0, page_success);

loadimage(page_success, L"./resource/page/666.png", 120, 120, true);
drawAlpha(page_success, 130, 260);

//绘制成功标题
RECT rect_success = { 220, 60, 580, 200 };
fillroundrect(rect_success.left, rect_success.top, rect_success.right, rect_success.bottom, 50, 50); // 绘制标题
settextcolor(GREEN); // 设置文本颜色为绿色
setbkmode(TRANSPARENT); // 设置文本背景透明
settextstyle(35, 0, _T("华文琥珀")); // 设置文本大小和字体
text_x = rect_success.left + (rect_success.right - rect_success.left - textwidth(success_name.c_str())) / 2;
text_y = rect_success.top + (rect_success.bottom - rect_success.top - textheight(success_name.c_str())) / 2;
outtextxy(text_x, text_y, success_name.c_str()); // 在按钮上绘制文本
fillroundrect(rect_success.left - 120, rect_success.top + 190, rect_success.right - 340, rect_success.bottom + 90, 50, 50); // 绘制安慰
settextstyle(25, 0, _T("华文琥珀")); // 设置文本大小和字体
outtextxy(rect_success.left - 100, rect_success.top + 200, L"牛哇牛哇!"); // 绘制通关提示
getimage(page_success, 0, 0, width, height); // 将页面的内容保存到图片中
addPage(page_success); // 添加成功页面
// 在成功页面创建重新挑战按钮
Button *success_restart = new Button(320, 280, 180, 90, L"重新挑战", [&]() {
//init(); // 初始化数据并返回游戏界面
setCurrentIndex(2);
});
addButton(13, success_restart); // 将按钮添加到页面
// 在成功页面创建返回按钮
Button *success_exit = new Button(320, 420, 180, 90, L"返回开始界面", [&]() {
setCurrentIndex(1); // 初始化数据并返回游戏界面
});
addButton(13, success_exit); // 将按钮添加到页面

setCurrentIndex(0); // 设置初始显示页面
FlushBatchDraw(); // 将缓冲区内容显示在屏幕上
}

// 运行,进入消息循环
void run()
{
ExMessage msg;

BeginBatchDraw(); // 开始批量绘制

while (true)
{
if (peekmessage(&msg)) // 检查是否有消息
{
int mouseX = msg.x; // 获取鼠标x坐标
int mouseY = msg.y; // 获取鼠标y坐标

switch (msg.message)
{
case WM_LBUTTONDOWN: // 鼠标左键按下事件
mouseClick(mouseX, mouseY); // 处理鼠标点击事件
break;
case WM_MOUSEMOVE: // 鼠标移动事件
mouseMove(mouseX, mouseY); // 处理鼠标移动事件
break;
}
}

draw(); // 绘制当前页面内容
FlushBatchDraw(); // 将缓冲区内容显示在屏幕上
Sleep(10);
}

EndBatchDraw(); // 结束批量绘制
}

// 关闭
void close()
{
closegraph(); // 关闭图形环境
}
};

int main()
{
mciSendString(L"open ./music/game_music.mp3", NULL, 0, NULL);
mciSendString(L"play ./music/game_music.mp3", NULL, 0, NULL);
Widget widget(800, 640);
widget.init();
widget.run();
widget.close();
return 0;
}

完整版项目体验

下载地址