jediob1
Posts: 8
Joined: Thu Dec 27, 2012 4:31 pm

python game shooting not working

Sat Dec 29, 2012 5:33 pm

Hello, i have modified a dodging game's code i found in a book (http://inventwithpython.com/chapter20.html) and i wanted to make the player shoot. Here is my code:

Code: Select all

import pygame, random, sys
from pygame.locals import *

WINDOWWIDTH = 900
WINDOWHEIGHT = 600
TEXTCOLOR = (255, 255, 255)
BACKGROUNDCOLOR = (200, 50, 50)
FPS = 40
BADDIEMINSIZE = 10
BADDIEMAXSIZE = 40
BADDIEMINSPEED = 1
BADDIEMAXSPEED = 8
ADDNEWBADDIERATE = 6
PLAYERMOVERATE = 5

def terminate():
    pygame.quit()
    sys.exit()

def waitForPlayerToPressKey():
    while True:
        for event in pygame.event.get():
            if event.type == QUIT:
                terminate()
            if event.type == KEYDOWN:
                if event.key == K_ESCAPE: # pressing escape quits
                    terminate()
                return

def playerHasHitBaddie(playerRect, baddies):
    for b in baddies:
        if playerRect.colliderect(b['rect']):
            return True
    return False

def drawText(text, font, surface, x, y):
    textobj = font.render(text, 1, TEXTCOLOR)
    textrect = textobj.get_rect()
    textrect.topleft = (x, y)
    surface.blit(textobj, textrect)

def playerWin():
    playerImage = pygame.image.load('playerHappy.png')
    windowSurface.blit(playerImage, playerRect)
    drawText('You Win!!!', font, windowSurface, (WINDOWWIDTH / 3), (WINDOWHEIGHT / 3))
    drawText('Press any key to restart.', font, windowSurface, (WINDOWWIDTH / 3) - 80, (WINDOWHEIGHT / 3) + 50)
    pygame.display.update()

def gameOver():
    # Stop the game and show the "Game Over" screen.
    playerImage = pygame.image.load('playerSad.png')
    windowSurface.blit(playerImage, playerRect)
    drawText('Game Over', font, windowSurface, (WINDOWWIDTH / 3), (WINDOWHEIGHT / 3))
    drawText('Press any key to restart.', font, windowSurface, (WINDOWWIDTH / 3) - 80, (WINDOWHEIGHT / 3) + 50)
    pygame.display.update()

# set up pygame, the window, and the mouse cursor
pygame.init()
mainClock = pygame.time.Clock()
windowSurface = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT))
pygame.display.set_caption('Cancer Attack')
pygame.mouse.set_visible(False)

# set up fonts
font = pygame.font.SysFont(None, 48)
fontSmall = pygame.font.SysFont(None, 26)


# set up images
playerImage = pygame.image.load('player.png')
playerRect = playerImage.get_rect()
baddieImage = pygame.image.load('baddie.png')
bulletImage = pygame.image.load('bullet.png')
bulletRect = playerImage.get_rect()

# show the "Start" screen
windowSurface.fill(BACKGROUNDCOLOR)
drawText('Cancer Attack', font, windowSurface, (WINDOWWIDTH / 3), (WINDOWHEIGHT / 3))
drawText('Use the mouse to move. Press any key to start.', fontSmall, windowSurface, (WINDOWWIDTH / 3) - 30, (WINDOWHEIGHT / 3) + 50)
pygame.display.update()
waitForPlayerToPressKey()


