【问题标题】:Object acting weird in vector movement物体在矢量运动中表现怪异
【发布时间】:2021-03-05 14:01:36
【问题描述】:

我目前有一个游戏,我希望用户通过将鼠标从球体拖动到任意位置来控制球体,程序将通过向相反方向移动球体来响应。方向很好,但是,我注意到在使用程序时,球体在左上方向的移动比在右下方向的移动少。我相信这可能是由于我对球体实施的重力减慢,但是,我无法找到导致问题的确切位置。

Main.py:

import pygame, sys, orb ...

def run_game():
    #Screen settings
    -snip-

    main_orb = Orb(screen)

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
        elif event.type == pygame.MOUSEBUTTONDOWN:
            main_orb.reset()
        elif event.type == pygame.MOUSEBUTTONUP:
            main_orb.release = True
            main_orb.calc_vector(mouse_pos)
        
    main_orb.update()
    main_orb.release_func(mouse_pos)
    main_orb.blitme()
    pygame.display.flip()

run_game()

orb.py

import pygame, math ...

class Orb():
    def __init__(self,screen):
        self.screen = screen

        # Get self image&rect and center position
        -snip-

        # Physics properties
        self.velocity = 0
        self.acceleration = 0
        self.vector = pygame.Vector2(0,-1)
        self.g = -30
        self.release = False

        # Update flag
        self.dont_update = False

    def reset(self):
        self.acceleration = 0
        self.velocity = 0
    def update(self):
        if self.velocity < 0 or self.dont_update == True:
            self.acceleration = 0
            self.velocity = 0
            self.dont_update = True
        else:
            self.acceleration = self.acceleration + self.g/60/60
            self.velocity = self.velocity + self.acceleration
            self.rect.x = self.rect.x + self.vector[0] * self.velocity
            self.rect.y = self.rect.y + self.vector[1] * self.velocity

    def calc_vector(self, mouse_pos):
        self.vector = pygame.Vector2(mouse_pos[0] - self.rect.centerx, 
                                         mouse_pos[1] - self.rect.centery)
        self.vector.rotate_ip(180)
        self.vector.normalize_ip()


    def release_func(self,mouse_pos):
        if self.release == True:
            self.acceleration = 2/1000 * math.hypot((self.rect.x-mouse_pos[0]),(self.rect.y-mouse_pos[1]))
            self.dont_update = False
            self.release = False

    def blitme(self):
        self.screen.blit(self.image,self.rect)

(P.S.)我知道我使用了很多标志,所以如果有任何关于如何重构代码的建议,将不胜感激。

【问题讨论】:

  • 好吧,除非它已经被关闭,否则您无法获得 MOUSEBUTTONUP。这应该允许您删除 mouse_down_before
  • 谢谢,我改了。当我编写代码时,我的印象是 mousebuttonup 是按钮的状态,但你的定义很清楚。
  • 你能发布你的整个代码,或者至少足够它可以测试吗?无法运行和测试程序真的很难调试
  • 没问题,我只是尝试发布最小的可重现示例。这是包含我当前代码的谷歌驱动器文件夹:drive.google.com/drive/folders/…

标签: python pygame


【解决方案1】:

问题是因为pygame.Rect存储了积分坐标:

Rect 对象的坐标都是整数。 [...]

self.vector[0] * self.velocityself.vector[1] * self.velocity 的小数部分在你这样做时会丢失:

self.rect.x = self.rect.x + self.vector[0] * self.velocity
self.rect.y = self.rect.y + self.vector[1] * self.velocity

另见Pygame doesn't let me use float for rect.move, but I need it


您必须以浮点精度进行计算。将pygame.Vector2 类型的属性self.pos 添加到类中:

class Orb():
    def __init__(self,screen):
        # [...]
        self.rect.center = self.screen_rect.center
        self.pos = pygame.Vector2(self.rect.center)

增加update中的属性并同步rect属性:

class Orb():
    # [...]

     def update(self):
        if self.velocity < 0 or self.dont_update == True:
            # [...]
        else:
            # [...]

            self.pos = self.pos + self.vector * self.velocity
            self.rect.center = round(self.pos.x), round(self.pos.y)

完整课程Orb:

class Orb():
    def __init__(self,screen):
        self.screen = screen

        # Get self image&rect and center position
        self.image = pygame.image.load('orb.bmp')
        self.rect = self.image.get_rect()
        self.screen_rect = screen.get_rect()
        self.rect.center = self.screen_rect.center
        self.pos = pygame.Vector2(self.rect.center)

        # physics properties
        self.velocity = 0
        self.acceleration = 0
        self.vector = pygame.Vector2(0,-1)
        self.collided = False
        self.g = -20
        self.release = False

        # Update flag
        self.dont_update = False

    def reset(self):
        self.acceleration = 0
        self.velocity = 0
    def update(self):
        if self.velocity < 0 or self.dont_update == True:
            self.acceleration = 0
            self.velocity = 0
            self.dont_update = True
        else:
            self.acceleration = self.acceleration + self.g/60/60
            self.velocity = self.velocity + self.acceleration
            print(self.vector)
            print(self.velocity)
            self.pos = self.pos + self.vector * self.velocity
            self.rect.center = round(self.pos.x), round(self.pos.y)

    def calc_vector(self, mouse_pos):
        self.vector = pygame.Vector2(mouse_pos[0] - self.pos.x, mouse_pos[1] - self.pos.y)
        self.vector.rotate_ip(180)
        self.vector.normalize_ip()


    def blitme(self):
        self.screen.blit(self.image,self.rect)

    def release_func(self,mouse_pos):
        if self.release == True:
            self.acceleration = 2/1000 * math.hypot((self.pos.x-mouse_pos[0]),(self.pos.y-mouse_pos[1]))
            self.dont_update = False
            self.release = False

    def collisioncheck(self):
        if self.rect.bottom >= self.screen_rect.bottom:
            self.collided = True
        elif self.rect.top <= self.screen_rect.top:
            self.collided = False
        elif self.rect.left <= self.screen_rect.left:
            self.collided = True
        elif self.rect.right >= self.screen_rect.right:
            self.collided = True
        else:
            self.collided = False

【讨论】:

    猜你喜欢
    • 2022-01-24
    • 1970-01-01
    • 1970-01-01
    • 2014-05-28
    • 1970-01-01
    • 2012-02-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多