# not working yet
import solara
import numpy as np
import asyncio
import time
import pyxel
data = solara.reactive(None)
width = 320
height = 200
screen = None
canvas = None
### BOILERPLATE START ###
def setup():
global screen, canvas
import js
canvas = js.OffscreenCanvas.new(width, height)
canvas.id = "canvas" # emscripten wants this?
canvas.style = js.Object.new() # otherwise we'll get a style.cursor error
js.pyodide.canvas.setCanvas2D(canvas)
# # emscripten assumes globalThis.screen to exist
js.screen = {
"width": width,
"height": height,
}
# # pygame.display.init()
# # we define a mock globalThis.window, and to
# # avoid 'eventHandler.target.addEventListener is not a function'
# # we put in this mock addEventListener
js.window.addEventListener = js.Function.new()
js.window.removeEventListener = js.Function.new()
# # monkey patch document
js.document = js.Object.new()
js.document.querySelector = lambda x: js.window
js.document.fullscreenEnabled = False
js.document.addEventListener = js.Function.new()
# crashes here
pyxel.init(160, 120, title="Hello Pyxel")
# screen = pygame.display.set_mode((width, height))
def transfer_image():
# read off a pixel from the canvas
context = canvas.getContext("2d")
# can possibly be faster?
mem_obj = context.getImageData(0, 0, width, height).data.to_py()
np_array = np.frombuffer(mem_obj, dtype=np.uint8)
np_array.shape = (height, width, 4)
data.value = np_array
# ideally, all the above boilerplate goes away
### BOILERPLATE END ###
setup()
async def game_loop():
# player_pos.x = 10
frames = 5
t0 = time.time()
for i in range(frames):
# screen.fill("red")
# pygame.draw.circle(screen, "blue", player_pos, 40)
# pygame.display.flip()
# transfer_image()
await asyncio.sleep(1./frames)
# player_pos.x += width/frames
t1 = time.time()
print("fps", frames/(t1-t0))
class App:
def __init__(self):
pyxel.init(160, 120, title="Hello Pyxel")
pyxel.images[0].load(0, 0, "assets/pyxel_logo_38x16.png")
pyxel.run(self.update, self.draw)
def update(self):
if pyxel.btnp(pyxel.KEY_Q):
pyxel.quit()
def draw(self):
pyxel.cls(0)
pyxel.text(55, 41, "Hello, Pyxel!", pyxel.frame_count % 16)
pyxel.blt(61, 66, 0, 0, 0, 38, 16)
# App()
reset_counter = solara.reactive(0)
def reset():
reset_counter.value += 1
@solara.component
def Page():
solara.Button(label=f"Restart", on_click=reset, outlined=True, color="primary")
solara.lab.use_task(game_loop, dependencies=[reset_counter.value])
if data.value is not None:
solara.Image(data.value)