Lots of code cleanup. Start implementing mod buffer culling.

This commit is contained in:
Anna Rose 2019-12-11 01:34:46 -05:00
parent 16bcbc8e00
commit 1e9c456f78
4 changed files with 56 additions and 81 deletions

View File

@ -40,7 +40,7 @@ function debug_print()
end
function debug_print_res()
clip(70, 0, 16, 24)
clip(70, 0, 32, 24)
print(stat(0), 70, 0, 15)
print(stat(1), 70, 8, 15)
print(stat(9) .. " / " .. stat(8), 70, 16, 15)
@ -54,15 +54,15 @@ function debug_print_sfx()
end
function debug_print_map()
clip(24, 0, 32, 24)
print(camera_pos_x .. " " .. camera_pos_y, 24, 0, 15)
print(player_pos_x .. " " .. player_pos_y, 24, 8, 15)
print(get_biome_name(player_pos_x, player_pos_y), 24, 16, 15)
clip(24, 0, 32, 16)
print(player_x .. " " .. player_y, 24, 0, 15)
print(get_biome_name(player_x, player_y), 24, 8, 15)
clip()
end
function debug_print_mod_buffer()
clip(0, 0, 16, 128)
rectfill(0,0,16,128,0)
for k,v in pairs(mod_buffer) do
print(k .. ": " .. tostr(v))
end

View File

@ -1,38 +1,18 @@
function _init()
init_sound""
init_world""
init_player(32, 32)
init_player""
init_debug""
end
function _update()
handle_input""
-- handle_map_update""
end
function _draw()
cls""
-- the screen is 128x128 pixels, so it fits 16x16 sprites
-- map(camera_pos_x, camera_pos_y, 0, 0, 16, 16)
draw_world_segment(player_pos_x, player_pos_y)
draw_world(player_x, player_y)
draw_player""
debug_print""
end
-- decide whether we need to regenerate the map.
-- if so, call generate_map appropriately and reset coordinates.
function handle_map_update()
if out_of_bounds(camera_pos_x, camera_pos_y) then
-- out_of_bounds() checks all screen bounds
-- we need to regenerate the map, so we generate a map chunk that
-- places the player in the middle of it.
generate_map(player_pos_x-32, player_pos_y-32)
camera_pos_x, camera_pos_y = 24, 24
end
end
function out_of_bounds(pos_x, pos_y)
return pos_x < 0 or pos_x > 48 or
pos_y < 0 or pos_y > 48
end

View File

