-
-
Notifications
You must be signed in to change notification settings - Fork 2.3k
/
alieninvasion.py
249 lines (245 loc) · 10.1 KB
/
alieninvasion.py
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
'''
Function:
外星人入侵小游戏
Author:
Charles
微信公众号:
Charles的皮卡丘
'''
import os
import random
import pygame
from ...utils import QuitGame
from ..base import PygameBaseGame
from .modules import aircraftSprite, ufoSprite, enemySprite, myBulletSprite, enemyBulletSprite, showLife, showText, endInterface
'''配置类'''
class Config():
# 根目录
rootdir = os.path.split(os.path.abspath(__file__))[0]
# 一些颜色
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
GREEN = (50, 250, 5)
RED = (255, 0, 0)
# FPS
FPS = 60
# 背景音乐路径
BGM_PATH = os.path.join(rootdir, 'resources/bgm.mp3')
# 最高分保存路径
HIGHEST_SCORE_SAVE_PATH = os.path.join(rootdir, 'score')
# 屏幕大小
SCREENSIZE = (800, 600)
# 标题
TITLE = '外星人入侵小游戏 —— Charles的皮卡丘'
# 字体路径
FONT_PATHS_DICT = {
'default18': {'name': 'arial', 'size': 18, 'system_font': True},
'default30': {'name': 'arial', 'size': 30, 'system_font': True},
}
'''外星人入侵小游戏'''
class AlienInvasionGame(PygameBaseGame):
game_type = 'alieninvasion'
def __init__(self, **kwargs):
self.cfg = Config
super(AlienInvasionGame, self).__init__(config=self.cfg, **kwargs)
'''运行游戏'''
def run(self):
# 初始化
screen, resource_loader, cfg = self.screen, self.resource_loader, self.cfg
# 播放背景音乐
resource_loader.playbgm()
# 游戏主循环
while True:
is_win = self.GamingInterface(screen, cfg, resource_loader)
endInterface(screen, cfg.BLACK, is_win, cfg, resource_loader)
'''开始游戏'''
def GamingInterface(self, screen, cfg, resource_loader):
clock = pygame.time.Clock()
# 加载字体
font = resource_loader.fonts['default18']
if not os.path.isfile('score'):
f = open(cfg.HIGHEST_SCORE_SAVE_PATH, 'w')
f.write('0')
f.close()
with open(cfg.HIGHEST_SCORE_SAVE_PATH, 'r') as f:
highest_score = int(f.read().strip())
# 敌方
enemies_group = pygame.sprite.Group()
for i in range(55):
if i < 11:
enemy = enemySprite('small', i, cfg.WHITE, cfg.WHITE)
elif i < 33:
enemy = enemySprite('medium', i, cfg.WHITE, cfg.WHITE)
else:
enemy = enemySprite('large', i, cfg.WHITE, cfg.WHITE)
enemy.rect.x = 85 + (i % 11) * 50
enemy.rect.y = 120 + (i // 11) * 45
enemies_group.add(enemy)
boomed_enemies_group = pygame.sprite.Group()
en_bullets_group = pygame.sprite.Group()
ufo = ufoSprite(color=cfg.RED)
# 我方
myaircraft = aircraftSprite(color=cfg.GREEN, bullet_color=cfg.WHITE)
my_bullets_group = pygame.sprite.Group()
# 用于控制敌方位置更新
# --移动一行
enemy_move_count = 24
enemy_move_interval = 24
enemy_move_flag = False
# --改变移动方向(改变方向的同时集体下降一次)
enemy_change_direction_count = 0
enemy_change_direction_interval = 60
enemy_need_down = False
enemy_move_right = True
enemy_need_move_row = 6
enemy_max_row = 5
# 用于控制敌方发射子弹
enemy_shot_interval = 100
enemy_shot_count = 0
enemy_shot_flag = False
# 游戏进行中
running = True
is_win = False
# 主循环
while running:
screen.fill(cfg.BLACK)
for event in pygame.event.get():
# --点右上角的X或者按Esc键退出游戏
if event.type == pygame.QUIT:
QuitGame()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
QuitGame()
# --射击
if event.type == pygame.MOUSEBUTTONDOWN:
my_bullet = myaircraft.shot()
if my_bullet:
my_bullets_group.add(my_bullet)
# --我方子弹与敌方/UFO碰撞检测
for enemy in enemies_group:
if pygame.sprite.spritecollide(enemy, my_bullets_group, True, None):
boomed_enemies_group.add(enemy)
enemies_group.remove(enemy)
myaircraft.score += enemy.reward
if pygame.sprite.spritecollide(ufo, my_bullets_group, True, None):
ufo.is_dead = True
myaircraft.score += ufo.reward
# --更新并画敌方
# ----敌方子弹
enemy_shot_count += 1
if enemy_shot_count > enemy_shot_interval:
enemy_shot_flag = True
enemies_survive_list = [enemy.number for enemy in enemies_group]
shot_number = random.choice(enemies_survive_list)
enemy_shot_count = 0
# ----敌方移动
enemy_move_count += 1
if enemy_move_count > enemy_move_interval:
enemy_move_count = 0
enemy_move_flag = True
enemy_need_move_row -= 1
if enemy_need_move_row == 0:
enemy_need_move_row = enemy_max_row
enemy_change_direction_count += 1
if enemy_change_direction_count > enemy_change_direction_interval:
enemy_change_direction_count = 1
enemy_move_right = not enemy_move_right
enemy_need_down = True
# ----每次下降提高移动和射击速度
enemy_move_interval = max(15, enemy_move_interval-3)
enemy_shot_interval = max(50, enemy_move_interval-10)
# ----遍历更新
for enemy in enemies_group:
if enemy_shot_flag:
if enemy.number == shot_number:
en_bullet = enemy.shot()
en_bullets_group.add(en_bullet)
if enemy_move_flag:
if enemy.number in range((enemy_need_move_row-1)*11, enemy_need_move_row*11):
if enemy_move_right:
enemy.update('right', cfg.SCREENSIZE[1])
else:
enemy.update('left', cfg.SCREENSIZE[1])
else:
enemy.update(None, cfg.SCREENSIZE[1])
if enemy_need_down:
if enemy.update('down', cfg.SCREENSIZE[1]):
running = False
is_win = False
enemy.change_count -= 1
enemy.draw(screen)
enemy_move_flag = False
enemy_need_down = False
enemy_shot_flag = False
# ----敌方爆炸特效
for boomed_enemy in boomed_enemies_group:
if boomed_enemy.boom(screen):
boomed_enemies_group.remove(boomed_enemy)
del boomed_enemy
# --敌方子弹与我方飞船碰撞检测
if not myaircraft.one_dead:
if pygame.sprite.spritecollide(myaircraft, en_bullets_group, True, None):
myaircraft.one_dead = True
if myaircraft.one_dead:
if myaircraft.boom(screen):
myaircraft.resetBoom()
myaircraft.num_life -= 1
if myaircraft.num_life < 1:
running = False
is_win = False
else:
# ----更新飞船
myaircraft.update(cfg.SCREENSIZE[0])
# ----画飞船
myaircraft.draw(screen)
if (not ufo.has_boomed) and (ufo.is_dead):
if ufo.boom(screen):
ufo.has_boomed = True
else:
# ----更新UFO
ufo.update(cfg.SCREENSIZE[0])
# ----画UFO
ufo.draw(screen)
# --画我方飞船子弹
for bullet in my_bullets_group:
if bullet.update():
my_bullets_group.remove(bullet)
del bullet
else:
bullet.draw(screen)
# --画敌方子弹
for bullet in en_bullets_group:
if bullet.update(cfg.SCREENSIZE[1]):
en_bullets_group.remove(bullet)
del bullet
else:
bullet.draw(screen)
if myaircraft.score > highest_score:
highest_score = myaircraft.score
# --得分每增加2000我方飞船增加一条生命
if (myaircraft.score % 2000 == 0) and (myaircraft.score > 0) and (myaircraft.score != myaircraft.old_score):
myaircraft.old_score = myaircraft.score
myaircraft.num_life = min(myaircraft.num_life + 1, myaircraft.max_num_life)
# --敌人都死光了的话就胜利了
if len(enemies_group) < 1:
is_win = True
running = False
# --显示文字
# ----当前得分
showText(screen, 'SCORE: ', cfg.WHITE, font, 200, 8)
showText(screen, str(myaircraft.score), cfg.WHITE, font, 200, 24)
# ----敌人数量
showText(screen, 'ENEMY: ', cfg.WHITE, font, 370, 8)
showText(screen, str(len(enemies_group)), cfg.WHITE, font, 370, 24)
# ----历史最高分
showText(screen, 'HIGHEST: ', cfg.WHITE, font, 540, 8)
showText(screen, str(highest_score), cfg.WHITE, font, 540, 24)
# ----FPS
showText(screen, 'FPS: ' + str(int(clock.get_fps())), cfg.RED, font, 8, 8)
# --显示剩余生命值
showLife(screen, myaircraft.num_life, cfg.GREEN)
pygame.display.update()
clock.tick(cfg.FPS)
with open(cfg.HIGHEST_SCORE_SAVE_PATH, 'w') as f:
f.write(str(highest_score))
return is_win