Why is my pymunk program is way too slow? - python

My pymunk program is way too slow. Every time I run the program it takes 5 seconds while loading. Here is my code. Thanks in advance.
import pymunk # Import pymunk..
import pygame
pygame.init()
display = pygame.display.set_mode((800,800))
clock = pygame.time.Clock()
space = pymunk.Space() # Create a Space which contain the simulation
FPS = 30
def convert_coordinates(point):
return point[0], 800-point[1]
running = True
space.gravity = 0,-1000 # Set its gravity
# Set the position of the body
body = pymunk.Body()
shape = pymunk.Circle(body, 10)
body.position = (400,800)
shape.density = 1
space.add(body,shape)
while running: # Infinite loop simulation
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
pygame.display.update()
clock.tick(FPS)
space.step(1/FPS)
display.fill((255,255,255))
x,y = convert_coordinates(body.position)
sprite = pygame.draw.circle(display,(255,0,0), (int(x),int(y)),10)
pygame.quit()

It's a matter of Indentation. You have to draw the scene in the application loop rather than the event loop:
while running: # Infinite loop simulation
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# <--- INDENTATION
clock.tick(FPS)
space.step(1/FPS)
display.fill((255,255,255))
x,y = convert_coordinates(body.position)
sprite = pygame.draw.circle(display,(255,0,0), (int(x),int(y)),10)
pygame.display.update()
pygame.quit()

Related

Keep getting an error about pygame not being initialised

I keep getting an error about system not being initialised. The error is about the pygame.display.update()
Where is this meant to go?
import pygame #IMPORTS THE PYGAME CLASSES, METHODS AND ATTRIBUTES
from pygame.locals import * #IMPORTING ALL PYGAME MODULES
pygame.init() #INITIALISING PYGAME
WIDTH, HEIGHT = 1000, 600
WINDOW = pygame.display.set_mode((WIDTH,HEIGHT))
pygame.display.set_caption("On The Run")
blue = 146,244,255 #BACKGROUND COLOUR
width = 80
height = 60
x = 200 #X-POSITION OF THE CHARACTER
y = 100 #Y-POSITION OF THE CHARACTER
player1 = pygame.image.load('assets/characterMove3.jpg') #DISPLAYING THE IMAGE ONTO THE SCREEN
player1 = pygame.transform.scale(player1,(width,height)) #SCALING THE IMAGE TO SUITABLE DIMENSIONS
WINDOW.blit(player1,(x,y))
def game_loop(): #WHERE THE WINDOW IS CREATED
run = True
while run:
WINDOW.fill(blue)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False #WE WILL QUIT THE GAME AS THE VARIABLE run IS NOW FALSE
pygame.quit() #IT WON'T SHOW THE MOST RECENT THING I DREW UNLESS I MANUALLY UPDATE IT
pygame.display.update()
game_loop()
The problem is that pygame.quit() is called in the application loop. pygame.quit() deinitializes all Pygame modules and crashes all subsequent Pygame API calls. pygame.quit() must be the very last Pygame API call. Call pygame.quit() after the application loop:
def game_loop(): #WHERE THE WINDOW IS CREATED
run = True
while run:
WINDOW.fill(blue)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
#pygame.quit() <-- DELETE
pygame.display.update()
pygame.quit() # <-- INSERT
game_loop()

Why is the background not loading?

import pygame
screen = pygame.display.set_mode((3840,2160))
running = True
pygame.display.set_caption("GermanBall")
bg = pygame.image.load("Tan.jpg")
while running == True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
screen.blit(bg,(0,0))
pygame.display.update()
i need to know why this doesnt work
i tried changing the resolution of the image and the screen but to no avail, the image and screen are of same size
I think you have an indentation problem on the two last lines. The blit and the update are outside the while loop:
import pygame
screen = pygame.display.set_mode((3840,2160))
running = True
pygame.display.set_caption("GermanBall")
bg = pygame.image.load("Tan.jpg")
while running == True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
screen.blit(bg,(0,0)) # <- HERE
pygame.display.update() # <- HERE

pygame.time.set_timer() it works incorrectly [duplicate]

