python pygame window wont close "not responding" - python

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)

Related

How would I create side scrolling text in PyGame?

I am currently working on a weather application using the PyGame framework and it needs to have side scrolling text at the bottom, but I wouldn't know how to do it. I have looked for tutorials online and I have found things similar but not quite what I would like.
This is my code around the end, where all of the text is initalized.
desc_text = desc.render(description, True, (255, 255, 255))
desc_rect = desc_text.get_rect()
desc_rect.center = (238, 740)
screen = pygame.display.set_mode((960, 720), pygame.FULLSCREEN, vsync=1)
while running:
try:
for event in pygame.event.get():
if event.type == KEYDOWN:
if event.key == K_ESCAPE:
running = False
elif event.type == QUIT:
running = False
screen.fill((0, 0, 125))
screen.blit(header_text, header_rect)
screen.blit(temperature_text, temperature_rect)
screen.blit(wind_text, wind_rect)
screen.blit(desc_text, desc_rect)
pygame.display.update()
except KeyboardInterrupt:
print("Quitting...")
running = False
This is the text.
I want it to be like a marquee, scrolling left to right endlessly.
I don't understand what is the problem.
The simplest version which moves to left and when all text leave screen on left side then it shows it again on right need
put on right side rect.x = screen_rect.right
in every loop move rect.x -= 1
in every loop check if it all text leave screen rect.right <= 0 and move to right side rect.x = screen_rect.right
and you should start with this - and later try to create more complex version which repeat text at once after when there is space text.
import pygame
# --- constants --- # PEP8: `UPPER_CASE_NAMES`; directly after import
FPS = 30
# --- main ---
pygame.init()
screen = pygame.display.set_mode((960, 720))#, pygame.FULLSCREEN, vsync=1)
screen_rect = screen.get_rect()
font = pygame.font.SysFont(None, 50)
description = " How would I create side scrolling text in PyGame? "
desc_text = font.render(description, True, (255, 255, 255))
desc_rect = desc_text.get_rect(left=screen_rect.right)
clock = pygame.time.Clock()
running = True
while running:
try:
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
running = False
elif event.type == pygame.QUIT:
running = False
# --- updates (without draws) ---
desc_rect.x -= 5
if desc_rect.right <= 0: # if leave on left side
desc_rect.x = screen_rect.right # then move to right side
# --- draws (without updates) ---
screen.fill((0, 0, 125))
screen.blit(desc_text, desc_rect)
pygame.display.update()
clock.tick(FPS) # slowdown to 30 FPS
except KeyboardInterrupt:
print("Quitting...")
running = False
pygame.quit()
To make more complex version you have to repeate the same text 2 or 3 times - so it needs to create 2 or 3 rect with offsets. First starts at rect.x second starts at rect.x + rect.width and third starts at rect.x + rect.width + rect.width. And for all of then you have to repeat (almost) the same code as in previous version. If you put all rect on list then it can be simpler.
Difference is: when it leave on left side then move to right by rect.width * 3
import pygame
# --- constants --- # PEP8: `UPPER_CASE_NAMES`; directly after import
FPS = 30
# --- main ---
pygame.init()
screen = pygame.display.set_mode((960, 720))#, pygame.FULLSCREEN, vsync=1)
screen_rect = screen.get_rect()
font = pygame.font.SysFont(None, 50)
description = " How would I create side scrolling text in PyGame? "
desc_text = font.render(description, True, (255, 255, 255))
# because text is short so I need 3 copies (with different offsets)
desc_rects = []
for i in range(3):
rect = desc_text.get_rect(left=screen_rect.right)
rect.x += rect.width * i # add offset
desc_rects.append(rect)
clock = pygame.time.Clock()
running = True
while running:
try:
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
running = False
elif event.type == pygame.QUIT:
running = False
# --- updates (without draws) ---
for rect in desc_rects:
rect.x -= 5
if rect.right <= 0:
rect.x += rect.width * 3
# --- draws (without updates) ---
screen.fill((0, 0, 125))
for rect in desc_rects:
screen.blit(desc_text, rect)
pygame.display.update()
clock.tick(FPS) # slowdown to 30 FPS
except KeyboardInterrupt:
print("Quitting...")
running = False
pygame.quit()

