- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
所以我决定在 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()
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
最佳答案
我不确定您的矩形字符对于每种可能的按键/按钮组合应该有什么 react ,因为有些是模棱两可的,例如同时按住左键和右键时 - 所以以下修改(仅适用于 EventManagement.Listen()
方法)可能不会产生完全受欢迎的行为。
在修订版中,如果您在向右移动的同时按下左键,则在您松开右键之前不会出现任何视觉效果,而在相反的情况下会发生相反的情况。无论哪种方式,速度都会平滑地变化。
基本上我所做的是将两个速度键的处理实现为 event-driven finite-state-machine它可以处于四种状态之一,代表这两个键处于向上或向下位置的所有可能组合。除此之外,还有 4 个不同的力度键“事件”对应于这些键的按下或释放。
代码有点长,因为它必须处理每个可能状态下的每个可能事件,但这并不是我所说的复杂。可以通过使其缩短 table-driven ,这是实现 finite-state-automata 的另一种方法.
# added constants
LEFT_KEY = K_a
RIGHT_KEY = K_d
LURU, LDRU, LURD, LDRD = range(4) # velocity states
LD, RD, LU, RU = range(4) # velocity key events
VEL_EVENTS = {LD, RD, LU, RU} # all possible velocity key events
MAX_VELOCITY = 200
class EventManagement(object):
''' Handles keyboard events.
Toggles player variables according to the event.
'''
def __init__(self, player):
self.player = player
self.state = LURU
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():
vel_event = None
if event.type == QUIT:
self.is_doneloop(True)
break
if event.type == KEYDOWN:
if event.key == LEFT_KEY:
vel_event = LD
elif event.key == RIGHT_KEY:
vel_event = RD
if event.type == KEYUP:
if event.key == K_ESCAPE:
self.is_doneloop(True)
break
if event.key == LEFT_KEY:
vel_event = LU
elif event.key == RIGHT_KEY:
vel_event = RU
if vel_event in VEL_EVENTS:
if self.state == LURU:
if vel_event == LD:
self.player.velocity_goal.x = -MAX_VELOCITY
self.state = LDRU
elif vel_event == RD:
self.player.velocity_goal.x = MAX_VELOCITY
self.state = LURD
elif self.state == LDRU:
if vel_event == RD:
self.state = LDRD
elif vel_event == LU:
self.state = LURU
self.player.velocity_goal.x = 0
elif self.state == LURD:
if vel_event == LD:
self.state = LDRD
elif vel_event == RU:
self.state = LURU
self.player.velocity_goal.x = 0
elif self.state == LDRD:
if vel_event == LU:
self.state = LURD
self.player.velocity_goal.x = MAX_VELOCITY
elif vel_event == RU:
self.state = LDRU
self.player.velocity_goal.x = -MAX_VELOCITY
#-------------------------------------------------------------------------
更新
update()
中注释掉的行:
# self.position = self.position.add(self.velocity) * dt
不起作用,因为它不是 C++ 版本的正确翻译:
box.vecPosition = box.vecPosition + box.vecVelocity * dt;
因为它添加了
position
至
velocity
首先,然后将结果乘以
dt
.所以要修复它,只需让你的相同:
self.position.x = self.position.x + (self.velocity.x * dt)
这将允许数量
self.velocity.x * dt
首先通过标准计算
operator precedence ,然后将其添加到
self.position.x
.
velocity_goal.x
引起的值太小(代码中的 +/-7)。相反,使用更大的东西,比如
200
.当你在做的时候,用一个新的常量替换它们——比如
MAX_VELOCITY = 200
所以你只需要在一个地方改变这个值。
Vector
通过这种方式编写代码稍微类:
class Vector(object):
''' Performs vector arithmetic
'''
def __init__(self, x, y):
self.x, self. y = x, y
def add(self, v):
return Vector(self.x + v.x, self.y + v.y)
def mult(self, s):
return Vector(s * self.x, s * self.y)
你可以更进一步定义
Vector.__add__()
,
Vector.__mul__()
等,然后才能更自然地使用它们。
self.ground = {'shape': self.rect, 'color': self.color}
和
self.player = {'shape': self.rect, 'color': self.color}
只需
self.shape
和
self.color
属性——因为把它们放在一个单独的字典中几乎没有什么好处,相反只会减慢访问它们的值并使访问复杂化。
# added constants
LEFT_KEY = K_a
RIGHT_KEY = K_d
LURU, LDRU, LURD, LDRD = range(4) # velocity states
LD, RD, LU, RU = range(4) # velocity key events
VEL_EVENTS = {LD, RD, LU, RU} # every velocity key event value
NEW_VELOCITY_GOAL, NEW_STATE = range(2) # indices of EVENT_DECISION_TABLE entries
MAX_VELOCITY = 200
# non-None entries represent new velocity_goal and state value for each event for each state
EVENT_DECISION_TABLE = [
# event LD RD LU RU # cur state
[[-MAX_VELOCITY, LDRU], [MAX_VELOCITY, LURD], [None, None], [None, None]], # LURU
[[None, None], [None, LDRD], [0, LURU], [None, None]], # LDRU
[[None, LDRD], [None, None], [None, None], [0, LURU]], # LURD
[[None, None], [None, None], [MAX_VELOCITY, LURD], [-MAX_VELOCITY, LDRU]], # LDRD
]
class EventManagement(object):
''' Handles keyboard event's.
Toggles player variables according to the event's.
'''
def __init__(self, player):
self.player = player
self.state = LURU
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():
vel_event = None
if event.type == QUIT:
self.is_doneloop(True)
break
elif event.type == KEYDOWN:
if event.key == LEFT_KEY:
vel_event = LD
elif event.key == RIGHT_KEY:
vel_event = RD
elif event.type == KEYUP:
if event.key == K_ESCAPE:
self.is_doneloop(True)
break
elif event.key == LEFT_KEY:
vel_event = LU
elif event.key == RIGHT_KEY:
vel_event = RU
if vel_event in VEL_EVENTS:
entry = EVENT_DECISION_TABLE[self.state][vel_event]
if entry[NEW_VELOCITY_GOAL] is not None:
self.player.velocity_goal.x = entry[NEW_VELOCITY_GOAL]
if entry[NEW_STATE] is not None:
self.state = entry[NEW_STATE]
#-------------------------------------------------------------------------
更新 3
PlayerData.approach()
相关的系列视频方法,我想我现在明白它的作用(以及为什么它的代码让我感到困惑)。
dt
参数不是时间差值,这就是为什么它需要在
PlayerData.update()
之前乘以另一个魔数(Magic Number)称它。基本上它是每个增量时间的增量速度(也称为加速度)。它的值与最大速度、每秒帧数 (FPS) 以及您希望玩家从零(平均加速度)达到该速度所需的时间有关。
value passed to
PlayerData.update()` 将是 0.025 秒,因此如果最大速度为 80 或 1000,即使您每秒执行 40 次,将其添加到当前速度也几乎没有影响。
dt
对于给定的 FPS,它应该是一个相当常数,每帧加速度可以提前计算并存储为另一个命名常数。
# more constants
MAX_VELOCITY = 200
ACCEL_TIME = 1 # secs to accelerate to max velocity (or slow down from it)
AVG_ACCEL = MAX_VELOCITY / float(ACCEL_TIME) # per sec
ACCEL_PER_FRAME = AVG_ACCEL / FPS
class PlayerData(object):
### showing updated methods only
def approach(self, vel_goal, vel_curr, accel):
difference = vel_goal - vel_curr
if difference > accel:
return vel_curr + accel
if difference < -accel:
return vel_curr - accel
return vel_goal
def update(self, dt):
self.velocity.x = self.approach(self.velocity_goal.x,
self.velocity.x, ACCEL_PER_FRAME)
self.position.x = self.position.x + (self.velocity.x * dt)
self.player['shape'].top = self.position.y
self.player['shape'].left = self.position.x
关于python - lerp 移动和键盘移动按钮 - 快速按下会导致角色卡在原地,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19808183/
在 Android 的 API > 19 中是否有任何方法可以获取可移动 SD 卡的路径? 与外部 SD 卡一样,我们有 Environment.getExternalStorageDirectory
一些 Android 设备有 microSD(或其他存储卡)插槽,通常安装为 /storage/sdcard1 据我所知,自 Android 4.4 起 Google 限制了对此内存的访问,并在 An
我使用 Java Card 2.1.2 SDK 和 GPShell 作为与设备通信的方式在 Java Card 上构建一个项目。我从 GpShell 测试了 helloworld 示例,并成功发送了
我开发了一个应用程序,它有一个来电接收器,它适用于所有手机。一位用户有一部双 SIM 卡安卓手机。该应用程序适用于第一张 SIM 卡。但是当有人调用他的第二张 SIM 卡时,我们的应用程序不会被调用。
我有一个带预览的文件输入。 这是笔 Codepen 我想强制高度,我无法理解我该怎么做。我想将此组件的高度固定为 300px(示例),我还需要保持加载图像的正确纵横比,用灰色背景填充空白。现在我保持宽
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 想改进这个问题?将问题更新为 on-topic对于堆栈溢出。 6年前关闭。 Improve this qu
我正在使用此代码访问 SD card : import os from os.path import join from jnius import autoclass #from android.pe
我正在为数据记录设备编写固件。它以 20 Hz 的频率从传感器读取数据并将数据写入 SD 卡。但是,向SD卡写入数据的时间并不一致(大约200-300 ms)。因此,一种解决方案是以一致的速率将数据写
我正在使用以下代码将视频放到网站上,但是在垂直方向上,手机屏幕上只能看到视频的左半部分 我不是网络开发人员。有人可以告诉我确切的内容吗,如何使其正确放置在手机屏幕上? 是在youtube iframe
我正在使用 Vuetify 1.5 和 Vuetify 网格系统来设置我的布局。现在我有一个组件 HelloWorld我将其导入到我的 Parent 中成分。我已经在我的 HelloWorld 中设置
我使用 python 制作了一个简单的二十一点游戏。我制作了游戏的其余部分,但我正在努力放入 ASCII 卡,所以这只是代码的一小部分。我尝试将 * len(phand) 放在附加行的末尾。虽然这确实
我正在使用玩家卡设置 Twitter 卡。它可以在预览工具中运行,但文档说它需要在“twitter.com 现代桌面浏览器? native iOs 和 Android Twitter 应用程序?mob
任何旧的 GSM 兼容 SIM 卡(3G USIM 的奖励)。 我想我需要一些硬件?谁能为业余爱好者推荐一些便宜的东西,以及一些更专业的东西? 我认为会有一个带有硬件的 API 的完整文档,所以也许这
我使用 python 制作了一个简单的二十一点游戏。我制作了游戏的其余部分,但我正在努力放入 ASCII 卡,所以这只是代码的一小部分。我尝试将 * len(phand) 放在附加行的末尾。虽然这确实
我记得前一段时间读到有 cpu 卡供系统添加额外的处理能力来进行大规模并行化。任何人都有这方面的经验和任何资源来研究项目的硬件和软件方面吗?这项技术是否不如传统集群?它更注重功率吗? 最佳答案 有两个
我检查外部存储是否已安装并且可用于读/写,然后从中读取。我使用的是确切的官方 Android 示例代码 ( from here )。 它说外部存储未安装。 getExternalFilesDir(nu
在 Android 2.1 及更低版本中,Android 应用程序可以请求下载到 SD 卡上吗?另外我想知道应用程序是否可以请求一些包含视频的文件夹下载到 SD 卡上?以及如何做到这一点? 提前致谢。
我们编写了一个 Windows 设备驱动程序来访问我们的自定义 PCI 卡。驱动程序使用 CreateFile 获取卡的句柄。 我们最近在一次安装中遇到了问题,卡似乎停止工作了。我们尝试更换卡(更换似
有些新设备(例如 Samsung Galaxy)带有两个 SD 卡。我想知道是否有任何方法可以确定设备是否有两张 SD 卡或一张 SD 卡。谢谢 最佳答案 我认为唯一的方法是使用 检查可用根的列表 F
我正在尝试将文件读/写到 SD 卡。我已经尝试在我的真实手机和 Eclipse 中的模拟器上执行此操作。在这两种设备上,对/mnt/sdcard/或/sdcard 的权限仅为“d--------”,我
我是一名优秀的程序员,十分优秀!