// # Clone by Brendan McGrath of:
// # "Hello Pyscript" by Brendan McGrath
// # https://ancientbrain.com/world.php?world=5833407984
// # Please leave this clone trail here.
// # Clone by Brendan McGrath of:
// # "Python demo (customisable)" by Starter user
// # https://ancientbrain.com/world.php?world=4219533706
// # Please leave this clone trail here.
// The rule for how this API handles Python 'print' output:
// If we have an element with id="ab-python-console" then 'print' appends to it.
// If such an element does not exist, 'print' writes to the console.
// choose one of:
// <script type="py">
// <script type="mpy">
document.write(`
<style>
#fancy-output {
font-family: "Fira Mono", "Consolas", monospace;
color: #2b90d9;
background: #222;
padding: 2em;
border-radius: 8px;
font-size: 1.2em;
margin: 5em auto;
width: 350px;
box-shadow: 0 2px 8px #0006;
display: flex;
flex-direction: column;
align-items: center;
justify-content: flex-start;
}
#snake-score {
margin: 0.5em 0;
}
#snake-container {
border: 2px solid #444;
border-radius: 6px;
background: #111;
}
</style>
<div id="fancy-output">
<h3>Snake Game</h3>
<p class="help">
Use arrow keys to control the snake. Press Space to restart after game over.
</p>
<div id="snake-score">Score: 0</div>
<div id="snake-container">
<canvas id="snake-canvas" width="280" height="280"></canvas>
</div>
</div>
<script type="py">
from js import document, window, console
import random
from pyodide.ffi import create_proxy
# Snake constants
SNAKE_CELL_SIZE = 20
SNAKE_WIDTH = 14
SNAKE_HEIGHT = 14
snake_canvas_element = document.querySelector("#snake-canvas")
snake_ctx = snake_canvas_element.getContext("2d")
snake_score_element = document.querySelector("#snake-score")
snake_body = [(7,7),(6,7),(5,7)]
snake_direction = (1,0)
snake_food = (10,10)
snake_score = 0
snake_game_over = False
snake_last_time = 0
snake_speed = 200
def draw_snake_cell(x,y,color):
snake_ctx.fillStyle = color
snake_ctx.fillRect(x*SNAKE_CELL_SIZE, y*SNAKE_CELL_SIZE, SNAKE_CELL_SIZE-2, SNAKE_CELL_SIZE-2)
def draw_snake_game():
snake_ctx.clearRect(0,0,snake_canvas_element.width,snake_canvas_element.height)
draw_snake_cell(snake_food[0], snake_food[1], "#e57373")
for i,(x,y) in enumerate(snake_body):
color = "#ffd54f" if i==0 else "#81c784"
draw_snake_cell(x,y,color)
def place_snake_food():
while True:
fx=random.randint(0,SNAKE_WIDTH-1)
fy=random.randint(0,SNAKE_HEIGHT-1)
if (fx,fy) not in snake_body:
return (fx,fy)
def update_snake_score():
snake_score_element.innerHTML = f"Score: {snake_score}"
def update_snake_game():
global snake_body,snake_food,snake_score,snake_game_over
if snake_game_over:
return
head_x,head_y = snake_body[0]
dx,dy = snake_direction
new_head = ((head_x+dx)%SNAKE_WIDTH,(head_y+dy)%SNAKE_HEIGHT)
if new_head in snake_body:
snake_game_over=True
snake_ctx.fillStyle="#fff"
snake_ctx.font="20px monospace"
snake_ctx.fillText("Game Over!",80,130)
snake_ctx.font="16px monospace"
snake_ctx.fillText("Press Space to restart",60,160)
return
snake_body.insert(0,new_head)
if new_head==snake_food:
snake_score+=1
update_snake_score()
snake_food=place_snake_food()
else:
snake_body.pop()
draw_snake_game()
def restart_snake_game():
global snake_body,snake_direction,snake_food,snake_score,snake_game_over,snake_last_time
snake_body=[(7,7),(6,7),(5,7)]
snake_direction=(1,0)
snake_food=place_snake_food()
snake_score=0
snake_game_over=False
snake_last_time=0
update_snake_score()
draw_snake_game()
window.requestAnimationFrame(snake_loop_proxy)
def snake_game_loop(current_time):
global snake_last_time
if current_time - snake_last_time >= snake_speed:
update_snake_game()
snake_last_time=current_time
if not snake_game_over:
window.requestAnimationFrame(snake_loop_proxy)
def snake_keydown_handler(event):
global snake_direction
key=event.key
if snake_game_over and key==" ":
restart_snake_game()
return
if snake_game_over:
return
dx,dy=snake_direction
if key=="ArrowUp" and dy!=1:
snake_direction=(0,-1)
elif key=="ArrowDown" and dy!=-1:
snake_direction=(0,1)
elif key=="ArrowLeft" and dx!=1:
snake_direction=(-1,0)
elif key=="ArrowRight" and dx!=-1:
snake_direction=(1,0)
snake_loop_proxy=create_proxy(snake_game_loop)
snake_keydown_proxy=create_proxy(snake_keydown_handler)
window.addEventListener("keydown",snake_keydown_proxy)
update_snake_score()
draw_snake_game()
window.requestAnimationFrame(snake_loop_proxy)
console.log("Snake game started")
</script>
`);