@@ -14,32 +14,23 @@ class GameState(enum.Enum):
1414
1515
1616@idom .element
17- async def GameView (grid_size , block_scale ):
17+ def GameView (grid_size , block_scale ):
1818 game_state , set_game_state = idom .hooks .use_state (GameState .init )
1919
2020 if game_state == GameState .play :
2121 return GameLoop (grid_size , block_scale , set_game_state )
2222
23- async def start_playing (event ):
24- set_game_state (GameState .play )
23+ start_button = idom .html .button (
24+ {"onClick" : lambda event : set_game_state (GameState .play )},
25+ "Start" ,
26+ )
2527
2628 if game_state == GameState .won :
27- await asyncio .sleep (1 )
28- return idom .html .div (
29- idom .html .h1 ("You won!" ),
30- idom .html .button ({"onClick" : start_playing }, "Start" ),
31- )
29+ return idom .html .div (idom .html .h1 ("You won!" ), start_button )
3230 elif game_state == GameState .lost :
33- await asyncio .sleep (1 )
34- return idom .html .div (
35- idom .html .h1 ("You lost" ),
36- idom .html .button ({"onClick" : start_playing }, "Start" ),
37- )
31+ return idom .html .div (idom .html .h1 ("You lost" ), start_button )
3832 else :
39- return idom .html .div (
40- idom .html .h1 ("Click to play" ),
41- idom .html .button ({"onClick" : start_playing }, "Start" ),
42- )
33+ return idom .html .div (idom .html .h1 ("Click to play" ), start_button )
4334
4435
4536class Direction (enum .Enum ):
@@ -50,7 +41,7 @@ class Direction(enum.Enum):
5041
5142
5243@idom .element
53- async def GameLoop (grid_size , block_scale , set_game_state ):
44+ def GameLoop (grid_size , block_scale , set_game_state ):
5445 # we `use_ref` here to capture the latest direction press without any delay
5546 direction = idom .hooks .use_ref (Direction .ArrowRight .value )
5647
@@ -75,17 +66,23 @@ async def on_direction_change(event):
7566 for location in snake :
7667 assign_grid_block_color (grid , location , "white" )
7768
69+ new_game_state = None
7870 if snake [- 1 ] in snake [:- 1 ]:
7971 assign_grid_block_color (grid , snake [- 1 ], "red" )
80- set_game_state ( GameState .lost )
72+ new_game_state = GameState .lost
8173 elif len (snake ) == grid_size ** 2 :
8274 assign_grid_block_color (grid , snake [- 1 ], "yellow" )
83- set_game_state ( GameState .won )
75+ new_game_state = GameState .won
8476
8577 interval = use_interval (0.5 )
8678
87- @use_async_effect
79+ @idom . hooks . use_async
8880 async def animate ():
81+ if new_game_state is not None :
82+ await asyncio .sleep (1 )
83+ set_game_state (new_game_state )
84+ return
85+
8986 await interval
9087
9188 new_snake_head = (
@@ -105,31 +102,6 @@ async def animate():
105102 return grid
106103
107104
108- def use_async_effect (function ):
109- def ensure_effect_future ():
110- future = asyncio .ensure_future (function ())
111-
112- def cleanup ():
113- if future .done ():
114- future .result ()
115- else :
116- future .cancel ()
117-
118- return cleanup
119-
120- idom .hooks .use_effect (ensure_effect_future )
121-
122-
123- def use_interval (rate ):
124- usage_time = idom .hooks .use_ref (time .time ())
125-
126- async def interval ():
127- await asyncio .sleep (rate - (time .time () - usage_time .current ))
128- usage_time .current = time .time ()
129-
130- return asyncio .ensure_future (interval ())
131-
132-
133105def use_snake_food (grid_size , current_snake ):
134106 grid_points = {(x , y ) for x in range (grid_size ) for y in range (grid_size )}
135107 points_not_in_snake = grid_points .difference (current_snake )
@@ -142,6 +114,16 @@ def set_food():
142114 return food , set_food
143115
144116
117+ def use_interval (rate : float ) -> Awaitable [None ]:
118+ usage_time = use_ref (time .time ())
119+
120+ async def interval () -> None :
121+ await asyncio .sleep (rate - (time .time () - usage_time .current ))
122+ usage_time .current = time .time ()
123+
124+ return asyncio .ensure_future (interval ())
125+
126+
145127def create_grid (grid_size , block_scale ):
146128 return idom .html .div (
147129 {
0 commit comments