首页 > 编程语言 >Python学习笔记45:游戏篇之外星人入侵(六)

Python学习笔记45:游戏篇之外星人入侵(六)

时间:2024-07-27 23:27:58浏览次数:10  
标签:子弹 Python self 45 外星人 pygame screen ship event

前言

飞船模块的功能基本已经完成。今天继续完成子弹模块的功能。

子弹模块

子弹和飞船模块,在游戏逻辑中有一种生成与被生成的表面关系,因为子弹在游戏中是由飞船发射的。但是在我们实际抽象的过程中,飞船与子弹并不是is的关系,甚至可以说不是has的关系。因此我们需要将两个对象封装到不同模块来完成我们的功能。

考虑子弹是由飞船’'生成",我们在子弹对象生成渲染的时候,应该将飞船实时位置传递到子弹对象中。

此外,相比于飞船,子弹是需要一直生成的,因此屏幕可以存在多个子弹,我们需要一些容器对子弹进行管理。同时子弹的移动不像飞船到了边界就要停止,通常来说子弹触碰到窗口边界的时候子弹就应该消失,可以直接不管让子弹移动到窗口外不被加载,也可以让子弹在到达边界时自己销毁。

bullet

bullet.py模块的基础信息我们在最开始就写好了,现在我们需要根据我们实际的游戏业务进行填充。

import pygame


class Bullet:
    def __init__(self, setting, screen, ship):
        super(Bullet, self).__init__()
        self.screen = screen
        # 创建子弹矩形
        self.rect = pygame.Rect(0, 0, setting.bullet_width, setting.bullet_height)
        self.rect.centerx = ship.rect.centerx
        self.rect.top = ship.rect.top

    def move(self):
        """向上移动子弹"""
        pass

首先是介绍子弹的属性以及值。

  1. self.screen
    游戏窗口信息,这个不多做介绍,毕竟子弹是在窗口上显示的。
  2. self.rect
    子弹矩形,我们可以将子弹理解为一个实心矩形,并且通过系统设置文件配置子弹的长度和宽度。
  3. self.rect.centerx
    这个相信大家已经很熟了,子弹矩形的中心x坐标是飞船中心x坐标。
  4. self.rect.top
    这个应该也不陌生,子弹矩形的顶部,设置等于飞船的顶部。这样就会有一种子弹从飞船出来的感觉。大家也可以改造一下定义一个self.rect.bottom的属性,至于值,大家自己发挥,很简单的我不写出来了。

填充业务代码

上色

我们需要个给子弹上一个颜色!

self.color = setting.bullet_color

移动

子弹是自行移动的,所以我们的移动函数并不需要按键控制,只要每次渲染的时候调用一下move函数即可。

    def move(self):
        """向上移动子弹"""
        # 更新子弹位置
        self.rect.y -= 1

生成子弹

我们需要一个新的函数,在调用这个函数的时候,飞船的上方出现一个子弹。也就是我们说的发射子弹的函数。

函数比较简单,就是在窗口中绘制一个矩形就行。

  def draw_bullet(self):
        """在屏幕上绘制子弹"""
        pygame.draw.rect(self.screen, self.color, self.rect)

至此,我们的子弹模块已经填充好了。

import pygame


class Bullet:
    def __init__(self, setting, screen, ship):
        super(Bullet, self).__init__()
        self.screen = screen
        # 创建子弹矩形
        self.rect = pygame.Rect(0, 0, setting.bullet_width, setting.bullet_height)
        self.rect.centerx = ship.rect.centerx
        self.rect.top = ship.rect.top
        # 子弹颜色
        self.color = setting.bullet_color

    def move(self):
        """向上移动子弹"""
        # 更新子弹位置
        self.rect.y -= 1

    def draw_bullet(self):
        """在屏幕上绘制子弹"""
        pygame.draw.rect(self.screen, self.color, self.rect)

发射子弹

在编写这部分代码以前,我们需要理解一下信息:

  • 在游戏中,我们定义按下空格发射子弹,因此我们要对空格键按下的进行监听并处理。
  • 游戏中并不是只存在一个子弹,我们需要一个能管理多个子弹的容器。
  • 子弹会一直往上移动,但是当子弹穿过上边界时,我们需要移除该子弹。如果能容忍资源的浪费,也可以不管。

子弹组

在pygame中,我们要实现组的功能,需要继承Sprite。改造bullet模块代码如下:

import pygame
from pygame.sprite import Sprite


