简单的拖动物理,向左或向右移动时的动作不同 [英] Simple drag physics, acting differently when moving left or right

查看:30
本文介绍了简单的拖动物理,向左或向右移动时的动作不同的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的代码对负速度的作用不同于正速度

我正在尝试实现平台物理学,玩家在X方向上具有速度,当用户按下"A"时,速度会增加或减少.或"D"或当玩家与墙壁碰撞时设置为0.

为了模拟与地面的摩擦,将玩家的X速度乘以"self.drag".(浮点数小于1)

我希望这段代码能够降低玩家的X速度,随着时间的流逝,它会微弱地降低到接近0,而实际上并未反转速度(就像减去一个值一样),这将阻止玩家在用户不在的情况下无法控制地滑动估算移动命令.

此功能在向右移动时如预期那样工作,但是在向左移动时它的行为有所不同,当向左移动时,玩家似乎在停止之前会继续漂浮一段时间.

在播放器类中,这是需要播放器输入的代码,运行每一帧:

  dx = 0如果pygame.key.get_pressed()[pygame.K_a]:dx-= self.speed如果pygame.key.get_pressed()[pygame.K_d]:dx + = self.speed#减慢水平运动self.vx * = self.drag#将速度变化添加到总速度self.vx + = dxself.vy + = dy 

也许这个概念行得通,但我没有正确实现它?有碰撞代码可能以我未注意到的方式影响速度吗?对于正负速度,此系统是否工作不同?

谢谢!任何帮助都非常感激

解决方案

之所以引起该问题,是因为 self.Rect.x + = dx

  self.Rect.y + = dy 


您必须以浮点精度进行计算.向该类添加 x y 属性.在 move 中增加属性,并同步 Rect 属性:

  class Player:def __init __(自身,颜色):self.Rect = pygame.Rect([50,50],[30,50])self.x = self.Rect.xself.y = slef.Rect.y#[...]def移动(self,dx,dy,平台):#测试与平台的碰撞#处理X轴上的运动self.x + = dxself.Rect.x =轮(self.x)对于平台中的平台:如果self.Rect.colliderect(platform.Rect):如果dx>0:self.Rect.right =平台.Rect.left如果dx<0:self.Rect.left =平台.Rect.rightself.x = self.Rect.x#重置与墙碰撞时的速度self.vx = 0#处理Y轴上的运动self.Rect.y + = dyself.Rect.y = round(self.y)对于平台中的平台:如果self.Rect.colliderect(platform.Rect):如果dy>0:self.Rect.bottom =平台.Rect.top如果dy<0:self.Rect.top =平台.Rect.bottomself.y = self.Rect.y#与地板或屋顶碰撞时重置速度self.vy = 0#将正确碰撞的矩形返回给draw()返回self.Rect 

My code is acting differently for negative velocities than it is positive ones

I'm trying to implement platformer physics, the player has velocity in the X direction, the velocity is increased or decreased when the user presses "A" or "D" respectively, or set to 0 when the player collides with a wall.

To simulate friction with the ground, the X Velocity of the player is multiplied with "self.drag" (a float less than 1)

I expected this code to reduce the players X Velocity, over time reducing it neglibly near to 0, without actually reversing the velocity (like subtracting a value would), this would stop the player sliding about uncontrollably when the user isn't imputing movement commands.

This works as intended when moving right, however when moving left it acts differently, when moving to the left the player seems to continue floating for a while before coming to a stop.

Here's the code that takes player input, inside the player class, run each frame:

dx = 0
if pygame.key.get_pressed()[pygame.K_a]:
        dx -= self.speed
if pygame.key.get_pressed()[pygame.K_d]:
        dx += self.speed

# to slow down horizontal movement
self.vx *= self.drag

# Add change in velocity to total velocity
self.vx += dx
self.vy += dy

Maybe the concept works and I've implemented it incorrectly? There's collision code that may be affecting the velocities in ways I haven't noticed? Does this system work differently for positive and negative velocities?

Thanks! Any help is much appreciated

解决方案

The issue is caused, because pygame.Rect stores integral coordinates:

The coordinates for Rect objects are all integers. [...]

The fraction component of dx and dy is lost when you do:

self.Rect.x += dx

self.Rect.y += dy


You have to do the calculations with floating point accuracy. Add an x ​​and y attribute to the class. Increment the attributes in move and synchronize the Rect attribute:

class Player:
    def __init__(self, color):
        self.Rect = pygame.Rect([50, 50], [30, 50])
        self.x = self.Rect.x
        self.y = slef.Rect.y
        # [...]

    def move(self, dx, dy, platforms):
        # Test for collisions with platforms

        # handle movement on the X axis
        self.x += dx
        self.Rect.x = round(self.x)
        for platform in platforms:
            if self.Rect.colliderect(platform.Rect):
                if dx > 0:
                    self.Rect.right = platform.Rect.left
                if dx < 0:
                    self.Rect.left = platform.Rect.right
                self.x = self.Rect.x
                # Reset velocity when collision with wall
                self.vx = 0

        # handle movement on the Y axis
        self.Rect.y += dy
        self.Rect.y = round(self.y)
        for platform in platforms:
            if self.Rect.colliderect(platform.Rect):
                if dy > 0:
                    self.Rect.bottom = platform.Rect.top
                if dy < 0:
                    self.Rect.top = platform.Rect.bottom
                self.y = self.Rect.y
                # Reset velocity when collision with floor or roof
                self.vy = 0

        # return correctly collided rect to draw()
        return self.Rect 

这篇关于简单的拖动物理,向左或向右移动时的动作不同的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