Failing to blit image to screen - python

I am attempting to use pygame to draw a map to a screen, but cannot understand why it won't. I'm not getting a traceback. The screen is initializing, then the image is not being drawn. I've attempted with other .bmp images with the same result, so there must be something in my code that is not ordered/written correctly.
Here is the main module of the game:
import pygame
import sys
from board import Board
def run_game():
#Launch the screen.
screen_size = (1200, 700)
screen = pygame.display.set_mode(screen_size)
pygame.display.set_caption('Horde')
#Draw the board.
game_board = Board(screen)
game_board.blit_board()
#Body of the game.
flag = True
while flag == True:
game_board.update_board()
run_game()
Here is the board module that you see being used. Specifically, the blit_board() function, which is silently failing to draw the map.bmp file I ask it to (file is in the same directory).
import pygame
import sys
class Board():
def __init__(self, screen):
"""Initialize the board and set its starting position"""
self.screen = screen
#Load the board image and get its rect.
self.image = pygame.image.load('coll.bmp')
self.rect = self.image.get_rect()
self.screen_rect = screen.get_rect()
#Start the board image at the center of the screen.
self.rect.centerx = self.screen_rect.centerx
self.rect.centery = self.screen_rect.centery
def blit_board(self):
"""Draw the board on the screen."""
self.screen.blit(self.image, self.rect)
def update_board(self):
"""Updates the map, however and whenever needed."""
#Listens for the user to click the 'x' to exit.
for event in pygame.event.get():
if event.type == pygame.QUIT: sys.exit()
#Re-draws the map.
self.blit_board()
All I get is a black screen. Why will the map.bmp image not draw?

As Dan MaĊĦek stated you need to tell PyGame to update the display after drawing the image.
To achieve this simply modify your 'board' loop to the following:
def update_board(self):
"""Updates the map, however and whenever needed."""
#Listens for the user to click the 'x' to exit.
for event in pygame.event.get():
if event.type == pygame.QUIT: sys.exit()
#Re-draws the map.
self.blit_board()
pygame.display.update()

Related

pygame.display.update causing flickering or not showing anything

In my game I am trying to make it so when you walk into a object, it displays an image.
I'm pretty sure that pygame.display.update() is being called every frame because otherwise the game would be perfectly still.
However when I draw my new rect upon collision it doesn't appear, unless I put another pygame.display.update(rect) with it after it being drawn. This means that update is being called twice at one time, in the main game loop and after drawing the rect. This causes the rect (which has been drawn now) to flicker because of the multiple update calls.
I cannot figure it out why it doesn't get drawn without the second update call.
Main game loop call:
def events(self):
#game loop events
for event in pygame.event.get():
if event.type == pygame.QUIT:
self.playing = False
self.running = False
def update(self):
self.all_sprites.update()
def main(self):
while self.playing:
self.events()
self.update()
self.draw()
self.running = False
def draw(self):
self.screen.fill(black)
self.all_sprites.draw(self.screen)
self.clock.tick(FPS)
pygame.display.update()
#create game instance
g= Game()
g.new()
while g.running:
#main gameloop
g.main()
pygame.quit()
sys.exit()
Here is when I call to draw the rect after collision with my object:
def update(self):
self.hitbox.center = numpy.add(self.rect.center,(8,22))
self.interactionhitbox.center = numpy.add(self.rect.center, (8,16))
if(self.showPopup):
# Initialwzng Color
color = (255,0,0)
# Drawing Rectangle
rect = pygame.Rect((0,0,60,60))
pygame.display.update(rect) # WITHOUT THIS LINE IT DOES NOT GET DRAWN, WITH IT IT FLICKERS
pygame.draw.rect(self.game.screen, color, rect)
So basically with the second pygame.display.update(rect) call it appears but flickers, and without it it doesn't show up at all
Any help is appreciated sorry if this is a bad question or not formatted right I haven't been here since 2017!
The rectangle is not drawn because the screen will later be cleared with self.screen.fill(black) later. You must draw the rectangle after self.screen.fill(black) and before pygame.display.update().
Create 2 images and choose the image to be drawn in update:
def __init__(self, ...)
# [...]
self.image = ...
self.original_image = self.image
self.image_and_rect = self.image.copy()
pygame.draw.rect(self.image_and_rect, (255,0,0), self.image_and_rect.get_rect(), 5)
def update(self):
self.hitbox.center = numpy.add(self.rect.center,(8,22))
self.interactionhitbox.center = numpy.add(self.rect.center, (8,16))
if self.showPopup:
self.image = self.image_and_rect
else:
self.image = self.original_image

