Bug using pygame where my sprite won't appear on screen - python

I'm at the very beginning of a chess program and want to print the board on the screen. However, I am having trouble at the first hurdle and cannot even get it to print the squares of the board. It just comes up with a black screen and doesn't put the sprite on it.
I've tried looking at some code from a previous project where it worked, but I can't find any differences in this part of the program.
import pygame
import os
import time
pygame.init()
WHITE = (0, 30, 0)
BLACK = (200, 200, 200)
screen_width = 1400
screen_height = 800
square_size = screen_height/10
screen = pygame.display.set_mode([screen_width, screen_height])
os.environ['SDL_VIDEO_WINDOWS_POS'] = '10,10'
class square(pygame.sprite.Sprite):
def __init__(self, colour, x, y):
super().__init__()
self.image = pygame.Surface([square_size, square_size])
pygame.draw.rect(self.image, colour, [0, 0, square_size, square_size])
self.colour = colour
self.rect = self.image.get_rect()
squares = pygame.sprite.Group()
s = square(WHITE, 20, 20)
squares.add(s)
squares.draw(screen)
time.sleep(3)
I would expect this to output one white square in the top left hand corner of the screen, but only a black screen appears.

You need an event.get loop, and to update your display using pygame.display.update() after the squares.draw(screen):
import pygame
import os
import time
pygame.init()
WHITE = (0, 30, 0)
BLACK = (200, 200, 200)
screen_width = 1400
screen_height = 800
square_size = screen_height/10
screen = pygame.display.set_mode([screen_width, screen_height])
os.environ['SDL_VIDEO_WINDOWS_POS'] = '10,10'
class square(pygame.sprite.Sprite):
def __init__(self, colour, x, y):
super().__init__()
self.image = pygame.Surface([square_size, square_size])
pygame.draw.rect(self.image, colour, [0, 0, square_size, square_size])
self.colour = colour
self.rect = self.image.get_rect()
for event in pygame.event.get():
pass
squares = pygame.sprite.Group()
s = square(WHITE, 20, 20)
squares.add(s)
squares.draw(screen)
pygame.display.update()
time.sleep(3)
Also note, an RGB value of (0, 30, 0) is not white, it's a dark green, if you want bright white try (255, 255, 255).

Most likely, your problem is that you didn't flip/update the screen.

Related

drawing objects on pygame

