Python Forum
[PyGame] pygame.draw.rect function stretches across the screen instead of moving
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
[PyGame] pygame.draw.rect function stretches across the screen instead of moving
#1
The title basically says it all, I'm currently getting started with pygame and whenever I use the draw rect function and try to move the rectangle it stretches instead. I put comments in my code wherever code related to the rectangles is.
[python]
import pygame
import time
import random

pygame.init()

car_width = 99
    
display_width = 800
display_height = 600

black = (0,0,0)
white = (255,255,255)
red = (255,0,0)
blue = (0,0,255)
green = (0,255,0)
dark_green = (0,150,0)
    
    
gameDisplay = pygame.display.set_mode((display_width,display_height))
pygame.display.set_caption("A bit racey")
clock = pygame.time.Clock()

carImg = pygame.image.load("racecar.png")
carImg = pygame.transform.scale(carImg, (100, 90))
#--------------------------------------------------------------------  
def things(thingx, thingy, thingw, thingh, color):
    pygame.draw.rect(gameDisplay, color, [thingx, thingy, thingw, thingy])
#--------------------------------------------------------------------
def text_objects(text, font, color):
    textSurface = font.render(text, True, color)
    return textSurface, textSurface.get_rect()
 
def crash():
    message_display("You Crashed!")

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

    pygame.display.update()

    time.sleep(2)

    game_loop()

def car(x,y):

    gameDisplay.blit(carImg,(x,y))
    return

def game_loop():






    x = (display_width * 0.45)
    y = (display_height * 0.8)
        
    x_change = 0
#--------------------------------------------------------------------  
    thing_startx = random.randrange(0, display_width)
    thing_starty = -600
    thing_speed = 7
    thing_width = 100
    thing_height = 100
#--------------------------------------------------------------------  
    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
                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


            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_a:
                    x_change = -5
                elif event.key == pygame.K_d:
                    x_change = 5
            if event.type == pygame.KEYUP:
                if event.key == pygame.K_a or event.key == pygame.K_d:
                    x_change = 0
                    
        x += x_change

                    

        gameDisplay.fill(white)

        
#--------------------------------------------------------------------  
        things(thing_startx, thing_starty, thing_width, thing_height, dark_green)
        thing_starty += thing_speed
#--------------------------------------------------------------------          
        car(x,y)

        crashed = False

        if x > display_width- car_width or x < 0:
            crash()
#--------------------------------------------------------------------  
        if thing_starty > display_height:
            thing_starty = 0 - thing_height
            thing_startx = random.randrange(0, display_width)
#--------------------------------------------------------------------  
        pygame.display.update()
        clock.tick(60)
    quit()
    pygame.quit()
    return

game_loop()


    
    
Reply
#2
A lot of times when something doesn't work, I like to use the print function to see what the heck is going on. When I print the thing_h, I see, it stays at 100. The i can trace it back the the things function. May want to take a look at it. Anyways here you go, this code is kinda sloppy, Sentdex makes good tutorials, except his one in pygame is not all that great.
import pygame
import time
import random
 
pygame.init()
 
car_width = 99
     
display_width = 800
display_height = 600
 
black = (0,0,0)
white = (255,255,255)
red = (255,0,0)
blue = (0,0,255)
green = (0,255,0)
dark_green = (0,150,0)
     
     
gameDisplay = pygame.display.set_mode((display_width,display_height))
pygame.display.set_caption("A bit racey")
clock = pygame.time.Clock()
 
carImg = pygame.image.load("racecar.png")
carImg = pygame.transform.scale(carImg, (100, 90))
#--------------------------------------------------------------------  
def things(thingx, thingy, thingw, thingh, color):
    pygame.draw.rect(gameDisplay, color, [thingx, thingy, thingw, thingh])
#--------------------------------------------------------------------
def text_objects(text, font, color):
    textSurface = font.render(text, True, color)
    return textSurface, textSurface.get_rect()
  
def crash():
    message_display("You Crashed!")
 
def message_display(text):
    largeText = pygame.font.Font("freesansbold.ttf" ,115)
    TextSurf, TextRect = text_objects(text, largeText, red)
    TextRect.center = ((display_width/2), (display_height/2))
    gameDisplay.blit(TextSurf, TextRect)
 
    pygame.display.update()
 
    time.sleep(2)
 
    game_loop()
 
def car(x,y):
 
    gameDisplay.blit(carImg,(x,y))
    return
 
