所以我决定在 pygame 中为我的矩形字符添加线性插值。几天前我看到了 lerp,我不确定我是否遗漏了什么。
问题是:例如当我向右移动时。速度插值以达到所需的最大速度 - (7) 或(左侧为 -7)。当我释放键时,速度再次插入,从最大速度到 0,非常平滑。但是,如果我在向右移动时按下左键,则插值从速度 7 变为 0,使我的角色停止。
编辑:这是整个游戏的一部分,我跳过了跳跃和窗口边界碰撞检测等功能。但是这段代码仍然重现了我不想要的动作。
import pygame
import sys
import math
import datetime
from pygame.locals import *
class Vector(object):
''' Performs vector aritmetics
'''
def __init__(self, x, y):
self.x = x
self.y = y
def add(self, v):
x = self.x + v.x
y = self.y + v.y
return Vector(x, y)
class GroundData(object):
''' Ground data structure.
Creates a ground data structure and her component's.
'''
def __init__(self):
# Vectors
self.position = Vector(0, WINDOWHEIGHT - WINDOWHEIGHT / 3)
self.size = Vector(WINDOWWIDTH, WINDOWHEIGHT-self.position.y)
# Ground data structure
self.color = (128, 128, 128) # Gray
self.rect = pygame.Rect((self.position.x, self.position.y),
(self.size.x, self.size.y))
self.ground = {'shape': self.rect, 'color': self.color}
def draw(self):
''' Draw's the ground shape and color using pygame.draw.rect(...).
'''
pygame.draw.rect(WINDOWSURFACE, self.ground['color'],
self.ground['shape'])
class PlayerData(object):
''' Player data structure.
Creates a player data structure and handles few actions.
'''
def __init__(self):
self.ground = GroundData()
# Vectors
self.size = Vector(50, 70)
self.position = Vector(
15, self.ground.position.y - self.size.y + 1) # + 1 forced collision
self.velocity = Vector(0, 0)
self.velocity_goal = Vector(0, 0)
self.gravity = Vector(0, 3)
# Player data structure
self.color = (0, 100, 0) # Dark Green
self.rect = pygame.Rect((self.position.x, self.position.y),
(self.size.x, self.size.y))
self.player = {'shape': self.rect, 'color': self.color}
def is_colliding_ground(self):
''' Returns true if player shape is colliding with a ground.
'''
if self.position.y + self.size.y >= self.ground.position.y:
return True
return False
def approach(self, vel_goal, vel_curr, dt):
difference = vel_goal - vel_curr
if difference > dt:
return vel_curr + dt
if difference < -dt:
return vel_curr - dt
return vel_goal
def update(self, dt):
self.velocity.x = self.approach(self.velocity_goal.x,
self.velocity.x, dt * 95)
# Update position and velocity
# self.position = self.position.add(self.velocity) * dt
# If I mult (x, y) by dt I get alot slower.
self.position = self.position.add(self.velocity)
self.player['shape'].top = self.position.y
self.player['shape'].left = self.position.x
def draw(self):
''' Draw's the player shape and color using pygame.draw.rect(...).
'''
pygame.draw.rect(WINDOWSURFACE, self.player['color'],
self.player['shape'])
class EventManagement(object):
''' Handles keyboard event's.
Toggles player variables according to the event's.
'''
def __init__(self, player):
self.player = player
def is_doneloop(self, flag):
global is_doneloop
is_doneloop = flag
return is_doneloop
def listen(self):
''' Toggles player variables according to keyboard/mouse input.
'''
for event in pygame.event.get():
if event.type == QUIT:
self.is_doneloop(True)
if event.type == KEYDOWN:
if event.key == ord('a'):
self.player.velocity_goal.x = -7
if event.key == ord('d'):
self.player.velocity_goal.x = 7
if event.type == KEYUP:
if event.key == K_ESCAPE:
self.is_doneloop(True)
if event.key == ord('a'):
self.player.velocity_goal.x = 0
if event.key == ord('d'):
self.player.velocity_goal.x = 0
#-------------------------------------------------------------------------
WINDOWWIDTH = 900
WINDOWHEIGHT = 500
WINDOWSURFACE = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT), 0, 32)
is_doneloop = False
Clock = pygame.time.Clock()
FPS = 40
def mainloop():
pygame.init()
Ground = GroundData()
Player = PlayerData()
EventHandle = EventManagement(Player)
prev_time = 0
curr_time = datetime.datetime.now()
while not is_doneloop:
# Get deltaT
dt = Clock.tick(FPS)
dt = dt / 1000.0 # Convert milliseconds to seconds
pygame.display.set_caption('FPS: %.2f' % Clock.get_fps())
# Handle events
EventHandle.listen()
# Update game state
Player.update(dt)
# Draw
WINDOWSURFACE.fill((0, 0, 0)) # Black
Ground.draw()
Player.draw()
pygame.display.update()
pygame.quit()
sys.exit()
if __name__ == '__main__':
mainloop()
我的活动课上的更新 2
class EventManager(object):
''' Event management.
Listens and handles keyboard and mouse events.
'''
def __init__(self, player):
self.player = player
# Player movement flags, according to keyboard/mouse state
self.is_move_left, self.is_move_right = False, False
self.is_jump = False
def exit_game(self):
''' Closes pygame and sys modules.
A break statement follows this method to break the mainloop.
'''
pygame.quit()
sys.exit()
def listener(self):
''' Toggles Player movement flags, according to keyboard/mouse state.
'''
for event in pygame.event.get():
if event.type == QUIT:
self.exit_game()
break
if event.type == KEYDOWN:
if event.key == K_a:
self.is_move_left = True
elif event.key == K_d:
self.is_move_right = True
if event.type == KEYUP:
if event.key == K_ESCAPE:
self.exit_game()
break
if event.key == K_a:
self.is_move_left = False
elif event.key == K_d:
self.is_move_right = False
def handler(self):
''' Set Player velocity_goal according to movement flags.
'''
if self.is_move_left and not self.is_move_right:
self.player.velocity_goal.x = -self.player.MAX_VELOCITY
elif self.is_move_right and not self.is_move_left:
self.player.velocity_goal.x = self.player.MAX_VELOCITY
elif not self.is_move_left and not self.is_move_right:
self.player.velocity_goal.x = 0