1

I am making a simply game with pygame, and the objective is to dodge the incoming enemies. I want a tie fighter image to come down randomly, and the xwing has to dodge them or you will die. How do I implement random tie fighters into my script? In my code I get an error that says x is not defined.

import pygame
import time
import random
pygame.init()

display_width = 1280
display_height= 800


pygame.display.set_mode((display_width, display_height), pygame.FULLSCREEN)

gameDisplay= pygame.display.set_mode((display_width,display_height))
pygame.display.set_caption('X-Wing Game')
clock= pygame.time.Clock()

black= (0,0,0)
white= (255,255,255)
red = (255,0,0)
blue_violet = (138,43,226)


xwing_width = 65
xwing_height = 130

tie_width = 80
tie_height =64

#images
xwingImg = pygame.image.load('X-Wing.bmp')
tieImg= pygame.image.load('tiefighter.png')

def things(thingx, thingy, thingw, thingh, color):
    pygame.draw.rect(gameDisplay, color, [thingx, thingy, thingw, thingh])
    gameDisplay.blit(tieImg,(x,y))

def tieImg (x,y):
    pygame.image.load('tieImg')


def xwing (x,y):
    gameDisplay.blit (xwingImg,(x,y))

def text_objects(text, font):
    textSurface = font.render(text, True, red)
    return textSurface, textSurface.get_rect()

def crash ():
    message_display ('Ouch, You Crashed!')

def message_display(text):
    largeText = pygame.font.Font('freesansbold.ttf',25)
    TextSurf, TextRect = text_objects(text, largeText)
    TextRect.center = ((display_width/2), (display_height/2))
    gameDisplay.blit(TextSurf, TextRect)

    pygame.display.update()

    time.sleep(1.3)

    game_loop()


def game_loop():

    x = (display_width * 0.45)
    y = (display_height * .75)

    x_change = 0
    y_change = 0

    thing_startx = random.randrange(0, display_width)
    thing_starty = -600
    thing_speed = 7
    thing_width = 81
    thing_height =65


    gameEXIT = False

    while not gameEXIT:

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

            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_LEFT:
                    x_change = -5
                if event.key == pygame.K_UP:
                     y_change= -5
                if event.key == pygame.K_DOWN:
                    y_change =5
                elif event.key == pygame.K_RIGHT:
                    x_change = 5


            if event.type == pygame.KEYUP:
                if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
                    x_change=0



        x += x_change
        y += y_change

        gameDisplay.fill(black)

        things(thing_startx, thing_starty, thing_width, thing_height, black )
        thing_starty += thing_speed
        xwing (x,y)

        if x > display_width - xwing_width or x < 0:
             x_change=0
        if y>display_height-xwing_height or y<0:
            y_change=0


        pygame.display.update()
        clock.tick(60)


game_loop()
pygame.quit()
quit()
joe
  • 43
  • 1
  • 6
  • In your `things` function, `x` will indeed be undefined, as will `y`. Did you mean to type `gameDisplay.blit(tieImg,(thingx,thingy))` instead ? – nb1987 Apr 29 '17 at 03:43
  • Do you already know how to use classes, pygame sprites and sprite groups? If not, you can use a list and append [`pygame.Rect`](http://www.pygame.org/docs/ref/rect.html)s to it which store the position and size of the enemies, then just blit the enemy image at the rect positions. Also use a rect for the player and for the collision detection loop over the enemy list and check `if player_rect.colliderect(enemy_rect):`. I think I have to post an example. – skrx Apr 29 '17 at 06:22

1 Answers1

1

You can use a list and append pygame.Rects to it which store the position and size of the enemies, then just blit the enemy image at the rect positions. For the collision detection, loop over the enemy list and use the Rect.colliderect method to check if the player rect collides with an enemy rect.

import sys
import random
import pygame as pg


pg.init()
screen = pg.display.set_mode((640, 480))

XWING_IMG = pg.Surface((25, 38))
XWING_IMG.fill((90, 120, 150))
TIE_IMG = pg.Surface((40, 24))
TIE_IMG.fill((190, 60, 50))
BG_COLOR = pg.Color('gray15')


def main():
    clock = pg.time.Clock()
    # Surfaces/images have a `get_rect` method which 
    # returns a rect with the dimensions of the image.
    player_rect = XWING_IMG.get_rect()
    player_rect.center = (300, 400)
    change_x = 0
    change_y = 0
    enemies = []
    spawn_counter = 30

    done = False

    while not done:
        for event in pg.event.get():
            if event.type == pg.QUIT:
                done = True
            if event.type == pg.KEYDOWN:
                if event.key == pg.K_d:
                    change_x = 5
                if event.key == pg.K_a:
                    change_x = -5
            if event.type == pg.KEYUP:
                if event.key == pg.K_d and change_x > 0:
                    change_x = 0
                if event.key == pg.K_a and change_x < 0:
                    change_x = 0

        # Spawn enemies if counter <= 0 then reset it.
        spawn_counter -= 1
        if spawn_counter <= 0:
            # Append an enemy rect. You can pass the position directly as an argument.
            enemies.append(TIE_IMG.get_rect(topleft=(random.randrange(600), 0)))
            spawn_counter = 30

        # Update player_rect and enemies.
        player_rect.x += change_x
        player_rect.y += change_y
        for enemy_rect in enemies:
            enemy_rect.y += 5
            # Collision detection with pygame.Rect.colliderect.
            if player_rect.colliderect(enemy_rect):
                print('Collision!')

        # Draw everything.
        screen.fill(BG_COLOR)
        for enemy_rect in enemies:
            screen.blit(TIE_IMG, enemy_rect)
        screen.blit(XWING_IMG, player_rect)

        pg.display.flip()
        clock.tick(30)


if __name__ == '__main__':
    main()
    pg.quit()
    sys.exit()

Counting the frames in this way with the spawn_counter variable means that the game will be frame rate dependent (the objects spawn slower or faster depending on the frame rate). To implement a frame rate independent spawn timer you can use the time returned by clock.tick or pygame.time.get_ticks as explained here.

skrx
  • 19,980
  • 5
  • 34
  • 48
  • I also recommend to take a look at classes and `pygame.sprite.Sprite`s (chapter 12 and 13 of [Program Arcade Games](http://programarcadegames.com/index.php?chapter=introduction_to_classes&lang=de#section_12)). – skrx Apr 30 '17 at 22:33