Python学习笔记(3)---B站黑马程序员

Python学习笔记(1)—B站黑马程序员

Python学习笔记(2)—B站黑马程序员

Python学习笔记(3)—B站黑马程序员

文章目录

  • 五、项目实战——飞机大战
    • 001-Pycharm中安装pygame
    • 002-快速入门
      • (1)项目准备
      • (2)使用 pygame 创建图形窗口
      • (3)理解图像并实现图像绘制
      • (4)理解游戏循环和游戏时钟
      • (5)理解精灵和精灵组
    • 003-游戏框架搭建
      • (1)明确主程序职责
      • (2)实现主程序类
      • (3)准备游戏精灵组
    • 004-游戏背景
      • (1)背景交替滚动
      • (2)显示游戏背景
      • (3)简化代码
    • 005-敌机
      • (1)使用定时器添加敌机
      • (2)设计Enemy类
    • 006-英雄和子弹
      • (1)设计英雄和子弹类
      • (2)创建和移动英雄
      • (3)创建和发射子弹
    • 007-碰撞检测
  • 六、Vi

五、项目实战——飞机大战

001-Pycharm中安装pygame

(1)点击pycharm下方的Terminal:

在这里插入图片描述
(2)输入命令:pip install pygame
在这里插入图片描述
(3)输入命令验证pygame是否安装:python -m pygame.examples.aliens
Python学习笔记(3)---B站黑马程序员_第1张图片

002-快速入门

Python学习笔记(3)---B站黑马程序员_第2张图片

(1)项目准备

Python学习笔记(3)---B站黑马程序员_第3张图片

游戏素材评论区有,这里给出链接:

飞机大战游戏素材

移动静止的图像产生动画效果

(2)使用 pygame 创建图形窗口

Python学习笔记(3)---B站黑马程序员_第4张图片
Python学习笔记(3)---B站黑马程序员_第5张图片
Python学习笔记(3)---B站黑马程序员_第6张图片
Python学习笔记(3)---B站黑马程序员_第7张图片
Python学习笔记(3)---B站黑马程序员_第8张图片

游戏中的所有元素(物体)都是以 矩形区域 来描述位置的
通过四个要素(x, y)物体在游戏窗口中的位置(物体所在矩形区域的左上角),
		  (width, height)物体所在矩形区域的宽度和高度,来描述这个矩形区域。

python提供pygame.Rect类来描述矩形区域,这个类中很多属性,如上图。
pygame.Rect(x, y, width, height) ---> 创建对象
size属性返回一个元组(width, height)

不执行 pygame.init()方法,同样可以使用 pygame.Rect

Python学习笔记(3)---B站黑马程序员_第9张图片
Python学习笔记(3)---B站黑马程序员_第10张图片
Python学习笔记(3)---B站黑马程序员_第11张图片
Python学习笔记(3)---B站黑马程序员_第12张图片

(3)理解图像并实现图像绘制

Python学习笔记(3)---B站黑马程序员_第13张图片
Python学习笔记(3)---B站黑马程序员_第14张图片
Python学习笔记(3)---B站黑马程序员_第15张图片
Python学习笔记(3)---B站黑马程序员_第16张图片

Python学习笔记(3)---B站黑马程序员_第17张图片

上面图像的小格子是透明区域

Python学习笔记(3)---B站黑马程序员_第18张图片

(4)理解游戏循环和游戏时钟

Python学习笔记(3)---B站黑马程序员_第19张图片

每次调用update方法会将之前所有绘制的结果,一次性更新到游戏屏幕上。
每次调用update方法得到的结果是帧,一般要达到每秒调用60次update方法。
游戏中的动画效果,大部分是通过静态图像移动显示的。

Python学习笔记(3)---B站黑马程序员_第20张图片
Python学习笔记(3)---B站黑马程序员_第21张图片
Python学习笔记(3)---B站黑马程序员_第22张图片
Python学习笔记(3)---B站黑马程序员_第23张图片

英雄(飞机)每移动一次,背景图片就要被重新绘制一次,否则英雄会有残影。
在这里插入图片描述

当飞机“完全”从上方飞出屏幕之后,再将飞机移动到屏幕底部:
	两种方法:
	if hero_rect.y + hero_rect.height <= 0:
		hero_rect.y = 700
	或者
	hero_rect.bottom = hero_rect.y + hero_rect.height
	if hero_rect.bottom <= 0:
		hero_rect.y = 700 