def game_loop():
 
 
 
 
 
 
    x = (display_width * 0.45)
    y = (display_height * 0.8)
         
    x_change = 0
#--------------------------------------------------------------------
    thing_width = 100
    thing_height = 100
    thing_startx = random.randrange(0, display_width - thing_width)
    thing_starty = -600
    thing_speed = 7
#--------------------------------------------------------------------  
    gameExit = False
    while not gameExit:
        print(thing_height)
        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
                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
 
                     
 
        gameDisplay.fill(white)
 
         
#--------------------------------------------------------------------  
        things(thing_startx, thing_starty, thing_width, thing_height, dark_green)
        thing_starty += thing_speed
#--------------------------------------------------------------------          
        car(x,y)
 
        crashed = False
 
        if x > display_width- car_width or x < 0:
            crash()
#--------------------------------------------------------------------  
        if thing_starty > display_height:
            thing_starty = 0 - thing_height
            thing_startx = random.randrange(0, display_width - thing_width)
#--------------------------------------------------------------------  
        pygame.display.update()
        clock.tick(60)
 
game_loop()
pygame.quit()
quit()

I'd suggest following the tutorials this forum has. They teach pygame better then the tutorial you are watching.
Reply
#3
I would also highly suggest to be cautious when using sentdex tutorials for pygame. I even wrote a comparison of code for this exact tutorial on how bad it was.
https://python-forum.io/Thread-PyGame-wa...-tutorials
#8 is the worst of all. At the bottom compares this tutorial to using classes and a single main game loop.

I think you might of typed it out wrong as even the example i use does not do what you are having issues with. To be honest looking at this style of coding gives me a headache. I would recommend to look at the link provided and use 1) classes and 2) only EVER one game loop (AKA only one line pygame.display.update() should ever exxist in your entire program).

import pygame
import time
import random
  
pygame.init()
display_width = 800
display_height = 600
  
black = (0,0,0)
white = (255,255,255)
red = (255,0,0)
  
gameDisplay = pygame.display.set_mode((display_width,display_height))
gameDisplay_rect = gameDisplay.get_rect()
pygame.display.set_caption('A bit Racey')
clock = pygame.time.Clock()
 
class Car:
    def __init__(self, screen_rect):
        self.screen_rect = screen_rect
        width = 100
        height = 100
        self.set_start()
        self.starty = -100
        self.speed = 7
        self.image = pygame.Surface((width,height)).convert()
        self.image.fill((0,0,0))
        self.set_rect()
         
    def set_rect(self):
        self.rect = self.image.get_rect(center=(self.startx,self.starty))
         
    def set_start(self):
        self.startx = random.randrange(0, self.screen_rect.width)
         
    def reset(self):
        self.set_start()
        self.set_rect()
         
    def update(self):
        self.rect.y += self.speed
        if self.rect.top > self.screen_rect.bottom:
            self.reset()
        #if thing_starty > display_height:
        #    thing_starty = 0 - thing_height
        #    thing_startx = random.randrange(0,display_width)
         
    def draw(self,surface):
        surface.blit(self.image, self.rect)
 
class Player:
    def __init__(self, screen_rect):
        self.screen_rect = screen_rect
        car_width = 55
        #carImg = pygame.image.load('Car.png') #-->no image to use
        self.image = pygame.Surface((car_width,50)).convert()
        self.image.fill((255,0,0))
        self.rect = self.image.get_rect(center=(screen_rect.centerx, screen_rect.centery+200))
        self.speed = 5
             
    def check_collision(self, car_rect):
        if self.rect.colliderect(car_rect):
            return True #switch pause state
         
    def update(self, keys):
        if keys[pygame.K_a]:
            self.rect.x -= self.speed
        if keys[pygame.K_d]:
            self.rect.x += self.speed
        self.rect.clamp_ip(self.screen_rect) #keep player in screen
         
    def draw(self, surface):
        surface.blit(self.image, self.rect)
        #def car(x,y):
        #    gameDisplay.blit(carImg, (x,y))
 
#-->no need for this, Car.image is the rectange, and Car.draw draws it to the screen
#def thing(thingx, thingy, thingw, thingh, color):
#    pygame.draw.rect(gameDisplay, color, [thingx, thingy, thingw, thingh])
      
