Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/build-and-archive.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ jobs:
fetch-depth: 15
- uses: actions/setup-node@v4
- name: Setup Lua/Teal
run: sudo apt install luarocks make zip && sudo luarocks install tl
run: sudo apt install luarocks make zip && sudo luarocks install tl && sudo luarocks install cerulean
- name: Setup release bot
run: npm install -g semantic-release @semantic-release/release-notes-generator @semantic-release/exec @commitlint/cli @commitlint/config-conventional
- name: Lint
Expand Down
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,7 @@ package: ${LUTRO_DIST_PATH}

lint:
tl check ${SRCS_LINT}
ceru --check src

format:
ceru src
4 changes: 2 additions & 2 deletions README.MD
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
A minimal Saturn Bomberman clone that is easy to play on RecalBox with friends. Will also work as a way to add new interesting game mechanics.

### Development setup
For developing and building, the dependencies [Lua](https://www.lua.org/), [LuaRocks](https://luarocks.org/), [Make](https://www.gnu.org/software/make/), Zip, and [Teal](https://teal-language.org/) are needed.
For developing and building, the dependencies [Lua](https://www.lua.org/), [LuaRocks](https://luarocks.org/), [Make](https://www.gnu.org/software/make/), Zip, [Cerulean](https://github.com/efredriksson/cerulean), and [Teal](https://teal-language.org/) are needed.

So, something like ```sudo apt install luarocks make zip``` and then ```sudo luarocks install tl``` or similar for your system should do the trick.
So, something like ```sudo apt install luarocks make zip``` and then ```sudo luarocks install tl && luarocks install cerulean``` or similar for your system should do the trick.

You most likely want to setup so that you have a Teal LSP, see [here](https://github.com/teal-language/tl?tab=readme-ov-file#text-editor-support).

Expand Down
17 changes: 11 additions & 6 deletions src/bombs/bombs.tl
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,10 @@ function Bomb:_trigger_belt(direction?: Vector): ConveyorBelt | nil
for _, belt in ipairs(belts) do
if self.position:distance_to(grid.snap_to(self.position)) <= 3 then
local snap_pos = grid.snap_to(self.position)
if snap_pos:equal(belt.position)
and not belt.direction:same_direction(bomb_move_dir) then
if
snap_pos:equal(belt.position)
and not belt.direction:same_direction(bomb_move_dir)
then
return belt
end
end
Expand Down Expand Up @@ -148,8 +150,10 @@ local function moving_into_new_block(
snaps_to.x + i * grid.TILE_SIZE, snaps_to.y + j * grid.TILE_SIZE
)
)
if new_movementbox:overlap(close_block)
and not movementbox:overlap(close_block) then
if
new_movementbox:overlap(close_block)
and not movementbox:overlap(close_block)
then
return close_block
end
end
Expand Down Expand Up @@ -538,8 +542,9 @@ function Bombs:update(
bomb_bouncing = true
end

if not grid.area():contains(bomb:hitbox())
and not bomb.delegate:get_goal() then
if
not grid.area():contains(bomb:hitbox()) and not bomb.delegate:get_goal()
then
bomb_bouncing = true
end

Expand Down
6 changes: 4 additions & 2 deletions src/dino_inputs.tl
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,10 @@ local function handle_jump_input(
dino.jump_powerup_for = dino.jump_powerup_for + dt
end

if (joysticks.is_released(player.id, joysticks.BUTTONS.B) and player:can_jump())
or player:must_jump() then
if
(joysticks.is_released(player.id, joysticks.BUTTONS.B) and player:can_jump())
or player:must_jump()
then
local jump_to = get_jump_target()
player:jump_with_dino(jump_to)
end
Expand Down
6 changes: 4 additions & 2 deletions src/engine/collision.tl
Original file line number Diff line number Diff line change
Expand Up @@ -162,8 +162,10 @@ function Lookup:collisions_between<K is Entity, T>(
for j = y_min, y_max do
local index = index_2d_to_1d(i, j)
for _, check_against in ipairs(self.map[index] or {}) do
if entity ~= check_against
and entity:hitbox():overlap(check_against:hitbox()) then
if
entity ~= check_against
and entity:hitbox():overlap(check_against:hitbox())
then
local in_group = group:get(check_against)
if not (in_group is nil) then
collides_with[entity] = in_group
Expand Down
4 changes: 2 additions & 2 deletions src/engine/geometry/rectangles.tl
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ end
function Rectangle:overlap(other: Rectangle): boolean
return interval_overlap(self.x, self.x + self.width, other.x, other.x + other.width)
and interval_overlap(
self.y, self.y + self.height, other.y, other.y + other.height
)
self.y, self.y + self.height, other.y, other.y + other.height
)
end

local function interval_contained(
Expand Down
4 changes: 3 additions & 1 deletion src/engine/scenes.tl
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,9 @@ function PerformanceSample:start(): number
end

function PerformanceSample:record(before_seconds: number, label: string)
self.accumulated_seconds = self.accumulated_seconds + (lutro.timer.getTime() - before_seconds)
self.accumulated_seconds = self.accumulated_seconds + (
lutro.timer.getTime() - before_seconds
)
self.frame_count = self.frame_count + 1
if self.frame_count >= 300 then
local avg_ms = (self.accumulated_seconds / self.frame_count) * 1000
Expand Down
8 changes: 5 additions & 3 deletions src/engine/tracing.tl
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,11 @@ function SpanTiming:_reqursive_report(indentation: string): string
local parts: {string} = {}
table.insert(
parts,
indentation .. self.name .. ": " .. string.format(
"%.1f", self.elapsed * 1000
) .. "ms"
indentation
.. self.name
.. ": "
.. string.format("%.1f", self.elapsed * 1000)
.. "ms"
)
for _, next_level in ipairs(self.next_levels) do
table.insert(parts, next_level:_reqursive_report(indentation .. " "))
Expand Down
6 changes: 4 additions & 2 deletions src/game/timer.tl
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,10 @@ function GameTimer:update(dt: number)
hurry_up_sound:play()
end
if self:warn_for_sudden_death() then
if self.hurry_text_position.x < hurry_letters_mid
and self.hurry_text_mid_countdown > 0 then
if
self.hurry_text_position.x < hurry_letters_mid
and self.hurry_text_mid_countdown > 0
then
self.hurry_text_mid_countdown = self.hurry_text_mid_countdown - dt
else
self.hurry_text_position = self.hurry_text_position:move(
Expand Down
10 changes: 6 additions & 4 deletions src/game/win_condition.tl
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,9 @@ function SinglesWinCondition:update(dt: number, players_: {Player})
self.is_standing_count = true
end

if not self.have_winner
and self.time_of_1_alive_player > time_to_wait_to_end_game then
if
not self.have_winner and self.time_of_1_alive_player > time_to_wait_to_end_game
then
local winner = alive_players[1]
self.score_board:add_point(winner.id)
self.have_winner = true
Expand Down Expand Up @@ -91,8 +92,9 @@ function TeamsWinCondition:update(dt: number, players_: {Player})
self.is_standing_count = true
end

if not self.have_winner
and self.time_of_1_alive_team > time_to_wait_to_end_game then
if
not self.have_winner and self.time_of_1_alive_team > time_to_wait_to_end_game
then
for winning_team, _ in pairs(alive_teams) do
self.score_board:add_point(winning_team)
end
Expand Down
5 changes: 3 additions & 2 deletions src/itertools.tl
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,9 @@ function LoopIndex:values(): function(): integer
local val = self.start - self.step
local function value_iterator(): integer
val = val + self.step
if (val <= self.end_ and self.step > 0)
or (val >= self.end_ and self.step < 0) then
if
(val <= self.end_ and self.step > 0) or (val >= self.end_ and self.step < 0)
then
return val
end
end
Expand Down
6 changes: 4 additions & 2 deletions src/level_layout/block_layouts.tl
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,10 @@ local function place_soft_blocks(
local i = lutro.math.random(dim.x_max + 1) - 1
local j = lutro.math.random(dim.y_max + 1) - 1
local cell: BlockType = layout[i][j]
if cell == "none"
and not contains_point(exclusion_zone, grid.get_tile_position(i, j)) then
if
cell == "none"
and not contains_point(exclusion_zone, grid.get_tile_position(i, j))
then
layout[i][j] = "soft"
count = count + 1
end
Expand Down
14 changes: 9 additions & 5 deletions src/mad_bombers.tl
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,8 @@ function PlayerCart.new(id: integer, position: number, head: CharacterName): Pla
self.cannon_powerup_for = 0.0
self.turbo = false
self.reload_countdown = 0.0
self.animations, self.loading_animations, self.firing_animations = get_cart_animations()
self.animations, self.loading_animations, self.firing_animations = get_cart_animations(
)
return self
end

Expand Down Expand Up @@ -360,13 +361,16 @@ function MadBombers:handle_cart_move_input(dt: number, cart: PlayerCart)
cart:set_state("backward")
end

if lutro.joystick.isDown(cart.id, joysticks.BUTTONS.R)
and cart.cannon == "ready" then
if
lutro.joystick.isDown(cart.id, joysticks.BUTTONS.R) and cart.cannon == "ready"
then
cart.cannon_powerup_for = cart.cannon_powerup_for + dt
end

if joysticks.is_released(cart.id, joysticks.BUTTONS.R)
or cart.cannon_powerup_for > 0.8 then
if
joysticks.is_released(cart.id, joysticks.BUTTONS.R)
or cart.cannon_powerup_for > 0.8
then
local fire_from, fire_len = cart:fire_cannon()
if fire_from then
local fire_dir = THROW_BOMB_DIRECTION_BY_SIDE[side]
Expand Down
11 changes: 8 additions & 3 deletions src/menus/update_screen.tl
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,10 @@ function UpdateCheckScene:download_finished(): boolean
end

function UpdateCheckScene:update(dt: number)
if joysticks.is_pressed_any(joysticks.BUTTONS.L)
or joysticks.is_pressed_any(joysticks.BUTTONS.A) then
if
joysticks.is_pressed_any(joysticks.BUTTONS.L)
or joysticks.is_pressed_any(joysticks.BUTTONS.A)
then
scenes.set(self.ctx)
return
end
Expand All @@ -105,7 +107,10 @@ function UpdateCheckScene:update(dt: number)
end
if self.have_connection and not (self.started_download or self.is_up_to_date) then
self.started_download = true
local download_cmd = "wget -O " .. self:download_dst() .. " " .. self.download_url
local download_cmd = "wget -O "
.. self:download_dst()
.. " "
.. self.download_url
local finish_touch = " && touch " .. self:download_finish_marker()
os.execute(download_cmd .. finish_touch .. " &")
end
Expand Down
16 changes: 10 additions & 6 deletions src/movement.tl
Original file line number Diff line number Diff line change
Expand Up @@ -222,8 +222,10 @@ local function restrict_player_movement(

local bombs_player_is_inside: {Kinematic: Kinematic} = {}
for _, bomb in ipairs(close_bombs) do
if bomb.position:distance_to(player.position) <= grid.TILE_SIZE * (3 / 4)
and not bomb.has_been_kicked then
if
bomb.position:distance_to(player.position) <= grid.TILE_SIZE * (3 / 4)
and not bomb.has_been_kicked
then
bombs_player_is_inside[bomb] = bomb
end
end
Expand Down Expand Up @@ -263,8 +265,9 @@ local function restrict_player_movement(

for _, bomb in ipairs(close_bombs) do
local bomb_hitbox = bomb:movementbox()
if walking_further_into_block(bomb_hitbox)
and not bombs_player_is_inside[bomb] then
if
walking_further_into_block(bomb_hitbox) and not bombs_player_is_inside[bomb]
then
-- If a bomb has been kicked then it is no longer to move
-- freely in far inside it. This is to stop moving through
-- bombs that are kicked against a player.
Expand Down Expand Up @@ -294,8 +297,9 @@ local function restrict_player_movement(

for _, bomb in ipairs(close_lightning_bombs) do
local bomb_hitbox = bomb:movementbox()
if walking_further_into_block(bomb_hitbox)
and not bombs_player_is_inside[bomb] then
if
walking_further_into_block(bomb_hitbox) and not bombs_player_is_inside[bomb]
then
local corner_cut = try_corner_cut(bomb_hitbox, bomb)
if corner_cut then
return corner_cut
Expand Down
31 changes: 23 additions & 8 deletions src/player_animations.tl
Original file line number Diff line number Diff line change
Expand Up @@ -272,9 +272,11 @@ end

function PlayerEntity:_get_animation(): Animation
local function get_direction(): Direction
if self.player.dino
if
self.player.dino
and self.player.dino.action == "slide"
and self.player.dino.level == 2 then
and self.player.dino.level == 2
then
-- For level 2 dino sliding the character riding it should turn depending
-- on the direction sliding for it to look like they bracing sliding to a stop:
return SLIDE_WIHT_DINO_DIR_MAP[self.player.direction]
Expand Down Expand Up @@ -338,19 +340,23 @@ function PlayerEntity:_draw_mounted()
draw_sonic_blasts(self.player)
end

if self.player.action == "dash"
if
self.player.action == "dash"
and self.player.dino
and self.player.dino.level == 3 then
and self.player.dino.level == 3
then
local shift_vector = DINO_AFTERIMGE_SHIFT[self.player.direction]:scale(
self.player.after_image_shift
)
-- Draw after image shifted behind when dashing
draw(dino_animation, dino_position():move(shift_vector))
end

if self.player.action == "slide"
if
self.player.action == "slide"
and self.player.dino
and self.player.dino.level == 2 then
and self.player.dino.level == 2
then
local character_pos = draw_position:move(
DINO_SLIDE_CHARACTER_ADJUST[self.player.direction]
)
Expand Down Expand Up @@ -418,7 +424,12 @@ local function character_sprite_for_action(
end
end

local base_path = "assets/" .. character_asset .. "/" .. state .. "/" .. action_resolved()
local base_path = "assets/"
.. character_asset
.. "/"
.. state
.. "/"
.. action_resolved()
return {
up = lutro.graphics.newImage(base_path .. "_up.png"),
down = lutro.graphics.newImage(base_path .. "_down.png"),
Expand Down Expand Up @@ -507,7 +518,11 @@ function player_animations.load_assets()
local function get_stun_cry_text_for_dir(dir: string): {integer: Image}
local result: {integer: Image} = {}
for level = 1, 3 do
local asset = "assets/tirras/level_" .. level .. "/stun_cry_text_" .. dir .. ".png"
local asset = "assets/tirras/level_"
.. level
.. "/stun_cry_text_"
.. dir
.. ".png"
result[level] = lutro.graphics.newImage(asset)
end

Expand Down
6 changes: 4 additions & 2 deletions src/player_selection.tl
Original file line number Diff line number Diff line change
Expand Up @@ -200,8 +200,10 @@ function PlayerSelection:handle_player_input()
ok_action = self.selector:increment()
elseif joysticks.is_pressed(self.player_selecting, joysticks.BUTTONS.LEFT) then
ok_action = self.selector:decrement()
elseif (joysticks.is_pressed(self.player_selecting, joysticks.BUTTONS.B)
or joysticks.is_pressed(self.player_selecting, joysticks.BUTTONS.R)) then
elseif (
joysticks.is_pressed(self.player_selecting, joysticks.BUTTONS.B)
or joysticks.is_pressed(self.player_selecting, joysticks.BUTTONS.R)
) then
local selected = table.remove(
self.selectable_characters, self.selector:get_value()
)
Expand Down
Loading
Loading