I am restarting some code for a covid simulation as I cant use the collide function in my current one. I have been able to draw the basic background, and draw one cell. However, when i try create the cell in a different place on my screen it does not appear for some reason.
My code is as seen below:
import random
import pygame
# import numpy
import time
pygame.init()
GREEN1 = (0, 255, 0) # Healthy cells
RED = (255, 0, 0) # Infected cells
GREEN2 = (0, 100, 0) # Healthy cells not susecptible
BLACK = (0, 0, 0) # Dead cells
WHITE = (255, 255, 255)
Bgcolor = (225, 198, 153)
ScreenSize = (800, 800)
Screen = pygame.display.set_mode(ScreenSize)
pygame.display.set_caption("Covid-19 Simualtion")
clock = pygame.time.Clock()
speed = [0.5, -0.5]
class Cells(pygame.sprite.Sprite):
def __init__(self, color, speed, width, height):
super().__init__()
self.color = color
self.x_cord = random.randint(0, 400)
self.y_cord = random.randint(50, 700)
self.radius = 5
self.speed = speed
self.image = pygame.Surface([width, height])
self.image.fill(WHITE)
self.image.set_colorkey(WHITE)
pygame.draw.circle(self.image, self.color, [30, 70], self.radius, width = 0)
self.rect = self.image.get_rect()
self.radius = 5
#x_number = random.randint(0, 1)
#self.xSpeed = speed[x_number]
#y_number = random.randint(0, 1)
#self.ySpeed = speed[y_number]
allCellsList = pygame.sprite.Group()
Cell1 = Cells(GREEN1, 5, 50, 50)
allCellsList.add(Cell1)
End = False
while not End:
for event in pygame.event.get():
if event.type == pygame.QUIT:
End = True
Screen.fill(Bgcolor)
pygame.draw.rect(Screen, BLACK, (0, 50, 400, 700), 3)
allCellsList.update()
allCellsList.draw(Screen)
pygame.display.flip()
clock.tick(60)
Thanks for any help in advance
The main problem is that your cell has size (50,50) and you try to draw on position (20,70) so it draws outside rectangle (50, 50) and you can't see it. You have to draw inside rectangle (50, 50) - for example in center (25,25). And later you should use self.rect to move it on screen.
Second problem is that you keep position in self.x_coord, self.x_coord but you should use self.rect.x self.rect.y because Sprite use self.image and self.rect to draw it on screen.
And it show third problem - in Cell you need method update which will change values in self.rect to move object.
Minimal working example which move 5 cells in random directions.
I organize code in different way and try to use PEP 8 - Style Guide for Python Code
import random
import pygame
# --- constants --- (UPPER_CASE_NAMES)
GREEN1 = (0, 255, 0) # Healthy cells
RED = (255, 0, 0) # Infected cells
GREEN2 = (0, 100, 0) # Healthy cells not susecptible
BLACK = (0, 0, 0) # Dead cells
WHITE = (255, 255, 255)
BACKGROUND_COLOR = (225, 198, 153)
SCREEN_SIZE = (800, 800)
# --- classes --- (CamelCaseNames)
# class keeep only one cell so it should has name `Cell` instead of `Cells`
class Cell(pygame.sprite.Sprite):
def __init__(self, color, speed, width, height):
super().__init__()
self.color = color
self.speed = speed
self.image = pygame.Surface([width, height])
self.image.fill(WHITE)
self.image.set_colorkey(WHITE)
self.radius = width//2 # 25
center = [width//2, height//2]
pygame.draw.circle(self.image, self.color, center, self.radius, width=0)
self.rect = self.image.get_rect()
self.rect.x = random.randint(0, 400)
self.rect.y = random.randint(50, 700)
def update(self):
self.rect.x += random.randint(-10, 10)
self.rect.y += random.randint(-10, 10)
# --- functions --- (lower_case_names)
# empty
# --- main --- (lower_case_names)
pygame.init()
screen = pygame.display.set_mode(SCREEN_SIZE)
pygame.display.set_caption("Covid-19 Simualtion")
speed = [0.5, -0.5]
# - objects -
all_cells = pygame.sprite.Group() # PEP8: lower_case_name
for _ in range(5):
cell = Cell(GREEN1, 5, 50, 50) # PEP8: lower_case_name
all_cells.add(cell)
# - loop -
clock = pygame.time.Clock()
end = False
while not end:
# - events -
for event in pygame.event.get():
if event.type == pygame.QUIT:
end = True
# - upadates (without draws) -
all_cells.update()
# - draws (without updates) -
screen.fill(BACKGROUND_COLOR)
pygame.draw.rect(screen, BLACK, (0, 50, 400, 700), 3)
all_cells.draw(screen)
pygame.display.flip()
clock.tick(30) # to use less CPU
# - end
pygame.quit() # some system may need it to close window

Pygame draw.rect not working with rect argument

Trying to make a clone of space invaders. I'm following a guide from here https://kidscancode.org/blog/2016/08/pygame_shmup_part_5/. This is the player sprite
class Player(pygame.sprite.Sprite):
def __init__(self):
super(Player, self).__init__()
self.image = pygame.image.load('./Assets/PNG/playerShip1_orange.png').convert()
self.image.set_colorkey(BLACK)
self.image = pygame.transform.scale(self.image, (50, 40))
# WIN_SIZE = 500, 500
self.rect = self.image.get_rect()
self.rect.centerx = WIN_SIZE[0] / 2
self.rect.bottom = WIN_SIZE[1] - 10
self.speedx = 0
# NOT WORKING FOR SOME REASON
# self.image.fill(WHITE, self.rect)
# pygame.draw.rect(self.image, WHITE, self.rect, 1)
# pygame.draw.circle(self.image, WHITE, self.rect.center, 25, 1)
pygame.draw.rect(self.image, WHITE, ( (0,0), (50, 40) ), 1)
I want to create a rectangular outline around the sprite, which i'm able to do if i use the last line in above code. However, the commented code doesn't work for some reason even though each argument is correct and no compile/runtime error is thrown.
Relevent Snippets from Main Class
class Game:
def __init__(self):
pygame.init()
self._win = pygame.display.set_mode(WIN_SIZE, 0, 32)
self._clock = pygame.time.Clock()
self._all_sprites = pygame.sprite.Group()
self._player = Player()
self._all_sprites.add(self._player)
self._game_over = False
def run(self):
while not self._game_over:
self._clock.tick(FPS)
self._all_sprites.update()
self._all_sprites.draw(self._win)
pygame.display.flip()
def main():
game = Game()
game.run()
if __name__ == "__main__":
main()
Complete Source : https://github.com/muneeb-devp/Shmup
Any sorta help would be appreciated :)
You have to draw the outline on the image, before the position of the rectangle is set:
self.rect = self.image.get_rect()
pygame.draw.rect(self.image, WHITE, self.rect, 1)
pygame.draw.circle(self.image, WHITE, self.rect.center, 25, 1)
self.rect.centerx = WIN_SIZE[0] // 2
self.rect.bottom = WIN_SIZE[1] - 10
self.speedx = 0
The location of the rectangle which is returned by get_rect() is (0, 0). This is also the top left position of the outline in the image. Note, you draw the outline on the image not on the display.

