Физика прыгающего мяча - PullRequest
       23

Физика прыгающего мяча

1 голос
/ 05 ноября 2019

Недавно я пытался создать прыгающий шар в Pygame, и мне удалось использовать спрайт-прямоугольник, однако, когда дело доходит до плавающего блока, шар не знает, следует ли инвертировать горизонтальную или вертикальную скорость или если онпопадает в угол, поэтому я начал использовать точки столкновения, но после многих неудачных попыток, когда мяч должен стать неподвижным вертикально, шар просто вибрирует.

Вот мой код для обработки столкновений:

def HitHorizontal(self):
        self.velocity[0] = self.velocity[0] * self.bounce
        self.velocity[1] = -self.velocity[1] * self.bounce
        self.move_y = self.velocity[1]


    def HitVertical(self):
        self.velocity[0] = -self.velocity[0] * self.bounce
        self.velocity[1] = self.velocity[1] * self.bounce
        self.move_x = self.velocity[0]



    def move_checker(self,obj):
        rect = obj.rect
        #hits left or right of ball
        horizontal = False
        vertical = False
        if rect.collidepoint((self.rect.topleft[0]+self.move_x,self.rect.topleft[1])):
            vertical = True
        elif rect.collidepoint((self.rect.topright[0]+self.move_x,self.rect.topright[1])):
            vertical = True
        elif rect.collidepoint((self.rect.bottomleft[0]+self.move_x,self.rect.bottomleft[1])):
            vertical = True
        elif rect.collidepoint((self.rect.bottomright[0]+self.move_x,self.rect.bottomright[1])):
            vertical = True

        #hits top or bottom of ball

        if rect.collidepoint((self.rect.topleft[0],self.rect.topleft[1]+self.move_y)):
            horizontal = True
        elif rect.collidepoint((self.rect.topright[0],self.rect.topright[1]+self.move_y)):
            horizontal = True
        elif rect.collidepoint((self.rect.bottomleft[0],self.rect.bottomleft[1]+self.move_y)):
            horizontal = True
        elif rect.collidepoint((self.rect.bottomright[0],self.rect.bottomright[1]+self.move_y)):
            horizontal = True

        #hits corner of wall

        if rect.collidepoint((self.rect.topleft[0]+self.move_x,self.rect.topleft[1]+self.move_y)):
            vertical = True
            horizontal = True
        elif rect.collidepoint((self.rect.topright[0]+self.move_x,self.rect.topright[1]+self.move_y)):
            vertical = True
            horizontal = True
        elif rect.collidepoint((self.rect.bottomleft[0]+self.move_x,self.rect.bottomleft[1]+self.move_y)):
            vertical = True
            horizontal = True
        elif rect.collidepoint((self.rect.bottomright[0]+self.move_x,self.rect.bottomright[1]+self.move_y)):
            vertical = True
            horizontal = True

        if horizontal:
            self.HitHorizontal()
        if vertical:
            self.HitVertical()

Вот полный код:

import sys, pygame, random, math, time
pygame.init()

xsize = 800
ysize = 600
startx = 600
starty = 100

class Wall(pygame.sprite.Sprite):
    def __init__(self, x, y, w, h):
        super().__init__()
        self.image = pygame.Surface((w, h))
        self.image.fill((0,0,0))
        self.rect = self.image.get_rect(topleft=(x, y))

