【问题标题】:Python Pygame Making a ball push another ballPython Pygame 让一个球推动另一个球
【发布时间】:2021-03-20 12:09:01
【问题描述】:

我试图让一个球推动另一个球,问题是当球相撞时,红球进入蓝色,红色向鼠标左键移动,蓝色球在鼠标右键单击时被绘制。我注意到速度 (Velocidad) 和

        self.xb2-=self.dx+overlapx/(tamaño/2)
        self.yb2-=self.dy+overlapy/(tamaño/2)

除数 tamaño/2 的大小在问题中具有重要作用。

这是代码

import pygame, math, random
pygame.init()
vel = 5
ancho = 600
alto = 500
tamaño=30
color = (250,0,0)
color2= (0,0,250)
FPS=60
negro= 0,0,0
posantes = [[300,250], [- 50, - 50]]   #posicion anterior, bola  y bola1/ initial position bola , initial position bola1
mouse = [[300,250], [ - 50, - 50]]            #posicion mouse, click izquierdo  , click derecho
pantalla = pygame.display.set_mode((ancho, alto))
reloj = pygame.time.Clock()
class Bola():
    def __init__(self, color, xyb, tamaño):
        super().__init__()
        pygame.draw.circle(pantalla, color, xyb,tamaño)
        
    def colision(self,xyb,xyb2):
        self.colision = False
        self.xyb = posantes [0]
        self.xyb2 = posantes[1]
        self.xb,self.yb = posantes[0][0],posantes[0][1]
        self.xb2,self.yb2 = posantes[1][0],posantes[1][1]
        dist = math.hypot(self.xb2-self.xb,self.yb2-self.yb)
       
        if dist<tamaño*2:
            self.colision =True
        else:
            self.colision =False
        
    def reaccion(self,xyb,xyb2):
        overlapx , overlapy = self.xb-self.xb2, self.yb-self.yb2    
        if self.colision==True:
          
            self.xb2-=self.dx+overlapx/(tamaño/2)
            self.yb2-=self.dy+overlapy/(tamaño/2)
            posantes[1]=[self.xb2,self.yb2]
            print(" !! reaccion   ¡¡")
    
    def moverbola(self, xyb, xy,bi):
        
        self.xyb = posantes[bi]
        self.xy  = mouse[bi]
        self.xb,self.yb = self.xyb[0] , self.xyb[1]
        self.x,self.y = self.xy[0] , self.xy[1]
        self.dx,self.dy = abs(self.x-self.xb) , abs(self.y-self.yb)
        dist = math.hypot(self.x-self.xb,self.y-self.yb)
       
        if   dist!= 0:
            self.dx = self.dx / dist
            self.dy = self.dy / dist
    
        if self.xb < self.x:
            self.xb+=vel * self.dx
        if self.xb > self.x:
            self.xb-=vel * self.dx
        if self.yb < self.y:
            self.yb+=vel * self.dy
        if self.yb > self.y :
            self.yb -=vel * self.dy
        self.xyb = [self.xb,self.yb]
        posantes[bi] = self.xyb
      
    
terminar = False
    
while not terminar:
    reloj.tick(FPS)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            terminar=True
        if event.type == pygame.MOUSEBUTTONDOWN and event.button==1:
            mouse[0] = pygame.mouse.get_pos()[0], pygame.mouse.get_pos()[1]
        if event.type == pygame.MOUSEBUTTONDOWN and event.button==3:
            mouse[1] = pygame.mouse.get_pos()[0],pygame.mouse.get_pos()[1] 
            posantes[1] = mouse[1]
           
    pantalla.fill(negro)
    bola1 = Bola(color2, posantes[1], tamaño)
    bola = Bola(color,posantes[0], tamaño)
    bola.moverbola(posantes[0], mouse[0],0)
    bola.colision(posantes[0],posantes[1])
    bola.reaccion(posantes[0],posantes[1])
   
   
    
    pygame.display.update()
     
pygame.quit()
quit()

【问题讨论】:

标签: python pygame push physics collision


【解决方案1】:

您误解了面向对象编程的概念。您必须在应用程序循环之前创建 Bola 类的实例,但在循环中使用它们:

bola1 = Bola(color2, [-50, -50], tamaño)
bola = Bola(color, [300, 250], tamaño)

terminar = False
while not terminar:

    bola1.draw()
    bola.draw()

在构造函数中设置属性Bola并在方法中使用它,例如B.到drawBola

