Python基础 -- 06 基础语法(pyGame)

一、Pygame


1、通过pip导入pygame的包

pip install pygame


2、导入飞机大战需要的资源文件到项目根路径下




3、Pygame的基本使用


import time
# 导入pygame的包
import pygame

# 初始化pygame,让计算机硬件做准备
pygame.init()

# 创建一个窗口对象,并指定宽和高
pygame.display.set_mode([500, 700])

# 导入磁盘上的图片资源文件,返回一个图片对象
image = pygame.image.load("res/app.ico")

# 设置窗口显式的图标
pygame.display.set_icon(image)

# 设置窗口名称
pygame.display.set_caption("飞机大战v1.0")

time.sleep(5)


4、pygame的图片基本处理


# 导入pygame的包
import pygame
import time

# 初始化pygame,让计算机硬件做准备
pygame.init()

# 初始化窗口对象的宽高属性
WINDOW_WIDTH = 512
WINDOW_HEIGHT = 768

# 创建一个窗口对象,并指定宽和高,返回一个窗口对象
window = pygame.display.set_mode([WINDOW_WIDTH, WINDOW_HEIGHT])

# 加载图片资源文件,返回图片对象
# 背景图
bg_image = pygame.image.load("res/img_bg_level_1.jpg")
# 飞机图片
plane_image = pygame.image.load("res/hero2.png")

# 绘制图片,将图片的坐标原点放到窗口的指定位置,参数1:图片对象;参数2:窗口的坐标(窗口左上角为原点(0,0))
# 先绘制背景图,再绘制飞机图,否则背景图会覆盖飞机图,导致不显示飞机图
window.blit(bg_image, (0, 0))
window.blit(plane_image, (100, 200))

# 刷新窗口,让图片加载到窗口中
pygame.display.update()

time.sleep(3)


5、pygame的图片移动处理 -- rect矩形对象


# 导入pygame的包
import pygame
import time

# 初始化pygame,让计算机硬件做准备
pygame.init()

# 初始化窗口对象的宽高属性
WINDOW_WIDTH = 512
WINDOW_HEIGHT = 768

window = pygame.display.set_mode([WINDOW_WIDTH, WINDOW_HEIGHT])

bg_image = pygame.image.load("res/img_bg_level_1.jpg")

window.blit(bg_image, (0, 0))

plane_image = pygame.image.load("res/hero2.png")

"""
    创建这个图片的矩形对象,这个对象其实就是一个元组
    (图片原点在x轴坐标, 图片原点在y轴坐标, 图片的宽, 图片的高)
    默认x,y轴的坐标都是0
"""
plane_rect = plane_image.get_rect()
# print(plane_rect)           # <rect(0, 0, 120, 78)>

"""
    通过矩形对象的 move_ip(x, y) 这个方法,可以将矩形对象相对于当前位置移动指定的偏移量
    
    if 按下键盘上键:
        plane_rect.move_ip(0, -偏移量)
    if 按下键盘下键:
        plane_rect.move_ip(0, +偏移量)
    if 按下键盘左键:
        plane_rect.move_ip(-偏移量, 0)
    if 按下键盘右键:
        plane_rect.move_ip(+偏移量, 0)
        
"""
# 将飞机图片移动到屏幕中间爱你
plane_rect.move_ip(WINDOW_WIDTH / 2 - plane_rect[2] / 2, WINDOW_HEIGHT / 2 - plane_rect[3] / 2)
# print(plane_rect)           # <rect(196, 345, 120, 78)>

# 根据矩形对象设置飞机图片位置
window.blit(plane_image, (plane_rect[0], plane_rect[1]))

# 动态让飞机图片每次向上偏移1
while True:
    plane_rect.move_ip(0, -1)

    window.blit(bg_image, (0, 0))

    window.blit(plane_image, (plane_rect[0], plane_rect[1]))

    # 刷新窗口,让图片加载到窗口中
    pygame.display.update()


time.sleep(3)


6、pygame的事件处理


import sys  # sys是处理和程序相关的操作
import pygame

pygame.init()

WINDOW_WIDTH = 512
WINDOW_HEIGHT = 768

window = pygame.display.set_mode([WINDOW_WIDTH, WINDOW_HEIGHT])

bg_image = pygame.image.load("res/img_bg_level_1.jpg")

