Why does my simple pygame lag? [duplicate] - python

This question already has answers here:
Lag when win.blit() background pygame
(2 answers)
Closed 2 years ago.
I have been making a simple python game using pygame and after I added the feature of switching guns the game started to lag. I have no idea why it is lagging. I have tried rebooting but it didn't work. The code is really short so maybe it is just my computer, but if there is anything that may help run it faster please let me know. Here is the code:
import sys, pygame, pygame.mixer
from pygame.locals import *
pygame.init()
size = width, height = 600, 400
screen = pygame.display.set_mode(size)
pygame.display.set_caption('Blue Screen of Death')
#variables
x = 100
y = 200
gun_type = "gun1"
gun = pygame.image.load("gun1.png")
gun = pygame.transform.scale(gun,(500,250))
gun_sound = pygame.mixer.Sound("gun_sound.wav")
clock = pygame.time.Clock()
while 1:
mx, my = pygame.mouse.get_pos()
for event in pygame.event.get():
if event.type == pygame.QUIT:sys.exit()
elif event.type == KEYDOWN and event.key == K_ESCAPE:
sys.exit()
elif event.type == MOUSEBUTTONDOWN:
gun_sound.play()
elif event.type == KEYDOWN and event.key == K_1:
gun = pygame.image.load("gun1.png")
gun = pygame.transform.scale(gun,(500,250))
gun_type = "gun2"
elif event.type == KEYDOWN and event.key == K_2:
gun = pygame.image.load("gun2.png")
gun = pygame.transform.scale(gun,(500,250))
gun_type = "gun2"
elif event.type == KEYDOWN and event.key == K_TAB:
if gun_type == "gun2":
gun_type = "gun2_aimed"
elif gun_type == "gun2_aimed":
gun_type = "gun2"
elif gun_type == "gun2_aimed":
gun = pygame.image.load("gun2_aimed.png")
gun = pygame.transform.scale(gun,(500,250))
#frames per second
clock.tick(60)
hallway = pygame.image.load("hallway.png")
hallway = pygame.transform.scale(hallway,(600,400))
screen.blit(hallway,(0,0))
screen.blit(gun,(mx-100,y))
pygame.display.flip()
Thanks for your help.

