Pygame doesn't blit images onto canvas - python

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)

Related

transparent bits in pygame mask are black instead of being transparent

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()

pygame, how can I use sprite.Group.draw() to draw all sprites?

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

Pygame Screen Won't Erase Before Each Loop

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

Why is this sprite not being displayed on the screen?

I made a class called Player that has an image called player.img that is not being displayed on the screen. When I run the code, it just displays a black screen with nothing on it. I'm trying to learn how to make classes so sorry if this is really messed up.
import pygame
import sys
from pygame.locals import *
#starts the program
pygame.init()
white = (255, 255, 255)
black = (0, 0, 0)
red = (255, 0, 0)
blue = (0, 0, 255)
green = (0, 255, 0)
yellow = (255, 255, 153)
#creates a window of 800x600
setDisplay = pygame.display.set_mode((800, 600))
pygame.display.set_caption('Menu')
img = pygame.image.load('C:\\Users\\Ben\\Documents\\sprite.png')
class Player(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.img = pygame.image.load('C:\\Users\\Ben\\Documents\\sprite.png').convert()
self.imgx = 10
self.imgy = 10
self.screen = pygame.display.get_surface()
def draw(self):
self.screen.blit(self.img)
def load(self, filename):
self.img = pygame.image.load('C:\\Users\\Ben\\Documents\\sprite.png').convert_alpha()
player = Player()
def gameLoop():
imgx = 10
imgy = 10
lead_x_change = 0
lead_y_change = 0
move_variable = 5
while True:
screen.blit(player.img, [player.imgx,player.imgy])
for event in pygame.event.get():
#print (event)
if event.type == QUIT:
pygame.quit()
sys.exit()
gameLoop()
I can see two issues with your current code.
You never flip your display. This is generally performed after all blitting is complete for a given frame. For example your while loop would look like this:
while True:
screen.blit(player.img, [player.imgx,player.imgy])
pygame.display.flip()
for event in pygame.event.get():
#print (event)
if event.type == QUIT:
pygame.quit()
sys.exit()
Your gameLoop() function doesn't know what "screen" is. You will need to specify it somewhere. For example, right before your while loop starts would be fine.
screen = pygame.display.get_surface()
while True:
screen.blit....
You will definitely want to restructure some things. If I have some time later I will add to this answer my recommendations for how to restructure. But for now, these two adjustments should get your program running.

Can't draw rect in python pygame

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)

Categories

Resources