本文内容

  • 精灵 类的使用
  • Rect 类的使用
  • 实现一个坦克的移动和旋转

效果演示

添加一个静态坦克

我们已经知道如何创建一个游戏窗口,并设置背景图片,还让游戏程序可以对键盘和鼠标进行响应,接着我们需要给游戏添加一个精灵,精灵是游戏开发里的一个概念,比如游戏里面的一个坦克,一棵树木,一个子弹都可以是一个精灵。
pgame.sprite提供了一个最基础的精灵类Sprite,它包含了图片image和位置rect,它只能让一个图片移动,当我们要更多的功能的时候,比如动画等,则需要继承Sprite,自己进一步编写代码。本次学习中,我们准备了3个图片,分别是一个坦克机身,和2个炮筒:

首先,我们把准备好的素材添加到游戏工程中,可以通过拖拽,复制粘贴等方式:

导入好资源之后,我们开始正式编写代码。首先,我们创建1个Surface对象,来存放我们第1个资源文件,和添加背景一样的操作,如下所示:

tank_image = pygame.image.load('tank.png').convert()                            #创建坦克

接着,我们继承Sprite类,创建一个HeroTank类,以便我们进一步扩展功能,先看具体代码:

class HeroTank(pygame.sprite.Sprite):def __init__(self):pygame.sprite.Sprite.__init__(self)                              #初始化 Sprite类构造函数self.tank_image = tank_image                                   #初始化坦克机生图片self.tank_rect = self.tank_image.get_rect()                      #获取机身rect对象def display(self,screen):screen.blit(self.tank_image, self.tank_rect)                    #screen在坦克机身的rect上绘制坦克机身图片

现在,它只有一个构造函数,和一个显示函数。接着我们使用HeroTank类创建一个对象,并调用该类的display方法,来显示坦克机身,完整的程序如下:

# 导入模块
import pygame
from pygame.locals import *
from sys import exit# 初始化部分
pygame.init()# 设置游戏窗口
screen = pygame.display.set_mode((640,480))
pygame.display.set_caption("My Game Window")
background = pygame.image.load("background_640x480.jpg").convert()# 坦克精灵类
tank_image = pygame.image.load('tank.png').convert_alpha()       #使用convert_alpha()保留透明信息,而不是convert()class HeroTank(pygame.sprite.Sprite):def __init__(self):pygame.sprite.Sprite.__init__(self)self.tank_image = tank_imageself.tank_rect = self.tank_image.get_rect()def display(self,screen):screen.blit(self.tank_image, self.tank_rect)my_tank = HeroTank()while True:for event in pygame.event.get():if event.type == QUIT:exit()screen.blit(background, (0, 0))my_tank.display(screen)pygame.display.update()

因为在对象中,我们没有指定生成的坦克机身image的rect位置,所以默认是(0,0)。当我们在rect上填充坦克image的时候,就会默认在srceen的左上角,程序运行如下所示:

我们顺利的添加了坦克的机身,接下来就是添加炮筒了,其逻辑是相似的,以下是具体代码:

# 导入模块
import pygame
from pygame.locals import *
from sys import exit# 初始化部分
pygame.init()# 设置游戏窗口
screen = pygame.display.set_mode((640,480))
pygame.display.set_caption("My Game Window")
background = pygame.image.load("background_640x480.jpg").convert()# 坦克精灵类
tank_image = pygame.image.load('tank.png').convert_alpha()
cannon1_image = pygame.image.load('cannon_1.png').convert_alpha()class HeroTank(pygame.sprite.Sprite):def __init__(self):pygame.sprite.Sprite.__init__(self)self.tank_image = tank_imageself.cannon1_image = cannon1_imageself.tank_rect = self.tank_image.get_rect()self.cannon1_rect = self.cannon1_image.get_rect()def display(self,screen):screen.blit(self.tank_image, self.tank_rect)self.cannon1_rect.center = self.tank_rect.center #炮筒中心点和坦克机生rect的中心点保持一致screen.blit(self.cannon1_image, self.cannon1_rect)my_tank = HeroTank()while True:for event in pygame.event.get():if event.type == QUIT:exit()screen.blit(background, (0, 0))my_tank.display(screen)pygame.display.update()

