Pygame rectangle position not updating [duplicate] - python

This question already has an answer here:
How to detect collisions between two rectangular objects or images in pygame
(1 answer)
Closed 2 years ago.
I am writing simple snake game using pygame library. Now I am writing the checkPosition() function. It uses the contains() method from pygame. Problem is that it takes the coordinates prom the start of the loop and it is not updating. How can i reset theese variables or make to update the loop? The whole code is here:
import pygame
import random
pygame.init()
screen = pygame.display.set_mode((500, 500))
pygame.display.set_caption("Snake Game using Pygame")
#colors (RGB code)
blue = (3, 119, 252)
yellow = [251, 255, 36]
gray = [48, 48, 47]
# Variables for control
# Speed of movement
vel = 10
# Snake width and height
width = 35
height = 35
#Snake spawn position
x = 25
y = 25
clock = pygame.time.Clock()
# Random coordinates for spawning snake "snack"
randomSnackX = random.randrange(0, 500, 20)
randomSnackY = random.randrange(0, 500, 20)
# Snack width and height - thickness
snackThickness = 10
# Variable for initial game loop
run = True
# Draw snack and snake
def drawInitialElements():
# Draw raadom snak position from variables
snack = pygame.draw.rect(screen, (255, 255, 255), [randomSnackX,randomSnackY,snackThickness,snackThickness])
#Draw snake
snake = pygame.draw.rect(screen, (255, 255, 255), (x, y, width, height))
return snake, snack
snake, snack = drawInitialElements()
def checkPosition():
if (snake.contains(snack)) == True:
print("Eated snack")
#Initial game loop
while run:
pygame.time.delay(100)
screen.fill((0, 0, 0))
# If quit
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
#Controls
keys = pygame.key.get_pressed()
if keys[pygame.K_RIGHT]:
x += vel
if keys[pygame.K_LEFT]:
x -= vel
if keys[pygame.K_UP]:
y -= vel
if keys[pygame.K_DOWN]:
y += vel
drawInitialElements()
checkPosition()
pygame.display.update()
pygame.quit()
Thanks for your help, Tom.

To verify if pygame.Rect objects are colliding, you have to use colliderect:
def checkPosition():
if snake.colliderect(snack):
print("Eated snack")
drawInitialElements returns a tuple containing the rectangle of the snake and the snack. Assign the return value the variables snake and snack in globale namespace:
while run:
# [...]
snake, snack = drawInitialElements()
# [...]
Complete application code:
import pygame
import random
pygame.init()
screen = pygame.display.set_mode((500, 500))
pygame.display.set_caption("Snake Game using Pygame")
#colors (RGB code)
blue = (3, 119, 252)
yellow = [251, 255, 36]
gray = [48, 48, 47]
# Variables for control
# Speed of movement
vel = 10
# Snake width and height
width = 35
height = 35
#Snake spawn position
x = 25
y = 25
clock = pygame.time.Clock()
# Random coordinates for spawning snake "snack"
randomSnackX = random.randrange(0, 500, 20)
randomSnackY = random.randrange(0, 500, 20)
# Snack width and height - thickness
snackThickness = 10
# Variable for initial game loop
run = True
# Draw snack and snake
def drawInitialElements():
# Draw raadom snak position from variables
snack = pygame.draw.rect(screen, (255, 255, 255), [randomSnackX,randomSnackY,snackThickness,snackThickness])
#Draw snake
snake = pygame.draw.rect(screen, (255, 255, 255), (x, y, width, height))
return snake, snack
snake, snack = drawInitialElements()
def checkPosition():
if (snake.contains(snack)) == True:
print("Eated snack")
#Initial game loop
while run:
pygame.time.delay(100)
screen.fill((0, 0, 0))
# If quit
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
#Controls
keys = pygame.key.get_pressed()
if keys[pygame.K_RIGHT]:
x += vel
if keys[pygame.K_LEFT]:
x -= vel
if keys[pygame.K_UP]:
y -= vel
if keys[pygame.K_DOWN]:
y += vel
snake, snack = drawInitialElements()
checkPosition()
pygame.display.update()
pygame.quit()

