4
0

grid movement

This commit is contained in:
Zsolt Tasnadi
2025-12-04 09:58:39 +01:00
parent f8b5184e6c
commit 449d314670

View File

@@ -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
end $player[:moving] = true
elsif $player[:pixelY] < targetY
def update_enemy $player[:pixelY] = [$player[:pixelY] + MOVE_SPEED, targetY].min
$enemy[:moveTimer] += 1 $player[:moving] = true
return if $enemy[:moveTimer] < 3 elsif $player[:pixelY] > targetY
$enemy[:moveTimer] = 0 $player[:pixelY] = [$player[:pixelY] - MOVE_SPEED, targetY].max
$player[:moving] = true
# try current direction
dirs = [[0, -1], [0, 1], [-1, 0], [1, 0]]
dir = $enemy[:dir]
dx = dirs[dir] ? dirs[dir][0] : 0
dy = dirs[dir] ? dirs[dir][1] : 0
newEnemyX = $enemy[:x] + dx
newEnemyY = $enemy[:y] + dy
if !solid_for_enemy?(newEnemyX, newEnemyY) && rand > 0.1
$enemy[:x] = newEnemyX
$enemy[:y] = newEnemyY
else else
$enemy[:dir] = rand(4) $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 end
def solid_for_enemy?(x, y) def update_enemy
gridLeft = (x / TILE_SIZE).floor targetX = $enemy[:gridX] * TILE_SIZE
gridTop = (y / TILE_SIZE).floor targetY = $enemy[: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 $enemy[:pixelX] < targetX
return true if $map[gridTop][gridRight] >= SOLID_WALL $enemy[:pixelX] = [$enemy[:pixelX] + MOVE_SPEED, targetX].min
return true if $map[gridBottom][gridLeft] >= SOLID_WALL $enemy[:moving] = true
return true if $map[gridBottom][gridRight] >= SOLID_WALL elsif $enemy[:pixelX] > targetX
false $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
return if $enemy[:moveTimer] < 30
$enemy[:moveTimer] = 0
# pick random direction
dirs = [[0, -1], [0, 1], [-1, 0], [1, 0]]
dir = rand(4)
newGridX = $enemy[:gridX] + dirs[dir][0]
newGridY = $enemy[:gridY] + dirs[dir][1]
if can_move_to?(newGridX, newGridY)
$enemy[:gridX] = newGridX
$enemy[:gridY] = newGridY
end
end
def can_move_to?(gridX, gridY)
return false if gridX < 0 || gridY < 0 || gridX > 14 || gridY > 8
return false if $map[gridY][gridX] >= SOLID_WALL
true
end
def reset_player
$player[:gridX] = 1
$player[:gridY] = 1
$player[:pixelX] = 16
$player[:pixelY] = 16
$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)