I started using pygame and I want to do simple game. One of the elements which I need is countdown timer.
How can I do the countdown time (eg 10 seconds) in PyGame?
Another easy way is to simply use pygame's event system.
Here's a simple example:
import pygame
pygame.init()
screen = pygame.display.set_mode((128, 128))
clock = pygame.time.Clock()
counter, text = 10, '10'.rjust(3)
pygame.time.set_timer(pygame.USEREVENT, 1000)
font = pygame.font.SysFont('Consolas', 30)
run = True
while run:
for e in pygame.event.get():
if e.type == pygame.USEREVENT:
counter -= 1
text = str(counter).rjust(3) if counter > 0 else 'boom!'
if e.type == pygame.QUIT:
run = False
screen.fill((255, 255, 255))
screen.blit(font.render(text, True, (0, 0, 0)), (32, 48))
pygame.display.flip()
clock.tick(60)
On this page you will find what you are looking for http://www.pygame.org/docs/ref/time.html#pygame.time.get_ticks
You download ticks once before beginning the countdown (which can be a trigger in the game - the key event, whatever).
For example:
start_ticks=pygame.time.get_ticks() #starter tick
while mainloop: # mainloop
seconds=(pygame.time.get_ticks()-start_ticks)/1000 #calculate how many seconds
if seconds>10: # if more than 10 seconds close the game
break
print (seconds) #print how many seconds
In pygame exists a timer event. Use pygame.time.set_timer() to repeatedly create an USEREVENT. e.g.:
timer_interval = 500 # 0.5 seconds
timer_event = pygame.USEREVENT + 1
pygame.time.set_timer(timer_event , timer_interval)
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 pygame.USEREVENT+1 is the event id for the timer event.
To disable the timer for an event, set the milliseconds argument to 0.
Receive the event in the event loop:
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == timer_event:
# [...]
The timer event can be stopped by passing 0 to the time parameter.
See the example:
import pygame
pygame.init()
window = pygame.display.set_mode((200, 200))
clock = pygame.time.Clock()
font = pygame.font.SysFont(None, 100)
counter = 10
text = font.render(str(counter), True, (0, 128, 0))
timer_event = pygame.USEREVENT+1
pygame.time.set_timer(timer_event, 1000)
run = True
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
elif event.type == timer_event:
counter -= 1
text = font.render(str(counter), True, (0, 128, 0))
if counter == 0:
pygame.time.set_timer(timer_event, 0)
window.fill((255, 255, 255))
text_rect = text.get_rect(center = window.get_rect().center)
window.blit(text, text_rect)
pygame.display.flip()
pygame.time.Clock.tick returns the time in milliseconds since the last clock.tick call (delta time, dt), so you can use it to increase or decrease a timer variable.
import pygame as pg
def main():
pg.init()
screen = pg.display.set_mode((640, 480))
font = pg.font.Font(None, 40)
gray = pg.Color('gray19')
blue = pg.Color('dodgerblue')
# The clock is used to limit the frame rate
# and returns the time since last tick.
clock = pg.time.Clock()
timer = 10 # Decrease this to count down.
dt = 0 # Delta time (time since last tick).
done = False
while not done:
for event in pg.event.get():
if event.type == pg.QUIT:
done = True
timer -= dt
if timer <= 0:
timer = 10 # Reset it to 10 or do something else.
screen.fill(gray)
txt = font.render(str(round(timer, 2)), True, blue)
screen.blit(txt, (70, 70))
pg.display.flip()
dt = clock.tick(30) / 1000 # / 1000 to convert to seconds.
if __name__ == '__main__':
main()
pg.quit()
There are several ways you can do this- here's one. Python doesn't have a mechanism for interrupts as far as I know.
import time, datetime
timer_stop = datetime.datetime.utcnow() +datetime.timedelta(seconds=10)
while True:
if datetime.datetime.utcnow() > timer_stop:
print "timer complete"
break
There are many ways to do this and it is one of them
import pygame,time, sys
from pygame.locals import*
pygame.init()
screen_size = (400,400)
screen = pygame.display.set_mode(screen_size)
pygame.display.set_caption("timer")
time_left = 90 #duration of the timer in seconds
crashed = False
font = pygame.font.SysFont("Somic Sans MS", 30)
color = (255, 255, 255)
while not crashed:
for event in pygame.event.get():
if event.type == QUIT:
crashed = True
total_mins = time_left//60 # minutes left
total_sec = time_left-(60*(total_mins)) #seconds left
time_left -= 1
if time_left > -1:
text = font.render(("Time left: "+str(total_mins)+":"+str(total_sec)), True, color)
screen.blit(text, (200, 200))
pygame.display.flip()
screen.fill((20,20,20))
time.sleep(1)#making the time interval of the loop 1sec
else:
text = font.render("Time Over!!", True, color)
screen.blit(text, (200, 200))
pygame.display.flip()
screen.fill((20,20,20))
pygame.quit()
sys.exit()
This is actually quite simple. Thank Pygame for creating a simple library!
import pygame
x=0
while x < 10:
x+=1
pygame.time.delay(1000)
That's all there is to it! Have fun with pygame!
Another way to do it is to set up a new USEREVENT for a tick, set the time interval for it, then put the event into your game loop
'''
import pygame
from pygame.locals import *
import sys
pygame.init()
#just making a window to be easy to kill the program here
display = pygame.display.set_mode((300, 300))
pygame.display.set_caption("tick tock")
#set tick timer
tick = pygame.USEREVENT
pygame.time.set_timer(tick,1000)
while 1:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.USEREVENT:
if event.type == tick:
## do whatever you want when the tick happens
print('My tick happened')

Doing something after a period of time: Pygame

I wanted to do something after a period of time. On stack overflow I found a question that helps solve that, (Link) but when I run the program the code works, however it goes away after a millisecond. Whereas I want it to stay there after the amount of time I want it to wait. In this case for a test run I am blitting some text onto the screen. Here is the code:
import pygame
# Importing the modules module.
pygame.init()
# Initializes Pygame
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
screen = pygame.display.set_mode((800, 600))
# Sets the screen to pygame looks and not normal python looks.
pygame.display.set_caption("Test Run")
# Changes the title
# Heading
headingfont = pygame.font.Font('Bouncy-PERSONAL_USE_ONLY.otf', 45)
headingX = 230
headingY = 10
class Other():
def show_heading():
Heading = headingfont.render("Health Run!", True, (255, 255, 255))
screen.blit(Heading, (headingX, headingY))
pygame.time.set_timer(pygame.USEREVENT, 100)
running = True
while running:
screen.fill((0,0,0))
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.USEREVENT:
Other.show_heading()
#Update Display
pygame.display.update()
If you want to draw the text permanently, you need to draw it in the application loop. Set a Boolean variable "draw_text" when the timer event occurs. Draw the text depending on draw_text in the application loop:
draw_text = False
running = True
while running:
screen.fill((0,0,0))
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.USEREVENT:
draw_text = True
if draw_text:
Other.show_heading()
#Update Display
pygame.display.update()
For more information about timers and timer events, see Spawning multiple instances of the same object concurrently in python, How can I show explosion image when collision happens? or Adding a particle effect to my clicker game and many more.

Pygame-Countdown Timer On Screen With Other Stuff [duplicate]

I started using pygame and I want to do simple game. One of the elements which I need is countdown timer.
How can I do the countdown time (eg 10 seconds) in PyGame?
Another easy way is to simply use pygame's event system.
Here's a simple example:
import pygame
pygame.init()
screen = pygame.display.set_mode((128, 128))
clock = pygame.time.Clock()
counter, text = 10, '10'.rjust(3)
pygame.time.set_timer(pygame.USEREVENT, 1000)
font = pygame.font.SysFont('Consolas', 30)
run = True
while run:
for e in pygame.event.get():
if e.type == pygame.USEREVENT:
counter -= 1
text = str(counter).rjust(3) if counter > 0 else 'boom!'
if e.type == pygame.QUIT:
run = False
screen.fill((255, 255, 255))
screen.blit(font.render(text, True, (0, 0, 0)), (32, 48))
pygame.display.flip()
clock.tick(60)
On this page you will find what you are looking for http://www.pygame.org/docs/ref/time.html#pygame.time.get_ticks
You download ticks once before beginning the countdown (which can be a trigger in the game - the key event, whatever).
For example:
start_ticks=pygame.time.get_ticks() #starter tick
while mainloop: # mainloop
seconds=(pygame.time.get_ticks()-start_ticks)/1000 #calculate how many seconds
if seconds>10: # if more than 10 seconds close the game
break
print (seconds) #print how many seconds
In pygame exists a timer event. Use pygame.time.set_timer() to repeatedly create an USEREVENT. e.g.:
timer_interval = 500 # 0.5 seconds
timer_event = pygame.USEREVENT + 1
pygame.time.set_timer(timer_event , timer_interval)
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 pygame.USEREVENT+1 is the event id for the timer event.
To disable the timer for an event, set the milliseconds argument to 0.
Receive the event in the event loop:
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == timer_event:
# [...]
The timer event can be stopped by passing 0 to the time parameter.
See the example:
import pygame
pygame.init()
window = pygame.display.set_mode((200, 200))
clock = pygame.time.Clock()
font = pygame.font.SysFont(None, 100)
counter = 10
text = font.render(str(counter), True, (0, 128, 0))
timer_event = pygame.USEREVENT+1
pygame.time.set_timer(timer_event, 1000)
run = True
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
elif event.type == timer_event:
counter -= 1
text = font.render(str(counter), True, (0, 128, 0))
if counter == 0:
pygame.time.set_timer(timer_event, 0)
window.fill((255, 255, 255))
text_rect = text.get_rect(center = window.get_rect().center)
window.blit(text, text_rect)
pygame.display.flip()
pygame.time.Clock.tick returns the time in milliseconds since the last clock.tick call (delta time, dt), so you can use it to increase or decrease a timer variable.
import pygame as pg
def main():
pg.init()
screen = pg.display.set_mode((640, 480))
font = pg.font.Font(None, 40)
gray = pg.Color('gray19')
blue = pg.Color('dodgerblue')
# The clock is used to limit the frame rate
# and returns the time since last tick.
clock = pg.time.Clock()
timer = 10 # Decrease this to count down.
dt = 0 # Delta time (time since last tick).
done = False
while not done:
for event in pg.event.get():
if event.type == pg.QUIT:
done = True
timer -= dt
if timer <= 0:
timer = 10 # Reset it to 10 or do something else.
screen.fill(gray)
txt = font.render(str(round(timer, 2)), True, blue)
screen.blit(txt, (70, 70))
pg.display.flip()
dt = clock.tick(30) / 1000 # / 1000 to convert to seconds.
if __name__ == '__main__':
main()
pg.quit()
There are several ways you can do this- here's one. Python doesn't have a mechanism for interrupts as far as I know.
import time, datetime
timer_stop = datetime.datetime.utcnow() +datetime.timedelta(seconds=10)
while True:
if datetime.datetime.utcnow() > timer_stop:
print "timer complete"
break
There are many ways to do this and it is one of them
import pygame,time, sys
from pygame.locals import*
pygame.init()
screen_size = (400,400)
screen = pygame.display.set_mode(screen_size)
pygame.display.set_caption("timer")
time_left = 90 #duration of the timer in seconds
crashed = False
font = pygame.font.SysFont("Somic Sans MS", 30)
color = (255, 255, 255)
while not crashed:
for event in pygame.event.get():
if event.type == QUIT:
crashed = True
total_mins = time_left//60 # minutes left
total_sec = time_left-(60*(total_mins)) #seconds left
time_left -= 1
if time_left > -1:
text = font.render(("Time left: "+str(total_mins)+":"+str(total_sec)), True, color)
screen.blit(text, (200, 200))
pygame.display.flip()
screen.fill((20,20,20))
time.sleep(1)#making the time interval of the loop 1sec
else:
text = font.render("Time Over!!", True, color)
screen.blit(text, (200, 200))
pygame.display.flip()
screen.fill((20,20,20))
pygame.quit()
sys.exit()
This is actually quite simple. Thank Pygame for creating a simple library!
import pygame
x=0
while x < 10:
x+=1
pygame.time.delay(1000)
That's all there is to it! Have fun with pygame!
Another way to do it is to set up a new USEREVENT for a tick, set the time interval for it, then put the event into your game loop
'''
import pygame
from pygame.locals import *
import sys
pygame.init()
#just making a window to be easy to kill the program here
display = pygame.display.set_mode((300, 300))
pygame.display.set_caption("tick tock")
#set tick timer
tick = pygame.USEREVENT
pygame.time.set_timer(tick,1000)
while 1:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.USEREVENT:
if event.type == tick:
## do whatever you want when the tick happens
print('My tick happened')

Categories

Resources