plane_image = pygame.image.load("res/hero2.png")
plane_rect = plane_image.get_rect()
plane_rect.move_ip(WINDOW_WIDTH / 2 - plane_rect[2] / 2, WINDOW_HEIGHT / 2 - plane_rect[3] / 2)

# 设置飞机移动速度
speed = 1

while True:
    window.blit(bg_image, (0, 0))
    window.blit(plane_image, (plane_rect[0], plane_rect[1]))

    """
        pygame.event.get() 获取所有的单次事件,并将所有的事件放入一个列表,并返回
    """
    # 获取事件列表
    evenList = pygame.event.get()
    # 遍历事件列表,获取每个事件
    for event in evenList:
        # 判断事件如果是点击退出事件
        if event.type == pygame.QUIT:
            # 如果是,就结束程序
            sys.exit()  # 直接结束程序的运行(线程)
            pygame.quit()   # 退出pygame包的运行程序
        # 判断是否是键盘按下事件
        if event.type == pygame.KEYDOWN:
            # 判断按键是什么
            if event.key == pygame.K_ESCAPE:
                # 如果是退出键,就退出程序
                sys.exit()
                pygame.quit()
            if event.key == pygame.K_SPACE or event.key == pygame.K_j:
                # 按下的是空格或者J键,用来发射子弹
                print("发射子弹")
            if event.key == pygame.K_DOWN:
                # 按的是上键,向上移动飞机
                pass

    """
        pygame.key.get_pressed() : 获取键盘上一直被按下的键,返回一个元组
        (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0 ...)
        该元组是没个键对应的ASCII码表的元组,值为1的地方,即表示当前索引代表的元素的按键被一直按下
    """
    # 获取键盘中的连续按键(一直按着键盘不松)
    pressed_key = pygame.key.get_pressed()

    # 判断按下的键是什么
    # pygame.K_UP 得到的是上键的数字,对应数字(索引)在元组中如果是1,则if判断成立,即表示上键一直被按着
    if pressed_key[pygame.K_UP]:
        # 上键一直被按着,向上移动
        # 向上移动前需要先判断飞机是否超出屏幕区域,如果超出,则不移动
        if plane_rect[1] <= 0:
            pass
        else:
            plane_rect.move_ip(0, -speed)

    if pressed_key[pygame.K_DOWN]:
        # 向下移动之前判断是否超出屏幕区域,超出不移动
        if plane_rect[1] >= WINDOW_HEIGHT - plane_rect[3]:
            pass
        else:
            plane_rect.move_ip(0, speed)

    if pressed_key[pygame.K_LEFT]:
        # 向做移动之前判断飞机是否超出屏幕区域,超出不移动
        if plane_rect[0] <= 0:
            pass
        else:
            plane_rect.move_ip(-speed, 0)

    if pressed_key[pygame.K_RIGHT]:
        # 向右移动之前判断是否超出屏幕区域,超出不移动
        if plane_rect[0] >= WINDOW_WIDTH - plane_rect[2]:
            pass
        else:
            plane_rect.move_ip(speed, 0)

    window.blit(bg_image, (0, 0))
    window.blit(plane_image, (plane_rect[0], plane_rect[1]))

    pygame.display.update()


7、背景图(地图)滚动效果处理


import pygame

pygame.init()

WINDOW_WIDTH = 512
WINDOW_HEIGHT = 768

window = pygame.display.set_mode([WINDOW_WIDTH, WINDOW_HEIGHT])

bg1_image = pygame.image.load("res/img_bg_level_1.jpg")
bg2_image = pygame.image.load("res/img_bg_level_1.jpg")

bg1_rect = bg1_image.get_rect()
bg2_rect = bg2_image.get_rect()

# 设置第一次绘制背景图时y轴坐标的位置
bg1_rect[1] = -WINDOW_HEIGHT
bg2_rect[1] = 0

# 设置变量,作为绘制的y轴的坐标值,每次循环(滚动)之后会增加
bg1_y = bg1_rect[1]
bg2_y = bg2_rect[1]