Python学习笔记(3)---B站黑马程序员_第24张图片
Python学习笔记(3)---B站黑马程序员_第25张图片

pygame.event.get()可以获得用户所有的操作:
	鼠标移动,按键盘,关闭窗口等等

上面的代码,点击叉号 是无法关闭游戏窗口的,下面演示如何关闭游戏窗口:

Python学习笔记(3)---B站黑马程序员_第26张图片
Python学习笔记(3)---B站黑马程序员_第27张图片

(5)理解精灵和精灵组

Python学习笔记(3)---B站黑马程序员_第28张图片

Python学习笔记(3)---B站黑马程序员_第29张图片

在一个游戏中,有很多游戏对象。
对于每一个游戏对象,都要设置它的图像image,位置rect等属性和更新位置update等方法,
	如果一个一个创建游戏对象很麻烦,所以pygame提供里两个类:sprite是精灵的意思。
	pygame.sprite.Sprite ---> 专门设置游戏对象的图像,位置等属性和更新位置等方法
	pygame.sprite.Group ---> 游戏对象组,放置多个游戏对象,可以同时设置多个游戏对象

注意:pygame.sprite.Sprite类中本身是没有image和rect两个属性的,要在它的派生子类中设置
	 并且默认的update方法中也没有写任何代码,要在子类中重写。

Python学习笔记(3)---B站黑马程序员_第30张图片
如果一个类的父类不是object,在重写初始化方法__init__时,要先super()调用一个父类的__init__方法,因为父类的__init__也写有代码,需要执行,而子类重写__init__方法会覆盖父类的init方法,导致父类的init方法无法执行。
Python学习笔记(3)---B站黑马程序员_第31张图片
在这里插入图片描述
Python学习笔记(3)---B站黑马程序员_第32张图片

Python学习笔记(3)---B站黑马程序员_第33张图片
Python学习笔记(3)---B站黑马程序员_第34张图片

import pygame
from plane_sprites import *

pygame.init()

# 创建游戏窗口 宽480像素 高700像素,返回游戏屏幕
screen = pygame.display.set_mode((480, 700))

# 绘制背景图像
# 1>加载图像数据
background = pygame.image.load("./images/background.png")

# 2> blit 设置图像位置:(0, 0) 图像的左上角放在游戏窗口左上角
screen.blit(background, (0, 0))

# 3> update 更新屏幕显示
# pygame.display.update()

# 绘制英雄的飞机图像
hero = pygame.image.load("./images/me1.png")
screen.blit(hero, (200, 500))

# 最后调用一次update方法即可
pygame.display.update()


# 创建游戏时钟对象
clock = pygame.time.Clock()

# 1.定义英雄的初始位置
hero_rect = pygame.Rect(150, 500, 102, 126)


# 创建敌机精灵
enemy1 = GameSprite("./images/enemy1.png")
enemy2 = GameSprite("./images/enemy1.png", 2)
enemy2.rect.x = 200
# 创建敌机精灵组
enemy_group = pygame.sprite.Group(enemy1, enemy2)


# 游戏循环,让游戏窗口一直保持(游戏循环,意味着游戏开始)
while True:
    # 设置游戏刷新帧率
    clock.tick(60)

    # 监听事件(同一时刻可能会发生多个事件,所以用for)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            print("游戏结束。。。")

            # 卸载所有游戏模块
            pygame.quit()

            # 终止程序执行(因为有for和while,所以不能使用break)
            exit()

    # 2.更新英雄位置
    hero_rect.y -= 1

    # 3.如果移出屏幕,则将英雄从顶部移动到屏幕底部

    if hero_rect.y + hero_rect.height <= 0:
        hero_rect.y = 700

    # 4.绘制背景图片(英雄每移动一次,背景图片就要被重新绘制一次,否则会出现英雄的残影)
    screen.blit(background, (0, 0))

    # 5.绘制英雄图像
    screen.blit(hero, hero_rect)


    # 让精灵组调用两个方法
    # update--->调用精灵组的update方法可以让每一个精灵分别调用自己的update方法(让组中的所有精灵更新位置)
    enemy_group.update()
    # draw(self,surface屏幕对象)--->将所有的精灵图像显示到屏幕上(在screen上绘制所有的精灵)
    enemy_group.draw(screen)


    # 6.更新显示
    pygame.display.update()

pygame.quit()

003-游戏框架搭建

Python学习笔记(3)---B站黑马程序员_第35张图片

(1)明确主程序职责