pygame NameError: name 'self' is not defined but can't see indentation issue [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
I have seen This question on this but I can not see any indentation issues in my code. How do I fix the error:
NameError: name 'self' is not defined
My code:
import PySimpleGUI as sg
hp = 0
import pygame, random
#Let's import the Car Class
from player import Car
pygame.init()
def play():
font = pygame.font.Font(None, 100)
GREEN = (20, 255, 140)
GREY = (210, 210 ,210)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
PURPLE = (255, 0, 255)
YELLOW = (255, 255, 0)
CYAN = (0, 255, 255)
BLUE = (100, 100, 255)
speed = 1
colorList = (RED, GREEN, PURPLE, YELLOW, CYAN, BLUE)
SCREENWIDTH=800
SCREENHEIGHT=600
lack_bar = pygame.Surface((SCREENWIDTH, 35))
size = (SCREENWIDTH, SCREENHEIGHT)
screen = pygame.display.set_mode(size)
pygame.display.set_caption("Car Racing")
#This will be a list that will contain all the sprites we intend to use in our game.
all_sprites_list = pygame.sprite.Group()
playerCar = Car(RED, 60, 80, 70)
playerCar.rect.x = 160
playerCar.rect.y = SCREENHEIGHT - 100
car1 = Car(PURPLE, 60, 80, random.randint(50,100))
car1.rect.x = 60
car1.rect.y = -100
car2 = Car(YELLOW, 60, 80, random.randint(50,100))
car2.rect.x = 160
car2.rect.y = -600
car3 = Car(CYAN, 60, 80, random.randint(50,100))
car3.rect.x = 260
car3.rect.y = -300
car4 = Car(BLUE, 60, 80, random.randint(50,100))
car4.rect.x = 360
car4.rect.y = -900
# Add the car to the list of objects
all_sprites_list.add(playerCar)
all_sprites_list.add(car1)
all_sprites_list.add(car2)
all_sprites_list.add(car3)
all_sprites_list.add(car4)
all_coming_cars = pygame.sprite.Group()
all_coming_cars.add(car1)
all_coming_cars.add(car2)
all_coming_cars.add(car3)
all_coming_cars.add(car4)
#Allowing the user to close the window...
carryOn = True
clock=pygame.time.Clock()
while carryOn:
for event in pygame.event.get():
if event.type==pygame.QUIT:
carryOn=False
end()
elif event.type==pygame.KEYDOWN:
if event.key==pygame.K_x:
playerCar.moveRight(10)
#Check if there is a car collision
car_collision_list = pygame.sprite.spritecollide(playerCar,all_coming_cars,False)
for car in car_collision_list:
carryOn=False
end()
self.text = font.render("text that should appear", True, (238, 58, 140))
self.screen.blit(self.text, [400,300])
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
playerCar.moveLeft(5)
if keys[pygame.K_RIGHT]:
playerCar.moveRight(5)
if keys[pygame.K_UP]:
speed += 0.05
if keys[pygame.K_DOWN]:
speed -= 0.05
#Game Logic
for car in all_coming_cars:
car.moveForward(speed)
if car.rect.y > SCREENHEIGHT:
car.changeSpeed(random.randint(50,100))
car.repaint(random.choice(colorList))
car.rect.y = -200
all_sprites_list.update()
#Drawing on Screen
screen.fill(GREEN)
#Draw The Road
pygame.draw.rect(screen, GREY, [40,0, 400,SCREENHEIGHT])
#Draw Line painting on the road
pygame.draw.line(screen, WHITE, [140,0],[140,SCREENHEIGHT],5)
#Draw Line painting on the road
pygame.draw.line(screen, WHITE, [240,0],[240,SCREENHEIGHT],5)
#Draw Line painting on the road
pygame.draw.line(screen, WHITE, [340,0],[340,SCREENHEIGHT],5)
#Now let's draw all the sprites in one go. (For now we only have 1 sprite!)
all_sprites_list.draw(screen)
#Refresh Screen
pygame.display.flip()
#Number of frames per secong e.g. 60
clock.tick(60)
def end():
layout = [[sg.Text("Car Crash"), sg.Button("Try Again"), sg.Button("End")]]
window = sg.Window("Car Crash!!!", layout)
while True:
event, values = window.read()
if event == "End":
window.close()
pygame.quit()
if event == "Try Again":
window.close()
play()
play()
My sprite class:
import pygame
WHITE = (255, 255, 255)
class Car(pygame.sprite.Sprite):
#This class represents a car. It derives from the "Sprite" class in Pygame.
def __init__(self, color, width, height, speed):
# Call the parent class (Sprite) constructor
super().__init__()
# Pass in the color of the car, 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)
#Initialise attributes of the car.
self.width=width
self.height=height
self.color = color
self.speed = speed
# Draw the car (a rectangle!)
pygame.draw.rect(self.image, self.color, [0, 0, self.width, self.height])
# Instead we could load a proper picture of a car...
# self.image = pygame.image.load("car.png").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
def moveForward(self, speed):
self.rect.y += self.speed * speed / 20
def moveBackward(self, speed):
self.rect.y -= self.speed * speed / 20
def changeSpeed(self, speed):
self.speed = speed
def repaint(self, color):
self.color = color
pygame.draw.rect(self.image, self.color, [0, 0, self.width, self.height])
what is going on? I am following The answer to this question for how to show text on the screen (picking things up) - what have I missed? My code (except from own contributions) comes from HERE
Whole traceback:
Traceback (most recent call last):
File "C:\Users\tom\Documents\python\In development\Doge those cars\Doge those cars.py", line 154, in <module>
play()
File "C:\Users\tom\Documents\python\In development\Doge those cars\Doge those cars.py", line 90, in play
self.text = font.render("text that should appear", True, (238, 58, 140))
NameError: name 'self' is not defined
The answer was said in the comments. self isn't defined in your code, either as an argument for your function or as a global variable. In fact, your play function isn't even defined in a class, so I'm not too sure as to why you're using the self keyword at all.
Follow the traceback:
in your file Doge those cars.py line 90, that is in the func play()
there is a line that states self.text = font.render("text that should appear", True, (238, 58, 140))
but it isn't in your class, and there is no 'self' defined.

