Im making a 2D platformer-ish shooter its really simple and not much effort put in it, it is my first game Im making in python and its for a school project and needs to be finnised really soon. Everything is working just fine but Im having problem with some collision detection with my shoots, I don't know how to make it. So would really appreciate any help I could get.

Feel free to tell me if anything is wrong or could be better and use this code for your own learnings.

And I know its a bit messy but I just want this to be finnished so havent done anything with classes or functions since Im not really that sure how to do them correct.

import time
import pygame
from pygame.locals import*

pygame.init()
screenWidth = 1018
screenHeight = 720
screen = pygame.display.set_mode((screenWidth,screenHeight))
facingLeft = False
clock = pygame.time.Clock()
fps = 50
shootLeft = False
shootRight = False

#Player img

Player_facing_screen = pygame.image.load('GoodGuyFramPng.png')
Player_left = pygame.image.load('GubbeVanster.png')
Player_right = pygame.image.load('GubbeSidan.png')
Player = Player_facing_screen
PlayerRect = Player.get_rect()


#Boss img
Boss_right = pygame.image.load('OndgubbeHoger.png')
Boss_left = pygame.image.load('OndgubbeVanster.png')
Bossen = Boss_left
Boss = Bossen.get_rect()

#commented out my first little try with shoots
#Shot
#shot_left = pygame.image.load('Shot.png')
#shot_right = pygame.image.load('Shot_right.png')
#shotIm = shot_right
#shot = shotIm.get_rect()


done = False
#Player variabels
x = 0
PlayerRect.y = screenHeight - 111
vx = 0
vy = 0
g = 2

onGround = False
jumping = False
moving = False


#Boss variabels
Boss.x = 500
Boss.y = screenHeight - 111
goingLeft = False
goingRight = True
bvx = 0
bvy = 0
radius = 10
BonGround = False
Bjumping = False

bullets = []
while not done:

    #Comands
    for event in pygame.event.get():
        #Shoot (commented out my first little  try)
        if event.type == KEYDOWN and event.key == K_LCTRL:
            bullets.append((PlayerRect.x,(PlayerRect.y + 40), (1,-1)[facingLeft] * 20))
            #shot.top = PlayerRect.y + 40
            #if facingLeft:
                #shot.left = PlayerRect.left
                #shootLeft = True
                #shotIm = shot_left
            #elif not facingLeft:
                #shot.right = PlayerRect.right
                #shootRight = True
                #shotIm = shot_right
        #Jump
        elif event.type == KEYDOWN and event.key == K_SPACE and onGround:
            vy = -20
            onGround = False
            jumping = True
        elif event.type == KEYUP and event.key == K_SPACE and not onGround and vy < 0:
            vy = 0
            jumping = False


    pressedKeys = pygame.key.get_pressed()
    #Walk/run
    if pressedKeys[K_LEFT]:
        PlayerRect.x -= (4 + pressedKeys[K_LSHIFT] * 8)
        facingLeft = True
        moving = True
        Player = Player_left
        if PlayerRect.left < 0:
            PlayerRect.x += (4 + pressedKeys[K_LSHIFT] * 8)
    elif pressedKeys[K_RIGHT]:
        PlayerRect.x += (4 + pressedKeys[K_LSHIFT] * 8)
        facingLeft = False
        moving = True
        Player = Player_right

        if PlayerRect.right > screenWidth:
            PlayerRect.right -= (4 + pressedKeys[K_LSHIFT] * 8)
    #finish
    if event.type == KEYUP and (event.key == K_RIGHT or event.key == K_LEFT):
        moving = False

    if event.type == pygame.QUIT:
            done = True

    elif pressedKeys[K_ESCAPE]:
        done = True

    if not moving:
        Player = Player_facing_screen

    #Physics
    newBullets = []
    for bullet in bullets:
        if(-(screenWidth+100) < bullet[0] - x < (screenWidth + 100)):
            newBullets.append((bullet[0] + bullet[2], bullet[1], bullet[2]))
    bullets = newBullets

    PlayerRect.y += vy
    PlayerRect.x += vx

    vy = min(vy + g, 20)

    onGround = False

    # Check collision
    # Floor
    if vy > 0 and PlayerRect.bottom >= screenHeight:
        if PlayerRect.bottom >= screenHeight and PlayerRect.bottom < screenHeight + vy:
            PlayerRect.bottom = screenHeight
            vy = 0
            onGround = True

    #--------Bossen------------------------------------------------------------

    #Walk
    if goingLeft:
        Bossen = Boss_left
        Boss.x -= 4
        if Boss.left <= screenWidth/2:
            goingLeft = False
            goingRight = True
    elif goingRight:
        Bossen = Boss_right
        Boss.x += 4
        if Boss.right >= screenWidth:
            goingRight = False
            goingLeft = True

    #Physics
    Boss.y += bvy
    Boss.x += bvx

    bvy = min(bvy + g, 20)

    BonGround = False

    # Check collision with floor
    if bvy > 0 and Boss.bottom >= screenHeight:
        if Boss.bottom >= screenHeight and Boss.bottom < screenHeight + bvy:
            Boss.bottom = screenHeight
            bvy = 0
            BonGround = True
    #-----------------------------------------------------------------------
    jumping = jumping and vy < 0
    Bjumping = Bjumping and bvy < 0

    #Draw

    #Background
    for i in range (1):     
        background = pygame.image.load('bakgrund.jpg')
        screen.blit(background, (0,0))

    #shoots (commented out my first little try)
    for bullet in bullets:
        pygame.draw.circle(screen,(255,255,255),(bullet[0],bullet[1]),3)
    #if shootLeft == True:
        #screen.blit(shotIm,shot)
        #shot.left -= 15
    #elif shootRight == True:
        #screen.blit(shotIm,shot)
        #shot.right += 15
    #if shot.left >= screenWidth:
        #shootRight = False
    #if shot.right <= 0:
        #shootLeft = False


    #Characters
    screen.blit(Bossen,Boss)
    screen.blit(Player,PlayerRect)

    pygame.display.flip()

    clock.tick(fps)