# 定义背景滚动速度
speed = 1
while True:

    pygame.event.get()

    # x轴坐标不变,每次按照偏移y轴坐标量进行绘制
    window.blit(bg1_image, (bg1_rect[0], bg1_y))
    window.blit(bg2_image, (bg2_rect[0], bg2_y))

    # 如果第一张图的y轴到达坐标0的时候,需要重新将第一张图的y轴设置为初始值
    if bg1_y >= 0:
        bg1_y = -WINDOW_HEIGHT

    # 如果第二张图的y轴到达屏幕最下端的时候,需要重新将第二张图的y轴设置为初始值
    if bg2_y >= WINDOW_HEIGHT:
        bg2_y = 0

    # 每次循环,y轴的偏移量都增加一个速率
    bg1_y += speed
    bg2_y += speed

    # 更新window
    pygame.display.update()


8、pygame实现飞机大战的基本框架


# 导入pygame
import pygame
# 导入sys
import sys
# 导入random
import random

# 初始化pygame环境
pygame.init()

# 设定屏幕宽高常量
WINDOW_WIDTH = 512
WINDOW_HEIGHT = 768

# 构建窗口对象
window = pygame.display.set_mode([WINDOW_WIDTH, WINDOW_HEIGHT])

# ------------------------------定义背景图片自动滚动的效果 start--------------------------------------
bg1_image = pygame.image.load("res/img_bg_level_1.jpg")
bg2_image = pygame.image.load("res/img_bg_level_1.jpg")

# 获取两张背景图片的矩形对象
bg1_rect = bg1_image.get_rect()
bg2_rect = bg2_image.get_rect()

# 设置第一次绘制背景图时,两张图片y轴的起始位置
bg1_rect[1] = -WINDOW_HEIGHT
bg2_rect[1] = 0

# 设置变量,用来接收每次滚动时,两张图片 y 轴的坐标值,初始值为两张图片y轴的初始值
bg1_y = bg1_rect[1]
bg2_y = bg2_rect[1]
# ------------------------------定义背景图片自动滚动的效果 end--------------------------------------

# ------------------------------定义飞机移动的效果 start--------------------------------------
# 初始化英雄飞机对象
hero_plane = pygame.image.load("res/hero.png")
# 获取英雄飞机的矩形对象
hero_rect = hero_plane.get_rect()
# 设置英雄飞机矩形对象的偏移量(即首次登场时候所在的位置)
hero_rect.move_ip(WINDOW_WIDTH / 2 - hero_rect[2] / 2, WINDOW_HEIGHT - hero_rect[3])

# 随机初始化敌机对象
enemy_num = str(random.randint(1, 7))
enemy_plane = pygame.image.load("res/img-plane_" + enemy_num + ".png")
# 获取敌机的矩形对象
enemy_rect = enemy_plane.get_rect()
# 设置敌机首次出现的位置(在屏幕上方,最左边不能小于0,最右边不能大于屏幕长度-敌机度, y轴从-敌机高开始)
enemy_rect.move_ip(random.randint(0, WINDOW_WIDTH - enemy_rect[2]), -enemy_rect[3])

# 设置飞机移动速度以及背景图片移动速度
plane_speed = 3
bg_speed = 1
# ------------------------------定义飞机移动的效果 start--------------------------------------


# 定义退出游戏操作的函数
def game_over():
    sys.exit()
    pygame.quit()


# 定义显示分数操作的函数
def show_score():
    # 设置起始分数
    score = 10
    # 设置字体的样式和大小,返回字体对象
    font = pygame.font.SysFont('SimHei', 42)
    # 设置字体属性 render(文本内容,抗锯齿,颜色(RBG数值)), 返回文字对象
    text_obj = font.render("得分:%s" % score, 1, (255, 255, 255))
    # 获取文字矩形对象,并且设置矩形对象的位置
    text_rect = text_obj.get_rect()
    text_rect.move_ip(10, 10)
    # 在指定的位置绘制文字对象