class Bullet(Sprite):
    def __init__(self, setting, screen, ship):
        super(Bullet, self).__init__()
        self.screen = screen
        # 创建子弹矩形
        self.rect = pygame.Rect(0, 0, setting.bullet_width, setting.bullet_height)
        self.rect.centerx = ship.rect.centerx
        self.rect.top = ship.rect.top
        # 子弹颜色
        self.color = setting.bullet_color
	
	# 原来是move,继承后改成update
    def update(self):
        """向上移动子弹"""
        # 更新子弹位置
        self.rect.y -= 1

    def draw_bullet(self):
        """在屏幕上绘制子弹"""
        pygame.draw.rect(self.screen, self.color, self.rect)

我们需要在main模块中创建管理多个子弹的容器,而pygame的中group可以很好的完成这个任务。

	# 创建子弹编组
    bullets = Group()

同时我们处理监听事件时需要把新建的这个子弹组传入,因为我们每次按下空格,就需要将一枚子弹放入这个组中。

gf.check_events(ship, setting, screen, bullets)

最后我们需要更新子弹的位置,并在屏幕绘制中绘制子弹

 	# 更新子弹
    gf.update_bullets(setting, screen, bullets)
    # 更新屏幕
    gf.update_screen(setting, screen, ship, bullets)

监听事件

每次按下空格键,我们就需要调用一个名叫fire的函数,将子弹放入子弹组中。

def check_event(ship, setting, screen, bullets):
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_RIGHT:
                ship.moving_right = True
            elif event.key == pygame.K_LEFT:
                ship.moving_left = True
            elif event.key == pygame.K_UP:
                ship.moving_top = True
            elif event.key == pygame.K_DOWN:
                ship.moving_bottom = True
            elif event.key == pygame.K_q:
                pygame.quit()
            elif event.key == pygame.K_SPACE:
                fire(bullets, screen, setting, ship)
        elif event.type == pygame.KEYUP:
            if event.key == pygame.K_RIGHT:
                ship.moving_right = False
            elif event.key == pygame.K_LEFT:
                ship.moving_left = False
            elif event.key == pygame.K_UP:
                ship.moving_top = False
            elif event.key == pygame.K_DOWN:
                ship.moving_bottom = False


def fire(bullets, screen, setting, ship):
    # 创建一颗子弹,并将其加入到编组bullets中
    new_bullet = Bullet(setting, screen, ship)
    bullets.add(new_bullet)

可以看到移动飞船的代码占据很长篇幅,我们再次封装一下这些参数。

def check_event(ship, setting, screen, bullets):
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()
        elif event.type == pygame.KEYDOWN:
            check_keydown_events(event, ship, setting, screen, bullets)
        elif event.type == pygame.KEYUP:
            check_keyup_events(event, ship)


def fire(bullets, screen, setting, ship):
    # 创建一颗子弹,并将其加入到编组bullets中
    new_bullet = Bullet(setting, screen, ship)
    bullets.add(new_bullet)
    
    
def check_keydown_events(event, ship, setting, screen, bullets):
    """响应按键"""
    if event.key == pygame.K_RIGHT:
        ship.moving_right = True
    elif event.key == pygame.K_LEFT:
        ship.moving_left = True
    elif event.key == pygame.K_UP:
        ship.moving_top = True
    elif event.key == pygame.K_DOWN:
        ship.moving_bottom = True
    elif event.key == pygame.K_SPACE:
        fire(bullets, screen, setting, ship)
    elif event.key == pygame.K_q:
        sys.exit()


def check_keyup_events(event, ship):
    """响应松开"""
    if event.key == pygame.K_RIGHT:
        ship.moving_right = False
    elif event.key == pygame.K_LEFT:
        ship.moving_left = False
    elif event.key == pygame.K_UP:
        ship.moving_top = False
    elif event.key == pygame.K_DOWN:
        ship.moving_bottom = False

这样如果再有按键的监听时间,直接对应到check_keydown_eventscheck_keyup_events两个函数中操作即可。

更新子弹

main模块中,我们调用了gf模块的更新子弹函数,这里我们需要填充这部分代码。

def update_bullets(bullets):
    """更新子弹"""
    bullets.update()
    # 删除已经消失的子弹
    for bullet in bullets.copy():
        # 当子弹矩形底部坐标小于0,说明子弹已经出了上边界
        if bullet.rect.bottom <= 0:
            bullets.remove(bullet)

另外我们在更新屏幕函数中也要绘制子弹。

def update_screen(setting, screen, ship, bullets):
    """更新屏幕"""
    # 填充背景色
    screen.fill(setting.bg_color)
    # 加载飞船
    ship.blitme()
    # 绘制子弹
    for bullet in bullets.sprites():
        bullet.draw_bullet()
    # 让最近绘制的屏幕可见
    pygame.display.flip()

发射子弹