Related

How to add a background and simple square as a character for a single screen platformer in pygame?

I’ve tried adding a background for the game, but as it pops up a second later it goes away It is white and everything else with the background is fine, but this is the only issue. Also, I tried to make a square to use as a character but it just won’t pop up.
import pygame, sys
from pygame.locals import QUIT
background_colour = (255, 255, 255)
BLUE = (0, 0, 255)
RED = (255, 0, 0)
(width, height) = (900, 450)
screen = pygame.display.set_mode((width, height))
screen.fill(background_colour)
pygame.display.flip()
pygame.display.update()
pygame.init()
dt = 0
x = 30
y = 30
w = 30
h = 30
a = 30
e = 30
l = 30
k = 30
def draw():
square = pygame.draw.rect(screen, RED, pygame.Rect(30, 30, 60, 60), 2)
pygame.display.flip()
def screen_bound():
global x
global y
global w
global h
global a
global e
global l
global k
# hit right wall
if ((x+w) > width):
x = width - w
# hit floor
if ((y+h) > height):
y = height - h
# hit left wall
if (x < 0):
x = 0
# hit roof
if (y < 0):
y = 0
def movement():
global x
global y
GRAVITY = .8
keys = pygame.key.get_pressed()
if keys[pygame.K_w]:
y = y - (.5*dt)
if keys[pygame.K_s]:
y = y + (.5*dt)
y = y = GRAVITY
def handle_events():
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN:
pass
def start():
draw()
movement()
screen_bound()
handle_events()
You need to implement an application loop where you move the objects and redraw the scene in each frame. The typical PyGame application loop has to:
limit the frames per second to limit CPU usage with pygame.time.Clock.tick
handle the events by calling either pygame.event.pump() or pygame.event.get().
update the game states and positions of objects dependent on the input events and time (respectively frames)
clear the entire display or draw the background
draw the entire scene (blit all the objects)
update the display by calling either pygame.display.update() or pygame.display.flip()
import pygame
pygame.init()
window = pygame.display.set_mode((300, 300))
clock = pygame.time.Clock()
background = pygame.Surface(window.get_size())
ts, w, h, c1, c2 = 50, *background.get_size(), (128, 128, 128), (64, 64, 64)
tiles = [((x*ts, y*ts, ts, ts), c1 if (x+y) % 2 == 0 else c2) for x in range((w+ts-1)//ts) for y in range((h+ts-1)//ts)]
[pygame.draw.rect(background, color, rect) for rect, color in tiles]
rect = pygame.Rect(0, 0, 20, 20)
rect.center = window.get_rect().center
speed = 5
# main application loop
run = True
while run:
# limit frames per second
clock.tick(100)
# event loop
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
# update the game states and positions of objects dependent on the input
keys = pygame.key.get_pressed()
rect.x += (keys[pygame.K_RIGHT] - keys[pygame.K_LEFT]) * speed
rect.y += (keys[pygame.K_DOWN] - keys[pygame.K_UP]) * speed
border_rect = window.get_rect()
rect.clamp_ip(border_rect)
# clear the display and draw background
window.blit(background, (0, 0))
# draw the scene
pygame.draw.rect(window, (255, 0, 0), rect)
# update the display
pygame.display.flip()
pygame.quit()
exit()

My Pygame sprite won't appear. What's wrong with my code?

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

Collision for Pygame Game Map

I am trying to make a maze game in Pygame but am unable to achieve collision for the 1 (maze wall) in the array. I tried to put the collision detection in the loop creating the map but it is not working. I also put the collision detection in the main loop but only the top left rect detected the collision, not all the 1 rects. How would I go about fixing this? Thank you!
import pygame
pygame.init()
screen = pygame.display.set_mode((700,700))
pygame.display.set_caption("Game")
speed = 20
x = 200
y = 600
def game_map():
global rect_one
surface = pygame.Surface((100, 100), pygame.SRCALPHA)
rect_one = pygame.draw.rect(surface, (0, 0, 255), (0, 0, 50, 50))
global rect_two
surface_one = pygame.Surface((80, 80), pygame.SRCALPHA)
rect_two = pygame.draw.rect(surface_one, (255, 255, 255), (0, 0, 50, 50))
tileX = 0
tileY = 0
global tile_list
tile_list = []
map = [
[1,1,1,1,1,1,1,1,1,1,1,1,1],
[1,0,0,0,1,0,1,0,0,0,0,0,1],
[1,0,1,0,0,0,1,0,1,1,1,0,1],
[1,0,0,0,1,1,1,0,0,0,0,0,1],
[1,0,1,0,0,0,0,0,1,1,1,0,1],
[1,0,1,0,1,1,1,0,1,0,0,0,1],
[1,0,1,0,1,0,0,0,1,1,1,0,1],
[1,0,1,0,1,1,1,0,1,0,1,0,1],
[1,0,0,0,0,0,0,0,0,0,1,0,1],
[1,1,1,1,1,1,1,1,1,1,1,1,1]
]
for y, row in enumerate(map):
tileX = 0
for x, cell in enumerate(row):
image = surface if cell == 1 else surface_one
screen.blit(image, [x*50, y*50])
tile_list.append(rect_one)
pygame.display.update()
def player():
player = pygame.draw.rect(screen, (255,0,0), (x, y, 20, 20))
for i in tile_list:
if player.colliderect(i):
print("hello")
loop = True
while loop:
pygame.time.delay(100)
for event in pygame.event.get():
if event.type == pygame.QUIT:
loop = False
#player controls
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
x -= speed
if keys[pygame.K_RIGHT]:
x += speed
if keys[pygame.K_UP]:
y -= speed
if keys[pygame.K_DOWN]:
y += speed
screen.fill((255,255,255))
game_map()
player()
pygame.display.update()
pygame.quit()
Your tile_list only contains one Rect multiple times.
I simplified your code a little bit and use a Rect with the correct coordinates for each 1 in your map. Also note the comments:
import pygame
pygame.init()
screen = pygame.display.set_mode((700,700))
pygame.display.set_caption("Game")
speed = 10
player_x = 200
player_y = 600
# Use a constant. There's not need to make big Surfaces and then draw a smaller rect on them to create the map.
TILESIZE = 50
tile_list = []
map = [
[1,1,1,1,1,1,1,1,1,1,1,1,1],
[1,0,0,0,1,0,1,0,0,0,0,0,1],
[1,0,1,0,0,0,1,0,1,1,1,0,1],
[1,0,0,0,1,1,1,0,0,0,0,0,1],
[1,0,1,0,0,0,0,0,1,1,1,0,1],
[1,0,1,0,1,1,1,0,1,0,0,0,1],
[1,0,1,0,1,0,0,0,1,1,1,0,1],
[1,0,1,0,1,1,1,0,1,0,1,0,1],
[1,0,0,0,0,0,0,0,0,0,1,0,1],
[1,1,1,1,1,1,1,1,1,1,1,1,1]
]
# let's create a single Surface for the map and reuse that
grid = pygame.Surface((len(map[0]) * TILESIZE, len(map) * TILESIZE), pygame.SRCALPHA)
for y, row in enumerate(map):
for x, cell in enumerate(row):
# if we want a wall, we draw it on the new Surface
# also, we store the Rect in the tile_list so collision detection works
if cell:
rect = pygame.draw.rect(grid, 'blue', (x*TILESIZE, y*TILESIZE, TILESIZE, TILESIZE))
tile_list.append(rect)
loop = True
clock = pygame.time.Clock()
while loop:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
loop = False
#player controls
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
player_x -= speed
if keys[pygame.K_RIGHT]:
player_x += speed
if keys[pygame.K_UP]:
player_y -= speed
if keys[pygame.K_DOWN]:
player_y += speed
screen.fill((255,255,255))
# draw the map surface to the screen
screen.blit(grid, (0 ,0))
player = pygame.draw.rect(screen, (255,0,0), (player_x, player_y, 20, 20))
# now collision detection works because for each 1 in the map
# there's a Rect in tile_list with the correct coordinates
for i in tile_list:
if player.colliderect(i):
print("colliding")
break
else:
print('not colliding')
pygame.display.update()
pygame.quit()
Save the position of the player before moving it:
pos = x, y
Compute the row and column after the player has moved:
row = y // 50
column = x // 50
Reset the player's position if the new position is on a wall:
if map[row][column] == 1:
x, y = pos
Additionally you have to move the map variable to global namespace. The speed should a integral divider of the tile size. Change the starting position to a position in the grid:
speed = 25
x = 50
y = 50
Complete code:
import pygame
pygame.init()
screen = pygame.display.set_mode((700,700))
pygame.display.set_caption("Game")
speed = 25
x = 50
y = 50
map = [
[1,1,1,1,1,1,1,1,1,1,1,1,1],
[1,0,0,0,1,0,1,0,0,0,0,0,1],
[1,0,1,0,0,0,1,0,1,1,1,0,1],
[1,0,0,0,1,1,1,0,0,0,0,0,1],
[1,0,1,0,0,0,0,0,1,1,1,0,1],
[1,0,1,0,1,1,1,0,1,0,0,0,1],
[1,0,1,0,1,0,0,0,1,1,1,0,1],
[1,0,1,0,1,1,1,0,1,0,1,0,1],
[1,0,0,0,0,0,0,0,0,0,1,0,1],
[1,1,1,1,1,1,1,1,1,1,1,1,1]
]
def game_map():
global rect_one
surface = pygame.Surface((100, 100), pygame.SRCALPHA)
rect_one = pygame.draw.rect(surface, (0, 0, 255), (0, 0, 50, 50))
global rect_two
surface_one = pygame.Surface((80, 80), pygame.SRCALPHA)
rect_two = pygame.draw.rect(surface_one, (255, 255, 255), (0, 0, 50, 50))
tileX = 0
tileY = 0
for y, row in enumerate(map):
tileX = 0
for x, cell in enumerate(row):
image = surface if cell == 1 else surface_one
screen.blit(image, [x*50, y*50])
pygame.display.update()
def player():
player = pygame.draw.rect(screen, (255,0,0), (x, y, 25, 25))
loop = True
while loop:
pygame.time.delay(100)
for event in pygame.event.get():
if event.type == pygame.QUIT:
loop = False
#player controls
keys = pygame.key.get_pressed()
pos = x, y
if keys[pygame.K_LEFT]:
x -= speed
if keys[pygame.K_RIGHT]:
x += speed
if keys[pygame.K_UP]:
y -= speed
if keys[pygame.K_DOWN]:
y += speed
row = y // 50
column = x // 50
if map[row][column] == 1:
x, y = pos
screen.fill((255,255,255))
game_map()
player()
pygame.display.update()
pygame.quit()

how to generate random rectangles in a pygame and make them move like flappy bird?

I am a python beginner. I want to recreate chrome dino game. the random rectangle won't stop and the loop runs forever...please help me to stop the loop and make rectangles move.
Code:
import pygame
import random
pygame.init()
win = pygame.display.set_mode((500, 500))
#red rectangle(dino)
x = 20
y = 400
width = 30
height = 42
gravity = 5
vel = 18
black = (0, 0, 0)
#ground
start_pos = [0, 470]
end_pos = [500, 470]
#cactus
x1 = 20
y1 = 30
white = (2, 200, 200)
run = True
clock = pygame.time.Clock()
while run:
clock.tick(30)
pygame.time.delay(10)
win.fill(black)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
#random rectangle generation
for i in range(1):
width2 = random.randint(25, 25)
height2 = random.randint(60, 60)
top = random.randint(412, 412)
left = random.randint(300, 800)
rect = pygame.draw.rect(win, white, (left, top, width2,height2))
keys = pygame.key.get_pressed()
if keys[pygame.K_UP]:
y = y - vel
else:
y = min(428, y + gravity)
pygame.draw.rect(win, (255, 0, 0), (x, y, width, height))
pygame.draw.line(win, white, start_pos, end_pos, 2)
pygame.display.update()
pygame.display.flip()
pygame.quit()
pygame.draw.rect() des not "generate" a rectangle, it draws a rectangle on a surface.
pygame.Rect is a rectangle object. Create an instance of pygame.Rect before the main application loop:
obstracle = pygame.Rect(500, random.randint(0, 412), 25, 60)
Change the position of the rectangle:
obstracle.x -= 3
if obstracle.right <= 0:
obstracle.y = random.randint(0, 412)
And draw the rectangle to the window surface:
pygame.draw.rect(win, white, obstracle)
Example:
import pygame
import random
pygame.init()
win = pygame.display.set_mode((500, 500))
start_pos = [0, 470]
end_pos = [500, 470]
gravity = 5
vel = 18
black = (0, 0, 0)
white = (2, 200, 200)
hit = 0
dino = pygame.Rect(20, 400, 30, 40)
obstracles = []
number = 5
for i in range(number):
ox = 500 + i * 500 // number
oy = random.randint(0, 412)
obstracles.append(pygame.Rect(ox, oy, 25, 60))
run = True
clock = pygame.time.Clock()
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
keys = pygame.key.get_pressed()
if keys[pygame.K_UP]:
dino.y -= vel
else:
dino.y = min(428, dino.y + gravity)
for obstracle in obstracles:
obstracle.x -= 3
if obstracle.right <= 0:
obstracle.x = 500
obstracle.y = random.randint(0, 412)
if dino.colliderect(obstracle):
hit += 1
win.fill(black)
color = (min(hit, 255), max(255-hit, 0), 0)
pygame.draw.rect(win, color, dino)
for obstracle in obstracles:
pygame.draw.rect(win, white, obstracle)
pygame.draw.line(win, white, start_pos, end_pos, 2)
pygame.display.update()
pygame.quit()

How do I make player_1 move with keys?

I want to make a Pong game in Python. I already have the windows and the player models.
I tried to make it with
if keys[pygame.K_LEFT]:
x -= speed
if keys[pygame.K_LEFT]:
x += speed
this is my whole code:
import pygame
from pygame import *
import math
import random
clock = pygame.time.Clock() # fps
pygame.init() # start
title = pygame.display.set_caption("Pong")
width = 640
height = 480
screen = pygame.display.set_mode((width, height)) # screen
running = True
speed = 10
white = (255, 255, 255)
x = 120
y = 5
player_1 = pygame.draw.rect(screen, white, (240, 430, x, y))
player_2 = pygame.draw.rect(screen, white, (240, 40, x, y))
pong = pygame.draw.circle(screen, white, (300, 235), 4)
pygame.display.update()
fps = clock.tick(60)
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
x -= speed
if keys[pygame.K_LEFT]:
x += speed
while 1:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
running = False
I wanted to make the lower player to move with the arrow keys but nothing happens at all.
Put
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
x -= speed
if keys[pygame.K_LEFT]:
x += speed
player_1 = pygame.draw.rect(screen, white, (240, 430, x, y))
player_2 = pygame.draw.rect(screen, white, (240, 40, x, y))
pong = pygame.draw.circle(screen, white, (300, 235), 4)
pygame.display.update()
fps = clock.tick(60)
within the while loop.
Also, change
if keys[pygame.K_LEFT]:
x += speed
to
if keys[pygame.K_RIGHT]:
x += speed

Categories

Resources