python之“太空大战”小游戏实现

本文博主将讲述python开发“太空大战”小游戏的过程

一、对即将开发的小游戏初认识

注:初认识的目的是,让开发者脑中有个你即将开发的游戏的大概轮廓和游戏功能
1、先给大家介绍一下游戏的玩法和界面说明
当你刚开始运行代码时,出现如图界面问你是否开始游戏
在这里插入图片描述
按下“回车”确认开始后,出现如下待机界面,(注:该待机界面不会超过10秒)
在这里插入图片描述
游戏开始后,玩法和界面说明
在这里插入图片描述
注:按“空格”键是发射子弹,键盘的“左右”键用来控制飞机左右躲避陨石撞击(注:您一共有三架飞机,若是三架飞机都被撞毁,则游戏结束)

二、对整个工程的解释:

在这里插入图片描述
整个工程相对来说还是挺简单的,在你的工程下创建一个文件夹命名为“game”用来存放整个项目,“assets”是存放游戏所需的图片资源,“sounds”是存放游戏所需的音频资源,“shooter.py”文件是实现游戏的python代码,以下是“shooter.py”文件的代码,“assets”和“sounds”文件夹,我会打包给你们(点击这里获取
),直接放到你创建的game目录下即可;

注:本人博客所有内容完全免费,请放心下载
在这里插入图片描述

三、开始写python代码,写完代码运行即可开始游戏

代码我做了比较详细的说明,希望你能看懂

#!/usr/bin/env python
# _*_ coding: utf-8 _*_

# 导入模块
import pygame
from os import path
import random

# 图片资源路径
img_dir = path.join(path.dirname(__file__), 'assets')
# 音频资源路径
sound_folder = path.join(path.dirname(__file__), 'sounds')

# 游戏界面的宽度
WIDTH = 480
# 游戏界面的高度
HEIGHT = 600
# 游戏中生命条长度
BAR_LENGTH = 100
# 游戏中生命条高度
BAR_HEIGHT = 10

# 游戏中的字体
font_name = pygame.font.match_font('楷体', 16)
# 帧数
FPS = 60

# 游戏中的常用颜色 RGB
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
YELLOW = (255, 255, 0)
# 游戏初始化   .是调用的意思
# 如何进入源码查看Ctrl+鼠标左键
pygame.init()
# 游戏音频初始化操作
pygame.mixer.init()
# 初始化游戏显示窗口   数组  列表  (1,2,3,4)元组
#                                  [1,2,3,4]列表
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()
# 飞机图片
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()
# 一个个资源获取  添加到陨石图片列表中
# 利用循环将资源获取添加
# 陨石图片列表
metor_images = []
# 陨石图片名称列表
metor_list = [
    'meteorBrown_big1.png',
    'meteorBrown_big2.png',
    'meteorBrown_med1.png',
    'meteorBrown_med3.png',
    'meteorBrown_small1.png',
    'meteorBrown_small2.png',
    'meteorBrown_tiny1.png',
]
# 向陨石图片列表添加图片
for image in metor_list:
    metor_images.append(pygame.image.load(path.join(img_dir, image)).convert())

# 字典
# ni---》你   key(键值)————》value(内容)
# 爆炸图片动画
explosion_anim = {}
explosion_anim ['lg'] = []
explosion_anim ['sm'] = []
explosion_anim ['player'] = []

# 循环添加图片到列表中
for i in range(9):
    # 获取文件名
    fileName = 'regularExplosion0{}.png'.format(i)
    # 根据文件名获取图片
    img = pygame.image.load(path.join(img_dir, fileName)).convert()
    img.set_colorkey(BLACK)
    # 将爆炸图片缩放(75,75) 大的陨石爆炸效果
    img_lg = pygame.transform.scale(img, (75, 75))
    # 将缩放后的图片添加到lg列表中
    explosion_anim['lg'].append(img_lg)
    # 将爆炸图片缩放(32,32)小的陨石爆炸效果
    img_sm = pygame.transform.scale(img, (32, 32))
    # 将缩放后的图片添加到sm列表中
    explosion_anim['sm'].append(img_sm)
    # 飞机爆炸
    # 获取文件名
    fileName = 'regularExplosion0{}.png'.format(i)
    # 根据文件名获取图片
    img = pygame.image.load(path.join(img_dir, fileName)).convert()
    img.set_colorkey(BLACK)
    # 将获得的图片添加到player列表中
    explosion_anim['player'].append(img)
# 小飞机图片
# 缩放小飞机图片
player_mini_img = pygame.transform.scale(player_img, (25, 19))
player_mini_img.set_colorkey(BLACK)

