4
\$\begingroup\$

I am trying to make bullets bounce of walls, but I can't figure out how to correctly do the collision detection. What I am currently doing is iterating through all the solid blocks and if the bullet hits the bottom, top or sides, its vector is adjusted accordingly. However, sometimes when I shoot, the bullet doesn't bounce, I think it's when I shoot at a border between two blocks.

Here is the update method for my Bullet class:

def update(self, dt):
    if self.can_bounce:
        #if the bullet hasnt bounced find its vector using the mousclick pos and player pos
        speed = -10.
        range = 200
        distance = [self.mouse_x - self.player[0], self.mouse_y - self.player[1]]
        norm = math.sqrt(distance[0] ** 2 + distance[1] ** 2)
        direction = [distance[0] / norm, distance[1 ] / norm]
        bullet_vector = [direction[0] * speed, direction[1] * speed]

        self.dx = bullet_vector[0]
        self.dy = bullet_vector[1]

    #check each block for collision
    for block in self.game.solid_blocks:
        last = self.rect.copy()
        if self.rect.colliderect(block):
            topcheck = self.rect.top < block.rect.bottom and self.rect.top > block.rect.top
            bottomcheck = self.rect.bottom > block.rect.top and self.rect.bottom < block.rect.bottom
            rightcheck = self.rect.right > block.rect.left and self.rect.right < block.rect.right 
            leftcheck = self.rect.left < block.rect.right and self.rect.left > block.rect.left
            each test tests if it hit the top bottom left or right side of the block its colliding with 
            if self.can_bounce:                      
                if topcheck: 
                    self.rect = last
                    self.dy  *= -1 
                    self.can_bounce = False
                    print "top"

                if bottomcheck:
                    self.rect = last
                    self.dy  *= -1 #Bottom check
                    self.can_bounce = False
                    print "bottom"

                if rightcheck:
                    self.rect = last 
                    self.dx  *= -1 #right check
                    self.can_bounce = False
                    print "right"

                if leftcheck:
                    self.rect = last
                    self.dx  *= -1 #left check
                    self.can_bounce = False
                    print "left"

            else:
                # if it has already bounced and colliding again kill it
                self.kill()

    for enemy in self.game.enemies_list:
        if self.rect.colliderect(enemy):
            self.kill()
    #update position
    self.rect.x -= self.dx
    self.rect.y -= self.dy

This definitely isn't the best way to do it but I can't think of another way. If anyone has done this or can help that would be awesome!

\$\endgroup\$
4
  • \$\begingroup\$ Hey man! Anyhow, an idea may be to add blocks (with 100% alpha) between the other blocks, so it always bounces off of something? If your problem is that it is hitting the intersection of the blocks, that should make sure that collision happens. \$\endgroup\$
    – Pip
    Commented Dec 12, 2013 at 21:34
  • \$\begingroup\$ its detecting collision between blocks but its the wrong collision, i need a better way to test it \$\endgroup\$
    – Serial
    Commented Dec 13, 2013 at 1:57
  • \$\begingroup\$ I see. I don't think there is a better way to do this in Pygame, so maybe you could find an external library? nullege.com/codes/search?cq=collision \$\endgroup\$
    – Pip
    Commented Dec 13, 2013 at 3:21
  • \$\begingroup\$ @TheProgramm3r No, I know there is ive seen it done but im having trouble implementing it properly \$\endgroup\$
    – Serial
    Commented Dec 13, 2013 at 3:34

2 Answers 2

1
\$\begingroup\$

If you try and do the X and Y collision at the same time, you will find it troublesome to implement any kind of bouncing; it's more effort to calculate which way the object will need to bounce.

To remedy this, we can split up the X and Y collision calculation, and the velocity reversing calculation. some pseudocode:

move(int x, int y){
    pos.x += x;
    checkHorizontalCollision();
    pos.y += y;
    checkVerticalCollision();
}

the checkXCollision methods simply reverse the velocity and maybe remove some depending on your requirements.

\$\endgroup\$
3
  • \$\begingroup\$ Your answer was short enough to be flagged for a low-quality check. It is rather succinct. If you think it is the correct solution to the OP's problem, you might elaborate about why their attempted method failed. \$\endgroup\$ Commented Aug 12, 2014 at 4:26
  • 4
    \$\begingroup\$ I think you have a valid solution, but please elaborate so that it can be an excellent answer. \$\endgroup\$ Commented Aug 12, 2014 at 8:10
  • \$\begingroup\$ That and a little code goes a long way. \$\endgroup\$ Commented Aug 12, 2014 at 8:18
0
\$\begingroup\$

Pygame has a built in and very good collision detection function for sprites. If you have one sprite, and want to tell if it is colliding with members of another group of sprites, you can do this:

collisions = pygame.sprite.spritecollide(<sprite>,<group>,False)     #argument one is the sprite, argument two is the group to test collisions with the sprite for, and the final argument should almost always be False, because when it is True, colliding sprites will automatically get deleted.
for item in collisions:                                              #Spritecollide returns a list of colliding sprites. This will iterate through them.
    if item != <sprite>:                                             #spritecollide will also always return that the sprite is colliding with itself. this will filter that out, because you don't want this information.
        print "collision detected, insert code to run on collision here or return True from a function"

This should work fine.

\$\endgroup\$
1
  • 3
    \$\begingroup\$ Yes, if you read my code, or my question even then, you would know that im already using colliderect, and my question isnt how to use simple collision it is how to tell if the sprite is touching a floor (horizontal), or a wall(vertical) \$\endgroup\$
    – Serial
    Commented Dec 16, 2013 at 0:24

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .