0
\$\begingroup\$

when i was making a pygame in python for the first time i kinda have a problem where sometimes the player and the object would touch and the game would not close as intended i dint seem to find the solution to this problem mostly it would work but sometimes the collision would occur but the player would clip right through i have tried numerous collision techniques which i have heard but none seem to work as well the problem would still exit

here is my code

import math
import pygame
import random
RED=(255,0,0)
BLUE=(0,0,255)
bg_COLOR=(0,0,0)
WHITE=(255,255,255)

pygame.init()
font = pygame.font.SysFont('monospace', 15)
wid=720
hight=600

player_size = [40,40]
flag=0
player_pos = [int(wid/2),hight-2*player_size[1]]

enemy_size = 50
enemy_pos = [random.randint(0,wid-enemy_size),0]

en_list=[enemy_pos]
speed=10
en_num=4
block_evade=0

screen = pygame.display.set_mode((wid,hight))
pygame.display.set_caption('x wing shooter alpha v1')
game_over = False

clock = pygame.time.Clock()
def score_count(block_evade,block_attack=0):
    text = font.render('score:', 1,WHITE)
    text2 = font.render(str(block_evade + block_attack),1,WHITE) 
    screen.blit(text,(0,0))
    screen.blit(text2,(50,0))


def game_quit():
     pygame.display.quit()
     pygame.quit()


def spawn_en(en_list):
    delay = random.random()
    if len(en_list)<en_num and delay < 0.2:#
        x_pos=random.randint(0,wid-enemy_size)
        y_pos=0
        en_list.append([x_pos ,y_pos])

def create_en(en_list):
    for enemy_pos in en_list:
        pygame.draw.rect(screen,BLUE,(enemy_pos[0],enemy_pos[1],enemy_size,enemy_size))

def detect_col(player_pos, enemy_pos):
    p_x=player_pos[0]
    p_y=player_pos[1]

    e_x=enemy_pos[0]
    e_y=enemy_pos[1]
    x1=int(e_x+enemy_size/2)
    x2=int(p_x+player_size[0]/2)
    y1=int(e_y+enemy_size/2)
    y2=int(p_y+player_size[1]/2)
    distance =int(math.sqrt((math.pow(x2-x1,2))+(math.pow(y2-y1,2))))

    if(e_x + enemy_size >= p_x > e_x):
        if(e_y + enemy_size >= p_y > e_y):
            return True
    elif(p_x + player_size[0] >= e_x > p_x):
        if(p_y + player_size[1] >= e_y > p_y):
            return True
    elif(distance <= int(enemy_size/2)):
        return True




def fall_en(en_list):
    block_evade=0
    for idx, enemy_pos in enumerate(en_list):
        if enemy_pos[1] >= 0 and enemy_pos[1]<=hight:
            enemy_pos[1]+=speed
        else:
            en_list.pop(idx)
            block_evade+=1
    return block_evade

def col_check(en_list, player_pos):
    for enemy_pos in en_list:
        if detect_col(player_pos,enemy_pos):
            return True
        else:
            return False


while not game_over:

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
           game_quit()
           flag=1
           break 
    if event.type == pygame.KEYDOWN:
        x = player_pos[0]
        y = player_pos[1]
        if event.key == pygame.K_LEFT and player_pos[0] >= 0:
            x-=10
        elif event.key == pygame.K_RIGHT and player_pos[0] <= wid-player_size[0]:
            x+=10
        elif event.key == pygame.K_DOWN  and player_pos[1] <= hight-player_size[1]:
            y+=10
        elif event.key == pygame.K_UP  and player_pos[1] >= 0:
            y-=10
        player_pos = [x,y]


    if flag != 1:    
        screen.fill(bg_COLOR)    






    spawn_en(en_list)
    block_evade+=fall_en(en_list)
    if col_check(en_list, player_pos):
        game_over=True
    create_en(en_list)
    score_count(block_evade,0)
    pygame.draw.rect(screen,RED,(player_pos[0],player_pos[1],player_size[0],player_size[1]))

    clock.tick(20)

    pygame.display.update()

else:
    game_quit()
\$\endgroup\$
0
\$\begingroup\$

You may want to create a Player and Enemy class that hold their position and size as member variables. These objects could have a rect() function that returns a Rect based on the position and size of that object. To detect overlap between two of these Rects, you could then call playerRect.colliderect(enemy.rect()), which returns True if they do.
You could also use player.rect().collidelist(enemyRects) instead. This returns the index of the first colliding rectangle in the list, and -1 when no collision is detected.

| improve this answer | |
\$\endgroup\$
  • 1
    \$\begingroup\$ Why not rect.collide(rect)? Also, it would be helpful to describe what causes the issue described in the question. \$\endgroup\$ – Vaillancourt May 6 at 15:02
  • \$\begingroup\$ Thanks, I had not encountered that function. I think part of the issue is likely to result from the current collision detection implementation. This answer would completely change that and make it easier to debug, if the issue persists. \$\endgroup\$ – 魔大农 May 6 at 15:10
  • \$\begingroup\$ Sure it will help with a "more proper apporach", but the question asked is "Why does collision only work sometimes when there are multiple objects in the game?", which would help them figure out what went wrong! \$\endgroup\$ – Vaillancourt May 6 at 15:19
  • \$\begingroup\$ Agreed, but serendipity is key. ツ \$\endgroup\$ – 魔大农 May 6 at 15:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.