diff --git a/planeshoot.py b/planeshoot.py new file mode 100644 index 0000000..e3b144b --- /dev/null +++ b/planeshoot.py @@ -0,0 +1,659 @@ +# 飞机游戏 +import pygame +import random +import os + +FPS = 60 +WIDTH = 500 +HEIGHT = 600 + +BLACK = (0, 0, 0) +WHITE = (255, 255, 255) +GREEN = (0, 255, 0) +RED = (255, 0, 0) +YELLOW = (255, 255, 0) + +# 游戏初始化 +pygame.init() +pygame.mixer.init() +screen = pygame.display.set_mode((WIDTH, HEIGHT)) +pygame.display.set_caption("第一个游戏") +clock = pygame.time.Clock() + +# 为游戏图片载入准备 +background_img = pygame.image.load(os.path.join("img", "background.png")).convert()#载入背景图片 +player_img = pygame.image.load(os.path.join("img", "player.png")).convert()#载入飞机图片 +player_mini_img = pygame.transform.scale(player_img, (25, 19))#载入飞机生命图片 +player_mini_img.set_colorkey(BLACK) +pygame.display.set_icon(player_mini_img) +enemy_img = pygame.image.load(os.path.join("img", "player.png")).convert() +bullet_img = pygame.image.load(os.path.join("img", "bullet.png")).convert()#载入子弹图片 +#载入石头图片 +rock_imgs = [] +for i in range(7): + rock_imgs.append(pygame.image.load(os.path.join("img", f"rock{i}.png")).convert()) +expl_anim = {} +expl_anim['lg'] = [] +expl_anim['sm'] = [] +expl_anim['player'] = []#载入爆炸图片 +for i in range(9): + expl_img = pygame.image.load(os.path.join("img", f"expl{i}.png")).convert() + expl_img.set_colorkey(BLACK) + expl_anim['lg'].append(pygame.transform.scale(expl_img, (75, 75))) + expl_anim['sm'].append(pygame.transform.scale(expl_img, (30, 30))) + player_expl_img = pygame.image.load(os.path.join("img", f"player_expl{i}.png")).convert() + player_expl_img.set_colorkey(BLACK) + expl_anim['player'].append(player_expl_img) +power_imgs = {}#载入掉落物品图片 +power_imgs['shield'] = pygame.image.load(os.path.join("img", "shield.png")).convert() +power_imgs['gun'] = pygame.image.load(os.path.join("img", "gun.png")).convert() +power_imgs['body'] = pygame.image.load(os.path.join("img", "p2341.png")).convert() +#读档准备 +score=0 +score1=0 +score2=0 +plant_lives=0 +plant2_lives=0 +plant_healths=0 +plant2_healths=0 +load_s=False + +# 载入音乐 +shoot_sound = pygame.mixer.Sound(os.path.join("sound", "shoot.wav")) +gun_sound = pygame.mixer.Sound(os.path.join("sound", "pow1.wav")) +shield_sound = pygame.mixer.Sound(os.path.join("sound", "pow0.wav")) +die_sound = pygame.mixer.Sound(os.path.join("sound", "rumble.ogg")) +expl_sounds = [ + pygame.mixer.Sound(os.path.join("sound", "expl0.wav")), + pygame.mixer.Sound(os.path.join("sound", "expl1.wav")) +] +pygame.mixer.music.load(os.path.join("sound", "background.ogg")) +pygame.mixer.music.set_volume(0.4) +#使用字体simhei.ttf黑体 +font_name = ("C:\Windows\Fonts\simhei.ttf") +def draw_text(surf, text, size, x, y): + font = pygame.font.Font(font_name, size) + text_surface = font.render(text, True, WHITE) + text_rect = text_surface.get_rect() + text_rect.centerx = x + text_rect.top = y + surf.blit(text_surface, text_rect) +#重新生成石头 +def new_rock(): + r = Rock() + all_sprites.add(r) + rocks.add(r) +#画血条 +def draw_health(surf, hp, x, y): + if hp <=0: + hp = 0 + BAR_LENGTH = 100 + BAR_HEIGHT = 10 + fill = (hp/100)*BAR_LENGTH + outline_rect = pygame.Rect(x, y, BAR_LENGTH, BAR_HEIGHT) + fill_rect = pygame.Rect(x, y, fill, BAR_HEIGHT) + pygame.draw.rect(surf, GREEN, fill_rect) + pygame.draw.rect(surf, WHITE, outline_rect, 2) +#画生命 +def draw_lives(surf, lives, img, x, y): + for i in range(lives): + img_rect = img.get_rect() + img_rect.x = x + 32*i + img_rect.y = y + surf.blit(img, img_rect) +#结束界面 +def draw_init2(): + screen.blit(background_img, (0,0)) + draw_text(screen, '按p重新开始', 64, WIDTH/2, HEIGHT/4) + draw_text(screen, '按l结束', 64, WIDTH / 2, HEIGHT / 4+80) + draw_text(screen, 'YOUR SCORE:'+str(score), 32, WIDTH / 2-50, HEIGHT / 4-50) + draw_text(screen, 'PLAYER1 SCORE:' + str(score1), 20, WIDTH/2 , HEIGHT - 100) + draw_text(screen, 'PLAYER2 SCORE:' + str(score2), 20, WIDTH/2-0 , HEIGHT - 50) + pygame.display.update() + waiting = True + while waiting: + clock.tick(FPS) + # 取得輸入 + for event in pygame.event.get(): + if event.type == pygame.QUIT: + waiting = False + return True + if event.type == pygame.KEYDOWN: + if event.key==pygame.K_p: + waiting = False + return False + elif event.key==pygame.K_l: + waiting = False + return True +#开始界面 +def draw_init(): + global score + global score1 + global score2 + global plant_lives + global plant2_lives + global plant_healths + global plant2_healths + global load_s + screen.blit(background_img, (0,0)) + draw_text(screen, '飞机大战!', 64, WIDTH/2, HEIGHT/4) + draw_text(screen, '移动飞船 空白键射击', 22, WIDTH/2, HEIGHT/2) + draw_text(screen, '按O读档', 30, WIDTH / 2, HEIGHT / 2+60) + draw_text(screen, '按空格开始游戏!', 18, WIDTH/2, HEIGHT*3/4) + draw_text(screen, '按L结束游戏!', 18, WIDTH / 2, HEIGHT * 3 / 4+30) + pygame.display.update() + waiting = True + while waiting: + clock.tick(FPS) + # 取得輸入 + for event in pygame.event.get(): + if event.type == pygame.QUIT: + pygame.quit() + return True + if event.type == pygame.KEYDOWN: + if event.key == pygame.K_SPACE: + waiting = False + return False + elif event.key == pygame.K_l: + pygame.quit() + return True + elif event.key==pygame.K_o: + with open("file.txt", "r") as fp: + s = fp.readlines() + s = [int(line.strip()) for line in s] + score=s[0] + score1=s[1] + score2=s[2] + plant_lives=s[3] + plant2_lives=s[4] + plant_healths=s[5] + plant2_healths =s[6] + load_s=True + waiting = False + return False +#玩家飞机类 +class Player2(pygame.sprite.Sprite): + def __init__(self): + pygame.sprite.Sprite.__init__(self)#继承类pygame.sprite.Sprite + self.image = pygame.transform.scale(player_img, (50, 38))#调整引入图片 + self.image.set_colorkey(BLACK) + self.rect = self.image.get_rect()#图片位置 + self.radius = 20 + self.rect.centerx = WIDTH#图片位置 + self.rect.bottom = HEIGHT - 10#图片位置 + self.speedx = 8#飞机速度 + self.health = 100#血量 + self.lives = 3#生命 + self.hidden = False + self.hide_time = 0 + self.gun = 1#子弹数量 + self.gun11=1 + self.gun_time = 0#子弹数量持续时间 + self.gun11_time=0 + self.hide21=False + + def update(self):#更新飞机图片状态 + now = pygame.time.get_ticks() + #子弹状态 + if self.gun == 2 and now - self.gun_time > 5000: + self.gun = 1 + self.gun_time = now + + now = pygame.time.get_ticks() + if self.gun11 == 2 and now - self.gun11_time > 5000: + self.gun11 = 1 + self.gun11_time = now +#飞机状态,隐藏,生命为零消失 + if self.hidden and now - self.hide_time > 1000: + self.hidden = False + self.rect.centerx = WIDTH / 2 + self.rect.bottom = HEIGHT - 10 + if self.hide21: + self.rect.x=WIDTH+500 + self.rect.y=HEIGHT+500 + self.kill() +#左右上下移动 + key_pressed = pygame.key.get_pressed() + if key_pressed[pygame.K_d]: + self.rect.x += self.speedx + if key_pressed[pygame.K_a]: + self.rect.x -= self.speedx + if self.rect.right > WIDTH: + self.rect.right = WIDTH + if self.rect.left < 0: + self.rect.left = 0 + if key_pressed[pygame.K_w]: + self.rect.y-=self.speedx + if self.rect.y < 0: + self.rect.y = 0 + if key_pressed[pygame.K_s]: + self.rect.y +=self.speedx + if self.rect.bottom > HEIGHT: + self.rect.bottom = HEIGHT +#发射子弹 + def shoot(self): + if not(self.hidden): + if self.gun == 1: + bullet = Bullet(self.rect.centerx, self.rect.top) + all_sprites.add(bullet) + bullets2.add(bullet) + shoot_sound.play() + elif self.gun ==2: + bullet1 = Bullet(self.rect.left, self.rect.centery) + bullet2 = Bullet(self.rect.right, self.rect.centery) + all_sprites.add(bullet1) + all_sprites.add(bullet2) + bullets2.add(bullet1) + bullets2.add(bullet2) + shoot_sound.play() + def hide(self): + self.hidden = True + self.hide_time = pygame.time.get_ticks() + self.rect.center = (WIDTH/2, HEIGHT+500) + + def hide2(self): + self.hide21=True + + def gunup(self): + self.gun = 2 + self.gun_time = pygame.time.get_ticks() + def gunup1(self): + self.gun11 = 2 + self.gun11_time = pygame.time.get_ticks() + +class Player(pygame.sprite.Sprite): + def __init__(self): + pygame.sprite.Sprite.__init__(self) + self.image = pygame.transform.scale(player_img, (50, 38)) + self.image.set_colorkey(BLACK) + self.rect = self.image.get_rect() + self.radius = 20 + # pygame.draw.circle(self.image, RED, self.rect.center, self.radius) + self.rect.centerx = WIDTH / 2 + self.rect.bottom = HEIGHT - 10 + self.speedx = 8 + self.health = 100 + self.lives = 3 + self.hidden = False + self.hide21=False + self.hide_time = 0 + self.gun = 1 + self.gun11=1 + self.gun_time = 0 + self.gun11_time = 0 + + def update(self): + now = pygame.time.get_ticks() + if self.gun == 2 and now - self.gun_time > 5000: + self.gun = 1 + self.gun_time = now + + now = pygame.time.get_ticks() + if self.gun11 == 2 and now - self.gun_time > 5000: + self.gun11 = 1 + self.gun11_time = now + + if self.hidden and now - self.hide_time > 1000: + self.hidden = False + self.rect.centerx = WIDTH / 2 + self.rect.bottom = HEIGHT - 10 + + if self.hide21: + self.rect.x=WIDTH+1100 + self.rect.y=HEIGHT+1100 + self.kill() + + key_pressed = pygame.key.get_pressed() + if key_pressed[pygame.K_RIGHT]: + self.rect.x += self.speedx + if key_pressed[pygame.K_LEFT]: + self.rect.x -= self.speedx + if self.rect.right > WIDTH: + self.rect.right = WIDTH + if self.rect.left < 0: + self.rect.left = 0 + + if key_pressed[pygame.K_DOWN]: + self.rect.y+=self.speedx + if self.rect.bottom > HEIGHT: + self.rect.bottom = HEIGHT + if key_pressed[pygame.K_UP]: + self.rect.y-=self.speedx + if self.rect.y < 0: + self.rect.y = 0 + + def shoot(self): + if not(self.hidden): + if self.gun == 1: + bullet = Bullet(self.rect.centerx, self.rect.top) + all_sprites.add(bullet ) + bullets1.add(bullet) + shoot_sound.play() + elif self.gun ==2: + bullet1 = Bullet(self.rect.left, self.rect.centery) + bullet2 = Bullet(self.rect.right, self.rect.centery) + all_sprites.add(bullet1) + all_sprites.add(bullet2) + bullets1.add(bullet1) + bullets1.add(bullet2) + shoot_sound.play() + + def hide(self): + self.hidden = True + self.hide_time = pygame.time.get_ticks() + self.rect.center = (WIDTH/2, HEIGHT+500) + + def hide2(self): + self.hide21=True + + def gunup(self): + self.gun = 2 + self.gun_time = pygame.time.get_ticks() + def gunup1(self): + self.gun11 = 2 + self.gun11_time = pygame.time.get_ticks() + +class enemy(pygame.sprite.Sprite): + def __init__(self, x=0, y=0): + self.x = x + self.y = y + self.screen = screen + self.fangxiang = 'right' + self.name = 'enemyer' + self.bullet = [] + + def draw(self): + self.screen.blit(self.image, (self.x, self.y)) + for temp in self.bullet: + temp.draw() + + def move(self): + + if self.fangxiang == 'right': + self.x += 2 + elif self.fangxiang == 'left': + self.x -= 2 + if self.x > 460: + self.fangxiang = 'left' + elif self.x <= 0: + self.fangxiang = 'right' + # print(self.x) + randomNum = random.randint(1, 100) + if randomNum in [50, 70]: + self.bullet.append(Bullet(self.name, self.x + 30, self.y + 24)) +#石头类 +class Rock(pygame.sprite.Sprite): + def __init__(self): + pygame.sprite.Sprite.__init__(self)#继承类pygame.sprite.Sprite + self.image_ori = random.choice(rock_imgs) #石头图片 + self.image_ori.set_colorkey(BLACK) + self.image = self.image_ori.copy() + self.rect = self.image.get_rect()#位置 + self.radius = int(self.rect.width * 0.85 / 2)#石头威力 + # pygame.draw.circle(self.image, RED, self.rect.center, self.radius) + self.rect.x = random.randrange(0, WIDTH - self.rect.width)#位置 + self.rect.y = random.randrange(-180, -100) + self.speedy = random.randrange(2, 5) + self.speedx = random.randrange(-3, 3)#速度 + self.total_degree = 0 + self.rot_degree = random.randrange(-3, 3) + + def rotate(self):#石头旋转 + self.total_degree += self.rot_degree + self.total_degree = self.total_degree % 360 + self.image = pygame.transform.rotate(self.image_ori, self.total_degree) + center = self.rect.center + self.rect = self.image.get_rect() + self.rect.center = center + + def update(self): + self.rotate() + self.rect.y += self.speedy#石头速度 + self.rect.x += self.speedx + if self.rect.top > HEIGHT or self.rect.left > WIDTH or self.rect.right < 0: + self.rect.x = random.randrange(0, WIDTH - self.rect.width) + self.rect.y = random.randrange(-100, -40) + self.speedy = random.randrange(2, 10) + self.speedx = random.randrange(-3, 3) +#子弹类 +class Bullet(pygame.sprite.Sprite):#继承类pygame.sprite.Sprite + def __init__(self, x, y): + pygame.sprite.Sprite.__init__(self) + self.image = bullet_img#引入子弹图片 + self.image.set_colorkey(BLACK) + self.rect = self.image.get_rect() + self.rect.centerx = x + self.rect.bottom = y + self.speedy = -10 + + def update(self): + self.rect.y += self.speedy + if self.rect.bottom < 0: + self.kill() +#爆炸效果类 +class Explosion(pygame.sprite.Sprite): + def __init__(self, center, size): + pygame.sprite.Sprite.__init__(self)#继承类pygame.sprite.Sprite + self.size = size + self.image = expl_anim[self.size][0] + self.rect = self.image.get_rect()#位置 + self.rect.center = center + self.frame = 0 + self.last_update = pygame.time.get_ticks() + self.frame_rate = 50 + + def update(self): + now = pygame.time.get_ticks() + if now - self.last_update > self.frame_rate: + self.last_update = now + self.frame += 1 + if self.frame == len(expl_anim[self.size]): + self.kill() + else: + self.image = expl_anim[self.size][self.frame] + center = self.rect.center + self.rect = self.image.get_rect() + self.rect.center = center +#掉落物类 +class Power(pygame.sprite.Sprite): + def __init__(self, center): + pygame.sprite.Sprite.__init__(self) + self.type = random.choice(['shield', 'gun','body'])#三种掉落物 + self.image = power_imgs[self.type] + self.image.set_colorkey(BLACK) + self.rect = self.image.get_rect()#位置 + self.rect.center = center + self.speedy = 3 + + def update(self): + self.rect.y += self.speedy + if self.rect.top > HEIGHT: + self.kill() + +#一直重复背景音乐 +pygame.mixer.music.play(-1) + +# 游戏循环 +show_init = True#开始界面判断 +running = True#游戏结束判断 +while running: + if show_init: + player = Player() + player2 = Player2() + close = draw_init() + if close:#存档 + with open("file.txt", "w") as fp: + fp.write(str(int(score))) + fp.write('\n') + fp.write(str(int(score1))) + fp.write('\n') + fp.write(str(int(score2))) + fp.write('\n') + fp.write(str(player.lives)) + fp.write('\n') + fp.write(str(player2.lives)) + fp.write('\n') + fp.write(str(int(player.health))) + fp.write('\n') + fp.write(str(int(player2.health))) + break + show_init = False + all_sprites = pygame.sprite.Group() + rocks = pygame.sprite.Group() + bullets1 = pygame.sprite.Group() + bullets2 = pygame.sprite.Group() + powers = pygame.sprite.Group() + if load_s:#读档 + player.lives=plant_lives + player.health=plant_healths + player2.lives = plant2_lives + player2.health = plant2_healths + load_s=False + all_sprites.add(player) + all_sprites.add(player2) + for i in range(8):#石头数量 + new_rock() + + clock.tick(FPS)#一秒最多60次图片更新 + # 得到输入 + for event in pygame.event.get():#判断是否按右上角退出 + if event.type == pygame.QUIT:#意外退出自动保存 + with open("file.txt", "w") as fp: + fp.write(str(score)) + fp.write('\n') + fp.write(str(score1)) + fp.write('\n') + fp.write(str(score2)) + fp.write('\n') + fp.write(str(player.lives)) + fp.write('\n') + fp.write(str(player2.lives)) + fp.write('\n') + fp.write(str(int(player.health))) + fp.write('\n') + fp.write(str(int(player2.health))) + running = False + elif event.type == pygame.KEYDOWN:#判断游戏键盘输入 + if event.key ==pygame.K_SPACE:#空格发射子弹 + player.shoot() + + if event.key == pygame.K_q:#q发射子弹 + player2.shoot() + + # 更新游戏 + all_sprites.update() + # 石头类子弹类碰撞处理 + hits = pygame.sprite.groupcollide(rocks, bullets1, True, True) + for hit in hits: + random.choice(expl_sounds).play() + score += hit.radius + score1+=hit.radius + expl = Explosion(hit.rect.center, 'lg') + all_sprites.add(expl) + if random.random() > 0.9: + pow = Power(hit.rect.center) + all_sprites.add(pow) + powers.add(pow) + new_rock() + + hits = pygame.sprite.groupcollide(rocks, bullets2, True, True) + for hit in hits: + random.choice(expl_sounds).play()#爆炸动画 + score += hit.radius#计算分数 + score2+=hit.radius + expl = Explosion(hit.rect.center, 'lg') + all_sprites.add(expl) + if random.random() > 0.9:#掉落物的概率 + pow1 = Power(hit.rect.center) + all_sprites.add(pow1) + powers.add(pow1) + new_rock() + # 石头类飞机类碰撞处理 + hits = pygame.sprite.spritecollide(player, rocks, True, pygame.sprite.collide_circle) + for hit in hits: + new_rock() + player.health -= hit.radius * 2 + expl = Explosion(hit.rect.center, 'sm') + all_sprites.add(expl) + if player.health <= 0: + player.gun=1 + death_expl = Explosion(player.rect.center, 'player') + all_sprites.add(death_expl) + die_sound.play() + player.lives -= 1 + if player.lives<=0: + player.hide2() + player.health = 100 + player.hide() + + hits = pygame.sprite.spritecollide(player2, rocks, True, pygame.sprite.collide_circle) + for hit in hits: + new_rock() + player2.health -= hit.radius * 2#扣的血量等于石头的半径*2 + expl = Explosion(hit.rect.center, 'sm')#爆炸效果 + all_sprites.add(expl) + if player2.health <= 0: + player2.gun = 1 + death_expl = Explosion(player2.rect.center, 'player') + all_sprites.add(death_expl) + die_sound.play() + player2.lives -= 1 + if player2.lives<=0:#飞机死了消失一下 + player2.hide2() + player2.health = 100#重置血量 + player2.hide() + # 飞机类掉落类碰撞处理 + hits = pygame.sprite.spritecollide(player, powers, True) + for hit in hits: + if hit.type == 'body': + player.health += 20 + if player.health > 100: + player.health = 100 + shield_sound.play() + elif hit.type == 'shield': + player.gunup() + gun_sound.play() + elif hit.type == 'gun': + player.gunup1() + player.speedx+=4 + # player.gunup1() + + hits = pygame.sprite.spritecollide(player2, powers, True) + for hit in hits: + if hit.type == 'body':#加飞机血量的道具 + player2.health += 20 + if player2.health > 100: + player2.health = 100 + shield_sound.play() + elif hit.type == 'shield':#加飞机子弹的道具 + player2.gunup() + gun_sound.play() + elif hit.type == 'gun':#加飞机速度的道具 + player2.gunup1() + player2.speedx+=4 +#判断飞机生命值归零,游戏结束 + if player.lives==0 and player2.lives == 0 : + close2 = draw_init2()#展开结束界面 + if not(close2): + close=False + show_init = True + else: + break + + + # 画面 + screen.fill(BLACK) + screen.blit(background_img, (0,0)) + all_sprites.draw(screen) + draw_text(screen, str(score), 18, WIDTH/2, 10)#画飞机得分 + #血条显示 + if player.lives>0: + draw_health(screen, player.health, 5, 15) + if player2.lives > 0: + draw_health(screen, player2.health, 5, 30) + #画飞机生命 + draw_lives(screen, player.lives, player_mini_img, WIDTH - 100, 15) + draw_lives(screen, player2.lives, player_mini_img, WIDTH - 100, 40) + pygame.display.update() + +pygame.quit() \ No newline at end of file