Search code examples
pythonpygamegame-physics

pygame - Enemy flies off screen when collision with ground?


first time poster here.

Ill try to keep this as simple as possible. I am trying to make a game in pygame but it seems my collision detection is acting up. I have a player class that detects whether or not the player is colliding with the ground or any other objects in the environment list, and I have an enemy class that collides with anything in the same list. The enemies work out what direction they need to travel in in order to try and hit the player. There is gravity which is very likely to play a major part in the problem.

The problem is that when the 'flies' are placed in and fall to the ground, they immediately jump off screen, even though their X and Y values seem (according to logs of items on the screen) to not move at all?

As clarification, the two 'flies' are placed into a secondary list to allow for collision detection. Also, as a side note, the 'glitch' doesn't occur if there is no left and right collide detection... Thanks to anyone who can provide help :)

def collisions():

#Detection Working as intended
    for fly in Fly.List:
        fly_proj = pygame.sprite.spritecollide(fly, Projectile.List, True)
        if len(fly_proj) > 0:
            for hit in fly_proj:
                fly.health -= 100

        X = pygame.sprite.spritecollide(fly, current_level.object_list, False)
        if len(X) == 0: #Gravity here:
            if (fly.vspeed == 0):
                fly.vspeed = 1
                print("Gravity")
            else:
                fly.vspeed += 0.35
        if len(X) > 1: 
            for hit in X:

                if fly.vspeed > 0:            
                    fly.rect.bottom = hit.rect.top +1
                    fly.vspeed = 0
                elif fly.vspeed < 0:    
                    fly.rect.top = hit.rect.bottom -1
                elif fly.hspeed > 0:
                    fly.rect.right = hit.rect.left
                    fly.hspeed = 0
                elif fly.hspeed < 0:            
                    fly.rect.left = hit.rect.right
                    fly.hspeed = 0

        print(len(X),framecounter, fly.vspeed, fly.hspeed)
#Kill fly if health reaches 0            
        if fly.health <= 0:
            fly.destroy(Fly)

 #Detect where the player is
        if window_rect.contains(fly.rect):
            fly.playersnapshot = player.rect.x
        if fly.rect.x - player.rect.x >= -10:
            #print("LEFTING")
            fly.hspeed = -2
        if fly.rect.x - player.rect.x <= 10:
            fly.hspeed = 2
        fly.truefalse = True
        event = None

        fly.rect.y += fly.vspeed
        fly.rect.x += fly.hspeed

Solution

  • I think your if/else is incorrect.

    Probably when fly touch ground you set vspeed to zero and then if/else checks hspeed and it use ground left/right to change fly left/right.

    I know one method.

    1. move fly vertically
    2. check collision and use if/else with vspeed
    3. move fly horizontally
    4. check collision and use if/else with hspeed

    --

    EDIT:

     # move horizontally only
    
     fly.rect.x += fly.hspeed
    
     X = pygame.sprite.spritecollide( ... )
    
     for hit in X:
         if fly.hspeed > 0:
             fly.rect.right = hit.rect.left
         else:
             fly.rect.left = hit.rect.right
    
     # move vertically only
    
     fly.rect.y += fly.vspeed
    
     X = pygame.sprite.spritecollide( ... )
    
     for hit in X:
         if fly.vspeed > 0:
             fly.rect.bottom = hit.rect.top
         else:
             fly.rect.top = hit.rect.bottom
    
         # on_ground = True
    

    I found this method in source code of "Platform Jumper" on ProgramArcadeGames.com

    see page with: platform_jumper.py