# 游戏开始,进行循环
while True:
    # ------------------------------处理背景图片自动滚动的效果 start--------------------------------------
    # x轴不变,按照y轴变量进行背景图片绘制
    window.blit(bg1_image, (bg1_rect[0], bg1_y))
    window.blit(bg2_image, (bg2_rect[0], bg2_y))

    # 如果第一张图片的y轴到大屏幕最下端,重新设置y轴为初始值
    if bg1_y >= 0:
        bg1_y = -WINDOW_HEIGHT

    # 如果第二张图片的y轴原点到大屏幕最下端,重新设置y轴为初始值
    if bg2_y >= WINDOW_HEIGHT:
        bg2_y = 0

    # 每次循环,变量增加
    bg1_y += bg_speed
    bg2_y += bg_speed
    # ------------------------------处理背景图片自动滚动的效果 end--------------------------------------

    # ------------------------------处理飞机移动的效果 start--------------------------------------
    # 绘制敌我飞机起始位置
    window.blit(hero_plane, (hero_rect[0], hero_rect[1]))
    window.blit(enemy_plane, (enemy_rect[0], enemy_rect[1]))

    # 设置地方飞机每次的偏移量
    enemy_rect.move_ip(0, plane_speed)      # 敌方飞机目前只能向 y 轴飞

    # 设置地方飞机的活动范围
    if enemy_rect[1] >= WINDOW_HEIGHT:  # 如果地方飞机飞出屏幕区域,从新设置地方飞机的起始位置(地方飞机时随机 x 轴起始位置)
        enemy_rect.move_ip(-enemy_rect[0], -enemy_rect[1])   # 将目前飞机的偏移量都减掉,回到首次偏移之前的位置
        enemy_rect.move_ip(random.randint(0, WINDOW_WIDTH-enemy_rect[2]), -enemy_rect[3])

    # 处理键盘和鼠标的单击事件
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            game_over()

        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_ESCAPE:
                game_over()

            if event.key == pygame.K_SPACE:
                print("发射子弹~~")

            if event.key == pygame.K_UP:
                if hero_rect[1] > 0:
                    hero_rect.move_ip(0, -plane_speed)

            if event.key == pygame.K_DOWN:
                if hero_rect[1] < WINDOW_HEIGHT - hero_rect[3]:
                    hero_rect.move_ip(0, plane_speed)

            if event.key == pygame.K_LEFT:
                if hero_rect[0] > 0:
                    hero_rect.move_ip(-plane_speed, 0)

            if event.key == pygame.K_RIGHT:
                if hero_rect[0] < WINDOW_WIDTH - hero_rect[2]:
                    hero_rect.move_ip(plane_speed, 0)

    # 处理键盘的持续按下事件
    pressed_keys = pygame.key.get_pressed()

    if pressed_keys[pygame.K_SPACE] or pressed_keys[pygame.K_j]:
        print("持续发射子弹~~")

    if pressed_keys[pygame.K_UP]:
        if hero_rect[1] > 0:
            hero_rect.move_ip(0, -plane_speed)

    if pressed_keys[pygame.K_DOWN]:
        if hero_rect[1] < WINDOW_HEIGHT - hero_rect[3]:
            hero_rect.move_ip(0, plane_speed)

    if pressed_keys[pygame.K_LEFT]:
        if hero_rect[0] > 0:
            hero_rect.move_ip(-plane_speed, 0)

    if pressed_keys[pygame.K_RIGHT]:
        if hero_rect[0] < WINDOW_WIDTH - hero_rect[2]:
            hero_rect.move_ip(plane_speed, 0)

    # 显示字体
    show_score()

    # 刷新窗口
    pygame.display.update()


二、使用面向对象的思想进行飞机大战的实现


1、飞机大战的基本游戏窗口


# 导入pygame
import pygame
import sys

# 设置基本的窗口信息
WINDOW_WIDTH = 512
WINDOW_HEIGHT = 768


# 创建游戏窗口
class GameWindow(object):
    def __init__(self):
        # 初始化pygame
        pygame.init()
        # 设置窗口参数
        self.window = pygame.display.set_mode([WINDOW_WIDTH, WINDOW_HEIGHT])

    # 启动游戏,游戏就是一个大的循环
    def run(self):
        while True:
            # 移动矩形对象
            self.active()
            # 根据移动过后的矩形对象坐标绘制图片
            self.draw()
            # 处理点击事件
            self.event()
            # 重新加载窗口对象
            self.update()
            

    # 处理各个矩形对象的坐标移动
    def active(self):
        pass

    # 根据矩形对象的坐标,重新对元素进行绘制
    def draw(self):
        pass

    # 处理键盘点击事件
    def event(self):
        # 遍历单击事件
        for event in pygame.event.get():
            # 判断时候时退出操作
            if event.type == pygame.QUIT:
                self.gameover()

            # 判断是否时键盘按下操作
            if event.type == pygame.KEYDOWN:
                # 如果时ESC键
                if event.key == pygame.K_ESCAPE:
                    self.gameover()
                # 如果

    # 更新窗口
    def update(self):
        pygame.display.update()

    # 退出游戏
    def gameover(self):
        pygame.quit()
        sys.exit()