#-->having this split into two functions is redundant, moved to message_display()
#def text_objects(text, font):
#    textSurface = font.render(text, True, black)
#    return textSurface, textSurface.get_rect()
 
  
def message_display(text, screen_rect):
    largeText = pygame.font.Font('freesansbold.ttf',115)
    textSurface = largeText.render(text, True, black)
    TextRect = textSurface.get_rect()
    #TextRect.center = ((display_width/2), (display_height/2)) #-->no need for math when you use pygame rects
    TextRect.center = screen_rect.center
    return textSurface, TextRect
    #gameDisplay.blit(TextSurf, TextRect) #-->no need to blit here
    #pygame.display.update() #-->you should only ever see one of these in your entire game
    #time.sleep(2) #-->NEVER use time.sleep in a GUI program
    #game_loop() #-->gameloop only runs once and is ever called once. ACtually you dont even need the content in a function at all
  
def game_loop():
    gameExit = False
    player = Player(gameDisplay_rect)
    car = Car(gameDisplay_rect)
    msg, msg_rect = message_display('You Crashed!', gameDisplay_rect)
    pause = False
    pause_timer = 0.0
    pause_delay = 3000
 
    while not gameExit:
        now = pygame.time.get_ticks()
        keys = pygame.key.get_pressed()
        gameDisplay.fill(white)
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                gameExit = True
                #-->this is already called at the end of the script, should always use the variable to break
                #pygame.quit()
                #quit()
        if not pause:
            car.update()
            car.draw(gameDisplay)
            player.update(keys)
            player.draw(gameDisplay)
        else:
            gameDisplay.blit(msg, msg_rect)
             
        #pause if collision
        if player.check_collision(car.rect):
            pause = True
         
        #reset pause
        if now-pause_timer > pause_delay:
            pause_timer = now
            if pause:
                pause = False
                car.reset()
             
        pygame.display.update()
        clock.tick(60)
         
         
        #-->its better to use pygame.key.get_pressed() for constant key press, located in Player.update()
        #if event.type == pygame.KEYDOWN:
        #    if event.key == pygame.K_a:
        #        x_change += -5
        #    if event.key == pygame.K_d:
        #        x_change += 5
        #if event.type == pygame.KEYUP:
        #    if event.key == pygame.K_a or event.key == pygame.K_d:
        #        x_change = 0
        #x += x_change
 
        #-->This is all handled by Player.check_collision()
        #thingx, thingy, thingw, thingh, color
        #thing(thing_startx, thing_starty, thing_width, thing_height, black)
        #thing_starty += thing_speed
        #car(x,y)
        #if x > display_width - car_width or x < 0:
        #    crash()
        #if y < thing_starty + thing_height:
        #    print('y crossover')
        #    if x > thing_startx and x < thing_startx + thing_width or x + car_width > thing_startx and x + car_width < thing_startx + thing_width:
        #        print('x crossover')
        #        crash()
 
game_loop()
pygame.quit()
quit()
Recommended Tutorials:
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  pygame full screen help corsasri 2 2,743 Mar-20-2024, 07:35 AM
Last Post: reginarodriguez
  [PyGame] When I hit the space bar from the home screen, it sends me to the game over screen JesusisKing 1 953 Apr-30-2023, 10:11 PM
Last Post: deanhystad
  [PyGame] Rect object penetrates wall on one side Jan_97 4 2,463 Dec-30-2021, 11:08 PM
Last Post: Jan_97
  [PyGame] printing integers on pygame.draw.rect Shyckh 1 2,475 Aug-22-2020, 11:44 AM
Last Post: metulburr
  [PyGame] Pygame : clearing a screen issue Reldaing 4 6,028 Jun-23-2020, 09:10 AM
Last Post: JudyLarose
  [PyGame] pygame, help with making a function to detect collision between player and enemy. Kris1996 3 3,282 Mar-07-2020, 12:32 PM
Last Post: Kris1996
  rect object not loading BlueClaw 2 4,108 Dec-11-2019, 04:25 PM
Last Post: BlueClaw
  [PyGame] How to Display pygame on SSD1351 screen kalihotname 0 1,831 Nov-11-2019, 07:32 AM
Last Post: kalihotname
  Pygame sprite not moving michael1789 1 2,784 Nov-10-2019, 03:54 AM
Last Post: michael1789
  moving bullets up the screen using y-coordinate allusernametaken 4 2,529 Nov-10-2019, 02:34 AM
Last Post: allusernametaken

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020