Im trying to solve this un-smooth and choppy animations and movements on pygame, i've been trying everything but nothing works

heres the video of the animation https://www.youtube.com/watch?v=uhPdN3v8vg0
other pygame codes dont act like this, only this specific one, so i'm pretty sure its not hardware problem
import sys
import time
import pygame
import os
from pygame import mixer
pygame.init()
pygame.mixer.init()
width,height=(900,500)
border= pygame.Rect(0,0,6,height)
WIN=pygame.display.set_mode((width,height))
bg= pygame.image.load(os.path.join('','pixel_bg.jpg'))
bg=pygame.transform.scale(bg,(width,height))
person1=pygame.image.load(os.path.join('','mario.png'))
p1_width, p1_height = (50,60)
person1=pygame.transform.scale(person1,(p1_width,p1_height))
black=(0,0,0)
p1_rect = pygame.Rect(50,340,p1_width,p1_height)
pygame.display.set_caption("rpg game")
Velocity= 4
jump_height = 50
FPS = 60
mixer.music.load("adventurebeat.mp3")
mixer.music.play(-1)
def draw():
WIN.blit(bg, (0, 0))
WIN.blit(person1, (p1_rect.x,p1_rect.y))
pygame.display.update()
def p1_movement(keys_pressed, p1_rect):
if keys_pressed[pygame.K_a] and p1_rect.x - Velocity > border.x + border.width: # left
p1_rect.x -= Velocity
if keys_pressed[pygame.K_d] and p1_rect.x + Velocity + p1_rect.width < width: # right
p1_rect.x += Velocity
if keys_pressed[pygame.K_w] and p1_rect.y - Velocity > 0: # up
p1_rect.y -= Velocity
if keys_pressed[pygame.K_SPACE] and p1_rect.y - Velocity > 0: # up
p1_rect.y -= jump_height
if keys_pressed[pygame.K_s] and p1_rect.y + Velocity + p1_rect.height < height: # down
p1_rect.y += Velocity
def main():
clock = pygame.time.Clock()
run = True
while run:
clock.tick_busy_loop(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
pygame.quit()
sys.exit()
draw()
keys_pressed = pygame.key.get_pressed()
p1_movement(keys_pressed,p1_rect)
main()
I've tried changing the clock.tick_busy_loop() to clock.tick() but it still doesnt work :/
You need to draw the object in the application loop instead of the event loop:
def main():
clock = pygame.time.Clock()
run = True
while run:
clock.tick_busy_loop(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
pygame.quit()
sys.exit()
# draw() <--- DELETE
keys_pressed = pygame.key.get_pressed()
p1_movement(keys_pressed,p1_rect)
draw() # <--- INSERT
The application loop is executed in every frame, but the event loop only is executed when an event occurs.

Trying to delay a specific function for spawning enemy after a certain amount of time

I am making a mole shooter game using pygame. I want my mole to spawn at a random position after every 1 second. I have tried using time.sleep(1.0) but that delays my whole code and thus the game doesn't function properly because of delayed responses. I am moving an aim using the mouse(which also gets affected because of time.sleep) to which i will be adding a click to shoot. I need help with delaying and spawning my mole. I would also like some opinions on how to organize my code to provide various levels of difficulty and a main menu later on.
import pygame
import random
import time
from threading import Timer
pygame.font.init()
win_width = 1000
win_height = 710
FPS = 60
screen = pygame.display.set_mode((win_width, win_height))
pygame.display.set_caption("Mole Shooter")
white = (255,255,255)
red = (255, 0, 0)
counter, text = 30, 'Time Left: 30'.rjust(3)
pygame.time.set_timer(pygame.USEREVENT, 1000)
font = pygame.font.Font('freesansbold.ttf', 32)
run = True
clock = pygame.time.Clock()
background = pygame.transform.scale(pygame.image.load('back_land.png'), (win_width, win_height))
aim = pygame.image.load("aim.png")
mole = pygame.image.load("mole.png")
def mole_spawn_easy():
molex = random.randint(50, 950)
moley = random.randint(450, 682)
screen.blit(mole, (molex, moley))
while run:
screen.blit(background, [0,0])
ax, ay = pygame.mouse.get_pos()
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.USEREVENT:
counter -= 1
text = ("Time Left: " + str(counter)).rjust(3)
if counter > 0:
time.sleep(1.0);mole_spawn_easy()
else:
print("game over")
break
screen.blit(aim, ((ax - 32 ),(ay - 32)))
screen.blit(font.render(text, True, (0, 0, 0)), (32, 48))
clock.tick(FPS)
pygame.display.flip()
In pygame exists a timer event. Use pygame.time.set_timer() to repeatedly create a USEREVENT in the event queue.. The time has to be set in milliseconds:
pygame.time.set_timer(pygame.USEREVENT, 1000) # 1 second
Note, in pygame customer events can be defined. Each event needs a unique id. The ids for the user events have to be between pygame.USEREVENT (24) and pygame.NUMEVENTS (32). In this case the value of pygame.USEREVENT is the event id for the timer event.
Receive the event in the event loop:
running = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
elif event.type == pygame.USEREVENT:
# [...]
The timer event can be stopped by passing 0 to the time argument of pygame.time.set_timer.
See also Spawning multiple instances of the same object concurrently in python.
Create a list of moles and add a random position to the list in mole_spawn_easy:
moles = []
def mole_spawn_easy():
molex = random.randint(50, 950)
moley = random.randint(450, 682)
moles.append((molex, moley))
Draw the moles in the main application loop:
while run:
# [...]
for pos in moles:
screen.blit(mole, pos)
See the example:
moles = []
def mole_spawn_easy():
molex = random.randint(50, 950)
moley = random.randint(450, 682)
moles.append((molex, moley))
pygame.time.set_timer(pygame.USEREVENT, 1000)
while run:
ax, ay = pygame.mouse.get_pos()
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.USEREVENT:
counter -= 1
text = ("Time Left: " + str(counter)).rjust(3)
if counter > 0:
mole_spawn_easy()
else:
print("game over")
screen.blit(background, [0,0])
for pos in moles:
screen.blit(mole, pos)
screen.blit(aim, ((ax - 32 ),(ay - 32)))
screen.blit(font.render(text, True, (0, 0, 0)), (32, 48))
pygame.display.flip()
clock.tick(FPS)

Python 2D Sprite Animation

I'm trying to animate a sprite using a loop such that each time the loop runs through the position number for an image in an array increases by one. I keep getting "UnboundLocalError: local variable 'Antic' referenced before assignment". There is
Antic = 0
Antic = int(Antic)
# Global constants
StAnmtn = ["Images/PlayerVampireStanding1.png", "
Images/PlayerVampireStanding2.png",
"Images/PlayerVampireStanding3.png","Images/PlayerVampireStanding4.png",
"Images/PlayerVampireStanding5.png", "Images/PlayerVampireStanding6.png",
"Images/PlayerVampireStanding7.png", "Images/PlayerVampireStanding8.png"]
`
at the start and
def main():
""" Main Program """
pygame.init()
clock = pygame.time.Clock() # creates clock to limit frames per
second
FPS = 60 # sets max speed of min loop
SCREENSIZE = SCREENWIDTH, SCREENHEIGHT = 1300, 700 # sets size of
screen/window
screen = pygame.display.set_mode(SCREENSIZE) # creates window and game
screen
pygame.display.set_caption("Count Acheron")
# Create the player
player = Player()
# Create all the levels
level_list = []
level_list.append( Level_01(player) )
# Set the current level
current_level_no = 0
current_level = level_list[current_level_no]
active_sprite_list = pygame.sprite.Group()
player.level = current_level
player.rect.x = 340
player.rect.y = SCREEN_HEIGHT - player.rect.height
active_sprite_list.add(player)
# Loop until the user clicks the close button.
done = False
# Used to manage how fast the screen updates
clock = pygame.time.Clock()
# -------- Main Program Loop -----------
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
player.go_left()
if event.key == pygame.K_RIGHT:
player.go_right()
if event.key == pygame.K_UP:
player.jump()
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT and player.change_x < 0:
player.stop()
if event.key == pygame.K_RIGHT and player.change_x > 0:
player.stop()
if Antic > 6:
Antic = 0
else:
Antic += 1
# Update the player.
active_sprite_list.update()
# Update items in the level
current_level.update()
# ALL CODE TO DRAW SHOULD GO BELOW THIS COMMENT
current_level.draw(screen)
active_sprite_list.draw(screen)
# ALL CODE TO DRAW SHOULD GO ABOVE THIS COMMENT
# Limit to 60 frames per second
clock.tick(60)
# Go ahead and update the screen with what we've drawn.
pygame.display.flip()
# Be IDLE friendly. If you forget this line, the program will 'hang'
# on exit.
pygame.quit()
if __name__ == "__main__":
main()
as the loop. What it doesn't seem to like is the snippet of code
if Antic > 6:
Antic = 0
else:
Antic += 1
How do I fix this?
Personally I've never used pygame's sprite module.
import pygame
class character:
def __init__(self, x, y):
self.x = x
self.y = y
self.sprites = [pygame.image.load("img1.png"), pygame.image.load("img2.png")]
self.frame = 0
def draw(self, surface):
surface.blit(self.sprites[self.frame], (self.x, self.y))
self.frame += 1
if self.frame > len(self.sprites) - 1: self.frame = 0
pygame.init()
DS = pygame.display.set_mode((1280, 720))
clock = pygame.time.Clock()
c = character(640, 360)
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT or (event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE):
pygame.quit()
c.draw(DS)
pygame.display.update()
clock.tick(30)
DS.fill((0, 0, 0))
Needed to globalise the function ("global Antic" in the main loop)

image is bad with python in pygame

I have a program in python:
import sys, random, pygame
from pygame.locals import *
pygame.init()
# Preparing Pygame
size = width, height = 718, 502
screen = pygame.display.set_mode(size)
framerate = pygame.time.Clock()
pygame.display.set_caption('Flappy Cube')
#Peparing background
background_x = 0
background_y = 0
background = pygame.image.load("background.jpg")
#Preparing Cube
cube_x = 100
cube_y = 200
cube_unscaled = pygame.image.load("cube.png")
cube = pygame.transform.smoothscale(cube_unscaled, (64, 64))
#Preparing Tubes
tube_x = 750
tube_y= 300
tube_unscaled = pygame.image.load("tube.png")
tube = pygame.transform.smoothscale(tube_unscaled, (125, 500))
# The main game loop
def exit_game():
sys.exit()
while True:
#Background
screen.blit(background, (background_x,background_y))
background_x = background_x+254.5
screen.blit(cube,(cube_x, cube_y))
#Tube
tube_x = tube_x -.075
screen.blit(tube,(tube_x, tube_y))
# If exit
for event in pygame.event.get():
if event.type == pygame.QUIT: exit_game()
# If Space Key is presed
elif event.type == pygame.KEYDOWN and event.key == K_SPACE:
cube_y = cube_y-10
#If Clicked
elif pygame.mouse.get_pressed()[0]:
cube_y = cube_y-10
framerate.tick(60)
pygame.display.flip()
run_game()
I get this result: http://i.stack.imgur.com/MKYRM.png
I have to boost framerate.tick(60) to framerate.tick(700) it looks a glichy. when I program the gravity the multiple images won't look good.
how can i fix the images been drawn multiple times before the screen updates?
Try:
cube_unscaled = pygame.image.load("cube.png").convert_alpha()
You shouldn't need to boost your FPS in such way, 60 is a good value.
Also, I like better this order for your main loop: check events, draw, update, tick.
I don't think it makes a difference to your problem, but I think it easier to understand that way.
while True:
# If exit
for event in pygame.event.get():
if event.type == pygame.QUIT: exit_game()
# If Space Key is presed
elif event.type == pygame.KEYDOWN and event.key == K_SPACE:
cube_y = cube_y-10
#If Clicked
elif pygame.mouse.get_pressed()[0]:
cube_y = cube_y-10
#Background
screen.blit(background, (background_x,background_y))
background_x = background_x+254.5
screen.blit(cube,(cube_x, cube_y))
#Tube
tube_x = tube_x -.075
screen.blit(tube,(tube_x, tube_y))
pygame.display.flip()
framerate.tick(60)
I fixed it! I just needed to fill the screen with black before "bliting" it.

Categories