## MAKE A ONE-BUTTON GAME USING PICO8 #6 – BLOCK WITH NO WALLS

In this post, we will modify the block data structure to support remove left/right walls from the block. It will add more challenge to the game. What we need to do to support this feature.
– modify the function for creating block data.
– modify the function for drawing block.
– modify the function for checking collision between the player’s character and the block.
– add a condition for checking when the player’s character runs outside the block. It should start appling gravity.

###### ADD VARIABLES TO BLOCK DATA

It needs to have 2 boolean variables for left/right walls. If the value is false then it means no wall for that side.

```function create_block(x,y,w,h,left_wall,right_wall)
return {x=x,y=y,w=w,h=h,obstacles={},left_wall=left_wall,right_wall=right_wall}
end```
###### SUPPORT DRAWING BLOCK WITHOUT WALL

Currently, we draw the block using “rect()” function. This function uses for drawing a rectangle on the screen. It doesn’t work for drawing some parts of the rectangle. we will use “line()” for drawing each side of the block instead.

```function draw_block(b,c)
if (b == nil) return

line(b.x,b.y,b.x+b.w,b.y,c)
line(b.x,b.y-b.h,b.x+b.w,b.y-b.h,c)

if b.left_wall == true then
line(b.x,b.y,b.x,b.y-b.h,c)
end
if b.right_wall == true then
line(b.x+b.w,b.y,b.x+b.w,b.y-b.h,c)
end

for obs in all(b.obstacles) do
print("✽", b.x + (b.w*obs.value), b.y - 6, 8)
end
end```
###### PLAYER'S CHARACTER WILL NOT CHECK COLLISION WHEN RUN TO "NO WALL"

We need to add conditions in the “player_running()” function to make it support block with no left/right walls. When the player’s character hit the wall. It will use the current running direction and status of wall/no wall from block data to decide that it should hit the wall or not.

```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

if player.di == 1 and current_block.right_wall == false then

elseif player.di == -1 and current_block.left_wall == false then

else
player.di = player.di * -1
next_px = player.x + player.di
end
end

player.x = next_px
end```
###### APPLY GRAVITY WHEN THE PLAYER'S CHARACTER RUNS OUTSIDE THE BLOCK

Currently, The code starts applying gravity when the player’s character jump. If it runs outside the block without jumping. It will keep running without falling. It can fix by adding a condition to check that if the player’s character runs outside the block. It will stop staying on the ground.

```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
else
if is_inside_block(player.x, player.y, current_block) == false then
player.ground = false
end
end

player.y = next_py
end```
###### 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,left_wall,right_wall)
return {x=x,y=y,w=w,h=h,obstacles={},left_wall=left_wall,right_wall=right_wall}
end

function draw_block(b,c)
if (b == nil) return

line(b.x,b.y,b.x+b.w,b.y,c)
line(b.x,b.y-b.h,b.x+b.w,b.y-b.h,c)

if b.left_wall == true then
line(b.x,b.y,b.x,b.y-b.h,c)
end
if b.right_wall == true then
line(b.x+b.w,b.y,b.x+b.w,b.y-b.h,c)
end

for obs in all(b.obstacles) do
print("✽", b.x + (b.w*obs.value), b.y - 6, 8)
end
end

function distance(x1,y1,x2,y2)
local dx = x1-x2
local dy = y1-y2
local distance = sqrt(dx*dx+dy*dy)

return distance
end

function change_current_block(b)

current_block = b

local d = distance(camera_data.target_x + 64, camera_data.target_y + 64, current_block.x + current_block.w/2, current_block.y - current_block.h/2)
_debug = d
if d > 12 then
set_camera_target(current_block)
end
end

if (b == nil) return
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

if player.di == 1 and current_block.right_wall == false then

elseif player.di == -1 and current_block.left_wall == false then

else
player.di = player.di * -1
next_px = player.x + player.di
end
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
else
if is_inside_block(player.x, player.y, current_block) == false then
player.ground = false
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
change_current_block(b)
break
end
end
end
end

function player_hit_obstacle(b)
if b == nil then return false end
if is_inside_block(player.x, player.y, current_block) == false  then return false end

for o in all(b.obstacles) do
local d = distance(player.x, player.y, (b.x + b.w * o.value), b.y)

if d < 3 then
return true
end
end
end

function player_reset()
player = {x=64,y=64,di=1,jump_counter=0,ground=true}
change_current_block(block_list)
end

camera_data = {x=0,y=0,target_x=0,target_y=0}

function set_camera_target(b)
if b == nil then return end

local block_center_x = b.x + b.w/2
local block_center_y = b.y - b.h/2

camera_data.target_x = block_center_x - 64
camera_data.target_y = block_center_y - 64
end

function update_camera()
if camera_data.x > camera_data.target_x then
camera_data.x -= 1
elseif camera_data.x < camera_data.target_x then
camera_data.x += 1
end

if camera_data.y > camera_data.target_y then
camera_data.y -= 1
elseif camera_data.y < camera_data.target_y then
camera_data.y += 1
end

camera(camera_data.x, camera_data.y)
end

function _init()
player_reset()

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

update_camera()
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```