Skip to content

Instantly share code, notes, and snippets.

@rmorshea
Created February 28, 2019 22:47
Show Gist options
  • Save rmorshea/56509989480306236dc29c5f95eafb22 to your computer and use it in GitHub Desktop.
Save rmorshea/56509989480306236dc29c5f95eafb22 to your computer and use it in GitHub Desktop.
The game Snake implemented in Python with iDOM (https://github.com/rmorshea/idom)
import idom
import enum
import time
import random
import asyncio
class WASD(enum.Enum):
w = (-1, 0)
a = (0, -1)
s = (1, 0)
d = (0, 1)
@idom.element
async def Game(
self,
grid_size,
block_size,
snake=idom.Context(list),
direction=idom.Context(WASD.d),
food=idom.Context(),
won=idom.Context(False),
lost=idom.Context(False),
):
snake.current = []
grid = Grid(grid_size, block_size)
grid.attributes["tabIndex"] = -1
events = grid.eventHandlers = idom.Events()
@events.on("KeyDown")
def direction_change(key):
if hasattr(WASD, key):
old = direction.current.value
new = WASD[key].value
vector_sum = tuple(map(sum, zip(old, new)))
if vector_sum != (0, 0):
direction.current = WASD[key]
snake.current.extend([
(grid_size // 2 - 1, grid_size // 2 - 3),
(grid_size // 2 - 1, grid_size // 2 - 2),
(grid_size // 2 - 1, grid_size // 2 - 1),
])
grid_points = set((x, y) for x in range(grid_size) for y in range(grid_size))
def set_new_food():
points_not_in_snake = grid_points.difference(snake.current)
new_food = food.current = random.choice(list(points_not_in_snake))
grid["children"][new_food[0]]["children"][new_food[1]].update(color="red")
async def loop():
if self.state.lost.current:
self.reset(grid_size, block_size)
await asyncio.sleep(2)
return
elif self.state.won.current:
return
else:
await draw(self, grid, grid_size, set_new_food)
self.callback(loop)
self.callback(loop)
set_new_food()
return grid
async def draw(game, grid, grid_size, set_new_food):
start = time.time()
snake = game.state.snake.current
old_head = snake[-1]
new_head = (
# grid wraps due to mod op here
(old_head[0] + game.state.direction.current.value[0]) % grid_size,
(old_head[1] + game.state.direction.current.value[1]) % grid_size,
)
new_head_element = grid["children"][new_head[0]]["children"][new_head[1]]
new_head_element.update("black")
if new_head == game.state.food.current:
set_new_food()
else:
old_tail = snake.pop(0)
old_tail_element = grid["children"][old_tail[0]]["children"][old_tail[1]]
old_tail_element.update("white")
if new_head in snake:
game.state.lost.current = True
elif len(snake) == grid_size * grid_size:
game.state.won.current = True
snake.append(new_head)
stop = time.time()
await asyncio.sleep(0.3 - (start - stop))
def Grid(grid_size, block_size):
return idom.node(
"div",
[
{
"tagName": "div",
"attributes": {"style": {"height": block_size}},
"children": [Block("white", block_size) for i in range(grid_size)]
}
for i in range(grid_size)
],
style={
"height": "%spx" % (block_size * grid_size),
"width": "%spx" % (block_size * grid_size),
}
)
@idom.element
def Block(self, color, block_size):
return idom.node(
"div",
style={
"height": "%spx" % block_size,
"width": "%spx" % block_size,
"backgroundColor": color,
"display": "inline-block"
}
)
idom.SimpleWebServer(Game, 15, 30).daemon("localhost", 8765)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment