I'm new to working with Pyglet and I've written a small program which moves a ball around the screen. Right now I'm having difficulty establishing a steady frame rate of 60 fps. While Pyglet is supposed to sync with my monitor's refresh rate of 60Hz, Pyglet is setting my fps to half of my refresh rate (ex. when 60Hz, 30 fps). Is there something wrong in my code that is causing this?
import pyglet
import physicalobject
import random
from pyglet.window import mouse
pyglet.resource.path = ['./resources']
pyglet.resource.reindex()
ball_image = pyglet.resource.image("ball2.png")
#sets clock format
fps_display = pyglet.clock.ClockDisplay(format='%(fps).2f fps')
def center_image(image):
image.anchor_x = image.width/2
image.anchor_y = image.height/2
center_image(ball_image)
ball = physicalobject.PhysicalObject(img=ball_image, x = 400, y = 300)
ball.scale = .2
ball.velocity_x = random.randint(-4,4)*150
ball.velocity_y = random.randint(-4,4)*150
#Calls update function to set new ball position based on velocity
def update(dt):
ball.update(dt)
#window.event
def on_mouse_drag(x, y, dx, dy, button, modifiers):
ball.x = x
ball.y = y
ball.velocity_x = dx * 20
ball.velocity_y = dy * 20
#window.event
def on_draw():
window.clear()
ball.draw()
fps_display.draw()
def main():
pyglet.clock.schedule_interval(update, 1/120.0)
pyglet.app.run()
if __name__ == '__main__':
main()
Pyglet simply doesn't handle it correctly on some systems, you have to disable your application window's vsync in order to get it to work. Here's an example script you can run to get a feel for how it works:
import pyglet
# Show FPS
fps = pyglet.clock.ClockDisplay()
# The game window
class Window(pyglet.window.Window):
def __init__(self):
super(Window, self).__init__(vsync = False)
# Run "self.update" 128 frames a second and set FPS limit to 128.
pyglet.clock.schedule_interval(self.update, 1.0/128.0)
pyglet.clock.set_fps_limit(128)
# You need the dt argument there to prevent errors,
# it does nothing as far as I know.
def update(self, dt):
pass
def on_draw(self):
pyglet.clock.tick() # Make sure you tick the clock!
self.clear()
fps.draw()
# Create a window and run
win = Window()
pyglet.app.run()
import pyglet
from time import time, sleep
class Window(pyglet.window.Window):
def __init__(self, refreshrate):
super(Window, self).__init__(vsync = False)
self.frames = 0
self.framerate = pyglet.text.Label(text='Unknown', font_name='Verdana', font_size=8, x=10, y=10, color=(255,255,255,255))
self.last = time()
self.alive = 1
self.refreshrate = refreshrate
def on_draw(self):
self.render()
def render(self):
self.clear()
if time() - self.last >= 1:
self.framerate.text = str(self.frames)
self.frames = 0
self.last = time()
else:
self.frames += 1
self.framerate.draw()
self.flip()
def on_close(self):
self.alive = 0
def run(self):
while self.alive:
self.render()
event = self.dispatch_events()
sleep(1.0/self.refreshrate)
win = Window(23) # set the fps
win.run()
Note the lack of the clock feature.
Also, try setting vsync = True and removing the sleep(1.0/self.refreshrate), this will lock the refresh rate to your monitor.
Also, note that i don't use pyglet.app.run() to lock the rendering process, i call self.dispatch_events() instead.. it doesn't really do anything except let the graphic "poll" and move on, without it.. pyglet waits for a poll to occur, which pyglet.app.run() normally does.
Related
Currently, I am loading all images at the start of the program. Is there a better solution for this? As some images may not be used at all throughout the entire game (I'm currently making a main menu).
Main.py
import pygame as pg
from Menu import Menu
pg.init()
"""Displays screen"""
winWidth = 1920
winHeight = 1080
size = (winWidth, winHeight)
win = pg.display.set_mode(size)
"""Load images"""
bg_img = pg.image.load('Pic/td-gui/PNG/menu/bg.png')
title_img = pg.image.load('transtitle.png')
settings_img = pg.image.load('Pic/td-gui/PNG/menu/button_settings.png')
play_img = pg.image.load('Pic/td-gui/PNG/menu/button_play.png')
reg_img = pg.image.load('Pic/td-gui/PNG/menu/button_registration.png')
quit_img = pg.image.load('Custom/Menu/Quit.png')
rope_img = pg.image.load('Pic/td-gui/PNG/menu/rope_small.png')
changeDiff_img = pg.image.load('Custom/Menu/Change_Difficulty.png')
score_img = pg.image.load('Custom/Menu/Scoreboard.png')
selectmap_img = pg.image.load('Custom/Menu/Select_map.png')
tutorial_img = pg.image.load('Custom/Menu/Tutorial.png')
"""Puts loaded images into the correct size"""
bg_img = pg.transform.scale(bg_img,(winWidth, winHeight))
title_img = pg.transform.scale(title_img, (750, 75))
play_img = pg.transform.scale(play_img, (250, 250))
rope_img = pg.transform.scale(rope_img, (27, 290))
clock = pg.time.Clock()
win.blit(bg_img, (0, 0))
mainMenu = True
settingsMenu = False
run = True
running = True
while run:
clock.tick(30)
pg.display.update()
for event in pg.event.get():
if event.type == pg.QUIT:
run = False
if not run:
pg.quit()
"""Places correct images in specified location"""
title = Menu(winWidth // 2 - 375, winHeight // 2 - 500, title_img)
if mainMenu:
reg_button = Menu(winWidth // 2 - 150, winHeight // 2 - 100, reg_img)
ropeR = Menu(winWidth // 2 - 100, 200, rope_img)
ropeL = Menu(winWidth // 2 + 70, 200, rope_img)
scoreboard_button = Menu(winWidth//2 - 330, winHeight//2 + 275, score_img)
play_button = Menu(winWidth // 2 - 125, winHeight // 2 - 375, play_img)
reg_button = Menu(winWidth // 2 - 161, winHeight // 2 - 100, reg_img)
quit_button = Menu(winWidth//2 + 30, winHeight//2 + 275, quit_img)
changeDiff_button = Menu(winWidth//2 - 330, winHeight//2 + 80, changeDiff_img)
selectmap_button = Menu(winWidth//2 + 30, winHeight//2 + 80, selectmap_img)
settings_button = Menu(winWidth - 200, winHeight - 200, settings_img)
"""Draws images in specified location and makes buttons if specified"""
title.draw_img(win)
if reg_button.draw_button(win):
print('Reg button clicked')
ropeL.draw_img(win)
ropeR.draw_img(win)
if scoreboard_button.draw_button(win):
print("options Clicked")
if play_button.draw_button(win):
print("Play Clicked")
if quit_button.draw_button(win):
pg.quit()
if changeDiff_button.draw_button(win):
print('Change Difficulty button pressed')
if selectmap_button.draw_button(win):
print('Select Map button preseed')
if settings_button.draw_button(win):
print('Settings button pressed')
mainMenu = False
settingsMenu = True
if settingsMenu:
win.blit(bg_img, (0, 0))
title.draw_img(win)
Menu.py
import pygame as pg
pg.init()
class Menu():
def __init__(self, x, y, img):
self.img = img
self.rect = self.img.get_rect()
self.rect.y = y
self.rect.x = x
self.clicked = False
def draw_button(self, win):
action = False
#get mouse position
pos = pg.mouse.get_pos()
#check mouseover and clicked conditions
if self.rect.collidepoint(pos):
if pg.mouse.get_pressed()[0] == 1 and not self.clicked:
action = True
self.clicked = True
if pg.mouse.get_pressed()[0] == 0:
action = False
#draw image
win.blit(self.img, (self.rect.x, self.rect.y))
return action
def draw_img(self, win):
win.blit(self.img, (self.rect.x, self.rect.y))
Say I'm making a music button, which is accessible through the settings button, I would currently load the music button image at the start of the program. Is there a way to make it so the music image would only be loaded once the settings button has been pressed?
To give a quick and simple overview of what you could do, here's an example. You define an abstract Scene class. Then, every "scene" in your game inherits from it. Each scene has a setup method that loads everything the scene needs (or might need).
import pygame
class Scene:
def __init__(self):
""" Create all attributes """
def setup(self):
""" Load everything in and initialize attributes """
def handle_events(self, events):
""" Handle the events for this scene """
def update(self, dt):
""" Run logic """
def render(self, screen):
""" Draw to the screen """
class Menu(Scene):
def __init__(self):
""" Create all attributes """
self.image1 = None
self.image2 = None
# ... and so on ...
def setup(self):
""" Load everything in and initialize attributes """
self.image1 = pygame.image.load("my_image1.png")
self.image2 = pygame.image.load("my_image2.png")
# ... and so on ...
def handle_events(self, events):
""" Handle the events for this scene """
def update(self, dt):
""" Run logic """
def render(self, screen):
""" Draw to the screen """
screen.blit(self.image1, (0, 0))
# ... and so on ...
class Game(Scene):
def __init__(self):
""" Create all attributes """
self.player = None
self.enemies = None
# ... and so on ...
def setup(self):
""" Load everything in and initialize attributes """
self.player = Player(position=(100, 100), image=pygame.image.load("player.png"))
self.enemies = [
Enemy(position=(200, 400), pygame.image.load("enemy1.png")),
Enemy(position=(200, 500), pygame.image.load("enemy2.png")),
]
# ... and so on ...
def handle_events(self, events):
""" Handle the events for this scene """
for event in events:
if event.type == pygame.KEY_DOWN:
print('PAM!')
def update(self, dt):
""" Run logic """
self.player.update(dt)
for enemy in self.enemies:
enemy.update()
def render(self, screen):
""" Draw to the screen """
screen.blit(self.player.image, self.player.position)
for enemy in self.enemies:
screen.blit(enemy.image, enemy.position)
# ... and so on ...
Here's roughly how a game loop would look like.
def main():
screen = pygame.display.set_mode((1024, 1024))
clock = pygame.time.Clock()
running = True
scene = Menu()
scene.setup()
while running:
dt = clock.tick(60)
events = list(pygame.event.get())
scene.handle_events(events)
scene.update(dt)
scene.render(screen)
# Have some way of determining when to switch scene.
if should_switch_to_game:
scene = Game()
scene.setup()
elif should_switch_to_menu:
scene = Menu()
scene.setup()
# ... and so on ...
This is a basic starting point, but there are other ways to handle the situation, like having an asset manager that dynamically load and unload assets based on usage. However, these are quite complicated and will make development and debugging much harder. It's always best to keep things simple when you can. If you can load all images at the beginning of the program, then I'd suggest doing so.
Also, remember that there's nothing that's "best" or "optimized" as all you're doing is tradeoffs. If you're trying to optimize for memory, then you're often making your program slower. If you're optimizing for speed, then you're often making your program use more memory.
If you are loading things just when you need them, you're going to have a loading time switching between different views in your menu. This is often not something you want as the user expects it to be fast. Switching from the game to the menu, it's more forgiving to have a couple of extra ms. But if you feel you want to go the other way then different views in the menu could be considered different scenes.
In general, no it's not a problem to load images that are never used, as long as the images are small. It's better to load them all at once so that the interface never has to wait for loading.
However, if you have a very large amount of images or your images are very big, it might be worth loading some images only when you need them. You could do something like this when you start your music field:
def start_music_menu():
global music_icon # Sorry about the global
if music_icon is None:
music_icon = pygame.image.load('...')
In this case your interface will freeze while loading the extra image. You can also use threading or asyncio to keep your interface responsive while a image is loading.
Properly use OOP concept make separate class for various loading image and then use them accordingly .
Given that so far I have always used Pygame, I wanted to start using Pyglet, to understand a little how it works.
import pyglet, os
class runGame():
widthDisplay = 1024
heightDiplay = 576
title = "Pokémon Life and Death: Esploratori del proprio Destino"
wra = pyglet.image.load("wra.png")
wrb = pyglet.image.load("wrb.png")
def __init__(self):
platform = pyglet.window.get_platform()
display = platform.get_default_display()
screen = display.get_default_screen()
self.widthScreen = screen.width
self.heightScreen = screen.height
self.xDisplay = int(self.widthScreen / 2 - self.widthDisplay / 2)
self.yDisplay = int(self.heightScreen / 2 - self.heightDiplay / 2)
self.Display = pyglet.window.Window(width=self.widthDisplay, height=self.heightDiplay, caption=self.title, resizable=False)
self.Display.set_location(self.xDisplay, self.yDisplay)
pyglet.app.run()
game = runGame()
Up to here everything is fine and everything works correctly. But I was wrong, in the sense, now that I have to draw something, how should I do? In the sense, can Pyglet stay in a class like Pygame or not?
The marked solution might solve the problem.
However, in my opinion it doesn't really add more functionality than you can already achieve.
If you truly want to make Pyglet into a class, you actually gotta inherit something, or make use of the possibility of programming in a OOP way i recon.
Here's my two cents:
import pyglet
from pyglet.gl import *
from collections import OrderedDict
from time import time
key = pyglet.window.key
class main(pyglet.window.Window):
def __init__ (self, width=1024, height=576, caption="Pokémon Life and Death: Esploratori del proprio Destino", fps=True, *args, **kwargs):
super(main, self).__init__(width, height, *args, **kwargs)
platform = pyglet.window.get_platform()
display = platform.get_default_display()
screen = display.get_default_screen()
self.xDisplay = int(screen.width / 2 - self.width / 2)
self.yDisplay = int(screen.height / 2 - self.height / 2)
self.set_location(self.xDisplay, self.yDisplay)
self.sprites = OrderedDict()
if fps:
self.sprites['fps_label'] = pyglet.text.Label('0 fps', x=10, y=10)
self.last_update = time()
self.fps_count = 0
self.keys = OrderedDict()
self.mouse_x = 0
self.mouse_y = 0
self.alive = 1
def on_draw(self):
self.render()
def on_close(self):
self.alive = 0
def on_mouse_motion(self, x, y, dx, dy):
self.mouse_x = x
self.mouse_y = y
def on_mouse_release(self, x, y, button, modifiers):
print('Released mouse at {}x{}'.format(x, y))
def on_mouse_press(self, x, y, button, modifiers):
if button == 1:
print('Pressed mouse at {}x{}'.format(x, y))
def on_mouse_drag(self, x, y, dx, dy, button, modifiers):
self.drag = True
print('Dragging mouse at {}x{}'.format(x, y))
def on_key_release(self, symbol, modifiers):
try:
del self.keys[symbol]
except:
pass
def on_key_press(self, symbol, modifiers):
if symbol == key.ESCAPE: # [ESC]
self.alive = 0
self.keys[symbol] = True
def pre_render(self):
pass
def render(self):
self.clear()
# FPS stuff (if you want to)
self.fps_count += 1
if time() - self.last_update > 1: # 1 sec passed
self.sprites['fps_label'].text = str(self.fps_count)
self.fps_count = 0
self.last_update = time()
#self.bg.draw()
self.pre_render()
for sprite in self.sprites:
self.sprites[sprite].draw()
self.flip()
def run(self):
while self.alive == 1:
self.render()
# -----------> This is key <----------
# This is what replaces pyglet.app.run()
# but is required for the GUI to not freeze
#
event = self.dispatch_events()
if __name__ == '__main__':
x = main()
x.run()
This way, you can actually interact with your class as if it were the pyglet class. For instance, you got on_key_press without having to use decorators etc.
You should make more functions for each thing you are doing. For example if you want to make a line you might have
import pyglet, os
class runGame():
widthDisplay = 1024
heightDiplay = 576
title = "Pokémon Life and Death: Esploratori del proprio Destino"
wra = pyglet.image.load("wra.png")
wrb = pyglet.image.load("wrb.png")
def __init__(self):
platform = pyglet.window.get_platform()
display = platform.get_default_display()
screen = display.get_default_screen()
self.widthScreen = screen.width
self.heightScreen = screen.height
self.xDisplay = int(self.widthScreen / 2 - self.widthDisplay / 2)
self.yDisplay = int(self.heightScreen / 2 - self.heightDiplay / 2)
self.Display = pyglet.window.Window(width=self.widthDisplay, height=self.heightDiplay, caption=self.title, resizable=False)
self.Display.set_location(self.xDisplay, self.yDisplay)
pyglet.app.run()
def drawLine(x, y):
drawLine(x, y)
You will have to make the functions based on what you want to do, but if you aren't going to use the runGame class multiple times before you kill the program, you shouldn't use OOP programming and use Procedural Programming.
You can create a custom pyglet window, by inheriting from the pyglet.window.Window class. After that in your init method call the super classes init (this will call the the init inside pyglet.window.Window class )Then overwrite the inherited methods (on_draw, on_key_press, on_key_release etc.). After that create an update method, which will be called by the pyglet.clock.schedule_interval 60 times in a second.Lastly just call the pyglet.app.run() method.
import pyglet
class GameWindow(pyglet.window.Window):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
def on_draw(self):
self.clear()
def on_mouse_press(self, x, y, button, modifiers):
pass
def on_mouse_release(self, x, y, button, modifiers):
pass
def on_mouse_motion(self, x, y, dx, dy):
pass
def update(self, dt):
pass
if __name__ == "__main__":
window = GameWindow(1280, 720, "My Window", resizable=False)
pyglet.clock.schedule_interval(window.update, 1/60.0)
pyglet.app.run()
I'm trying to make a simple application with pyglet. My main problem so far is that I can't seem to blit an image with alpha - all of the transparent pixels are converted into black pixels. I'm not sure whether the problem is with the loading of the image or the blitting. Here is a very basic overview of how I'm trying to render the image:
import pyglet
import pyglet.clock
window = pyglet.window.Window()
window.config.alpha_size = 8
#fancy text
text = pyglet.resource.image("text.png")
#background image
bg = pyglet.resource.image("bg.png")
bg.blit(0, 0)
text.blit(100, 100)
pyglet.app.run()
Any help is appreciated. Thanks in advance.
You most likely just need to enable GL ALPHA blends.
from pyglet.gl import *
glEnable(GL_BLEND)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
But first of all, your code is not able to run.
Mostly because you don't declare a window.event function to handle the on_draw where you normally render things.
Secondly, you never clear your window (which will cause a mess).
Here's a minimal working example of your code:
import pyglet
import pyglet.clock
window = pyglet.window.Window()
window.config.alpha_size = 8
#fancy text
text = pyglet.resource.image("text.png")
#background image
bg = pyglet.resource.image("bg.png")
#window.event
def on_draw():
window.clear()
bg.blit(0, 0)
text.blit(100, 100)
pyglet.app.run()
Now this generates this:
And here's a working example of how you use the GL_BLEND feature:
import pyglet
import pyglet.clock
from pyglet.gl import *
window = pyglet.window.Window()
window.config.alpha_size = 8
#fancy text
text = pyglet.resource.image("text.png")
#background image
bg = pyglet.resource.image("bg.png")
#window.event
def on_draw():
window.clear()
glEnable(GL_BLEND)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
bg.blit(0, 0)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
text.blit(100, 100)
pyglet.app.run()
This yields a result like so:
However, this code will quickly become messy.
So there's two things you can do. You can first, put your images into sprite objects. Secondly, make this a bit more object oriented.
First, we'll use sprites.
self.fancy_background = pyglet.sprite.Sprite(pyglet.image.load('bg.png'))
self.fancy_background.draw() # not blit!
Sprites automatically uses transparency, which makes your life (and code) a lot easier.
Secondly, we'll put these into a batch.
Batches are made to bunch A LOT of sprites so you can call .draw() on the batch, and all sprites in that batch gets insta-rendered.
self.background = pyglet.graphics.Batch()
self.fancy_background = pyglet.sprite.Sprite(pyglet.image.load('bg.png'), batch=self.background)
self.background.draw() # background, not fancy_background! And also not blit!!
Last and most certainly not least.
We'll put this into a class so we can do cool stuff later on.
import pyglet
import pyglet.clock
from pyglet.gl import *
key = pyglet.window.key
class main(pyglet.window.Window):
def __init__ (self, width=800, height=600, fps=False, *args, **kwargs):
super(main, self).__init__(width, height, *args, **kwargs)
self.x, self.y = 0, 0
self.background = pyglet.graphics.Batch()
self.texts = pyglet.graphics.Batch()
self.fancy_background = pyglet.sprite.Sprite(pyglet.image.load('bg.png'), batch=self.background)
self.fancy_text = pyglet.sprite.Sprite(pyglet.image.load('text.png'), batch=self.texts)
self.mouse_x = 0
self.mouse_y = 0
self.alive = 1
def on_draw(self):
self.render()
def on_close(self):
self.alive = 0
def on_mouse_motion(self, x, y, dx, dy):
self.mouse_x = x
self.mouse_y = y
def on_mouse_press(self, x, y, button, modifiers):
if button == 1: # Left click
pass
def on_key_press(self, symbol, modifiers):
if symbol == key.ESCAPE: # [ESC]
self.alive = 0
def render(self):
self.clear()
self.background.draw()
self.texts.draw()
self.flip()
def run(self):
while self.alive == 1:
self.render()
# -----------> This is key <----------
# This is what replaces pyglet.app.run()
# but is required for the GUI to not freeze
#
event = self.dispatch_events()
if __name__ == '__main__':
x = main()
x.run()
BAM.
This code will enable you to create custom functions and custom "player objects" later on for instance. Also you can do collision detection easier and the code just looks a lot more structured (I threw in a little bonus features such as keyboard and mouse events).
Note tho, that the position of the sprites will default to x=0, y=0 as shown in the last picture. You can set the position with x=100 either on the variable/handle or when creating the sprite.
couple of days ago, I made a code that plays a video in pygame window.
Code works just fine, just as I originally intended. However, when I print debug statement to see its fps, it's somewhere around 30fps. If I were to increase fps, what should I do?
Here is the code I used.
import sys
from color import *
import pyglet
pygame.init()
running = True
gameDisplay= pygame.display.set_mode((800,600))
window = pyglet.window.Window(visible=False)
background_vid = pyglet.media.Player()
background_vid.queue(pyglet.media.load(".\\music_folder\\music_vid/servant_of_evil_converted.mp4"))
background_vid.play()
def hellow():
print "hellow bloody world"
def on_draw():
#We have to convert the Pyglet media player's image to a Pygame surface
rawimage = background_vid.get_texture().get_image_data()
print "rawimage "+str(rawimage)
pixels = rawimage.get_data('RGBA', rawimage.width *8)
video = pygame.image.frombuffer(pixels, (rawimage.width*2,rawimage.height), 'RGBA')
#Blit the image to the screen
gameDisplay.blit(video, (0, 0))
circle_x=300
while True:
pyglet.clock.tick()
on_draw()
print "fps: "+str(pyglet.clock.get_fps())
for event in pygame.event.get():
if(event.type == pygame.QUIT):
sys.exit()
pygame.quit()
pygame.draw.rect(gameDisplay, red, (circle_x, 300, 300, 300), 5)
circle_x+=1
pygame.display.update()
So what #pydude said is not completely wrong.
However, in order to actually messure FPS I'd put a custom counter in the on_draw function, that will give better accuracy.
Further more, the only real problem with your code is that you don't insert vsync=False into your Window() decorator.
I've reworked your code to make it a little bit more modular, I've also removed potential bottle-necks and added my own custom FPS counter (via GL and not console), here - have a go and see if it works better for you.
(Note: Pressing Escape will exit the application)
import sys
from color import *
import pyglet
from pyglet.gl import *
from time import time # Used for FPS calc
key = pyglet.window.key
class main(pyglet.window.Window):
def __init__ (self):
super(main, self).__init__(800, 800, fullscreen = False, vsync = True)
self.running = True
self.background_vid = pyglet.media.Player()
self.background_vid.queue(pyglet.media.load(".\\music_folder\\music_vid/servant_of_evil_converted.mp4"))
self.background_vid.play()
self.fps_counter = 0
self.last_fps = time()
self.fps_text = pyglet.text.Label(str(self.fps_counter), font_size=12, x=10, y=10)
def on_key_press(self, symbol, modifiers):
if symbol == key.ESCAPE: # [ESC]
self.running = False
def on_draw(self):
self.render()
#We have to convert the Pyglet media player's image to a Pygame surface
def render(self):
self.clear()
rawimage = background_vid.get_texture().get_image_data()
pixels = rawimage.get_data('RGBA', rawimage.width *8)
video = pygame.image.frombuffer(pixels, (rawimage.width*2,rawimage.height), 'RGBA')
#Blit the image to the screen
self.blit(video, (0, 0))
# And flip the GL buffer
self.fps_counter += 1
if time() - self.last_fps > 1:
self.fps_text.text = str(self.fps_counter)
self.fps_counter = 0
self.last_fps = time()
self.fps_text.draw()
self.flip()
def run(self):
while self.running is True:
self.render()
# -----------> This is key <----------
# This is what replaces pyglet.app.run()
# but is required for the GUI to not freeze
#
event = self.dispatch_events()
if event and event.type == pygame.QUIT:
self.running = False
x = main()
x.run()
Try toggling vsync = True to vsync = False and watch the difference in the FPS counter.
With python, printing is very slow. Try just printing every once and a while.
Example:(requires import random):
if random.random()>0.09:print "fps: "+str(pyglet.clock.get_fps())
I do not understand completely how to use pyglet's event system. What I need to do is to get each event for each frame. In Pygame I can do it in the following way:
import sys, pygame
pygame.init()
size = width, height = 320, 240
screen = pygame.display.set_mode(size)
while 1:
for event in pygame.event.get():
print event
if event.type == pygame.QUIT: sys.exit()
screen.fill((0,0,0))
pygame.display.flip()
I accomplish something similar with pyglet, using 'pyglet.window.event.WindowEventLogger()' but I do not how to acces to the information that the WindowEventLogger prints, and it prints the same event more than once.
How could I obtain a pyglet version of the pygame code above?
Here's a basic example of a working class that dispatches events.
#!/usr/bin/python
import pyglet
from time import time, sleep
class Window(pyglet.window.Window):
def __init__(self, refreshrate):
super(Window, self).__init__(vsync = False)
self.frames = 0
self.framerate = pyglet.text.Label(text='Unknown', font_name='Verdana', font_size=8, x=10, y=10, color=(255,255,255,255))
self.last = time()
self.alive = 1
self.refreshrate = refreshrate
def on_draw(self):
self.render()
def render(self):
self.clear()
if time() - self.last >= 1:
self.framerate.text = str(self.frames)
self.frames = 0
self.last = time()
else:
self.frames += 1
self.framerate.draw()
self.flip()
def on_close(self):
self.alive = 0
def run(self):
while self.alive:
self.render()
event = self.dispatch_events() # <-- This is the event queue
sleep(1.0/self.refreshrate)
win = Window(23) # set the fps
win.run()
However note that normally I never encounter any events at all in this event queue. Most likely because Pyglet works with function decorators/hooks.
So for instance, if you want to catch keyboard events, you would simply add the following code to this awesome class:
def on_key_release(self, symbol, modkey):
print(symbol, modkey)
There's also on_mouse_motion etc :)