I was trying to create a simple pygame game that uses sprites, but when i compiled the code the movement seemed to have some kind of lag spikes. I did some debugging and extracted the problem into the code below. The image moves smoothly for most of a second, but then a lag spike occurs and so on.
I've seen that converting images helped a lot of people, but nothing changed for me.
import pygame, sys
class Game():
def __init__(self):
pygame.init()
self.screen = pygame.display.set_mode((1280, 720))
pygame.display.set_caption("Spaceshooter")
self.clock = pygame.time.Clock()
self.image = pygame.image.load("player.png").convert_alpha()
self.rect = self.image.get_rect()
def run(self):
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
self.screen.fill("black")
self.rect.x += 5
self.screen.blit(self.image, self.rect)
self.clock.tick(60)
pygame.display.update()
if __name__ == "__main__":
game = Game()
game.run()
Try to reduce the movement speed and increase the fps. I believe it will help you, Adam.
Related
I was following a pygame tutorial, tested to see if the player blit was working and it wasnt, checked for problems but there were none that I could find, and then I tested a .blit() directly in the game loop and that didnt work so I've been stumped for a good bit now.
player class below, "Player_Down" should be irrelevant rn since its just an image
class Player():
def __init__(self, x, y):
direction = "down"
self.image = player_down
self.rect = self.image.get_rect()
self.rect.center = (x, y)
def draw(self):
screen.blit(self.image, self.rect)
ply = Player(SCREEN_WIDTH // 2 , SCREEN_HEIGHT - 150)
Game loop with draw function called
running = True
while running:
screen.fill((83,90,83))
ply.draw()
#event handler
for event in pygame.event.get():
if event.type == pygame.QUIT:
print("Game quit via X button")
running = False
pygame.display.update()
There is no problem with the code in the question. Your suspicion that blit does not work is wrong (alos see How to draw images and sprites in pygame?). The code works fine.
However, I suggest passing the screen Surface as an argument to draw method. See the minimal and working example:
import pygame
pygame.init()
SCREEN_WIDTH, SCREEN_HEIGHT = 400, 400
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
player_down = pygame.Surface((30, 30))
player_down.fill((255, 0, 0))
class Player():
def __init__(self, x, y):
direction = "down"
self.image = player_down
self.rect = self.image.get_rect()
self.rect.center = (x, y)
def draw(self, surf):
surf.blit(self.image, self.rect)
ply = Player(SCREEN_WIDTH // 2 , SCREEN_HEIGHT - 150)
running = True
while running:
#event handler
for event in pygame.event.get():
if event.type == pygame.QUIT:
print("Game quit via X button")
running = False
screen.fill((83,90,83))
ply.draw(screen)
pygame.display.update()
pygame.quit()
exit()
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
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()
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()
I've just downloaded python 3.3.2 and pygame-1.9.2a0.win32-py3.3.msi.
I have decided to try a few tutorials on youtube and see if they work.
I have tried thenewboston's 'Game Development Tutorial - 2 - Basic Pygame Program' to see if it works. It is supposed to produce a black background and a ball that is the mouse (or so i think). It comes up with a syntax error when i try to run it, if i delete it it just produces a black pygame window. Here is the code:
bgg="bg.jpg"
ball="ball.png"
import pygame, sys
from pygame.locals import *
pygame.init()
screen=pygame.display.set_mode((540,341),0,32)
background=pygame.image.load(bgg).convert()
mouse_c=pygame.image.load(ball).convert_alpha()
while True:
for event in pygame.event.get():
if event.type ==QUIT:
pygame.quit()
sys.exit()
screen.blit(background), (0,0))
The screen.blit(bakcgorund, (0,0)) command is the problem, when it comes up with the syntax error it highlights the second bracket on the furthest right of the command. If I delete it it just shows a black pygame window. can anyone help me?
I updated your code:
import pygame
from pygame.locals import *
#about: pygame boilerplate
class GameMain():
# handles intialization of game and graphics, as well as game loop
done = False
def __init__(self, width=800, height=600):
"""Initialize PyGame window.
variables:
width, height = screen width, height
screen = main video surface, to draw on
fps_max = framerate limit to the max fps
limit_fps = boolean toggles capping FPS, to share cpu, or let it run free.
now = current time in Milliseconds. ( 1000ms = 1second)
"""
pygame.init()
# save w, h, and screen
self.width, self.height = width, height
self.screen = pygame.display.set_mode(( self.width, self.height ))
pygame.display.set_caption( "pygame tutorial code" )
self.sprite_bg = pygame.image.load("bg.jpg").convert()
self.sprite_ball = pygame.image.load("ball.png").convert_alpha()
def main_loop(self):
"""Game() main loop."""
while not self.done:
self.handle_events()
self.update()
self.draw()
def draw(self):
"""draw screen"""
self.screen.fill(Color('darkgrey'))
# draw your stuff here. sprites, gui, etc....
self.screen.blit(self.sprite_bg, (0,0))
self.screen.blit(self.sprite_ball, (100,100))
pygame.display.flip()
def update(self):
"""physics/move guys."""
pass
def handle_events(self):
"""handle events: keyboard, mouse, etc."""
events = pygame.event.get()
kmods = pygame.key.get_mods()
for event in events:
if event.type == pygame.QUIT:
self.done = True
# event: keydown
elif event.type == KEYDOWN:
if event.key == K_ESCAPE: self.done = True
if __name__ == "__main__":
game = GameMain()
game.main_loop()
Your parenthesis are unbalanced; there are 2 opening parenthesis, and 3 closing parenthesis; that is one closing parenthesis too many:
screen.blit(background), (0,0))
# -----^ ------^ ---^
You probably want to remove the closing parenthesis after background:
screen.blit(background, (0,0))