pygame.quit()   
Attachments OndgubbeVanster.png 11.91 KB Shot.png 3.33 KB bakgrund.jpg 69.69 KB GoodGuyFramPng.png 8.07 KB OndgubbeHoger.png 11.76 KB Shot_right.png 3.33 KB GubbeVanster.png 7.4 KB GubbeSidan.png 7.47 KB

You might want to look into using the PyGame Sprite class for the bullets, as it includes built-in colission detection. For that matter the regular Rect class has several collision detection methods which could be of use, though they aren't as fine-grained as the Sprite methods are.

I was planing on using the Rect class, but just couldent find how to use it with the bullets, can't sort out how to do with the bullets since I can't find what their rect is

You presumably would use get_rect(), the same as with the other sprites.

I'm in a bit of a quandary about how to help you, as I've more or less completely re-written the program for my own amusement, and I'm not sure if what I've done would apply to your code in any meaningful way. My code really does depned on using classes, and specifically, inheritance. My current version has a base class, GameObject, that itself is derived from pygame.DirtySprite (which in turn inherits from pygame.Sprite), and is the parent class of the Player, Enemy, and Bullet classes. I relies on the pygame.sprite.RenderUpdates collection class to draw the sprites, and uses the collision detection in the parent pygame.Sprite class for determining of the bullets hit their target. Unrolling all this to procedural code is not a viable option.

Edited 3 Years Ago by Schol-R-LEA

Yeah I been thinking about using the get_rect() but I don't know how to do it and since im really unsecure about using classes, is there another way to make shoots that can hit if you use my code? Let's say we take away the shoot code I have right now and we start over, any sugestions then?

Okey I fixed it, at line 183 where I draw the bullets I just added this

    for bullet in bullets:
        crect = pygame.Rect(bullet[0] - 3, bullet[1] - 3,3*2,3*2)
        shoot = pygame.draw.circle(screen,(255,255,255),(crect.center),3)
        if crect.colliderect(Boss):
            print('hit')

so now I can use the rect's hit box instead, however a new problem comes in hand. I don't know how to remove the shoot when they hit the boss. Is it possible to do it my way (the sloppy way) or do I have to make a function of some sort or even worse, a class?

The simplest solution here is just to remove said bullet from the list bullets.

    hit = None

    for index, bullet in enumerate(bullets):
        crect = pygame.Rect(bullet[0] - 3, bullet[1] - 3,3*2,3*2)
        shoot = pygame.draw.circle(screen,(255,255,255),(crect.center),3)
        if crect.colliderect(Boss):
            print('hit')
            hit = index

    if hit is not None:
        del bullets[index]

when I put this into my code and when the bullet hit the boss, then it makes an error saying:

del bullets[index]
IndexError: list assignment index out of range

Odd, I have that code running flawlessly on my system. What version of Python are you using?

Can you check the code again, to make sure you didn't drop anything? I am specifically thinking that you might not have included the first line (hit = None), which is important in that it resets hit after the bullet is removed from the list.

Also, try changing bullets[index] to bullets[hit]. It may be that index is going out of scope, though I would expect that it would give a different error were that the case.

Edited 3 Years Ago by Schol-R-LEA

Ah I accedently put the hit = None outside the main loop, so changed it and now it works, the only problem I find now is more like a bug and either ill just have to live with it but would rather not to. When it removes the shoot it removes all that is shot, not just the one that hit

and just solved the problem

hit = None
    for index, bullet in enumerate(bullets):
        crect = pygame.Rect(bullet[0] - 3, bullet[1] - 3,3*2,3*2)
        shoot = pygame.draw.circle(screen,(255,255,255),(crect.center),3)
        if crect.colliderect(Boss):
            print("hit")
            hit = index
            del bullets[index]

by placing it in the same for loop as the shots and not making a function for it seperatly works

You could try do delete the actual bullet item from the list:

for bullet in bullets:
    crect = pygame.Rect(bullet[0] - 3, bullet[1] - 3,3*2,3*2)
    shoot = pygame.draw.circle(screen,(255,255,255),(crect.center),3)
    if crect.colliderect(Boss): bullets.remove(bullet)
This question has already been answered. Start a new discussion instead.