How to move pygame sprite up

I am using pygame and following a tutorial HERE. I have the following code:
import pygame
import sys
#Let's import the Car Class
from player import Car
pygame.init()
GREEN = (20, 255, 140)
GREY = (210, 210 ,210)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
PURPLE = (255, 0, 255)
SCREENWIDTH=400
SCREENHEIGHT=500
size = (SCREENWIDTH, SCREENHEIGHT)
screen = pygame.display.set_mode(size)
pygame.display.set_caption("Car Racing")
#This will be a list that will contain all the sprites we intend to use in our game.
all_sprites_list = pygame.sprite.Group()
playerCar = Car(RED, 20, 30)
playerCar.rect.x = 200
playerCar.rect.y = 300
# Add the car to the list of objects
all_sprites_list.add(playerCar)
#Allowing the user to close the window...
carryOn = True
clock=pygame.time.Clock()
while carryOn:
for event in pygame.event.get():
if event.type==pygame.QUIT:
carryOn=False
elif event.type==pygame.KEYDOWN:
if event.key==pygame.K_x: #Pressing the x Key will quit the game
carryOn=False
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
playerCar.moveLeft(5)
if keys[pygame.K_RIGHT]:
playerCar.moveRight(5)
if keys[pygame.K_UP]:
playerCar.moveUp(5)
#Game Logic
all_sprites_list.update()
#Drawing on Screen
screen.fill(GREEN)
#Draw The Road
pygame.draw.rect(screen, GREY, [40,0, 200,300])
#Draw Line painting on the road
pygame.draw.line(screen, WHITE, [140,0],[140,300],5)
#Now let's draw all the sprites in one go. (For now we only have 1 sprite!)
all_sprites_list.draw(screen)
#Refresh Screen
pygame.display.flip()
#Number of frames per secong e.g. 60
clock.tick(60)
pygame.quit()
The
if keys[pygame.K_UP]:
playerCar.moveUp(5)
is my own contribution. I also have my my sprite class:
import pygame
WHITE = (255, 255, 255)
class Car(pygame.sprite.Sprite):
#This class represents a car. It derives from the "Sprite" class in Pygame.
def __init__(self, color, width, height):
# Call the parent class (Sprite) constructor
super().__init__()
# Pass in the color of the car, 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)
# Draw the car (a rectangle!)
pygame.draw.rect(self.image, color, [0, 0, width, height])
# Instead we could load a proper pciture of a car...
# self.image = pygame.image.load("car.png").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
def moveUp(self, pixels, y):
self.rect.x += pixels
The
def moveUp(self, pixels, y):
self.rect.x += pixels
is my own contribution. Before when my contribution was:
def moveUp(self, pixels):
self.rect.x += pixels
my sprite moved right when I pressed the up arrow. With the code as it is now I get the error:
TypeError: moveUp() missing 1 required positional argument: 'y'
How do I fix this and get my sprite to move up when I press the up arrow?
You want to change self.rect.x to self.rect.y:
Try changing the line
def moveUp(self, pixels, y):
self.rect.x += pixels
to this:
def moveUp(self, pixels):
self.rect.y += pixels