class Ball(pygame.sprite.Sprite):

    def __init__(self):
        super().__init__()
        self.velocity = [0, 0]
        self.image = pygame.image.load('ball.png')
        self.image = pygame.transform.scale(self.image,(50,50))
        self.gravity = 9.81
        self.bounce = 0.8

        self.rect = self.image.get_rect()
        self.put(startx, starty)
        self.collision = [False] * 9
        self.velocity[0] = 0
        self.velocity[1] = 0

    def put(self, x, y):
        self.rect.x = x
        self.rect.y = y

    def push(self, x, y):
        self.velocity[0]= x
        self.velocity[1] = y

    def Get_Move(self):
        self.move_x = self.velocity[0]
        self.velocity[1] += (self.gravity * 0.2)
        self.move_y = self.velocity[1]



    def update(self):
        self.rect.x += self.move_x
        self.rect.y += self.move_y



    def HitHorizontal(self):
        self.velocity[0] = self.velocity[0] * self.bounce
        self.velocity[1] = -self.velocity[1] * self.bounce
        self.move_y = self.velocity[1]


    def HitVertical(self):
        self.velocity[0] = -self.velocity[0] * self.bounce
        self.velocity[1] = self.velocity[1] * self.bounce
        self.move_x = self.velocity[0]



    def move_checker(self,obj):
        rect = obj.rect
        #hits left or right of ball
        horizontal = False
        vertical = False
        if rect.collidepoint((self.rect.topleft[0]+self.move_x,self.rect.topleft[1])):
            vertical = True
        elif rect.collidepoint((self.rect.topright[0]+self.move_x,self.rect.topright[1])):
            vertical = True
        elif rect.collidepoint((self.rect.bottomleft[0]+self.move_x,self.rect.bottomleft[1])):
            vertical = True
        elif rect.collidepoint((self.rect.bottomright[0]+self.move_x,self.rect.bottomright[1])):
            vertical = True

        #hits top or bottom of ball

        if rect.collidepoint((self.rect.topleft[0],self.rect.topleft[1]+self.move_y)):
            horizontal = True
        elif rect.collidepoint((self.rect.topright[0],self.rect.topright[1]+self.move_y)):
            horizontal = True
        elif rect.collidepoint((self.rect.bottomleft[0],self.rect.bottomleft[1]+self.move_y)):
            horizontal = True
        elif rect.collidepoint((self.rect.bottomright[0],self.rect.bottomright[1]+self.move_y)):
            horizontal = True

        #hits corner of wall

        if rect.collidepoint((self.rect.topleft[0]+self.move_x,self.rect.topleft[1]+self.move_y)):
            vertical = True
            horizontal = True
        elif rect.collidepoint((self.rect.topright[0]+self.move_x,self.rect.topright[1]+self.move_y)):
            vertical = True
            horizontal = True
        elif rect.collidepoint((self.rect.bottomleft[0]+self.move_x,self.rect.bottomleft[1]+self.move_y)):
            vertical = True
            horizontal = True
        elif rect.collidepoint((self.rect.bottomright[0]+self.move_x,self.rect.bottomright[1]+self.move_y)):
            vertical = True
            horizontal = True

        if horizontal:
            self.HitHorizontal()
        if vertical:
            self.HitVertical()



class Game:

    def __init__(self):
        self.AllSprites = pygame.sprite.Group()
        self.Walls = pygame.sprite.Group()
        self.total_shots = 0
        self.putting = False
        self.LoadLevel()

    def LoadLevel(self):
        self.GetWalls()

    def start(self):
        self.ball.Moving = True


    def GetWalls(self):
        self.wall_list = [[0,300,xsize,600],[0,-30,xsize,30],[-30,0,30,ysize],[xsize,0,30,ysize],[0,100,300,20 ]]

    def CreateWalls(self):
        for wally in self.wall_list:
            new_wall = Wall(wally[0],wally[1],wally[2],wally[3])
            self.Walls.add(new_wall)
            self.AllSprites.add(new_wall)

    def CreateBall(self):
        self.ball = Ball()
        self.ball.put(300,100)
        self.AllSprites.add(self.ball)


    def DetectWallCollide(self):
        for wall in self.Walls:
            if self.ball.rect.colliderect(wall.rect):
                self.ball.move_checker(wall)



def main():
    screen = pygame.display.set_mode((xsize, ysize), 0, 32)
    clock = pygame.time.Clock()

    game = Game()
    game.CreateWalls()
    game.CreateBall()

    game.start()



    # The main loop
    while True:
        # Test for exit
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                sys.exit()

        # Update the screen
        screen.fill((255, 255, 0))

        game.ball.Get_Move()
        game.DetectWallCollide()
        game.ball.update()
        game.AllSprites.draw(screen)
        pygame.display.update()
        clock.tick(50)


main()

Спасибо за любую помощь, Адам.

...