1- use std:: { collections:: VecDeque , ops:: Not } ;
1+ use std:: collections:: VecDeque ;
2+
3+ use web_sys:: console;
24
35use crate :: {
46 render:: PlatformRenderer ,
5- utils:: { lerpf, rand} ,
7+ utils:: { emod , lerpf, rand} ,
68} ;
79
810// Constants
@@ -12,8 +14,10 @@ const ROWS: i32 = 9;
1214const BACKGROUND_COLOR : u32 = 0xFF181818 ;
1315const CELL1_COLOR : u32 = BACKGROUND_COLOR ;
1416const CELL2_COLOR : u32 = 0xFF183018 ;
15- const SNAKE_BODY_COLOR : u32 = 0xFF189018 ;
16- const SNAKE_SPINE_COLOR : u32 = 0xFF185018 ;
17+ const SNAKE_HEAD_COLOR : u32 = 0xFF00FF00 ;
18+ const SNAKE_BODY_COLOR : u32 = 0xFF32CD32 ;
19+ const SNAKE_TAIL_COLOR : u32 = 0xFF228B22 ;
20+ const SNAKE_SPINE_COLOR : u32 = 0xFF006400 ;
1721const EGG_BODY_COLOR : u32 = 0xFF31A6FF ;
1822const EGG_SPINE_COLOR : u32 = 0xFF3166BB ;
1923const SNAKE_SPINE_THICKNESS_PERCENT : f32 = 0.05 ;
@@ -39,7 +43,27 @@ enum Direction {
3943 Down = 3 ,
4044}
4145
42- impl Not for Direction {
46+ impl Direction {
47+ pub const ALL : [ Direction ; 4 ] = [
48+ Direction :: Right ,
49+ Direction :: Up ,
50+ Direction :: Left ,
51+ Direction :: Down ,
52+ ] ;
53+ }
54+
55+ impl Into < Cell > for Direction {
56+ fn into ( self ) -> Cell {
57+ match self {
58+ Direction :: Right => Cell { x : 1 , y : 0 } ,
59+ Direction :: Left => Cell { x : -1 , y : 0 } ,
60+ Direction :: Up => Cell { x : 0 , y : -1 } ,
61+ Direction :: Down => Cell { x : 0 , y : 1 } ,
62+ }
63+ }
64+ }
65+
66+ impl std:: ops:: Not for Direction {
4367 type Output = Self ;
4468
4569 fn not ( self ) -> Self :: Output {
@@ -64,6 +88,34 @@ struct Vec2<I> {
6488 y : I ,
6589}
6690
91+ impl < I > std:: ops:: Sub for Vec2 < I >
92+ where
93+ I : std:: ops:: Sub < Output = I > ,
94+ {
95+ type Output = Vec2 < I > ;
96+
97+ fn sub ( self , rhs : Self ) -> Self :: Output {
98+ Vec2 {
99+ x : self . x - rhs. x ,
100+ y : self . y - rhs. y ,
101+ }
102+ }
103+ }
104+
105+ impl < I > std:: ops:: Add for Vec2 < I >
106+ where
107+ I : std:: ops:: Add < Output = I > ,
108+ {
109+ type Output = Vec2 < I > ;
110+
111+ fn add ( self , rhs : Self ) -> Self :: Output {
112+ Vec2 {
113+ x : self . x + rhs. x ,
114+ y : self . y + rhs. y ,
115+ }
116+ }
117+ }
118+
67119struct Rect {
68120 x : f32 ,
69121 y : f32 ,
@@ -95,6 +147,29 @@ impl From<&Sides> for Rect {
95147
96148type Cell = Vec2 < i32 > ;
97149
150+ impl Cell {
151+ fn determine_dir ( & self , another : & Cell ) -> Direction {
152+ for dir in Direction :: ALL {
153+ if self . advance ( dir) == * another {
154+ return dir;
155+ }
156+ }
157+ unreachable ! ( )
158+ }
159+
160+ fn advance ( & self , dir : Direction ) -> Cell {
161+ let dir_cell: Cell = dir. into ( ) ;
162+ let mut res: Cell = dir_cell + * self ;
163+ res. wrap_by_game_size ( ) ;
164+ res
165+ }
166+
167+ fn wrap_by_game_size ( & mut self ) {
168+ self . x = emod ( self . x , COLS ) ;
169+ self . y = emod ( self . y , ROWS ) ;
170+ }
171+ }
172+
98173struct Sides {
99174 lens : Vec < f32 > ,
100175}
@@ -128,9 +203,13 @@ struct Snake {
128203}
129204
130205impl Snake {
131- pub fn contains_cell ( & self , cell : & Cell ) -> bool {
206+ fn contains_cell ( & self , cell : & Cell ) -> bool {
132207 self . body . contains ( cell)
133208 }
209+
210+ fn size ( & self ) -> usize {
211+ self . body . len ( )
212+ }
134213}
135214
136215pub struct Game < P : PlatformRenderer > {
@@ -203,7 +282,31 @@ impl<P: PlatformRenderer> Game<P> {
203282 self . random_egg ( true ) ;
204283 }
205284
206- pub fn update ( & mut self , delta_time : f64 ) { }
285+ pub fn update ( & mut self , dt : f32 ) {
286+ let mut dt = dt;
287+ #[ cfg( feature = "dev" ) ]
288+ {
289+ dt *= self . dt_scale ;
290+ }
291+
292+ match self . state {
293+ State :: Gameplay => {
294+ self . step_cooldown -= dt;
295+ if self . step_cooldown > 0.0 {
296+ return ;
297+ }
298+
299+ let next_head = self . snake . body . back ( ) . unwrap ( ) . advance ( self . dir ) ;
300+ self . snake . body . push_back ( next_head) ;
301+ self . snake . body . pop_front ( ) ;
302+ self . eating_egg = false ;
303+
304+ self . step_cooldown = STEP_INTERVAL ;
305+ }
306+ State :: Pause => { }
307+ State :: Gameover => { }
308+ }
309+ }
207310
208311 pub fn render ( & self ) {
209312 match self . state {
@@ -218,18 +321,59 @@ impl<P: PlatformRenderer> Game<P> {
218321 }
219322
220323 fn snake_render ( & self ) {
221- // let t = self.step_cooldown / STEP_INTERVAL;
222- let t = 0.5 ;
324+ let t = self . step_cooldown / STEP_INTERVAL ;
223325
224326 let head_cell = self . snake . body . back ( ) . unwrap ( ) ;
225327 let head_dir = self . dir ;
226-
227328 let mut head_slide_sides: Sides = ( & Rect :: from ( head_cell) ) . into ( ) ;
228329 head_slide_sides. adjust_2_slide_sides ( !head_dir, t) ;
229330
230- let tail_cell = * self . snake . body . front ( ) . unwrap ( ) ;
331+ let tail_cell = self . snake . body . front ( ) . unwrap ( ) ;
332+ let mut tail_slide_sides: Sides = ( & Rect :: from ( tail_cell) ) . into ( ) ;
333+ let tail_dir = self
334+ . snake
335+ . body
336+ . get ( 0 )
337+ . unwrap ( )
338+ . determine_dir ( self . snake . body . get ( 1 ) . unwrap ( ) ) ;
339+ tail_slide_sides
340+ . adjust_2_slide_sides ( tail_dir, if self . eating_egg { 1.0 } else { 1.0 - t } ) ;
341+
342+ if self . eating_egg {
343+ self . fill_cell ( head_cell, EGG_BODY_COLOR , 1.0 ) ;
344+ self . fill_cell (
345+ head_cell,
346+ EGG_SPINE_COLOR ,
347+ SNAKE_SPINE_THICKNESS_PERCENT * 2.0 ,
348+ ) ;
349+ }
231350
351+ // self.fill_sides(&head_slide_sides, SNAKE_HEAD_COLOR);
352+ // self.fill_sides(&tail_slide_sides, SNAKE_TAIL_COLOR);
232353 self . fill_sides ( & head_slide_sides, SNAKE_BODY_COLOR ) ;
354+ self . fill_sides ( & tail_slide_sides, SNAKE_BODY_COLOR ) ;
355+
356+ for i in 1 ..self . snake . size ( ) - 1 {
357+ self . fill_cell ( self . snake . body . get ( i) . unwrap ( ) , SNAKE_BODY_COLOR , 1.0 ) ;
358+ }
359+
360+ #[ cfg( feature = "dev" ) ]
361+ {
362+ for i in 0 ..self . snake . size ( ) {
363+ console:: log_1 ( & "test" . into ( ) ) ;
364+ self . stroke_rect ( self . snake . body . get ( i) . unwrap ( ) . into ( ) , 0xFF0000FF ) ;
365+ }
366+ }
367+ }
368+
369+ fn stroke_rect ( & self , rect : Rect , color : u32 ) {
370+ self . platform_renderer . stroke_rect (
371+ ( rect. x - self . camera_pos . x ) as i32 + ( self . width / 2 ) as i32 ,
372+ ( rect. y - self . camera_pos . y ) as i32 + ( self . height / 2 ) as i32 ,
373+ rect. w as i32 ,
374+ rect. h as i32 ,
375+ color,
376+ ) ;
233377 }
234378
235379 fn fill_sides ( & self , sides : & Sides , color : u32 ) {
0 commit comments