# 奖励图片
powerup_images = {}
powerup_images['shield'] = pygame.image.load(path.join(img_dir, 'bolt_gold.png')).convert()
powerup_images['dun'] = pygame.image.load(path.join(img_dir, 'shield_gold.png')).convert()
# 导弹图片
missile_img = pygame.image.load(path.join(img_dir, 'missile.png')).convert_alpha()

# 陨石爆炸音频列表
expl_sounds = []
for sound in ['expl3.wav', 'expl6.wav']:
    expl_sounds.append(pygame.mixer.Sound(path.join(sound_folder, sound)))
# 飞机爆炸音效
player_die_sound = pygame.mixer.Sound(path.join(sound_folder, 'rumble1.ogg'))
# 音效资源获取
shooting_sound = pygame.mixer.Sound(path.join(sound_folder, 'pew.wav'))
# 导弹发射音效资源获取
missile_sound = pygame.mixer.Sound(path.join(sound_folder, 'rocket.ogg'))


# 主菜单函数 得分函数名称(参数.......):
def main_menu():
    global screen
    # 获取游戏主菜单背景音乐资源
    menu_song = pygame.mixer.music.load(path.join(sound_folder, 'menu.ogg'))
    # 无限时的播放
    pygame.mixer.music.play(-1)
    # 获取游戏主菜单背景图片
    background_menu = pygame.image.load(path.join(img_dir, 'main.png')).convert()
    # 缩放背景图片
    background_menu = pygame.transform.scale(background_menu, (WIDTH, HEIGHT), screen)
    # 将缩放后的图片设置到主菜单上
    screen.blit(background_menu, (0, 0))
    # 刷新屏幕(部分刷新屏幕)
    pygame.display.update()
    # 提示  使用不可控制次数循环
    while True:
        # 键盘的监听
        ev = pygame.event.poll()
        # 如果是按键按下事件
        if ev.type == pygame.KEYDOWN:
            # 如果用户按下了回车键
            if ev.key == pygame.K_RETURN:
                break
            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)
            draw_text(screen, "or [Q] to Quit", 30, WIDTH/2, (HEIGHT/2)+40)
            # 刷新屏幕
            pygame.display.update()
    # 游戏的准备界面
    # 获取游戏准备的音频资源
    ready = pygame.mixer.Sound(path.join(sound_folder, 'getready.ogg'))
    # 仅播放一次
    ready.play()
    # 将游戏屏幕填充为黑色
    screen.fill(BLACK)
    draw_text(screen, "GET READY!", 80, WIDTH/2, HEIGHT/2)
    # 刷新屏幕
    pygame.display.update()

# 绘制字体的函数
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)

# 飞机类
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()
        # 设置矩形的 x方向中心点
        self.rect.centerx = WIDTH/2
        # 设置矩形的底部坐标 y
        self.rect.bottom = HEIGHT - 10
        # 飞机的X方向移动速度
        self.speedx = 0
        # 飞机最后一次发射完成时间    pygame.time.get_ticks() 获得当前的系统时间
        self.last_shoot = pygame.time.get_ticks()
        # 子弹发射时间间隔
        self.shoot_delay = 100
        # 子弹的初始火力值
        self.power = 1
        # 子弹的火力时间
        self.power_time = pygame.time.get_ticks()
        # 飞机的生命值
        self.sheild = 100
        # 飞机的生命
        self.lives = 3
        # 半径
        self.radius = 20
        # 飞机的隐身状态
        self.hidden = False
        # 飞机的隐身时间
        self.hide_timer = pygame.time.get_ticks()
    # 飞机的更新函数
    def update(self):
        # 消弱飞机的火力
        if self.power >=2 and pygame.time.get_ticks() - self.power_time > 5000:
            self.power -=1
            self.power_time = pygame.time.get_ticks()

        # 恢复飞机 取消隐身
        if self.hidden and pygame.time.get_ticks() - self.hide_timer > 2000:
            self.hidden = False
            self.rect.centerx = WIDTH /2
            self.rect.bottom = HEIGHT - 10
        self.speedx = 0
        keystate = pygame.key.get_pressed()
        # 如果按键按下的是左键
        if keystate[pygame.K_LEFT]:
            self.speedx = -5
        # 如果按建按下的是右键
        if keystate[pygame.K_RIGHT]:
            self.speedx = 5
        # 空格按键监听
        if keystate[pygame.K_SPACE]:
            self.shoot()
        # 越界检测  飞机左边x坐标是3  -5  =-2  =0
        if self.rect.left < 0:
            self.rect.left = 0
        if self.rect.right > WIDTH:
            self.rect.right = WIDTH
        # 让飞机加上 速度
        # 15 + 5 =20
        # self.rect.x + self.speedx = self.rect.x
        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
            # 判断火力值
            if self.power == 1:
                # 生产(穿建)一颗子弹
                bullet = Bullet(self.rect.centerx, self.rect.top)
                # 将子弹添加到精灵组合中
                all_sprites.add(bullet)
                # 将子弹添加到子弹的精灵组合中
                bullets.add(bullet)
                # 播放射击音效
                shooting_sound.play()
            if self.power == 2:
                bullet1 = Bullet(self.rect.left, self.rect.top)
                bullet2 = Bullet(self.rect.right, self.rect.top)
                all_sprites.add(bullet1)
                all_sprites.add(bullet2)
                bullets.add(bullet1)
                bullets.add(bullet2)
                shooting_sound.play()
            # 火力值大于等于3的情况
            if self.power >= 3:
                bullet1 = Bullet(self.rect.left, self.rect.top)
                bullet2 = Bullet(self.rect.right, self.rect.top)
                # 导弹
                missile1 = Missile(self.rect.centerx, self.rect.top)

                all_sprites.add(bullet1)
                all_sprites.add(bullet2)
                all_sprites.add(missile1)

                bullets.add(bullet1)
                bullets.add(bullet2)
                bullets.add(missile1)
                shooting_sound.play()
                missile_sound.play()

    # 飞机的隐身函数
    def hide(self):
        self.hidden = True
        self.hide_timer = pygame.time.get_ticks()
        self.rect.center = (WIDTH / 2, HEIGHT + 200)
    # 飞机的火力增加函数
    def powerup(self):
        self.power += 1
        self.power_time = pygame.time.get_ticks()

