Pygame Screen Won't Erase Before Each Loop - python

I've looked everywhere for an answer and can't seem to figure this out.
Here is the code for where I am actually running the pygame and where I created the car object.
I suspect the problem may have something to do with how I'm feeding in a screen when I create the Car object.
Any help would be appreciated.
Thanks!
main:
import sys
import pygame
from carObject import Car
# set up display
screen = pygame.display.set_mode(size=(1000, 800))
pygame.display.set_caption("jtest")
# color background
background = pygame.Surface(screen.get_size())
WHITE = (255, 255, 255)
# white background
background.fill(WHITE)
screen.blit(background, (0, 0))
# create car
c = Car(background, 475, 650)
while True:
for event in pygame.event.get():
# update screen
pass
# draw things that are happening
screen.fill(WHITE)
c.drawCar()
c.driveForward()
c.driveLeft()
screen.blit(background, (0, 0))
pygame.display.flip()
# if game window is close, end game
if event.type == pygame.QUIT:
pygame.quit()
break
Car object
import pygame
class Car:
def __init__(self, screen, x, y):
# takes screen to draw to as input
# takes x and y coordinates for starting position
self.X = x
self.Y = y
# set car color
self.BODY_COLOR = (0, 0, 255)
#set tire color
self.TIRE_COLOR = (0, 0, 0)
#set headlight color
self.HEADLIGHT_COLOR = (255, 255, 0)
# set screen
self.SCREEN = screen
# set speed
self.SPEED = 1
def drawCar(self):
# store l and w as variables
length = 120
width = 65
# draw main body
pygame.draw.rect(self.SCREEN, self.BODY_COLOR, (self.X, self.Y, width, length))
# draw tires
# front left tire
pygame.draw.rect(self.SCREEN, self.TIRE_COLOR, (self.X-10, self.Y+15, 10, 30))
# front right tire
pygame.draw.rect(self.SCREEN, self.TIRE_COLOR, (self.X+width, self.Y+15, 10, 30))
# back left tire
pygame.draw.rect(self.SCREEN, self.TIRE_COLOR, (self.X-10, self.Y+75, 10, 30))
# back right tire
pygame.draw.rect(self.SCREEN, self.TIRE_COLOR, (self.X+width, self.Y+75, 10, 30))
# draw headlights
# left headlight
pygame.draw.circle(self.SCREEN, self.HEADLIGHT_COLOR, (self.X+15, self.Y+12), 7, 0)
# right headlight
pygame.draw.circle(self.SCREEN, self.HEADLIGHT_COLOR, (self.X+50, self.Y+12), 7, 0)
def driveForward(self):
self.Y -= self.SPEED
def driveBackward(self):
self.Y += self.SPEED
def driveLeft(self):
self.X -= self.SPEED
def driveRight(self):
self.X += self.SPEED

Change your display loop to this, so it clears the background before drawing the car on it. Since you're drawing on the background and it's the same size as the screen, there's no need fill the screen with WHITE each frame.
while True:
for event in pygame.event.get():
# if game window is close, end game
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
# draw things that are happening
# screen.fill(WHITE) # Not needed.
background.fill(WHITE)
c.drawCar()
c.driveForward()
c.driveLeft()
screen.blit(background, (0, 0))
pygame.display.flip()

And I've solved it!
Had to update the screen.fill from inside the drawCar() function in the Car object

Related

i cant figure out my python game keep crashing