Python学习笔记(3)---B站黑马程序员_第36张图片

一个游戏主程序的职责有两个:
	游戏初始化:init
		设置游戏窗口
		创建游戏时钟
		创建精灵/精灵组 --->创建一个私有方法__create_sprites专门处理
			
	游戏循环(即游戏开始):start_game
		设置刷新帧率
		事件监听--->__event_handler
		碰撞检测--->__check_collide
		更新/绘制精灵组--->__update_sprites
		更新屏幕显示
		
		游戏结束--->__game_over 在事件监听到鼠标点击×时调用
		一个循环里写了太多东西,所以创建相应的私有方法解决部分操作。

Python学习笔记(3)---B站黑马程序员_第37张图片

(2)实现主程序类

Python学习笔记(3)---B站黑马程序员_第38张图片
Python学习笔记(3)---B站黑马程序员_第39张图片
在这里插入图片描述
Python学习笔记(3)---B站黑马程序员_第40张图片
Python学习笔记(3)---B站黑马程序员_第41张图片
Python学习笔记(3)---B站黑马程序员_第42张图片
Python学习笔记(3)---B站黑马程序员_第43张图片
Python学习笔记(3)---B站黑马程序员_第44张图片

import pygame
from plane_sprites import *


class PlaneGame(object):
    """飞机大战游戏主程序"""

    def __init__(self):
        print("游戏初始化")
        # 1.创建游戏的窗口(set_mode(元组) SCREEN_RECT.size--->元组(屏幕宽度,屏幕高度))
        self.screen = pygame.display.set_mode(SCREEN_RECT.size)
        # 2.创建游戏的时钟
        self.clock = pygame.time.Clock()
        # 3.调用私有方法,创建精灵和精灵组
        self.__create_sprites()

    def __create_sprites(self):
        pass

    def start_game(self):
        print("开始游戏。。。")

        while True:
            pass


# 测试当前程序:创建游戏对象,开始游戏
# __name__代表当前模块名,如果__name__=__main__则导入当前模块
if __name__ == "__main__":
    # 创建游戏对象
    game = PlaneGame()

    # 开始游戏
    game.start_game()

在这里插入图片描述
Python学习笔记(3)---B站黑马程序员_第45张图片

import pygame
from plane_sprites import *


class PlaneGame(object):
    """飞机大战游戏主程序"""

    def __init__(self):
        print("游戏初始化")
        # 1.创建游戏的窗口(set_mode(元组) SCREEN_RECT.size--->元组(屏幕宽度,屏幕高度))
        self.screen = pygame.display.set_mode(SCREEN_RECT.size)
        # 2.创建游戏的时钟
        self.clock = pygame.time.Clock()
        # 3.调用私有方法,创建精灵和精灵组
        self.__create_sprites()

    def __create_sprites(self):
        pass

    def start_game(self):
        print("开始游戏。。。")

        # 游戏循环(代表游戏开始)
        while True:
            # 1.设置刷新帧率(将刷新帧率设置为常量,在为主程序提供工具的plane_sprites文件中设置)
            self.clock.tick(FRAME_PER_SCREEN)
            # 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()

    def __check_collide(self):
        """碰撞检测"""
        pass

    def __update_sprites(self):
        """更新精灵组"""
        pass

    @staticmethod
    # 没有调用任何属性,应设置位静态方法
    def __game_over():
        """游戏结束"""

        print("游戏结束")
        pygame.quit()
        exit()


# 测试当前程序:创建游戏对象,开始游戏
# __name__代表当前模块名,如果__name__=__main__则导入当前模块
if __name__ == "__main__":
    # 创建游戏对象
    game = PlaneGame()

    # 开始游戏
    game.start_game()

(3)准备游戏精灵组

以下操作先不写,看懂就好,跳过这一步。
Python学习笔记(3)---B站黑马程序员_第46张图片
Python学习笔记(3)---B站黑马程序员_第47张图片

004-游戏背景

Python学习笔记(3)---B站黑马程序员_第48张图片

(1)背景交替滚动

Python学习笔记(3)---B站黑马程序员_第49张图片

Python学习笔记(3)---B站黑马程序员_第50张图片
Python学习笔记(3)---B站黑马程序员_第51张图片

父类GameSprite的update方法无法实现背景图片滚动,所以再写一个子类Background重写父类的update方法。

Python学习笔记(3)---B站黑马程序员_第52张图片

(2)显示游戏背景