Pygame.image.load Image wont be added to the screen

I've tried everything to fix this, my code runs and a screen is shown but the image is not on the screen.
so far I've tried:
putting an absolute path when entering the image in pygame.image.load
trying os.join.path method (file cannot be found error)
And loads of other things
-How after trying everything, and closely following the book, i cant get it to work?
my code from alien_invasion.py:
import sys
import pygame
from settings import Settings
from ship import Ship
class AlienInvasion:
def __init__(self):
pygame.init()
self.settings = Settings()
self.screen = pygame.display.set_mode((self.settings.screen_width, self.settings.screen_height))
pygame.display.set_caption("Alien Invasion")
self.bg_color = (255, 0, 0)
self.ship = Ship(self)
def run_game(self):
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
self.screen.fill(self.settings.bg_color)
pygame.display.flip()
self.screen.fill(self.bg_color)
self.ship.blitme()
if __name__ == '__main__':
ai = AlienInvasion()
ai.run_game()
code from ship.py:
import pygame
class Ship:
def __init__(self, ai_game):
self.screen = ai_game.screen
self.screen_rect = ai_game.screen.get_rect()
self.image = pygame.image.load('C:/Users/Documents/Python Learning/python crash course lessons/Alien Invasion/ship1.bmp')
self.rect = self.image.get_rect()
self.rect.midbottom = self.screen_rect.midbottom
def blitme(self):
self.screen.blit(self.image, self.rect)
code from settings.py
class Settings:
"""A class to store all settings for Alien Invasion."""
def __init__(self):
"""Initialize the game's settings."""
# Screen settings
self.screen_width = 1200
self.screen_height = 800
self.bg_color = (230, 230, 230)
I really want to find the solution to this otherwise I will remain stuck since none of the solutions to other people with the same problem has solved my problem...
the program works, there are no errors shown the image just doesn't load to the image to the screen.
thank you if you helped
The image is not shown, because the display is not updated after drawing the image. Update the display after drawing the ship:
class AlienInvasion:
# [...]
def run_game(self):
clock = pygame.time.Clock()
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
self.screen.fill(self.bg_color)
self.ship.blitme()
pygame.display.flip()
clock.tick(60)
pygame.quit()
sys.exit()
The typical PyGame application loop has to:
handle the events by 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 either pygame.display.update() or pygame.display.flip()
limit frames per second to limit CPU usage with pygame.time.Clock.tick

How to extend ships' boundary when screen is resized Python Pygame?