@ -2,24 +2,19 @@
-- Larger sprites will probably work for objects, but not for the player.
--
-- exported variables:
-- player_pos_[xy] # absolute position of the player on the 'world map'
-- camera_pos_[xy] # Represents top-left position of the pico-8 camera on
-- # the pico-8 map
-- facing_[vh] # Current facing of the player. Values of
-- # each element can be -1 (up or left), 0 (neutral),
-- # or 1 (down or right)
-- player_[xy] # position of the player on the 'world map'
-- facing_[vh] # Current facing of the player. Values of
-- # each element can be -1 (up or left), 0 (neutral),
-- # or 1 (down or right)
--
-- functions:
-- init_player(x,y) # call this in _init(). Sets player starting position,
-- # assumes the top-left of the pico-8 map is currently
-- # world position 0,0
-- handle_input() # call in _update() to handle movement key presses.
-- # Assumes any sprite with flag 0 set is an obstacle.
-- draw_player() # call in _draw(). Draws the player sprite.
-- init_player() # call this in _init().
-- handle_input() # call in _update() to handle movement key presses.
-- # Assumes any sprite with flag 0 set is an obstacle.
-- draw_player() # call in _draw(). Draws the player sprite.
function init_player(start_pos_x, start_pos_y)
player_pos_x, player_pos_y = start_pos_x, start_pos_y
camera_pos_x, camera_pos_y = start_pos_x-8, start_pos_y-8
function init_player()
player_x, player_y = 0, 0
facing_v = 1
facing_h = 0
@ -46,8 +41,7 @@ end
function handle_input()
local new_pos_x, new_pos_y = camera_pos_x, camera_pos_y
local new_ppos_x, new_ppos_y = player_pos_x, player_pos_y
local new_x, new_y = player_x, player_y
if btnp"4" then
interact()
@ -55,13 +49,11 @@ function handle_input()
if btnp"0" or btnp"1" or btnp"2" or btnp"3" then
if btnp"0" then
new_pos_x -= 1 -- move left
new_ppos_x -= 1
new_x -= 1 -- move left
facing_h = 0xffff
end
if btnp"1" then
new_pos_x += 1 -- move right
new_ppos_x += 1 -- move right
new_x += 1 -- move right
facing_h = 1
end
if not (btnp"0" or btnp"1") then
@ -69,13 +61,11 @@ function handle_input()
end
if btnp"2" then
new_pos_y -= 1 -- move up
new_ppos_y -= 1 -- move up
new_y -= 1 -- move up
facing_v = 0xffff
end
if btnp"3" then
new_pos_y += 1 -- move down
new_ppos_y += 1 -- move down
new_y += 1 -- move down
facing_v = 1
end
if not (btnp"2" or btnp"3") then
@ -83,9 +73,9 @@ function handle_input()
end
end
if legal_move(new_pos_x, new_pos_y) then
camera_pos_x, camera_pos_y = new_pos_x, new_pos_y
player_pos_x, player_pos_y = new_ppos_x, new_ppos_y
-- note that facing always changes, even if we can't move to the new location
if legal_move(new_x, new_y) then
player_x, player_y = new_x, new_y
end
end
@ -102,52 +92,48 @@ function draw_player()
-- todo: introduce the concept of an inventory here
end
-- uses global variables instead of arguments
-- returns x,y for the map-local coordinates of the interactable object
-- returns x,y as the coordinates of the interactable object
-- nil,nil if nothing to interact with
-- NB: this function calls get_tile() from world.lua
function can_interact()
-- flag 1 represents an interactable (read: destructible) sprite.
-- need a map of destructible map objects, appropriate sfx, replacement
-- sprites.
local player_rel_x, player_rel_y = player_pos_x+8, player_pos_y+8
-- check the tile the player is standing on
if fget(mget(player_rel_x, player_rel_y), 1) then
return player_rel_x, player_rel_y
if fget(get_tile(player_x, player_y), 1) then
return player_x, player_y
end
-- check the tile the player is facing
faced_tile_x, faced_tile_y = get_position_facing()
if fget(mget(faced_tile_x, faced_tile_y), 1) then
if fget(get_tile(faced_tile_x, faced_tile_y), 1) then
return faced_tile_x, faced_tile_y
end
return nil, nil
end
-- NB: this function calls get_tile() and references the
-- object_interaction_map from world.lua
function interact()
-- get the position to interact with
local x, y = can_interact()
if (x == nil or y == nil) return
local sprite = mget(x, y)
local sprite = get_tile(x, y)
local data = object_interaction_map[sprite]
-- todo: figure out playing sound effects, animation?
-- modify the rendered tile
mset(x, y, data.replacement)
-- and write the change to the buffer
-- modify the tile by writing the change to the mod_buffer
-- (the rendered image will be updated by draw_world()
write_map_change(data.replacement, x, y)
end
-- returns x,y representing the map-local position the player is facing.
function get_position_facing()
return camera_pos_x+8+facing_h, camera_pos_y+8+facing_v
return player_x+facing_h, player_y+facing_v
end
-- pos is camera position, meaning the map-relative player
-- position is pos + {8, 8}.
-- NB: this function calls get_tile() from world.lua
function legal_move(pos_x, pos_y)
return not fget(mget(pos_x+8, pos_y+8), 0)
return not fget(get_tile(pos_x, pos_y), 0)
end

View File

@ -85,15 +85,15 @@ function init_world()
-- initialize a ring buffer of changed positions. In use, this will be keyed
-- using strings of the form mod_buffer["x:y"], using absolute world
-- coordinates. this is to flatten the buffer so that #mod_cache is useful
-- for checking against max_mod_entries.
max_mod_entries = 4096
-- for checking against the number of allowed entries
mod_buffer = {}
mod_queue = {}
end
-- draw the sprites for this part of the world to the screen
-- this calculates everything about the world fresh every frame,
-- but pico-8 handles this just fine!
function draw_world_segment(start_x, start_y)
function draw_world(start_x, start_y)
for x=0,15 do
for y=0,15 do
spr(get_tile(start_x-8+x, start_y-8+y), x*8, y*8)
@ -172,16 +172,25 @@ function get_mod_key(x, y)
end
-- x and y are map-local coords
function write_map_change(new_sprite, x, y)
local global_x, global_y = calculate_world_pos(x, y)
if #mod_buffer >= max_mod_entries then
function write_map_change(new_sprite, x, y, perm)
if #mod_buffer >= 8192 then
cull_mod_buffer()
end
local key = get_mod_key(x, y)
mod_buffer[key] = new_sprite
mod_buffer[get_mod_key(global_x, global_y)] = new_sprite
-- the queue gives us a time-ordered list of items to delete.
-- anything that should persist is simply not added to the queue,
-- making it un-deletable.
-- obviously if we end up with a *very large number* of persistent
-- objects we can run into trouble, but this is functionally a design
-- limitation.
if not perm then
add(mod_queue, key)
end
end
function cull_mod_buffer()
-- we cull 10% of the mod buffer at a time
-- todo: implement this
-- we cull 512 entries at a time.
-- stub: implement me!
end