refakt
This commit is contained in:
236
bomberman.lua
236
bomberman.lua
@@ -67,6 +67,7 @@ local POWERUP_SPAWN_CHANCE = 0.3
|
|||||||
|
|
||||||
local Input = {}
|
local Input = {}
|
||||||
local Map = {}
|
local Map = {}
|
||||||
|
local Powerup = {}
|
||||||
local UI = {}
|
local UI = {}
|
||||||
local TopBar = {}
|
local TopBar = {}
|
||||||
local Splash = {}
|
local Splash = {}
|
||||||
@@ -137,7 +138,11 @@ local POWERUP_TYPES = {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
local function get_powerup_config(type_name)
|
--------------------------------------------------------------------------------
|
||||||
|
-- Powerup module
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
function Powerup.get_config(type_name)
|
||||||
for _, p in ipairs(POWERUP_TYPES) do
|
for _, p in ipairs(POWERUP_TYPES) do
|
||||||
if p.type == type_name then
|
if p.type == type_name then
|
||||||
return p
|
return p
|
||||||
@@ -146,7 +151,7 @@ local function get_powerup_config(type_name)
|
|||||||
return POWERUP_TYPES[1]
|
return POWERUP_TYPES[1]
|
||||||
end
|
end
|
||||||
|
|
||||||
local function get_random_powerup_type()
|
function Powerup.get_random_type()
|
||||||
local total_weight = 0
|
local total_weight = 0
|
||||||
for _, p in ipairs(POWERUP_TYPES) do
|
for _, p in ipairs(POWERUP_TYPES) do
|
||||||
total_weight = total_weight + p.weight
|
total_weight = total_weight + p.weight
|
||||||
@@ -162,6 +167,45 @@ local function get_random_powerup_type()
|
|||||||
return POWERUP_TYPES[1].type
|
return POWERUP_TYPES[1].type
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function Powerup.init()
|
||||||
|
State.powerups = {}
|
||||||
|
for row = 1, MAP_HEIGHT do
|
||||||
|
for col = 1, MAP_WIDTH do
|
||||||
|
if State.map[row][col] == BREAKABLE_WALL and math.random() < POWERUP_SPAWN_CHANCE then
|
||||||
|
table.insert(State.powerups, {gridX = col, gridY = row, type = Powerup.get_random_type()})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function Powerup.draw_all()
|
||||||
|
for _, pw in ipairs(State.powerups) do
|
||||||
|
if State.map[pw.gridY][pw.gridX] == EMPTY then
|
||||||
|
local drawX = (pw.gridX - 1) * TILE_SIZE
|
||||||
|
local drawY = (pw.gridY - 1) * TILE_SIZE
|
||||||
|
local config = Powerup.get_config(pw.type)
|
||||||
|
rect(drawX + 5, drawY + 5, 10, 10, COLOR_SHADOW)
|
||||||
|
rect(drawX + 3, drawY + 3, 10, 10, config.color)
|
||||||
|
print(config.label, drawX + 5, drawY + 5, COLOR_BLACK)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function Powerup.check_pickup()
|
||||||
|
for _, player in ipairs(State.players) do
|
||||||
|
for i = #State.powerups, 1, -1 do
|
||||||
|
local pw = State.powerups[i]
|
||||||
|
if State.map[pw.gridY][pw.gridX] == EMPTY and
|
||||||
|
player.gridX == pw.gridX and player.gridY == pw.gridY then
|
||||||
|
local config = Powerup.get_config(pw.type)
|
||||||
|
config.apply(player)
|
||||||
|
table.remove(State.powerups, i)
|
||||||
|
sfx(1, nil, 8)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
-- Input module
|
-- Input module
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
@@ -241,21 +285,38 @@ function Map.can_move_to(gridX, gridY, player)
|
|||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function Map.init_powerups()
|
function Map.reset()
|
||||||
State.powerups = {}
|
|
||||||
for row = 1, MAP_HEIGHT do
|
for row = 1, MAP_HEIGHT do
|
||||||
for col = 1, MAP_WIDTH do
|
for col = 1, MAP_WIDTH do
|
||||||
if State.map[row][col] == BREAKABLE_WALL and math.random() < POWERUP_SPAWN_CHANCE then
|
State.map[row][col] = State.initial_map[row][col]
|
||||||
table.insert(State.powerups, {gridX = col, gridY = row, type = get_random_powerup_type()})
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function Map.draw_shadows()
|
||||||
|
for row = 1, MAP_HEIGHT do
|
||||||
|
for col = 1, MAP_WIDTH do
|
||||||
|
local tile = State.map[row][col]
|
||||||
|
if tile == SOLID_WALL or tile == BREAKABLE_WALL then
|
||||||
|
local drawX = (col - 1) * TILE_SIZE
|
||||||
|
local drawY = (row - 1) * TILE_SIZE
|
||||||
|
rect(drawX + 2, drawY + 2, TILE_SIZE, TILE_SIZE, COLOR_SHADOW)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function Map.reset()
|
function Map.draw_tiles()
|
||||||
for row = 1, MAP_HEIGHT do
|
for row = 1, MAP_HEIGHT do
|
||||||
for col = 1, MAP_WIDTH do
|
for col = 1, MAP_WIDTH do
|
||||||
State.map[row][col] = State.initial_map[row][col]
|
local tile = State.map[row][col]
|
||||||
|
local drawX = (col - 1) * TILE_SIZE
|
||||||
|
local drawY = (row - 1) * TILE_SIZE
|
||||||
|
if tile == SOLID_WALL then
|
||||||
|
spr(SOLID_WALL_SPRITE, drawX, drawY, 0, 2)
|
||||||
|
elseif tile == BREAKABLE_WALL then
|
||||||
|
spr(BREAKABLE_WALL_SPRITE, drawX, drawY, 0, 2)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -372,62 +433,11 @@ end
|
|||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
function GameBoard.draw()
|
function GameBoard.draw()
|
||||||
-- draw wall shadows first
|
Map.draw_shadows()
|
||||||
for row = 1, MAP_HEIGHT do
|
Bomb.draw_explosions()
|
||||||
for col = 1, MAP_WIDTH do
|
Map.draw_tiles()
|
||||||
local tile = State.map[row][col]
|
Powerup.draw_all()
|
||||||
if tile == SOLID_WALL or tile == BREAKABLE_WALL then
|
Bomb.draw_all()
|
||||||
local drawX = (col - 1) * TILE_SIZE
|
|
||||||
local drawY = (row - 1) * TILE_SIZE
|
|
||||||
rect(drawX + 2, drawY + 2, TILE_SIZE, TILE_SIZE, COLOR_SHADOW)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- draw explosions (after shadows, before walls)
|
|
||||||
for _, expl in ipairs(State.explosions) do
|
|
||||||
if expl.spread <= 0 then
|
|
||||||
rect(expl.x, expl.y, TILE_SIZE, TILE_SIZE, COLOR_RED)
|
|
||||||
else
|
|
||||||
local progress = 1 - (expl.spread / (expl.dist * SPREAD_DELAY))
|
|
||||||
if progress > 0 then
|
|
||||||
local size = math.floor(TILE_SIZE * progress)
|
|
||||||
local offset = math.floor((TILE_SIZE - size) / 2)
|
|
||||||
rect(expl.x + offset, expl.y + offset, size, size, COLOR_RED)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- draw map tiles
|
|
||||||
for row = 1, MAP_HEIGHT do
|
|
||||||
for col = 1, MAP_WIDTH do
|
|
||||||
local tile = State.map[row][col]
|
|
||||||
local drawX = (col - 1) * TILE_SIZE
|
|
||||||
local drawY = (row - 1) * TILE_SIZE
|
|
||||||
if tile == SOLID_WALL then
|
|
||||||
spr(SOLID_WALL_SPRITE, drawX, drawY, 0, 2)
|
|
||||||
elseif tile == BREAKABLE_WALL then
|
|
||||||
spr(BREAKABLE_WALL_SPRITE, drawX, drawY, 0, 2)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- draw powerups
|
|
||||||
for _, pw in ipairs(State.powerups) do
|
|
||||||
if State.map[pw.gridY][pw.gridX] == EMPTY then
|
|
||||||
local drawX = (pw.gridX - 1) * TILE_SIZE
|
|
||||||
local drawY = (pw.gridY - 1) * TILE_SIZE
|
|
||||||
local config = get_powerup_config(pw.type)
|
|
||||||
rect(drawX + 5, drawY + 5, 10, 10, COLOR_SHADOW)
|
|
||||||
rect(drawX + 3, drawY + 3, 10, 10, config.color)
|
|
||||||
print(config.label, drawX + 5, drawY + 5, COLOR_BLACK)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- draw bombs
|
|
||||||
for _, bomb in ipairs(State.bombs) do
|
|
||||||
Bomb.draw(bomb.x, bomb.y)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- draw players
|
-- draw players
|
||||||
for idx, player in ipairs(State.players) do
|
for idx, player in ipairs(State.players) do
|
||||||
@@ -445,6 +455,27 @@ function Bomb.draw(x, y)
|
|||||||
spr(BOMB_SPRITE, x, y, 0, 2)
|
spr(BOMB_SPRITE, x, y, 0, 2)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function Bomb.draw_all()
|
||||||
|
for _, bomb in ipairs(State.bombs) do
|
||||||
|
Bomb.draw(bomb.x, bomb.y)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function Bomb.draw_explosions()
|
||||||
|
for _, expl in ipairs(State.explosions) do
|
||||||
|
if expl.spread <= 0 then
|
||||||
|
rect(expl.x, expl.y, TILE_SIZE, TILE_SIZE, COLOR_RED)
|
||||||
|
else
|
||||||
|
local progress = 1 - (expl.spread / (expl.dist * SPREAD_DELAY))
|
||||||
|
if progress > 0 then
|
||||||
|
local size = math.floor(TILE_SIZE * progress)
|
||||||
|
local offset = math.floor((TILE_SIZE - size) / 2)
|
||||||
|
rect(expl.x + offset, expl.y + offset, size, size, COLOR_RED)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
function Bomb.place(player)
|
function Bomb.place(player)
|
||||||
if player.activeBombs >= player.maxBombs then return end
|
if player.activeBombs >= player.maxBombs then return end
|
||||||
|
|
||||||
@@ -890,17 +921,17 @@ end
|
|||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
function Game.init()
|
function Game.init()
|
||||||
|
State.winner = nil
|
||||||
|
State.win_timer = 0
|
||||||
|
Bomb.clear_all()
|
||||||
|
Map.reset()
|
||||||
|
|
||||||
State.players = {}
|
State.players = {}
|
||||||
table.insert(State.players, Player.create(2, 2, COLOR_BLUE, false))
|
table.insert(State.players, Player.create(2, 2, COLOR_BLUE, false))
|
||||||
local p2_is_ai = not State.two_player_mode
|
local p2_is_ai = not State.two_player_mode
|
||||||
table.insert(State.players, Player.create(14, 8, COLOR_RED, p2_is_ai))
|
table.insert(State.players, Player.create(14, 8, COLOR_RED, p2_is_ai))
|
||||||
Map.init_powerups()
|
|
||||||
end
|
|
||||||
|
|
||||||
function Game.set_winner(player_num)
|
Powerup.init()
|
||||||
State.winner = player_num
|
|
||||||
State.win_timer = WIN_SCREEN_DURATION
|
|
||||||
State.score[player_num] = State.score[player_num] + 1
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function Game.restart()
|
function Game.restart()
|
||||||
@@ -912,22 +943,14 @@ function Game.restart()
|
|||||||
for _, p in ipairs(State.players) do
|
for _, p in ipairs(State.players) do
|
||||||
Player.reset(p)
|
Player.reset(p)
|
||||||
end
|
end
|
||||||
Map.init_powerups()
|
|
||||||
|
Powerup.init()
|
||||||
end
|
end
|
||||||
|
|
||||||
function Game.check_powerup_pickup()
|
function Game.set_winner(player_num)
|
||||||
for _, player in ipairs(State.players) do
|
State.winner = player_num
|
||||||
for i = #State.powerups, 1, -1 do
|
State.win_timer = WIN_SCREEN_DURATION
|
||||||
local pw = State.powerups[i]
|
State.score[player_num] = State.score[player_num] + 1
|
||||||
if State.map[pw.gridY][pw.gridX] == EMPTY and
|
|
||||||
player.gridX == pw.gridX and player.gridY == pw.gridY then
|
|
||||||
local config = get_powerup_config(pw.type)
|
|
||||||
config.apply(player)
|
|
||||||
table.remove(State.powerups, i)
|
|
||||||
sfx(1, nil, 8)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function Game.check_death_by_explosion()
|
function Game.check_death_by_explosion()
|
||||||
@@ -960,6 +983,30 @@ function Game.check_death_by_collision()
|
|||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function Game.update()
|
||||||
|
-- Get human player as target for AI
|
||||||
|
local human_player = State.players[1]
|
||||||
|
|
||||||
|
-- update all players
|
||||||
|
for idx, player in ipairs(State.players) do
|
||||||
|
Player.update_movement(player)
|
||||||
|
if player.is_ai then
|
||||||
|
AI.update(player, human_player)
|
||||||
|
elseif idx == 1 then
|
||||||
|
Player.handle_input(player)
|
||||||
|
else
|
||||||
|
Player.handle_input_p2(player)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
Bomb.update_all()
|
||||||
|
Powerup.check_pickup()
|
||||||
|
|
||||||
|
if Game.check_death_by_explosion() then return true end
|
||||||
|
if Game.check_death_by_collision() then return true end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
-- Main game loop
|
-- Main game loop
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
@@ -985,26 +1032,7 @@ function TIC()
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Get human player as target for AI
|
if Game.update() then return end
|
||||||
local human_player = State.players[1]
|
|
||||||
|
|
||||||
-- update all players
|
|
||||||
for idx, player in ipairs(State.players) do
|
|
||||||
Player.update_movement(player)
|
|
||||||
if player.is_ai then
|
|
||||||
AI.update(player, human_player)
|
|
||||||
elseif idx == 1 then
|
|
||||||
Player.handle_input(player)
|
|
||||||
else
|
|
||||||
Player.handle_input_p2(player)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
Bomb.update_all()
|
|
||||||
Game.check_powerup_pickup()
|
|
||||||
|
|
||||||
if Game.check_death_by_explosion() then return end
|
|
||||||
if Game.check_death_by_collision() then return end
|
|
||||||
|
|
||||||
GameBoard.draw()
|
GameBoard.draw()
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user