I am trying to recreate the classic "Space Invaders" game and I want to allow anyone playing the game to resize their window using the box icon (restore / maximise) next to the close window button on the window. I have enabled the pygame.resizeable flag in the code. I am able to toggle the screen sizes using the box button and the background changes scale as it should. However, I am finding it a challenge to allow the ship to extend its boundary to the newly found "space".
The code is split into different modules according to their task. And so far I have the main game module, a settings module, game functions module, ship and bullets module respectively.
I have created a separate function (check_screen_resized(event,ship)) in the "game functions module" to respond to the pygame.VIDEORESIZE event.The function first toggles a "flag" (self.screen_resized = True) then sets the new resolution which is stored in the variable "screen" to self.screen_res = screen.
In the "ship module", when self.screen_resized = True, an "if" statement in the "update function" is activated to change the screen resolution. I am calling this "update" function in the main game module's while loop.
But my approach is not working. Can someone help me with this problem?
# MAIN GAME MODULE
---------------------------------------------------------------------------------------------
import pygame
from pygame.sprite import Group
import game_functions as gme_func
from settings import Settings
from ship import Ship
def run_game():
"""Initialise pygame, settings, ship and screen object."""
pygame.init()
ai_settings = Settings()
# screen settings.
screen = pygame.display.set_mode(
(ai_settings.screen_width, ai_settings.screen_height), pygame.RESIZABLE
)
pygame.display.set_icon(ai_settings.icon)
pygame.display.set_caption("Alien Invasion")
# make a ship.
ship = Ship(screen, ai_settings)
# store bullets in a group.
bullets = Group()
# the main game loop.
while True:
# listen to keyboard and mouse events.
gme_func.check_events(ai_settings, screen, ship, bullets)
# update the ship's movement.
ship.update()
# update the bullet position and delete disappeared bullets.
gme_func.update_bullets(bullets)
# redraw the screen during each pass through the loop.
# make the most recently drawn screen visible.
gme_func.update_screen(screen, ai_settings, ship, bullets)
run_game()
---------------------------------------------------------------------------------------------
# GAME FUNCTIONS MODULE
---------------------------------------------------------------------------------------------
import sys
import pygame
from bullet import Bullet
*****
*****
def check_screen_resized(event, ship):
"""Update screen surfaces with resolution change."""
screen = pygame.display.set_mode((event.w, event.h), pygame.RESIZABLE)
ship.screen_resized = True
ship.screen_res = screen
def check_events(ai_settings, screen, ship, bullets):
"""Listen to keyboard and mouse events."""
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
# moving the ship
elif event.type == pygame.KEYDOWN:
check_keydown_events(event, ai_settings, screen, ship, bullets)
elif event.type == pygame.KEYUP:
check_keyup_events(event, ship)
# resize the game window.
elif event.type == pygame.VIDEORESIZE:
check_screen_resized(event, ship)
*****
*****
---------------------------------------------------------------------------------------------
# SHIP MODULE
---------------------------------------------------------------------------------------------
import pygame
class Ship:
"""A class that creates a ship for the Alien Invasion game."""
def __init__(self, screen, ai_settings):
"""Initialise the ship and set its starting position."""
self.ai_settings = ai_settings
self.screen = screen
self.screen_rect = self.screen.get_rect()
# load the ship image and get its rectangle.
self.image = pygame.image.load(alien_invasion\images\ship3.png").convert_alpha()
self.ship_rect = self.image.get_rect()
# start each new ship at the bottom centre of the screen.
self.ship_rect.centerx = self.screen_rect.centerx
self.ship_rect.bottom = self.screen_rect.bottom
# convert the centerx and centery values to decimal.
self.centerx = float(self.ship_rect.centerx)
self.centery = float(self.ship_rect.centery)
# movement flags.
self.moving_right = False
self.moving_left = False
self.moving_up = False
self.moving_down = False
# screen resized flag.
self.screen_resized = False
self.screen_res = None
def update(self):
"""Update the ship's position based on the movement flags."""
if self.moving_right and self.ship_rect.right < self.screen_rect.right:
self.centerx += self.ai_settings.ship_speed_factor
if self.moving_left and self.ship_rect.left > self.screen_rect.left:
self.centerx -= self.ai_settings.ship_speed_factor
if self.moving_up and self.ship_rect.top > self.screen_rect.top:
self.centery -= self.ai_settings.ship_speed_factor
if self.moving_down and self.ship_rect.bottom < self.screen_rect.bottom:
self.centery += self.ai_settings.ship_speed_factor
# update the rectangle position from centerx and centery.
self.ship_rect.centerx = self.centerx
self.ship_rect.centery = self.centery
# responding to screen resizing.
if self.screen_resized:
self.screen = self.screen_res
def blit_ship(self):
"""Draw the ship at its current location."""
self.screen.blit(self.image, self.ship_rect)
---------------------------------------------------------------------------------------------
If I'm not mistaken, the following code is a basic snippet that starts a resizable screen and prints its current height and width. The following should work:
import pygame
pygame.init()
# resizable screen
win = pygame.display.set_mode((1000,500), pygame.RESIZABLE)
pygame.display.set_caption("First Game")
run = True
while run:
pygame.time.delay(100)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
keys = pygame.key.get_pressed()
win.fill((0,0,0))
pygame.display.update()
# printing the width and height - we get the pygame.display.get_surface() object, and
# get the width and height with the get_width() and get_height() funcs that the
# returned obj has
print(pygame.display.get_surface().get_width(), pygame.display.get_surface().get_height())
pygame.quit()
You can put this code snippet to use by getting updated variables containing the current screen width and height, thus telling you where the real border is.

How to convert the background color of image to match the color of Pygame window?

What I need to do is match the color of the image background with the color of Pygame windows.
But the background of image and pygame window didn't match. It looks something like this
ship.py
import pygame
class Ship:
""" A class to manage the ship. """
def __init__(self, ai_game):
""" Initialize the ship and the starting position. """
self.screen = ai_game.screen
self.screen_rect = ai_game.screen.get_rect()
# Load the ship image and get its rect.
self.image = pygame.image.load('images/ship.bmp')
self.rect = self.image.get_rect()
# Start each new ship at the bottom center of the screen.
self.rect.midbottom = self.screen_rect.midbottom
def blitme(self):
""" Draw ship at its current location. """
self.screen.blit(self.image, self.rect)
alieninvasion.py
import sys
import pygame
from ship import Ship
class AlienInvasion:
"""Overall class to manage game assets and behavior."""
def __init__(self):
"""Initialize the game, and create game resources."""
pygame.init()
self.screen = pygame.display.set_mode((1200, 800))
pygame.display.set_caption("Alien Invasion")
# Set background colour
self.bg_color = (0, 0, 255)
self.ship = Ship(self)
def run_game(self):
"""Start the main loop for the game."""
while True:
# Watch for keyboard and mouse events.
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
# Redraw the screen during each pass through the loop.
self.screen.fill(self.bg_color)
self.ship.blitme()
# Make the most recently drawn screen visible.
pygame.display.flip()
if __name__ == '__main__':
# Make a game instance, and run the game.
ai = AlienInvasion()
ai.run_game()
I tried the answers from this discussion but I couldn't fix it.
I couldn't understand how to use image.convert_alpha() and image.set_colorkey() and using them in ship.py did not show any changes for me.
Note: ship.py is the class to make changes on ship while alieninvasion.py is the main file.
You don't need to change the background color of the image to the background color of the window, but make the background of the image transparent.
Set the transparent colorkey by pygame.Surface.set_colorkey:
Set the current color key for the Surface. When blitting this Surface onto a destination, any pixels that have the same color as the colorkey will be transparent.
Note, all the background has to have exactly the same color. In your case the background color seems to be gray (230, 230, 230):
self.image = pygame.image.load('images/ship.bmp').convert()
self.image.set_colorkey((230, 230, 230))
Another option wound be to create a new image (you need to draw it in a painting application) with per pixel alpha (e.g. PNG) and a transparent background:
self.image = pygame.image.load('images/ship.png').convert_alpha()

Pygame : player sprite that disappears behind the background

So there you go, I wanted to experiment a little pygame but I find myself stuck.
Context
I created a small sprite (with Piskelapp) that represents the player and looks like:
player.png
then add my background in jpg format. However when launching the game, my sprite is cut by the background as follows:
The ship is not placed in front of the background and more I go up it, more it disappears behind the background...
Here is my code:
import pygame
pygame.init()
# class user
class Player(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.pv = 100
self.__max_health = 100
self.attack = 2
self.velocity = 5
self.image = pygame.image.load('assets/player.png')
self.rect = self.image.get_rect()
self.rect.x = 400
self.rect.y = 500
# open game window
pygame.display.set_caption("Rocket 'n' Rock")
screen = pygame.display.set_mode((1080, 720))
# background import
bg = pygame.image.load('assets/bg.jpg')
# load player
player = Player()
running = True
# game mainloop
while running:
# bg apply
screen.blit(bg, (0,-400))
# screen update
pygame.display.flip()
# player image apply
screen.blit(player.image, player.rect)
# if player close the window
for event in pygame.event.get():
# *close event
if event.type == pygame.QUIT:
running = False
pygame.quit()
print("close game")
anyone have a tip? I'm wondering if it's not a file format problem?
thank you for your time
In you game mainloop, you should put:
screen.blit(player.image, player.rect)
before:
pygame.display.flip()

Categories

Resources