please help when i press space, e, or f my game crashes but i cant find out why also can you help me make this dam block move upwards. please help me i will go insane if i cant figure this out.
`
# import the pygame module
import pygame
import keyboard
import time
xb = 30
yb = 670
x = 30
y = 670
o = 0
# Define the background colour
# using RGB color coding.
background_colour = (10,10,10)
# Define the dimensions of
# screen object(width,height)
screen = pygame.display.set_mode((800, 750),pygame.RESIZABLE)
# Set the caption of the screen
pygame.display.set_caption('shoter')
# Fill the background colour to the screen
screen.fill(background_colour)
def player():
color = (40,40,45)
pygame.draw.rect(screen, color, pygame.Rect(x, y, 60, 60))
pygame.draw.polygon(screen, color, ((x+60,y), (x+30,y-80), (x,y)))
pygame.draw.polygon(screen, color, ((x-20,y+52.5), (x+30,y+70), (x+80,y+52.5)))
color = (60,60,65)
pygame.draw.rect(screen, color, pygame.Rect((x-70), (y+20), 200, 30))
color = (40,40,45)
pygame.draw.rect(screen, color, pygame.Rect(x-70, y-20, 20, 40))
pygame.draw.rect(screen, color, pygame.Rect(x+110, y-20, 20, 40))
# Update the display using flip
pygame.display.flip()
# Variable to keep our game loop running
running = True
while running:
for event in pygame.event.get():
# Check for QUIT event
if event.type == pygame.QUIT:
running = False
if keyboard.is_pressed("a") or keyboard.is_pressed("w") or keyboard.is_pressed("left arrow"):
print("left")
screen.fill(background_colour)
x = (x + -3.75)
player()
time.sleep(0.005)
pygame.display.flip()
if keyboard.is_pressed("d") or keyboard.is_pressed("s") or keyboard.is_pressed("right arrow"):
print("right")
screen.fill(background_colour)
x = (x + 3.75)
player()
time.sleep(0.005)
pygame.display.flip()
if keyboard.is_pressed("space") or keyboard.is_pressed("f") or keyboard.is_pressed("e"):
color = (255,0,0)
pygame.draw.rect(screen, color, pygame.Rect(xb, yb, 60, 60))
while (yb > -40):
yb = yb + 5
time.sleep(0.5)
print("shot")
pygame.display.flip()
time.sleep(0.01)
`
please help me ive tried to almost everything to make it work but everytime i press space it crashes
i think this is because of the while loop?
In PyGame, the 0,0 co-ordinate is in the upper-left corner of the window. In your game the player is positioned at the bottom, so the projectile moves up the display, going from a large y-coordinate to a smaller one, and eventually negative once off-screen.
As #Chris Doyle points out in a comment, your code has a tight loop where yb is increased, but then is tested for being < -40. Since yb is already positive, this can never happen. So your program is locking up at this point, as the loop exiting condition can never be satisfied.
Looking at your code, there's a few tweaks necessary for the projectile logic.
First it's best to try to paint everything on the screen from one place, then you're not re-painting (or accidentally erasing) items on every loop.
I also moved the logic of the bullet movement out into the main loop. So pressing space only starts the bullet. The movement happens when the main loop "sees" a bullet on the screen (when firing is True).
Other tweaks: I don't have the keyboard module, so I ported this to standard PyGame keys. And I took the liberty of renaming the x,y and xb,yb to player_x, player_y and projectile_x, projectile_y. I hope that's OK.
# import the pygame module
import pygame
#import keyboard
import time
projectile_x = 30
projectile_y = 670
player_x = 30
player_y = 670
o = 0
# Define the background colour
# using RGB color coding.
background_colour = (10,10,10)
# Define the dimensions of
# screen object(width,height)
screen = pygame.display.set_mode((800, 750),pygame.RESIZABLE)
# Set the caption of the screen
pygame.display.set_caption('shoter')
# Fill the background colour to the screen
screen.fill(background_colour)
def player():
color = (40,40,45)
pygame.draw.rect(screen, color, pygame.Rect(player_x, player_y, 60, 60))
pygame.draw.polygon(screen, color, ((player_x+60,player_y), (player_x+30,player_y-80), (player_x,player_y)))
pygame.draw.polygon(screen, color, ((player_x-20,player_y+52.5), (player_x+30,player_y+70), (player_x+80,player_y+52.5)))
color = (60,60,65)
pygame.draw.rect(screen, color, pygame.Rect((player_x-70), (player_y+20), 200, 30))
color = (40,40,45)
pygame.draw.rect(screen, color, pygame.Rect(player_x-70, player_y-20, 20, 40))
pygame.draw.rect(screen, color, pygame.Rect(player_x+110, player_y-20, 20, 40))
# Update the display using flip
pygame.display.flip()
# Is a projectile on screen?
firing = False
# Variable to keep our game loop running
running = True
clock = pygame.time.Clock()
while running:
for event in pygame.event.get():
# Check for QUIT event
if event.type == pygame.QUIT:
running = False
keys = pygame.key.get_pressed()
a_w_left = keys[pygame.K_LEFT] or keys[pygame.K_a] or keys[pygame.K_w]
d_s_right = keys[pygame.K_RIGHT] or keys[pygame.K_d] or keys[pygame.K_s]
e_f_space = keys[pygame.K_SPACE] or keys[pygame.K_e] or keys[pygame.K_f]
if a_w_left:
print("left")
player_x = (player_x + -3.75)
if d_s_right:
print("right")
player_x = (player_x + 3.75)
if e_f_space:
if ( not firing ):
firing = True
projectile_x = player_x
projectile_y = player_y - 10
print("shot")
# repaint the screen
screen.fill(background_colour)
player()
if ( firing ):
color = (255,0,0)
pygame.draw.rect(screen, color, pygame.Rect(projectile_x, projectile_y, 60, 60))
projectile_y = projectile_y - 5
if ( projectile_y < -60 ):
firing = False # bullet off screen
pygame.display.flip()
clock.tick( 60 ) # limit FPS
Also, it's not good practice to use time.sleep() to control movement (etc.) in a PyGame program, because it blocks everything up. It's better to use the real-time millisecond clock provided by pygame.time.get_ticks().

