太空射击python

# 导入模块
import random  # 随机数模块
import pygame  # 制作游戏模块
from os import path  # 系统路径模块

# 游戏资源路径
img_dir = path.join(path.dirname(__file__), 'assets')
sound_folder = path.join(path.dirname(__file__), 'sounds')

# 游戏中的值
WIDTH = 480
HEIGHT = 600
FPS = 60

# 常用颜色值
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
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 = pygame.image.load(path.join(img_dir, 'starfield.png')).convert()
# 获取游戏背景图片矩形
background_rect = background.get_rect()
# 获取字体
font_name = pygame.font.match_font('楷体', 16)
# 获取飞机类的图片资源
player_img = pygame.image.load(path.join(img_dir, 'playerShip1_orange.png')).convert()
# 获取子弹类的图片资源
bullet_img = pygame.image.load(path.join(img_dir, 'laserRed16.png')).convert()
# 获取陨石类的图片资源
meteor_images = []
meteor_list = [
    'meteorBrown_tiny1.png',
    'meteorBrown_small2.png',
    'meteorBrown_small1.png',
    'meteorBrown_med3.png',
    'meteorBrown_med1.png',
    'meteorBrown_big2.png',
    'meteorBrown_big1.png',
]

# 遍历
for image in meteor_list:
    meteor_images.append(pygame.image.load(path.join(img_dir, image)).convert())
# 获取爆炸类的图片资源
explosion_anim = {}
explosion_anim['lg'] = []
explosion_anim['sm'] = []
for i in range(9):
    filename = 'regularExplosion0{}.png'.format(i)
    img = pygame.image.load(path.join(img_dir, filename)).convert()
    img.set_colorkey(BLACK)
    img_lg = pygame.transform.scale(img, (75, 75))
    explosion_anim['lg'].append(img_lg)
    img_sm = pygame.transform.scale(img, (32, 32))
    explosion_anim['sm'].append(img_sm)

##音频资源
# 飞机射击音频资源
shooting_sound = pygame.mixer.Sound(path.join(sound_folder, 'pew.wav'))
# 陨石爆炸的音频资源
expl_sounds = []
for sound in ['expl3.wav', 'expl6.wav']:
    expl_sounds.append(pygame.mixer.Sound(path.join(sound_folder, sound)))


# 绘制字体
# parm1 屏幕
# Parm2 文本内容
# parm3 字体大小
# parm4 x坐标
# parm5 y坐标
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.midtop = (x, y)
    # 将文本内容绘制到屏幕上
    surf.blit(text_surface, text_rect)


# 绘制主菜单函数
def main_menu():
    # 全局变量 屏幕
    global screen
    # 主菜单音频资源获取
    menu_song = pygame.mixer.music.load(path.join(sound_folder, 'menu.ogg'))

    # 主菜单音频资源播放
    pygame.mixer.music.play(-1)

    ## 设置游戏主菜单标题

    # 获取标题图片资源
    title = pygame.image.load(path.join(img_dir, 'main.png')).convert()
    # 标题图片资源等比例缩放
    title = pygame.transform.scale(title, (WIDTH, HEIGHT), screen)
    # 绘制标题图片到屏幕上
    screen.blit(title, (0, 0))
    # 部分刷新显示
    pygame.display.update()
    # 监听用户操作
    while True:
        ev = pygame.event.poll()
        # 判断用户操作(事件类型是否是按键按下事件)
        if ev.type == pygame.KEYDOWN:
            # 判断用户是否按下了回车键
            if ev.key == pygame.K_RETURN:
                break
            # 判断用户是否按下了Q键
            elif ev.key == pygame.K_q:
                # 游戏退出
                pygame.quit()
                # 程序退出
                quit()
        # 判断用户操作(事件类型是否是用户点击退出事件)        
        elif ev.type == pygame.QUIT:
            # 游戏退出
            pygame.quit()
            # 程序退出
            quit()
        # 否则
        else:
            # 绘制提示字
            # 首先绘制提示字:按回车按键开始游戏
            draw_text(screen, "Press [ENTER] TO Begin", 30, WIDTH / 2, HEIGHT / 2)
            # 绘制提示字: 按Q键退出游戏
            draw_text(screen, "or [Q] To Quit", 30, WIDTH / 2, (HEIGHT / 2) + 40)
            # 部分刷新显示
            pygame.display.update()
    # #游戏准备界面

    # 获取游戏准备界面音频资源
    ready_song = pygame.mixer.Sound(path.join(sound_folder, 'getready.ogg'))
    # 播放游戏准备界面音频资源
    ready_song.play()
    # 填充游戏屏幕为黑色
    screen.fill(BLACK)
    # 绘制游戏准备界面字体
    draw_text(screen, "GET READY!", 60, WIDTH / 2, HEIGHT / 2)
    # 部分刷新显示
    pygame.display.update()


