2

I am currently creating my first Python game using pygame and have now come across something that baffles me so I would appreciate your help.

In the current statues of the game, all that there is on the screen is an image of a space ship over a white background (gameDisplay.fill(white)) that can only move up and down, located at the left side of the screen. When clicking on the space bar, the space ship shoots two laser beams (or basically creates two thin rects that move from left to right, changing x position but keeping the y position so that the movement would be only horizontal).

The problem that I have is that instead of moving from left to right, it seems as though the 'lasers' stretch out to the right, so that the left side of the rect stays near the space ship image on the left of the screen while the right side of the rect moves to toward the right side of the screen.

As shown in the image below:

Laser stretching out

After playing around with the problem, I found that if I use an image as a background instead of filling the background with the color white, everything works as it should.

In the image below you can see how it looks when I use a plain white picture as a background image (Using bg = pygame.image.load("img\white_background.png" and then blitting it inside the game loop before all other drawings):

Laser working fine

I currently have 4 files that make up the game:

1 main.py:

import time
import pygame
from first_game.game_loop import game_loop
from first_game.space_ship import space_ship

pygame.init()

display_width = 800
display_height = 600

colors = {
'black':(0, 0, 0),
'white':(255, 255, 255),
'red':(255, 0, 0)
}

gameDisplay = pygame.display.set_mode((display_width, display_height))

pygame.display.set_caption('First game')

clock = pygame.time.Clock()

gameDisplay.fill(colors['white'])

player = space_ship("img\\space_ship.png","player",103,103)

game_loop(gameDisplay,display_width,display_height,clock, player, bg)

2 game_loop.py:

import pygame
import first_game.methods

def game_loop(gameDisplay, display_width, display_height, clock, space_ship, bg):
    space_ship_x = (display_width * 0.05)
    space_ship_y = (display_height * 0.45)

    space_ship_y_change = 0

    both_laser_x = 0
    top_laser_y = 0
    bottom_laser_y = 0
    both_laser_width = 50
    both_laser_height = 5
    laser_speed = 15

    laser_adjustment_x = 70
    laser_adjustment_y = 18

    laser_fired = False

    while True:

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

            if event.type == pygame.KEYDOWN:

                if event.key == pygame.K_UP:
                    space_ship_y_change = -5

                if event.key == pygame.K_DOWN:
                    space_ship_y_change = 5

                if event.key == pygame.K_SPACE:
                    top_laser_y = space_ship_y + laser_adjustment_y
                    bottom_laser_y = space_ship_y + space_ship.height - laser_adjustment_y
                    both_laser_x = space_ship_x + space_ship.width - laser_adjustment_x
                    laser_fired = True

            if event.type == pygame.KEYUP:

                if event.key == pygame.K_UP or event.key == pygame.K_DOWN:
                    space_ship_y_change = 0

        if both_laser_x>display_width:
            laser_fired=False

        first_game.methods.space_ship(space_ship.img_location, space_ship_x, space_ship_y, gameDisplay)

        if laser_fired == True:
            first_game.methods.laser(gameDisplay,both_laser_x, top_laser_y,bottom_laser_y,both_laser_width,both_laser_height)
            both_laser_x += laser_speed

        if space_ship_y == -20:
            if space_ship_y_change<0:
                space_ship_y_change=0

        if space_ship_y+space_ship.height>=display_height+20:
            if space_ship_y_change>0:
                space_ship_y_change=0

        space_ship_y = space_ship_y + space_ship_y_change

        pygame.display.update()

        clock.tick(60)

3 methods.py:

def space_ship(space_ship_location, x, y, gameDisplay):
    space_ship_img = pygame.image.load(space_ship_location)
    gameDisplay.blit(space_ship_img, (x, y))

def laser(gameDisplay,x,y1,y2,w,h):
    pygame.draw.rect(gameDisplay, (255,0,0), [x, y1, w, h])
    pygame.draw.rect(gameDisplay, (255,0,0), [x, y2, w, h])

4 space_ship.py

class space_ship():
    def __init__(self,img_location, type, width, height):
        self.img_location = img_location
        self.type = type
        self.width = width
        self.height = height
MaxFury86
  • 21
  • 2
  • It sounds like you didn't fill the `gameDisplay` each frame. If you don't fill it or blit a background image onto it all the time, everything that you blit will persist. – skrx Sep 24 '17 at 07:55
  • Does it work correctly if you fill the display each frame or are there other problems? I see a few more things in your game that should be changed: Don't load the image from the hard disk in your while loop, do it once in the global scope of your module. Then just blit this image/surface instead of loading it again and again. Also, call `convert` or `convert_alpha` to improve the performance `space_ship_img = pygame.image.load(space_ship_location).convert_alpha()`. – skrx Sep 24 '17 at 08:23
  • You're also not using the `player` instance. The space_ship variables like `space_ship_x` and `space_ship_y_change` should be attributes of the `player` (defined in the `space_ship` class). And the `space_ship` function could be a method of the class (also better rename it to `draw` or `blit`). If you want a complete review, you can post your code on https://codereview.stackexchange.com/ but make sure that it's complete and works correctly first. – skrx Sep 24 '17 at 08:29
  • Let me know if you need more help. We could also open a chat room. – skrx Sep 24 '17 at 13:26
  • Yep, that fixed it. I only filled in the display once in the main file. Moving the gameDisplay.fill() method into the game loop fixed my issue. I also understand now better how the drawing on the display works in relation to the frames. Thank you for your quick help I also implemented your other advise and now work using class instant variables and methods instead of what I used until now. Seems like it will make it much simpler when the game will grow into thousand of code lines. – MaxFury86 Sep 24 '17 at 13:36
  • Great! If you want, I can post an answer to show you how I would refactor the game. But as I mentioned, it would be better to do that on https://codereview.stackexchange.com/ . BTW, do you already know how [`pygame.sprite.Sprite`s](http://programarcadegames.com/index.php?chapter=introduction_to_sprites&lang=en#section_13) and sprite groups work? – skrx Sep 24 '17 at 13:42
  • Not yet I just started out learning pygame a short while ago. I am in the midst of watching a youtube series on the subject. If you got any good tutorials that can help me improve I would be more then happy to review them. – MaxFury86 Sep 25 '17 at 05:49
  • I linked the tutorial in the previous comment. ;) – skrx Sep 25 '17 at 08:20

0 Answers0