diff --git a/src/Enemy.zig b/src/Enemy.zig index 26daa21..f56d7ed 100644 --- a/src/Enemy.zig +++ b/src/Enemy.zig @@ -5,6 +5,7 @@ const Attrib = @import("Tile.zig").Attrib; const Room = @import("Room.zig"); const Renderer = @import("Renderer.zig"); const Rect = Renderer.Rect; +const effects = @import("effects.zig"); const Self = @This(); @@ -13,7 +14,6 @@ pub const Type = enum { }; var gopher_sprite: Renderer.Texture = undefined; -var hurt_fx: Renderer.Texture = undefined; active: bool = false, type: Type = undefined, @@ -27,7 +27,6 @@ face_left: bool = false, pub fn load() void { gopher_sprite.loadFromUrl("img/gopher.png", 72, 24); - hurt_fx.loadFromUrl("img/hurt.png", 24, 24); } pub fn activate(self: *Self, @"type": Type, box: Box) void { @@ -109,7 +108,7 @@ fn tickGopher(self: *Self, r: std.rand.Random, game: *GameData, attribs: []const fn drawGopher(self: Self) void { if (self.invincibility_frames % 6 >= 3) { - Renderer.Sprite.draw(hurt_fx, self.box.x - 4, self.box.y); + Renderer.Sprite.draw(effects.hurt_fx, self.box.x - 4, self.box.y); return; } diff --git a/src/Player.zig b/src/Player.zig index d4af493..c00b8b7 100644 --- a/src/Player.zig +++ b/src/Player.zig @@ -6,6 +6,7 @@ const Renderer = @import("Renderer.zig"); const Rect = Renderer.Rect; const Tile = @import("Tile.zig"); const Room = @import("Room.zig"); +const effects = @import("effects.zig"); const use_joys_sprite = false; @@ -76,7 +77,6 @@ pub const vmax = 0x0700; const max_health = 31; var sprite: Renderer.Texture = undefined; -var hurt_fx: Renderer.Texture = undefined; var shot_sprite: Renderer.Texture = undefined; pub var no_clip: bool = false; @@ -102,7 +102,6 @@ pub fn load() void { } else { sprite.loadFromUrl("img/zero.png", 256, 64); } - hurt_fx.loadFromUrl("img/hurt.png", 24, 24); shot_sprite.loadFromUrl("img/shot.png", 8, 8); } @@ -125,7 +124,7 @@ pub fn hurt(self: *Player, damage: u8) void { pub fn draw(self: *Player) void { if (self.invincibility_frames % 6 >= 3) { if (self.state == .hurting) { - Renderer.Sprite.draw(hurt_fx, self.box.x - 4, self.box.y); + Renderer.Sprite.draw(effects.hurt_fx, self.box.x - 4, self.box.y); } return; } diff --git a/src/effects.zig b/src/effects.zig new file mode 100644 index 0000000..f96d8e7 --- /dev/null +++ b/src/effects.zig @@ -0,0 +1,50 @@ +const math = @import("std").math; +const Renderer = @import("Renderer.zig"); +const Rect = Renderer.Rect; +const Sprite = Renderer.Sprite; + +var effects_tex: Renderer.Texture = undefined; +var teleport_tex: Renderer.Texture = undefined; +pub var hurt_fx: Renderer.Texture = undefined; + +pub fn load() void { + effects_tex.loadFromUrl("img/effects.png", 120, 24); + teleport_tex.loadFromUrl("img/teleport.png", 24, 32); + hurt_fx.loadFromUrl("img/hurt.png", 24, 24); +} + +pub fn drawDeathEffect(x: i32, y: i32, counter: u32) void { + const frame = @as(i32, @intCast((counter / 3) % 6)); + const src_rect = Rect.init(frame * 24, 0, 24, 24); + + var i: usize = 0; + while (i < 8) : (i += 1) { + const angle: f32 = math.pi * @as(f32, @floatFromInt(i)) / 4.0; + const r: f32 = 2 * @as(f32, @floatFromInt(counter)); + const dx = x + @as(i32, @intFromFloat(r * @cos(angle))); + const dy = y + @as(i32, @intFromFloat(r * @sin(angle))); + Sprite.drawFrame(effects_tex, src_rect, dx, dy); + } +} + +pub fn drawTeleportEffect(player_x: i32, player_y: i32, counter: u8) void { + if (counter < 32) return; + const frame: i32 = counter - 32; + const x = player_x; + var y = player_y; + if (frame <= 10 or frame == 15) { + if (frame != 15) y -= 16 * (10 - frame); + const src_rect = Rect.init(8, 0, 8, 8); + var i: i32 = 0; + while (i < 4) : (i += 1) { + Sprite.drawFrame(teleport_tex, src_rect, x - 4, y + i * 8 - 32); + } + } else if (frame <= 12) { + Sprite.drawFrame(teleport_tex, Rect.init(0, 16, 24, 16), x - 12, y - 16); + Sprite.drawFrame(teleport_tex, Rect.init(0, 16, 24, 8), x - 12, y - 24); + Sprite.drawFrame(teleport_tex, Rect.init(8, 8, 8, 8), x - 4, y - 32); + } else if (frame <= 14) { + Sprite.drawFrame(teleport_tex, Rect.init(0, 24, 24, 8), x - 12, y - 8); + Sprite.drawFrame(teleport_tex, Rect.init(8, 8, 8, 8), x - 4, y - 16); + } +} diff --git a/src/main.zig b/src/main.zig index 46d17ba..1313072 100644 --- a/src/main.zig +++ b/src/main.zig @@ -13,6 +13,7 @@ const Room = @import("Room.zig"); const Stage = @import("Stage.zig"); const Player = @import("Player.zig"); const Enemy = @import("Enemy.zig"); +const effects = @import("effects.zig"); const needleman = @import("stages/needleman.zig").needleman; // Overwrite default log handler @@ -33,9 +34,6 @@ var tiles_tex: Renderer.Texture = undefined; var prev_room_tex: Renderer.Texture = undefined; var cur_room_tex: Renderer.Texture = undefined; -var effects_tex: Renderer.Texture = undefined; -var teleport_tex: Renderer.Texture = undefined; - var font_tex: Renderer.Texture = undefined; var text_tex: Renderer.Texture = undefined; const text_w = screen_width / 8; @@ -376,6 +374,7 @@ fn setText(text: []const u8, x: usize, y: usize) void { export fn onInit() void { Renderer.init(); + effects.load(); Player.load(); Enemy.load(); title_tex.loadFromUrl("img/title.png", 192, 56); @@ -383,8 +382,6 @@ export fn onInit() void { door_sprite.loadFromUrl("img/door.png", 16, 16); spike_sprite.loadFromUrl("img/spike.png", 16, 24); tiles_tex.loadFromUrl("img/needleman.png", 16, 8); - effects_tex.loadFromUrl("img/effects.png", 120, 24); - teleport_tex.loadFromUrl("img/teleport.png", 24, 32); font_tex.loadFromUrl("img/font.png", 16, 8); clearText(); text_tex.loadFromData(text_buffer[0..], text_w, text_h); @@ -458,45 +455,6 @@ fn setNextRoom(next_room_index: u8) void { uploadRoomTexture(&cur_room_tex, cur_stage.rooms[game_data.cur_room_index]); } -var death_frame_counter: u32 = 0; -fn drawDeathEffect(x: i32, y: i32) void { - const frame = @as(i32, @intCast((death_frame_counter / 3) % 6)); - const src_rect = Rect.init(frame * 24, 0, 24, 24); - - var i: usize = 0; - while (i < 8) : (i += 1) { - const angle: f32 = std.math.pi * @as(f32, @floatFromInt(i)) / 4.0; - const r: f32 = 2 * @as(f32, @floatFromInt(death_frame_counter)); - const dx = x + @as(i32, @intFromFloat(r * @cos(angle))); - const dy = y + @as(i32, @intFromFloat(r * @sin(angle))); - Sprite.drawFrame(effects_tex, src_rect, dx, dy); - } - - death_frame_counter += 1; -} - -fn drawTeleportEffect() void { - if (game_data.counter < 32) return; - const frame: i32 = game_data.counter - 32; - const x = game_data.player.box.x + @divTrunc(game_data.player.box.w, 2); - var y = game_data.player.box.y + game_data.player.box.h; - if (frame <= 10 or frame == 15) { - if (frame != 15) y -= 16 * (10 - frame); - const src_rect = Rect.init(8, 0, 8, 8); - var i: i32 = 0; - while (i < 4) : (i += 1) { - Sprite.drawFrame(teleport_tex, src_rect, x - 4, y + i * 8 - 32); - } - } else if (frame <= 12) { - Sprite.drawFrame(teleport_tex, Rect.init(0, 16, 24, 16), x - 12, y - 16); - Sprite.drawFrame(teleport_tex, Rect.init(0, 16, 24, 8), x - 12, y - 24); - Sprite.drawFrame(teleport_tex, Rect.init(8, 8, 8, 8), x - 4, y - 32); - } else if (frame <= 14) { - Sprite.drawFrame(teleport_tex, Rect.init(0, 24, 24, 8), x - 12, y - 8); - Sprite.drawFrame(teleport_tex, Rect.init(8, 8, 8, 8), x - 4, y - 16); - } -} - fn drawTitle() void { Sprite.drawFrame(title_tex, Rect.init(0, 0, 192, 56), 32, 64); } @@ -507,6 +465,7 @@ fn drawHealthbar() void { Sprite.drawFrame(healthbar_tex, Rect.init(12, 0, 12, h), 22, 14); } +var death_frame_counter: u32 = 0; fn draw() void { Renderer.clear(); @@ -528,13 +487,15 @@ fn draw() void { } if (game_data.state == .start) { - // game_data.player.draw(); - drawTeleportEffect(); + const player_x = game_data.player.box.x + @divTrunc(game_data.player.box.w, 2); + const player_y = game_data.player.box.y + game_data.player.box.h; + effects.drawTeleportEffect(player_x, player_y, game_data.counter); } else if (game_data.state == .gameover) { if (death_frame_counter < 40 and death_frame_counter % 8 < 4) { game_data.player.draw(); } - drawDeathEffect(game_data.player.box.x - 4, game_data.player.box.y); + effects.drawDeathEffect(game_data.player.box.x - 4, game_data.player.box.y, death_frame_counter); + death_frame_counter += 1; } else { game_data.player.draw(); }