Pygame#
pygame-ce can be used in
{exec} python blocks by listing it in the
exec.python.packages metadata.
Define the PYGAME_HIDE_SUPPORT_PROMPT environment variable to prevent console
output while importing pygame.
exec:
python:
packages: [pygame-ce]
env:
PYGAME_HIDE_SUPPORT_PROMPT:
Important
Code using Pygame must run in the main environment.
Tip
Pygame grabs the keyboard in pygame.init(), and releases it in
pygame.quit(). If the program exits without calling the latter, the page will
not respond to keyboard input anymore (e.g. typing in an editor won't have any
effect). It is useful to have a code block like the following on the page, to
force releasing the keyboard if this happens.
import pygame; pygame.quit()
import tdoc.pygame
setup_canvas()
Changes required#
Pygame programs require a few minor adjustments to run in the browser.
The rendering canvas must be created prior to setting the display mode by calling
setup_canvas().Calls to
pygame.timefunctions, includingClockmethods, must be replaced with asynchronous calls to subtitutes. This requires the main loop to be made asynchronous as well.Calls to
pygame.event.wait()must be replaced with a loop callingpygame.event.poll()and sleeping asynchronously while no event is available.
Pygame |
Replacement |
|---|---|
|
|
|
|
|
|
|
|
The program below is a slightly modified version of the
liquid.py
example in the pygame-ce repository, converted to an asynchronous main loop.
Press Q or click a mouse button to terminate.
1import pygame
2import math
3
4async def main():
5 pygame.init()
6 screen = pygame.display.set_mode((640, 480), pygame.DOUBLEBUF)
7
8 bitmap = pygame.image.load("liquid.png")
9 bitmap = pygame.transform.scale2x(bitmap)
10 bitmap = pygame.transform.scale2x(bitmap)
11
12 if screen.get_bitsize() == 8:
13 screen.set_palette(bitmap.get_palette())
14 else:
15 bitmap = bitmap.convert()
16
17 xblocks = range(0, 640, 20)
18 yblocks = range(0, 480, 20)
19 running = True
20 t = animation_time() / 1000
21 while running:
22 for e in pygame.event.get():
23 if (e.type == pygame.MOUSEBUTTONDOWN
24 or (e.type == pygame.KEYDOWN and e.key == pygame.K_q)):
25 running = False
26
27 for x in xblocks:
28 xpos = (x + (math.sin(t + x * 0.01) * 15)) + 20
29 for y in yblocks:
30 ypos = (y + (math.sin(t + y * 0.01) * 15)) + 20
31 screen.blit(bitmap, (x, y), (xpos, ypos, 20, 20))
32
33 t = await animation_frame() / 1000
34 pygame.display.flip()
35
36try:
37 await main()
38finally:
39 pygame.quit()
Using resource files#
The example below demonstrates loading resources from files specified in the
exec.python.files metadata. Press
Q to terminate the program.
1import pygame
2from random import randint
3
4width, height = 600, 600
5
6async def main():
7 pygame.init()
8 window = pygame.display.set_mode((width, height))
9 pygame.event.set_grab(True)
10 pygame.mouse.set_visible(False)
11
12 class Sprite(pygame.sprite.Sprite):
13 def __init__(self, cx, cy):
14 super().__init__()
15 self.rect = self.image.get_rect()
16 self.rect.centerx, self.rect.centery = cx, cy
17
18 class Pineapple(Sprite):
19 image = pygame.image.load("pineapple.png").convert_alpha()
20
21 class Basket(Sprite):
22 image = pygame.image.load("basket.png").convert_alpha()
23
24 class Text(pygame.sprite.Sprite):
25 font = pygame.font.Font(None, 36)
26
27 def __init__(self, cx, cy, *args):
28 super().__init__()
29 self.image = self.font.render(*args)
30 self.rect = self.image.get_rect()
31 self.rect.centerx, self.rect.centery = cx, cy
32
33 pineapples = pygame.sprite.LayeredUpdates()
34 sprites = pygame.sprite.LayeredUpdates()
35 basket = Basket(width / 2, height - Basket.image.get_rect().height / 2)
36 sprites.add(basket)
37
38 game_over = False
39 score = 0
40 running = True
41 while running:
42 await animation_frame()
43 pygame.display.flip()
44
45 window.fill((36, 242, 232))
46 pineapples.draw(window)
47 sprites.draw(window)
48
49 for event in pygame.event.get():
50 if event.type == pygame.KEYDOWN and event.key == pygame.K_q:
51 running = False
52 if event.type == pygame.MOUSEMOTION:
53 basket.rect.centerx = event.pos[0]
54
55 if game_over: continue
56 if randint(0, 60) == 0:
57 pineapple = Pineapple(randint(0, width - 1),
58 -Pineapple.image.get_rect().height / 2)
59 pineapples.add(pineapple)
60 for pineapple in pineapples.sprites():
61 pineapple.rect.y += 5
62 if pineapple.rect.colliderect(basket):
63 score += 1
64 pineapple.kill()
65 if pineapple.rect.y > height:
66 game_over = True
67 sprites.add(Text(
68 window.get_rect().centerx, window.get_rect().centery,
69 f"Game over. Score: {score}", True, (10, 10, 10),
70 (255, 90, 20)))
71
72try:
73 await main()
74finally:
75 pygame.quit()
Examples from Pygame repository#
Some of the
examples in
the pygame-ce repository can be run unchanged by monkey-patching the
functionality of Pygame related to time. This only works on
Chromium-based browsers.
For the examples below, the .py files and all required assets are loaded
directly from GitHub into the in-memory filesystem.
Note
The examples cannot be interrupted via the button. If a program doesn't terminate, reload the page.
Aliens#
Move the vehicle left and right with the cursor keys, and fire with Space. Terminate the program with Esc.
1import pygame
2try:
3 from aliens import main
4 main()
5finally:
6 pygame.quit()
Events and inputs#
Terminate the program with Esc.
1import pygame
2try:
3 from eventlist import main
4 main()
5except SystemExit:
6 pass
7finally:
8 pygame.quit()