C++ EGE 实现坦克大战小游戏,供大家参考,具体内容如下
因为有过一次用EGE写小游戏的经验,所以这一次写坦克大战快了很多。并且使用对象编程也简化了很多编程时繁琐的步骤。
写出坦克大战使我在学习编程的道路上又迈出了一大步。
如果您需要图片素材的,我可以单独发给您。
技术环节:
编译环境:Windows VS2019
需求:
控制坦克移动发射炮弹,炮弹可以消灭敌军坦克,且可以消灭砖块。坦克遇到方块会被挡住。敌军消灭我军三次或基地被毁则游戏失败,共摧毁十次敌方坦克游戏胜利。
思路:
先写出坦克的父类,我方坦克类和敌方坦克类继承坦克父类,实例化我方坦克和敌方坦克。地图使用list容器存储。
在代码注释中标注了每一步是怎么实现的。
注意:
因为我在程序中用了一些不规范的写法,所以要在VS中正常编译运行,需要右键源文件->属性->C/C+±>符合模式,改为否。
包含<graphics.h>图形库需要提前配置EGE图形库。
如要在其他graphics图形库下编译,可能需要修改某些地方。
运行效果:
代码:
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
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167#include <graphics.h> //图形库 #include <ctime> //time(); #include <list> //list容器 using namespace std; //标准命名空间 list等 //设置图片对象中图片的宽高 全局函数 //参数:宽、高、对象名 void setimage(int pwidth, int pheight, PIMAGE img_1); //地图全局结构 struct mapstr { int m_x; //xy坐标 int m_y; int prop; //属性 }; //地图类 class Mymap { private: list<mapstr> listmap; //地图容器,存储全地图信息,全地图1350个20*20的格子 public: //设置地图 Mymap() { mapstr temp; //构造函数为链表容器中的地图赋值 //全地图横向45个格子 竖向30个格子 //基地部分 { temp.prop = 0; for (int i = 0; i < 4; i++) { temp.m_x = 380 + i * 20; temp.m_y = 540; listmap.push_back(temp); } for (int i = 0; i < 4; i++) { temp.m_x = 380 + i * 20; temp.m_y = 520; listmap.push_back(temp); } for (int i = 0; i < 2; i++) { temp.m_x = 380; temp.m_y = 560 + i * 20; listmap.push_back(temp); } for (int i = 0; i < 4; i++) { temp.m_x = 360; temp.m_y = 520 + i * 20; listmap.push_back(temp); } for (int i = 0; i < 2; i++) { temp.m_x = 440; temp.m_y = 560 + i * 20; listmap.push_back(temp); } for (int i = 0; i < 4; i++) { temp.m_x = 460; temp.m_y = 520 + i * 20; listmap.push_back(temp); } temp.prop = 4, temp.m_x = 400, temp.m_y = 560; listmap.push_back(temp); } //左上角部分 { temp.prop = 0; //左上角单独砖块 for (int i = 0; i < 2; i++) { temp.m_x = 40 + i * 20; temp.m_y = 80; listmap.push_back(temp); } for (int i = 0; i < 2; i++) { temp.m_x = 40 + i * 20; temp.m_y = 100; listmap.push_back(temp); } //竖铁块 for (int i = 0; i < 4; i++) { temp.m_x = 160; temp.m_y = i * 20; temp.prop = 1; listmap.push_back(temp); } for (int i = 0; i < 4; i++) { temp.m_x = 180; temp.m_y = i * 20; listmap.push_back(temp); } //砖块 for (int i = 0; i < 4; i++) { temp.m_x = 160; temp.m_y = 160 + i * 20; temp.prop = 0; listmap.push_back(temp); } for (int i = 0; i < 4; i++) { temp.m_x = 180; temp.m_y = 160 + i * 20; listmap.push_back(temp); } //草块 for (int i = 0; i < 4; i++) { temp.m_x = 0; temp.m_y = 200 + i * 20; temp.prop = 2; listmap.push_back(temp); } for (int i = 0; i < 4; i++) { temp.m_x = 20; temp.m_y = 200 + i * 20; listmap.push_back(temp); } for (int i = 0; i < 2; i++) { temp.m_x = 40 + i * 20; temp.m_y = 240; listmap.push_back(temp); } for (int i = 0; i < 2; i++) { temp.m_x = 40 + i * 20; temp.m_y = 260; listmap.push_back(temp); } } //中上部分 { //铁块 for (int i = 0; i < 2; i++) { temp.m_x = 320; temp.m_y = i * 20; temp.prop = 1; listmap.push_back(temp); } for (int i = 0; i < 2; i++) { temp.m_x = 340; temp.m_y = i * 20; listmap.push_back(temp); } for (int i = 0; i < 2; i++) { temp.m_x = 280 + i * 20; temp.m_y = 160; listmap.push_back(temp); } for (int i = 0; i < 2; i++) { temp.m_x = 280 + i * 20; temp.m_y = 180; listmap.push_back(temp); } for (int i = 0; i < 4; i++) { temp.m_x = 400 + i * 20; temp.m_y = 200; listmap.push_back(temp); } for (int i = 0; i < 4; i++) { temp.m_x = 400 + i * 20; temp.m_y = 220; listmap.push_back(temp); } //砖块 for (int i = 0; i < 4; i++) { temp.m_x = 320; temp.m_y = 40 + i * 20; temp.prop = 0; listmap.push_back(temp); } for (int i = 0; i < 4; i++) { temp.m_x = 340; temp.m_y = 40 + i * 20; listmap.push_back(temp); } for (int i = 0; i < 2; i++) { temp.m_x = 240; temp.m_y = 200 + i * 20; listmap.push_back(temp); } for (int i = 0; i < 2; i++) { temp.m_x = 260; temp.m_y = 200 + i * 20; listmap.push_back(temp); } } //右上部分 { //砖块 for (int i = 0; i < 4; i++) { temp.m_x = 480; temp.m_y = 40 + i * 20; listmap.push_back(temp); } for (int i = 0; i < 4; i++) { temp.m_x = 500; temp.m_y = 40 + i * 20; listmap.push_back(temp); } for (int i = 0; i < 2; i++) { temp.m_x = 480; temp.m_y = 160 + i * 20; listmap.push_back(temp); } for (int i = 0; i < 2; i++) { temp.m_x = 500; temp.m_y = 160 + i * 20; listmap.push_back(temp); } for (int i = 0; i < 4; i++) { temp.m_x = 600; temp.m_y = 40 + i * 20; listmap.push_back(temp); } for (int i = 0; i < 4; i++) { temp.m_x = 620; temp.m_y = 40 + i * 20; listmap.push_back(temp); } for (int i = 0; i < 2; i++) { temp.m_x = 600; temp.m_y = 160 + i * 20; listmap.push_back(temp); } for (int i = 0; i < 2; i++) { temp.m_x = 620; temp.m_y = 160 + i * 20; listmap.push_back(temp); } for (int i = 0; i < 6; i++) { temp.m_x = 680 + i * 20; temp.m_y = 200; listmap.push_back(temp); } for (int i = 0; i < 6; i++) { temp.m_x = 680 + i * 20; temp.m_y = 220; listmap.push_back(temp); } for (int i = 0; i < 6; i++) { temp.m_x = 760; temp.m_y = 0 + i * 20; listmap.push_back(temp); } for (int i = 0; i < 6; i++) { temp.m_x = 780; temp.m_y = 0 + i * 20; listmap.push_back(temp); } //草块 for (int i = 0; i < 6; i++) { temp.m_x = 560; temp.m_y = 160 + i * 20; temp.prop = 2; listmap.push_back(temp); } for (int i = 0; i < 6; i++) { temp.m_x = 580; temp.m_y = 160 + i * 20; listmap.push_back(temp); } for (int i = 0; i < 4; i++) { temp.m_x = 520; temp.m_y = 160 + i * 20; listmap.push_back(temp); } for (int i = 0; i < 4; i++) { temp.m_x = 540; temp.m_y = 160 + i * 20; listmap.push_back(temp); } for (int i = 0; i < 4; i++) { temp.m_x = 860; temp.m_y = 80 + i * 20; listmap.push_back(temp); } for (int i = 0; i < 4; i++) { temp.m_x = 880; temp.m_y = 80 + i * 20; listmap.push_back(temp); } //铁块 for (int i = 0; i < 4; i++) { temp.m_x = 520 + i * 20; temp.m_y = 80; temp.prop = 1; listmap.push_back(temp); } for (int i = 0; i < 4; i++) { temp.m_x = 520 + i * 20; temp.m_y = 100; listmap.push_back(temp); } for (int i = 0; i < 4; i++) { temp.m_x = 640 + i * 20; temp.m_y = 160; listmap.push_back(temp); } for (int i = 0; i < 4; i++) { temp.m_x = 640 + i * 20; temp.m_y = 180; listmap.push_back(temp); } for (int i = 0; i < 6; i++) { temp.m_x = 800 + i * 20; temp.m_y = 200; listmap.push_back(temp); } for (int i = 0; i < 6; i++) { temp.m_x = 800 + i * 20; temp.m_y = 220; listmap.push_back(temp); } } //左下部分 { //铁块 for (int i = 0; i < 2; i++) { temp.m_x = i * 20; temp.m_y = 360; temp.prop = 1; listmap.push_back(temp); } for (int i = 0; i < 2; i++) { temp.m_x = i * 20; temp.m_y = 380; listmap.push_back(temp); } for (int i = 0; i < 4; i++) { temp.m_x = 160; temp.m_y = 320 + i * 20; listmap.push_back(temp); } for (int i = 0; i < 4; i++) { temp.m_x = 180; temp.m_y = 320 + i * 20; listmap.push_back(temp); } //砖块 for (int i = 0; i < 12; i++) { temp.m_x = 40; temp.m_y = 360 + i * 20; temp.prop = 0; listmap.push_back(temp); } for (int i = 0; i < 12; i++) { temp.m_x = 60; temp.m_y = 360 + i * 20; listmap.push_back(temp); } for (int i = 0; i < 8; i++) { temp.m_x = 40 + i * 20; temp.m_y = 280; listmap.push_back(temp); } for (int i = 0; i < 8; i++) { temp.m_x = 40 + i * 20; temp.m_y = 300; listmap.push_back(temp); } for (int i = 0; i < 4; i++) { temp.m_x = 160; temp.m_y = 400 + i * 20; listmap.push_back(temp); } for (int i = 0; i < 4; i++) { temp.m_x = 180; temp.m_y = 400 + i * 20; listmap.push_back(temp); } for (int i = 0; i < 2; i++) { temp.m_x = 160; temp.m_y = 560 + i * 20; listmap.push_back(temp); } for (int i = 0; i < 2; i++) { temp.m_x = 180; temp.m_y = 560 + i * 20; listmap.push_back(temp); } for (int i = 0; i < 2; i++) { temp.m_x = 240 + i * 20; temp.m_y = 240; listmap.push_back(temp); } for (int i = 0; i < 2; i++) { temp.m_x = 240 + i * 20; temp.m_y = 260; listmap.push_back(temp); } for (int i = 0; i < 8; i++) { temp.m_x = 280; temp.m_y = 320 + i * 20; listmap.push_back(temp); } for (int i = 0; i < 8; i++) { temp.m_x = 300; temp.m_y = 320 + i * 20; listmap.push_back(temp); } for (int i = 0; i < 8; i++) { temp.m_x = 320; temp.m_y = 320 + i * 20; listmap.push_back(temp); } for (int i = 0; i < 8; i++) { temp.m_x = 340; temp.m_y = 320 + i * 20; listmap.push_back(temp); } for (int i = 0; i < 4; i++) { temp.m_x = 360; temp.m_y = 400 + i * 20; listmap.push_back(temp); } for (int i = 0; i < 4; i++) { temp.m_x = 380; temp.m_y = 400 + i * 20; listmap.push_back(temp); } for (int i = 0; i < 4; i++) { temp.m_x = 400; temp.m_y = 400 + i * 20; listmap.push_back(temp); } for (int i = 0; i < 4; i++) { temp.m_x = 420; temp.m_y = 400 + i * 20; listmap.push_back(temp); } for (int i = 0; i < 8; i++) { temp.m_x = 440; temp.m_y = 320 + i * 20; listmap.push_back(temp); } for (int i = 0; i < 8; i++) { temp.m_x = 460; temp.m_y = 320 + i * 20; listmap.push_back(temp); } for (int i = 0; i < 8; i++) { temp.m_x = 480; temp.m_y = 320 + i * 20; listmap.push_back(temp); } for (int i = 0; i < 8; i++) { temp.m_x = 500; temp.m_y = 320 + i * 20; listmap.push_back(temp); } for (int i = 0; i < 8; i++) { temp.m_x = 520; temp.m_y = 320 + i * 20; listmap.push_back(temp); } for (int i = 0; i < 8; i++) { temp.m_x = 540; temp.m_y = 320 + i * 20; listmap.push_back(temp); } //草块 for (int i = 0; i < 10; i++) { temp.m_x = 200 + i * 20; temp.m_y = 280; temp.prop = 2; listmap.push_back(temp); } for (int i = 0; i < 10; i++) { temp.m_x = 200 + i * 20; temp.m_y = 300; listmap.push_back(temp); } for (int i = 0; i < 4; i++) { temp.m_x = 200 + i * 20; temp.m_y = 320; listmap.push_back(temp); } for (int i = 0; i < 4; i++) { temp.m_x = 200 + i * 20; temp.m_y = 340; listmap.push_back(temp); } } //右下部分 { //砖块 for (int i = 0; i < 8; i++) { temp.m_x = 600; temp.m_y = 320 + i * 20; temp.prop = 0; listmap.push_back(temp); } for (int i = 0; i < 8; i++) { temp.m_x = 620; temp.m_y = 320 + i * 20; listmap.push_back(temp); } for (int i = 0; i < 4; i++) { temp.m_x = 560; temp.m_y = 520 + i * 20; listmap.push_back(temp); } for (int i = 0; i < 4; i++) { temp.m_x = 580; temp.m_y = 520 + i * 20; listmap.push_back(temp); } for (int i = 0; i < 8; i++) { temp.m_x = 600 + i * 20; temp.m_y = 560; listmap.push_back(temp); } for (int i = 0; i < 8; i++) { temp.m_x = 600 + i * 20; temp.m_y = 580; listmap.push_back(temp); } for (int i = 0; i < 4; i++) { temp.m_x = 680 + i * 20; temp.m_y = 520; listmap.push_back(temp); } for (int i = 0; i < 4; i++) { temp.m_x = 680 + i * 20; temp.m_y = 540; listmap.push_back(temp); } for (int i = 0; i < 7; i++) { temp.m_x = 760 + i * 20; temp.m_y = 320; listmap.push_back(temp); } for (int i = 0; i < 7; i++) { temp.m_x = 760 + i * 20; temp.m_y = 340; listmap.push_back(temp); } for (int i = 0; i < 8; i++) { temp.m_x = 800; temp.m_y = 320 + i * 20; listmap.push_back(temp); } for (int i = 0; i < 8; i++) { temp.m_x = 820; temp.m_y = 320 + i * 20; listmap.push_back(temp); } //铁块 for (int i = 0; i < 4; i++) { temp.m_x = 640; temp.m_y = 320 + i * 20; temp.prop = 1; listmap.push_back(temp); } for (int i = 0; i < 4; i++) { temp.m_x = 660; temp.m_y = 320 + i * 20; listmap.push_back(temp); } for (int i = 0; i < 2; i++) { temp.m_x = 680; temp.m_y = 320 + i * 20; temp.prop = 1; listmap.push_back(temp); } for (int i = 0; i < 2; i++) { temp.m_x = 700; temp.m_y = 320 + i * 20; temp.prop = 1; listmap.push_back(temp); } for (int i = 0; i < 4; i++) { temp.m_x = 820 + i * 20; temp.m_y = 480; listmap.push_back(temp); } for (int i = 0; i < 4; i++) { temp.m_x = 820 + i * 20; temp.m_y = 500; listmap.push_back(temp); } //草块 for (int i = 0; i < 4; i++) { temp.m_x = 560; temp.m_y = 360 + i * 20; temp.prop = 2; listmap.push_back(temp); } for (int i = 0; i < 4; i++) { temp.m_x = 580; temp.m_y = 360 + i * 20; listmap.push_back(temp); } } } //显示地图 void printmap(list<mapstr>& listmap) { PIMAGE mapprop_0 = newimage(); getimage(mapprop_0, "坦克大战完整素材\砖块.png"); setimage(20, 20, mapprop_0); PIMAGE mapprop_1 = newimage(); getimage(mapprop_1, "坦克大战完整素材\铁块.png"); setimage(20, 20, mapprop_1); PIMAGE mapprop_2 = newimage(); getimage(mapprop_2, "坦克大战完整素材\草块.png"); setimage(20, 20, mapprop_2); PIMAGE mapprop_4 = newimage(); getimage(mapprop_4, "坦克大战完整素材\老鹰_1.png"); setimage(40, 40, mapprop_4); PIMAGE mapprop_5 = newimage(); getimage(mapprop_5, "坦克大战完整素材\老鹰_2.png"); setimage(40, 40, mapprop_5); for (list<mapstr>::iterator it = listmap.begin(); it != listmap.end(); it++) { switch (it->prop) { case 0: putimage(it->m_x, it->m_y, mapprop_0); break; case 1: putimage(it->m_x, it->m_y, mapprop_1); break; case 2: putimage(it->m_x, it->m_y, mapprop_2); break; case 4: putimage(it->m_x, it->m_y, mapprop_4); break; case 5: putimage(it->m_x, it->m_y, mapprop_5); break; } } delimage(mapprop_0); delimage(mapprop_1); delimage(mapprop_2); delimage(mapprop_4); delimage(mapprop_5); } //获取地图容器 list<mapstr> getmapves() { return listmap; } }; //坦克父类 class Tank { public: virtual void move(const list<mapstr>& tempves) = 0; //坦克移动函数 int getlauch_x() //获取子弹x坐标 { return b_m_x; } int getlauch_y() //获取子弹y坐标 { return b_m_y; } void setlauch_xy() //设置子弹坐标 { b_m_x = m_x + 18; //重置位置为坦克中间 b_m_y = m_y + 18; key1 = key2; //key1 = key2避免炮弹一直发射 } int getTank_x() //获取坦克x坐标 { return m_x; } int getTank_y() //获取坦克y坐标 { return m_y; } char getkey2() //返回发射时的坦克方向信息 { return key2; } //坦克攻击子弹位置爆炸 void exploed() { PIMAGE explimg_1 = newimage(); getimage(explimg_1, "坦克大战完整素材\爆炸效果1.png"); setimage(10, 10, explimg_1); PIMAGE explimg_2 = newimage(); getimage(explimg_2, "坦克大战完整素材\爆炸效果2.png"); setimage(20, 20, explimg_2); PIMAGE explimg_3 = newimage(); getimage(explimg_3, "坦克大战完整素材\爆炸效果3.png"); setimage(40, 40, explimg_3); PIMAGE explimgarr[3] = { explimg_1, explimg_2, explimg_3 }; for (int i = 0; i < 3; i++) { if (key2 == 'd' || key2 == 'a')//根据坦克的攻击朝向确定爆炸的位置 putimage(b_m_x, b_m_y - 6 * i, explimgarr[i]); else putimage(b_m_x - 6 * i, b_m_y, explimgarr[i]); delay_fps(42); } delimage(explimg_1); delimage(explimg_2); delimage(explimg_3); } //构造函数 Tank() { m_x = 0; m_y = 0; m_health = 0; m_damage = 0; path_1 = NULL; path_2 = NULL; path_3 = NULL; path_4 = NULL; b_m_x = 0; b_m_y = 0; key1 = '0'; key2 = '0'; } protected: //从文件中获取坦克图片 void gettank(const char *path) { PIMAGE tankimg = newimage(); //创建图片对象 getimage(tankimg, path); //在文件中获取图片到图片对象 setimage(40, 40, tankimg); //设置图片对象大小 putimage(this->m_x, this->m_y, tankimg);//在坐标处输出图片 delimage(tankimg); //释放图片对象 } //输出显示坦克 void printtank(const char key2) { //根据当前的键值,输出坦克 switch (key2) { case 'w': gettank(path_1); break; //输出坦克 case 's': gettank(path_2); break; case 'a': gettank(path_3); break; case 'd': gettank(path_4); break; } } //发射子弹 void launch() { printtank(key2); setfillcolor(WHITE); switch (key2) { case 'w': b_m_y -= 10; bar(b_m_x, b_m_y, b_m_x + 4, b_m_y + 8); break; case 'a': b_m_x -= 10; bar(b_m_x, b_m_y, b_m_x + 8, b_m_y + 4); break; case 's': b_m_y += 10; bar(b_m_x, b_m_y, b_m_x + 4, b_m_y + 8); break; case 'd': b_m_x += 10; bar(b_m_x, b_m_y, b_m_x + 8, b_m_y + 4); break; } //子弹越界目标则子弹坐标刷新 if (b_m_x >= 900 || b_m_x <= 0 || b_m_y >= 600 || b_m_y <= 0) setlauch_xy(); //重置子弹位置 } int m_x; //坦克xy坐标 int m_y; int m_health; //坦克血量 int m_damage; //子弹伤害量 char* path_1; //四张不同方向的坦克图片,由派生类决定图片路径 char* path_2; char* path_3; char* path_4; int b_m_x; //子弹坐标xy int b_m_y; char key1; //用于接收键盘信息 char key2; //用于存储上一条键值,也是发射时的坦克的朝向 }; //游戏失败结束全局函数 在生命为0 和 基地被攻击时调用 void gameoverfalse() { cleardevice(); PIMAGE gameoverbackimg = newimage(); getimage(gameoverbackimg, "坦克大战完整素材\游戏结束背景.jpg"); setimage(900,600,gameoverbackimg); putimage(0, 0, gameoverbackimg); //输出背景图片 PIMAGE gameoverimg = newimage(); getimage(gameoverimg, "坦克大战完整素材\游戏结束.png"); setimage(200, 200, gameoverimg); putimage_withalpha(NULL, gameoverimg, 350, 200); //透明格式输出游戏结束图片 delimage(gameoverbackimg); delimage(gameoverimg); //释放内存 getch(); getch(); } //我方坦克,可被操控移动 class TankFriend :public Tank { private: int Fridienum = 0; public: //构造函数初始化坦克坐标 TankFriend() { m_x = 300; //我方坦克的初始坐标为屏幕中下方 m_y = 560; m_health = 100; //坦克血量 m_damage = 90; //坦克伤害 b_m_x = m_x + 18; b_m_x = m_x + 18; path_1 = "坦克大战完整素材\己方坦克上.png"; //赋值需要将源文件属性语言中符合模式改为否 path_2 = "坦克大战完整素材\己方坦克下.png"; path_3 = "坦克大战完整素材\己方坦克左.png"; path_4 = "坦克大战完整素材\己方坦克右.png"; key1 = 'w'; //初始化key1用于输出初始的坦克 } int getTankdamage() //获取坦克伤害 { return m_damage; } int getTankhealth() //获取坦克血量 { return m_health; } void setTankhealth(const int health) //设置坦克血量 { m_health = health; } int getFridienumfun() //获取我方坦克被消灭次数 { return Fridienum; } //坦克被操控移动 virtual void move(const list<mapstr>& tempves) { if (key1 != 'j') key2 = key1; //key2记录上一个key1的值 if (kbhit()) { //用临时变量接收键值,如果键值为wasdj中的一个则赋给使用的变量 char tempkey = getch(); switch (tempkey) { case 'w': case 'a': case 's': case 'd': case 'j': key1 = tempkey; break; //接收的键盘值不是wasdj直接return default: return; } //判断坦克撞墙情况,坦克撞墙可以改变方向,但不会移动坐标 for (list<mapstr>::const_iterator it = tempves.begin(); it != tempves.end(); it++) { switch (tempkey) { //这里的大于小于号一个都不能错 case 'w': if ( ( //判断坦克原xy点 (m_x >= it->m_x && m_x < it->m_x + 20) && (m_y - 20 == it->m_y) || //判断坦克右xy点 (m_x + 40 > it->m_x&& m_x + 40 <= it->m_x + 20) && (m_y - 20 == it->m_y) ) //判断方块属性 && (it->prop == 0 || it->prop == 1) //判断地图边界范围 || (m_y - 20 < 0) ) return; break; case 'a': if ( ( //判断坦克原xy点 (m_y >= it->m_y && m_y < it->m_y + 20) && (m_x - 20 == it->m_x) || //判断坦克右xy点 (m_y + 40 > it->m_y && m_y + 40 <= it->m_y + 20) && (m_x - 20 == it->m_x) ) //方块属性 && (it->prop == 0 || it->prop == 1) //判断地图边界范围 || (m_x - 20 < 0) ) return; break; case 's': if ( ( //判断坦克原xy点 (m_x >= it->m_x && m_x < it->m_x + 20) && (m_y + 40 == it->m_y) || //判断坦克右xy点 (m_x + 40 > it->m_x&& m_x + 40 <= it->m_x + 20) && (m_y + 40 == it->m_y) ) //判断方块属性 && (it->prop == 0 || it->prop == 1) //判断地图边界范围 || (m_y + 60 > 600) ) return; break; case 'd': if ( ( //判断坦克原xy点 (m_y >= it->m_y && m_y < it->m_y + 20) && (m_x + 40 == it->m_x) || //判断坦克右xy点 (m_y + 40 > it->m_y&& m_y + 40 <= it->m_y + 20) && (m_x + 40 == it->m_x) ) //方块属性 && (it->prop == 0 || it->prop == 1) //判断地图边界范围 || (m_x + 60 > 900) ) return; break; } } //根据key1值修改坦克坐标 switch (key1) { case 'w': m_y -= 20; break; case 'a': m_x -= 20; break; case 's': m_y += 20; break; case 'd': m_x += 20; break; } } //如果键值为j则发射炮弹,如果键值为wasd则移动坦克 if (key1 == 'j') launch(); else { printtank(key1); //根据键值输出显示坦克 b_m_x = m_x + 18; //移动时也重置子弹坐标 b_m_y = m_y + 18; //这里key1值不能重置为key2值 } //如果我军坦克被消灭,则被消灭次数+1,并重置坦克 if (m_health <= 0) { Fridienum++; m_x = 300; //坐标 m_y = 560; m_health = 100; //血量 } } }; //统计所有敌军坦克次数全局变量 int Endienum; //敌军坦克 class TankEnemy :public Tank { private: int pathsch; //路线方案 int contdir; bool Entankdie = true; //标记敌军坦克的死亡状态 public: //构造函数接收初始坦克坐标 TankEnemy(const int x ,const int y, const int pathsch) //构造函数初始化坦克坐标 { m_x = x; //敌方坦克初始坐标 m_y = y; b_m_x = m_x + 18; //坦克子弹坐标 b_m_x = m_x + 18; m_health = 300; //坦克血量 m_damage = 90; //坦克伤害 contdir = 0; this->pathsch = pathsch; //路线 path_1 = "坦克大战完整素材\敌方坦克上.png"; //赋值需要将源文件属性语言中符合模式改为否 path_2 = "坦克大战完整素材\敌方坦克下.png"; path_3 = "坦克大战完整素材\敌方坦克左.png"; path_4 = "坦克大战完整素材\敌方坦克右.png"; gettank(path_1);//输出一个坦克图片 } int getTankdamage() //获取坦克伤害 { return m_damage; } int getTankhealth() //获取坦克血量 { return m_health; } void setTankhealth(const int health) //设置坦克血量 { m_health = health; } bool getEntadist() //获取坦克的死亡状态 { return Entankdie; } void setpathsch(const int tanknum) //修改坦克行动路线 { switch (tanknum) //判断坦克编号 { case 1: pathsch = 5; //坦克1路线切换为路线2 break; case 2: pathsch = 6; break; case 3: pathsch = 7; break; case 4: pathsch = 8; break; } } //重置坦克 void setEntank(const int tanknum) { if (Entankdie == false && (pathsch == 5 || pathsch == 6 || pathsch == 7 || pathsch == 8)) return; //如果这个坦克的路线已经被修改过,且再次死亡,则不再重置 switch (tanknum) { case 1: m_x = 200, m_y = 40; contdir = 2; break; case 2: m_x = 720, m_y = 120; contdir = 3; break; case 3: m_x = 560, m_y = 120; contdir = 2; break; case 4: m_x = 80, m_y = 360; contdir = 2; } m_health = 300; Entankdie = true; } //坦克1第二路线 //直接攻击基地 void pathschfun5_1_2() { static bool temp = true; //临时变量用作标记 if(temp == true) contdir = 2; if (m_y == 560 && temp == true) //往右 contdir = 4; if (m_y == 560 && m_x == 240) { m_y = 560, m_x = 240; contdir = 0; temp = false; } } //坦克2路线2 void pathschfun6_2_2() { //720, 120 //需要改变两次方向 static bool temp = true; static bool temp2 = true; if (temp == true && temp2 == true) contdir = 3; //往左 if (m_x == 200 && temp == true && temp2 == true) //往下 contdir = 2; if (m_x == 200 && m_y == 560 && temp == true) { contdir = 4; //往右 temp2 = false; } if (m_y == 560 && m_x == 280) { m_y = 560, m_x = 280; contdir = 0; temp = false; } } //坦克3路线2 void pathschfun7_3_2() { static bool temp = true; if (temp == true) contdir = 2; //往下 if (m_y == 560 && temp == true) //往左 contdir = 3; if (m_y == 560 && m_x == 480) { m_y = 560, m_x = 480; contdir = 0; temp = false; } } //坦克4路线2 void pathschfun8_4_2() { static bool temp = true; if(temp == true) contdir = 2; if (m_y == 560 && temp == true) contdir = 4; if (m_x == 200 && m_y == 560) { m_x = 200, m_y = 560; contdir = 0; temp = false; } } //正常路线1 void pathschfun_1() { static bool temp = false; //临时变量辅助控制坦克行走路线 if (m_y == 480 && m_x == 200 && temp == true) //上 { b_m_x = m_x + 18; //重置子弹位置为坦克中间 b_m_y = m_y + 18; contdir = 1; return; } else if (m_y == 40 && m_x == 200) //下 { b_m_x = m_x + 18; b_m_y = m_y + 18; contdir = 2; temp = false; return; } else if (m_y == 480 && m_x == 200 && temp == false) //右 { b_m_x = m_x + 18; b_m_y = m_y + 18; contdir = 4; temp = true; return; } else if (m_x == 700 && m_y == 480) //左 { b_m_x = m_x + 18; b_m_y = m_y + 18; contdir = 3; return; } } //正常路线2 void pathschfun_2() { if (m_x == 720) { b_m_x = m_x + 18; b_m_y = m_y + 18; contdir = 3; return; } if (m_x <= 140) { b_m_x = m_x + 18; b_m_y = m_y + 18; contdir = 4; return; } } //正常路线3 void pathschfun_3() { if (m_y == 120) { b_m_x = m_x + 18; b_m_y = m_y + 18; contdir = 2; return; } if (m_y >= 480) { b_m_x = m_x + 18; b_m_y = m_y + 18; contdir = 1; return; } } //正常路线4 void pathschfun_4() { if (m_y == 360) { b_m_x = m_x + 18; b_m_y = m_y + 18; contdir = 2; return; } if (m_y >= 560) { b_m_x = m_x + 18; b_m_y = m_y + 18; contdir = 1; return; } } //敌军坦克自动移动 virtual void move(const list<mapstr>& tempves) { //根据contdir值,向不同方向移动 switch (contdir) { case 1: key2 = 'w'; //方向 gettank(path_1); //坦克图片 m_y -= 4; break; case 2: key2 = 's'; gettank(path_2); m_y += 4; break; case 3: key2 = 'a'; gettank(path_3); m_x -= 4; break; case 4: key2 = 'd'; gettank(path_4); m_x += 4; break; } launch(); //发射子弹 //不同pathsch不同路线 一个坦克两条路线 switch (pathsch) { case 1: pathschfun_1(); break; case 2: pathschfun_2(); break; case 3: pathschfun_3(); break; case 4: pathschfun_4(); break; case 5: pathschfun5_1_2(); break; case 6: pathschfun6_2_2(); break; case 7: pathschfun7_3_2(); break; case 8: pathschfun8_4_2(); } //敌军坦克被消灭 //如果坦克血量小于等于0,则将坦克从界面内移除 if (m_health <= 0) { Endienum++; //敌军坦克被消灭次数自增 Entankdie = false; //死亡状态为false m_x = -40,m_y = -40;//坦克被移除至页面外 b_m_x = m_x, b_m_y = m_y;//子弹跟随坦克 } } }; //敌军坦克数量 const int N = 4; //子弹命中检测 bool hittest(TankFriend& tank_f, TankEnemy* Etankarr, list<mapstr>& listmap) //参数:我方坦克对象,敌军坦克对象数组,地图list容器 { const int tanfirlau_x = tank_f.getlauch_x(); //友军坦克子弹x坐标 const int tanfirlau_y = tank_f.getlauch_y(); //友军坦克子弹y坐标 const int firtank_x = tank_f.getTank_x(); //友军坦克x坐标 const int firtank_y = tank_f.getTank_y(); //友军坦克y坐标 const int tankfirdam = tank_f.getTankdamage(); //友军坦克伤害 const int tankfirhea = tank_f.getTankhealth(); //友军坦克血量 for (int i = 0; i < N; i++) { //发射子弹需要判断两个点 //如果友军子弹和敌军坦克重合,敌军坦克血量减少,且友军坦克子弹坐标重置 if ((tanfirlau_x >= Etankarr[i].getTank_x() && tanfirlau_x <= Etankarr[i].getTank_x() + 40 && tanfirlau_y >= Etankarr[i].getTank_y() && tanfirlau_y <= Etankarr[i].getTank_y() + 40) || (tanfirlau_x + 4 >= Etankarr[i].getTank_x() && tanfirlau_x <= Etankarr[i].getTank_x() + 4 + 40 && tanfirlau_y >= Etankarr[i].getTank_y() + 4 && tanfirlau_y + 4 <= Etankarr[i].getTank_y() + 40)) { Etankarr[i].setTankhealth(Etankarr[i].getTankhealth() - tankfirdam); //血量减少 tank_f.exploed(); //友方坦克攻击导致子弹遇到对方的位置爆炸 tank_f.setlauch_xy(); //友军的炮弹坐标重置 } //如果敌军子弹和友军坦克重合,友军坦克血量减少,且敌军坦克子弹坐标重置 if ((Etankarr[i].getlauch_x() >= firtank_x && Etankarr[i].getlauch_x() <= firtank_x + 40 && Etankarr[i].getlauch_y() >= firtank_y && Etankarr[i].getlauch_y() <= firtank_y + 40) || (Etankarr[i].getlauch_x() + 4 >= firtank_x && Etankarr[i].getlauch_x() + 4 <= firtank_x + 40 && Etankarr[i].getlauch_y() + 4 >= firtank_y && Etankarr[i].getlauch_y() + 4 <= firtank_y + 40)) { tank_f.setTankhealth(tankfirhea - Etankarr[i].getTankdamage()); //友军坦克本身血量 - 敌军坦克伤害 Etankarr[i].exploed(); Etankarr[i].setlauch_xy(); //敌军的炮弹坐标重置 } //判断墙的状态 //包括我军坦克和敌军坦克子弹和墙的状态 for (list<mapstr>::iterator it = listmap.begin(); it != listmap.end(); it++) { //子弹碰到墙壁需要判断两个点 if ((tank_f.getlauch_x() >= it->m_x && tank_f.getlauch_x() <= it->m_x + 20 && tank_f.getlauch_y() >= it->m_y && tank_f.getlauch_y() <= it->m_y + 20) || (tank_f.getlauch_x() + 4 >= it->m_x && tank_f.getlauch_x() + 4 <= it->m_x + 20 && tank_f.getlauch_y() + 4 >= it->m_y && tank_f.getlauch_y() + 4 <= it->m_y + 20)) { switch (it->prop) { case 0: //砖块可以被删除 tank_f.exploed(); //子弹处发生爆炸 tank_f.setlauch_xy(); //子弹重置 listmap.erase(it); //删除被子弹击中的墙壁数据 break; case 1: //铁块会爆炸不会被删除 tank_f.exploed(); //子弹处发生爆炸 tank_f.setlauch_xy(); //子弹重置 break; case 2: //草块不会有作用 break; case 4: mapstr temp; temp.m_x = it->m_x; temp.m_y = it->m_y; temp.prop = 5; listmap.insert(it, temp); listmap.erase(it); //老鹰被攻击游戏结束 return true; } //最后break break; } if ((Etankarr[i].getlauch_x() >= it->m_x && Etankarr[i].getlauch_x() <= it->m_x + 20 && Etankarr[i].getlauch_y() >= it->m_y && Etankarr[i].getlauch_y() <= it->m_y + 20) || (Etankarr[i].getlauch_x() + 4 >= it->m_x && Etankarr[i].getlauch_x() + 4 <= it->m_x + 20 && Etankarr[i].getlauch_y() + 4 >= it->m_y && Etankarr[i].getlauch_y() + 4 <= it->m_y + 20)) { switch (it->prop) { case 0: //砖块可以被删除 Etankarr[i].exploed(); //子弹处发生爆炸 Etankarr[i].setlauch_xy(); //子弹重置 listmap.erase(it); //删除被子弹击中的墙壁数据 break; case 1: //铁块会爆炸不会被删除 Etankarr[i].exploed(); //子弹处发生爆炸 Etankarr[i].setlauch_xy(); //子弹重置 break; case 2: //草块不会有作用 break; case 4: mapstr temp; temp.m_x = it->m_x; temp.m_y = it->m_y; temp.prop = 5; listmap.insert(it, temp); listmap.erase(it); return true; } //最后break break; } } } return false; } //游戏开始界面 void initgamebegin() { //开始背景 PIMAGE gabegbaimg = newimage(); getimage(gabegbaimg,"坦克大战完整素材\开始游戏背景.jpg"); setimage(1000,600,gabegbaimg); putimage(0, 0, gabegbaimg); //开始按钮 PIMAGE gabegimg = newimage(); getimage(gabegimg, "坦克大战完整素材\开始游戏.png"); setimage(290, 210, gabegimg); putimage_withalpha (NULL, gabegimg, 305, 440); setfont(120,0,"楷体"); //设置字号,字体 setcolor(YELLOW); //设置文字颜色 setbkmode(1); //文字背景色透明 outtextxy(210, 100, "坦克大战"); //输出文字 mouse_msg msg; //接收开始游戏的鼠标信息 while (true) { msg = getmouse(); if (msg.is_left()) if (msg.x >= 305 && msg.y >= 440 && msg.x <= 305 + 290 && msg.y <= 440 + 210) break; delay_fps(50); } } //游戏胜利结束,全局函数 void gameovertrue() { cleardevice(); PIMAGE gameoverbackimg = newimage(); getimage(gameoverbackimg, "坦克大战完整素材\游戏胜利结束背景.jpg"); setimage(1000, 600, gameoverbackimg); putimage(0, 0, gameoverbackimg); //输出背景图片 PIMAGE gameoverimg = newimage(); getimage(gameoverimg, "坦克大战完整素材\胜利文字.png"); setimage(206, 107, gameoverimg); putimage_withalpha(NULL, gameoverimg, 347, 220); //透明格式输出游戏结束图片 delimage(gameoverbackimg); delimage(gameoverimg); //释放内存 getch(); getch(); } //主函数 int main() { initgraph(900, 600, INIT_RENDERMANUAL); //初始化图形界面 setcaption("C++ EGE坦克大战"); //设置窗口标题 initgamebegin(); //游戏开始界面 TankFriend tank_f; //我方坦克 TankEnemy tank_e_1(200, 40, 1); //敌方坦克 1 TankEnemy tank_e_2(720, 120, 2); //敌方坦克 2 TankEnemy tank_e_3(560, 120, 3); //敌方坦克 3 TankEnemy tank_e_4(80, 360, 4); //敌方坦克 4 //敌军坦克数组 TankEnemy Etankarr[N] = { tank_e_1, tank_e_2,tank_e_3,tank_e_4 }; Mymap map_1; //地图 //获取地图信息 list<mapstr> listmap = map_1.getmapves(); bool gameoverstat = false; //判断游戏结束状态变量,默认失败 bool basestat = false; //判断基地老鹰的状态,为真则游戏失败 //游戏循环 while (true) { cleardevice(); //清屏 //三条生命 被消灭三次时结束游戏 if (tank_f.getFridienumfun() < 3) tank_f.move(listmap); else break; //敌军坦克数组循环 for (int i = 0; i < N; i++) { if(Etankarr[i].getEntadist() == true) //坦克必须存活时才会调用移动函数 Etankarr[i].move(listmap); //敌方坦克 else { switch (Endienum) { case 3: //坦克死亡时,且敌军总被消灭次数为3时,已被消灭坦克复活 Etankarr[i].setEntank(i + 1); //重置已坦克被消灭 break; case 4: case 6: case 8: case 10: Etankarr[i].setEntank(i + 1); //重置坦克 Etankarr[i].setpathsch(i + 1); //修改坦克路线 } } } map_1.printmap(listmap); //输出地图 basestat = hittest(tank_f, Etankarr ,listmap); //子弹命中坦克检测 if (basestat) break; //如果basestat为true则游戏按失败break if (Endienum > 10) //消灭敌军达10则游戏胜利 { gameoverstat = true; break; } delay_fps(62); } //根据游戏结束状态,调用结束函数 gameoverstat ? gameovertrue(): gameoverfalse(); //游戏结束 return 0; } //设置图片宽高全局函数 void setimage(int pwidth, int pheight, PIMAGE img_1) { int whidth = getwidth(img_1), height = getheight(img_1);//获取当前img图像对象的宽高 PIMAGE img_2 = newimage(pwidth, pheight); //创建一个新的图像对象,这个新的图像对象的宽高为 //要重新设置的图像的宽高 putimage(img_2, 0, 0, pwidth, pheight, img_1, 0, 0, whidth, height); //将原本img中的图像拉伸绘制到img_2中 getimage(img_1, img_2, 0, 0, pwidth, pheight); //img再获取img_2中的图像 delimage(img_2); //使用完毕将释放掉 }
不足之处:
参照标准的坦克大战,子弹在攻击砖块时,如果子弹正好打中两个砖块,则两个砖块同时被消灭,这个效果我在程序中做不出来。只能是用一个一个地消灭代替了。
在按下键键值不是wasdj时和坦克碰到墙壁时坦克会闪的问题,也暂时没有找到解决办法。
因为初学C++,所以我在类和对象的使用上面还有着很多很多的缺陷和不规范的地方。
还有关于地图的问题,因为我没有经验,所以不知道该怎么简便地创造一个游戏地图,在刚开始的时候还在为用什么实现地图而犹豫过,最后还是选择了list容器逐个将地图元素塞进去,因为考虑到list容器插入和删除数据很快。
我知道在程序中很多地方我都写的极为地不合理,以至于程序运行效率非常低(从我的CPU占用看出来的),但是我会继续努力,继续学习,争取早日解决这些问题。
欢迎大家提出批评和建议。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持靠谱客。
最后
以上就是开放乌冬面最近收集整理的关于C++实现坦克大战小游戏EGE图形界面的全部内容,更多相关C++实现坦克大战小游戏EGE图形界面内容请搜索靠谱客的其他文章。
发表评论 取消回复