pygame, how can I use sprite.Group.draw() to draw all sprites?

I am learning pygame by making a simple game.
Here is the code:
Main script:
import pygame
from gracz2 import SpriteGenerator
BLACK = ( 0, 0, 0)
WHITE = ( 255, 255, 255)
GREEN = ( 0, 255, 0)
RED = ( 255, 0, 0)
BLUE = ( 0, 0, 255)
pygame.init()
pygame.display.set_caption("Super Gra!")
screen_height = 720
screen_width = 1280
screen = pygame.display.set_mode((screen_width, screen_height))
all_sprites_list = pygame.sprite.Group()
playerSprite = SpriteGenerator(1,150,150)
playerSprite.rect.x = (screen_width/2 - 75)
playerSprite.rect.y = 550
all_sprites_list.add(playerSprite)
clock = pygame.time.Clock()
mainloop = True
playtime = 0
while mainloop:
for event in pygame.event.get():
# User presses QUIT-button.
if event.type == pygame.QUIT:
mainloop = False
elif event.type == pygame.KEYDOWN:
# User presses ESCAPE-Key
if event.key == pygame.K_ESCAPE:
mainloop = False
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
playerSprite.moveLeft(8)
if keys[pygame.K_RIGHT]:
playerSprite.moveRight(8)
milliseconds = clock.tick(60)
playtime += milliseconds / 1000.0
all_sprites_list.update()
pygame.display.set_caption("Czas gry: " + str(round(playtime,1)) + " sekund")
# Refresh the screen
screen.fill(BLACK)
all_sprites_list.draw(screen)
screen.blit(playerSprite.image, (playerSprite.rect.x,playerSprite.rect.y))
pygame.display.flip()
print(all_sprites_list.sprites())
print(all_sprites_list)
print(playerSprite.rect.x)
print(playerSprite.rect.y)
pygame.quit()
and another file called "gracz2.py":
import pygame
WHITE = (255, 255, 255)
BLACK = ( 0, 0, 0)
class SpriteGenerator(pygame.sprite.Sprite):
#This class represents a player. It derives from the "Sprite" class in Pygame.
def __init__(self, type, width, height):
# Call the parent class (Sprite) constructor
super().__init__()
# Pass in the color of the player, and its x and y position, width and height.
# Set the background color and set it to be transparent
self.image = pygame.Surface([width, height])
self.image.fill(WHITE)
self.image.set_colorkey(WHITE)
if type == 1:
self.image = pygame.image.load("sprite-ufo.gif").convert_alpha()
elif type == 2:
self.image = pygame.image.load("sprite-bomb.jpg").convert_alpha()
# Fetch the rectangle object that has the dimensions of the image.
self.rect = self.image.get_rect()
def moveRight(self, pixels):
self.rect.x += pixels
def moveLeft(self, pixels):
self.rect.x -= pixels
It could be done in one file but the code is more readable for me this way.
around line 50 i call all_sprites_list.draw(screen)
which to my understanding should blit all the sprites contained in all_sprites_list but it does nothing.
I have to use screen.blit(playerSprite.image, (playerSprite.rect.x,playerSprite.rect.y))
to manually blit the sprite.
As i am going to add generate lots of sprites later i can't blit them all manually.
Why doesn't all_sprites_list.draw(screen) work as intended?
It's probably a stupid mistake in the code but I am trying to find for over an hour now and I am unable to locate it.
Turns out that when i restart my PC the draw() function works fine.
I don't know what caused it first, sorry for asking without following the first rule of IT troubleshooting first (restart and try again)
PS: thank you furas for your answers