Pygame drawing a rectangle with OOP

I'm trying to learn OOP with pygame and make a simple game, I'm loosely following a tutorial, but have tried to modify it to fit my own needs and now it's not working. I'm trying to draw a white rectangle onto a black window, the tutorial draws a blue circle on a black window and when I replace the circle to a rectangle it doesn't work.
My code is sepereated into 2 different files heres the first file:
import pygame
import LanderHandler
black = (0, 0, 0)
white = (255, 255, 255)
green = (0, 255, 0)
red = (255, 0, 0)
class MainLoop(object):
def __init__(self, width=640, height=400):
pygame.init()
pygame.display.set_caption("Lander Game")
self.width = width
self.height = height
self.screen = pygame.display.set_mode((self.width, self.height), pygame.DOUBLEBUF)
self.background = pygame.Surface(self.screen.get_size()).convert()
def paint(self):
lander = LanderHandler.Lander()
lander.blit(self.background)
def run(self):
self.paint()
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
running = False
pygame.display.flip()
pygame.quit()
if __name__ == '__main__':
# call with width of window and fps
MainLoop().run()
And my second file:
import pygame
black = (0, 0, 0)
white = (255, 255, 255)
green = (0, 255, 0)
red = (255, 0, 0)
class Lander(object):
def __init__(self, height=10, width=10, color=white, x=320, y=240):
self.x = x
self.y = y
self.height = height
self.width = width
self.surface = pygame.Surface((2 * self.height, 2 * self.width))
self.color = color
pygame.draw.rect(self.surface, white, (self.height, self.height, self.width, self.width))
def blit(self, background):
"""blit the Ball on the background"""
background.blit(self.surface, (self.x, self.y))
def move(self, change_x, change_y):
self.change_x = change_x
self.change_y = change_y
self.x += self.change_x
self.y += self.change_y
if self.x > 300 or self.x < 0:
self.change_x = -self.change_x
if self.y > 300 or self.y < 0:
self.change_y = -self.change_y
Any help or pointing me in the right direction would be amazing thank you.
P.S. I get no running errors and a black window does pop up, but without a white rectangle.
Problem is because you draw rectangle on surface self.background
lander.blit(self.background)
but you never blit self.background on self.screen which is main buffer and which is send on monitor when you do
pygame.display.flip()
So you can draw directly on self.screen
lander.blit(self.screen)
or you have to blit self.background on self.screen
lander.blit(self.background)
self.screen.blit(self.background, (0,0))
You shouldn't create a function with the name blit because it might get in the way of the actual blit function. Also right here in the second code:
pygame.draw.rect(self.surface, white, (self.height, self.height, self.width, self.width))
you should use surface

Categories