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)
Related
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().
I have been trying to make a little game using Pygame. This is my first time using Pygame and I have looked at many tutorials, but my sprite still won't appear. It only shows a black line. How can I fix it?
Xcord = 0
grey = (192,192,192)
import pygame, random, time
pygame.init()
import time
Color_line=(0,0,0)
screen = pygame.display.set_mode([1000, 500])
all_sprites_list = pygame.sprite.Group()
import pygame
grey = (192,192,192)
playerWidth = 50
playerHeight = 50
all_sprites_list = pygame.sprite.Group()
class Player(pygame.sprite.Sprite):
def __init__(self, grey, playerWidth, playerHeight):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface([50, 50])
self.image.fill(grey)
self.image.set_colorkey(grey)
pygame.draw.rect(self.image, grey, [0, 0, playerWidth, playerHeight])
self.rect = self.image.get_rect()
player = Player(grey, 50, 50)
player.rect.x = Xcord
player.rect.y = 400
def update(Player):
pygame.sprite.Sprite.update(Player)
player.rect.x = Xcord
player.rect.y = 400
all_sprites_list.add(player)
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
screen.fill((255, 255, 255))
all_sprites_list.update()
pygame.draw.line(screen,Color_line,(0,500),(1000,500), 75)
all_sprites_list.draw(screen)
pygame.display.flip()
Xcord =+ 50
if Xcord == 400:
Xcord == 0
pygame.quit()
I am kind of trying to make something similar to Google Chrome's no Wi-Fi dinosaur game.
You have a few mistakes.
First: you fill sprite with GRAY and you use set_key on GRAY, so the sprite is transparent and simply you can't see the sprite.
Second: the code runs very fast and the sprite leaves the window and you can't see the sprite.
Third: in the code if Xcord == 400: Xcord == 0, you need = 0 instead of == 0 - and this is why the sprite leaves the window and never go back to position (0, 400)
Another problem is the big mess in the code - you even run some code two times.
My version with many changes.
# PEP8: all imports at start.
# PEP8: every module on a separate line
import pygame
import random
import time
# --- constants --- # PEP8: `UPPER_CAS_NAMES`
GRAY = (192, 192, 192)
RED = (255, 0, 0)
# --- classes --- # PEP8: `CamelCaseName`
class Player(pygame.sprite.Sprite):
def __init__(self, color, x, y, width, weight): # you don't need prefix `player` in variables in class `Player`
super().__init__() # Python 3 method for running a function from the original class
self.color = color
self.image = pygame.Surface([width, weight])
self.image.fill(color)
#self.image.set_colorkey(color)
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
def update(self):
self.rect.x += 5
if self.rect.x >= 400:
self.rect.x = 0
# --- main ---
color_line = (0,0,0) # PEP8: spaces around `=`, space after `,`
pygame.init()
screen = pygame.display.set_mode([1000, 500])
all_sprites_list = pygame.sprite.Group()
player_width = 50
player_weight = 50
player = Player(RED, 50, 400, 50, 50) # color, x, y, width, height
all_sprites_list.add(player)
clock = pygame.time.Clock()
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# - only updates -
all_sprites_list.update()
# - only draws -
screen.fill((255, 255, 255))
pygame.draw.line(screen, color_line, (0, 500), (1000, 500), 75)
all_sprites_list.draw(screen)
pygame.display.flip()
clock.tick(30) # Slow down to 30 FPS (frames per seconds)
pygame.quit()
PEP 8 -- Style Guide for Python Code
I am working on a basic pong pygame and I have coded my main.py, paddle.py, and ball.py files and unfortunately, when I run the game it only displays a black pygame window. My paddles, ball, net, and score are not visible... it's just blank.
Screenshot of Blank/Black Window
The following is my code, I have seperated it by each file.
I cannot seem to find what is causing this error so any feedback would be appreciated.
MAIN.PY
# Import pygame library and initialize the game engine
import pygame
from paddle import Paddle
from ball import Ball
pygame.init()
# Define some colors
BLACK = (0,0,0)
WHITE = (255,255,255)
# Open a new window
size = (700, 500)
screen = pygame.display.set_mode(size)
pygame.display.set_caption("Pong")
paddleA = Paddle(WHITE, 10, 100)
paddleA.rect.x = 20
paddleA.rect.y = 200
paddleB = Paddle(WHITE, 10, 100)
paddleB.rect.x = 670
paddleB.rect.y = 200
ball = Ball(WHITE, 10, 10)
ball.rect.x = 345
ball.rect.y = 195
# This will be a list that contains all the sprites we intend to use in game.
all_sprites_list = pygame.sprite.Group()
# Add paddles to the list of sprites
all_sprites_list.add(paddleA)
all_sprites_list.add(paddleB)
all_sprites_list.add(ball)
# Loop will carry on until user exits the game (ex. clicks the close button)
carryOn = True
# Clock will be used to control how fast the screen updates
clock = pygame.time.Clock()
# Initialize player scores
scoreA = 0
scoreB = 0
# ----- Main Program Loop -----
while carryOn:
# --- Main Event Loop ---
for event in pygame.event.get(): # user did something
if event.type==pygame.QUIT: # if user clicked close
carryOn==False # Flag that we are done so we exit this loop
elif event.type==pygame.KEYDOWN:
if event.key==pygame.K_x: # Pressing the x key will quit the game
carryOn==False
# Moving the paddles when the user uses the arrow keys (Player A),
# or W/S keys (Player B)
keys = pygame.key.get_pressed()
if keys[pygame.K_w]:
paddleA.moveUp(5)
if keys[pygame.K_s]:
paddleA.moveDown(5)
if keys[pygame.K_UP]:
paddleB.moveUp(5)
if keys[pygame.K_DOWN]:
paddleB.moveDown(5)
# --- Game Logic ---
all_sprites_list.update()
# Checks if the ball is bouncing against any of the 4 walls
if ball.rect.x>=690:
ball.velocity[0] = -ball.velocity[0]
if ball.rect.x<=0:
ball.velocity[0] = -ball.velocity[0]
if ball.rect.y>490:
ball.velocity[1] = -ball.velocity[1]
if ball.rect.y<0:
ball.velocity[1] = -ball.velocity[1]
#Detect collisions between the ball and the paddles
if pygame.sprite.collide_mask(ball, paddleA) or pygame.sprite.collide_mask(ball, paddleB):
ball.bounce()
# --- Drawing Code ---
# clears the screen to black
screen.fill(BLACK)
# draws the net
pygame.draw.line(screen, WHITE, [349, 0], [349, 500], 5)
# Draws all sprites in one go (I only have 2 for now)
all_sprites_list.draw(screen)
# Display scores
font = pygame.font.Font(None, 74)
text = font.render(str(scoreA), 1, WHITE)
screen.blit(text, (250,10))
text.font.render(str(scoreB), 1, WHITE)
screen.blit(text (420,10))
# update screen with what we've drawn
pygame.display.flip()
# limit to 60 frames per second
clock.tick(60)
# Once we have exited the main program loop we stop the game engine
pygame.quit()
PADDLE.PY
import pygame
BLACK = (0,0,0)
class Paddle(pygame.sprite.Sprite):
# This class represents a paddle. 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 paddle and it's x and y position (width nd height).
# Set the background color as transparent
self.image = pygame.Surface([width, height])
self.image.fill(BLACK)
self.image.set_colorkey(BLACK)
# Draw the paddle which is a rectangle
pygame.draw.rect(self.image, color, [0,0, width, height])
# Fetch the rectangle object that has the dimensions of the image
self.rect = self.image.get_rect()
def moveUp(self, pixels):
self.rect.y -= pixels
# Check that you are not going too far (off screen)
if self.rect.y < 0:
self.rect.y = 0
def moveDown(self, pixels):
self.rect.y += pixels
# Check that you are not going too far (off screen)
if self.rect.y > 400:
self.rect.y = 400
BALL.PY
import pygame
from random import randint
BLACK = (0,0,0)
class Ball(pygame.sprite.Sprite):
#This class represents a ball. 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 ball, its width and height.
# Set the background color and set it to be transparent
self.image = pygame.Surface([width, height])
self.image.fill(BLACK)
self.image.set_colorkey(BLACK)
# Draw the ball (a rectangle!)
pygame.draw.rect(self.image, color, [0, 0, width, height])
self.velocity = [randint(4,8),randint(-8,8)]
# Fetch the rectangle object that has the dimensions of the image.
self.rect = self.image.get_rect()
def update(self):
self.rect.x += self.velocity[0]
self.rect.y += self.velocity[1]
def bounce(self):
self.velocity[0] = -self.velocity[0]
self.velocity[1] = randint(-8,8)
You are simply not flipping the screen in the main loop, in the main file.
All is actually being updated, but nothing is being rendered on the screen.
Just intend the code from
# --- Drawing Code ---
to
clock.tick(60)
I think you forgot to indent it.
Just be careful not to include pygame.quit() in the main loop.
Just add a tabulation layer from
...
# --- Drawing Code ---
...
to end in main.py
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
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