MAKE A ONE-BUTTON GAME USING PICO8 #4 – OBSTACLES
In this port, we will add obstacles into the block and the game will reset the player’s character position into starting position when the player’s character touch obstacles.
ADD VARIABLE AND FUNCTION FOR SUPPORT OBSTACLES IN THE BLOCK
First, we need to modify the function for creating a block by adding a variable for keeping obstacles data.
function create_block(x,y,w,h)
return {x=x,y=y,w=w,h=h,obstacles={}}
end
Second, we add a new function to create obstacle data into the block data. currently, It only data for obstacle’s position inside the block. The value between 0 to 1. 0 = left, 1 = right
function add_obstacle(b,v)
if (b == nil) return
add(b.obstacles, {value=v})
end
And the last one, we need to modify the function for drawing block to support obstacle.
function draw_block(b,c)
if (b == nil) return
rect(b.x,b.y,b.x+b.w,b.y-b.h,c)
for obs in all(b.obstacles) do
print("✽", b.x + (b.w*obs.value), b.y - 6, 8)
end
end
ADD FUNCTIONS FOR THE PLAYER'S CHARACTER
We need to make the player’s character interact with obstacles. We will add 2 new functions for collision detect and reset the player’s character to start position.
function player_hit_obstacle(b)
if b == nil then return false end
for o in all(b.obstacles) do
local dx = player.x - (b.x + b.w * o.value)
local dy = player.y - b.y
local distance = sqrt(dx*dx+dy*dy)
if distance < 3 then
return true
end
end
end
function player_reset()
player = {x=64,y=64,di=1,jump_counter=0,ground=true}
current_block = block_list[1]
end
PUT EVERYTHING TOGETHER
We will add obstacles into a second and third block and make _update60() call function to detect collision between the player’s character and obstacles in the current block.
function _init() add(block_list, create_block(16,64,96,8)) add(block_list, create_block(16,56,96,8)) add(block_list, create_block(16,48,96,8)) current_block = block_list[1] add_obstacle(block_list[2], 0.8) add_obstacle(block_list[3], 0.2) add_obstacle(block_list[3], 0.5) end function _update60() player_running() player_jumping() player_apply_gravity() player_find_new_current_block() local hit_result = player_hit_obstacle(current_block) if hit_result == true then player_reset() end end
RESULT

SOURCE CODE
player = {x=64,y=64,di=1,jump_counter=0,ground=true}
current_block = nil
block_list = {}
function create_block(x,y,w,h)
return {x=x,y=y,w=w,h=h,obstacles={}}
end
function draw_block(b,c)
if (b == nil) return
rect(b.x,b.y,b.x+b.w,b.y-b.h,c)
for obs in all(b.obstacles) do
print("✽", b.x + (b.w*obs.value), b.y - 6, 8)
end
end
function add_obstacle(b,v)
if (b == nil) return
add(b.obstacles, {value=v})
end
function is_inside_block(x,y,b)
if (b == nil) return
if x >= b.x and x < b.x + b.w then
if y <= b.y and y > b.y - b.h then
return true
end
end
return false
end
function player_running()
local next_px = player.x + player.di
if is_inside_block(player.x, player.y, current_block) == true and
is_inside_block(next_px, player.y, current_block) == false then
player.di = player.di * -1
next_px = player.x + player.di
end
player.x = next_px
end
function player_jumping()
if btnp(4) then
if player.jump_counter == 0 and player.ground == true then
player.jump_counter = 20
player.ground = false
end
end
local next_py = player.y
if player.jump_counter > 0 then
player.jump_counter -= 1
if player.jump_counter > 10 then
next_py = player.y - 1
else
next_py = player.y
end
end
player.y = next_py
end
function player_apply_gravity()
local next_py = player.y
if player.ground == false then
if player.jump_counter <= 0 then
next_py += 1
if is_inside_block(player.x, player.y, current_block) == true and
is_inside_block(player.x, next_py, current_block) == false then
next_py = player.y
player.ground = true
end
end
end
player.y = next_py
end
function player_find_new_current_block()
if player.ground == false and
is_inside_block(player.x, player.y, current_block) == false then
for b in all(block_list) do
if is_inside_block(player.x, player.y, b) == true then
current_block = b
break
end
end
end
end
function player_hit_obstacle(b)
if b == nil then return false end
for o in all(b.obstacles) do
local dx = player.x - (b.x + b.w * o.value)
local dy = player.y - b.y
local distance = sqrt(dx*dx+dy*dy)
if distance < 3 then
return true
end
end
end
function player_reset()
player = {x=64,y=64,di=1,jump_counter=0,ground=true}
current_block = block_list[1]
end
function _init()
add(block_list, create_block(16,64,96,8))
add(block_list, create_block(16,56,96,8))
add(block_list, create_block(16,48,96,8))
current_block = block_list[1]
add_obstacle(block_list[2], 0.8)
add_obstacle(block_list[3], 0.2)
add_obstacle(block_list[3], 0.5)
end
function _update60()
player_running()
player_jumping()
player_apply_gravity()
player_find_new_current_block()
local hit_result = player_hit_obstacle(current_block)
if hit_result == true then
player_reset()
end
end
function _draw()
cls(0)
print("웃", player.x-3, player.y - 5, 7)
for b in all(block_list) do
draw_block(b, 7)
end
end
function _draw()
cls(0)
print("웃", player.x-3, player.y - 5, 7)
for b in all(block_list) do
draw_block(b, 7)
end
end