Python学习笔记(3)---B站黑马程序员_第53张图片

(3)简化代码

Python学习笔记(3)---B站黑马程序员_第54张图片
Python学习笔记(3)---B站黑马程序员_第55张图片
Python学习笔记(3)---B站黑马程序员_第56张图片
在这里插入图片描述
Python学习笔记(3)---B站黑马程序员_第57张图片

005-敌机

在这里插入图片描述

(1)使用定时器添加敌机

Python学习笔记(3)---B站黑马程序员_第58张图片
Python学习笔记(3)---B站黑马程序员_第59张图片
Python学习笔记(3)---B站黑马程序员_第60张图片

(2)设计Enemy类

Python学习笔记(3)---B站黑马程序员_第61张图片
Python学习笔记(3)---B站黑马程序员_第62张图片
Python学习笔记(3)---B站黑马程序员_第63张图片

在plane_main.py的__create_sprites,添加敌机精灵组:
	敌机是定时被创建的,因此在这里不需要创建敌机精灵。

在这里插入图片描述

在plane_main.py的__event_handler,定时创建敌机,并添加到敌机精灵组:

Python学习笔记(3)---B站黑马程序员_第64张图片

在plane_main.py的__update_sprites,更新精灵组并绘制到屏幕上:

在这里插入图片描述
Python学习笔记(3)---B站黑马程序员_第65张图片

import random 写在 import pygame 上方
Python学习笔记(3)---B站黑马程序员_第66张图片
Python学习笔记(3)---B站黑马程序员_第67张图片

不做任何修改,敌机的初始位置如下的红方格:
Python学习笔记(3)---B站黑马程序员_第68张图片

敌机y方向的初始位置:bottom=0或者y=bottom-height
在这里插入图片描述
Python学习笔记(3)---B站黑马程序员_第69张图片
Python学习笔记(3)---B站黑马程序员_第70张图片

使用自带的kill()方法可以将精灵从精灵组中移出(即删除这个精灵)
因为__del__内置方法会在对象被销毁前调用,所以可以用来判断对象是否被销毁。
在 plane_sprites.py 中写如下代码:

Python学习笔记(3)---B站黑马程序员_第71张图片

006-英雄和子弹

Python学习笔记(3)---B站黑马程序员_第72张图片

(1)设计英雄和子弹类

Python学习笔记(3)---B站黑马程序员_第73张图片
Python学习笔记(3)---B站黑马程序员_第74张图片

(2)创建和移动英雄

首先将plane_sprites中的print()注释掉,太多了。然后给__del__中添加pass。
Python学习笔记(3)---B站黑马程序员_第75张图片
Python学习笔记(3)---B站黑马程序员_第76张图片
Python学习笔记(3)---B站黑马程序员_第77张图片
Python学习笔记(3)---B站黑马程序员_第78张图片

使用第二种方式
Python学习笔记(3)---B站黑马程序员_第79张图片
Python学习笔记(3)---B站黑马程序员_第80张图片
Python学习笔记(3)---B站黑马程序员_第81张图片

Python学习笔记(3)---B站黑马程序员_第82张图片

(3)创建和发射子弹

Python学习笔记(3)---B站黑马程序员_第83张图片
Python学习笔记(3)---B站黑马程序员_第84张图片
Python学习笔记(3)---B站黑马程序员_第85张图片
Python学习笔记(3)---B站黑马程序员_第86张图片
Python学习笔记(3)---B站黑马程序员_第87张图片

007-碰撞检测

Python学习笔记(3)---B站黑马程序员_第88张图片

groupcollide()方法--->两个精灵组中所有的精灵的碰撞检测:
	group1--->精灵组1
	group2--->精灵组2
	dokill1--->布尔类型,若设为True,则发生碰撞时销毁group1中发生碰撞的精灵
	dokill2--->布尔类型,若设为True,则发生碰撞时销毁group2中发生碰撞的精灵

Python学习笔记(3)---B站黑马程序员_第89张图片

spritecollide()方法--->判断某个精灵和指定精灵组中的精灵是否发生碰撞:
	sprite--->某个精灵
	group--->指定精灵组
	dokill--->布尔类型,如为True,则指定精灵组中发生碰撞的精灵会被自动移除
	该方法返回 指定精灵组中被移除的精灵列表

Python学习笔记(3)---B站黑马程序员_第90张图片

六、Vi

在评论区找到的讲义:

B站的Python课程讲义

你可能感兴趣的:(python,python,学习,pygame)