You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

284 lines
10 KiB

This file contains invisible Unicode characters!

This file contains invisible Unicode characters that may be processed differently from what appears below. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to reveal hidden characters.

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# -*- coding: utf-8 -*-
"""
Created on Sun Dec 22 09:26:13 2024
@author: 兰子芃
"""
import random
import pygame
# 屏幕大小的常量
SCREEN_RECT = pygame.Rect(0, 0, 480, 700)
# 刷新的帧率
FRAME_PER_SEC = 60
# 创建敌机的定时器常量
CREATE_ENEMY_EVENT = pygame.USEREVENT
# 英雄发射子弹事件
HERO_FIRE_EVENT = pygame.USEREVENT + 1
HERO_FIRE_EVENT2 = pygame.USEREVENT + 3
charge=pygame.USEREVENT+2
class GameSprite(pygame.sprite.Sprite):
"""飞机大战游戏精灵"""
def __init__(self, image_name, speed=1):
# 调用父类的初始化方法
super().__init__()
# 定义对象的属性
self.image = pygame.image.load(image_name)
self.rect = self.image.get_rect()
self.speed = speed
def update(self):
# 在屏幕的垂直方向上移动
self.rect.y += self.speed
class Background(GameSprite):
"""游戏背景精灵"""
def __init__(self, is_alt=False):
# 1. 调用父类方法实现精灵的创建(image/rect/speed)
super().__init__("./PythonProject/images/background.png")
# 2. 判断是否是交替图像,如果是,需要设置初始位置
if is_alt:
self.rect.y = -self.rect.height
def update(self):
# 1. 调用父类的方法实现
super().update()
# 2. 判断是否移出屏幕,如果移出屏幕,将图像设置到屏幕的上方
if self.rect.y >= SCREEN_RECT.height:
self.rect.y = -self.rect.height
class Enemy(GameSprite):
"""敌机精灵"""
def __init__(self):
# 1. 调用父类方法,创建敌机精灵,同时指定敌机图片
super().__init__("./PythonProject/images/enemy1.png")
# 2. 指定敌机的初始随机速度 1 ~ 3
self.speed = random.randint(1, 3)
# 3. 指定敌机的初始随机位置
self.rect.bottom = 0
max_x = SCREEN_RECT.width - self.rect.width
self.rect.x = random.randint(0, max_x)
def update(self):
# 1. 调用父类方法,保持垂直方向的飞行
super().update()
# 2. 判断是否飞出屏幕,如果是,需要从精灵组删除敌机
if self.rect.y >= SCREEN_RECT.height:
# print("飞出屏幕,需要从精灵组删除...")
# kill方法可以将精灵从所有精灵组中移出精灵就会被自动销毁
self.kill()
def __del__(self):
# print("敌机挂了 %s" % self.rect)
pass
class Hero(GameSprite):
"""英雄精灵"""
def __init__(self):
# 1. 调用父类方法设置image&speed
super().__init__("./PythonProject/images/me1.png", 0)
# 2. 设置英雄的初始位置
self.rect.centerx = SCREEN_RECT.centerx
self.rect.bottom = SCREEN_RECT.bottom - 120
self.mode=2
self.modetmp=1
# 3. 创建子弹的精灵组
self.bullets = pygame.sprite.Group()
def update(self):
if self.modetmp==1:
self.mode=1
else:
self.mode=2
# 英雄在水平方向移动
self.rect.x += self.speedx
self.rect.y += self.speedy
# 控制英雄不能离开屏幕
if self.rect.x < 0:
self.rect.x = 0
elif self.rect.right > SCREEN_RECT.right:
self.rect.right = SCREEN_RECT.right
elif self.rect.y>SCREEN_RECT.height:
self.rect.bottom = SCREEN_RECT.height
elif self.rect.y<-SCREEN_RECT.bottom:
self.rect.y=-SCREEN_RECT.bottom
def fire(self):
#print("发射子弹...")
if self.mode==1:
for i in (0, 1, 2):
# 1. 创建子弹精灵
bullet3 = Bullet()
# 2. 设置精灵的位置
bullet3.rect.bottom = self.rect.y - i * 20
bullet3.rect.centerx = self.rect.centerx
# 3. 将精灵添加到精灵组
self.bullets.add(bullet3)
else:
for i in (1, 2):
# 1. 创建子弹精灵
bullet = Bullet()
bullet2=Bullet()
# 2. 设置精灵的位置
bullet.rect.bottom = self.rect.y+ i*10
bullet.rect.centerx = self.rect.centerx+i*20
bullet2.rect.bottom = self.rect.y+i*10
bullet2.rect.centerx = self.rect.centerx-i*20
# 3. 将精灵添加到精灵组
self.bullets.add(bullet)
self.bullets.add(bullet2)
class Bullet(GameSprite):
"""子弹精灵"""
def __init__(self):
# 调用父类方法,设置子弹图片,设置初始速度
super().__init__("./PythonProject/images/bullet1.png", -2)
def update(self):
# 调用父类方法,让子弹沿垂直方向飞行
super().update()
# 判断子弹是否飞出屏幕
if self.rect.bottom < 0:
self.kill()
def __del__(self):
print("")
class PlaneGame(object):
"""飞机大战主游戏"""
def __init__(self):
print("游戏初始化")
# 1. 创建游戏的窗口
self.screen = pygame.display.set_mode(SCREEN_RECT.size)
pygame.display.set_caption('飞机大战')
# 2. 创建游戏的时钟
self.clock = pygame.time.Clock()
# 3. 调用私有方法,精灵和精灵组的创建
self.__create_sprites()
# 4. 设置定时器事件 - 创建敌机 1s
pygame.time.set_timer(CREATE_ENEMY_EVENT, 1000)
pygame.time.set_timer(HERO_FIRE_EVENT, 800)
pygame.time.set_timer(HERO_FIRE_EVENT2, 500)
pygame.time.set_timer(charge,10000)
self.inum=0
self.num=3
def __create_sprites(self):
# 创建背景精灵和精灵组
bg1 = Background()
bg2 = Background(True)
self.back_group = pygame.sprite.Group(bg1, bg2)
# 创建敌机的精灵组
self.enemy_group = pygame.sprite.Group()
# 创建英雄的精灵和精灵组
self.hero = Hero()
self.hero_group = pygame.sprite.Group(self.hero)
def start_game(self):
print("游戏开始...")
while True:
# 1. 设置刷新帧率
self.clock.tick(FRAME_PER_SEC)
# 2. 事件监听
self.__event_handler()
# 3. 碰撞检测
self.__check_collide()
# 4. 更新/绘制精灵组
self.__update_sprites()
# 5. 更新显示
pygame.display.update()
def __event_handler(self):
for event in pygame.event.get():
# 判断是否退出游戏
if event.type == pygame.QUIT:
PlaneGame.__game_over()
elif event.type == CREATE_ENEMY_EVENT:
# print("敌机出场...")
# 创建敌机精灵
enemy = Enemy()
# 将敌机精灵添加到敌机精灵组
self.enemy_group.add(enemy)
elif event.type == HERO_FIRE_EVENT :
self.hero.fire()
elif event.type==charge:
self.inum-=1
# elif event.type == pygame.KEYDOWN and event.key == pygame.K_RIGHT:
# print("向右移动...")
# 使用键盘提供的方法获取键盘按键 - 按键元组
keys_pressed = pygame.key.get_pressed()
# 判断元组中对应的按键索引值 1
if keys_pressed[pygame.K_RIGHT]:
self.hero.speedx = 2
if keys_pressed[pygame.K_UP]:
self.hero.speedy=-4
elif keys_pressed[pygame.K_DOWN]:
self.hero.speedy=4
else:
self.hero.speedy=0
if keys_pressed[pygame.K_LSHIFT] and self.inum<self.num:
pygame.key.set_repeat()
self.hero.speedx = 200
self.hero.speedy=0
self.inum += 1
print("{}".format(self.inum))
elif keys_pressed[pygame.K_LEFT]:
self.hero.speedx = -2
if keys_pressed[pygame.K_UP]:
self.hero.speedy=-4
elif keys_pressed[pygame.K_DOWN]:
self.hero.speedy=4
else:
self.hero.speedy=0
if keys_pressed[pygame.K_LSHIFT] and self.inum<self.num:
pygame.key.set_repeat()
self.hero.speedx = -200
self.hero.speedy=0
self.inum += 1
print("{}".format(self.inum))
elif keys_pressed[pygame.K_UP]:
self.hero.speedy =-4
if keys_pressed[pygame.K_LEFT]:
self.hero.speedx = -2
elif keys_pressed[pygame.K_RIGHT]:
self.hero.speedx = 2
else:
self.hero.speedx = 0
elif keys_pressed[pygame.K_DOWN]:
self.hero.speedy =4
if keys_pressed[pygame.K_LEFT]:
self.hero.speedx = -2
elif keys_pressed[pygame.K_RIGHT]:
self.hero.speedx = 2
else:
self.hero.speedx = 0
#到这里都是移动部分
elif keys_pressed[pygame.K_1]:
self.hero.modetmp=-self.hero.modetmp
else:
self.hero.speedx = 0
self.hero.speedy = 0
def __check_collide(self):
# 1. 子弹摧毁敌机
pygame.sprite.groupcollide(self.hero.bullets, self.enemy_group, True, True)
# 2. 敌机撞毁英雄
enemies = pygame.sprite.spritecollide(self.hero, self.enemy_group, True)
# 判断列表时候有内容
if len(enemies)>0:
# 让英雄牺牲
self.hero.kill()
# 结束游戏
PlaneGame.__game_over()
def __update_sprites(self):
self.back_group.update()
self.back_group.draw(self.screen)
self.enemy_group.update()
self.enemy_group.draw(self.screen)
self.hero_group.update()
self.hero_group.draw(self.screen)
self.hero.bullets.update()
self.hero.bullets.draw(self.screen)
@staticmethod
def __game_over():
print("游戏结束")
pygame.quit()
exit()
if __name__ == '__main__':
# 创建游戏对象
game = PlaneGame()
# 启动游戏
game.start_game()