I'm starting out in python and pygame. so I have been introduced to screen.blit for showing pictures on the screen. however when I use screen.blit nothing will happen in my program unless I am moving my mouse or clicking a button. I have no idea why this happens, I have simplified an example with only a cat moving across the screen. Nothing happens unless I am pressing a button or moving my mouse. I am using python 2.6.6
import pygame
pygame.init()
# Set the width and height of the screen [width, height]
size = (800, 600)
screen = pygame.display.set_mode(size)
pygame.display.set_caption("My Game")
# Loop until the user clicks the close button.
done = False
# Used to manage how fast the screen updates
clock = pygame.time.Clock()
floor = pygame.image.load("floor.png").convert()
cat = pygame.image.load("cat.png").convert()
a=0
b=0
# -------- Main Program Loop -----------
while not done:
# --- Main event loop
for event in pygame.event.get(): # User did something
if event.type == pygame.QUIT: # If user clicked close
done = True # Flag that we are done so we exit this loop
# --- Game logic should go here
a+=1
b+=1
# --- Drawing code should go here
# First, clear the screen to white. Don't put other drawing commands
# above this, or they will be erased with this command.
screen.blit(floor, [0,0])
screen.blit(cat, [a,b])
# --- Go ahead and update the screen with what we've drawn.
pygame.display.flip()
pygame.display.update()
# --- Limit to 60 frames per second
clock.tick(60)
# Close the window and quit.
# If you forget this line, the program will 'hang'
# on exit if running from IDLE.
pygame.quit()
That's because the screen.blip is inside the for event in pygame.event.get():
Correct the indentation and it will be fixed.
Try this:
while not done:
# --- Main event loop
for event in pygame.event.get(): # User did something
if event.type == pygame.QUIT: # If user clicked close
done = True # Flag that we are done so we exit this loop
# --- Game logic should go here
a+=1
b+=1
# --- Drawing code should go here
# First, clear the screen to white. Don't put other drawing commands
# above this, or they will be erased with this command.
screen.blit(floor, [0,0])
screen.blit(cat, [a,b])
# --- Go ahead and update the screen with what we've drawn.
pygame.display.flip()
pygame.display.update()
# --- Limit to 60 frames per second
clock.tick(60)
Related
I have a custom user event that I have assigned to the variable enemy_fire, and have it set to activate every 100 ms with pygame.time.set_timer(enemy_fire, 100). However, this does not work. I tried setting it to 10 ms: pygame.time.set_timer(enemy_fire, 10) and it worked, and I kept playing with the time parameter until I found the threshold in which it stopped working, and have found that anything higher than 16 ms does not work. I've been reading the documentation, and I'm pretty sure I'm using this function correctly. This seems like odd behavior to me, I'm not really sure why this is happening.
Here is the main part of my code:
import pygame
import gametools
import players
import enemies
from sys import exit
# initilaization
pygame.init()
screen = pygame.display.set_mode((800, 600))
pygame.display.set_caption('Bullet hell')
clock = pygame.time.Clock()
# Player
player = players.Player()
enemy = enemies.Enemy()
# Background
back_surf = pygame.image.load('sprites/backgrounds/background.png').convert()
enemy_fire = pygame.USEREVENT + 1
# main game loop
while True:
pygame.time.set_timer(enemy_fire, 100)
# event loop
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
if event.type == enemy_fire:
print('fire')
enemy.attack(screen)
# display background
screen.blit(back_surf, (0, 0))
player.draw(screen)
player.update(screen)
enemy.draw(screen)
enemy.update()
enemy.collision(enemy.rect, player.bullets)
pygame.display.update()
clock.tick(60)
You have to call pygame.time.set_timer(enemy_fire, 100) before the application loop, but not in the loop. When you call pygame.time.set_timer() in the loop, it will continuously restart and never fire unless you set an interval time faster than the application loop interval. Since the application loop is limited by clock.tick(60), that's about 16 milliseconds (1000/60).
pygame.time.set_timer(enemy_fire, 100) # <-- INSERT
# main game loop
while True:
# pygame.time.set_timer(enemy_fire, 100) <-- DELETE
# event loop
for event in pygame.event.get():
# [...]
I am trying to move my sprite across the screen when the window starts.... It moves for a second than stops for a while than it starts back up again. its not giving me an error.... So im really not sure whats going on here.... anyway here is the code.... any info is needed!
thanks,
import pygame
from sys import exit
pygame.init()
screen = pygame.display.set_mode((800,400))
sky_surface = pygame.image.load("bg_desert.png")
snail_surface = pygame.image.load("snailWalk1.png")
snail_x_pos = 600
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
snail_x_pos -=1
screen.blit(sky_surface,(0,0))
screen.blit(snail_surface,(snail_x_pos,350))
pygame.display.update()
Your loop will only execute when there are events. When there are no events, you don't move. If you wiggle your mouse in front of the screen, for example, you'll see pretty continuous movement.
You need to use pygame.time.set_timer to force an event for you to update.
It looks like the final 4 lines you have written are designed to run on each cycle of the for loop, however they will only run when an event occurs, because they are indented a block too far.
Your new code should look like this:
import pygame
from sys import exit
pygame.init()
screen = pygame.display.set_mode((800,400))
sky_surface = pygame.image.load("bg_desert.png")
snail_surface = pygame.image.load("snailWalk1.png")
snail_x_pos = 600
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
snail_x_pos -=1
screen.blit(sky_surface,(0,0))
screen.blit(snail_surface,(snail_x_pos,350))
pygame.display.update()
I have been trying to get my code collecting which mouse button is pressed and its position yet whenever I run the below code the pygame window freezes and the shell/code keeps outputting the starting position of the mouse. Does anybody know why this happens and more importantly how to fix it?
(For the code below I used this website https://www.pygame.org/docs/ref/mouse.html and other stack overflow answers yet they were not specific enough for my problem.)
clock = pygame.time.Clock()
# Set the height and width of the screen
screen = pygame.display.set_mode([700,400])
pygame.display.set_caption("Operation Crustacean")
while True:
clock.tick(1)
screen.fill(background_colour)
click=pygame.mouse.get_pressed()
mousex,mousey=pygame.mouse.get_pos()
print(click)
print(mousex,mousey)
pygame.display.flip()
You have to call one of the pygame.event functions regularly (for example pygame.event.pump or for event in pygame.event.get():), otherwise pygame.mouse.get_pressed (and some joystick functions) won't work correctly and the pygame window will become unresponsive after a while.
Here's a runnable example:
import pygame
pygame.init()
screen = pygame.display.set_mode((640, 480))
clock = pygame.time.Clock()
BG_COLOR = pygame.Color('gray12')
done = False
while not done:
# This event loop empties the event queue each frame.
for event in pygame.event.get():
# Quit by pressing the X button of the window.
if event.type == pygame.QUIT:
done = True
elif event.type == pygame.MOUSEBUTTONDOWN:
# MOUSEBUTTONDOWN events have a pos and a button attribute
# which you can use as well. This will be printed once per
# event / mouse click.
print('In the event loop:', event.pos, event.button)
# Instead of the event loop above you could also call pygame.event.pump
# each frame to prevent the window from freezing. Comment it out to check it.
# pygame.event.pump()
click = pygame.mouse.get_pressed()
mousex, mousey = pygame.mouse.get_pos()
print(click, mousex, mousey)
screen.fill(BG_COLOR)
pygame.display.flip()
clock.tick(60) # Limit the frame rate to 60 FPS.
I am trying to get the ball object to bounce around inside the screen, I have been testing different things for hours, looking at other pong game source code and other questions on here but I just can't seem to figure it out. Could someone give some pointers on where to start? Should I make separate functions for the different movements?
# ----- Game Loop ----- #
# Setting the loop breakers
game_exit = False
# ball positon/velocity
ball_x = DISP_W/2
ball_y = DISP_H/2
velocity = 5
# Game loop
while not game_exit:
# Gets all events
for event in pygame.event.get():
# Close event
if event.type == pygame.QUIT:
# Closes game loop
game_exit = True
# Background fill
GAME_DISP.fill(black)
# Setting positions
ball.set_pos(ball_x, ball_y)
# ceil.set_pos(0, 0)
# floor.set_pos(0, DISP_H - boundary_thickness)
ball_y += velocity
# Drawing sprites
ball_group.draw(GAME_DISP)
# collision_group.draw(GAME_DISP)
pygame.display.update()
# Setting FPS
clock.tick(FPS)
# ----- Game exit ----- #
pygame.quit()
quit()
FULL CODE: http://pastebin.com/4XxJaCvf
I would have a look at the pygame sprite class. It has a lot of handy methods to help with collisions and other stuff: https://www.pygame.org/docs/ref/sprite.html
I am trying to make a game in Pygame where he objective is to start the game but the start button keeps moving whenever you touch it but the window will not respond. I am not finished with the code yet because I tested it and it didn't work. Here is my code so far:
import pygame
import random
import time
pygame.init()
display = pygame.display.set_mode((800,600))
pygame.display.set_caption('BEST 3D PLATFORMER FPS GAME!')
clock = pygame.time.Clock()
pygame.display.update()
clock.tick(60)
display.fill((255,255,255))
def newposition()
randx = random.randrange(100, 700)
randy = random.randrange(100,500)
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pass
if event.ty
button = pygame.image.load('start.png')
display.blit(button,(randx,randy))
pygame.quit()
quit()
All comments inside code
import pygame
import random
# --- constants --- (UPPER_CASE names)
WHITE = (255, 255, 255) # space after every `,`
FPS = 30
# --- classes --- (CamelCase names)
#empty
# --- functions --- (lower_case names)
def new_position():
x = random.randrange(100, 700) # space after every `,`
y = random.randrange(100, 500) # space after every `,`
return x, y # you have to return value
# --- main --- (lower_case names)
# - init -
pygame.init()
display = pygame.display.set_mode((800, 600)) # space after every `,`
pygame.display.set_caption('BEST 3D PLATFORMER FPS GAME!')
# - objects -
# load only once - don't waste time to load million times in loop
button = pygame.image.load('start.png').convert_alpha()
button_rect = button.get_rect() # button size and position
button_rect.topleft = new_position() # set start position
# - mainloop -
clock = pygame.time.Clock()
running = True
while running:
# - events -
for event in pygame.event.get():
if event.type == pygame.QUIT:
#pass # it does nothing so you can't exit
running = False # to exit `while running:`
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
running = False # to exit `while running:`
elif event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1: # left button
button_rect.topleft = new_position() # set new position
# if event.ty # Syntax Error
# - updates (without draws) -
#empty
# - draws (without updates) -
# you have to use it inside loop
display.fill(WHITE) # clear screeen before you draw elements in new place
display.blit(button, button_rect)
# you have to use it inside loop
pygame.display.update() # you have to send buffer to monitor
# - FPS -
# you have to use it inside loop
clock.tick(FPS)
# - end -
pygame.quit()
BTW: simple template which you can use when you start new project.
PEP 8 -- Style Guide for Python Code
I had a similar issue, the fix is not straight forward. Here are my notes for python 3.6.1 and Pygame 1.9.3:
1) The event is unresponsive because there is no display generated for pygame, add a window display after pygame initialization:
pygame.init() # Initializes pygame
pygame.display.set_mode((500, 500)) # <- add this line. It generates a window of 500 width and 500 height
2) pygame.event.get() is a generates a list of event but not all event classes have .key method for example mouse motion. Thus, change all .key event handling codes such as
if event.key == pygame.K_q:
stop = True
To
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_q:
stop = True
3) In some mac/python combinations even after the window is generated it doesn't focus / record keyboard events, this is a pygame issue and is fixed in a reimplementation of pygame using sdl2 (SDL is a cross-platform development library which provides low level access to keyboard, audio ,mouse etc). it can be installed by following the instructions here https://github.com/renpy/pygame_sdl2. One might need to install homebrew for it, which is another package manager for macOS. Instructions can be found here https://brew.sh/
4) after installing it using the instructions on github link you need to change all import pygame to import pygame_sdl2 as pygame
5) Voila! fixed ...
You've got to load button outside the loop (it only needs to be done once.)
button = pygame.image.load('start.png')
Also, you have defined newposition(), but have not called it. Also, randx and randy would not be accessible from outside of the function, because the would be local to it.
So, change your function to this :
def newposition()
randx = random.randrange(100, 700)
randy = random.randrange(100,500)
return randx, randy # Output the generated values
Then, before the loop :
rand_coords = newposition()
You simply forgot to update the pygame display with your modifications to it.
At the end of your loop, add pygame.display.update(), like this:
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pass
# if event.ty why is that here?
display.blit(button,(rand_coords[0],rand_coords[1])) # Take our generated values
pygame.display.update()
Final code :
import pygame
import random
import time
pygame.init()
display = pygame.display.set_mode((800,600))
pygame.display.set_caption('BEST 3D PLATFORMER FPS GAME!') # Yeah, exactly :)
clock = pygame.time.Clock()
display.fill((255,255,255))
def newposition()
randx = random.randrange(100, 700)
randy = random.randrange(100,500)
return randx, randy # Output the generated values
rand_coords = newposition() # Get rand coords
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit() # Quit pygame if window in closed
# if event.ty why is that here?
clock.tick(60) # This needs to be in the loop
display.fill((255,255,255)) # You need to refill the screen with white every frame.
display.blit(button,(rand_coords[0],rand_coords[1])) # Take our generated values
pygame.display.update()