Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
255 changes: 174 additions & 81 deletions bin/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,46 @@
from src.enemy import SmallEnemy
from src.bullet import Bullet

# 初始化字体
pygame.font.init()
try:
# 尝试使用系统中文字体
font = pygame.font.SysFont('microsoftyaheimicrosoftyaheiui', 36)
except:
try:
# 备选方案:使用其他常见中文字体
font = pygame.font.SysFont(['simsunnsimsun', 'microsoftyahei', 'simhei'], 36)
except:
# 如果都失败了,使用系统默认字体
font = pygame.font.Font(None, 36)

bg_size = 480, 852 # 初始化游戏背景大小(宽, 高)
screen = pygame.display.set_mode(bg_size) # 设置背景对话框
pygame.display.set_caption("飞机大战") # 设置标题

background = pygame.image.load(os.path.join(BASE_DIR, "material/image/background.png")) # 加载背景图片,并设置为不透明

# 创建退出按钮
exit_button = pygame.Rect(bg_size[0] - 100, 10, 80, 30)
exit_text = font.render("Exit", True, (255, 255, 255))
exit_text_rect = exit_text.get_rect(center=exit_button.center)

# 结束对话框
game_over_dialog = pygame.Surface((300, 200))
game_over_dialog.fill((0, 0, 0))
game_over_dialog.set_alpha(200)
game_over_rect = game_over_dialog.get_rect(center=(bg_size[0]//2, bg_size[1]//2))

# 失败对话框
game_fail_dialog = pygame.Surface((300, 200))
game_fail_dialog.fill((0, 0, 0))
game_fail_dialog.set_alpha(200)
game_fail_rect = game_fail_dialog.get_rect(center=(bg_size[0]//2, bg_size[1]//2))

#退出确定键
confirm_button = pygame.Rect(game_over_rect.width//2 - 40, 120, 80, 30)
confirm_text = font.render("ensure", True, (255, 255, 255))
confirm_text_rect = confirm_text.get_rect(center=confirm_button.center)

# 血槽颜色绘制
color_black = (0, 0, 0)
Expand Down Expand Up @@ -45,6 +78,7 @@ def main():
# 响应音乐
pygame.mixer.music.play(-1) # loops 接收该参数, -1 表示无限循环(默认循环播放一次)
running = True
game_over = False
switch_image = False # 切换飞机的标识位(使飞机具有喷气式效果)
delay = 60 # 对一些效果进行延迟, 效果更好一些

Expand All @@ -58,113 +92,172 @@ def main():
e1_destroy_index = 0
me_destroy_index = 0

score = 0 # 初始化得分
final_score = 0

# 定义子弹实例化个数
bullet1 = []
bullet_num = 6
for i in range(bullet_num):
bullet1.append(Bullet(our_plane.rect.midtop))

while running:

# 绘制背景图
screen.blit(background, (0, 0))



# 微信的飞机貌似是喷气式的, 那么这个就涉及到一个帧数的问题
clock = pygame.time.Clock()
clock.tick(60)

# 绘制我方飞机的两种不同的形式
if not delay % 3:
switch_image = not switch_image

for each in small_enemies:
if each.active:
# 随机循环输出小飞机敌机
each.move()
screen.blit(each.image, each.rect)

pygame.draw.line(screen, color_black,
(each.rect.left, each.rect.top - 5),
(each.rect.right, each.rect.top - 5),
2)
energy_remain = each.energy / SmallEnemy.energy
if energy_remain > 0.2: # 如果血量大约百分之二十则为绿色,否则为红色
energy_color = color_green
if not game_over:
# 绘制我方飞机的两种不同的形式
if not delay % 3:
switch_image = not switch_image

for each in small_enemies:
if each.active:
# 随机循环输出小飞机敌机
each.move()
if each.rect.top >= bg_size[1]:
score -= 50 # 扣50分
each.active = False
each.reset()

screen.blit(each.image, each.rect)

pygame.draw.line(screen, color_black,
(each.rect.left, each.rect.top - 5),
(each.rect.right, each.rect.top - 5),
2)
energy_remain = each.energy / SmallEnemy.energy
if energy_remain > 0.2: # 如果血量大约百分之二十则为绿色,否则为红色
energy_color = color_green
else:
energy_color = color_red
pygame.draw.line(screen, energy_color,
(each.rect.left, each.rect.top - 5),
(each.rect.left + each.rect.width * energy_remain, each.rect.top - 5),
2)
else:
energy_color = color_red
pygame.draw.line(screen, energy_color,
(each.rect.left, each.rect.top - 5),
(each.rect.left + each.rect.width * energy_remain, each.rect.top - 5),
2)
else:
if e1_destroy_index == 0:
enemy1_down_sound.play()
screen.blit(each.destroy_images[e1_destroy_index], each.rect)
e1_destroy_index = (e1_destroy_index + 1) % 4
if e1_destroy_index == 0:
each.reset()

# 当我方飞机存活状态, 正常展示
if our_plane.active:
if switch_image:
screen.blit(our_plane.image_one, our_plane.rect)
if e1_destroy_index == 0:
enemy1_down_sound.play()
screen.blit(each.destroy_images[e1_destroy_index], each.rect)
e1_destroy_index = (e1_destroy_index + 1) % 4
if e1_destroy_index == 0:
each.reset()

# 当我方飞机存活状态, 正常展示
if our_plane.active:
if switch_image:
screen.blit(our_plane.image_one, our_plane.rect)
else:
screen.blit(our_plane.image_two, our_plane.rect)

# 飞机存活的状态下才可以发射子弹
if not (delay % 10): # 每十帧发射一颗移动的子弹
bullet_sound.play()
bullets = bullet1
bullets[bullet_index].reset(our_plane.rect.midtop)
bullet_index = (bullet_index + 1) % bullet_num

for b in bullets:
if b.active: # 只有激活的子弹才可能击中敌机
b.move()
screen.blit(b.image, b.rect)
enemies_hit = pygame.sprite.spritecollide(b, enemies, False, pygame.sprite.collide_mask)
if enemies_hit: # 如果子弹击中飞机
b.active = False
for e in enemies_hit:
e.active = False
score += 10 # 击中加分

if score < 0 or not our_plane.active:
game_over = True
final_score = score

# 毁坏状态绘制爆炸的场面
else:
screen.blit(our_plane.image_two, our_plane.rect)

# 飞机存活的状态下才可以发射子弹
if not (delay % 10): # 每十帧发射一颗移动的子弹
bullet_sound.play()
bullets = bullet1
bullets[bullet_index].reset(our_plane.rect.midtop)
bullet_index = (bullet_index + 1) % bullet_num

for b in bullets:
if b.active: # 只有激活的子弹才可能击中敌机
b.move()
screen.blit(b.image, b.rect)
enemies_hit = pygame.sprite.spritecollide(b, enemies, False, pygame.sprite.collide_mask)
if enemies_hit: # 如果子弹击中飞机
b.active = False # 子弹损毁
for e in enemies_hit:
e.active = False # 小型敌机损毁

# 毁坏状态绘制爆炸的场面
else:
if not (delay % 3):
screen.blit(our_plane.destroy_images[me_destroy_index], our_plane.rect)
me_destroy_index = (me_destroy_index + 1) % 4
if me_destroy_index == 0:
me_down_sound.play()
our_plane.reset()

# 调用 pygame 实现的碰撞方法 spritecollide (我方飞机如果和敌机碰撞, 更改飞机的存活属性)
enemies_down = pygame.sprite.spritecollide(our_plane, enemies, False, pygame.sprite.collide_mask)
if enemies_down:
our_plane.active = False
for row in enemies:
row.active = False
if not (delay % 3):
screen.blit(our_plane.destroy_images[me_destroy_index], our_plane.rect)
me_destroy_index = (me_destroy_index + 1) % 4
if me_destroy_index == 0:
me_down_sound.play()
our_plane.reset()

# 调用 pygame 实现的碰撞方法 spritecollide (我方飞机如果和敌机碰撞, 更改飞机的存活属性)
enemies_down = pygame.sprite.spritecollide(our_plane, enemies, False, pygame.sprite.collide_mask)
if enemies_down:
our_plane.active = False
game_over = True
final_score = score
for row in enemies:
row.active = False

# 获得用户所有的键盘输入序列(如果用户通过键盘发出"向上"的指令,其他类似)
key_pressed = pygame.key.get_pressed()
if key_pressed[K_w] or key_pressed[K_UP]:
our_plane.move_up()
if key_pressed[K_s] or key_pressed[K_DOWN]:
our_plane.move_down()
if key_pressed[K_a] or key_pressed[K_LEFT]:
our_plane.move_left()
if key_pressed[K_d] or key_pressed[K_RIGHT]:
our_plane.move_right()

# 响应用户的操作
for event in pygame.event.get():
if event.type == 12: # 如果用户按下屏幕上的关闭按钮,触发QUIT事件,程序退出
if event.type == QUIT: # 如果用户按下屏幕上的关闭按钮,触发QUIT事件,程序退出
pygame.quit()
sys.exit()
elif event.type == MOUSEBUTTONDOWN:
mouse_pos = event.pos
if exit_button.collidepoint(mouse_pos):
game_over = True
elif game_over and confirm_button.collidepoint(mouse_pos[0] - game_over_rect.left, mouse_pos[1] - game_over_rect.top):
pygame.quit()
sys.exit()

if delay == 0:
delay = 60
delay -= 1

# 获得用户所有的键盘输入序列(如果用户通过键盘发出“向上”的指令,其他类似)
key_pressed = pygame.key.get_pressed()
if key_pressed[K_w] or key_pressed[K_UP]:
our_plane.move_up()
if key_pressed[K_s] or key_pressed[K_DOWN]:
our_plane.move_down()
if key_pressed[K_a] or key_pressed[K_LEFT]:
our_plane.move_left()
if key_pressed[K_d] or key_pressed[K_RIGHT]:
our_plane.move_right()

# 绘制退出按钮
pygame.draw.rect(screen, (100, 100, 100), exit_button)
screen.blit(exit_text, exit_text_rect)

score_text = font.render(f"Score: {score}", True, (255, 255, 255))
screen.blit(score_text, (10, 10))

# 如果游戏结束,显示游戏结束对话框
if game_over:
# 游戏失败界面
if score < 0 or not our_plane.active:
# 绘制失败对话框
screen.blit(game_fail_dialog, game_fail_rect)

# 显示游戏结束文本
fail_text = font.render("Game Over!", True, (255, 255, 255))
screen.blit(fail_text, (game_fail_rect.centerx - 70, game_fail_rect.centery - 50))

# 显示最终得分
final_text = font.render(f"Final Score: {final_score}", True, (255, 255, 255))
screen.blit(final_text, (game_fail_rect.centerx - 90, game_fail_rect.centery - 10))

# 退出按钮
quit_btn = pygame.Rect(game_fail_rect.centerx - 40, game_fail_rect.centery + 30, 80, 30)
pygame.draw.rect(screen, (100, 100, 100), quit_btn)
quit_text = font.render("Quit", True, (255, 255, 255))
screen.blit(quit_text, (quit_btn.x + 15, quit_btn.y + 5))
else:
screen.blit(game_over_dialog, game_over_rect)
screen.blit(confirm_text, (game_over_rect.left + confirm_text_rect.left, game_over_rect.top + confirm_text_rect.top))
pygame.draw.rect(screen, (100, 100, 100), (game_over_rect.left + confirm_button.left, game_over_rect.top + confirm_button.top, confirm_button.width, confirm_button.height))
screen.blit(confirm_text, (game_over_rect.left + confirm_text_rect.left, game_over_rect.top + confirm_text_rect.top))
#退出界面文本
quit_text = font.render("Make ture to exit?", True, (255, 255, 255))
screen.blit(quit_text, (game_over_rect.centerx - 100, game_over_rect.centery - 50))
# 绘制图像并输出到屏幕上面
pygame.display.flip()

Expand Down
1 change: 1 addition & 0 deletions manage.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"""
环境: python3 + pygame
running 起来就可以打飞机了O(∩_∩)O~.
规则:击中得10分,被一架飞机进攻成功扣50分,和敌机相撞或分数少于0,则游戏失败,会被结束游戏
"""
main()

Expand Down
1 change: 0 additions & 1 deletion src/enemy.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
"""

from random import randint

import pygame


Expand Down
2 changes: 1 addition & 1 deletion src/plane.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ def move_right(self):
self.rect.right = self.width

def reset(self):
# 初始化飞机(飞机挂了, 初始化到初始位置)
# 初始化飞机(飞机挂了, 初始化到初始位置) 现在飞机被碰撞后会游戏结束
self.rect.left, self.rect.top = (self.width - self.rect.width) // 2, (self.height - self.rect.height - 60)
# 重置飞机的存活状态
self.active = True
Expand Down