Pygame doesn't blit images onto canvas

I've made an icon for a gui in a little project I'm working on, and pygame doesn't display it. What am I doing wrong?
import pygame
black = (0,0,0)
toolscanvas = pygame.Surface((700,120))
pygame.init()
gameDisplay = pygame.display.set_mode((0,0),pygame.FULLSCREEN)
gameDisplay.fill(black)
gameDisplay.convert()
clock = pygame.time.Clock()
class GuiHouse:
def __init__(self):
self.x = 0
self.y = 20
self.canvas = pygame.Surface((300,300))
self.canvas.set_alpha(128)
self.iconed = pygame.image.load("house_icon.png").convert_alpha()
self.iconed = pygame.transform.scale(self.iconed, (60, 60))
def display(self):
global toolscanvas
toolscanvas.fill((0,0,0))
self.canvas.blit(self.iconed, (0, 0))
toolscanvas.blit(self.canvas, (self.x, self.y))
gameDisplay.blit(toolscanvas,(0,0))
guihouse = GuiHouse()
while True:
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
pygame.quit()
quit()
guihouse.display()
pygame.display.update()
clock.tick(120)
Real code is a lot longer, let me know if it doesn't work.
Here's what the icon should look like
There are two small errors
You forgot to draw toolscanvas on main pygame display (gameDisplay.blit(toolscanvas, (0, 0)))
An image is read with alfa channel and has only black pixels. So you are drawing a black picture on a black background. At example solution I have added filling image canvas with white color, so now the image is visible, but not pretty. But I hope you will find better solution :)
Example solution:
black = (0, 0, 0)
white = (255, 255, 255)
toolscanvas = pygame.Surface((700, 120))
pygame.init()
gameDisplay = pygame.display.set_mode((0, 0), pygame.FULLSCREEN)
gameDisplay.fill(black)
gameDisplay.convert()
clock = pygame.time.Clock()
class GuiHouse:
def __init__(self):
self.x = 0
self.y = 20
self.canvas = pygame.Surface((300, 300))
self.canvas.set_alpha(128)
self.canvas.fill(white)
self.iconed = pygame.image.load("house_icon.png").convert_alpha()
self.iconed = pygame.transform.scale(self.iconed, (60, 60))
def display(self):
global toolscanvas
toolscanvas.fill((0, 0, 0))
self.canvas.blit(self.iconed, (0, 0))
toolscanvas.blit(self.canvas, (self.x, self.y))
gameDisplay.blit(toolscanvas, (0, 0))
guihouse = GuiHouse()
while True:
guihouse.display()
pygame.display.update()
clock.tick(120)

Appending a variable to a list to create 10 rectangles

