transparent bits in pygame mask are black instead of being transparent - python

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

Related

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

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 doesn't blit images onto canvas

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)

screen.blit error in Pygame

I'm trying to make arrow keys movement in pygame but screen.blit isn't working :/
it keeps coming with a error saying
>###AttributeError: 'builtin_function_or_method' object has no attribute 'blit'
here is my code:
import sys, pygame
from pygame.locals import *
pygame.init()
pygame.display.set_caption(" Arrow keys to move ")
#Colour Defintions
white = pygame.Color(255,255,255)
black = pygame.Color( 0, 0 ,0)
gray = pygame.Color(90, 90, 90)
silver = pygame.Color( 200, 200, 200)
red = pygame.Color( 200, 0 , 0)
blue = pygame.Color(0, 255, 0)
#screen size
size = width, height = 1024, 640
velocity = [5, -20]
screen = pygame.display.set_mode
sprite = pygame.image.load("sprite01.png")
spriterect = sprite.get_rect()
clock = pygame.time.Clock()
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
pressed_keys = pygame.key.get_pressed()
if pressed_keys[pygame.K_RIGHT]:
spriterect = spriterect.move(5, 0)
if pressed_keys[pygame.K_LEFT]:
spriterect = spriterect.move(-5, 0)
if pressed_keys[pygame.K_UP]:
spriterect = spriterect.move(0, 5)
if pressed_keys[pygame.K_UP]:
spriterect = spriterect.move(0, -5)
if spriterect.top < 0:
spriterect.top = 0
if spriterect.bottom > height:
spriterect.bottom = height
screen.blit(sprite(0, 0))
screen.blit(spriterect(0, 0))
pygame.display.flip()
clock.tick(120)}
You've missed the parentheses on your set_mode call, so are referencing a function rather than the return value from calling that function.
screen = pygame.display.set_mode
Should be:
screen = pygame.display.set_mode(size)

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