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入门教程
Apr 03 Python
详解Python中with语句的用法
Apr 15 Python
老生常谈Python序列化和反序列化
Jun 28 Python
python利用高阶函数实现剪枝函数
Mar 20 Python
python 请求服务器的实现代码(http请求和https请求)
May 25 Python
Django uwsgi Nginx 的生产环境部署详解
Feb 02 Python
一文了解Python并发编程的工程实现方法
May 31 Python
python 表格打印代码实例解析
Oct 12 Python
10行Python代码计算汽车数量的实现方法
Oct 23 Python
jupyter notebook 的工作空间设置操作
Apr 20 Python
python可以用哪些数据库
Jun 22 Python
python如何利用paramiko执行服务器命令
Nov 07 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
PHP跨时区(UTC时间)应用解决方案
2013/01/11 PHP
destoon实现首页显示供应、企业、资讯条数的方法
2014/07/15 PHP
thinkphp中空模板与空模块的用法实例
2014/11/26 PHP
PHP使用php-resque库配合Redis实现MQ消息队列的教程
2016/06/29 PHP
php实现等比例压缩图片
2018/07/26 PHP
php使用gearman进行任务分发操作实例详解
2020/02/26 PHP
理解JAVASCRIPT中hasOwnProperty()的作用
2013/06/05 Javascript
千分位数字格式化(用逗号隔开 代码已做了修改 支持0-9位逗号隔开)的JS代码
2013/12/05 Javascript
js 阻止子元素响应父元素的onmouseout事件具体实现
2013/12/23 Javascript
jquery提交form表单简单示例分享
2014/03/03 Javascript
javascript学习笔记(六)数据类型和JSON格式
2014/10/08 Javascript
javascript浏览器窗口之间传递数据的方法
2015/01/20 Javascript
浅谈js中test()函数在正则中的使用
2016/08/19 Javascript
Jquery组件easyUi实现手风琴(折叠面板)示例
2016/08/23 Javascript
jquery实现图片平滑滚动详解
2017/03/22 jQuery
Bootstrap输入框组件使用详解
2017/06/09 Javascript
vue 监听某个div垂直滚动条下拉到底部的方法
2018/09/15 Javascript
详解vue中async-await的使用误区
2018/12/05 Javascript
微信小程序生成二维码的示例代码
2019/03/29 Javascript
深入了解JavaScript代码覆盖
2019/06/13 Javascript
Vue基于localStorage存储信息代码实例
2020/11/16 Javascript
[01:02:30]Mineski vs Secret 2019国际邀请赛淘汰赛 败者组 BO3 第三场 8.22
2019/09/05 DOTA
python中对list去重的多种方法
2014/09/18 Python
Python3读取Excel数据存入MySQL的方法
2018/05/04 Python
Python下使用Scrapy爬取网页内容的实例
2018/05/21 Python
Python unittest模块用法实例分析
2018/05/25 Python
Python并行分布式框架Celery详解
2018/10/15 Python
浅谈Python的条件判断语句if/else语句
2019/03/21 Python
戴森台湾线上商城:Dyson Taiwan
2018/05/21 全球购物
应届生财务管理求职信
2013/11/06 职场文书
党员活动日总结
2014/05/05 职场文书
小学语文教学经验交流材料
2014/06/02 职场文书
党的群众路线教育实践活动对照检查材料(个人)
2014/09/24 职场文书
2015年元旦联欢晚会活动总结
2014/11/28 职场文书
消防安全主题班会
2015/08/12 职场文书
eclipse创建项目没有dynamic web的解决方法
2021/06/24 Java/Android