所以主要问题是Animation 假设大图像中有一系列图像。它被称为精灵动画,它本质上只是一系列你想要的动作(通常是一行或一个网格模式)。它对于动画行走、攻击和其他类似的游戏机制非常有用。
但要在画布上移动对象,您需要以某种方式手动操作顶点或图像位置。您自己的解决方案的工作原理是检查X 是否大于或小于min 和max 限制。我只想在此基础上添加一些技巧,以便更轻松、更快速地处理动作和方向。下面我与bitwise operations 一起确定了运动的方向,这使得心脏在宽度和高度的父(窗口)约束周围反弹。
我还冒昧地通过将 pyglet Window 类继承到一个对象/类中并使 heart 成为自己的类来更容易地分离何时和何时调用的内容,从而使整个项目更加面向对象什么对象。
from pyglet import *
from pyglet.gl import *
key = pyglet.window.key
# Indented oddly on purpose to show the pattern:
UP = 0b0001
DOWN = 0b0010
LEFT = 0b0100
RIGHT = 0b1000
class heart(pyglet.sprite.Sprite):
def __init__(self, parent, image='heart.png', x=0, y=0):
self.texture = pyglet.image.load(image)
pyglet.sprite.Sprite.__init__(self, self.texture, x=x, y=y)
self.parent = parent
self.direction = UP | RIGHT # Starting direction
def update(self):
# We can use the pattern above with bitwise operations.
# That way, one direction can be merged with another without collision.
if self.direction & UP:
self.y += 1
if self.direction & DOWN:
self.y -= 1
if self.direction & LEFT:
self.x -= 1
if self.direction & RIGHT:
self.x += 1
if self.x+self.width > self.parent.width:
self.direction = self.direction ^ RIGHT # Remove the RIGHT indicator
self.direction = self.direction ^ LEFT # Start moving to the LEFT
if self.y+self.height > self.parent.height:
self.direction = self.direction ^ UP # Remove the UP indicator
self.direction = self.direction ^ DOWN # Start moving DOWN
if self.y < 0:
self.direction = self.direction ^ DOWN
self.direction = self.direction ^ UP
if self.x < 0:
self.direction = self.direction ^ LEFT
self.direction = self.direction ^ RIGHT
def render(self):
self.draw()
# This class just sets up the window,
# self.heart <-- The important bit
class main(pyglet.window.Window):
def __init__ (self, width=800, height=600, fps=False, *args, **kwargs):
super(main, self).__init__(width, height, *args, **kwargs)
self.x, self.y = 0, 0
self.heart = heart(self, x=100, y=100)
self.alive = 1
def on_draw(self):
self.render()
def on_close(self):
self.alive = 0
def on_key_press(self, symbol, modifiers):
if symbol == key.ESCAPE: # [ESC]
self.alive = 0
def render(self):
self.clear()
self.heart.update()
self.heart.render()
## Add stuff you want to render here.
## Preferably in the form of a batch.
self.flip()
def run(self):
while self.alive == 1:
self.render()
# -----------> This is key <----------
# This is what replaces pyglet.app.run()
# but is required for the GUI to not freeze
#
event = self.dispatch_events()
if __name__ == '__main__':
x = main()
x.run()
基本原理是一样的,操作sprite.x横向移动,sprite.y纵向移动。还有更多优化要做,例如,更新应该根据上次渲染进行缩放。这样做是为了避免在您的显卡跟不上时出现故障。它很快就会变得相当复杂,所以我会给你一个example,告诉你如何计算这些运动。
此外,您可能想要渲染一个批次,而不是直接渲染精灵。对于大型项目,这将大大加快渲染过程。
如果您不熟悉按位运算,简短的描述是它在bit/binary 级别上进行操作(以4 == 0100 为例),并对UP、@ 的值进行XOR 操作987654336@、LEFT 和 RIGHT。我们可以通过合并0100 和0001 来添加/删除方向,从而得到0101 作为示例。然后我们可以执行二进制AND(不像传统的and 运算符)来确定一个值是否在第三个位置(0100)上包含1,方法是执行self.direction & 0100,这将导致1 如果这是True。如果您愿意,这是检查“状态”的一种方便快捷的方法。