class Bola():
    def __init__(self, color, xyb, tamaño):
        super().__init__()
        self.color = color
        self.xyb = xyb
        self.tamaño = tamaño

    def draw(self):
        pos = round(self.xyb[0]), round(self.xyb[1])
        pygame.draw.circle(pantalla, self.color, pos, self.tamaño)

确保方法和属性具有不同的名称(collisioncolision_test)。 colision_test 方法返回测试结果:

class Bola():
    # [...]

    def colision_test(self,xyb2):
        dist = math.hypot(xyb2[0] - self.xyb[0], xyb2[1] - self.xyb[1])
        self.colision = dist < tamaño*2
        return (self.colision, dist)

根据函数的参数在reaccionmoverbola方法中移动Bola并更改存储位置的属性:

class Bola():
    # [...]

    def reaccion(self, xyb_other, reaction_dist):
        dx, dy = xyb_other[0] - self.xyb[0], xyb_other[1] - self.xyb[1]
        dist = math.hypot(dx, dy)
        if dist > 0:
            self.xyb = [self.xyb[0] - dx * reaction_dist / dist, self.xyb[1] - dy * reaction_dist / dist]

    def moverbola(self, target):
        dx, dy = target[0] - self.xyb[0], target[1] - self.xyb[1]
        dist = math.hypot(dx, dy)
        if dist > 0:
            step = min(dist, vel)
            self.xyb = [self.xyb[0] + dx * step / dist, self.xyb[1] + dy * step / dist]

完整示例:

import pygame, math, random
pygame.init()
vel = 5
ancho = 600
alto = 500
tamaño=30
color = (250,0,0)
color2= (0,0,250)
FPS=60
negro= 0,0,0

pantalla = pygame.display.set_mode((ancho, alto))
reloj = pygame.time.Clock()

class Bola():
    def __init__(self, color, xyb, tamaño):
        super().__init__()
        self.color = color
        self.xyb = xyb
        self.tamaño = tamaño

    def draw(self):
        pos = round(self.xyb[0]), round(self.xyb[1])
        pygame.draw.circle(pantalla, self.color, pos, self.tamaño)
        
    def colision_test(self,xyb2):
        dist = math.hypot(xyb2[0] - self.xyb[0], xyb2[1] - self.xyb[1])
        self.colision = dist < tamaño*2
        return (self.colision, dist)
        
    def reaccion(self, xyb_other, reaction_dist):
        dx, dy = xyb_other[0] - self.xyb[0], xyb_other[1] - self.xyb[1]
        dist = math.hypot(dx, dy)
        if dist > 0:
            self.xyb = [self.xyb[0] - dx * reaction_dist / dist, self.xyb[1] - dy * reaction_dist / dist]

    def moverbola(self, target):
        dx, dy = target[0] - self.xyb[0], target[1] - self.xyb[1]
        dist = math.hypot(dx, dy)
        if dist > 0:
            step = min(dist, vel)
            self.xyb = [self.xyb[0] + dx * step / dist, self.xyb[1] + dy * step / dist]
      
bola1 = Bola(color2, [-50, -50], tamaño)
bola = Bola(color, [300, 250], tamaño)
bola_target = [300, 250]

terminar = False
while not terminar:
    reloj.tick(FPS)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            terminar=True
        if event.type == pygame.MOUSEBUTTONDOWN and event.button==1:
            bola_target = event.pos
        if event.type == pygame.MOUSEBUTTONDOWN and event.button==3:
            bola1.xyb = event.pos
           
    bola.moverbola(bola_target)
    collision, dist = bola1.colision_test(bola.xyb)
    if collision:
        reaccion = (tamaño * 2 - dist)
        bp = bola.xyb[:]
        bp1 = bola1.xyb[:]
        bola.reaccion(bp1, reaccion)
        bola1.reaccion(bp, reaccion)
   
    pantalla.fill(negro)
    bola1.draw()
    bola.draw()
    pygame.display.update()
     
pygame.quit()
quit()

【讨论】:

  • 你能解释一下为什么反应等于 self.xyb = [self.xyb[0] - dx * reaction_dist / dist, self.xyb[1] - dy * reaction_dist / dist] 我明白了dx 和 dy 除以 dist 对向量进行归一化,你对 react_dist / dist 做同样的事情吗?我也不明白,这一行 step = min(dist, vel) Thx
  • (dx / dist, dy /dist) 是归一化距离,(dx * reaction_dist / dist, dy * reaction_dist / dist) 是长度为 reaction_dist 的向量。 Bola 不应越过目标。如果到目标的距离小于vel,则必须限制步长。因此step = min(dist, vel)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多