MAKE A ONE-BUTTON GAME USING PICO8 #7 – BLOCK WITH NO FLOOR

For making block support no floor. The steps that we need todo likely the same as the previous post.
– Add a variable to block data structure.
– Add condition for checking ground.
– Add condition for drawing block’s floor.

ADD A VARIABLE FOR BLOCK'S FLOOR

We need to modify a function for creating block data by adding “ground”.

function create_block(x,y,w,h,left_wall,right_wall, floor)
   return {x=x,y=y,w=w,h=h,obstacles={},left_wall=left_wall,right_wall=right_wall,floor=floor}
end
CONDITION FOR CHECKING GROUND

This condition need to add to “player_apply_gravity()” function. Before we set value that the player’s character stands on the ground. It needs to check that the block has the floor to stand.

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 and 
            current_block.floor == true
            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
MODIFY DRAWING BLOCK FUNCTION

For “draw_block()” function. we will add a condition for checking the “floor” variable for draw block’s floor and we need to remove code for draw block’s ceiling.

function draw_block(b,c)

   if (b == nil) return

   if b.floor == true then
      line(b.x,b.y,b.x+b.w,b.y,c)
   end

   
   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
EDIT BLOCKS

We will edit codes in the “_init()” function that creates block’s data to show what we can achieve with the block with no floor.

function _init()
   add(block_list, create_block(16,64,96,8,true ,true , true))
   add(block_list, create_block(16,56,96,8,true ,false, true))
   add(block_list, create_block(16,48,96,8,false,false , true))
   add(block_list, create_block(16,40,96,8,true,true , false))
   player_reset()

end
RESULT
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, floor)
   return {x=x,y=y,w=w,h=h,obstacles={},left_wall=left_wall,right_wall=right_wall,floor=floor}
end

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

   if b.floor == true then
      line(b.x,b.y,b.x+b.w,b.y,c)
   end

   
   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

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

      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 and 
            current_block.floor == true
            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[1])
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()
   add(block_list, create_block(16,64,96,8,true ,true , true))
   add(block_list, create_block(16,56,96,8,true ,false, true))
   add(block_list, create_block(16,48,96,8,false,false , true))
   add(block_list, create_block(16,40,96,8,true,true , false))
   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
SOURCE CODE

Related Posts