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