This is probably the most important thing you can learn in Pygame.
For many years, I've had lagging issues in Pygame. I was frustrated, and almost switched to Pyglet. My game was only running at 9 fps.
Then I found some Pygame documentation on my computer. It had some advice from David Clark, and he suggested you add .convert_alpha() at the end of all Pygame image loads. This increased my framerate to 32!
Here's the website:
https://www.pygame.org/docs/tut/newbieguide.html
I always just create a function to do it for me, so I don't have to keep typing '.convert_alpha()' too many times:
def loadify(imgname):
return pygame.image.load(imgname).convert_alpha()
Just replace pygame.image.load( to loadify( when using this function.
Have fun with Pygame!

You could try to load the images of your guns before the while loop and save a reference to them, this way you don't have to load the image on the fly every time.

Don't call pygame.image.load from your event handler.
Instead, call it on all of your resources at startup and just switch out which one you use.

Related

python pygame window wont close "not responding"

I am trying to make a python window for my game from my laptop in pygame... however when I try to close the window I get an error message saying "not responding" im not sure why that if I thought i had done everything right.... the code is below any help is needed.
Thanks!
import pygame
from sys import exit
pygame.init()
screen = pygame.display.set_mode((800,400))
clock = pygame.time.Clock()
sky_surface = pygame.image.load("bg_desert.png").convert()
snail_surface = pygame.image.load("snailWalk1.png").convert_alpha()
player_surf = pygame.image.load("p1_walk01.png")
snail_x_pos = 600
while True:
pygame.time.set_timer(snail_x_pos, 100)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
print("hello")
snail_x_pos -=4
if snail_x_pos < -100: snail_x_pos = 800
screen.blit(sky_surface,(0,0))
screen.blit(snail_surface,(snail_x_pos,350))
screen.blit(player_surf,(80, 200))
pygame.display.update()
clock.tick(60)
All problem makes
pygame.time.set_timer(snail_x_pos, 100)
which you run inside loop.
If I remove it then it closes without problem.
Every set_timer creates new timer which sends event every 100ms (again and again). If you run it in loop then you create hundreds timers.
You should run it only once - before loop - and it will repeatly send event which you can get in for-loop.
Problem is also that you use it in wrong way - you use snail position but it should user_id and time in milliseconds.
my_event_id = pygame.USEREVENT + 1
pygame.time.set_timer(my_event_id, 500) # 500ms = 0.5s
and later you can use it to move snail
elif event.type == my_event_id:
print('0.5 second')
snail_x_pos -= 4
Here my version with other changes.
I use Surfaces instead images so everyone can simply copy and run it.
I also use pygame.Rect to keep position and size - it has useful values (ie. .center to get/set center position) and functions (ie. to detect colisions). I use .left and .right to move snake to right side of window when it leaves window on left side.
import pygame
pygame.init()
screen = pygame.display.set_mode((800,400))
sky_surface = pygame.Surface((800, 100))
sky_surface.fill((0,0,255))
sky_surface_rect = sky_surface.get_rect()
snail_surface = pygame.Surface((100, 10))
snail_surface.fill((0,255,0))
snail_surface_rect = snail_surface.get_rect()
snail_surface_rect.x = 600
snail_surface_rect.y = 350
player_surf = pygame.Surface((10, 50))
player_surf.fill((255,0,0))
player_surf_rect = player_surf.get_rect()
player_surf_rect.x = 80
player_surf_rect.y = 200
clock = pygame.time.Clock()
my_event_id = pygame.USEREVENT + 1
pygame.time.set_timer(my_event_id, 500) # 500ms = 0.1s
while True:
# - events -
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
print("hello")
elif event.type == my_event_id:
print('0.5 second')
# move snake
snail_surface_rect.x -= 4
# use this event to slow down player
pressed = pygame.key.get_pressed()
if pressed[pygame.K_LEFT]:
player_surf_rect.x -= 4
elif pressed[pygame.K_RIGHT]:
player_surf_rect.x += 4
# - updates -
if snail_surface_rect.right < 0:
snail_surface_rect.left = 800
# - draw -
screen.fill((0,0,0)) # clear screen
screen.blit(sky_surface, sky_surface_rect)
screen.blit(snail_surface, snail_surface_rect)
screen.blit(player_surf, player_surf_rect)
pygame.display.update()
clock.tick(60)

The png image moves way too fast, how can I slow it down ? (python) [duplicate]

This question already has answers here:
Why is my pygame application loop not working properly?
(1 answer)
Why is my PyGame application not running at all?
(2 answers)
Closed 2 years ago.
I'm writing a program for school, but when I press a specific key to make my laser move across the screen, it disappears instantly. How can I make it move slowly, so the player can see it going from the left side to the right side of the screen ?
Here's the code (I wrote it again so I had only the part doing the laser moves)
#
import pygame, time
from pygame_functions import*
pygame.init()
win = pygame.display.set_mode((1440, 480))
laserImg = pygame.image.load('laser.png')
backgroundImg = pygame.image.load('bg.jpg')
laserX = 90
laserY = 400
clock = pygame.time.Clock()
run = True
while run:
clock.tick(14)
win.blit(backgroundImg, (0, 0))
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
keys = pygame.key.get_pressed()
win.blit(laserImg, (laserX, laserY))
if event.type == pygame.KEYDOWN:
print("touche")
if keys[pygame.K_UP]:
while laserX < 1500:
laserX += 10
pygame.display.update()
pygame.quit
#
Thanks if you can help me
edit : idk why but there wasn't the line saying "while laserX < 1500"
Try something like this:
run = True
laser_moving=False
while run:
clock.tick(14)
win.blit(backgroundImg, (0, 0))
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
keys = pygame.key.get_pressed()
win.blit(laserImg, (laserX, laserY))
if event.type == pygame.KEYDOWN:
print("touche")
if keys[pygame.K_UP]:
laser_moving=True
if laser_moving:
laser_x+=1
if laser_x > 1600:
laser_moving=False
Your issue is that you immediately move the laser outside the screen in your loop, without waiting for the next frame to be drawn in between. You need to exit your loop so the next frame can be drawn and the intermediate states of the laser are visible.

Creating a Buzzer System using python

We are having a holiday party at work, and are trying to set up a Family Feud game. With that, I'm trying to program a buzzer system. I am very new to pygame so maybe there is a better approach to what I'm trying to do.
I've written the following code which works to some degree. Right now, it recognizes the button and displays the picture as it should; however, it is recognizing all button presses where I only want it to recognize the first until after it is reset. For example, the left side buzzes in first, I want their picture to be displayed - then if the right team buzzes in after, I want that button to be ignored. Then if a third (reset) button is pushed, it resets back to the beginning to begin tracking for the first button pushed again. Any help would be greatly appreciated!
import pygame
import pdcurses
#import RPi.GPIO as GPIO
import image
import time
import clock
from pygame import mixer
from pygame.locals import *
displayWidth = 1600
displayHeight = 1200
pygame.init()
#mixer.init()
#pygame.display.init()
screen = pygame.display.set_mode((displayWidth, displayHeight))
pygame.display.set_caption('Family Feud')
pygame.display.update()
def reset():
global screen
kids = pygame.image.load("kids.jpg")
screen.blit(kids, (0,0))
pygame.display.update()
gameExit = False
while not gameExit:
for event in pygame.event.get():
if event.type == KEYDOWN:
if event.key == K_LEFT:
leftBuzzer = pygame.image.load("ice cream.jpg")
screen.blit(leftBuzzer,(0,0))
pygame.display.update()
if event.key == K_RIGHT:
rightBuzzer = pygame.image.load("snowman.jpg")
screen.blit(rightBuzzer,(0,0))
pygame.display.update()
if event.key == K_q:
pygame.quit()
if event.key == K_r:
reset()
You could add an alreadyPressed boolean and for each buzzer press have an if statement check alreadyPressed before displaying anything.

This simple program freezes for no apparent reason

I've just started programming in Python. I've been reading the book called "Making Games with Python & Pygame" and it's been very helpful so far, but I cannot find the reason why this simple program freezes. It should display an image and then move it by pressing left or right. It's strange, since it was working properly --I didn't change anything. I have tried everything so I'd really appreciate your help! Thanks in advance!
import pygame, sys
from pygame import *
# VARIABLES
x_res = 400
y_res = 300
DISPLAYSURF = 0
event = 0
person = 0
posx = 50
posy = 50
pygame.init()
DISPLAYSURF = pygame.display.set_mode((x_res, y_res))
pygame.display.set_caption("Test")
person = pygame.image.load("Person.png")
while True: # main game loop
DISPLAYSURF.blit(person, (posx, posy))
if event in pygame.event.get():
if event.type == KEYUP and event.key == K_RIGHT:
posx = posx + 5
DISPLAYSURF.fill((0,0,0))
if event.type == KEYUP and event.key == K_LEFT:
posx = posx - 5
DISPLAYSURF.fill((0,0,0))
if event.type == QUIT or (event.type == KEYUP and event.key == K_ESCAPE):
pygame.quit()
sys.exit()
pygame.display.update()
I'm not sure what you mean by "freezing" in this case, but I guess the problem is because you don't have an image called "Person.png", since when I tried out your code without an image on my file system called "Person.png" it also froze and gave me the error on the IDLE:
Traceback (most recent call last):
File "/Users/me/Desktop/your_program.py", line 17, in <module>
person = pygame.image.load("Person.png")
pygame.error: Couldn't open Person.png
Instead, if I have an image called "Person.png", it works properly.
Try writing "(wilst) true" instead of while? :)

How to create recurring, different rectangles in Pygame?

As a beginner at Pygame, and a relative beginner at Python (around 4 months of knowledge), I thought it would be good practice to try and recreate the popular phone app 'Flappy Bird.' I have been fine with doing this, up to the point I am at now. How do I keep one rectangle scrolling, while drawing another that will scroll using the same function? Is this possible? There is probably a method for just this, but I've only been learning the module for less than 7 hours :D Here's my code so far in Python 3.2. (Not including imports)
def drawPipe():
randh = random.randint(40,270)
scrollx -=0.2
pygame.draw.rect(screen, (0,150,30), Rect((scrollx,0),(30,340)))
bif = "BG.jpg"
mif = "bird.png"
pygame.init()
screen = pygame.display.set_mode((640,900),0,32)
background = pygame.image.load(bif).convert()
bird = pygame.image.load(mif).convert_alpha()
pygame.display.set_caption("Flappy Bird")
pygame.display.set_icon(bird)
x,y = 320,0
movex, movey = 0,0
scrollx = 640
while True:
for event in pygame.event.get():
movey = +0.8
if event.type == QUIT:
pygame.quit()
sys.exit()
elif event.type == KEYDOWN:
if event.key == K_SPACE:
movey = -2
x += movex
y += movey
screen.blit(background,(0,0))
screen.blit(bird,(x,y))
drawPipe()
pygame.display.update()
Thank you for any help you can give!
You should first create object that you want to have in the game, with one operation being to draw them.
So instead of having a function that draws a pipe and scrolls, you want to have something along these lines:
class Pipe:
def __init__(self,x,height):
self.rect = Rect((x,0),(30,height))
def update():
self.rect.move_ip(-2,0)
def draw(screen):
pygame.draw.rect(screen,color,self.rect)
And then later in game you can have:
pipes = [Pipe(x*20,random.randint(40,270)) for x in range(5)]
for pipe in pipes:
pipe.draw(screen)
pipe.update()
Later on you could just remove the pipes that are not on the screen, and append new ones when a pipe is removed.

Categories