grid movement
This commit is contained in:
204
bomberman.rb
204
bomberman.rb
@@ -16,22 +16,32 @@ EMPTY = 0
|
|||||||
SOLID_WALL = 1
|
SOLID_WALL = 1
|
||||||
BREAKABLE_WALL = 2
|
BREAKABLE_WALL = 2
|
||||||
|
|
||||||
# player
|
# player (grid position and pixel position for animation)
|
||||||
$playerX = 16
|
$player = {
|
||||||
$playerY = 16
|
gridX: 1,
|
||||||
|
gridY: 1,
|
||||||
|
pixelX: 16,
|
||||||
|
pixelY: 16,
|
||||||
|
moving: false
|
||||||
|
}
|
||||||
|
|
||||||
# game objects
|
# game objects
|
||||||
$bombs = []
|
$bombs = []
|
||||||
$explosions = []
|
$explosions = []
|
||||||
|
|
||||||
# enemy
|
# enemy (grid position and pixel position for animation)
|
||||||
$enemy = {
|
$enemy = {
|
||||||
x: 208,
|
gridX: 13,
|
||||||
y: 112,
|
gridY: 7,
|
||||||
dir: 0,
|
pixelX: 208,
|
||||||
|
pixelY: 112,
|
||||||
|
moving: false,
|
||||||
moveTimer: 0
|
moveTimer: 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# animation speed (pixels per frame)
|
||||||
|
MOVE_SPEED = 2
|
||||||
|
|
||||||
# 1=solid wall, 2=breakable wall
|
# 1=solid wall, 2=breakable wall
|
||||||
$map = [
|
$map = [
|
||||||
[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
|
[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
|
||||||
@@ -48,22 +58,13 @@ $map = [
|
|||||||
def TIC
|
def TIC
|
||||||
cls(0)
|
cls(0)
|
||||||
|
|
||||||
# handle input
|
# handle player movement
|
||||||
newX = $playerX
|
update_player
|
||||||
newY = $playerY
|
|
||||||
|
|
||||||
newY = $playerY - 1 if btn(0)
|
|
||||||
newY = $playerY + 1 if btn(1)
|
|
||||||
newX = $playerX - 1 if btn(2)
|
|
||||||
newX = $playerX + 1 if btn(3)
|
|
||||||
|
|
||||||
$playerX = newX unless solid?(newX, $playerY)
|
|
||||||
$playerY = newY unless solid?($playerX, newY)
|
|
||||||
|
|
||||||
# place bomb
|
# place bomb
|
||||||
if btnp(4)
|
if btnp(4)
|
||||||
bombX = ($playerX / TILE_SIZE).floor * TILE_SIZE
|
bombX = $player[:gridX] * TILE_SIZE
|
||||||
bombY = ($playerY / TILE_SIZE).floor * TILE_SIZE
|
bombY = $player[:gridY] * TILE_SIZE
|
||||||
$bombs << { x: bombX, y: bombY, timer: BOMB_TIMER }
|
$bombs << { x: bombX, y: bombY, timer: BOMB_TIMER }
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -109,88 +110,143 @@ def TIC
|
|||||||
# update enemy
|
# update enemy
|
||||||
update_enemy
|
update_enemy
|
||||||
|
|
||||||
# draw player
|
# draw player (centered in tile)
|
||||||
rect($playerX, $playerY, PLAYER_SIZE, PLAYER_SIZE, 12)
|
rect($player[:pixelX] + 2, $player[:pixelY] + 2, PLAYER_SIZE, PLAYER_SIZE, 12)
|
||||||
|
|
||||||
# draw enemy
|
# draw enemy (centered in tile)
|
||||||
rect($enemy[:x], $enemy[:y], PLAYER_SIZE, PLAYER_SIZE, 2)
|
rect($enemy[:pixelX] + 2, $enemy[:pixelY] + 2, PLAYER_SIZE, PLAYER_SIZE, 2)
|
||||||
|
|
||||||
# check player death by explosion
|
# check player death by explosion (grid-based)
|
||||||
$explosions.each do |expl|
|
$explosions.each do |expl|
|
||||||
if $playerX < expl[:x] + TILE_SIZE && $playerX + PLAYER_SIZE > expl[:x] &&
|
explGridX = (expl[:x] / TILE_SIZE).floor
|
||||||
$playerY < expl[:y] + TILE_SIZE && $playerY + PLAYER_SIZE > expl[:y]
|
explGridY = (expl[:y] / TILE_SIZE).floor
|
||||||
$playerX = 16
|
if $player[:gridX] == explGridX && $player[:gridY] == explGridY
|
||||||
$playerY = 16
|
reset_player
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# check player death by enemy
|
# check player death by enemy (grid-based)
|
||||||
if $playerX < $enemy[:x] + PLAYER_SIZE && $playerX + PLAYER_SIZE > $enemy[:x] &&
|
if $player[:gridX] == $enemy[:gridX] && $player[:gridY] == $enemy[:gridY]
|
||||||
$playerY < $enemy[:y] + PLAYER_SIZE && $playerY + PLAYER_SIZE > $enemy[:y]
|
reset_player
|
||||||
$playerX = 16
|
|
||||||
$playerY = 16
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# check enemy death by explosion
|
# check enemy death by explosion (grid-based)
|
||||||
$explosions.each do |expl|
|
$explosions.each do |expl|
|
||||||
if $enemy[:x] < expl[:x] + TILE_SIZE && $enemy[:x] + PLAYER_SIZE > expl[:x] &&
|
explGridX = (expl[:x] / TILE_SIZE).floor
|
||||||
$enemy[:y] < expl[:y] + TILE_SIZE && $enemy[:y] + PLAYER_SIZE > expl[:y]
|
explGridY = (expl[:y] / TILE_SIZE).floor
|
||||||
$enemy[:x] = 208
|
if $enemy[:gridX] == explGridX && $enemy[:gridY] == explGridY
|
||||||
$enemy[:y] = 112
|
reset_enemy
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
print("ARROWS:MOVE A:BOMB", 50, 2, 15)
|
print("ARROWS:MOVE A:BOMB", 50, 2, 15)
|
||||||
end
|
end
|
||||||
|
|
||||||
def solid?(x, y)
|
def update_player
|
||||||
gridLeft = (x / TILE_SIZE).floor
|
targetX = $player[:gridX] * TILE_SIZE
|
||||||
gridTop = (y / TILE_SIZE).floor
|
targetY = $player[:gridY] * TILE_SIZE
|
||||||
gridRight = ((x + PLAYER_SIZE - 1) / TILE_SIZE).floor
|
|
||||||
gridBottom = ((y + PLAYER_SIZE - 1) / TILE_SIZE).floor
|
|
||||||
|
|
||||||
return true if gridLeft < 0 || gridTop < 0 || gridRight > 14 || gridBottom > 8
|
# animate toward target position
|
||||||
return true if $map[gridTop][gridLeft] >= SOLID_WALL
|
if $player[:pixelX] < targetX
|
||||||
return true if $map[gridTop][gridRight] >= SOLID_WALL
|
$player[:pixelX] = [$player[:pixelX] + MOVE_SPEED, targetX].min
|
||||||
return true if $map[gridBottom][gridLeft] >= SOLID_WALL
|
$player[:moving] = true
|
||||||
return true if $map[gridBottom][gridRight] >= SOLID_WALL
|
elsif $player[:pixelX] > targetX
|
||||||
false
|
$player[:pixelX] = [$player[:pixelX] - MOVE_SPEED, targetX].max
|
||||||
|
$player[:moving] = true
|
||||||
|
elsif $player[:pixelY] < targetY
|
||||||
|
$player[:pixelY] = [$player[:pixelY] + MOVE_SPEED, targetY].min
|
||||||
|
$player[:moving] = true
|
||||||
|
elsif $player[:pixelY] > targetY
|
||||||
|
$player[:pixelY] = [$player[:pixelY] - MOVE_SPEED, targetY].max
|
||||||
|
$player[:moving] = true
|
||||||
|
else
|
||||||
|
$player[:moving] = false
|
||||||
|
end
|
||||||
|
|
||||||
|
# only accept input when not moving
|
||||||
|
return if $player[:moving]
|
||||||
|
|
||||||
|
newGridX = $player[:gridX]
|
||||||
|
newGridY = $player[:gridY]
|
||||||
|
|
||||||
|
if btn(0)
|
||||||
|
newGridY = $player[:gridY] - 1
|
||||||
|
elsif btn(1)
|
||||||
|
newGridY = $player[:gridY] + 1
|
||||||
|
elsif btn(2)
|
||||||
|
newGridX = $player[:gridX] - 1
|
||||||
|
elsif btn(3)
|
||||||
|
newGridX = $player[:gridX] + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
# check if new grid position is valid
|
||||||
|
if can_move_to?(newGridX, newGridY)
|
||||||
|
$player[:gridX] = newGridX
|
||||||
|
$player[:gridY] = newGridY
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def update_enemy
|
def update_enemy
|
||||||
|
targetX = $enemy[:gridX] * TILE_SIZE
|
||||||
|
targetY = $enemy[:gridY] * TILE_SIZE
|
||||||
|
|
||||||
|
# animate toward target position
|
||||||
|
if $enemy[:pixelX] < targetX
|
||||||
|
$enemy[:pixelX] = [$enemy[:pixelX] + MOVE_SPEED, targetX].min
|
||||||
|
$enemy[:moving] = true
|
||||||
|
elsif $enemy[:pixelX] > targetX
|
||||||
|
$enemy[:pixelX] = [$enemy[:pixelX] - MOVE_SPEED, targetX].max
|
||||||
|
$enemy[:moving] = true
|
||||||
|
elsif $enemy[:pixelY] < targetY
|
||||||
|
$enemy[:pixelY] = [$enemy[:pixelY] + MOVE_SPEED, targetY].min
|
||||||
|
$enemy[:moving] = true
|
||||||
|
elsif $enemy[:pixelY] > targetY
|
||||||
|
$enemy[:pixelY] = [$enemy[:pixelY] - MOVE_SPEED, targetY].max
|
||||||
|
$enemy[:moving] = true
|
||||||
|
else
|
||||||
|
$enemy[:moving] = false
|
||||||
|
end
|
||||||
|
|
||||||
|
# only move when animation is complete
|
||||||
|
return if $enemy[:moving]
|
||||||
|
|
||||||
$enemy[:moveTimer] += 1
|
$enemy[:moveTimer] += 1
|
||||||
return if $enemy[:moveTimer] < 3
|
return if $enemy[:moveTimer] < 30
|
||||||
|
|
||||||
$enemy[:moveTimer] = 0
|
$enemy[:moveTimer] = 0
|
||||||
|
|
||||||
# try current direction
|
# pick random direction
|
||||||
dirs = [[0, -1], [0, 1], [-1, 0], [1, 0]]
|
dirs = [[0, -1], [0, 1], [-1, 0], [1, 0]]
|
||||||
dir = $enemy[:dir]
|
dir = rand(4)
|
||||||
dx = dirs[dir] ? dirs[dir][0] : 0
|
newGridX = $enemy[:gridX] + dirs[dir][0]
|
||||||
dy = dirs[dir] ? dirs[dir][1] : 0
|
newGridY = $enemy[:gridY] + dirs[dir][1]
|
||||||
|
|
||||||
newEnemyX = $enemy[:x] + dx
|
if can_move_to?(newGridX, newGridY)
|
||||||
newEnemyY = $enemy[:y] + dy
|
$enemy[:gridX] = newGridX
|
||||||
|
$enemy[:gridY] = newGridY
|
||||||
if !solid_for_enemy?(newEnemyX, newEnemyY) && rand > 0.1
|
|
||||||
$enemy[:x] = newEnemyX
|
|
||||||
$enemy[:y] = newEnemyY
|
|
||||||
else
|
|
||||||
$enemy[:dir] = rand(4)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def solid_for_enemy?(x, y)
|
def can_move_to?(gridX, gridY)
|
||||||
gridLeft = (x / TILE_SIZE).floor
|
return false if gridX < 0 || gridY < 0 || gridX > 14 || gridY > 8
|
||||||
gridTop = (y / TILE_SIZE).floor
|
return false if $map[gridY][gridX] >= SOLID_WALL
|
||||||
gridRight = ((x + PLAYER_SIZE - 1) / TILE_SIZE).floor
|
true
|
||||||
gridBottom = ((y + PLAYER_SIZE - 1) / TILE_SIZE).floor
|
end
|
||||||
|
|
||||||
return true if gridLeft < 0 || gridTop < 0 || gridRight > 14 || gridBottom > 8
|
def reset_player
|
||||||
return true if $map[gridTop][gridLeft] >= SOLID_WALL
|
$player[:gridX] = 1
|
||||||
return true if $map[gridTop][gridRight] >= SOLID_WALL
|
$player[:gridY] = 1
|
||||||
return true if $map[gridBottom][gridLeft] >= SOLID_WALL
|
$player[:pixelX] = 16
|
||||||
return true if $map[gridBottom][gridRight] >= SOLID_WALL
|
$player[:pixelY] = 16
|
||||||
false
|
$player[:moving] = false
|
||||||
|
end
|
||||||
|
|
||||||
|
def reset_enemy
|
||||||
|
$enemy[:gridX] = 13
|
||||||
|
$enemy[:gridY] = 7
|
||||||
|
$enemy[:pixelX] = 208
|
||||||
|
$enemy[:pixelY] = 112
|
||||||
|
$enemy[:moving] = false
|
||||||
end
|
end
|
||||||
|
|
||||||
def explode(bombX, bombY)
|
def explode(bombX, bombY)
|
||||||
|
|||||||
Reference in New Issue
Block a user