Jun 25, 2018: ------------- ### prismelmappers whose rgraphs have n_frames > 1 ### It seems obvious that the resulting n_frames should be the product of mapper & mappee shapes. ...we could make it an attribute of prismelmapper: how to treat animation. Options: - mapper's animation happens once per frame of mappee's animation - mappee's animation happens once per frame of mapper's animation - mapper + mappee animate simultaneously <-- this is the default, cos its easiest?.. ...ah, but "mapper" is not a rendergraph, it's a mapper. We could define mapper's n_frames as the LCD of its rendergraphs' n_frames. Jun 27, 2018: ------------- mapper l.blu_double: we're expecting to see light-coloured prismels turned to white, others turned to light blue. But everything is turned to light blue. Is that because our double_sq, double_tri are defined with dark blue? (performs an experiment) ...YES. Well, ok but why?.. -> because of that recursive step: mappers end up seeing how things are composed, it's up to us to make sure they *behave* as if they only see the colors in their sub-shapes' rendered bitmaps. -> ok, so what's the fix? ...idunno, but take a look at that thing in prismelrenderer.c which says: /* TODO: think about this and make sure it's correct */ ...it's probably not correct, eh. UPDATE: It's not correct. I did abstract algebra at it until its incorrectness was proven. T__T Jun 30, 2018: ------------- WHAT'S NEEDED FOR A PROPER DEMO: - Music + SFX. Almost anything will do for now. - Get rid of hexmap "unit": unit starts as (1 0 0 0) and only mappers change it. Then add a way in the map.fus files to specify mapper cache entries, and that's how tilesets with different units can co-exist within same worldmap?.. Not that simple. There are no "vert", "edge" prismels. ...although we could add them, I suppose. Things get a little annoying, since we have to start adding single-"tri" versions of every tile (and player state??), and each mapper needs to have solid mappings for prismels tri, vert, edge. I guess the fus syntax would be: shapes: "tile1": prismels: # default, one-"tri" version: : "tri" (0 0 0 0) 0 f 2 # ...or even have no prismels at all?.. # But having one-"tri" versions is maybe nice # for e.g. a minimap mappings: "curvy": # We're now defining the shape which # will be used for map ("curvy") ("tile1") prismels: # etc "double": # ... Dec 9, 2018: ------------ Something is weird about the "-2+" etc in the following: "spit_dead": animation: once 12 shapes: : "dead_particle" (0 1 3 1) 1 f 0+ (0 6) : "dead_particle" (0 1 3 1) 3 f -2+ (2 6) : "dead_particle" (0 1 3 1) 6 f -3+ (3 6) : "dead_particle" (0 1 3 1) 9 f -5+ (5 6) ...I think those should all either be "0+" or the non-negative versions of themselves (if you see what I mean). Dec 10, 2018: ------------- Actor recordings: if we get a fus format for ranges of frames, and a half-decent tool for stepping through a recording (e.g. if player->keymap >= 0 then the arrow keys control their recording, maybe left/right is forward/back a frame, up/down jumps to start/end, action pauses/unpauses), then we could specify on which frames the given rules of an actor state should be run. Dec 17, 2018: ------------- Palette transitions which are intended to be "instantaneous" (e.g. if !game->smooth_scroll || game->reset_camera) actually lag behind camera pos by 1 frame. Sep 28, 2019: ------------- MAPPERS: These should be generic. Mapped and mappee should both be void*... And then have mapped_type and mappee_type, with some kind of enum whose values are PALETTE, RGRAPH, MAPPER, etc. Sep 29, 2019: ------------- Don't use raw strdup, malloc, etc -- make sure these things are gonna perror and exit() for you eh. Use more water?.. e.g. in dodecas area?.. Add swimming_rollers... or some kind of water creatures... Oct 3, 2019: ------------ COINS ARE FUN Let's make different kinds of collectibles... Little flies, berries, that kind of thing. And place them on the maps. Nov 2, 2019: ------------ * Slightly extend "big roller" section at bottom-right of dodecas, then point one of its doors at a new "gauntlet" worldmap * Extend spidertown, many "layers" connected by doors, eventually wilderness, on other side is another spider settlement (with houses like the broken ones found in wilderness) * Wilderness: actually non-random, please. Or anyway, non-random version. * Roller follows you if you're a roller. * Use this to collect the rollers in dodecas, getting them to... open a door?.. sacrifice them to the dodecas spiders?.. * If you go all the way up to spidertown as a roller, you can collect rollers up there, for some use or other. So we can hide rollers in various little out-of-the-way places which are currently unused. * If you're a spider and you go near these rollers, they could switch hiding-spots. Also we could stick some coins in some of these hiding spots. * Collecting coins does what? Make some nice "plants" with "berries", and make little "flies"... * Getting past the scary bird... gets you a powerup?.. frees the hermit?.. Nov 3, 2019: ------------ Trees: we have right-slanting trees... now also have left-slanting ones!.. E.g. one at bottom-right of current map. Need to go through the water area at top to come around down other side of the left-slanting tree. Trees: the tiny trangles at top should be leaves, so get them appropriate rgraphs. And maybe branches in a background layer. And also... decide why they exist, where they lead etc. Nov 7, 2019: ------------ water map: walled-in bubbles full of water, connected by tunnels?.. Giant rooms with suspended wall-less water bubbles?.. Inverted rooms filled with water but with suspended wall-less air bubbles?.. An enemy who swims faster than you, but you walk faster. So you need to "land" to escape, and "landing" often involves tricky sequences of jumping, doing some kind of turn while swimming, then landing again. Also with this enemy, if there are "air bubbles", then it needs to go around them, whereas you can jump through them! Mar 29, 2020: ------------- * "Firefly" coins which fly around * "Fruit/flower" coins which grow on little plants Jun 15, 2020: ------------- Keep it simple... I want more places to play in Dodecas is probably my favourite, more like that plz. Mix hexas + bigtris, birds + bigrollers. Aug 4, 2020: ------------ * Beef up actors * Better tools for recordings * Ok, we can now get a data dump with list_body. Cool! * How might we go about editing a recording?.. * NOTE: we already have a (self-proclaimedly "ganky") way to start an animation from an arbitrary frame... * body_restart_recording (which looks at body->rec.offset) * Can we turn that into a simple "step forward/backward" feature?.. * And mix that with... ability to scroll through the parts of recording's data (e.g. "+l", "w15") and edit them? * insert/delete/edit recording->nodes * WE DON'T WANT TO EDIT RAW DATA!!! We want to press keys, duhh. * So if you step backwards/forwards through the animation, you can record over it in any spot. * Yeah ok, but what if you want to record over one part and keep the next part?.. * Well that would only work if you ended up in the exact same spot. * So that probably only makes sense for animations which are already split up into actors. Aug 23, 2020: ------------- * MAKE AISPIDER CUSTOMIZABLE * "timid" variant, doesn't make big jumps, can therefore be confined to e.g. left part of spidertown... * The chance percentages could be int vars... * Separate chances for running vs "running off the edge"?.. Aug 23, 2020: ------------- * OMG birdplayer in jungle2.fus is amazing. You can run around & around the cave in the middle. * Add an area full of hexagons and birds. * Make it so when birdplayer is a bird, he's not crushed by birds. * Cheapo way to do it: when birdplayer is bird, he has no hitbox. So he neither crushes nor is crushed. * Future Ben says: modern way is to use a proc, e.g. on "crush": call: "crushed" ...and the "crushed" proc does whatever magic you want to change crushing behaviour based on whether you're a birdplayer or whatever. * Have this area eventually combine with big triangles area. * Is there a "big_trangleplayer"?.. :P * Finish up anim/bubblecar.fus!.. * jungle_aiplayer gets crushed by birds :'( * Add a special "invincible" thing to bodies?.. * (Currently just implicit when body->recording is playing...) Aug 29, 2020: ------------- * roller: after grab, stop until next "wentdown u"?.. Sep 1, 2020: ------------ * aiplayer jumps into walls & explodes sometimes. Not ideal. * after you pass big_roller in triangles world, he goes "crazed" and comes after you?.. * so we... have anim/_big_roller.fus and pass it an IS_CRAZED bool?.. :P Sep 5, 2020: ------------ * Spikeyplayer puzzle!.. there's one already (data/maps/trees/bubbles3-0.fus) where you become rollerplayer, then become spikeyplayer, then can get through a place with 4 deathrollers. If there's only 3 deathrollers, you can get through by waiting for a gap in them so you can safely jump across a little gap & escape. HOWEVER, even when there are 4, you can still escape if you spit at them and confuse them! So that could be used somewhere... * Roller movement: * While extended ("grabbing"), don't grab things on your long sides... that is, All 3 vertices are "sticky": + / \ (+)- + Only the "tip" vertex is "sticky": + - + / / (+)- + ...that still allows e.g. rolling over large gaps of this form: + . + . + Sep 12, 2020: ------------- Saw an aiplayer jump in from left, fly out top right, get stuck somewhere... The AI bug in action?!?! data/maps/wastes/start.fus /exit / enter + . . \ \ . . . + . + + - + + \ + ** Need a way to make actors invincible -- we've got that hardcoded thing with recordings, I want to replace that with an explicit thing, maybe can be set by a recording, but if so, needs to last once recording stops and actor takes over * We already have rec->reacts, is that all we need?.. but make it body->reacts?.. ** Render hexmap submaps' hexboxes for debugging purposes... * Instead of trying to render the outlines, we could e.g. render all tiles a solid colour while some button was held down?.. ** roller: still uses the old "turn" movement style while "u" is held??? (whlie "grabbing") Oct 11, 2020: ------------- * Extend trees worldmap at data/maps/trees/bubbles3-1.fus, going below-right, adding right-sloping tree. * Also: instead of trying to get this bubbles3-1.fus etc area "right", just copy-paste it a bunch (or make a bunch of similar things below it) -- remember why dodecas area is so fun!! Nov 21, 2020: ------------- * minieditor: F8 (reload) should *not* reset editor's properties?.. e.g. current rgraph. * ...but that might be hard, e.g. if you were looking at an rgraph who was dynamically generated (e.g. by a mapper being applied to something). At very least, we'd need to worry about rgraph's index changing, so we'd need to save its name, then reload, then look up that name again. Dec 10, 2020: ------------- Spidertown: current one is small -- "spider fort"? Anyway, the real one should be similar but composed of maany of those circular structures (see data/maps/test/map1.fus). But like... a whole field of them. Randomize it? Enhance collmaptool (or add hexmaptool, submaptool)? Then we can use current random generation stuff, but then *save* the results, and edit them by hand. Hand-curate, if you will. Dec 11, 2020: ------------- LOOK FURTHER INTO EMSCRIPTEN!!! It actually seems to work really well. But how can we e.g. stop window from scrolling when player hits arrow keys?.. And can we map the F* keys to something else?.. The big_roller who guards the entrance to maps/triangles tends to camp on the door. :P Dec 21, 2020: ------------- TINY GIF WRITERS!!! Get yourself some viiiiideoooo https://github.com/nothings/single_file_libs#images * https://github.com/charlietangora/gif-h * https://www.jonolick.com/home/gif-writer Some kind of hexcollmap transformations... similar to mappers for rgraphs: "double": unit: 2 0 0 0 entries: : vert -> collmap: ;; (+) : edge -> collmap: ;; (.)- + - . : face -> collmap: ;; . ;; * ;; . - . ;; *\*/* ;; (.) . . ...can we also map tile_c or whatever?.. the "colours"?.. Maybe: entries: : vert -> collmap: ;; (+) tiles: : "0" -> "1" ...etc... ...? * collmaptool has --rot but no --flip!.. add it plz! Dec 25, 2020: ------------- * A system for changing the tile_c of entire swaths of tiles in a hexcollmap at the same time. * (other than "tilebuckets") * So, continue to create hexcollmaps as we do now, based on how they'll affect collisions... ...but have an easy way to add variety and colour to portions of the map, *independent* of its "shape" (collisionarily speaking). * Present the game as a series of puzzles, similar to tutorial * Overlay that sequence with an open world, totally unexplained, like current demo map * Some interaction between the "two games" (puzzler and open exploration) * E.g. a switch is part of a simple puzzle, but also opens a door in the open world * Or turning into a rollerplayer in open world, using that to blow past a numer of puzzles * Add a door_t property like "noscroll" so camera jumps along with your body! Dec 26, 2020: ------------- * As well as "on" events, add an "always" handler which runs every frame? * Use for things like e.g. affecting the "lighting" (palette) based on distance from camera?.. * Use for things like heat, thirst, etc?.. Dec 30, 2020: ------------- * Currently in test_app_game.c we check if (body->out_of_bounds && !body->state->flying), and display the "You jumped off the map!" message. Instead, maybe add a new value for body->dead?.. (currently there is MOSTLY_DEAD and ALL_DEAD, maybe we want OUT_OF_BOUNDS) Mar 20, 2021: ------------- * When actor dies (or flies off map), should respawn itself after a second or two. (E.g. coin beasts killing themselves by running into walls :P) * player_t has these fields: hexgame_savelocation_t respawn_location; hexgame_savelocation_t safe_location; ...we could maybe move safe_location from player to body?.. ...or we could move {respawn,safe}_location into a new struct, and player & actor can both have one of these structs?.. ...or we could use actor->trf as the place to "reset" an actor to, when body_is_done_for(actor->body). => THIS PROBABLY MAKES THE MOST SENSE. * Add a "gamma" setting or something, so that palette colours are brighter by default. Aug 31, 2021: ------------- * finish tutorial. [*] other tilesets (e.g. wavy fronds of water tileset, and spiky grass of earth, don't hurt you...) [*] other creatures [*] switches [ ] transformations [ ] swimming (?.. or leave it a secret?..) * Where do you go after it?.. * demo. * The new camera scrolling doesn't work so well for certain areas (e.g. zoomed-in portions around jungle5) -- either "fix" those areas (by zooming them out a bit) or allow them to opt into the old scrolling behaviour?.. (or is that behaviour always broken if you fly?..) Oct 2, 2021: ------------ * The current end of water area: this is where the door in hermit's house leads. * He unlocks one side, you unlock the other -- that is, he causes the door to be opened, and you need to travel through water area the regular way to hit a switch, removing some stuff blocking the door. * Add some kind of water animal which chases spiders. * It's slow enough that you can get away, and/or shooting it makes it pause for a second. * BUT ALSO, see earlier in this TODO file, where we propose a water "enemy" who is *faster* than spider at swimming, but slower at walking. So you need to land & run away. And/or use "air bubbles" through which you can jump, but enemy must swim. * Right side of data/maps/demo/jungle5.fus: flierplayer can get trapped in a circle if he flies+lands in from the top-right of the circle O_o * Add rollers to the first water you see in trees area, and to water at start of water area, so players hopefully see it's possible to enter the water. * Water area: bubbles whose contents can be air or water, depending on a switch * You can already shoot while swimming, so the idea will be to swim around and hit switches, positioning yourself so that you land properly when the water you're in turns to air. * SAVEPOINT/DOOR COLLISION: It's weird because they are only this: . * . . ...but they look like they're this: . . *\*/* . - + - . */*\* . . ...this can be weird when a door/savepoint looks like it's "on the ceiling". Then you can't get into it if you're crouching on the ceiling. NOTE: this is fixed if you use anim/door.fus instead of 'D' tiles!.. The anim door is vastly superior in every way. TODO: get rid of 'D' tiles... * VISUAL CLUE SHOWING YOUR SPAWN LOCATION * (At least, showing last-touched savepoint) * You're leading another spider somewhere. At one point you go ahead, other spider waits behind. You come upon an eye, and a switch. The eye says "pssst!". When you hit the switch, eye closes, and other spider comes up. So it's as if... the eyes only open for you, and "hide" by staying closed when other spiders are around. Oct 6, 2021: ------------ MEMORY SAVING MEASURES: * Cache all hexcollmaps by filename + rot * Add properties to "shapes" (the fus structures which are turned into rendergraphs) indicating whether their bitmaps should be cached * See prend->cache_bitmaps (and play with "bin/demo --dont_cache_bitmaps") * Currently runs afoul of out-of-bound check in surface8_get_pixel_ptr, but that only issues a warning... maybe we should just remove the warning? * Also messes up... something... about rendering. prismelmapper->solid, maybe?.. * Collmap parser should "trim" empty space around edge of collmap (E.g. as left by "."s) * Add things spiders can roll?.. * In dodecas area, spiders can be hunting (spitting at some animals till they turn to rollable "food"), or collecting rollable whatevers... and somehow these are transported up to spidertown? * dodecas area: the spiders here should use an "ai" actor which knows how to stay safe from the hexrollers... in particular, this actor should know how to stay inside the dodeca shapes. * Maybe... this actor can use spikey spiders?.. Feels kind of like cheating, but otherwise we need a way for the actor to distinguish the safe and unsafe areas. Nov 3, 2021: ------------ * Sound! Read the ALSA docs: https://www.alsa-project.org/alsa-doc/alsa-lib/group___p_c_m.html#gabc748a500743713eafa960c7d104ca6f ...each function lists example .c files which use it!.. ...from this guy's post on TIGSource: https://forums.tigsource.com/index.php?topic=1733.msg1432473#msg1432473 Dec 13, 2021: ------------- * coinlike things should know how to remove themselves when their key becomes F (or antikey becomes T)?.. * Need this for when mapvar("eyeplayer_vines_ran_away_4") becomes T, then mini_eye should disappear Dec 14, 2021: ------------- Concerning turning into non-spider things, e.g. rollers... That's not gonna interact well with e.g. myvars("carrying"), eh? So we either need to call a certain proc when transforming, or... uh... do something else. => Maybe... switch bodies? => UPDATE: there are now "on_stateset_change" procs. Maaaaybe that could be a solution. Jan 27, 2022: ------------- * Change "nosave" to "save" (so, don't save variables by default...) * For "Roll into a corner" in anim/_spider_crawl.fus, need a different anim than "crawl_step" * We need an anim that makes it look like you're rotating in place, not like... teleporting backwards & then stepping forwards. You know? * Make a real "turn" anim for spider (instead of just reusing "step") Jan 30, 2022: ------------- Backgrounds: * Add more bg submaps, so the grid can be seen. See jungle5_bg.fus for inspiration... Feb 8, 2022: ------------ * Editor should attempt to switch screens or something... currently when it "clears" the screen, really that just adds a bunch of newlines. So after exiting the editor, you can scroll up and see every "frame" it ever rendered. * Factor out some stuff in hexcollmap.c to properly define the "space" of coordinates into collmap->tiles. This "space" is sometimes referred to as "tile coords"?.. E.g. in hexcollmap_collide_elem, a comment says: /* And now, because we were fools and defined */ /* the tile coords such that their Y is flipped */ /* compared to vecspaces, we need to flip that Y */ /* before calling trf_apply and then flip it back */ /* again: */ index.add[1] = -index.add[1]; ...and in hexcollmap.c there are some trf_t instances which represent coords in vecspace, others coords in... "tile space", as it were. Can we make vecspace_to_tilespace and vice versa?.. Should we?.. If not, how do we make it all clear?.. currently it's too confusing. Jul 1, 2022: ------------ Need a better way to debug recordings, hitboxes. * Need a way to start playing a recording, step through frame by frame, then take control at some point and start overwriting the rest of the recording. * set player->body to recording's body * Currently, recordings have 1 keyframe (followed by playback data). * Could we allow multiple keyframes? And then it would be very easy to have a tool for cutting & splicing recordings together?.. * For creating "actors" with multiple recordings: want to make 1 long recording, then automatically split it into multiple recordings and put conditionals between them... ======================================== Regarding this: * F9/F10: need a way to set the filename used by these * commandline option * console command Currently, we have these 2 functions (methods of test_app) for getting recording filenames: * test_app_get_save_recording_filename (used when recording with F9) * test_app_get_load_recording_filename (used when replying with F10) We could add two new fields to test_app: * save_recording_filename * load_recording_filename ...usually they are NULL, and so the current "recs/xxx.fus" template thing is used. But we could say, *if* they are non-NULL, then use them instead. And also, once you've recorded to save_recording_filename, it's set to NULL, so you don't accidentally overwrite it afterwards. ^ OKAY! We did that. Now the issue is that when you F9, it stops your F10. And I think really, the issue here is that body->recording has an "action" (i.e. a state) which can be PLAY or RECORD, when really we want separate body->playing_recording and body->recording_recording. As it were. typedef struct recording { int action; /* enum recording_action */ bool reacts; bool loop; bool resets_position; /* default: true, if false, looping doesn't reset body's position */ const char *stateset_name; const char *state_name; hexgame_location_t loc0; keyinfo_t keyinfo; ARRAY_DECL(struct recording_node, nodes) int frame_i; int node_i; int wait; const char *filename; FILE *file; int offset; /* Weakrefs: */ struct body *body; } recording_t; ^ Most of that isn't actually used when we start a new recording (which happens in body_start_recording). We call recording_reset, and then manually write some stuff to a file: anim: body->stateset->filename state: body->state->name pos: body->loc.pos rot: body->loc.rot turn: body->loc.turn keys: body->keyinfo.{is,was,went}down[i in KEYINFO_KEYS] data: ... ...so I don't think we really even need to use body->recording when we're recording... where all is it used? In body_key{down,up}, we do: if(body->recording.action == RECORDING_ACTION_RECORD){ body_record_keydown(body, key_i); } Of course F9, F10 check whether body->recording.action == RECORDING_ACTION_RECORD to decide what to do. recording_step does this: }else if(rec_action == RECORDING_ACTION_RECORD){ /* record */ recording->wait++; } ...so recording->wait is used when recording... body_start_recording does this: recording_reset(&body->recording); body->recording.action = RECORDING_ACTION_RECORD; body->recording.filename = filename; body->recording.file = f; ...so that's basically it, eh? We need to store the file we write to, maybe the filename, and the "wait" counter. Jul 3, 2022: ------------ * "@", "=", "o": these don't affect rendergraph's bounds???? ...so they can end up wrapping around the rgraph... ===> IMPORTANT! BUG! FIXME! Oct 9, 2022: ------------ When you touch a death roller who's stuck in one place, and you're a spikey spider, you get stuck there in your shielding animation forever! Jan 1, 2023: ------------ There should be an eye which comes out as some kind of eye-worm. O_o There should be eyes which grab death rollers and hold them for you. The rendergraphs generated from submaps should have a "nocache" bool set, causing their bitmaps to never be cached?.. => MAYBE NOT! I tried adding rgraph->cache_bitmaps, which is true by default, but false for submaps' rgraphs. And it actually seemed to cause my laptop to make little quiet clickly noises, like it had to think a bit harder in order to render everything... => TODO: FIGURE OUT HOW TO PROFILE ANYTHING All cached bitmaps should be forgotten whenever the map changes! ...detecting when the map changes would have to be done, like, with a game->cur_map or something... errr camera->cur_map?.. hmmm anyway. Sep 10, 2023: ------------- Owls & mice. Owls are huge; mice are same width as spider (in the sense of tunnel width... but they may be longer than spider). Sep 13, 2023: ------------- It's now possible (with "visible") to stand on some ground, jump off it, then have the gound disappear; so that if you hit something ("maybe_dead"), and then press "u" to go back onto the ground, you will appear in midair and repeatedly jump to your doom. Maybe that's okay?.. because you can still press "1". Or we could try to detect it, and have "u" do the same thing as "1". Jan 2, 2024: ------------ MUSIC!!!!!!!!!!!!! Bytebeats. Hell yeah. The way audio works is: * When initializing SDL, we hand SDL_OpenAudioDevice "desired" and "actual" SDL_AudioSpec structs. * Our desired one will be 1 channel, 8000 Hz, AUDIO_U8, etc. * The desired spec includes a callback function and some "user data" for it. Our user data should be some stuff which depends on current camera? The song (the bytebeat program) is set by... the map? But we pass it the submap, and submaps can turn on or off different parts of the map's music. Somehow. (I guess the submap .fus files can have "audio vars"?.. which are set per submap, and inherited like text etc?..) Anyway the userdata includes a snapshot of current map's vars, the submap "audio vars", and anything else which might be useful. (Can we include, like, distance from dangerous things?.. how would we detect what's dangerous or not?.. anything with a hitbox?.. naahhhh...) (Can we have a noise for jumping?.. maybe anims can have "audio vars"?.. but jumping is more of an event -- can we have "audio events"?.. what would those look like, a queue?.. or maybe just booleans, when each boolean is set by the anim, at the end of the hexgame's step function it notifies audio callback somehow, then resets the boolean to false...) The audio callback runs in a different thread, or something; so the userdata shouldn't include live pointers to game data. It should have copies/snapshots of stuff. And we should use a SDL_LockAudioDevice/SDL_UnlockAudioDevice pair while updating the userdata (which can happen each frame). How many different sample rates do we need to support? Looking at the dropdown on https://dollchan.net/bytebeat, there are preset entries for: * 8000 * 11025 * 16000 * 22050 * 32000 * 44100 * 48000 Soooo... we could try and do fancy math for all that... Or we could try to use SDL_AudioStream to do conversion for us?.. See: https://wiki.libsdl.org/SDL2/Tutorials-AudioStream Or we could just 100% standardize on 8000 Hz for now. Wheee! === TODO: vars_get_or_add is using strdup to copy the key. So, vars own their keys?!?! Preposterous! Give them a stringstore for goodness' sake. Feb 3, 2024: ------------ TOWARDS A HEXCOLLMAP EDITOR: Compare these: $ cat data/maps/demo/start2.fus $ bin/collmaptool -d data/maps/demo/start2.fus ...the latter is missing the vars here: parts: "h": recording "data/recs/hotspot.fus" vars: "key": "guide_passed_start" ...so make sure those are supported correctly. Also add support for '!' and '?'. So anyway, once we're able to read & write the text format for hexcollmap, then we can make a visual editor for it. Or do we want to implement a binary format?.. hmmmmmm naaaaaahh. Because then we'll have to make sure it's backwards compatible and all kinds of stuff, it's going to become a time suck. And harder to debug. Easier to just maintain a single human-readable text format. Anyway, we've already started adding an editor! Use `-E` with collmaptool: $ bin/collmaptool -E data/maps/demo/start.fus Dec 15, 2024: ------------- data/maps/tutorial2, start4.2: Make it easier, like maybe have parts of the map open up as player gets to more places. MULTIPLAYER: * only player 1 should be able to save other players can jump to player 1's last "safe location" Dec 22, 2024: ------------- NEXT STEPS: [ ] Fix all the broken recordings! [X] Fix the aispiders! (So they don't explode themselves, etc) [ ] When a body with a recording dies, e.g. a spider explodes, restart the recording (with resets_position forced to be true). [ ] In dodecas area, start making... "time progression". Like... when you do something, the area changes drastically. In particular, wilderness is transformed into populated stuff. So spiders start building things. [ ] Wilderness: randomized, like current maps/wilderness, but with TUNNELS etc chopped out over top, as it is slowly civilized. Current dodecas area is like a partially-civilized wilderness; we should add highly curated "time progression" to it, but also add a less-curated "dodecas wilderness" which only has the progress of tunnels added to it over time. [ ] TIME PROGRESSION: CHANGE IN TILESET! E.g. grass (earth tileset) overgrows a previously civilized area, or vice versa!.. Or an underwater area (vines tileset) is drained! [ ] Expand water area [ ] The tunnels near its start are actually really cool, like where you swim one direction & crouch, and then to get back, you swim "upside down" and crawl again. [ ] Make a swimming creature, faster than player. In the water worldmap, it chases you; you have to run on the ground to escape, and use air bubbles. [ ] Have a map where there are water-filled tunnels, with the swimming creature, and you need to keep escaping it by coming up onto "land". Sometimes to hit a switch, sometimes to sneak around the creature, etc. [ ] Add some areas where everything is water, with air bubbles; but when you hit switches, air and water are reversed. [ ] Add an area full of various flavours of aispider. Some which know how to hide from birds in tunnels... Some which know how to swim... Some which know how to spit at death rollers to reverse them... [ ] Fix data/maps/demo/jungle5.fus: When you jump up to escape the bird walking back and forth, the camera doesn't scroll to show you unless you go all the way up to the ceiling! Fiiiix [ ] Make an area, near jungle, full of birds. They chase you, you pop in and out of holes, etc. This teaches you how to deal with birds, which allows you to later on save the hermit spider. Or something. [ ] tutorial2: should be part of open-ended world [ ] tutorial3: should be part of open-ended world [ ] Make "pickup slots". You start with 1. Parts of the tutorial teach you how to use some pickups. After going through certain long parts of the open-ended world, you can get extra pickup slots. [ ] Don't worry about adding too many new places, rather make it so existing places change as you achieve stuff. [ ] And the ultimate goal is... what?.. something like rejoining spider city?.. So you complete tasks for spiders in various areas who are... making spider outposts?.. and then they help you get to the city?.. [ ] Big triangle rollers leave a trail?.. making their hitbox clear?.. [ ] Spit should leave a trail?.. [ ] Aimerspider should be able to aim while swimming. [ ] Bring back birdspider. You gain... spit which causes birds (and hexrollers?.. and bigrollers?.. and the water creature, once that exists?..) to kneel, and when you touch them in that state, you rise up on them. And you get back off with 'x' key. [ ] Have an area where spiders "herd" birds around, taming them, riding them, corralling them, etc. This occurs in a "time progression" of, say, jungle?.. [ ] maps/wilderness: for each 5 coins you collect, a tunnel is slowly built across the wilderness??... [ ] Add a way to "multiply", i.e. "stretch", entire anims/actors. E.g. multiply all hex coords by 2, replace "-" with "- + -" in all collmaps, etc. [ ] maps/spidertown (i.e. entrance to trees), the aispiders can currently get in the door from maps/demo!!!! That's... odd. Kind of cool tho. Can we make it clearer? Like, you are letting them in? Maybe they ask you to let them in? Hmmmmmm. OMG THEY CAN GET INTO TREES O_o Dec 31, 2024: ------------- Can coin beasts maybe... stack on top of one another? Become two-legged humanoids like that? [ ] Bring back flierspider! Press 'x' in midair to fly. There's a counter, after which you go back to jumping, and can't fly again until landing. [ ] Also add rockets?.. which do basically the same thing, except you aren't a "rocketspider", rather when you land on a rocket, you fly on it until a counter runs down?.. And rockets... fire continuously out of... cannons?.. [ ] And then we add rockets to an area, and getting to the end of that area gets you flierspider. HERE'S THE PLAN: * Finish all egregrious *fixes*, e.g. recordings. * maps/test/worldmap.fus is wacky, count this as a fix... * Make sure every area you can reach has a "purpose", e.g. a pick-up. * Make sure there's an ending -- any ending. * But it should probably require all the pick-ups. Or like, rescuing a spider from each area (which also have pick-ups, but you don't need to collect them). * Make sure there's an explanation -- any explanation. * E.g. in demo/start3.fus, have a message saying "bring the whatevers back here" or whatever. * Release as a completeable demo! [ ] trees: remove the rollerspider door here, just have spikeyspider. And add a spider which shows you how being spikey works, somehow... And force you to escape through a bunch of deathrollers... So, remove player's ability to just press "1" and magically appear back at a savepoint... [ ] LOOK AT MEMORY USAGE ...it may be causin' fans to blow ...ah ha, but in Jul 2026, we discovered we were creating a fresh texture every frame, and fixed it. It had been taking up almost half the CPU instructions involved with a step of the test_app. Sooo... maybe that will have helped! Jan 8, 2024: ------------ [ ] What do you get from tutorial3?.. rollerspider?.. no, but something. Rollerspider is too powerful!.. Maybe this is one area which is relatively easy, so we just get "progress", not an ability?.. Also, currently it's totally unclear that once you go down & come back up, the switch to get rollerspider has been "unlocked". But I think we should just remove tutorial3/start_exit.fus and its door entirely. I thiiiiink you should probably be rescuing a spider from tutorial3... [ ] I'd like a way to combine palettes. So, do a linear transform between 2 palettes (pal1, pal2, percent). Also a linear transform on a palette with a colour (pal, colour, percent). And then, we can have an area where there's a series of submaps, each one progressing linearly from one palette to another. [X] Instead of text, let's show people where to go using the minimap. So far, we haven't even taught players about the minimap during the tutorial!.. So, let's do things like: [X] Add "target" bodies, which flash on the minimap like the player's body does! But a different colour, maybe even a different rgraph, not just a triangle?.. [X] There is actually already a body->visible_expr, used for bodies which come from submap recordings!.. so... we could actually add support for a "target" field on recording "parts". [-] doors should show up on the minimap as cyan!.. So, when camera_render_map is rendering bodies on the minimap, it should somehow detect doors... I think a body_t field is prooooobably the most straightforward here?.. or rather, body->anim?.. errrrrrrr I guess it should be on the state. So, body->state->is_door. [X] Add "target" submaps, which are rendered on the minimap using a palmapper. (hexmap_submap_t has two fields, rgraph_map and rgraph_minimap. We can apply a palmapper to rgraph_minimap before using it in camera_render_map.) [X] The same way submaps have a visible_expr, they can have a target_expr. ...except, really we want that to go by hexmap_submap_group, right?.. [X] Add "doors" which show you the minimap [X] Make this a separate type of door, i.e. anim/minimap_door.fus [-] Add support for custom text for each such "door" [X] Teach about these in the tutorial?.. or just in demo/start3.fus?.. ...okay? And now, let's think about how to make use of those things... But like, without giving up our "naturalist" feel. I think if there are things on the map which let you use the minimap, instead of a dedicated button, that might be really nice. So then people aren't jumping in and out of the minimap; they're forced to plot a course and then explore it bodily, as it were. But also, the minimap tells people where to go next! And if we're going to show text, maybe we can do it while "using the minimap" like that. But we also need some kind of "dialogue system", I think... Like, it needs to be clearer that another character is speaking to you. Maybe?.. and we could like, point the camera at them while they're speaking, and zoom in a bit?.. [ ] Having a non-player body next to a door currently keeps it closed!.. fix that!.. Look for collmap("cooldown") in anim/_door.fus [ ] Ummmmmm we don't always want an rgraph's palmapper to apply to its labels. E.g. when a spider is carrying something... like if aispiders pick up food in dodecas area, the food turns purple. Jan 19, 2025: ------------- Roller spider: when you're a roller, you can't be crushed! No hitbox?.. Apr 29, 2025: ------------- [ ] When you get rollerspider at the end of tutorial3, we should give you a little puzzley area where you can learn how to use it. [X] When showing minimap, say "press Tab" or something! Actually, what if we remove Tab key, and in minimap you press Enter?.. And each minimap door controls the zoom at which you view the minimap?.. [ ] Replace the "red door" sprite with something minimap-specific [ ] Replace the "red savepoint" sprite with something minimap-specific [ ] A hexmap_submap_group can have a "minimap name", which is displayed when you're in that group at the minimap? [ ] Demo is too open. Currently, it has 3 basic sub-areas you can visit immediately: * jungle * dodecas * spidertown And there are spiders and rollers everywhere. Instead, let's start with the sub-areas closed, except for one, and after exploring for a bit, you meet someone who asks you to do something. Or you go to another worldmap -- maybe tutorial2 or tutorial3?.. And when you come back, more of the demo worldmap has been opened, and some of it has been changed (some rollers, spiders, whatever; also some tunnels added, or something; and of course, the way cleared to one of the sub-areas). [ ] EXPERIMENT WITH THE MAGIC 't' TILE TYPE!.. As the code sayeth: else if(elem->tile_c == 't'){ /* We found a "tunnel" -- some non-colliding stuff which overrides anything solid which might be (in a submap) underneath it!.. So, we break out of iterating over submaps. */ Jul 7, 2026: ------------ [X] Currently we're creating a fresh texture each frame!.. Should we... not do that?! => YES! Fixed it, see: notes/dont_create_a_texture_every_frame.txt [X] Get rid of the excessive "teach people about save points" stuff. Leave the one spikey ball, that's it! Maybe once you run into it, say "it's gone!" or something. [X] Add something visual to the bottom of data/maps/tutorial/entrance.fus to attract players, so they're not trying to figure out how to jump back up the "slides". [X] Similar to how animtool generates graphs of an anim's states, can we have a tool which shows the connections between worldmaps?.. Actually, what we could definitely do is create a graph showing worldmaps and their trees of submaps. What's trickier is doors, because these days there's no door_t, rather we have anim/door.fus, which sets player's map via the "effect" system. Buuuut maybe we can just check for anim/door.fus?.. Or do we need to worry about its "subclasses"?.. $ ack _door.fus anim anim/ability_door.fus 5:import "anim/_door.fus" anim/minimap_door.fus 5:import "anim/_door.fus" anim/door.fus 5:import "anim/_door.fus" Errrrm. And actually, maps don't refer directly to anim/door.fus, they refer to data/recs/door.fus, aaaand pass it some vars: E.g. in data/maps/test/map3_end.fus: "E": recording "data/recs/door.fus" vars: "map": "data/maps/test/worldmap.fus" "location": "test_exit" "D": recording "data/recs/ability_door.fus" vars: "location": "puzzle" "set_yourbool": "is_aimerspider" ...so actually then, maybe we can just check in hexmap_recording->vars for "map" and "location" vars?.. And there is hexcollmap->recordings to look through for that, and hexcollmap->locations which "location" refers to. [ ] Fullscreen mode is being weird!.. Ahhh, probably because of Wayland?.. [ ] Figure out why the window opens, then closes, then opens again... Maybe because of Wayland?.. [ ] Maybe upgrade to SDL3 and see if it works better with Wayland?.. https://wiki.libsdl.org/SDL3/README-wayland [ ] Add some "creatures" like... wavy grass... which you can brush past?.. maybe a "dripping water" kind of thing, too?.. Except there's no gravity, so what's the equivalent of dripping water in a place with no gravity?.. Water droplets which... roll off a surface, like how the spider does?.. Actually that's kind of perfect. Let's have "rolling water droplets" which travel exactly the path the spider should in entrance.fus. ===> OKAY, added "dripper". But it was too distracting in entrance.fus, so didn't add it there. Jul 15, 2026: ------------- [X] How can we extend the rules in actor/_aispider.fus?.. Like, right now we have to manually add combinations, like "jump short", "jump medium", "jump long", "backflip after first jumping short", etc. Clearly, we want some kind of recursive algorithm... OH HOLD UP! We probably only need a loop, not recursive function calls. Because we don't need to do branching logic right now, we just need to determine whether jumping is safe. So, it all comes together something like this: proc "safe_to_jump": #set myvar("_jump_location"): arr: 0 0 0 F set myvar("_jump_location"): my_location while: T do: if: any: coll: all yes at myvar("_jump_location") ;; (+)- + coll: all yes at myvar("_jump_location") ;; + ;; / ;; ( ) + then: set myvar("safe_to_jump"): T break if: coll: any yes at myvar("_jump_location") ;; \*/* ;; + - ;; /*\* ;; ( ) then: set myvar("safe_to_jump"): F break if: coll: all yes at myvar("_jump_location") ;; + ;; ;; ( ) + then: move myvar("_jump_location"): 1 0 rot myvar("_jump_location"): 1 else: move myvar("_jump_location"): 1 0 ...and then later on, we can do stuff like: call: "safe_to_jump" if: expr: myvar("safe_to_jump") then: key: down u ...and so, we need: [X] STATE_EFFECT_TYPE_WHILE [X] STATE_EFFECT_TYPE_BREAK/CONTINUE [X] everywhere we iterate over a bunch of effects and call state_effect_apply, we should factor that out into a function, and have it pay attention to controlflow.should_continue/break ...hmmm looks like we can't quite do a straight-up factor-out, but anyway we can add controlflow checks into the existing loops. See: hexgame_state_controlflow_t [X] support: set myvar("_jump_location"): my_location ...NOTE: `my_location` should allocate a fresh VAL_TYPE_ARR. How is that memory managed?.. Under the hood, `set myvar("_jump_location"): ...` when the value of `...` is VAL_TYPE_ARR does make a copy of the array. But where does the memory for `my_location` live?.. Actually, I think it can just live on the body?! O_o OH HOLD UP, maybe we can just create it in `body_refresh_vars`?!.. So instead of a separate `my_location`, we can just have `myvar(".location")`. Which is equivalent to: arr: myvar(".x") myvar(".y") myvar(".rot") myvar(".turn") ...in which case... why don't we just use that?.. AH HA! Because there is no such `arr: ...` syntax when evaluating an *expression*, only when evaluating a value *literal*. That is, currently only `val_parse` supports `arr`. So anyway, yeah `body_refresh_vars` would make sense. [X] support: move myvar("_jump_location"): 1 0 rot myvar("_jump_location"): 1 flip myvar("_jump_location") [X] support: coll: all yes at myvar("_jump_location") ...HOLY MOLY IT APPEARS TO BE WORKING!!!!! Jul 16, 2026: ------------- [X] Sometimes, aispiders in dodecas are making jumps which cause them to crash!.. is that a bug in "safe_to_jump" proc?.. Let's add a way to parse and run arbitrary effects from the console!.. OKAY ADDED! ae do: print("======") call: "safe_to_jump" vars: "debug": T ...and it looks to me like we are *not* incorrectly reporting that these jumps are safe... unless the way "safe_to_jump" is being called from an actor is the issue?.. OHHHHHHHHH it's because when you jump, you travel at least *two* units forward, not just one! So the proc needs to account for that. [X] The map editor, `bin/collmaptool -E`, currently doesn't grow the map. But we have hexcollmap_union_hexbox for that!.. So, let's have the editor union the collmap by e.g. a hexagon around the cursor each time you move it. Why bother?.. because for e.g. blockers and things, I think it'll be way faster to use arrow keys to sketch out a shape. [X] Map editor should create a new file if it doesn't find the one you specified Jul 17, 2026: ------------- [X] We need a way to tell AI spiders to avoid certain spaces. So basically, "invisible walls" for them. That way, we can keep them out of some places, e.g. keep them from going from spidertown through the door to trees, or keep them hiding inside the safe parts of dodecas so they don't get run over by hexrollers. ==> OKAY, adding a "colltag" concept to submaps... Hmm, but how will we actually use it?.. We would need it in the "safe_to_jump" proc, but also throughout actor/_aispider.fus, basically in every `coll: all no`, of which there are a lot. What if we only use it in "safe_to_jump"?.. so basically, we "allow" aispiders to walk & crawl wherever they want, but if they're gonna jump, they need to make sure we're okay with it. That gives us a way to corral them e.g. within the dodecas area. Is there a nice way to keep them safe from the hexrollers, though?.. Maybe we can implement a "search for safety" proc, which tries to see if we can reach a "safe area" (e.g. space marked with a "safe" colltag) by crawling. So, we don't need a search tree, because crawling forwards is always linear, i.e. you have no choices to make while doing it. That's actually pretty slick... but do we have to manually add the "safe spaces"?.. or can we... calculate the distance to the danger, and move away from it, i.e. check if moving in one or the other direction would decrease the distance?.. For now, let's just make aispiders crouch if they detect anything "crush" nearby. So they'll like... huddle down, waiting for the inevitable. So sad. Unless they're spikeyspiders, of course. ==> OK DONE! We even have them crawling away from the danger... [ ] Sometimes, aispiders in dodecas are making really far jumps, and landing, but then sitting there for a second before disappearing. I assume what's going on is that they're making a jump into "unsafe" space, getting marked as "dead", then hanging around for a few seconds so we can see their "dead" anim (even though it's not playing), then their recording is being restarted. Sooooooooooooooooooo one improvement here would be for the recording to be *immediately* restarted if the body is only "unsafe", not fully dead. Another thing we could do would be to stop aispider from making such far jumps!.. [ ] Maybe after picking up food, you can... pick up rollers?!?!?! Or lead them somewhere?.. how would that work, though... Ooh maybe you leave a trail. Invisible "scent" objects. They have a "freshness" which counts down, and rollers (and maybe other things) will go towards whichever side of them has the freshest scent. [ ] Can we make coins do something when you collect them?.. Like, give you a temporary speed boost or something?.. Ooh ooh or temporary invincibility. So you can power through death rollers, hexrollers, etc. Maybe both!.. and like, sparks can come out of you when you jump. How else do we show your "powerup"?.. can/should we do a palette cycle?.. Anyway, this becomes an easy thing we can hide in places, to give people a "reason" to explore them, because people apparently feel that they need reasons to explore. In particular, we can put some around data/maps/trees/bubbles2.fus. [ ] Added "power jump" and invincibility [ ] When you touch something dangerous and are not hurt, right now nothing happens. We need some kind of purple effect to be spawned... [ ] YOUR SPIT SHOULD BE PURPLE AND SUPER FAST OR SOMETHING [ ] When your spit collects a coin, how does the spit know to give the coin power to you?.. we can run spit's "collected_coin" proc, but it only has access to spit's vars, not yours... Presumably we want something like `as parent`. That is, we have body->parent which is set when one body spawns another (be careful, if parent is removed, all children should set that to NULL!..), and an AS_PARENT enum entry. [ ] Figure out what to do with the top of maps/trees... Ooh ooh, what about a switch which activates a bunch of rockets?.. So like, from then on, all up and down the tree, you can get around more easily by flying on rockets. Hell yeah. And maybe that lets you skip the "puzzle" of how to get from the main tree over to the right, like to start7.fus and its water area. So there are then 2 ways to solve that puzzle, a quick low-tech way where you just find the correct series of jumps, and a slower high-tech way where you get up to the top of the tree, activate the rockets, and use them... [ ] Finish rockets!.. There should be launchers, which can be active or not according to an expr, and they periodically shoot rockets, which you can ride if you jump on them. Hmmmmmmmmm that's probably too confusing. Rather, there are launchers, and if you step onto one, it shoots you out on a rocket. While on a rocket, you can fly (like the flierspiders of old), but there's a countdown, at the end of which you simply find yourself flying straight forward in the usual way (i.e. jumping). Also, probably if you fly into the water, your rocket disappears. [ ] Add cli args for setting mapvars?.. `--mapvar name value` Only usable with `-m map`?.. Although FWIW we can use _test_app_command_apply_effect, i.e. "ae" at the test app console: `ae set mapvar(name): value` [ ] Add an aibird, which checks along the ground to left & right, using a proc similar to "safe_to_jump", and chases spiders. And let's finally add that shark in maps/water. And get it to chase swimming spiders... [X] airollers need to respawn after being killed, like aispiders!.. [ ] Update src/main/animtool.c with recently added conds & effects (NOTE: EFFECT_TYPE_AS should be ignored, because we can't statically know what the stateset of "you" is...) [ ] Add ai blockers to the "spidertown_outskirts" area. And add a way to stop aispiders from entering doors. ...oh wait, I think we already added that?.. see anim/_door.fus: # A body can't use a minimap-door unless the body # is controlled by a player $IF MINIMAP: as you: is_player() Jul 19, 2026: ------------- [X] Get tutorial2 back into the demo!.. It can probably be where you get rollerspider!.. Especially at the end, like the 3 rotated copies of same submap which form a kind of maze: at first that's quite difficult to navigate, but then once you have rollerspider, it's probably much easier. (The submap in question is: data/maps/tutorial2/start4.2.fus) Although I guess we probably need a proper "puzzle which teaches you how to be a rollerspider"... But ok, maybe when you become a rollerspider, you go through such a teaching puzzle, then come *back* to the "3 rotated copies" thing, and this time it's much easier?.. Rollerspider puzzle can include stuff like this: + - + - + \ + - + / \ + - + + + / / / + + + + - + \ / / + - + + \ + - + - + ...but should also teach player about holding "d", e.g. alternating between holes to be avoided (don't press "d") and holes to be taken (do press "d"): *\*/* + - + + - + - + + - + - + + - + + - + / \ \ / / \ + + + - + - + - + + + */*\* */*\* [X] Add some flashing arrows at the start of demo, to show the major options: data/maps/demo/start3.fus: you can go left or right data/maps/demo/pebbles2.fus: you can go left, down, or to the right [X] When you touch an ability_door, it should set your spawn point there, instead of at last save point. Jul 21, 2026: ------------- [X] maps/rollerspider: make sure that one part can't be solved with stickyspider [X] Map collisions are expensive!.. are we doing enough, like are we using hexboxes to avoid iterating over tiles?.. HOLY MOLY, we're iterating over elems of the hitbox, then iterating over all submaps for each of those elems!!!! AND FOR EACH SUBMAP, WE'RE RECALCULATING ITS VISIBILITY ETC EACH TIME!.. (in hexmap_collide_elem, in src/hexmap.c) So that's awful. We should iterate over submaps first, check bounding box (i.e. submap->collmap->hexbox) in case we can exit early, then check visibility in case we can exit early, *THEN* iterate over hitbox elems. Also, from callgrind, I'm seeing that 25% of our time is spent in hexmap_submap_is_visible. O_o Here's a more general breakdown: 100% test_app_mainloop_step: 90% hexgame_step: 7% actor_step 88% hexgame_step: 81% hexmap_step: 36% body_step: 7% body_handle_rules 28% body_update_cur_submap: 24% hexmap_collide_special: 18% hexmap_submap_is_visible 42% hexcollmap_collide: 7% trf_apply 10% strchr (for checking elem_is_solid, etc) 10% test_app_render_game: 6.30% SDL_UpperBlitScaled [X] Cache submap->is_visible each frame! (And submap->colltag) ...okay, after caching is_visible, we now have: 100% test_app_mainloop_step: 6% SDL_PollEvent 12% test_app_render_game: 8.65% SDL_UpperBlitScaled 80% hexgame_step: 74% hexmap_step: 15% body_step: 6% body_handle_rules 7% body_update_cur_submap: 6.21% hexmap_collide_special 56% hexcollmap_collide: 12.67% strchr 9.13% trf_apply HRMMMMM actually, I don't think we gain much from iterating over submaps first. Looks like maps/demo only has 61 submaps?? And there is some trickiness which might make it difficult to change the order of iteration, e.g. in hexmap_collide_elem: else if(elem->tile_c == 't'){ /* We found a "tunnel" -- some non-colliding stuff which overrides anything solid which might be (in a submap) underneath it!.. So, we break out of iterating over submaps. */ break; } ...so maybe let's call it a day for now. We have submap->is_visible, which is already a big improvement. [X] data/maps/tutorial/skypipes2.fus: the guy should wake up and show you how to crawl data/maps/tutorial/skypipes3.fus: the guy should crawl back and forth in the correct spot, not just do it once and go to sleep data/maps/tutorial/skypipes4.fus: the eye should open when player is standing on the spot where they're supposed to jump left underneath... [X] When doing hexmap_collide_special for water, savepoints, etc, are we currently bothering to check against verts and edges?.. if so, cut that out!.. only faces are needed [X] Wow, looks like valexprs own *all* their strings. O_o So like, when valexpr_parse encounters a literal, it uses val_parse on it, which for string tokens results in the val owning the string. So... can we have like, valexpr_parse_with_stringstore, or something?.. Make sure we're passing constant owned strings (e.g. living in a stringstore) to these! [ ] vars_get_or_add -- make sure we always pass a const string, e.g. living in a stringstore, and then get rid of the call to str_dup in here! [X] check where _get_nosave_var is called [ ] check where vars_set_* are called [ ] in src/lexer.c, _fus_lexer_get_name returns a freshly allocated string!.. It's used by e.g. GET_NAME, GET_NAME_OR_STR, _fus_lexer_parse_macro. Do we need to give lexer a stringstore?.. [X] check valexpr_vars_entry_t.name ...looks fine, valexpr_vars doesn't own its own entry names. [X] val_parse -- replace GET_STR with GET_STR_CACHED [X] var_cleanup -- get rid of the free() [X] replace val_set_str with val_set_const_str [ ] review all calls to free() ...OKAY HOLD ON, instead of adding an explicit stringstore param to everything (e.g. to valexpr_parse), let's instead: [-] combine name_store and filename_store, which currently live on the prismelrenderer, for whatever reason... anyway, just have one more-or-less global stringstore. [-] pass a stringstore into fus_lexer_init (and fus_lexer_init_with_vars). [X] ACTUALLY, let's just have a global stringstore. [X] now get rid of all owned strings in the universe, just `const char *` everywhere, baby! [X] review all calls to free() [-] if this turns out to be slow somehow, stringstore can simply implement some kind of "hash" or whatever, so its searches are better than linear. Although, adding a call to stringstore_dump inside stringstore_cleanup, and running demo then exiting, looks like we currently have 4 stores: the name/filename stores for prend and prend_minimap. The prend_minimap stores are negilible. The prend filename store is negligible, like 100 entries. The prend name store is the meat: like 1000 entries. Even then, 1000 entries isn't that bad, since we're only ever doing it while parsing. TL;DR: I THINK WE DON'T CARE ENOUGH TO AIM FOR BETTER-THAN-LINEAR SEARCH. [X] From trees/start7.fus or something, you can jump underneath all the little water bubbles, all the way under the big roller, and end up past his structure! [ ] Add purple savepoints to demo, and make it clear to player that they can use them to jump around data/maps/demo/start3.fus: this is the "hub" data/maps/demo/jungle.fus: below where you deliver the vines spider data/maps/demo/jungle2.fus: currently has a purple savepoint, that's fine data/maps/demo/fisheye.fus: at bottom of dodecas data/maps/test/map2x.fus: in spidertown outskirts data/maps/test/map2x.fus: in "dark spidertown", i.e. data/maps/test/worldmap.fus [ ] Currently, tutorial3 gives you stickyspider. We need to add a data/maps/stickyspider/, similar to data/maps/rollerspider/, which teaches you what it does!.. [ ] Rename some of our map files... data/maps/test/worldmap.fus -> data/maps/dark_spidertown/worldmap.fus Also map1.fus, map3.fus, etc... [ ] MAYBE THE END OF THE GAME IS JUST GETTING THROUGH A SPACE WHICH REQUIRES ALL SPIDER ABILITIES TO GET THROUGH But how do we tell the player this?.. And why does the player want to get through this place?.. Also, ROOM FULL OF COINS!.. so you leave trails as you pass through them. [ ] In data/maps/trees/bubbles3-0.fus, make a better "puzzle which teaches you how to be a spikeyspider". Basically, "you're invincible when you crouch". First, you can go through a tunnel which forces you to crawl, with death rollers in it, and you discover that you are invincible to them. Then, a section where you need to do a series of jumps, during which you are not invincible. So you need to time the jumps, crouching in between them to survive death rollers. Add some spikey spiders whose AI knows to crouch when something dangerous is nearby! (By adding a collmap to aispider which collides with "crush" things in the vicinity.) [ ] The big roller should go *inside* the structure once you collect spikeyspider, so you can have fun going spikey against him [ ] Look into this comment in data/maps/demo/worldmap.fus: empty # no palmapper... this is needed so we can specify target... TODO: fix this madness [ ] Add aiflier, use it to replace the recording in spidertown outskirts. The aiflier should try to fly more or less parallel to some solid map nearby. [ ] Spikeyspider + rollerspider: while rolling, show your spikes, have a hitbox, and wiggle back & forth when crushed! [ ] Touma found a bug!.. one of the doors around "dark spidertown" resulted in: Loading submap: data/maps/test/map3x.fus Duplicate location: "test_exit" Cleaning up... double free or corruption (!prev) Aborted [ ] console.c improvements: [ ] support left/right arrow keys?.. and a flashing cursor?.. [ ] support history via up/down arrow keys?.. maybe save to a file?.. and copying should work with it, like if we do up-up-up and then copy, we should copy whatever we got from the history [ ] pasting text which contains newlines is currently broken, at least for test_app_command stuff... fix it! [ ] Delete unused frozen_string.[ch], bin/frozen_string_test [ ] Add a way to factor hitboxes off individual anims to something global. Hitbox sets?.. like, game->hitbox_sets is a list of filenames, and we load each file at most once, and doing so populates game->hitboxes, which is a dict of hitboxes. And then, in an anim, when you refer to a hitbox by name, it first checks stateset->hitboxes, then game->hitboxes. Although stateset doesn't have a reference to game, so maybe we need a hitbox_set_t, which stores the list of filenames loaded so far, plus the dict of hitboxes; and then we pass a hitbox_set_t when parsing statesets, and in practise we use game->hitbox_set for that (except in e.g. animtool).