这里我们在display()函数中添加了rect中心点的赋值语句,这是因为如果没有,那么炮筒绘画的也会在程序左上角,这样看起来炮筒就错位了,程序运行如下所示:

移动坦克

我们已经创建了一个精灵类,也初步了解了surface和rect对象,接着我们通过操作rect对象,来控制坦克的移动,首先我们是在类里面添加方法,分别添加四个方法来控制坦克的上下左右移动,具体类的代码如下(这里用了和上节不一样的键盘的获取方式,个人它的控制体验感觉更好):

# 导入模块
import pygame
from pygame.locals import *
from sys import exit# 初始化部分
pygame.init()# 设置游戏窗口
screen = pygame.display.set_mode((640,480))
pygame.display.set_caption("My Game Window")
background = pygame.image.load("background_640x480.jpg").convert()# 坦克精灵类
tank_image = pygame.image.load('tank.png').convert_alpha()
cannon1_image = pygame.image.load('cannon_1.png').convert_alpha()class HeroTank(pygame.sprite.Sprite):def __init__(self):pygame.sprite.Sprite.__init__(self)self.tank_image = tank_imageself.cannon1_image = cannon1_imageself.tank_rect = self.tank_image.get_rect()self.cannon1_rect = self.cannon1_image.get_rect()self.speed = 1;                                               #每次移动的像素def moveLeft(self):if self.tank_rect.left > 0:                                   #显示rect的范围,不至于玩家坦克移出屏幕self.tank_rect.x -= self.speeddef moveRight(self):elif self.tank_rect.right < 640:self.tank_rect.x += self.speeddef moveUp(self):elif self.tank_rect.top > 0:self.tank_rect.y -= self.speeddef moveDown(self):elif self.tank_rect.bottom < 480:self.tank_rect.y += self.speeddef display(self,screen):screen.blit(self.tank_image, self.tank_rect)self.cannon1_rect.center = self.tank_rect.centerscreen.blit(self.cannon1_image, self.cannon1_rect)my_tank = HeroTank()while True:for event in pygame.event.get():if event.type == QUIT:exit()key_press = pygame.key.get_pressed()if key_press[K_w]:my_tank.moveUp()elif key_press[K_s]:my_tank.moveDown()elif key_press[K_a]:my_tank.moveLeft()elif key_press[K_d]:my_tank.moveRight()screen.blit(background, (0, 0))my_tank.display(screen)pygame.display.update()

控制游戏速率——帧率的设置

当我们运行程序后,会发现坦克可以移动了,但是速度太快了,这是因为我们虽然每次只移动1个像素,但是我们1秒移动太多次了,这里我们用来控制整个游戏的速度。我们如果能够控制1秒程序刷新30次,那么1秒我们坦克就只会移动30个像素,虽然有点慢,但是看起来可控多了。我们使用以下函数来实现

framerate = pygame.time.Clock()        #实例化一个之中对象
framerate .tick(30)                             #控制循环为30帧/秒

clock.tick(30)函数的工作控制游戏速率原理是,当本次运行到这个函数和上次运行到这个函数时间差不到设定的时间1/30秒的时候,就等待,然后再接着运行,我们需要将函数放在主要循环中。接着我们稍微调整了下坦克的移动速度,即实例中的speed变量后,达到一个不错的效果(改动较小,所以完整代码和下一部分一起贴出):
也许你感觉他还是有点快,我把speed调节到了8,也就是每次8像素。每1秒30次,480像素宽的地图,只需要移动不到2秒(因为我们坦克有宽度),当然,速度的调节是简单的,现在还有一个问题,坦克好像装了麦克纳姆轮一样,平移着移动,不符合实际情况,接下来我们来解决这一问题。

旋转坦克精灵

我们可以通过Rect的旋转来实现:

pygame.transform.rotate(image,angle)

transform.rotate()的第1个参数为图像,第2个参数为角度,选择以后返回一个新的对象,在程序设计中,我们则会使用这个新的对象。因为我们现在坦克只有上下左右移动,所以我们图像有4个角度,0°,90°,180°,270°。我们为我们的坦克类新添加一个函数,以便我们更好的控制选择:

