Large refactor to avoid the need to use map() and camera() - the new approach just re-calculates the local world and allows us to scroll 'smoothly' forever.

This commit is contained in:
Anna Rose 2019-12-11 01:06:33 -05:00
parent 2ca23a7b4e
commit 16bcbc8e00
4 changed files with 98 additions and 111 deletions

View File

@ -2,9 +2,8 @@ pico-8 cartridge // http://www.pico-8.com
version 18
__lua__
#include debug.lua
#include data.lua
#include sound.lua
#include mapgen.lua
#include world.lua
#include player.lua
#include main.lua
__gfx__

View File

@ -1,84 +0,0 @@
-- data shared between modules goes here, both constants and mutable data.
-- also contains some functions that act solely on the data
--
-- also has commented "fake constants" that are replaced by actual values, for
-- reference.
--
-- also see index_map.md for more "constant" values
function init_data()
-- block_size = 64
-- biome_size = 128
-- the indices here are sprite numbers.
object_interaction_map = {
-- bush
[3] = {
replacement = 17,
sfx = 13,
drop = 68
},
-- tree
[4] = {
replacement = 14,
sfx = 11,
drop = 64
},
-- big mushroom
[8] = {
replacement = 16,
sfx = 12,
drop = 65
},
-- cactus w/ flower
[10] = {
replacement = 15,
sfx = 12,
drop = 67
},
-- cactus
[13] = {
replacement = 15,
sfx = 12,
drop = 66
}
}
-- 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
mod_buffer = {}
end
-- x and y are global coords
function get_mod_key(x, y)
return tostr(x) .. ":" .. tostr(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
cull_mod_buffer()
end
mod_buffer[get_mod_key(global_x, global_y)] = new_sprite
end
function cull_mod_buffer()
-- we cull 10% of the mod buffer at a time
-- todo: implement this
end
function calculate_world_pos(x, y)
-- player_pos_[xy] is world absolute, so we can get the world pos of map 0,0,
-- then add x and y back in.
return player_pos_x - camera_pos_x - 8 + x,
player_pos_y - camera_pos_y - 8 + y
end

View File

@ -1,24 +1,23 @@
function _init()
init_data()
init_sound()
init_mapgen()
init_sound""
init_world""
init_player(32, 32)
generate_map(0, 0)
init_debug()
init_debug""
end
function _update()
handle_input()
handle_map_update()
handle_input""
-- handle_map_update""
end
function _draw()
cls()
cls""
-- the screen is 128x128 pixels, so it fits 16x16 sprites
map(camera_pos_x, camera_pos_y, 0, 0, 16, 16)
draw_player()
debug_print()
-- map(camera_pos_x, camera_pos_y, 0, 0, 16, 16)
draw_world_segment(player_pos_x, player_pos_y)
draw_player""
debug_print""
end
-- decide whether we need to regenerate the map.

View File

@ -1,8 +1,6 @@
--- Procedural generation methods
function init_mapgen()
uid_seed = 2229 -- arbitrarily chosen number
function init_world()
-- Metadata for different biomes
-- tile_frequencies tuples are {frequency, sprite_index}, see index_map.md
-- frequencies by convention add up to 1000, but this is arbitrary, the
@ -45,6 +43,62 @@ function init_mapgen()
build_biome(biome, biome_data[biome])
end
-- the indices here are sprite numbers.
object_interaction_map = {
-- bush
[3] = {
replacement = 17,
sfx = 13,
drop = 68
},
-- tree
[4] = {
replacement = 14,
sfx = 11,
drop = 64
},
-- big mushroom
[8] = {
replacement = 16,
sfx = 12,
drop = 65
},
-- cactus w/ flower
[10] = {
replacement = 15,
sfx = 12,
drop = 67
},
-- cactus
[13] = {
replacement = 15,
sfx = 12,
drop = 66
}
}
-- 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
mod_buffer = {}
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)
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)
end
end
end
-- build the lookup table for a given biome, based on the biome_meta data for
@ -100,15 +154,34 @@ function get_tile(pos_x, pos_y)
return biome.tile_lookup[(uid % #biome.tile_lookup) + 1]
end
-- generate the map and writes to the map area from 0 - block_size,
-- assuming 'start' as the top-left corner of the map area to generate.
-- writes block_size x block_size tiles
-- after a call to generate_map you should always center the camera/player over the map, i.e.
-- camera at { (block_size / 2) - 8, (block_size / 2) - 8 }
function generate_map(start_x, start_y)
for x=0,63 do
for y=0,63 do
mset(x, y, get_tile(start_x+x, start_y+y))
end
end
---
--- mod buffer functions - these handle parts of the world map that have
--- changed from their 'default' position
---
--- todo: the mod buffer eventually needs to be a bit more elaborate.
--- we need to make it possible to cull only old and unimportant changes,
--- so each entry needs a 'critical' flag and something to indicate order
--- added. We could keep 2 buffers for the latter, one that's just keys
--- in an array... expensive though.
---
-- x and y are global coords
function get_mod_key(x, y)
return tostr(x) .. ":" .. tostr(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
cull_mod_buffer()
end
mod_buffer[get_mod_key(global_x, global_y)] = new_sprite
end
function cull_mod_buffer()
-- we cull 10% of the mod buffer at a time
-- todo: implement this
end