# 子弹类
class Bullet(pygame.sprite.Sprite):
    # 构造函数
    # 飞机在发射子弹的时候,由飞机当前位置计算子弹出现的x,y坐标
    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()
        # 底部边y坐标
        self.rect.bottom = y
        # 中心点x坐标
        self.rect.centerx = x
        # 子弹的移动速度
        self.speedy = -10
    # 子弹的更新函数
    def update(self):
        self.rect.y +=self.speedy
        if self.rect.y <= 0-self.rect.top:
            self.kill()

# 陨石类
class Mob(pygame.sprite.Sprite):
    # 构造函数
    def __init__(self):
        # 执行父类的构造函数
        pygame.sprite.Sprite.__init__(self)
        # 陨石图片  随机从列表中选择一个
        self.image_orig = random.choice(metor_images)
        # 设置陨石图片不透明
        self.image_orig.set_colorkey(BLACK)
        # 复制陨石的图片
        self.image = self.image_orig.copy()
        # 陨石图片的矩形
        self.rect = self.image.get_rect()
        # 陨石的半径
        self.radius = int(self.rect.width * .90 / 2)
        # 陨石的x坐标  x随机值  范围: 0 ~ 屏幕宽度-陨石本身的宽度
        self.rect.x = random.randrange(0, WIDTH - self.rect.width)
        # 陨石的y坐标   y随机值  范围: -150 ~ -100
        self.rect.y = random.randrange(-150, -100)
        # 陨石的x方向移动速度   陨石可以左右运动
        self.speedx = random.randrange(-3, 3)
        # 陨石的y方向移动速度   陨石只允许向下  不允许向上
        self.speedy = random.randrange(5, 20)
        # 陨石的旋转角度
        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.left > WIDTH + 20):
            # 重新生成陨石(为陨石重新设定坐标)
            self.rect.x = random.randrange(0, WIDTH - self.rect.width)
            self.rect.y = random.randrange(-100, -40)
            self.speedy = random.randrange(1, 8)