topScore = 0
while True:
    # set up the start of the game
    bullets = []
    baddies = []
    score = 0
    playerRect.topleft = (WINDOWWIDTH / 2, WINDOWHEIGHT - 50)
    moveLeft = moveRight = moveUp = moveDown = False
    reverseCheat = slowCheat = False
    baddieAddCounter = 0
    bulletAddCounter = 0

    while True: # the game loop runs while the game part is playing
        score += 1 # increase score

        for event in pygame.event.get():
            if event.type == QUIT:
                terminate()

            if event.type == KEYDOWN:
                if event.key == ord('z'):
                    reverseCheat = True
                if event.key == ord('x'):
                    slowCheat = True
                if event.key == K_LEFT or event.key == ord('a'):
                    moveRight = False
                    moveLeft = True
                if event.key == K_RIGHT or event.key == ord('d'):
                    moveLeft = False
                    moveRight = True
                if event.key == K_UP or event.key == ord('w'):
                    moveDown = False
                    moveUp = True
                if event.key == K_DOWN or event.key == ord('s'):
                    moveUp = False
                    moveDown = True

            if event.type == KEYUP:
                if event.key == ord('z'):
                    reverseCheat = False
                    score = 0
                if event.key == ord('x'):
                    slowCheat = False
                    score = 0
                if event.key == K_ESCAPE:
                        terminate()

                if event.key == K_LEFT or event.key == ord('a'):
                    moveLeft = False
                if event.key == K_RIGHT or event.key == ord('d'):
                    moveRight = False
                if event.key == K_UP or event.key == ord('w'):
                    moveUp = False
                if event.key == K_DOWN or event.key == ord('s'):
                    moveDown = False

            if event.type == MOUSEMOTION:
                # If the mouse moves, move the player where the cursor is.
                playerRect.move_ip(event.pos[0] - playerRect.centerx, event.pos[1] - playerRect.centery)

        # Add new baddies at the top of the screen, if needed.
        if not reverseCheat and not slowCheat:
            baddieAddCounter += 1
        if baddieAddCounter == ADDNEWBADDIERATE:
            baddieAddCounter = 0
            baddieSize = random.randint(BADDIEMINSIZE, BADDIEMAXSIZE)
            newBaddie = {'rect': pygame.Rect(random.randint(0, WINDOWWIDTH-baddieSize), 0 - baddieSize, baddieSize, baddieSize),
                        'speed': random.randint(BADDIEMINSPEED, BADDIEMAXSPEED),
                        'surface':pygame.transform.scale(baddieImage, (baddieSize, baddieSize)),
                        }

            baddies.append(newBaddie)
        if pygame.key.get_pressed()[K_SPACE]:
            bulletAddCounter += 1
            newBullet = {'rect': bulletRect,
                         'speed': 2,
                         'surface': pygame.transform.scale(bulletImage, (1, 1)),
                        }
            bullets.append(newBullet)

        # Move the mouse cursor to match the player.
        pygame.mouse.set_pos(playerRect.centerx, playerRect.centery)

        # Move the baddies down.
        for b in baddies:
            if not reverseCheat and not slowCheat:
                b['rect'].move_ip(0, b['speed'])
            elif reverseCheat:
                b['rect'].move_ip(0, -5)
            elif slowCheat:
                b['rect'].move_ip(0, 1)

         # Delete baddies that have fallen past the bottom.
        for b in baddies[:]:
            if b['rect'].top > WINDOWHEIGHT:
                baddies.remove(b)

        # Draw the game world on the window.
        windowSurface.fill(BACKGROUNDCOLOR)

        # Draw the score and top score.
        drawText('Score: %s' % (score), font, windowSurface, 10, 0)
        drawText('Highscore: %s' % (topScore), font, windowSurface, 10, 40)

        # Draw the player's rectangle
        windowSurface.blit(playerImage, playerRect)

        # Draw each baddie
        for b in baddies:
            windowSurface.blit(b['surface'], b['rect'])
        for t in bullets[:]:
            windowSurface.blit(t['surface'], t['rect'])
            t['rect'].centery += 1

        pygame.display.update()

        # Check if any of the baddies have hit the player.
        if playerHasHitBaddie(playerRect, baddies):
            if score > topScore:
                topScore = score # set new top score
            gameOver()
            waitForPlayerToPressKey()
            break

        if (score > 999):
            baddieAddCounter = 0
            playerWin()
            waitForPlayerToPressKey()
            break
        
        
        mainClock.tick(FPS)