def rotate(self,angle):self.tank_image = pygame.transform.rotate(tank_image, angle)  # 选择并生成一个新的对象self.rect = self.image.get_rect(center=self.rect.center)      #更新rect,否则旋转起来会“摇摇晃晃”

这里稍作解释,我们在旋转图像后,它的rect也就变化了,所以我们需要读取出旋转后的图像的rect,并且我们是以原来图像的中心点作为现在的中心点来读取的,否则它会默认在左上角生成。这就会造成如果你更新了rect,一旋转,坦克就会复位的初始点。
关于旋转的理解,可以参考这篇博客:pygame 笔记-9 图片旋转及边界反弹,博主以及做了不错的分析,这里不再赘述。现在看一下完整的程序:

# 导入模块
import pygame
from pygame.locals import *
from sys import exit# 初始化部分
pygame.init()# 设置游戏窗口
screen = pygame.display.set_mode((640,480))
pygame.display.set_caption("My Game Window")
background = pygame.image.load("background_640x480.jpg").convert()# 坦克精灵类
tank_image = pygame.image.load('tank.png').convert_alpha()
cannon1_image = pygame.image.load('cannon_1.png').convert_alpha()class HeroTank(pygame.sprite.Sprite):def __init__(self):pygame.sprite.Sprite.__init__(self)self.tank_image = tank_imageself.cannon1_image = cannon1_imageself.tank_rect = self.tank_image.get_rect()self.cannon1_rect = self.cannon1_image.get_rect()self.speed = 8def moveLeft(self):if self.tank_rect.left > 0:self.tank_rect.x -= self.speedself.rotate(270)def moveRight(self):if self.tank_rect.right < 640:self.tank_rect.x += self.speedself.rotate(90)def moveUp(self):if self.tank_rect.top > 0:self.tank_rect.y -= self.speedself.rotate(180)def moveDown(self):if self.tank_rect.bottom < 480:self.tank_rect.y += self.speedself.rotate(0)def rotate(self, angle):# 选择机身self.tank_image = pygame.transform.rotate(tank_image, angle)self.tank_rect = self.tank_image.get_rect(center=self.tank_rect.center)# 旋转炮筒self.cannon1_image = pygame.transform.rotate(cannon1_image, angle)self.cannon1_rect = self.cannon1_image.get_rect(center=self.cannon1_rect.center)def display(self, screen):screen.blit(self.tank_image, self.tank_rect)self.cannon1_rect.center = self.tank_rect.centerscreen.blit(self.cannon1_image, self.cannon1_rect)my_tank = HeroTank()
framerate = pygame.time.Clock()while True:framerate .tick(30)for event in pygame.event.get():if event.type == QUIT:exit()key_press = pygame.key.get_pressed()if key_press[K_w]:my_tank.moveUp()elif key_press[K_s]:my_tank.moveDown()elif key_press[K_a]:my_tank.moveLeft()elif key_press[K_d]:my_tank.moveRight()screen.blit(background, (0, 0))my_tank.display(screen)pygame.display.update()

运行程序,就得到了我们文章开始的效果。我们还有一个炮筒素材没有用上,这里我们可以作为额外练习,通过按一个键盘按键,来切换炮筒。
以下是整个工程,包括代码和图片资源的下载地址:
链接:资源下载
提取码:8xkc

