samedi 18 juin 2016

Pygame Collision with variable speed

it would be really amazing if you could help us with this problem . We're currently working on a game project at school and we want to create a Bomberman-like labyrinth game.

The problem is the following: the position and the speed of the bombs depend on the mouse which is tracked using float values but is getting way too high if you click far away so it can skip collision detection because it just goes too fast at times. Now there are some other weird errors when you line up the bomb with the bottom of a block and some other collisions.

Is the method colliderect the error ? Do we need to check for each site or are there any better solutions to this problem. We also thought about just using 4 directions but even that didn't work out properly.

I really hope somebody out there can help.

class Block( pygame.sprite.Sprite):

    def __init__(self,color = SCHWARZ, width = 40, height = 40, movable = 0):

        super().__init__()

        self.width = width 
        self.height = height

        self.color = color

        self.movable = movable

        self.image = pygame.Surface((width,height))
        self.image.fill(color)

        self.properties()

    def properties(self):

        self.rect = self.image.get_rect()

        self.origin_x = self.rect.centerx
        self.origin_y = self.rect.centery

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

    def render(self,window):
        pygame.draw.rect(window,self.color,(self.rect.x,self.rect.y,self.width,self.height))

class Bomb(Block):

    def __init__(self,player, target_x, target_y,countdown,zeit,color = BLAU):

        super().__init__(color, width = 20, height = 20)
        self.target_x = round(target_x)
        self.target_y = round(target_y)

        self.countdown = countdown
        self.zeit = zeit

        self.player_x = player.rect.left + player.width/2
        self.player_y = player.rect.top + player.height/2

        self.set_pos(player.rect.center[0]-self.width/2,player.rect.center[1]-self.height/2)
        self.truepos = list(self.rect.center)

        self.setspeed(3)

    def setspeed(self,factor):

        self.speed_x = (self.target_x - self.player_x)/100
        self.speed_y = (self.target_y - self.player_y)/100




        """self.direction = [0,0]

        if self.target_x - self.player_x < 0:
            self.direction[0] = -1
        elif self.target_x - self.player_x > 0:
            self.direction[0] = 1
        if self.target_y - self.player_y > 0:
            self.direction[1] = 1
        elif self.target_y - self.player_y < 0:
            self.direction[1] = -1

        self.speed_x = self.direction[0]* factor
        self.speed_y = self.direction[1]* factor

        print(self.speed_x)
        print(self.speed_y)"""

    def move(self):

        if self.speed_x != 0:
            self.collision()
        if self.speed_y != 0:
            self.collision()

    def update(self):

        self.move()

        if self.countdown > 0:
            self.countdown -= self.zeit

        elif self.countdown <= 0:
            bomblist_list.remove(self)

    def collision(self):
        for block in block_list:
            if block.movable != 1:
                if self.rect.colliderect(block.rect):
                    self.distance = [abs(block.rect.centerx - (self.truepos[0] + self.speed_x)), abs(block.rect.centery - (self.truepos[1] + self.speed_y))]
                    if self.distance[0] > self.distance[1]:
                        if self.speed_x < 0:
                            self.rect.left = block.rect.right - self.speed_x
                        elif self.speed_x > 0:
                            self.rect.right = block.rect.left -self.speed_x
                        self.speed_x = -self.speed_x
                    elif self.distance[0] < self.distance[1]:
                        if self.speed_y < 0:
                            self.rect.top = block.rect.bottom - self.speed_y
                        elif self.speed_y > 0:
                            self.rect.bottom = block.rect.top - self.speed_y
                        self.speed_y = -self.speed_y



        self.truepos[0] += self.speed_x
        self.truepos[1] += self.speed_y
        self.rect.center = self.truepos

# -------- Main Program Loop -----------
while not done:
    clock.tick(fps)
    millisekunde = float(clock.tick(fps))
    zeit = millisekunde /500
    vergangen += zeit

    # --- Main event loop
    for event in pygame.event.get(): # User macht irgendwas

        if event.type == pygame.QUIT: # Wenn der User Quit klickt
            done = True # Verlässt die Schleife

        elif event.type == pygame.KEYDOWN:
            pass



            #if event.key == pygame.K_UP:
                #if e


        elif event.type == pygame.MOUSEBUTTONDOWN:
            if event.button == 1:
                mx,my = pygame.mouse.get_pos()
                bomb = Bomb(player,mx,my,3,zeit)
                bomblist_list.append(bomb)
                planted = True

    keys = pygame.key.get_pressed()

    if keys[pygame.K_RIGHT]:
            player.move(speedx,0)
    if keys[pygame.K_LEFT]:
            player.move(-speedx,0)
    if keys[pygame.K_DOWN]:
            player.move(0,speedy)
    if keys[pygame.K_UP]:
            player.move(0,-speedy)

    if planted:
        for bomb in bomblist_list:
            bomb.update()

    screen.fill(SCHWARZ)

    for block in block_list:
        block.render(screen)

    if planted:
        for bomb in bomblist_list:
            bomb.render(screen)

    pygame.draw.rect(screen,red,player.rect)

    pygame.display.update()

pygame.quit()

Aucun commentaire:

Enregistrer un commentaire