pygame 精灵的行走及二段跳的实现方法(必看篇)


Posted in Python onJuly 10, 2017

不得不承认《Python游戏编程入门》这本书翻译、排版非常之烂,但是里面的demo还是很好的,之前做了些改编放到这里。

先是素材:

背景

pygame 精灵的行走及二段跳的实现方法(必看篇)

精灵

pygame 精灵的行走及二段跳的实现方法(必看篇)

所有素材均取自此书

接下来就是精灵类的创建了:

class MySprite(pygame.sprite.Sprite):
  def __init__(self, target):
    pygame.sprite.Sprite.__init__(self)
    self.master_image = None
    self.frame = 0
    self.old_frame = -1
    self.frame_width = 1
    self.frame_height = 1
    self.first_frame = 0
    self.last_frame = 0
    self.columns = 1
    self.last_time = 0

  #使用property方法,让精灵类对坐标操作更方便
  def _getx(self):
    return self.rect.x

  def _setx(self, value):
    self.rect.x = value

  X = property(_getx, _setx)

  def _gety(self):
    return self.rect.y

  def _sety(self, value):
    self.rect.y = value

  Y = property(_gety, _sety)

  def _getpos(self):
    return self.rect.topleft

  def _setpos(self, pos):
    self.rect.topleft = pos

  position = property(_getpos, _setpos)



