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)
Related
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()
I have a program where it fills in the bits of a mask that are overlapped from another mask, but when I blit the mask of the overlapping bits onto the screen, the transparent bits are fully black for some reason? The program works as intended and I've tried converting the surface for the overlapping bits to per pixel alpha but the transparent bits are black
example gif
import pygame
import sprites
SCREEN_HEIGHT, SCREEN_WIDTH = 800, 800
running = True
pygame.init()
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
clock = pygame.time.Clock()
player = sprites.Block((100, 100))
block2 = sprites.Block((100, 100))
blocks = pygame.sprite.Group(block2)
block2.rect.topleft = 150, 150
block2.image.fill((0, 255, 0))
while running:
events = pygame.event.get()
screen.fill((100, 100, 100))
for event in events:
if event.type == pygame.QUIT:
running = False
player.move(screen.get_rect())
screen.blit(player.image, player.rect)
blocks.draw(screen)
for block in blocks:
offset = (player.rect.x - block.rect.x, player.rect.y - block.rect.y)
colliding_bits = player.mask.overlap_mask(block.mask, offset)
colliding_bits_image = colliding_bits.to_surface(setcolor=(0, 255, 0))
screen.blit(colliding_bits_image, block.rect)
clock.tick(144)
pygame.display.flip()
code containing the sprite classes:
import pygame
class Block(pygame.sprite.Sprite):
def __init__(self, size):
self.image = pygame.image.load("flappy_bird.png")
self.rect = self.image.get_rect()
self.mask = pygame.mask.from_surface(self.image)
self.speed = 1
super().__init__()
def move(self, screen_rect):
pressed_keys = pygame.key.get_pressed()
if pressed_keys[pygame.K_w]:
self.rect.move_ip(0, -self.speed)
if pressed_keys[pygame.K_s]:
self.rect.move_ip(0, self.speed)
if pressed_keys[pygame.K_a]:
self.rect.move_ip(-self.speed, 0)
if pressed_keys[pygame.K_d]:
self.rect.move_ip(self.speed, 0)
self.rect.clamp_ip(screen_rect)
I added the unsetcolor attribute to the to_surface method and removed the line blocks.draw(screen) and it seems to produce the desired result :
from math import fabs
import pygame
import sprites
SCREEN_HEIGHT, SCREEN_WIDTH = 800, 800
running = True
pygame.init()
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
clock = pygame.time.Clock()
player = sprites.Block((100, 100))
block2 = sprites.Block((100, 100))
blocks = pygame.sprite.Group(block2)
block2.rect.topleft = 150, 150
block2.image.fill((0, 255, 0))
while running:
events = pygame.event.get()
screen.fill((100, 100, 100))
for event in events:
if event.type == pygame.QUIT:
running = False
player.move(screen.get_rect())
screen.blit(player.image, player.rect)
for block in blocks:
offset = (player.rect.x - block.rect.x, player.rect.y - block.rect.y)
colliding_bits = player.mask.overlap_mask(block.mask, offset)
colliding_bits_image = colliding_bits.to_surface(setcolor=(0, 255, 0, 255), unsetcolor=(0, 0, 0, 0))
screen.blit(colliding_bits_image, block.rect)
clock.tick(144)
pygame.display.flip()
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()
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)
When I run the following code, I get this error
reindeer.moveUp(screen)
File "C:\Users\adity\Desktop\Python\CPT.py", line 38, in moveUp
self.y = self.y - 3
AttributeError: 'pygame.Surface' object has no attribute 'y'
I want to move the rectangle up or down every time the user presses w or s using methods in the reindeer class. Is it because of something wrong with the methods?
Why does the program not know what y is? I assigned it in the list of attributes for the class.
import pygame
# Define some colors
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
GREEN = (0, 255, 0)
RED = (255, 0, 0)
pygame.init()
# Set the width and height of the screen [width, height]
size = (1000, 800)
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()
screen.fill(WHITE)
class Reindeer():
def __init__(self):
self.color = (255,0,0)
self.y_move = 3
self.x = 100
self.y = 100
self.width = 100
self.length = 100
def draw(screen, self):
pygame.draw.rect(screen, color, [self.x,self.y,self.width,self.length], 0)
def moveDown(screen, self):
self.y = self.y + 3
pygame.draw.rect(screen, self.color, [self.x,self.y,self.width, self.length], 0)
def moveUp(screen, self):
self.y = self.y - 3
pygame.draw.rect(screen, self.color, [self.x,self.y,self.width,self.length], 0)
reindeer = Reindeer()
# -------- Main Program Loop -----------
while not done:
# --- Main event loop
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_w:
reindeer.moveDown(screen)
elif event.key == pygame.K_s:
reindeer.moveUp(screen)
pygame.display.flip()
clock.tick(60)
pygame.quit()
I finally dug down to it, by (sigh) reading the code. You have your method parameters in the wrong order: the first parameter is, by definition, the invoking object. Switch your method signatures:
def moveDown(self, screen):
... and the same for all others.