当上面代码编写完毕,运行main模块,在屏幕上已经可以自由移动飞船并发射子弹了!

效果图:

在这里插入图片描述

但是你发现子弹移动速度有点快,怎么办呢?我们可以给子弹移动设置一个速度,每次移动以这个速度为单位。

那么我们需要改造bullet模块,代码改造如下:

属性

 		 # 子弹位置
        self.y = float(self.rect.y)
        # 子弹速度
        self.speed = setting.bullet_speed

函数

	def update(self):
		"""向上移动子弹"""
		# 更新子弹位置
		self.y -= self.speed
		self.rect.y = self.y

这个时候,可以看到我们子弹速度已经没有之前快了。

ps: 飞船也可以设置速度移动哦!

代码示例

贴一下本次修改后模块代码。

`main`模块:

import pygame
from pygame.sprite import Group

import alien_invasion.game_functions as gf
from alien_invasion.setting import Setting
from alien_invasion.ship import Ship


def run_game():
    """启动游戏"""

    # 初始化pygame
    pygame.init()
    # 定义一个系统设置对象
    setting = Setting()
    # 新建窗口
    screen = pygame.display.set_mode((setting.screen_width, setting.screen_height))
    # 窗口命名
    pygame.display.set_caption(setting.caption)
    # 定义一个飞船对象
    ship = Ship(setting, screen)
    # 创建子弹编组
    bullets = Group()

    while True:
        # 处理监听事件
        gf.check_event(ship, setting, screen, bullets)
        # 移动飞船
        ship.move()
        # 更新子弹位置
        gf.update_bullets(bullets)
        # 刷新屏幕
        gf.update_screen(setting, screen, ship, bullets)


if __name__ == '__main__':
    run_game()

bullet模块:

import pygame
from pygame.sprite import Sprite


class Bullet(Sprite):
    def __init__(self, setting, screen, ship):
        super(Bullet, self).__init__()
        self.screen = screen
        # 创建子弹矩形
        self.rect = pygame.Rect(0, 0, setting.bullet_width, setting.bullet_height)
        self.rect.centerx = ship.rect.centerx
        self.rect.top = ship.rect.top
        # 子弹颜色
        self.color = setting.bullet_color
        # 子弹位置
        self.y = float(self.rect.y)
        # 子弹速度
        self.speed = setting.bullet_speed

    def update(self):
        """向上移动子弹"""
        # 更新子弹位置
        self.y -= self.speed
        self.rect.y = self.y

    def draw_bullet(self):
        """在屏幕上绘制子弹"""
        pygame.draw.rect(self.screen, self.color, self.rect)

setting模块:

class Setting:
    """系统设置类"""
    def __init__(self):
        # 窗口宽
        self.screen_width = 1200
        # 窗口高
        self.screen_height = 800
        # 背景颜色
        self.bg_color = (230, 230, 230)
        # 窗口名
        self.caption = "Alien Invasion"
        # 子弹宽
        self.bullet_width = 3
        # 子弹长
        self.bullet_height = 15
        # 子弹颜色
        self.bullet_color = (60, 60, 60)
        # 飞船移动速度
        self.bullet_speed = 0.2

gf模块:

import sys
import pygame

from alien_invasion.bullet import Bullet


def check_event(ship, setting, screen, bullets):
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()
        elif event.type == pygame.KEYDOWN:
            check_keydown_events(event, ship, setting, screen, bullets)
        elif event.type == pygame.KEYUP:
            check_keyup_events(event, ship)


def fire(bullets, screen, setting, ship):
    # 创建一颗子弹,并将其加入到编组bullets中
    new_bullet = Bullet(setting, screen, ship)
    bullets.add(new_bullet)


def check_keydown_events(event, ship, setting, screen, bullets):
    """响应按键"""
    if event.key == pygame.K_RIGHT:
        ship.moving_right = True
    elif event.key == pygame.K_LEFT:
        ship.moving_left = True
    elif event.key == pygame.K_UP:
        ship.moving_top = True
    elif event.key == pygame.K_DOWN:
        ship.moving_bottom = True
    elif event.key == pygame.K_SPACE:
        fire(bullets, screen, setting, ship)
    elif event.key == pygame.K_q:
        sys.exit()


def check_keyup_events(event, ship):
    """响应松开"""
    if event.key == pygame.K_RIGHT:
        ship.moving_right = False
    elif event.key == pygame.K_LEFT:
        ship.moving_left = False
    elif event.key == pygame.K_UP:
        ship.moving_top = False
    elif event.key == pygame.K_DOWN:
        ship.moving_bottom = False