#
load方法中定义了图片位置,长宽和帧的列数,由此来将素材切成一帧一帧
  def load(self, filename, width, height, columns):
    self.master_image = pygame.image.load(filename).convert_alpha()
    self.frame_width = width
    self.frame_height = height
    self.rect = Rect(0, 0, width, height)
    self.columns = columns
    rect = self.master_image.get_rect()
    self.last_frame = (rect.width // width) * (rect.height // height) - 1

  def update(self, current_time, rate=30):
    #
更新帧数
    if current_time > self.last_time + rate:
      self.frame += 1
      if self.frame > self.last_frame:
        self.frame = self.first_frame
      self.last_time = current_time

    #
当帧数发生改变时,创建新的图片
    if self.frame != self.old_frame:
      frame_x = (self.frame % self.columns) * self.frame_width
      frame_y = (self.frame // self.columns) * self.frame_height
      rect = Rect(frame_x, frame_y, self.frame_width, self.frame_height)
      self.image = self.master_image.subsurface(rect)
      self.old_frame = self.frame

将精灵类“放置”到游戏屏幕上,并加上背景

pygame.init()
screen = pygame.display.set_mode((800, 600))
font = pygame.font.Font(None, 24)
framerate = pygame.time.Clock()

bg = pygame.image.load("background.png").convert_alpha()
pl = pygame.image.load('caveman.png').convert_alpha()
# 创建精灵组
group = pygame.sprite.Group()


player = MySprite(screen)
player.load("caveman.png", 50, 64, 8)
player.first_frame = 1
player.last_frame = 7
player.position = 400, 303
group.add(player)

while True:
  for event in pygame.event.get():
    if event.type == QUIT:
      sys.exit()
  #  设置帧数
  framerate.tick(30)
  ticks = pygame.time.get_ticks()

这样的话精灵就在画布上了,我们得让它能左右移动:

keys = pygame.key.get_pressed()
  if keys[K_ESCAPE]:
    sys.exit()
  if keys[K_RIGHT]:
    player.X += 8
  if keys[K_LEFT]:
    if player.X > 0:
      player.X -= 8

然后实现跳跃及二段跳跃

这里需要说下二段跳跃的注意点:

1.直到落地前,只能跳两次,也就是说精灵进行二次跳跃后不能再跳了

2.按下空格后,精灵的加速度重置

这需要修改前面的代码:

jump_vel = 0.0
#  设置一个记录跳跃次数的变量
space_number = 0
#  跳跃判断
player_jumping = False
player_start_y = player.Y

while True:
  for event in pygame.event.get():
    if event.type == QUIT:
      sys.exit()
    if event.type == KEYDOWN:
      if event.key == K_SPACE:
        #  跳跃次数小于2次时,
        if space_number < 2:
          jump_vel = -15.0
          space_number += 1
          player_jumping = True

  keys = pygame.key.get_pressed()
  if keys[K_ESCAPE]:
    sys.exit()
  if keys[K_RIGHT]:
    player.X += 8
  if keys[K_LEFT]:
    if player.X > 0:
      player.X -= 8
  #  设置帧数
  framerate.tick(30)
  ticks = pygame.time.get_ticks()

  #  当按下空格后,jump_vel变量不断变大,直到接触地面
  if player_jumping:
    player.Y += jump_vel
    jump_vel += 2
    #  落地后,重置跳跃速度和其他判断变量
    if player.Y >= player_start_y:
        player_jumping = False
        player.Y = player_start_y
        jump_vel = 0
        space_number = 0
        #  创建背景
  screen.blit(bg, (0, 0))

  # 精灵组更新
  group.update(ticks, 50)
  group.draw(screen)

  pygame.display.update()

所有代码:

import sys, time, random, math, pygame
from pygame.locals import *


class MySprite(pygame.sprite.Sprite):
  def __init__(self, target):
    pygame.sprite.Sprite.__init__(self)
    self.master_image = None
    self.frame = 0
    self.old_frame = -1
    self.frame_width = 1
    self.frame_height = 1
    self.first_frame = 0
    self.last_frame = 0
    self.columns = 1
    self.last_time = 0

  # 使用property方法,让精灵类对坐标操作更方便
  def _getx(self):
    return self.rect.x

  def _setx(self, value):
    self.rect.x = value

  X = property(_getx, _setx)

  def _gety(self):
    return self.rect.y

  def _sety(self, value):
    self.rect.y = value

  Y = property(_gety, _sety)

  def _getpos(self):
    return self.rect.topleft

  def _setpos(self, pos):
    self.rect.topleft = pos

  position = property(_getpos, _setpos)


  def load(self, filename, width, height, columns):
    self.master_image = pygame.image.load(filename).convert_alpha()
    self.frame_width = width
    self.frame_height = height
    self.rect = Rect(0, 0, width, height)
    self.columns = columns
    rect = self.master_image.get_rect()
    self.last_frame = (rect.width // width) * (rect.height // height) - 1


  def update(self, current_time, rate=30):
    # 
更新帧数
    if current_time > self.last_time + rate:
      self.frame += 1
      if self.frame > self.last_frame:
        self.frame = self.first_frame
      self.last_time = current_time

    # 当帧数发生改变时,创建新的图片
    if self.frame != self.old_frame:
      frame_x = (self.frame % self.columns) * self.frame_width
      frame_y = (self.frame // self.columns) * self.frame_height
      rect = Rect(frame_x, frame_y, self.frame_width, self.frame_height)
      self.image = self.master_image.subsurface(rect)
      self.old_frame = self.frame

pygame.init()
screen = pygame.display.set_mode((800, 600))
font = pygame.font.Font(None, 24)
framerate = pygame.time.Clock()

bg = pygame.image.load("background.png").convert_alpha()
pl = pygame.image.load('caveman.png').convert_alpha()
# 创建精灵组
group = pygame.sprite.Group()


player = MySprite(screen)
player.load("caveman.png", 50, 64, 8)
player.first_frame = 1
player.last_frame = 7
player.position = 400, 303
group.add(player)


jump_vel = 0.0
#  设置一个记录跳跃次数的变量
space_number = 0
#  跳跃判断
player_jumping = False
player_start_y = player.Y

while True:
  for event in pygame.event.get():
    if event.type == QUIT:
      sys.exit()
    if event.type == KEYDOWN:
      if event.key == K_SPACE:
        #  跳跃次数小于2次时,
        if space_number < 2:
          jump_vel = -15.0
          space_number += 1
          player_jumping = True

  keys = pygame.key.get_pressed()
  if keys[K_ESCAPE]:
    sys.exit()
  if keys[K_RIGHT]:
    player.X += 8
  if keys[K_LEFT]:
    if player.X > 0:
      player.X -= 8
  #  设置帧数
  framerate.tick(30)
  ticks = pygame.time.get_ticks()

  #  当按下空格后,jump_vel变量不断变大,直到接触地面
  if player_jumping:
    player.Y += jump_vel
    jump_vel += 2
    #  落地后
    if player.Y >= player_start_y:
        player_jumping = False
        player.Y = player_start_y
        jump_vel = 0
        space_number = 0
        rush_number = 0

  #  创建背景
  screen.blit(bg, (0, 0))

  # 精灵组更新
  group.update(ticks, 50)
  group.draw(screen)

  pygame.display.update()

这样,一个粗糙的、会二段跳的精灵就完成了。

很感谢这本书提供单次跳跃的思路,让我有思考二段跳的想法。其实像二段跳这类看上去容易,但实现其实还是需要思考一番的。

以上这篇pygame 精灵的行走及二段跳的实现方法(必看篇)就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python启动办公软件进程(word、excel、ppt、以及wps的et、wps、wpp)
Apr 09 Python
python中map、any、all函数用法分析
Apr 21 Python
python实现归并排序算法
Nov 22 Python
将python图片转为二进制文本的实例
Jan 24 Python
python 利用pyttsx3文字转语音过程详解
Sep 25 Python
春节到了 教你使用python来抢票回家
Jan 06 Python
使用pytorch和torchtext进行文本分类的实例
Jan 08 Python
解决pymysql cursor.fetchall() 获取不到数据的问题
May 15 Python
Pandas实现一列数据分隔为两列
May 18 Python
Python函数必须先定义,后调用说明(函数调用函数例外)
Jun 02 Python
python3+PyQt5+Qt Designer实现界面可视化
Jun 10 Python
分享提高 Python 代码的可读性的技巧
Mar 03 Python
Python 实现数据库更新脚本的生成方法
Jul 09 #Python
Python 实现数据库(SQL)更新脚本的生成方法
Jul 09 #Python
解决python文件字符串转列表时遇到空行的问题
Jul 09 #Python
python3 shelve模块的详解
Jul 08 #Python
Python基于scapy实现修改IP发送请求的方法示例
Jul 08 #Python
Python开发微信公众平台的方法详解【基于weixin-knife】
Jul 08 #Python
python 中random模块的常用方法总结
Jul 08 #Python
You might like
mysql 查询指定日期时间内sql语句实现原理与代码
2012/12/16 PHP
php实现比较两个文件夹异同的方法
2015/06/18 PHP
PHP面向对象五大原则之里氏替换原则(LSP)详解
2018/04/08 PHP
PHP如何使用array_unshift()在数组开头插入元素
2020/09/01 PHP
PHP autoload使用方法及步骤详解
2020/09/05 PHP
js自定义事件代码说明
2011/01/31 Javascript
javascript实现div的显示和隐藏的小例子
2013/06/25 Javascript
Javascript字符串浏览器兼容问题分析
2014/12/01 Javascript
javascript 构造函数方式定义对象
2015/01/02 Javascript
jQuery下拉美化搜索表单效果代码分享
2015/08/25 Javascript
Javascript实现图片轮播效果(二)图片序列节点的控制实现
2016/02/17 Javascript
jQuery Validate 数组 全部验证问题
2017/01/12 Javascript
深入理解vuex2.0 之 modules
2017/11/20 Javascript
JavaScript中使用Spread运算符的八种方法总结
2020/06/18 Javascript
python分布式环境下的限流器的示例
2017/10/26 Python
Python用sndhdr模块识别音频格式详解
2018/01/11 Python
python学生信息管理系统
2018/03/13 Python
python如何统计序列中元素
2020/07/31 Python
python pandas读取csv后,获取列标签的方法
2018/11/12 Python
使用coverage统计python web项目代码覆盖率的方法详解
2019/08/05 Python
Python类反射机制使用实例解析
2019/12/30 Python
基于python实现对文件进行切分行
2020/04/26 Python
pytorch中的weight-initilzation用法
2020/06/24 Python
python连接手机自动搜集蚂蚁森林能量的实现代码
2021/02/24 Python
LACOSTE波兰官网:Polo衫、服装和鞋类
2020/09/29 全球购物
医学生求职自荐信
2013/10/25 职场文书
汽车运用工程专业毕业生推荐信
2013/12/25 职场文书
机关干部个人对照检查材料思想汇报
2014/09/28 职场文书
护理医院见习报告
2014/11/03 职场文书
大学生入党自我鉴定范文
2019/06/21 职场文书
python 实现的截屏工具
2021/05/08 Python
MySQL系列之十三 MySQL的复制
2021/07/02 MySQL
使用Nginx搭载rtmp直播服务器的方法
2021/10/16 Servers
基于Python实现射击小游戏的制作
2022/04/06 Python
Nginx配置之禁止指定IP访问
2022/05/02 Servers
python中 Flask Web 表单的使用方法
2022/05/20 Python