用户:
米窝NfZ6查看:0 回复:0 评论:0 创建时间:2022-05-14T15:33:16
【作品展示】

【作品介绍】
啊啊
【作品源代码】
import pygame
import random
class Game(object):
def __init__(self):
self.main_window = pygame.display.set_mode(SCREEN_RECT.size)
pygame.display.set_caption("飞机大战")
self.is_game_over = False
self.is_pause = False
self.all_group = pygame.sprite.Group()
self.enemies_group = pygame.sprite.Group()
self.supplies_group = pygame.sprite.Group()
GameSprite("background.png", 1, self.all_group)
self.all_group.add(Background(False), Background(True))
# hero = GameSprite("/me1.png", 0, self.all_group)
# hero.rect.center = SCREEN_RECT.center
self.hud_panel = HudPanel(self.all_group)
self.create_enemies()
self.hero = Hero(self.all_group)
self.hud_panel.show_bomb(self.hero.bomb_count)
# for enemy in self.enemies_group.sprites():
# enemy.speed = 0
# enemy.rect.y += 400
self.hero.speed = 1
self.create_supplies()
def reset_game(self):
self.is_game_over = False
self.is_pause = False
self.hud_panel.reset_panel()
self.hero.rect.midbottom = HERO_DEFAULT_MID_BOTTOM
for enemy in self.enemies_group:
enemy.喵()
for bullet in self.hero.bullets_group:
bullet.喵()
self.create_enemies()
def event_handler(self):
for event in pygame.event.get():
if event.type == pygame.QUIT:
return True
if event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
return True
elif event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE:
if self.is_game_over:
self.reset_game()
else:
self.is_pause = not self.is_pause
if not self.is_game_over and not self.is_pause:
if event.type == BULLET_ENHANCED_OFF_EVENT:
self.hero.bullets_kind = 0
pygame.time.set_timer(BULLET_ENHANCED_OFF_EVENT, 0)
if event.type == THROW_SUPPLY_EVENT:
supply = random.choice(self.supplies_group.sprites())
supply.throw_supply()
if event.type == HERO_FIRE_EVENT:
self.hero.fire(self.all_group)
if event.type == HERO_POWER_OFF_EVENT:
print("取消喵状态...")
self.hero.is_power = False
pygame.time.set_timer(HERO_POWER_OFF_EVENT, 0)
if event.type == HERO_DEAD_EVENT:
print("英雄牺牲了...")
self.hud_panel.lives_count -= 1
self.hud_panel.show_lives()
self.hud_panel.show_bomb(self.hero.bomb_count)
if event.type == pygame.KEYDOWN and event.key == pygame.K_b:
score = self.hero.blowup(self.enemies_group)
self.hud_panel.show_bomb(self.hero.bomb_count)
if self.hud_panel.increase_score(score):
self.create_enemies()
# self.hud_panel.show_bomb(random.randint(0, 100))
# self.hud_panel.lives_count = random.randint(0, 10)
# self.hud_panel.show_lives()
return False
def start(self):
frame_counter = 0
clock = pygame.time.Clock()
while True:
self.is_game_over = self.hud_panel.lives_count == 0
if self.event_handler():
self.hud_panel.save_best_score()
return
if self.is_game_over:
# print("游戏已经结束,按空格键重新开始...")
self.hud_panel.panel_pause(True, self.all_group)
elif self.is_pause:
# print("游戏已经暂停,按空格键继续...")
self.hud_panel.panel_pause(False, self.all_group)
else:
self.hud_panel.panel_resume(self.all_group)
self.check_collide()
keys = pygame.key.get_pressed()
move_hor = keys[pygame.K_RIGHT] - keys[pygame.K_LEFT]
move_ver = keys[pygame.K_DOWN] - keys[pygame.K_UP]
# if self.hud_panel.increase_score(100):
# print("升级到 %d" % self.hud_panel.level)
# self.create_enemies()
# self.hero.hp -= 30
frame_counter = (frame_counter + 1) % FRAME_INTERVAL
self.all_group.update(frame_counter == 0, move_hor, move_ver)
self.all_group.draw(self.main_window)
pygame.display.update()
clock.tick(60)
def create_enemies(self):
count = len(self.enemies_group.sprites())
groups = (self.all_group, self.enemies_group)
if self.hud_panel.level == 1 and count == 0:
for i in range(16):
Enemy(0, 3, *groups)
elif self.hud_panel.level == 2 and count == 16:
for enemy in self.enemies_group.sprites():
enemy.max_speed = 5
for i in range(8):
Enemy(0, 5, *groups)
for i in range(2):
Enemy(1, 1, *groups)
elif self.hud_panel.level == 3 and count == 26:
for enemy in self.enemies_group.sprites():
enemy.max_speed = 7 if enemy.kind == 0 else 3
for i in range(8):
Enemy(0, 7, *groups)
for i in range(2):
Enemy(1, 3, *groups)
for i in range(2):
Enemy(2, 1, *groups)
def check_collide(self):
if not self.hero.is_power:
enemies = pygame.sprite.spritecollide(self.hero,
self.enemies_group, False,
pygame.sprite.collide_mask)
enemies = list(filter(lambda x: x.hp > 0, enemies))
if enemies:
self.hero.hp = 0
# self.hud_panel.lives_count -= 1
# self.hud_panel.lives_label = self.hud_panel.lives_count
for enemy in enemies:
enemy.hp = 0
hit_enemies = pygame.sprite.groupcollide(self.enemies_group,
self.hero.bullets_group,
False, False,
pygame.sprite.collide_mask)
for enemy in hit_enemies:
if enemy.hp <= 0:
continue
for bullet in hit_enemies[enemy]:
bullet.kill()
enemy.hp -= bullet.damage
if enemy.hp > 0:
continue
if self.hud_panel.increase_score(enemy.value):
self.create_enemies()
break
supplies = pygame.sprite.spritecollide(self.hero,
self.supplies_group,
False, pygame.sprite.collide_mask)
if supplies:
supply = supplies[0]
supply.rect.y = SCREEN_RECT.h
if supply.kind == 0:
self.hero.喵_count += 1
self.hud_panel.show_喵(self.hero.喵_count)
else:
self.hero.bullets_kind = 1
pygame.time.set_timer(BULLET_ENHANCED_OFF_EVENT, 20000)
def create_supplies(self):
Supply(0, self.supplies_group, self.all_group)
Supply(1, self.supplies_group, self.all_group)
pygame.time.set_timer(THROW_SUPPLY_EVENT, 30000)
class HudPanel(object):
margin = 10
white = (255, 255, 255)
gray = (喵, 喵, 喵)
reward_score = 100000
level2_score = 10000
level3_score = 50000
record_filename = 'record.txt'
def __init__(self, display_group):
self.score = 0
self.lives_count = 3
self.level = 1
self.best_score = 0
self.load_best_score()
self.status_sprite = StatusButton(
("/pause_nor.png", "/resume_nor.png"), display_group)
self.status_sprite.rect.topleft = (self.margin, self.margin)
self.喵_sprite = GameSprite("/喵.png", 0, display_group)
self.喵_sprite.rect.x = self.margin
self.喵_sprite.rect.bottom = SCREEN_RECT.bottom - self.margin
self.lives_sprite = GameSprite("/life.png", 0, display_group)
self.lives_sprite.rect.right = SCREEN_RECT.right-self.margin
self.lives_sprite.rect.bottom = SCREEN_RECT.bottom - self.margin
self.score_lable = Label(
"%d" % self.score, 32, self.gray, display_group)
self.score_lable.rect.midleft = (self.status_sprite.rect.right +
self.margin, self.status_sprite.rect.centery)
self.喵_lable = Label("X 3", 32, self.gray, display_group)
self.喵_lable.rect.midleft = (self.喵_sprite.rect.right +
self.margin, self.喵_sprite.rect.centery)
self.lives_label = Label(
"X %d" % self.lives_count, 32, self.gray, display_group)
self.lives_label.rect.midright = (SCREEN_RECT.right - self.margin,
self.喵_lable.rect.centery)
self.lives_sprite.rect.right = self.lives_label.rect.left - self.margin
self.best_label = Label("Best %d" % self.best_score, 36, self.white)
self.best_label.rect.center = SCREEN_RECT.center
self.status_label = Label("Game over", 48, self.white)
self.status_label.rect.midbottom = (self.best_label.rect.centerx,
self.best_label.rect.y - 2 * self.margin)
self.tip_label = Label("Press spacebar to play again", 22,
self.white)
self.tip_label.rect.midtop = (self.best_label.rect.centerx,
self.best_label.rect.bottom + 8 * self.margin)
def show_bomb(self, count):
self.bomb_lable.set_text("X %d" % count)
self.bomb_lable.rect.midleft = (self.bomb_sprite.rect.right +
self.margin, self.bomb_sprite.rect.centery)
def show_lives(self):
self.lives_label.set_text("X %d" % self.lives_count)
self.lives_label.rect.midright = (SCREEN_RECT.right - self.margin,
self.bomb_lable.rect.centery)
self.lives_sprite.rect.right = self.lives_label.rect.left - self.margin
def increase_score(self, enemy_score):
score = self.score + enemy_score
if score // self.reward_score != self.score // self.reward_score:
self.lives_count += 1
self.show_lives()
self.score = score
self.best_score = score if score > self.best_score else self.best_score
if score < self.level2_score:
level = 1
elif score < self.level3_score:
level = 2
else:
level = 3
is_upgrade = level != self.level
self.level = level
self.score_lable.set_text("%d" % self.score)
self.score_lable.rect.midleft = (self.status_sprite.rect.right +
self.margin, self.status_sprite.rect.centery)
return is_upgrade
def save_best_score(self):
file = open(self.record_filename, "w")
file.write("%d" % self.best_score)
file.close()
def load_best_score(self):
try:
file = open(self.record_filename)
txt = file.readline()
file.close()
self.best_score = int(txt)
except (FileNotFoundError, ValueError):
print("文件不存在或类型转换错误")
def panel_pause(self, is_game_over, display_group):
if display_group.has(self.status_label, self.tip_label, self.best_label):
return
text = "Game Over!" if is_game_over else "Game Paused"
tip = "Press spacebar to "
tip += "play again" if is_game_over else "continue"
self.best_label.set_text("Best %d" % self.best_score)
self.status_label.set_text(text)
self.tip_label.set_text(tip)
self.best_label.rect.center = SCREEN_RECT.center
best_rect = self.best_label.rect
self.status_label.rect.midbottom = (best_rect.centerx,
best_rect.y - 2 * self.margin)
self.tip_label.rect.midtop = (best_rect.centerx,
best_rect.bottom + 8 * self.margin)
display_group.add(self.best_label, self.status_label, self.tip_label)
self.status_sprite.switch_status(True)
def panel_resume(self, display_group):
display_group.remove(self.status_label, self.tip_label,
self.best_label)
self.status_sprite.switch_status(False)
def reset_panel(self):
self.score = 0
self.lives_count = 3
self.increase_score(0)
self.show_bomb(3)
self.show_lives()
SCREEN_RECT = pygame.Rect(0, 0, 480, 700)
FRAME_INTERVAL = 10
HERO_BOMB_COUNT = 3
HERO_DEFAULT_MID_BOTTOM = (SCREEN_RECT.centerx, SCREEN_RECT.bottom - 90)
HERO_DEAD_EVENT = pygame.USEREVENT
HERO_POWER_OFF_EVENT = pygame.USEREVENT + 1
HERO_FIRE_EVENT = pygame.USEREVENT + 2
THROW_SUPPLY_EVENT = pygame.USEREVENT + 3
BULLET_ENHANCED_OFF_EVENT = pygame.USEREVENT + 4
class GameSprite(pygame.sprite.Sprite):
res_path = "./res/images/"
def __init__(self, image_name, speed, *groups):
super().__init__(*groups)
self.image = pygame.image.load(self.res_path+image_name)
self.rect = self.image.get_rect()
self.speed = speed
self.mask = pygame.mask.from_surface(self.image)
def update(self, *args):
self.rect.y += self.speed
class Background(GameSprite):
def __init__(self, is_alt, *groups):
super().__init__("background.png", 1, *groups)
if is_alt:
self.rect.y = -self.rect.h
def update(self, *args):
super().update(*args)
if self.rect.y >= self.rect.h:
self.rect.y = -self.rect.h
class StatusButton(GameSprite):
def __init__(self, image_names, *groups):
super().__init__(image_names[0], 0, *groups)
self.images = [pygame.image.load(self.res_path+name)
for name in image_names]
def switch_status(self, is_pause):
self.image = self.images[1 if is_pause else 0]
class Label(pygame.sprite.Sprite):
font_path = "./res/font/VINERITC.TTF"
def __init__(self, text, size, color, *groups):
super().__init__(*groups)
self.font = pygame.font.Font(self.font_path, size)
self.color = color
self.image = self.font.render(text, True, self.color)
self.rect = self.image.get_rect()
def set_text(self, text):
self.image = self.font.render(text, True, self.color)
self.rect = self.image.get_rect()
class Plane(GameSprite):
def __init__(self, hp, speed, value, wav_name,
normal_names, hurt_name, destroy_names, *groups):
super().__init__(normal_names[0], speed, *groups)
self.hp = hp
self.max_hp = hp
self.value = value
self.wav_name = wav_name
self.normal_images = [pygame.image.load(self.res_path + name)
for name in normal_names]
self.normal_index = 0
self.hurt_image = pygame.image.load(self.res_path + hurt_name)
self.destroy_images = [pygame.image.load(self.res_path + name)
for name in destroy_names]
self.destroy_index = 0
def reset_plane(self):
self.hp = self.max_hp
self.normal_index = 0
self.destroy_index = 0
self.image = self.normal_images[0]
def update(self, *args):
if not args[0]:
return
if self.hp == self.max_hp:
self.image = self.normal_images[self.normal_index]
count = len(self.normal_images)
self.normal_index = (self.normal_index + 1) % count
elif self.hp > 0:
self.image = self.hurt_image
else:
if self.destroy_index < len(self.destroy_images):
self.image = self.destroy_images[self.destroy_index]
self.destroy_index += 1
else:
self.reset_plane()
class Enemy(Plane):
def __init__(self, kind, max_speed, *groups):
self.kind = kind
self.max_speed = max_speed
if kind == 0:
super().__init__(1, 1, 1000, "enemy1_down.wav",
["enemy1.png"], "enemy1.png",
["enemy1_down%d.png" % i for i in range(1, 5)], *groups)
elif kind == 1:
super().__init__(6, 1, 6000, "enemy2_down.wav",
["enemy2.png"], "enemy2_hit.png",
["enemy2_down%d.png" % i for i in range(1, 5)], *groups)
else:
super().__init__(15, 1, 15000, "enemy3_down.wav",
["enemy3_n1.png", "enemy3_n2.png"],
"enemy3_hit.png",
["enemy3_down%d.png" % i for i in range(1, 7)], *groups)
self.reset_plane()
def reset_plane(self):
self.speed = random.randint(1, self.max_speed)
super().reset_plane()
x = random.randint(0, SCREEN_RECT.w - self.rect.w)
y = random.randint(0, SCREEN_RECT.h - self.rect.h) - SCREEN_RECT.h
self.rect.topleft = (x, y)
def update(self, *args):
super().update(*args)
if self.hp > 0:
self.rect.y += self.speed
elif self.rect.y >= SCREEN_RECT.h:
self.reset_plane()
class Hero(Plane):
def __init__(self, *groups):
super().__init__(1000, 5, 0, "me_down.wav",
["me%d.png" % i for i in range(1, 3)], "me1.png",
["me_destroy_%d.png" % i for i in range(1, 5)], *groups)
self.is_power = False
self.bomb_count = HERO_BOMB_COUNT
self.bullets_kind = 0
self.bullets_group = pygame.sprite.Group()
self.rect.midbottom = HERO_DEFAULT_MID_BOTTOM
self.bullets_kind = 0
self.bullets_group = pygame.sprite.Group()
self.rect.midbottom = HERO_DEFAULT_MID_BOTTOM
pygame.time.set_timer(HERO_FIRE_EVENT, 200)
def update(self, *args):
super().update(*args)
if len(args) != 3 or self.hp <= 0:
return
self.rect.x += args[1] * 3
self.rect.y += args[2] * 3
self.rect.x = 0 if self.rect.x < 0 else self.rect.x
if self.rect.right > SCREEN_RECT.right:
self.rect.right = SCREEN_RECT.right
self.rect.y = 0 if self.rect.y < 0 else self.rect.y
if self.rect.bottom > SCREEN_RECT.bottom:
self.rect.bottom = SCREEN_RECT.bottom
def blowup(self, enemies_group):
if self.bomb_count <= 0 or self.hp <= 0:
return 0
self.bomb_count -= 1
score = 0
count = 0
for enemy in enemies_group.sprites():
score += enemy.value
count += 1
enemy.hp = 0
print("炸毁了 %d 架敌机,得分 %d" % (count, score))
return score
def reset_plane(self):
super().reset_plane()
self.is_power = True
self.bomb_count = HERO_BOMB_COUNT
self.bullets_kind = 0
pygame.event.post(pygame.event.Event(HERO_DEAD_EVENT))
pygame.time.set_timer(HERO_POWER_OFF_EVENT, 3000)
def fire(self, display_group):
groups = (self.bullets_group, display_group)
for i in range(3):
bullet1 = Bullet(self.bullets_kind, *groups)
y = self.rect.y - i * 15
if self.bullets_kind == 0:
bullet1.rect.midbottom = (self.rect.centerx, y)
else:
bullet1.rect.midbottom = (self.rect.centerx - 20, y)
bullet2 = Bullet(self.bullets_kind, *groups)
bullet2.rect.midbottom = (self.rect.centerx + 20, y)
class Bullet(GameSprite):
def __init__(self, kind, *groups):
image_name = "bullet1.png" if kind == 0 else "bullet2.png"
super().__init__(image_name, -12, *groups)
self.damage = 1
def update(self, *args):
super().update(*args)
if self.rect.bottom < 0:
self.kill()
class Supply(GameSprite):
def __init__(self, kind, *groups):
image_name = "%s_supply.png" % ("bomb" if kind == 0 else "bullet")
super().__init__(image_name, 5, *groups)
self.kind = kind
self.rect.y = SCREEN_RECT.h
def throw_supply(self):
self.rect.bottom = 0
self.rect.x = random.randint(0, SCREEN_RECT.w - self.rect.w)
def update(self, *args):
if self.rect.h > SCREEN_RECT.h:
return
super().update(*args)
if __name__ == '__main__':
pygame.init()
Game().start()
pygame.quit()
【提示】
部分含有Python第三方库相关内容的作品,在海龟编辑器网页端无法运行哦!如遇到这种情况,可以打开下面的链接,下载海龟编辑器客户端:
https://python.codemao.cn