def update_screen(setting, screen, ship, bullets):
    """更新屏幕"""
    # 填充背景色
    screen.fill(setting.bg_color)
    # 加载飞船
    ship.blitme()
    # 绘制子弹
    for bullet in bullets.sprites():
        bullet.draw_bullet()
    # 让最近绘制的屏幕可见
    pygame.display.flip()


def update_bullets(bullets):
    """更新子弹"""
    bullets.update()
    # 删除已经消失的子弹
    for bullet in bullets.copy():
        # 当子弹矩形底部坐标小于0,说明子弹已经出了上边界
        if bullet.rect.bottom <= 0:
            bullets.remove(bullet)

如果运行有问题,可以对照代码参考或者私信我。

结尾

目前我们已经可以自由移动飞船并发射子弹了,后面我们就要生成外星人了。

加油!!!

标签:子弹,Python,self,45,外星人,pygame,screen,ship,event
From: https://blog.csdn.net/weixin_48668564/article/details/140723629

相关文章

  • 三种语言实现二分(C++/Python/Java)
    题目给定一个按照升序排列的长度为......
  • python+flask计算机毕业设计农场营销管理系统(程序+开题+论文)
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表开题报告内容研究背景随着现代农业的快速发展,农场管理日益复杂,尤其是营销环节,传统的销售模式已难以满足市场快速变化的需求。农场主面临着如何高效管理农资采购......
  • python+flask计算机毕业设计社区独居老人健康管理系统(程序+开题+论文)
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表开题报告内容研究背景随着社会老龄化的加速,独居老人群体日益庞大,成为社会关注的焦点。这一群体在享受独立生活的同时,也面临着健康监测不及时、生活照料缺失、医......
  • NX二次开发(python)-创建管(一)
    用UF函数创建管,下图为NXOpenPython的参考指南:1.创建管可以用线也可以用边,以下是用线创建管的代码,先创建一个非关联线后再创建一个管importNXOpen.UFsign=NXOpen.UF.Modl.FeatureSigns.ValueOf(0)line_coords=NXOpen.UF.Curve.Line()line_coords.StartPoint=[0.0,0.0......
  • 代码随想录算法训练营第九天 | 151.翻转字符串里的单词,卡码网:55.右旋转字符串,28. 实现
    151.翻转字符串里的单词题目链接:力扣题目链接文章讲解:代码随想录 视频讲解:字符串复杂操作拿捏了!|LeetCode:151.翻转字符串里的单词思路这道题目可以说是综合考察了字符串的多种操作。其实这道题和反转字符串这道题目很像,而且用法也是通用的方法一:切片,reverse,以及......
  • 《最新出炉》系列入门篇-Python+Playwright自动化测试-55- 上传文件 (非input控件)- 中
    1.简介在实际工作中,我们进行web自动化的时候,文件上传是很常见的操作,例如上传用户头像,上传身份证信息等。所以宏哥打算按上传文件的分类对其进行一下讲解和分享。2.上传文件的API(非input控件)Playwright是一个现代化的自动化测试工具,它支持多种浏览器和操作系统,可以帮助开发人员......
  • Python 实现行为驱动开发 (BDD) 自动化测试详解
    在当今的软件开发领域,行为驱动开发(BehaviorDrivenDevelopment,BDD)作为一种新兴的测试方法,逐渐受到越来越多开发者的关注和青睐。Python作为一门功能强大且易于使用的编程语言,在实现BDD方面也有着独特的优势。那么,如何利用Python实现BDD自动化测试呢?本文将为你详细解析。如何......
  • Python 实现行为驱动开发 (BDD) 自动化测试详解
    ​ 在当今的软件开发领域,行为驱动开发(BehaviorDrivenDevelopment,BDD)作为一种新兴的测试方法,逐渐受到越来越多开发者的关注和青睐。Python作为一门功能强大且易于使用的编程语言,在实现BDD方面也有着独特的优势。那么,如何利用Python实现BDD自动化测试呢?本文将为你详细解析。如......
  • 【python学习】retry库用法大全!附示例代码
    Retry是一个用于Python的库,用于在函数调用失败时自动重试。它的目标是简化重试逻辑的编写,处理由于临时性问题(如网络故障、API限制等)导致的失败。Retry的主要特点包括:简单易用:只需使用装饰器或上下文管理器即可实现重试功能。灵活配置:可以配置重试次数、重试间隔、异常......
  • 最长的Hello, World!(Python)
    最长的Hello,World!(Python)(lambda_,__,___,____,_____,______,_______,________:getattr(__import__(True.__class__.__name__[_]+[].__class__.__name__[__]),().__class__.__eq__.__class__.__name__[:__]+().__iter__().__cla......