# #子弹类
class Bullet(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()

        # 矩形的中心的x值
        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 Mob(pygame.sprite.Sprite):
    # 石头的构造函数
    def __init__(self):
        # 将陨石设置为精灵
        pygame.sprite.Sprite.__init__(self)
        # 图片
        self.image_orig = random.choice(meteor_images)
        self.image_orig.set_colorkey(BLACK)
        # 复制初始图片
        self.image = self.image_orig.copy()
        # 图片的矩形形状
        self.rect = self.image.get_rect()
        # x坐标
        self.rect.x = random.randrange(0, WIDTH - self.rect.width)
        # y坐标
        self.rect.y = random.randrange(-150, -100)
        # 纵向移动速度
        self.speedy = random.randrange(5, 20)
        # 横向移动速度
        self.speedx = random.randrange(-3, 3)
        # 半径
        self.radius = int(self.rect.width * .90 / 2)
        # 旋转角度
        self.rotation = 0
        # 旋转角度变化速度
        self.rotation_speed = random.randrange(-8, 8)
        # 最后一次变化时间
        self.last_update = pygame.time.get_ticks()

    # 旋转函数
    def rotate(self):
        # 获取当前时间
        time_now = pygame.time.get_ticks()
        # 判断是否超出旋转时间
        if time_now - self.last_update > 50:
            # 将最后一次变化时间改为当前时间
            self.last_update = time_now
            # 改变旋转角度
            self.rotation = (self.rotation + self.rotation_speed) % 360
            # 旋转图片
            new_image = pygame.transform.rotate(self.image_orig, self.rotation)
            # 获得旋转中心点
            old_center = self.rect.center
            # 重新赋值、
            self.image = new_image
            # 重新获得图片矩形
            self.rect = self.image.get_rect()
            # 重新获得图片矩形设置中心点
            self.rect.center = old_center

    # 更新变化函数
    def update(self):
        # 执行旋转函数
        self.rotate()
        # 改变x
        self.rect.x += self.speedx
        # 改变y
        self.rect.y += self.speedy
        # 判断陨石是否出界
        if (self.rect.top > HEIGHT + 10) or (self.rect.left < -25) or (self.rect.right > WIDTH + 20):
            # 改变陨石的想,x,y,y方向的移动速度
            self.rect.x = random.randrange(0, WIDTH - self.rect.width)
            self.rect.y = random.randrange(-100, -40)
            self.speedy = random.randrange(1, 8)


# 创建陨石类对象函数
def newmob():
    # 创建陨石类对象
    mob_element = Mob()
    # 将陨石类添加到精灵组合
    all_sprites.add(mob_element)
    # 将陨石添加到陨石组合
    mobs.add(mob_element)


# #爆炸类
class Explosion(pygame.sprite.Sprite):
    # 爆炸类构造函数
    def __init__(self, center, size):
        # 将爆炸类设为精灵
        #  #大小
        self.size = size
        pygame.sprite.Sprite.__init__(self)
        # 图片
        self.image = explosion_anim[self.size][0]

        # 图片的矩形形状
        self.rect = self.image.get_rect()
        # 图片矩形的中心点
        self.rect.center = center
        # 设计
        self.frame = 0
        # 设计时间
        self.frame_rete = 75
        # 最后一次更新时间
        self.last_update = pygame.time.get_ticks()

    # 更新函数
    def update(self):
        # 现在的时间
        now = pygame.time.get_ticks()
        # 判断现在的时间减去最后一次更新时间是否大于设计时间
        if now - self.last_update > self.frame_rete:
            # 将最后一次更新时间变换为现在时间
            self.last_update = now
            self.frame += 1
            if self.frame == len(explosion_anim[self.size]):
                self.kill()
            else:
                center = self.rect.center
                self.image = explosion_anim[self.size][self.frame]
                self.rect = self.image.get_rect()
                self.rect.center = center


# #飞机类
# sprite
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.redius = 20
        # 矩形x中心点
        self.rect.centerx = WIDTH / 2
        # 矩形底部
        self.rect.bottom = HEIGHT - 10
        # x方向移动速度
        self.speedx = 0
        # 射击延迟时间
        self.shoot_delay = 250
        # 射击的最后时间
        self.last_shoot = pygame.time.get_ticks()

    # 飞机的更新函数
    def update(self):
        # x方向移动速度
        self.speedx = 0
        pygame.event.poll()

        # 获取键盘监听
        keystate = pygame.key.get_pressed()
        # 判断用户是否按了left键
        if keystate[pygame.K_LEFT]:
            self.speedx = -5
        # 判断right
        elif keystate[pygame.K_RIGHT]:
            self.speedx = 5

        # 判断用户是否获得空格键
        if keystate[pygame.K_SPACE]:
            # 执行射击方法
            self.shoot()
            # 飞机超出边界
        if self.rect.right > WIDTH:
            self.rect.right = WIDTH
        if self.rect.left < 0:
            self.rect.left = 0

        # 让飞机实现移动
        self.rect.x += self.speedx

    # 飞机的射击函数、
    def shoot(self):
        # 获得现在时间
        now = pygame.time.get_ticks()
        # 判断是否超出延迟时间
        if now - self.last_shoot > self.shoot_delay:
            # 将飞机最后时间改为当前时间
            self.last_shoot = now
            # 创建子弹对象
            bullet = Bullet(self.rect.centerx, self.rect.top)
            # 将子弹添加到精灵组合中
            all_sprites.add(bullet)
            # 将子弹添加到子弹集合中
            bullets.add(bullet)
            # 播放射击声音
            shooting_sound.play()

        # # 游戏的主循环(死循环)


# 游戏状态
running = True
# 菜单显示状态
menu_display = True
while running:

    # 判断菜单是否显示
    if menu_display:
        main_menu()
        # 进入游戏准备界面的时间
        pygame.time.wait(2000)
        # 停止播放主菜单音频
        pygame.mixer.music.stop()
        # 播放玩游戏时的背景音乐
        # 获取资源
        pygame.mixer.music.load(path.join(sound_folder, 'tgfcoder-FrozenJam-SeamlessLoop.ogg'))
        # 播放音频
        pygame.mixer.music.play(-1)
        # 菜单显示状态设置为false
        menu_display = False
        # 创造精灵组合
        all_sprites = pygame.sprite.Group()
        # 创建飞机对象
        player = Player()
        # 将飞机对象添加到精灵组合中
        all_sprites.add(player)

        # 创建子弹精灵组合
        bullets = pygame.sprite.Group()
        # 创建陨石精灵组合
        mobs = pygame.sprite.Group()
        # 创建陨石函数
        for i in range(8):
            # 调用创建陨石函数
            newmob()

    clock.tick(FPS)
    # 遍历事件
    for event in pygame.event.get():
        # 判断事件
        if event.type == pygame.QUIT:
            # 设置游戏状态
            running = False
        # 判断事件类型 按键按下
        if event.type == pygame.KEYDOWN:
            # 判断是否按下eSC
            if event.key == pygame.K_ESCAPE:
                # 设置游戏状态
                running = False

    # update

    all_sprites.update()
    # #游戏中的碰撞检测
    # 陨石雨与子弹
    hits = pygame.sprite.groupcollide(mobs, bullets, True, True)
    # 遍历hits表
    for hit in hits:
        # 爆炸音效
        random.choice(expl_sounds).play()
        # 爆炸动画
        expl = Explosion(hit.rect.center, 'lg')
        all_sprites.add(expl)
        # 产生新陨石
        newmob()
    # 填充屏幕
    screen.fill(BLACK)
    # 在屏幕中绘制游戏背景图片
    screen.blit(background, background_rect)

    all_sprites.draw(screen)
    # 更新整个待显示的绘制内容到屏幕中
    pygame.display.flip()
pygame.quit()

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:太空射击python - Python技术站

(0)
上一篇 2023年4月2日 下午5:06
下一篇 2023年4月2日 下午5:06
合作推广
合作推广
分享本页
返回顶部