# 定义main函数,作为程序运行的入口
def main():
    game = GameWindow()
    game.run()


if __name__ == "__main__":
    main()


2、飞机大战的背景图片添加


# 导入pygame
import pygame
import sys
import random

# 设置基本的窗口信息
WINDOW_WIDTH = 512
WINDOW_HEIGHT = 768


# 创建地图对象
class GameMap(object):
    def __init__(self):
        # 初始化地图数据
        self.num = str(random.randint(1,5))
        self.bg1_image = pygame.image.load("res/img_bg_level_" + self.num + ".jpg")
        self.bg2_image = pygame.image.load("res/img_bg_level_" + self.num + ".jpg")

        # 设置两张背景图的y轴初始值
        self.bg1_y = -WINDOW_HEIGHT
        self.bg2_y = 0

        # 设置地图滚动速度
        self.bg_speed = 1

    # 定义地图滚动的方法
    def map_scroll(self):
        if self.bg1_y >= 0:
            self.bg1_y = -WINDOW_HEIGHT

        if self.bg2_y >= WINDOW_HEIGHT:
            self.bg2_y = 0

        self.bg1_y += self.bg_speed
        self.bg2_y += self.bg_speed


# 创建游戏窗口
class GameWindow(object):
    def __init__(self):
        # 初始化pygame
        pygame.init()
        # 设置窗口参数
        self.window = pygame.display.set_mode([WINDOW_WIDTH, WINDOW_HEIGHT])
        # 创建地图对象
        self.map = GameMap()

    # 启动游戏,游戏就是一个大的循环
    def run(self):
        while True:
            # 移动矩形对象
            self.active()
            # 根据移动过后的矩形对象坐标绘制图片
            self.draw()
            # 处理点击事件
            self.event()
            # 重新加载窗口对象
            self.update()

    # 处理各个矩形对象的坐标移动
    def active(self):
        self.map.map_scroll()

    # 根据矩形对象的坐标,重新对元素进行绘制
    def draw(self):
        # 绘制背景图
        self.window.blit(self.map.bg1_image, (0, self.map.bg1_y))
        self.window.blit(self.map.bg2_image, (0, self.map.bg2_y))

    # 处理键盘点击事件
    def event(self):
        # 遍历单击事件
        for event in pygame.event.get():
            # 判断时候时退出操作
            if event.type == pygame.QUIT:
                self.gameover()

            # 判断是否时键盘按下操作
            if event.type == pygame.KEYDOWN:
                # 如果时ESC键
                if event.key == pygame.K_ESCAPE:
                    self.gameover()
                # 如果

    # 更新窗口
    def update(self):
        pygame.display.update()

    # 退出游戏
    def gameover(self):
        pygame.quit()
        sys.exit()


# 定义main函数,作为程序运行的入口
def main():
    game = GameWindow()
    game.run()


if __name__ == "__main__":
    main()


3、英雄飞机的添加和移动


# 导入pygame
import pygame
import sys
import random

# 设置基本的窗口信息
WINDOW_WIDTH = 512
WINDOW_HEIGHT = 768


"""
    创建飞机类
"""
class HeroPlane(object):
    def __init__(self):
        # 初始化飞机图片
        self.hero_plane_image = pygame.image.load("res/hero2.png")
        # 获得飞机的矩形对象
        self.hero_plane_rect = self.hero_plane_image.get_rect()
        # 设置飞机的初始位置
        self.hero_plane_rect.move_ip(WINDOW_WIDTH / 2 - self.hero_plane_rect[2] / 2, WINDOW_HEIGHT - self.hero_plane_rect[3])
        # 定义飞机移动速度
        self.hero_plane_speed = 2

    # 定义飞机移动的方法
    def move_up(self):
        if self.hero_plane_rect[1] > 0:
            self.hero_plane_rect.move_ip(0, -self.hero_plane_speed)

    def move_down(self):
        if self.hero_plane_rect[1] < WINDOW_HEIGHT - self.hero_plane_rect[3]:
            self.hero_plane_rect.move_ip(0, self.hero_plane_speed)

    def move_left(self):
        if self.hero_plane_rect[0] > 0:
            self.hero_plane_rect.move_ip(-self.hero_plane_speed, 0)

    def move_right(self):
        if self.hero_plane_rect[0] < WINDOW_WIDTH - self.hero_plane_rect[2]:
            self.hero_plane_rect.move_ip(self.hero_plane_speed, 0)

    # 定义发射子弹的方法
    def shot(self):
        print("发射子弹")


