summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrexim <reximkut@gmail.com>2024-03-20 03:05:59 +0700
committerrexim <reximkut@gmail.com>2024-03-20 03:05:59 +0700
commited1ea1aa66f2b576623606de3a29767cb860ff15 (patch)
tree9b912e7184e92e801cf52927163635fae68e4266
parentc15019b6c2595caf56af1f509679e32e2879ed43 (diff)
Implement eyes for the bosses
-rw-r--r--colors.txt5
-rw-r--r--game.adb79
-rw-r--r--map.pngbin1018 -> 1055 bytes
-rw-r--r--raymath.ads10
4 files changed, 77 insertions, 17 deletions
diff --git a/colors.txt b/colors.txt
index a2cf370..b336b26 100644
--- a/colors.txt
+++ b/colors.txt
@@ -8,8 +8,9 @@ Bomb 0 186 255
Label 0 0 255
Shrek 60 255 255
Urmom 242 196 212
-Gnome 65 194 255
+Gnome 125 194 255
Checkpoint 213 255 255
Explosion 213 255 255
-Healthbar 0 255 255
+Healthbar 0 173 255
NewGame 255 0 255
+EYES 0 0 0
diff --git a/game.adb b/game.adb
index 358c5d6..cffc73b 100644
--- a/game.adb
+++ b/game.adb
@@ -38,7 +38,8 @@ procedure Game is
COLOR_CHECKPOINT,
COLOR_EXPLOSION,
COLOR_HEALTHBAR,
- COLOR_NEW_GAME);
+ COLOR_NEW_GAME,
+ COLOR_EYES);
Palette_Names: constant array (Palette) of Unbounded_String := [
COLOR_BACKGROUND => To_Unbounded_String("Background"),
@@ -55,8 +56,8 @@ procedure Game is
COLOR_CHECKPOINT => To_Unbounded_String("Checkpoint"),
COLOR_EXPLOSION => To_Unbounded_String("Explosion"),
COLOR_HEALTHBAR => To_Unbounded_String("Healthbar"),
- COLOR_NEW_GAME => To_Unbounded_String("NewGame")
- ];
+ COLOR_NEW_GAME => To_Unbounded_String("NewGame"),
+ COLOR_EYES => To_Unbounded_String("EYES")];
type Byte is mod 256;
type HSV_Comp is (Hue, Sat, Value);
@@ -987,6 +988,15 @@ procedure Game is
end loop;
end;
+ function Screen_Player_Position(Game: in Game_State) return Vector2 is
+ begin
+ if Game.Turn_Animation > 0.0 then
+ return Interpolate_Positions(Game.Player.Prev_Position, Game.Player.Position, Game.Turn_Animation);
+ else
+ return To_Vector2(Game.Player.Position)*Cell_Size;
+ end if;
+ end;
+
procedure Game_Player(Game: in out Game_State) is
begin
if Game.Player.Dead then
@@ -1001,12 +1011,12 @@ procedure Game is
return;
end if;
+ Draw_Rectangle_V(Screen_Player_Position(Game), Cell_Size, Palette_RGB(COLOR_PLAYER));
+
if Game.Turn_Animation > 0.0 then
- 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, Palette_RGB(COLOR_PLAYER));
if Space_Down and then Game.Player.Bombs > 0 then
for Dir in Direction loop
declare
@@ -1087,7 +1097,7 @@ procedure Game is
end;
procedure Health_Bar(Boundary_Start, Boundary_Size: Vector2; Health: C_Float) is
- Health_Padding: constant C_Float := 20.0;
+ Health_Padding: constant C_Float := 10.0;
Health_Height: constant C_Float := 10.0;
Health_Width: constant C_Float := Boundary_Size.X*Health;
begin
@@ -1097,6 +1107,34 @@ procedure Game is
Palette_RGB(COLOR_HEALTHBAR));
end;
+ procedure Draw_Eyes(Start, Size: Vector2; Angle: Float; Closed: Boolean) 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;
+ begin
+ if Closed then
+ 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));
+ else
+ Draw_Rectangle_V(Left_Position, Eyes_Size, Palette_RGB(COLOR_EYES));
+ Draw_Rectangle_V(Right_Position, Eyes_Size, Palette_RGB(COLOR_EYES));
+ end if;
+ end;
+
+ procedure Draw_Cooldown_Timer_Bubble(Start, Size: Vector2; Cooldown: Integer; Background: Palette) is
+ Text_Color: constant Color := (A => 255, others => 0);
+ Bubble_Radius: constant C_Float := 30.0;
+ Bubble_Center: constant Vector2 := Start + Size*(0.5, 0.0) - (0.0, Bubble_Radius*2.0);
+ begin
+ Draw_Circle_V(Bubble_Center, Bubble_Radius, Palette_RGB(Background));
+ Draw_Number(Bubble_Center - (Bubble_Radius, Bubble_Radius), (Bubble_Radius, Bubble_Radius)*2.0, Cooldown, Text_Color);
+ end;
+
procedure Game_Bosses(Game: in out Game_State) is
begin
for Boss of Game.Bosses loop
@@ -1109,18 +1147,28 @@ procedure Game is
begin
if not Boss.Dead then
case Boss.Kind is
- when Gnome =>
- declare
- GNOME_SIZE: constant C_Float := 0.7;
- begin
- Draw_Rectangle_V(Position + Cell_Size*0.5 - Cell_Size*GNOME_SIZE*0.5, Cell_Size*GNOME_SIZE, Palette_RGB(Boss.Background));
- end;
when Shrek | Urmom =>
- Draw_Rectangle_V(Position, Cell_Size*To_Vector2(Boss.Size), Palette_RGB(Boss.Background));
+ Draw_Rectangle_V(Position, Size, Palette_RGB(Boss.Background));
Health_Bar(Position, Size, C_Float(Boss.Health));
if Boss.Path(Boss.Position.Y, Boss.Position.X) >= 0 then
- Draw_Number(Position, Size, Boss.Attack_Cooldown, (A => 255, others => 0));
+ 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)), Closed => False);
+ else
+ Draw_Eyes(Position, Size, -Float(Vector2_Line_Angle(Position + Size*0.5, Screen_Player_Position(Game) + Cell_Size*0.5)), Closed => True);
end if;
+ when Gnome =>
+ declare
+ GNOME_RATIO: constant C_Float := 0.7;
+ GNOME_SIZE: constant Vector2 := Cell_Size*GNOME_RATIO;
+ 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)), Closed => False);
+ 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)), Closed => True);
+ end if;
+ end;
end case;
end if;
end;
@@ -1287,7 +1335,6 @@ begin
Close_Window;
end;
--- TODO: Eyes for Bosses
-- TODO: Visual Clue that the Boss is about to kill the Player (only one step in Path Map)
-- TODO: Smarter Path Finding
-- - Recompute Path Map on each boss move. Not the Player turn. Because each Boss position change may affect the Path Map
@@ -1310,6 +1357,7 @@ end;
-- TODO: Different palettes depending on the area
-- Or maybe different palette for each NG+
-- TODO: Path finding considers explosion impenetrable @bug
+-- TODO: Boss slide attack animation is pretty boring @polish
-- TODO: Restart on any key press after ded
-- TODO: Sounds
-- TODO: Player Death animation @polish
@@ -1327,5 +1375,6 @@ end;
-- and the Player Bomb Placement. Map must be recomputed only after
-- the bombs are placed for the turn. This is related to making placement
-- of the bombs a legit turn.
+-- That enables escaping first boss btw.
-- TODO: placing a bomb is not a turn (should it be tho?)
-- TODO: Path finding on a separate thread
diff --git a/map.png b/map.png
index 36621c3..658570c 100644
--- a/map.png
+++ b/map.png
Binary files differ
diff --git a/raymath.ads b/raymath.ads
index 1d38226..4447d45 100644
--- a/raymath.ads
+++ b/raymath.ads
@@ -26,6 +26,16 @@ package Raymath is
Import => True,
Convention => C,
External_Name => "Vector2Scale";
+ function Vector2_Rotate(V: Vector2; Angle: C_Float) return Vector2
+ with
+ Import => True,
+ Convention => C,
+ External_Name => "Vector2Rotate";
+ function Vector2_Line_Angle(Start, Finish: Vector2) return C_Float
+ with
+ Import => True,
+ Convention => C,
+ External_Name => "Vector2LineAngle";
type Vector3 is record
x: C_float;
y: C_float;