I checked that the drawing code is being run by doing a print statement, however the bullets don't appear. I did change the bulletRect to the playerRect to see what would happen, and the player started moving down the screen so at least i know something is going on.
I use the python IDLE for development (not IDLE 3)
I am fluent in Objective C, however I am new to Python/Pygame and only in 6th grade.
I would appreciate any form of help very much. Thank you for your time and good will.

Heckles
Posts: 7
Joined: Sat Dec 22, 2012 11:37 pm

Re: python game shooting not working

Sat Dec 29, 2012 6:00 pm

I could be barking up completely the wrong tree here as I only had a quick look..

but

bulletImage = pygame.image.load('bullet.png')
bulletRect = playerImage.get_rect()

shouldn't that be:

bulletRect = bulletImage.get_rect() ???

not sure that's the cause of the issue or whether I've got something wrong as I'm a beginner myself with Python

jediob1
Posts: 8
Joined: Thu Dec 27, 2012 4:31 pm

Re: python game shooting not working

Sat Dec 29, 2012 6:12 pm

Heckles wrote:I could be barking up completely the wrong tree here as I only had a quick look..

but

bulletImage = pygame.image.load('bullet.png')
bulletRect = playerImage.get_rect()

shouldn't that be:

bulletRect = bulletImage.get_rect() ???

not sure that's the cause of the issue or whether I've got something wrong as I'm a beginner myself with Python
Thanks Heckles! Didn't catch that. That might have caused some problems. Didn't fix the main problem, but thanks anyways! :D

Gibble
Posts: 56
Joined: Wed May 09, 2012 9:52 am

Re: python game shooting not working

Sat Dec 29, 2012 6:50 pm

Hiya,

Not a Python man, so someone will probably correct me. I've had a play with your code...I think you are just referencing the same bullet each time in creation, so you won't get multiple bullets (I think!). So if you try something like...

Code: Select all

     if pygame.key.get_pressed()[K_SPACE]:
            bulletAddCounter += 1
            newBullet = {'rect': playerImage.get_rect(),
                         'speed': 2,
                         'surface': pygame.transform.scale(bulletImage, (10, 10)),
                        }
            newBullet['rect'].centerx = playerRect.centerx
            newBullet['rect'].centery = playerRect.centery
            bullets.append(newBullet)
So we use the latest image each time and position it the same as the player...and then...

Code: Select all

       for t in bullets:
            windowSurface.blit(t['surface'], t['rect'])
            t['rect'].centery -= 1
to make the bullet go upwards.

Its probably not the best way to do it, getting the playerRect each time, but I hope it make point you in the right direction.

jediob1
Posts: 8
Joined: Thu Dec 27, 2012 4:31 pm

Re: python game shooting not working

Sat Dec 29, 2012 7:44 pm

THANK YOU GIBBLE SO MUCH YOU DA MAN THAT FIXED IT!! :D Now one thing that would be nice is that the bullet spawns in the center of the player. I have done this before in my ping-pong iPhone app but again not sure how to do it in Python.

-rst-
Posts: 1316
Joined: Thu Nov 01, 2012 12:12 pm
Location: Dublin, Ireland

Re: python game shooting not working

Mon Dec 31, 2012 5:47 pm

Completely off the cuff... (I definitely have to find the time to install pygame... :oops: )

Assuming the player and bullet images are not the same size, you might want to combine Heckles' suggestion into Gibble's code and try changing:

Code: Select all