# 爆炸类
class Explosion(pygame.sprite.Sprite):
    # 构造函数
    def __init__(self, center, size):
        # 执行父类的构造函数
        pygame.sprite.Sprite.__init__(self)
        # 爆炸范围大小
        self.size = size
        # 爆炸图片
        self.image = explosion_anim[self.size][0]
        # 爆炸图片矩形
        self.rect = self.image.get_rect()
        # 设置爆炸矩形的中心点
        self.rect.center = center
        # 动画开始时间
        self.frame = 0
        # 动画间隔时间
        self.frame_rate = 75
        # 最后一次刷新的时间
        self.last_update = pygame.time.get_ticks()

    # 爆炸类更新函数
    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(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

# 奖励类
class Pow(pygame.sprite.Sprite):
    def __init__(self, center):
        pygame.sprite.Sprite.__init__(self)
        self.type = random.choice(['shield', 'dun'])
        # 图片
        self.image = powerup_images[self.type]
        self.image.set_colorkey(BLACK)
        self.rect = self.image.get_rect()
        self.rect.center = center
        # 移动速度
        self.speedy = 2
    def update(self):
        self.rect.y += self.speedy
        # 将出屏幕的奖励kill掉
        if self.rect.top > HEIGHT:
            self.kill()
# 导弹类
class Missile(pygame.sprite.Sprite):
    def __init__(self, x, y):
        pygame.sprite.Sprite.__init__(self)
        self.image = missile_img
        self.rect = self.image.get_rect()
        self.rect.bottom = y
        self.rect.centerx = x
        self.speedy = -10
    def update(self):
        self.rect.y += self.speedy
        if self.rect.bottom < 0:
            self.kill()


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

# 游戏运行
# 游戏运行状态
# 布尔值 False True
running = True
# 主菜单显示状态
menu_display = True

# 绘制飞机生命条的函数
def draw_shield_bar(surf, x, y, shield):
    # 在第一次执行这个函数的时候 取血量的最大值
    shield = max(shield, 0)
    # 填充长度
    fill = (shield / 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, x, y, lives, img):
    for i in range(lives):
        image_rect = img.get_rect()
        image_rect.x = x + 30 * i
        image_rect.y = y
        surf.blit(img, image_rect)


# 不可控的循环
while running:
    # 缩进 标准python下的缩进是四个空格
    # 条件语句
    if menu_display:
        # 显示主菜单  定义函数
        main_menu()
        # pygame延迟操作
        pygame.time.wait(3000)
        # 停止播放主菜单背景音乐
        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)
        # 陨石的精灵组合
        mobs = pygame.sprite.Group()
        for i in range(8):
            # 新建陨石
            newmob()

        # 子弹的精灵组合
        bullets = pygame.sprite.Group()
        # 奖励的精灵组合
        powerups = pygame.sprite.Group()
        # 初始分数
        score = 0

    clock.tick(FPS)
    # 循环获取用户事件
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_ESCAPE:
                running = False
    # 利用精灵组合执行精灵的变化函数
    all_sprites.update()

    # 子弹与陨石的碰撞  pygame提供的精灵组合与精灵组合之间的碰撞检测函数
    hits = pygame.sprite.groupcollide(mobs, bullets, True, True)
    for hit in hits:
        # 添加分数
        score += 50 - hit.radius
        # 播放爆炸音效
        random.choice(expl_sounds).play()
        # 产生爆炸效果
        exp1 = Explosion(hit.rect.center, 'lg')
        # 将爆炸效果添加到精灵组合中
        all_sprites.add(exp1)
        # 随机产生相应奖励
        if random.random() > 0.9:
            pow = Pow(hit.rect.center)
            all_sprites.add(pow)
            powerups.add(pow)
        # 产生新的陨石
        newmob()
    # 飞机与陨石的碰撞
    hits = pygame.sprite.spritecollide(player, mobs, True, pygame.sprite.collide_circle)
    for hit in hits:
        # 飞机减少生命值
        player.sheild -= hit.radius * 2
        # 产生爆炸效果 陨石
        expl = Explosion(hit.rect.center, 'sm')
        all_sprites.add(expl)
        # 产生新的陨石
        newmob()
        # 判断飞机的生命值是否小于等于0
        if player.sheild <= 0:
            # 播放飞机去世音效
            player_die_sound.play()
            # 飞机爆炸效果
            death_explosion = Explosion(player.rect.center, 'player')
            all_sprites.add(death_explosion)
            # 飞机隐身效果
            player.hide()
            # 飞机的生命-1
            player.lives -= 1
            # 重新设置飞机的生命值100
            player.sheild = 100
    # 飞机与奖励的碰撞
    hits = pygame.sprite.spritecollide(player, powerups, True)
    for hit in hits:
        # 火力值奖励
        if hit.type == 'shield':
            player.powerup()
        # 生命值(盾)奖励
        if hit.type == 'dun':
            player.sheild += random.randrange(10, 30)
            if player.sheild >= 100:
                player.sheild = 100

    # 判断飞机的生命是否为0 同时  飞机爆炸动画结束
    if player.lives == 0 and not death_explosion.alive():
        # 设置游戏状态为False
        running = False
    # 刷新屏幕
    # 将游戏屏幕填充为黑色
    screen.fill(BLACK)
    # 设置游戏运行背景图片
    screen.blit(background, background_rect)
    # 绘制精灵到屏幕中
    all_sprites.draw(screen)
    # 绘制分数
    draw_text(screen, str(score), 18, WIDTH/2, 10)
    # 绘制生命条
    draw_shield_bar(screen, 5, 5, player.sheild)
    # 绘制小飞机
    draw_lives(screen, WIDTH-100, 5, player.lives, player_mini_img)
    pygame.display.flip()

以上就是用python开发小游戏的全部过程和代码,希望你用的顺心!!!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值