Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/352.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 你能帮我修复pygame物理模拟中的这个错误吗?_Python_Pygame - Fatal编程技术网

Python 你能帮我修复pygame物理模拟中的这个错误吗?

Python 你能帮我修复pygame物理模拟中的这个错误吗?,python,pygame,Python,Pygame,我在pygame中编写了这个物理模拟,碰撞机制无法正常工作。当我从墙上方或左侧将玩家角色与墙碰撞时,它似乎起作用,而从底部或右侧碰撞时则不起作用 我已经试着找到这个bug有一段时间了,但我只是不知道是什么导致了这个。我正在使用python 3.7.3和pygame 1.9.5(最新版本) 很抱歉粘贴了整个文件,但我不知道问题出在哪里 import pygame # import the pygame library to have access to game building tools i

我在pygame中编写了这个物理模拟,碰撞机制无法正常工作。当我从墙上方或左侧将玩家角色与墙碰撞时,它似乎起作用,而从底部或右侧碰撞时则不起作用

我已经试着找到这个bug有一段时间了,但我只是不知道是什么导致了这个。我正在使用python 3.7.3和pygame 1.9.5(最新版本)

很抱歉粘贴了整个文件,但我不知道问题出在哪里

import pygame  # import the pygame library to have access to game building tools
import math

# these variables will be used to hold game objects and draw them
rigid_bodies = []
g = 100
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
PURPLE = (127, 0, 255)
RED = (200, 0, 0)
GREEN = (0, 200, 0)
BLUE = (0, 0, 200)


class RigidBody(pygame.Rect):
    """
    represents a rectangular object that acts according to newton's laws of motion
    """

    def __init__(self, canvas, color, m, u, x, y, w, h):
        """
        called automatically when a new object is created to initialize the object
        :param canvas: the canvas on which to draw the object
        :param color: the color of the object
        :param m: the mass of the object
        :param u: Coefficient of friction
        :param x: the starting position of the object on the x axis
        :param y: the starting position of the object on the y axis
        :param w: the width of the object
        :param h: the height of the object
        """
        super().__init__(x, y, w, h)  # initialize the parent Rect object
        self.canvas = canvas
        self.color = color
        self.m = m
        self.u = u
        self.x_speed = 0  # the speed of the object on the x axis
        self.y_speed = 0  # the speed of the object on the y axis

    def apply_force(self, axis, F, initiator=None):
        """
        used to apply force on the object
        :param axis: the axis of the force
        :param F: the amount of force to apply
        :param initiator: the object that is applying the force
        """
        a = F / self.m  # calculate the acceleration the object should have
        if axis == 'y':
            self.y_speed += a
        elif axis == 'x':
            self.x_speed += a
        if initiator:
            initiator.apply_force(axis, -1 * F)  # apply normal force
            print('colliding')

    def inertia(self):
        """
        shall be run every frame to make the object move according to its speed
        if possible and take the necessary steps if not
        """
        # go:
        self.x += self.x_speed
        self.y += self.y_speed
        for body in rigid_bodies:
            if self.colliderect(body):  # if collide with another object:
                self.x -= self.x_speed  # go back
                self.y -= self.y_speed
                body.apply_force('x', self.m * self.x_speed, self)  # and apply force on that object
                body.apply_force('y', self.m * self.y_speed, self)
                break

    def draw(self):
        """
        shall be run every frame to draw the object on the canvas
        """
        pygame.draw.rect(self.canvas, self.color, (self.x, self.y, self.w, self.h))


class Controller:
    def __init__(self, character, F):
        """
        initialize the controller object
        :param character: the character to control
        :param F: the force to apply to the character for every frame a button is being pressed
        """
        self.character = character
        self.up = 0  # whether to move up or not
        self.down = 0  # whether to move down or not
        self.left = 0  # whether to move left or not
        self.right = 0  # whether to move right or not
        self.F = F

    def stop(self):
        """
        stops applying force on the object
        """
        self.up = 0
        self.down = 0
        self.left = 0
        self.right = 0

    def run(self):
        """
        shall be run every frame to apply force on the character according to user input
        """
        self.character.apply_force('y', -self.F * self.up)
        self.character.apply_force('y', self.F * self.down)
        self.character.apply_force('x', -self.F * self.left)
        self.character.apply_force('x', self.F * self.right)


def main():
    """
    the main function contains the main loop
    that runs repeatedly while the game is running
    """
    crashed = False  # tells if the program crashed or if the window was closed
    pygame.init()  # required to use pygame
    canvas = pygame.display.set_mode((1000, 700))  # define the canvas
    clock = pygame.time.Clock()  # will be used to limit the number of times a loop runs per second
    pygame.display.set_caption('the dot game V2')
    character = RigidBody(canvas, WHITE, 1000, 0.3, 500, 500, 20, 50)  # initialize the character
    player = Controller(character, 500)  # initialize the controller
    rigid_bodies.append(RigidBody(canvas, WHITE, math.inf, 0, 300, 300, 300, 20))  # initialize the wall
    while not crashed:
        # handle inputs:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                crashed = True
            elif event.type == pygame.MOUSEBUTTONUP:
                pass
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_UP:
                    player.up = 1
                elif event.key == pygame.K_DOWN:
                    player.down = 1
                elif event.key == pygame.K_LEFT:
                    player.left = 1
                elif event.key == pygame.K_RIGHT:
                    player.right = 1
            elif event.type == pygame.KEYUP:
                player.stop()
        player.run()
        character.inertia()
        canvas.fill(BLACK)
        character.draw()
        for body in rigid_bodies:
            body.draw()
        pygame.display.update()
        clock.tick(60)


if __name__ == '__main__':
    main()
我怀疑问题出在“惯性”或“施加力”函数上,但我就是不知道这些函数有什么问题


角色每次撞击墙壁时都应该停止移动,但当它从下方或右侧撞击墙壁时,它会被卡住,只能向上或向左移动

该问题是由将浮点值强制转换为int引起的,可以通过以下方法解决:

存储位置=(self.x,self.y)
self.x+=self.x\u速度
self.y+=self.y\u速度
对于刚体中的实体:
if self.collide rect(body):#如果与另一个对象碰撞:
self.x,self.y=存储位置

请注意

不是的逆运算

e、 g:
a=2
b=0.5

int(a+b)==int(2+0.5)==2
int(a-b)==int(2-0.5)==1

解决方案是存储
self.x
self.y

存储位置=(self.x,self.y)
并在发生碰撞时恢复:

self.x,self.y=存储位置
self.x -= self.x_speed
self.y -= self.y_speed
self.x += self.x_speed
self.y += self.y_speed