diff options
author | rexim <reximkut@gmail.com> | 2024-03-14 02:33:53 +0700 |
---|---|---|
committer | rexim <reximkut@gmail.com> | 2024-03-14 02:33:53 +0700 |
commit | ed9fa76925909f94512ef70280b90712e35c3ab7 (patch) | |
tree | 96d4e2a6258a468d37b6b61c43ce7b132aec19e3 | |
parent | b081abc78ef9fd0c511b35eeabffdddba61cdd43 (diff) |
Introduce rough implementation of the palette editor
-rwxr-xr-x | build.sh | 2 | ||||
-rw-r--r-- | colors.txt | 26 | ||||
-rw-r--r-- | game.adb | 256 | ||||
-rw-r--r-- | raylib.ads | 11 | ||||
-rw-r--r-- | raymath.ads | 6 | ||||
-rw-r--r-- | test.adb | 53 |
6 files changed, 282 insertions, 72 deletions
@@ -2,7 +2,7 @@ set -xe -gnatmake -Wall -Wextra game.adb -largs -L./raylib/raylib-5.0_linux_amd64/lib/ -l:libraylib.a -lm +gnatmake -Wall -Wextra -gnat2022 game.adb -largs -L./raylib/raylib-5.0_linux_amd64/lib/ -l:libraylib.a -lm ./game # gnatmake -gnat2022 test.adb @@ -1,13 +1,13 @@ -Background 218.40001 0.69444 0.14118 -Floor 0.00000 0.00000 0.18431 -Wall 0.00000 0.00000 0.00000 -Player 216.68393 0.75686 1.00000 -Door 35.52941 1.00000 1.00000 -Key 35.52941 1.00000 1.00000 -Label 0.00000 0.00000 1.00000 -Shrek 84.47059 1.00000 1.00000 -Checkpoint 300.00000 1.00000 1.00000 -Bomb 0.0 1.0 1.0 -Barricade 0.0 1.0 1.0 -Healthbar 0.0 1.0 1.0 -Explosion 300.00000 1.00000 1.00000 +Background 266.39999 0.69444 0.14118 +Floor 0.00000 0.00000 0.17255 +Wall 0.00000 0.00000 0.00000 +Barricade 0.00000 1.00000 1.00000 +Player 327.04663 0.75686 1.00000 +Door 115.76471 1.00000 1.00000 +Key 35.52941 1.00000 1.00000 +Bomb 0.00000 1.00000 1.00000 +Label 0.00000 0.00000 1.00000 +Shrek 84.47059 1.00000 1.00000 +Checkpoint 300.00000 1.00000 1.00000 +Explosion 300.00000 1.00000 1.00000 +Healthbar 0.00000 1.00000 1.00000 @@ -1,3 +1,4 @@ +with Ada.Text_IO; with Text_IO; use Text_IO; with Interfaces.C; use Interfaces.C; with Raylib; use Raylib; @@ -14,18 +15,129 @@ with Ada.Strings; procedure Game is DEVELOPMENT : constant Boolean := True; - COLOR_BACKGROUND : constant Color := Get_Color(16#0b1424ff#); - COLOR_FLOOR : constant Color := Get_Color(16#2f2f2fFF#); - COLOR_WALL : constant Color := Get_Color(16#000000FF#); - COLOR_PLAYER : constant Color := Get_Color(16#3e89ffff#); - COLOR_DOOR : constant Color := Get_Color(16#ff9700ff#); - COLOR_KEY : constant Color := Get_Color(16#ff9700ff#); - COLOR_LABEL : constant Color := Get_Color(16#FFFFFFFF#); - COLOR_SHREK : constant Color := Get_Color(16#97FF00FF#); - COLOR_CHECKPOINT : constant Color := Get_Color(16#FF00FFFF#); + type Palette is ( + COLOR_BACKGROUND, + COLOR_FLOOR, + COLOR_WALL, + COLOR_BARRICADE, + COLOR_PLAYER, + COLOR_DOOR, + COLOR_KEY, + COLOR_BOMB, + COLOR_LABEL, + COLOR_SHREK, + COLOR_CHECKPOINT, + COLOR_EXPLOSION, + COLOR_HEALTHBAR); + + Palette_Names: constant array (Palette) of Unbounded_String := [ + COLOR_BACKGROUND => To_Unbounded_String("Background"), + COLOR_FLOOR => To_Unbounded_String("Floor"), + COLOR_WALL => To_Unbounded_String("Wall"), + COLOR_Barricade => To_Unbounded_String("Barricade"), + COLOR_PLAYER => To_Unbounded_String("Player"), + COLOR_DOOR => To_Unbounded_String("Door"), + COLOR_KEY => To_Unbounded_String("Key"), + COLOR_BOMB => To_Unbounded_String("Bomb"), + COLOR_LABEL => To_Unbounded_String("Label"), + COLOR_SHREK => To_Unbounded_String("Shrek"), + COLOR_CHECKPOINT => To_Unbounded_String("Checkpoint"), + COLOR_EXPLOSION => To_Unbounded_String("Explosion"), + COLOR_HEALTHBAR => To_Unbounded_String("Healthbar") + ]; + + Palette_RGB: array (Palette) of Color := [others => (A => 255, others => 0)]; + Palette_HSV: array (Palette) of Vector3 := [others => (others => 0.0)]; + + procedure Save_Colors(File_Name: String) is + F: File_Type; + + procedure Put_HSV(HSV: Vector3) is + package Float_IO is new Ada.Text_IO.Float_IO (C_Float); + begin + Float_IO.Put(F, Item => HSV.X, Exp => 0); + Put(F, " "); + Float_IO.Put(F, Item => HSV.Y, Exp => 0); + Put(F, " "); + Float_IO.Put(F, Item => HSV.Z, Exp => 0); + end; + begin + Create(F, Out_File, File_Name); + for C in Palette loop + Put(F, To_String(Palette_Names(C)) & " "); + Put_HSV(Color_To_HSV(Palette_RGB(C))); + Put_Line(F, ""); + end loop; + Close(F); + end; + + procedure Load_Colors(File_Name: String) is + F: File_Type; + Line_Number : Integer := 0; + begin + Open(F, In_File, File_Name); + while not End_Of_File(F) loop + Line_Number := Line_Number + 1; + declare + Line: Unbounded_String := To_Unbounded_String(Get_Line(F)); + + function Chop_By(Src: in out Unbounded_String; Pattern: String) return Unbounded_String is + Space_Index: constant Integer := Index(Src, Pattern); + Result: Unbounded_String; + begin + if Space_Index = 0 then + Result := Src; + Src := Null_Unbounded_String; + else + Result := Unbounded_Slice(Src, 1, Space_Index - 1); + Src := Unbounded_Slice(Src, Space_Index + 1, Length(Src)); + end if; + + return Result; + end; + function Find_Color_By_Key(Key: Unbounded_String; Co: out Palette) return Boolean is + begin + for C in Palette loop + if Key = Palette_Names(C) then + Co := C; + return True; + end if; + end loop; + return False; + end; + C: Palette; + Key: constant Unbounded_String := Chop_By(Line, " "); + begin + Line := Trim(Line, Ada.Strings.Left); + if Find_Color_By_Key(Key, C) then + Line := Trim(Line, Ada.Strings.Left); + Palette_HSV(C).X := C_Float'Value(To_String(Chop_By(Line, " "))); + Line := Trim(Line, Ada.Strings.Left); + Palette_HSV(C).Y := C_Float'Value(To_String(Chop_By(Line, " "))); + Line := Trim(Line, Ada.Strings.Left); + Palette_HSV(C).Z := C_Float'Value(To_String(Chop_By(Line, " "))); + Palette_RGB(C) := Color_From_HSV(Palette_HSV(C).X, Palette_HSV(C).Y, Palette_HSV(C).Z); + else + Put_Line(File_Name & ":" & Line_Number'Image & "WARNING: Unknown Palette Color: """ & To_String(Key) & """"); + end if; + end; + end loop; + Close(F); + end; - COLOR_RED : constant Color := Get_Color(16#FF0000FF#); - COLOR_PURPLE : constant Color := Get_Color(16#FF00FFFF#); + -- TODO(tool): implement the palette editor + -- COLOR_BACKGROUND : constant Color := Get_Color(16#0b1424ff#); + -- COLOR_FLOOR : constant Color := Get_Color(16#2f2f2fFF#); + -- COLOR_WALL : constant Color := Get_Color(16#000000FF#); + -- COLOR_PLAYER : constant Color := Get_Color(16#3e89ffff#); + -- COLOR_DOOR : constant Color := Get_Color(16#ff9700ff#); + -- COLOR_KEY : constant Color := Get_Color(16#ff9700ff#); + -- COLOR_LABEL : constant Color := Get_Color(16#FFFFFFFF#); + -- COLOR_SHREK : constant Color := Get_Color(16#97FF00FF#); + -- COLOR_CHECKPOINT : constant Color := Get_Color(16#FF00FFFF#); + + -- COLOR_RED : constant Color := Get_Color(16#FF0000FF#); + -- COLOR_PURPLE : constant Color := Get_Color(16#FF00FFFF#); -- TODO(tool): move this to a hotreloadable config TURN_DURATION_SECS : constant Float := 0.125; @@ -43,14 +155,18 @@ procedure Game is Shrek_Size: constant IVector2 := (3, 3); type Cell is (None, Floor, Wall, Barricade, Door, Explosion); Cell_Size : constant Vector2 := (x => 50.0, y => 50.0); - Cell_Colors : constant array (Cell) of Color := ( - None => COLOR_BACKGROUND, - Floor => COLOR_FLOOR, - Wall => COLOR_WALL, - Barricade => COLOR_RED, - Door => COLOR_DOOR, - Explosion => COLOR_PURPLE - ); + + function Cell_Colors(C: Cell) return Color is + begin + case C is + when None => return Palette_RGB(COLOR_BACKGROUND); + when Floor => return Palette_RGB(COLOR_FLOOR); + when Wall => return Palette_RGB(COLOR_WALL); + when Barricade => return Palette_RGB(COLOR_BARRICADE); + when Door => return Palette_RGB(COLOR_DOOR); + when Explosion => return Palette_RGB(COLOR_EXPLOSION); + end case; + end; type Shrek_Path is array (Positive range <>, Positive range <>) of Integer; type Shrek_Path_Access is access Shrek_Path; @@ -74,11 +190,6 @@ procedure Game is return A.X = B.X and then A.Y = B.Y; end; - function "-"(A, B: IVector2) return IVector2 is - begin - return (A.X - B.X, A.Y - B.Y); - end; - function "+"(A, B: IVector2) return IVector2 is begin return (A.X + B.X, A.Y + B.Y); @@ -398,7 +509,7 @@ procedure Game is procedure Draw_Key(Position: IVector2) is begin - Draw_Circle_V(To_Vector2(Position)*Cell_Size + Cell_Size*0.5, Cell_Size.X*0.25, COLOR_KEY); + Draw_Circle_V(To_Vector2(Position)*Cell_Size + Cell_Size*0.5, Cell_Size.X*0.25, Palette_RGB(COLOR_KEY)); end; procedure Draw_Number(Start, Size: Vector2; N: Integer; C: Color) is @@ -444,14 +555,14 @@ procedure Game is declare Checkpoint_Item_Size: constant Vector2 := Cell_Size*0.5; begin - Draw_Rectangle_V(To_Vector2(Key(C))*Cell_Size + Cell_Size*0.5 - Checkpoint_Item_Size*0.5, Checkpoint_Item_Size, COLOR_CHECKPOINT); + Draw_Rectangle_V(To_Vector2(Key(C))*Cell_Size + Cell_Size*0.5 - Checkpoint_Item_Size*0.5, Checkpoint_Item_Size, Palette_RGB(COLOR_CHECKPOINT)); end; when Bomb => if Element(C).Cooldown > 0 then - Draw_Bomb(Key(C), Color_Brightness(COLOR_RED, -0.5)); - Draw_Number(Key(C), Element(C).Cooldown, COLOR_LABEL); + Draw_Bomb(Key(C), Color_Brightness(Palette_RGB(COLOR_BOMB), -0.5)); + Draw_Number(Key(C), Element(C).Cooldown, Palette_RGB(COLOR_LABEL)); else - Draw_Bomb(Key(C), COLOR_RED); + Draw_Bomb(Key(C), Palette_RGB(COLOR_BOMB)); end if; end case; end loop; @@ -528,12 +639,12 @@ procedure Game is end loop; end; - Keys: constant array (Direction) of int := ( + Keys: constant array (Direction) of int := [ Left => KEY_A, Right => KEY_D, Up => KEY_W, Down => KEY_S - ); + ]; function Screen_Size return Vector2 is begin @@ -576,11 +687,11 @@ procedure Game is end if; if Game.Turn_Animation > 0.0 then - Draw_Rectangle_V(Interpolate_Positions(Game.Player.Prev_Position, Game.Player.Position, Game.Turn_Animation), Cell_Size, COLOR_PLAYER); + Draw_Rectangle_V(Interpolate_Positions(Game.Player.Prev_Position, Game.Player.Position, Game.Turn_Animation), Cell_Size, Palette_RGB(COLOR_PLAYER)); return; end if; - Draw_Rectangle_V(To_Vector2(Game.Player.Position)*Cell_Size, Cell_Size, COLOR_PLAYER); + Draw_Rectangle_V(To_Vector2(Game.Player.Position)*Cell_Size, Cell_Size, Palette_RGB(COLOR_PLAYER)); if Boolean(Is_Key_Down(KEY_SPACE)) and then Game.Player.Bombs > 0 then for Dir in Direction loop declare @@ -588,7 +699,7 @@ procedure Game is begin Step(Dir, Position); if Game.Map(Position.Y, Position.X) = Floor then - Draw_Bomb(Position, COLOR_RED); + Draw_Bomb(Position, Palette_RGB(COLOR_BOMB)); if Is_Key_Pressed(Keys(Dir)) then for Bomb of Game.Bombs loop if Bomb.Countdown <= 0 then @@ -682,8 +793,8 @@ procedure Game is begin for Bomb of Game.Bombs loop if Bomb.Countdown > 0 then - Draw_Bomb(Bomb.Position, COLOR_RED); - Draw_Number(Bomb.Position, Bomb.Countdown, COLOR_LABEL); + Draw_Bomb(Bomb.Position, Palette_RGB(COLOR_BOMB)); + Draw_Number(Bomb.Position, Bomb.Countdown, Palette_RGB(COLOR_LABEL)); end if; end loop; end; @@ -694,7 +805,7 @@ procedure Game is declare Position: constant Vector2 := (100.0 + C_float(Index - 1)*Cell_Size.X, 100.0); begin - Draw_Circle_V(Position, Cell_Size.X*0.25, COLOR_KEY); + Draw_Circle_V(Position, Cell_Size.X*0.25, Palette_RGB(COLOR_KEY)); end; end loop; @@ -702,11 +813,10 @@ procedure Game is declare Position: constant Vector2 := (100.0 + C_float(Index - 1)*Cell_Size.X, 200.0); begin - Draw_Circle_V(Position, Cell_Size.X*0.5, COLOR_RED); + Draw_Circle_V(Position, Cell_Size.X*0.5, Palette_RGB(COLOR_BOMB)); end; end loop; - if Game.Player.Dead then declare Label: constant Char_Array := To_C("Ded"); @@ -715,7 +825,7 @@ procedure Game is Text_Size: constant Vector2 := To_Vector2((Label_Width, Label_Height)); Position: constant Vector2 := Screen_Size*0.5 - Text_Size*0.5; begin - Draw_Text(Label, Int(Position.X), Int(Position.Y), Int(Label_Height), COLOR_LABEL); + Draw_Text(Label, Int(Position.X), Int(Position.Y), Int(Label_Height), Palette_RGB(COLOR_LABEL)); end; end if; end; @@ -728,7 +838,7 @@ procedure Game is Draw_Rectangle_V( Boundary_Start - (0.0, Health_Padding + Health_Height), (Health_Width, Health_Height), - COLOR_RED); + Palette_RGB(COLOR_HEALTHBAR)); end; procedure Game_Shrek(Game: in out Game_State) is @@ -741,14 +851,30 @@ procedure Game is if Game.Shrek.Dead then return; end if; - Draw_Rectangle_V(Position, Cell_Size*3.0, COLOR_SHREK); + Draw_Rectangle_V(Position, Cell_Size*3.0, Palette_RGB(COLOR_SHREK)); Health_Bar(Position, Size, C_Float(Game.Shrek.Health)); Draw_Number(Position, Size, Game.Shrek.Attack_Cooldown, (A => 255, others => 0)); end; Game: Game_State; Title: constant Char_Array := To_C("Hello, NSA"); + + Palette_Editor: Boolean := False; + Palette_Editor_Choice: Palette := Palette'First; + begin + -- Put("Background"); Put_HSV(Color_To_HSV(COLOR_BACKGROUND)); Put_Line(""); + -- Put("Floor"); Put_HSV(Color_To_HSV(COLOR_FLOOR)); Put_Line(""); + -- Put("Wall"); Put_HSV(Color_To_HSV(COLOR_WALL)); Put_Line(""); + -- Put("Player"); Put_HSV(Color_To_HSV(COLOR_PLAYER)); Put_Line(""); + -- Put("Door"); Put_HSV(Color_To_HSV(COLOR_DOOR)); Put_Line(""); + -- Put("Key"); Put_HSV(Color_To_HSV(COLOR_KEY)); Put_Line(""); + -- Put("Label"); Put_HSV(Color_To_HSV(COLOR_LABEL)); Put_Line(""); + -- Put("Shrek"); Put_HSV(Color_To_HSV(COLOR_SHREK)); Put_Line(""); + -- Put("Checkpoint"); Put_HSV(Color_To_HSV(COLOR_CHECKPOINT)); Put_Line(""); + -- return; + + Load_Colors("colors.txt"); Load_Game_From_File("map.txt", Game, True); Game_Save_Checkpoint(Game); Put_Line("Keys: " & Integer'Image(Game.Player.Keys)); @@ -757,7 +883,7 @@ begin Set_Target_FPS(60); while Window_Should_Close = 0 loop Begin_Drawing; - Clear_Background(COLOR_BACKGROUND); + Clear_Background(Palette_RGB(COLOR_BACKGROUND)); if DEVELOPMENT then if Is_Key_Pressed(KEY_R) then @@ -765,7 +891,13 @@ begin Game_Save_Checkpoint(Game); end if; - -- TODO(tool): implement the palette editor + if Is_Key_Pressed(KEY_O) then + Palette_Editor := not Palette_Editor; + if not Palette_Editor then + Save_Colors("colors.txt"); + end if; + end if; + -- TODO(tool): save current checkpoint to file for debug purposes end if; @@ -784,6 +916,42 @@ begin Game_Hud(Game); Draw_FPS(10, 10); + + if Palette_Editor then + if Is_Key_Pressed(KEY_S) then + if Palette_Editor_Choice /= Palette'Last then + Palette_Editor_Choice := Palette'Succ(Palette_Editor_Choice); + end if; + end if; + + if Is_Key_Pressed(KEY_W) then + if Palette_Editor_Choice /= Palette'First then + Palette_Editor_Choice := Palette'Pred(Palette_Editor_Choice); + end if; + end if; + + if Is_Key_Pressed(KEY_D) then + declare + C: Palette := Palette_Editor_Choice; + begin + Palette_HSV(C).X := Palette_HSV(C).X + 5.0; + Palette_RGB(C) := Color_From_HSV(Palette_HSV(C).X, Palette_HSV(C).Y, Palette_HSV(C).Z); + end; + end if; + + for C in Palette loop + declare + Label: constant Char_Array := To_C(To_String(Palette_Names(C))); + Label_Height: constant Integer := 32; + Position: constant Vector2 := (200.0, 200.0 + C_Float(Palette'Pos(C))*C_Float(Label_Height)); + begin + Draw_Text(Label, Int(Position.X), Int(Position.Y), Int(Label_Height), + (if C = Palette_Editor_Choice + then (R => 255, A => 255, others => 0) + else (others => 255))); + end; + end loop; + end if; End_Drawing; end loop; Close_Window; @@ -66,6 +66,7 @@ package Raylib is KEY_A: constant int := 65; KEY_D: constant int := 68; KEY_P: constant int := 80; + KEY_O: constant int := 79; KEY_SPACE: constant int := 32; function Is_Key_Pressed(key: int) return C_bool with @@ -146,4 +147,14 @@ package Raylib is Import => True, Convention => C, External_Name => "ColorBrightness"; + function Color_To_HSV(C: Color) return Vector3 + with + Import => True, + Convention => C, + External_Name => "ColorToHSV"; + function Color_From_HSV(Hue, Saturation, Value: C_Float) return Color + with + Import => True, + Convention => C, + External_Name => "ColorFromHSV"; end Raylib; diff --git a/raymath.ads b/raymath.ads index 18be3fe..1d38226 100644 --- a/raymath.ads +++ b/raymath.ads @@ -26,4 +26,10 @@ package Raymath is Import => True, Convention => C, External_Name => "Vector2Scale"; + type Vector3 is record + x: C_float; + y: C_float; + z: C_float; + end record + with Convention => C_Pass_By_Copy; end; @@ -1,23 +1,48 @@ +with Ada.Text_IO; with Text_IO; use Text_IO; with Ada.Strings.Fixed; use Ada.Strings.Fixed; with Ada.Strings; use Ada.Strings; with Ada.Containers.Vectors; +with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; procedure Test is - type Item_Kind is (Key, Bomb, Checkpoint); - type Item(Kind: Item_Kind := Key) is record - case Kind is - when Key | Checkpoint => null; - when Bomb => - Cooldown: Integer; - end case; - end record; - type Map is array (Natural range <>) of Item; - type Map_Access is access Map; + File_Name: constant String := "colors.txt"; + F: File_Type; - Items: Map_Access := null; + function Chop_By(Src: in out Unbounded_String; Pattern: String) return Unbounded_String is + Space_Index: Integer := Index(Src, Pattern); + Result: Unbounded_String; + begin + if Space_Index = 0 then + Result := Src; + Src := Null_Unbounded_String; + else + Result := Unbounded_Slice(Src, 1, Space_Index - 1); + Src := Unbounded_Slice(Src, Space_Index + 1, Length(Src)); + end if; + + return Result; + end; begin - Items := new Map(1..10); - Items(1) := (Kind => Bomb, Cooldown => 10); - Put_Line(Items.all'Image); + Open(F, In_File, File_Name); + while not End_Of_File(F) loop + declare + Line: Unbounded_String := To_Unbounded_String(Get_Line(F)); + begin + Line := Trim(Line, Ada.Strings.Left); + Put_Line('"' & To_String(Chop_By(Line, " ")) & '"'); + + for Times in 1..4 loop + Line := Trim(Line, Ada.Strings.Left); + declare + Token: Unbounded_String := Chop_By(Line, " "); + begin + -- Put_Line(Float'Value(To_String(Token))'Image); + Put_Line(To_String(Token)); + end; + end loop; + end; + Put_Line("------------------------------"); + end loop; + Close(F); end; |