newBullet = {'rect': playerImage.get_rect()
to

Code: Select all

newBullet = {'rect': bulletImage.get_rect()
(the code seems to be centering the bullet image on the player center, but that wrong rect might push it off...)
http://raspberrycompote.blogspot.com/ - Low-level graphics and 'Coding Gold Dust'

jediob1
Posts: 8
Joined: Thu Dec 27, 2012 4:31 pm

Re: python game shooting not working

Mon Dec 31, 2012 6:14 pm

Uhh... You want me to change the same thing to the same thing? And I Already tried both Heckles and Gibble's suggestions... Thanks anyways!

Gibble
Posts: 56
Joined: Wed May 09, 2012 9:52 am

Re: python game shooting not working

Tue Jan 01, 2013 4:12 pm

I think its the 'scale' thats putting it off. There needs to be a handle on what the object actual is compared to how its displayed (and then what points are being used for stuff like collision detection etc). If you scale, where its its left/right/center etc ?

Losing track a bit of the changes, but try something like...

Code: Select all

bulletImage = pygame.image.load('bullet.png')
bulletImage = pygame.transform.scale(bulletImage,(10,10))
bulletRect = bulletImage.get_rect()
So we scale it earlier once, no need to keep doing it anyway.

Code: Select all

           newBullet = {'rect': bulletImage.get_rect(),
                         'speed': 2,
                         'surface': bulletImage,
                        }
            newBullet['rect'].centerx = playerRect.centerx
            newBullet['rect'].centery = playerRect.centery
            bullets.append(newBullet)
You may also want to do something like create all the bullets first when everything initializes (say 20 bullets), then just flag them live/dead later or something and change positions, to save recreating objects etc. Not sure if some of the code would have memory leaks keep creating new bullets or not. I may be misleading you there, so just have it in mind maybe.

Gibble
Posts: 56
Joined: Wed May 09, 2012 9:52 am

Re: python game shooting not working

Tue Jan 01, 2013 4:21 pm

Just testing it, you may want to change it also so that the bullet comes out of the top, rather than center...so...

Code: Select all

            newBullet = {'rect': bulletImage.get_rect(),
                         'speed': 2,
                         'surface': bulletImage,
                        }
            newBullet['rect'].midbottom = playerRect.midtop
I think I changed the bullet image file from the player image, but not sure it will make much diff. Having fun with this :).

Gibble
Posts: 56
Joined: Wed May 09, 2012 9:52 am

Re: python game shooting not working

Tue Jan 01, 2013 4:34 pm

Couldn't resist while I was at it ;)....If you wanted to then make the bullets kill the baddies...

Code: Select all

def bulletHits( bulletRect, baddies):
    for b in baddies:
        if bulletRect.colliderect(b['rect']):
            baddies.remove(b)
and in main loop...

Code: Select all

        if pygame.key.get_pressed()[K_SPACE]:
            bulletAddCounter += 1

            newBullet = {'rect': bulletImage.get_rect(),
                         'speed': 2,
                         'surface': bulletImage,
                        }
            newBullet['rect'].midbottom = playerRect.midtop
            bullets.append(newBullet)

        for b in bullets:
                bulletHits(b['rect'], baddies)
Makes it a bit too easy now though! Maybe not the wisest way to do it, but quite quick to code up for fun.

-rst-
Posts: 1316
Joined: Thu Nov 01, 2012 12:12 pm
Location: Dublin, Ireland

Re: python game shooting not working

Wed Jan 02, 2013 1:07 pm

-rst- wrote:

Code: Select all

newBullet = {'rect': playerImage.get_rect()
to

Code: Select all

newBullet = {'rect': bulletImage.get_rect()
jediob1 wrote:Uhh... You want me to change the same thing to the same thing? And I Already tried both Heckles and Gibble's suggestions... Thanks anyways!
Hmm, how is 'playerImage.get_rect()' same as 'bulletImage.get_rect()'? (unless the images are and always will be the same size) ;)

And the problem with the earlier suggestions were, that the 'bulletRect' variable (which Heckles' fixed the initialisation for) was not used in the (Gibble's) code...
http://raspberrycompote.blogspot.com/ - Low-level graphics and 'Coding Gold Dust'

Return to “Python”