diff options
author | rexim <reximkut@gmail.com> | 2024-03-21 02:28:47 +0700 |
---|---|---|
committer | rexim <reximkut@gmail.com> | 2024-03-21 02:28:47 +0700 |
commit | 3fad142df592a37458fd2f511f4688452ec41904 (patch) | |
tree | 0b27b94c31ed9e375c7dee90f9d88ea2ba694f3a | |
parent | 1298c054ab13456a79a1945fd37720aa2ffee8e5 (diff) |
Animate transition between the eye states
-rw-r--r-- | game.adb | 92 | ||||
-rw-r--r-- | map.png | bin | 1044 -> 1040 bytes | |||
-rw-r--r-- | raylib.adb | 12 | ||||
-rw-r--r-- | raylib.ads | 7 | ||||
-rw-r--r-- | raymath.ads | 5 | ||||
-rw-r--r-- | test.adb | 143 |
6 files changed, 100 insertions, 159 deletions
@@ -249,13 +249,33 @@ procedure Game is Dead: Boolean := False; end record; + type Eyes_Kind is (Eyes_Open, Eyes_Closed, Eyes_Angry); + type Eye_Mesh is new Vector2_Array(1..4); + type Eye is (Left_Eye, Right_Eye); + type Eyes_Mesh is array (Eye) of Eye_Mesh; + Eyes_Meshes: constant array (Eyes_Kind) of Eyes_Mesh := [ + Eyes_Open => [ + Left_Eye => [ (0.0, 0.0), (0.0, 1.0), (1.0, 0.0), (1.0, 1.0) ], + Right_Eye => [ (0.0, 0.0), (0.0, 1.0), (1.0, 0.0), (1.0, 1.0) ] + ], + Eyes_Closed => [ + Left_Eye => [ (0.0, 0.8), (0.0, 1.0), (1.0, 0.8), (1.0, 1.0) ], + Right_Eye => [ (0.0, 0.8), (0.0, 1.0), (1.0, 0.8), (1.0, 1.0) ] + ], + Eyes_Angry => [ + Left_Eye => [ (0.0, 0.0), (0.0, 1.0), (1.0, 0.3), (1.0, 1.0) ], + Right_Eye => [ (0.0, 0.3), (0.0, 1.0), (1.0, 0.0), (1.0, 1.0) ] + ] + ]; + type Boss_Kind is (Shrek, Urmom, Gnome); type Boss_State is record Kind: Boss_Kind; Dead: Boolean := True; - Prev_Position: IVector2; - Position: IVector2; + Position, Prev_Position: IVector2; + Prev_Eyes: Eyes_Kind; + Eyes: Eyes_Kind := Eyes_Closed; Size: IVector2; Path: Path_Map_Access; @@ -860,7 +880,7 @@ procedure Game is Prev_Position: constant Vector2 := To_Vector2(IPrev_Position)*Cell_Size; Curr_Position: constant Vector2 := To_Vector2(IPosition)*Cell_Size; begin - return Prev_Position + (Curr_Position - Prev_Position)*C_Float(1.0 - T*T); + return Vector2_Lerp(Prev_Position, Curr_Position, C_Float(1.0 - T*T)); end; Space_Down: Boolean := False; @@ -900,6 +920,7 @@ procedure Game is for Me in Boss_Index loop if not Game.Bosses(Me).Dead then Game.Bosses(Me).Prev_Position := Game.Bosses(Me).Position; + Game.Bosses(Me).Prev_Eyes := Game.Bosses(Me).Eyes; case Game.Bosses(Me).Kind is when Shrek | Urmom => Recompute_Path_For_Boss(Game, Me, SHREK_STEPS_LIMIT, SHREK_STEP_LENGTH_LIMIT); @@ -931,7 +952,14 @@ procedure Game is else Game.Bosses(Me).Attack_Cooldown := Game.Bosses(Me).Attack_Cooldown - 1; end if; + + if Game.Bosses(Me).Path(Game.Bosses(Me).Position.Y, Game.Bosses(Me).Position.X) = 1 then + Game.Bosses(Me).Eyes := Eyes_Angry; + else + Game.Bosses(Me).Eyes := Eyes_Open; + end if; else + Game.Bosses(Me).Eyes := Eyes_Closed; Game.Bosses(Me).Attack_Cooldown := SHREK_ATTACK_COOLDOWN + 1; end if; @@ -969,6 +997,9 @@ procedure Game is Game.Bosses(Me).Position := Available_Positions(Random_Integer.Random(Gen) mod Count); end if; end; + Game.Bosses(Me).Eyes := Eyes_Open; + else + Game.Bosses(Me).Eyes := Eyes_Closed; end if; end; end case; @@ -1107,39 +1138,24 @@ procedure Game is Palette_RGB(COLOR_HEALTHBAR)); end; - type Eyes_Kind is (Eyes_Open, Eyes_Closed, Eyes_Angry); - - procedure Draw_Eyes(Start, Size: Vector2; Angle: Float; Kind: Eyes_Kind; Background: Palette) is + procedure Draw_Eyes(Start, Size: Vector2; Angle: Float; Prev_Kind, Kind: Eyes_Kind; T: Float) is Dir: constant Vector2 := Vector2_Rotate((1.0, 0.0), C_Float(Angle)); Eyes_Ratio: constant Vector2 := (13.0/64.0, 23.0/64.0); Eyes_Size: constant Vector2 := Eyes_Ratio*Size; Center: constant Vector2 := Start + Size*0.5; Position: constant Vector2 := Center + Dir*Eyes_Size.X*0.6; - Left_Position: constant Vector2 := Position - Eyes_Size*(0.5, 0.0) - Eyes_Size*(1.0, 0.5); - Right_Position: constant Vector2 := Position + Eyes_Size*(0.5, 0.0) - Eyes_Size*(0.0, 0.5); - Closed_Ratio: constant C_Float := 0.2; + Positions: constant array (Eye) of Vector2 := [ + Left_Eye => Position - Eyes_Size*(0.5, 0.0) - Eyes_Size*(1.0, 0.5), + Right_Eye => Position + Eyes_Size*(0.5, 0.0) - Eyes_Size*(0.0, 0.5) + ]; + Mesh: Eye_Mesh; begin - case Kind is - when Eyes_Closed => - Draw_Rectangle_V(Left_Position + Eyes_Size*(0.0, 1.0 - Closed_Ratio), Eyes_Size*(1.0, Closed_Ratio), Palette_RGB(COLOR_EYES)); - Draw_Rectangle_V(Right_Position + Eyes_Size*(0.0, 1.0 - Closed_Ratio), Eyes_Size*(1.0, Closed_Ratio), Palette_RGB(COLOR_EYES)); - when Eyes_Open => - Draw_Rectangle_V(Left_Position, Eyes_Size, Palette_RGB(COLOR_EYES)); - Draw_Rectangle_V(Right_Position, Eyes_Size, Palette_RGB(COLOR_EYES)); - when Eyes_Angry => - Draw_Rectangle_V(Left_Position, Eyes_Size, Palette_RGB(COLOR_EYES)); - Draw_Triangle( - Left_Position, - Left_Position + Eyes_Size*(1.0, 0.3), - Left_Position + Eyes_Size*(1.0, 0.0), - Palette_RGB(Background)); - Draw_Rectangle_V(Right_Position, Eyes_Size, Palette_RGB(COLOR_EYES)); - Draw_Triangle( - Right_Position, - Right_Position + Eyes_Size*(0.0, 0.3), - Right_Position + Eyes_Size*(1.0, 0.0), - Palette_RGB(Background)); - end case; + for Eye_Index in Eye loop + for Vertex_Index in Eye_Mesh'Range loop + Mesh(Vertex_Index) := Positions(Eye_Index) + Eyes_Size*Vector2_Lerp(Eyes_Meshes(Prev_Kind)(Eye_Index)(Vertex_Index), Eyes_Meshes(Kind)(Eye_Index)(Vertex_Index), C_Float(1.0 - T*T)); + end loop; + Draw_Triangle_Strip(Mesh, Palette_RGB(COLOR_EYES)); + end loop; end; procedure Draw_Cooldown_Timer_Bubble(Start, Size: Vector2; Cooldown: Integer; Background: Palette) is @@ -1168,13 +1184,10 @@ procedure Game is Health_Bar(Position, Size, C_Float(Boss.Health)); if Boss.Path(Boss.Position.Y, Boss.Position.X) = 1 then Draw_Cooldown_Timer_Bubble(Position, Size, Boss.Attack_Cooldown, Boss.Background); - Draw_Eyes(Position, Size, -Float(Vector2_Line_Angle(Position + Size*0.5, Screen_Player_Position(Game) + Cell_Size*0.5)), Eyes_Angry, Boss.Background); elsif Boss.Path(Boss.Position.Y, Boss.Position.X) >= 0 then Draw_Cooldown_Timer_Bubble(Position, Size, Boss.Attack_Cooldown, Boss.Background); - Draw_Eyes(Position, Size, -Float(Vector2_Line_Angle(Position + Size*0.5, Screen_Player_Position(Game) + Cell_Size*0.5)), Eyes_Open, Boss.Background); - else - Draw_Eyes(Position, Size, -Float(Vector2_Line_Angle(Position + Size*0.5, Screen_Player_Position(Game) + Cell_Size*0.5)), Eyes_Closed, Boss.Background); end if; + Draw_Eyes(Position, Size, -Float(Vector2_Line_Angle(Position + Size*0.5, Screen_Player_Position(Game) + Cell_Size*0.5)), Boss.Prev_Eyes, Boss.Eyes, Game.Turn_Animation); when Gnome => declare GNOME_RATIO: constant C_Float := 0.7; @@ -1182,11 +1195,7 @@ procedure Game is GNOME_START: constant Vector2 := Position + Cell_Size*0.5 - GNOME_SIZE*0.5; begin Draw_Rectangle_V(GNOME_START, GNOME_SIZE, Palette_RGB(Boss.Background)); - if Boss.Path(Boss.Position.Y, Boss.Position.X) >= 0 then - Draw_Eyes(GNOME_START, GNOME_SIZE, -Float(Vector2_Line_Angle(GNOME_START + GNOME_SIZE*0.5, Screen_Player_Position(Game) + Cell_Size*0.5)), Eyes_Open, Boss.Background); - else - Draw_Eyes(GNOME_START, GNOME_SIZE, -Float(Vector2_Line_Angle(GNOME_START + GNOME_SIZE*0.5, Screen_Player_Position(Game) + Cell_Size*0.5)), Eyes_Open, Boss.Background); - end if; + Draw_Eyes(GNOME_START, GNOME_SIZE, -Float(Vector2_Line_Angle(GNOME_START + GNOME_SIZE*0.5, Screen_Player_Position(Game) + Cell_Size*0.5)), Boss.Prev_Eyes, Boss.Eyes, Game.Turn_Animation); end; end case; end if; @@ -1195,7 +1204,7 @@ procedure Game is end; Game: Game_State; - Title: constant Char_Array := To_C("Hello, NSA"); + Title: constant Char_Array := To_C("Eepers"); Palette_Editor: Boolean := False; Palette_Editor_Choice: Palette := Palette'First; @@ -1212,7 +1221,7 @@ begin Init_Window(800, 600, Title); Set_Target_FPS(60); Set_Exit_Key(KEY_NULL); - while Window_Should_Close = 0 loop + while not Window_Should_Close loop Begin_Drawing; Clear_Background(Palette_RGB(COLOR_BACKGROUND)); @@ -1356,7 +1365,6 @@ end; -- TODO: End Game as a Huge White Eeper -- TODO: Closed eyes should always point down --- TODO: Animate transition between the eye states -- TODO: Checkpoints must refill the bombs -- TODO: Special Eeper Eyes on Damage -- TODO: Show Boss Cooldown timer outside of the screen somehow Binary files differdiff --git a/raylib.adb b/raylib.adb new file mode 100644 index 0000000..89fe8af --- /dev/null +++ b/raylib.adb @@ -0,0 +1,12 @@ +package body Raylib is + procedure Draw_Triangle_Strip(Points: Vector2_Array; C: Color) is + procedure Draw_Triangle_Strip_C(Points: Vector2_Array; Point_Count: Int; C: Color) + with + Import => True, + Convention => C, + External_Name => "DrawTriangleStrip"; + begin + Draw_Triangle_Strip_C(Points, Points'Length, C); + end; + +end Raylib; @@ -1,5 +1,4 @@ with Interfaces.C; use Interfaces.C; -with Interfaces.C.Pointers; with Raymath; use Raymath; package Raylib is @@ -13,7 +12,7 @@ package Raylib is Import => True, Convention => C, External_Name => "CloseWindow"; - function Window_Should_Close return int + function Window_Should_Close return C_Bool with Import => True, Convention => C, @@ -206,4 +205,8 @@ package Raylib is Import => True, Convention => C, External_Name => "DrawTriangle"; + + type Vector2_Array is array (size_t range <>) of aliased Vector2; + + procedure Draw_Triangle_Strip(Points: Vector2_Array; C: Color); end Raylib; diff --git a/raymath.ads b/raymath.ads index 4447d45..81f2a37 100644 --- a/raymath.ads +++ b/raymath.ads @@ -42,4 +42,9 @@ package Raymath is z: C_float; end record with Convention => C_Pass_By_Copy; + function Vector2_Lerp(V1, V2: Vector2; Amount: C_Float) return Vector2 + with + Import => True, + Convention => C, + External_Name => "Vector2Lerp"; end; @@ -9,127 +9,40 @@ with Raylib; use Raylib; with Interfaces.C; use Interfaces.C; with Interfaces.C.Pointers; with Ada.Unchecked_Conversion; +with Raylib; use Raylib; +with Raymath; use Raymath; function Test return Integer is - type Color_Array is array (Natural range <>) of aliased Raylib.Color; - package Color_Pointer is new Interfaces.C.Pointers( - Index => Natural, - Element => Raylib.Color, - Element_Array => Color_Array, - Default_Terminator => (others => 0)); - function To_Color_Pointer is new Ada.Unchecked_Conversion (Raylib.Addr, Color_Pointer.Pointer); - use Color_Pointer; - - function Load_Text_As_Image(File_Name: in String) return Raylib.Image is - package Rows is new - Ada.Containers.Vectors( - Index_Type => Natural, - Element_Type => Unbounded_String); - F: File_Type; - Map_Rows: Rows.Vector; - Width: Integer := 0; - Height: Integer := 0; - Img: Raylib.Image; - Pixels: Color_Pointer.Pointer; + type Vector2_Array is array (size_t range <>) of aliased Vector2; + procedure Draw_Triangle_Strip(Points: Vector2_Array; C: Color) is + procedure Draw_Triangle_Strip_C(Points: Vector2_Array; Point_Count: Int; C: Color) + with + Import => True, + Convention => C, + External_Name => "DrawTriangleStrip"; begin - Open(F, In_File, File_Name); - while not End_Of_File(F) loop - declare - Line: constant String := Get_Line(F); - begin - if Line'Length > Width then - Width := Line'Length; - end if; - Map_Rows.Append(To_Unbounded_String(Line)); - Height := Height + 1; - end; - end loop; - Close(F); - - Img := Raylib.Gen_Image_Color(Int(Width), Int(Height), (others => 0)); - Pixels := To_Color_Pointer(Img.Data); - - for Row in 1..Height loop - declare - Map_Row: constant Unbounded_String := Map_Rows(Row - 1); - begin - Put_Line(To_String(Map_Rows(Row - 1))); - for Column in 1..Width loop - declare - Index: Ptrdiff_T := Ptrdiff_T((Row - 1)*Width + (Column - 1)); - Pixel: Color_Pointer.Pointer := Pixels + Index; - BLACK: constant Raylib.Color := (A => 255, others => 0); - WHITE: constant Raylib.Color := (others => 255); - RED: constant Raylib.Color := (R => 255, A => 255, others => 0); - ORANGE: constant Raylib.Color := (R => 255, G => 150, A => 255, others => 0); - FOO: constant Raylib.Color := (R => 255, B => 150, A => 255, others => 0); - GREEN: constant Raylib.Color := (G => 255, A => 255, others => 0); - BAR: constant Raylib.Color := (G => 255, R => 150, A => 255, others => 0); - BLUE: constant Raylib.Color := (B => 255, A => 255, others => 0); - CYAN: constant Raylib.Color := (G => 255, B => 255, A => 255, others => 0); - PURPLE: constant Raylib.Color := (R => 255, B => 255, A => 255, others => 0); - YELLOW: constant Raylib.Color := (R => 255, G => 255, A => 255, others => 0); - begin - if Column in 1..Length(Map_Row) then - case Element(Map_Row, Column) is - when 'G' => Pixel.all := ORANGE; - when 'M' => Pixel.all := BAR; - when 'B' => Pixel.all := GREEN; - when '.' => Pixel.all := WHITE; - when '#' => Pixel.all := BLACK; - when '=' => Pixel.all := CYAN; - when '!' => Pixel.all := PURPLE; - when '*' => Pixel.all := RED; - when '&' => Pixel.all := FOO; - when '%' => Pixel.all := YELLOW; - when '@' => Pixel.all := BLUE; - when others => Pixel.all := (others => 0); - end case; - else - Pixel.all := (others => 0); - end if; - end; - end loop; - end; - end loop; - return Img; + Draw_Triangle_Strip_C(Points, Points'Length, C); end; - type Level_Cell is ( - Level_None, - Level_Gnome, - Level_Urmom, - Level_Shrek, - Level_Floor, - Level_Wall, - Level_Door, - Level_Checkpoint, - Level_Bomb_Gen, - Level_Barricade, - Level_Key, - Level_Player); - - Level_Cell_Color: constant array (Level_Cell) of Color := [ - Level_None => Get_Color(16#00000000#), - Level_Gnome => Get_Color(16#FF9600FF#), - Level_Urmom => Get_Color(16#96FF00FF#), - Level_Shrek => Get_Color(16#00FF00FF#), - Level_Floor => Get_Color(16#FFFFFFFF#), - Level_Wall => Get_Color(16#000000FF#), - Level_Door => Get_Color(16#00FFFFFF#), - Level_Checkpoint => Get_Color(16#FF00FFFF#), - Level_Bomb_Gen => Get_Color(16#FF0000FF#), - Level_Barricade => Get_Color(16#FF0096FF#), - Level_Key => Get_Color(16#FFFF00FF#), - Level_Player => Get_Color(16#0000FFFF#), - - Img: Raylib.Image := Raylib.Load_Image(To_C("glider.png")); - Pixels: Color_Pointer.Pointer := To_Color_Pointer(Img.Data); - New_Img: Raylib.Image := Load_Text_As_Image("map.txt"); - + Size: Vector2; + Radius: constant C_Float := 100.0; begin - for Cell in Level_Cell loop - Put_Line(Unsigned'Image(Color_To_Int(Level_Cell_Color(Cell)))); + Init_Window(800, 600, To_C("Test")); + Set_Target_FPS(60); + while not Window_Should_Close loop + Begin_Drawing; + Size := (C_Float(Get_Screen_Width), C_Float(Get_Screen_Height)); + Clear_Background(Get_Color(16#181818FF#)); + Draw_Triangle_Strip( + Points => [ + Size*0.5 + (-Radius, -Radius), + Size*0.5 + (-Radius, Radius), + Size*0.5 + (Radius, -Radius), + Size*0.5 + (Radius, Radius) + ], + C => (R => 255, A => 255, others => 0)); + End_Drawing; end loop; + Close_Window; return 0; end; |