pygame 学习笔记(7)添加一个精灵:坦克的移动和旋转相关推荐

  1. pygame 学习笔记(8)精灵动画的实现:子弹的爆炸效果

    本文内容 subsurface() 子 surface的学习 实现一个精灵动画 Note:本文代码基于上一小节,可以直接在上文文末下载工程文件. 在上一节中,我们只是让坦克移动起来,但不是真正的动画, ...

  2. pygame学习笔记(5)——精灵

    转载请注明:@小五义 http://www.cnblogs.com/xiaowuyi 据说在任天堂FC时代,精灵的作用相当巨大,可是那时候只知道怎么玩超级玛丽.魂斗罗,却对精灵一点也不知.pygame ...

  3. 【Pygame 学习笔记】8.精灵

    术语"精灵"是旧计算机和游戏机的保留.这些较旧的盒子无法以足够快的速度绘制和擦除普通图形,使其无法用作游戏.这些机器有特殊的硬件来处理需要快速动画的游戏对象.这些对象被称为&quo ...

  4. tensorflow学习笔记二——建立一个简单的神经网络拟合二次函数

    tensorflow学习笔记二--建立一个简单的神经网络 2016-09-23 16:04 2973人阅读 评论(2) 收藏 举报  分类: tensorflow(4)  目录(?)[+] 本笔记目的 ...

  5. Pygame学习笔记 4 —— 时间与运动

        还记得我们在之前的程序中如何让兔子动起来的吗,没错,使用event模块检测键盘事件,改变绘图的坐标,画面刷新后兔子就移动了.接下来我们细说如何精确控制时间和运动. 主要内容: pygame的时 ...

  6. Pygame学习笔记 6 —— 3D游戏

        pygame是是上世纪的产品,虽然不适合最3D游戏,但我可以使用pygame来绘制简单的3D图形,就像在白纸上画立体图形一样. 主要内容: 视觉上的远近.3D空间.绘制一个空间图形 一.视觉上 ...

  7. MyBatis学习笔记2 ——第一个MyBatis程序

    MyBatis学习笔记2 --第一个MyBatis程序 参考教程B站狂神https://www.bilibili.com/video/BV1NE411Q7Nx 环境搭建 建立一个mybatis数据库用 ...

  8. Spark学习笔记1——第一个Spark程序:单词数统计

    Spark学习笔记1--第一个Spark程序:单词数统计 笔记摘抄自 [美] Holden Karau 等著的<Spark快速大数据分析> 添加依赖 通过 Maven 添加 Spark-c ...

  9. Python第三方库pygame学习笔记(一)

    Pygame Python最经典的2D游戏开发第三方库,也支持3D游戏开发 Pygame适合用于游戏逻辑验证.游戏入门及系统演示验证 Pygame是一种游戏开发引擎,基本逻辑具有参考价值 pygame ...

最新文章

  1. 超强图文|并发编程【等待/通知机制】就是这个feel~
  2. IE中页面不居中,火狐谷歌等正常
  3. moa 35 批量删除
  4. jQuery的效果方法
  5. web图片铺满网页_web单页面实现多个echarts图表铺满整个div(柱状图,折线图,饼形图……)...
  6. Qt学习(二):菜单栏、工具栏和对话框
  7. 手把手带你撸一把springsecurity框架源码中的认证流程
  8. ap测试系统软件,符合AUTOSAR(APCP)的嵌入式系统和软件设计工具
  9. MATLAB实现LDA(线性判别分析),以两个类别数目为例
  10. 纯Java文件操作工具,支持文件、文件夹的复制、删除、移动
  11. 接口文档模板,接口规范
  12. 小技巧 - LeetCode 如何查看他人耗时更优的代码答案?
  13. Ubuntu安装与Xshell的配置
  14. 在CentOS 7 1804 中 安装 使用 GitLab 11.4.3-ee (企业版、社区版最新版、或任意版本)
  15. python练习题(一):输入某年某月某日,判断这一天是这一年的第几天
  16. 为什么穷人越穷,富人越富?
  17. 【UVM基础】两种启动 sequence 的方式
  18. python教学视频k_10个Python奇趣教程,附视频讲解+练手项目。
  19. MatLab 画图方法
  20. Douyin-Bot 项目优化-改进(二),主播昵称识别+数据库储存

热门文章

  1. 交换机POE技术知识大全
  2. Unity中Combined Mesh (root: scene)的解决方法
  3. mysql 取分组中最新记录
  4. 润乾报表CookBook与使用
  5. html及Dreamweaver学习心得
  6. python数据挖掘入门与实践-第一章-用最简单OneR算法对Iris植物分类
  7. Linksys玩多了,来看看真正的Cisco~技术帖
  8. 苹果每部iPhone4S可赚3917元 开售首日收入39亿元
  9. 电脑搜索不出网络共享文件夹内容
  10. Redis学习总结(数据类型、持久化、事务、数据删除策略、主从复制、哨兵、缓存雪崩等)