I'm trying to make my code have 10 randomly placed and sized rectangles appear all over the screen, but even with my loop I'm not getting the 10, only one. I'm pretty sure my issue is with the way I'm appending the stuff in my loop to my_list, but I'm not sure.
I know this is probably an easy fix, but I just can't figure it out, thanks for the help ahead of time.
import pygame
import random
# Define some colors
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
GREEN = (0, 255, 0)
RED = (255, 0, 0)
class Rectangle():
def __init__(self):
self.x = random.randrange (0, 700)
self.y = random.randrange (0, 500)
self.height = random.randrange (20, 70)
self.width = random.randrange (20, 70)
self.change_x = random.randrange (-3, 3)
self.change_y = random.randrange (-3, 3)
def move(self):
self.x += self.change_x
self.y += self.change_y
def draw(self, screen):
pygame.draw.rect(screen, GREEN, [self.x, self.y, self.height, self.width])
pygame.init()
# Set the width and height of the screen [width, height]
size = (700, 500)
screen = pygame.display.set_mode(size)
pygame.display.set_caption("My Game")
# Loop until the user clicks the close button.
done = False
# Used to manage how fast the screen updates
clock = pygame.time.Clock()
my_list = []
for i in range(10):
my_object = Rectangle()
my_list.append(my_object)
# -------- Main Program Loop -----------
while not done:
# --- Main event loop
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
# --- Game logic should go here
# --- Drawing code should go here
# First, clear the screen to white. Don't put other drawing commands
# above this, or they will be erased with this command.
screen.fill(WHITE)
my_object.move()
my_object.draw(screen)
# --- Go ahead and update the screen with what we've drawn.
pygame.display.flip()
# --- Limit to 60 frames per second
clock.tick(60)
pygame.quit()
You're only drawing one rectangle. This:
while not done:
[..]
# --- Drawing code should go here
# First, clear the screen to white. Don't put other drawing commands
# above this, or they will be erased with this command.
screen.fill(WHITE)
my_object.move()
my_object.draw(screen)
Should be more like this:
while not done:
[..]
# --- Drawing code should go here
# First, clear the screen to white. Don't put other drawing commands
# above this, or they will be erased with this command.
screen.fill(WHITE)
for my_object in my_list:
my_object.move()
my_object.draw(screen)

Can't draw rect in python pygame

I'm just getting started with PyGame. Here, I'm trying to draw a rectangle, but it's not rendering.
Here's the whole program.
import pygame
from pygame.locals import *
import sys
import random
pygame.init()
pygame.display.set_caption("Rafi's Game")
clock = pygame.time.Clock()
screen = pygame.display.set_mode((700, 500))
class Entity():
def __init__(self, x, y):
self.x = x
self.y = y
class Hero(Entity):
def __init__(self):
Entity.__init__
self.x = 0
self.y = 0
def draw(self):
pygame.draw.rect(screen, (255, 0, 0), ((self.x, self.y), (50, 50)), 1)
hero = Hero()
#--------------Main Loop-----------------
while True:
hero.draw()
keysPressed = pygame.key.get_pressed()
if keysPressed[K_a]:
hero.x = hero.x - 3
if keysPressed[K_d]:
hero.x = hero.x + 3
if keysPressed[K_w]:
hero.y = hero.y - 3
if keysPressed[K_s]:
hero.y = hero.y + 3
screen.fill((0, 255, 0))
#Event Procesing
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
#Event Processing End
pygame.display.flip()
clock.tick(20)
self.x and self.y are currently 0 and 0.
Note that this is not a finished program, all it should do is draw a red square on a green background that can be controled by the WASD keys.
Let's look at a portion of your main loop:
while True:
hero.draw()
keysPressed = pygame.key.get_pressed()
if keysPressed[K_a]:
hero.x = hero.x - 3
if keysPressed[K_d]:
hero.x = hero.x + 3
if keysPressed[K_w]:
hero.y = hero.y - 3
if keysPressed[K_s]:
hero.y = hero.y + 3
screen.fill((0, 255, 0))
Inside the Hero class's draw function, you are drawing the rect. In the main loop, you are calling hero.draw(), and then after handling your inputs, you are calling screen.fill(). This is drawing over the rect you just drew. Try this:
while True:
screen.fill((0, 255, 0))
hero.draw()
keysPressed = pygame.key.get_pressed()
....
That will color the entire screen green, then draw your rect over the green screen.
This is more of an extended comment and question than an answer.
The following draws a red square. Does it work for you?
import sys
import pygame
pygame.init()
size = 320, 240
black = 0, 0, 0
red = 255, 0, 0
screen = pygame.display.set_mode(size)
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
screen.fill(black)
# Either of the following works. Without the fourth argument,
# the rectangle is filled.
pygame.draw.rect(screen, red, (10,10,50,50))
#pygame.draw.rect(screen, red, (10,10,50,50), 1)
pygame.display.flip()
Check these links:
http://www.pygame.org/docs/ref/draw.html#pygame.draw.rect
And here have a some examples:
http://nullege.com/codes/search?cq=pygame.draw.rect
pygame.draw.rect(screen, color, (x,y,width,height), thickness)
pygame.draw.rect(screen, (255, 0, 0), (self.x, self.y, 50, 50), 1)

Categories

Resources