# 创建地图对象
class GameMap(object):
    def __init__(self):
        # 初始化地图数据
        self.num = str(random.randint(1,5))
        self.bg1_image = pygame.image.load("res/img_bg_level_" + self.num + ".jpg")
        self.bg2_image = pygame.image.load("res/img_bg_level_" + self.num + ".jpg")

        # 设置两张背景图的y轴初始值
        self.bg1_y = -WINDOW_HEIGHT
        self.bg2_y = 0

        # 设置地图滚动速度
        self.bg_speed = 1

    # 定义地图滚动的方法
    def map_scroll(self):
        if self.bg1_y >= 0:
            self.bg1_y = -WINDOW_HEIGHT

        if self.bg2_y >= WINDOW_HEIGHT:
            self.bg2_y = 0

        self.bg1_y += self.bg_speed
        self.bg2_y += self.bg_speed


# 创建游戏窗口
class GameWindow(object):
    def __init__(self):
        # 初始化pygame
        pygame.init()
        # 设置窗口参数
        self.window = pygame.display.set_mode([WINDOW_WIDTH, WINDOW_HEIGHT])
        # 创建地图对象
        self.map = GameMap()
        # 创建英雄飞机对象
        self.hero_plane = HeroPlane()

    # 启动游戏,游戏就是一个大的循环
    def run(self):
        while True:
            # 移动矩形对象
            self.active()
            # 根据移动过后的矩形对象坐标绘制图片
            self.draw()
            # 处理点击事件
            self.event()
            # 重新加载窗口对象
            self.update()

    # 处理各个矩形对象的坐标移动
    def active(self):
        # 让背景图滚动
        self.map.map_scroll()

    # 根据矩形对象的坐标,重新对元素进行绘制
    def draw(self):
        # 绘制背景图
        self.window.blit(self.map.bg1_image, (0, self.map.bg1_y))
        self.window.blit(self.map.bg2_image, (0, self.map.bg2_y))
        # 绘制英雄飞机图
        self.window.blit(self.hero_plane.hero_plane_image, (self.hero_plane.hero_plane_rect[0], self.hero_plane.hero_plane_rect[1]))

    # 处理键盘点击事件
    def event(self):
        # 遍历单击事件
        for event in pygame.event.get():
            # 判断是否是退出操作
            if event.type == pygame.QUIT:
                self.gameover()

            # 判断是否是键盘按下操作
            if event.type == pygame.KEYDOWN:
                # 如果时ESC键
                if event.key == pygame.K_ESCAPE:
                    self.gameover()
                # 如果是发射子弹
                if event.key == pygame.K_SPACE or event.key == pygame.K_j:
                    self.hero_plane.shot()

        # 获取连续按下事件
        pressed_keys = pygame.key.get_pressed()
        plane = self.hero_plane
        # 判断是什么连续按下事件
        if pressed_keys[pygame.K_UP]:
            if plane.hero_plane_rect[1] > 0:
                plane.hero_plane_rect.move_ip(0, -plane.hero_plane_speed)

        if pressed_keys[pygame.K_DOWN]:
            if plane.hero_plane_rect[1] < WINDOW_HEIGHT - plane.hero_plane_rect[3]:
                plane.hero_plane_rect.move_ip(0, plane.hero_plane_speed)

        if pressed_keys[pygame.K_LEFT]:
            if plane.hero_plane_rect[0] > 0:
                plane.hero_plane_rect.move_ip(-plane.hero_plane_speed, 0)

        if pressed_keys[pygame.K_RIGHT]:
            if plane.hero_plane_rect[0] < WINDOW_WIDTH - plane.hero_plane_rect[2]:
                plane.hero_plane_rect.move_ip(plane.hero_plane_speed, 0)

        if pressed_keys[pygame.K_SPACE] or pressed_keys[pygame.K_j]:
            self.hero_plane.shot()

    # 更新窗口
    def update(self):
        pygame.display.update()

    # 退出游戏
    def gameover(self):
        pygame.quit()
        sys.exit()


# 定义main函数,作为程序运行的入口
def main():
    game = GameWindow()
    game.run()


if __name__ == "__main__":
    main()


4、英雄飞机装备子弹并发射


# 导入pygame
import pygame
import sys
import random

# 设置基本的窗口信息
WINDOW_WIDTH = 512
WINDOW_HEIGHT = 768


"""
    创建子弹类
"""
class Bullet(object):
    def __init__(self):
        # 初始化子弹图片
        self.bullet_image = pygame.image.load("res/bullet_10.png")
        # 获取子弹矩形对象
        self.bullet_rect = self.bullet_image.get_rect()
        # 给子弹设置发射状态,True代表已经发射,False代表为发射,默认时Flase
        # 如果子弹时为发射状态,不做绘制,不做位置移动计算,也不做碰撞检测
        # 如果时发射状态,就做绘制,做位置移动计算,做碰撞检测
        self.is_shot = False
        # 设置子弹的移动速度
        self.bullet_speed = 5

    # 子弹移动的方法:子弹发射之后,是x轴不变,y轴一直在减少
    def move(self):
        self.bullet_rect.move_ip(0, -self.bullet_speed)
        # 当子弹超出屏幕范围,状态设置为False
        if self.bullet_rect[1] <= -self.bullet_rect[3]:
            self.is_shot = False

"""
    创建飞机类
"""
class HeroPlane(object):
    def __init__(self):
        # 初始化飞机图片
        self.hero_plane_image = pygame.image.load("res/hero2.png")
        # 获得飞机的矩形对象
        self.hero_plane_rect = self.hero_plane_image.get_rect()
        # 设置飞机的初始位置
        self.hero_plane_rect.move_ip(WINDOW_WIDTH / 2 - self.hero_plane_rect[2] / 2, WINDOW_HEIGHT - self.hero_plane_rect[3])
        # 定义飞机移动速度
        self.hero_plane_speed = 2
        # 创建有十发子弹的列表
        self.bullet_list = [Bullet() for _ in range(10)]

    # 定义飞机移动的方法
    def move_up(self):
        if self.hero_plane_rect[1] > 0:
            self.hero_plane_rect.move_ip(0, -self.hero_plane_speed)

    def move_down(self):
        if self.hero_plane_rect[1] < WINDOW_HEIGHT - self.hero_plane_rect[3]:
            self.hero_plane_rect.move_ip(0, self.hero_plane_speed)

    def move_left(self):
        if self.hero_plane_rect[0] > 0:
            self.hero_plane_rect.move_ip(-self.hero_plane_speed, 0)

    def move_right(self):
        if self.hero_plane_rect[0] < WINDOW_WIDTH - self.hero_plane_rect[2]:
            self.hero_plane_rect.move_ip(self.hero_plane_speed, 0)

    # 定义发射子弹的方法,每次只发射一发子弹
    def shot(self):
        for bullet in self.bullet_list:
            # 判断子弹是否时发射状态,如果不是,就取出子弹
            if not bullet.is_shot:
                # 设置子弹发射时候的 x 轴默认位置
                bullet.bullet_rect[0] = self.hero_plane_rect[0] + self.hero_plane_rect[2] / 2 - bullet.bullet_rect[2] / 2
                # 设置子弹发射时候的 y 轴默认位置
                bullet.bullet_rect[1] = self.hero_plane_rect[1] - bullet.bullet_rect[3] - 3
                # 子弹发射之后,修改在单的发射状态
                bullet.is_shot = True
                # 每次空格只发射一次子弹,发射之后,就停止循环
                break


# 创建地图对象
class GameMap(object):
    def __init__(self):
        # 初始化地图数据
        self.num = str(random.randint(1,5))
        self.bg1_image = pygame.image.load("res/img_bg_level_" + self.num + ".jpg")
        self.bg2_image = pygame.image.load("res/img_bg_level_" + self.num + ".jpg")

        # 设置两张背景图的y轴初始值
        self.bg1_y = -WINDOW_HEIGHT
        self.bg2_y = 0

        # 设置地图滚动速度
        self.bg_speed = 1

    # 定义地图滚动的方法
    def map_scroll(self):
        if self.bg1_y >= 0:
            self.bg1_y = -WINDOW_HEIGHT

        if self.bg2_y >= WINDOW_HEIGHT:
            self.bg2_y = 0

        self.bg1_y += self.bg_speed
        self.bg2_y += self.bg_speed


# 创建游戏窗口
class GameWindow(object):
    def __init__(self):
        # 初始化pygame
        pygame.init()
        # 设置窗口参数
        self.window = pygame.display.set_mode([WINDOW_WIDTH, WINDOW_HEIGHT])
        # 创建地图对象
        self.map = GameMap()
        # 创建英雄飞机对象
        self.hero_plane = HeroPlane()

    # 启动游戏,游戏就是一个大的循环
    def run(self):
        while True:
            # 移动矩形对象
            self.active()
            # 根据移动过后的矩形对象坐标绘制图片
            self.draw()
            # 处理点击事件
            self.event()
            # 重新加载窗口对象
            self.update()

    # 处理各个矩形对象的坐标移动
    def active(self):
        # 让背景图滚动
        self.map.map_scroll()
        # 遍历英雄飞机类中的子弹列表,如果状态时发射状态,就移动图片
        for bullet in self.hero_plane.bullet_list:
            if bullet.is_shot:
                # 执行子弹移动的方法
                bullet.move()

    # 根据矩形对象的坐标,重新对元素进行绘制
    def draw(self):
        # 绘制背景图
        self.window.blit(self.map.bg1_image, (0, self.map.bg1_y))
        self.window.blit(self.map.bg2_image, (0, self.map.bg2_y))
        # 绘制英雄飞机图
        self.window.blit(self.hero_plane.hero_plane_image, (self.hero_plane.hero_plane_rect[0], self.hero_plane.hero_plane_rect[1]))
        # 绘制子弹图
        # 遍历子弹列表,判断子弹是否为发射状态,如果是,就绘制
        for bullet in self.hero_plane.bullet_list:
            if bullet.is_shot:
                # 绘制子弹图片
                self.window.blit(bullet.bullet_image, (bullet.bullet_rect[0], bullet.bullet_rect[1]))

    # 处理键盘点击事件
    def event(self):
        # 遍历单击事件
        for event in pygame.event.get():
            # 判断是否是退出操作
            if event.type == pygame.QUIT:
                self.gameover()

            # 判断是否是键盘按下操作
            if event.type == pygame.KEYDOWN:
                # 如果时ESC键
                if event.key == pygame.K_ESCAPE:
                    self.gameover()
                # 如果是发射子弹
                if event.key == pygame.K_SPACE or event.key == pygame.K_j:
                    self.hero_plane.shot()

        # 获取连续按下事件
        pressed_keys = pygame.key.get_pressed()
        plane = self.hero_plane
        # 判断是什么连续按下事件
        if pressed_keys[pygame.K_UP]:
            if plane.hero_plane_rect[1] > 0:
                plane.hero_plane_rect.move_ip(0, -plane.hero_plane_speed)

        if pressed_keys[pygame.K_DOWN]:
            if plane.hero_plane_rect[1] < WINDOW_HEIGHT - plane.hero_plane_rect[3]:
                plane.hero_plane_rect.move_ip(0, plane.hero_plane_speed)

        if pressed_keys[pygame.K_LEFT]:
            if plane.hero_plane_rect[0] > 0:
                plane.hero_plane_rect.move_ip(-plane.hero_plane_speed, 0)

        if pressed_keys[pygame.K_RIGHT]:
            if plane.hero_plane_rect[0] < WINDOW_WIDTH - plane.hero_plane_rect[2]:
                plane.hero_plane_rect.move_ip(plane.hero_plane_speed, 0)

        if pressed_keys[pygame.K_SPACE] or pressed_keys[pygame.K_j]:
            pass

    # 更新窗口
    def update(self):
        pygame.display.update()

    # 退出游戏
    def gameover(self):
        pygame.quit()
        sys.exit()


# 定义main函数,作为程序运行的入口
def main():
    game = GameWindow()
    game.run()


if __name__ == "__main__":
    main()



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值