diff --git a/old_readme.md b/old_readme.md new file mode 100644 index 0000000..69722b6 --- /dev/null +++ b/old_readme.md @@ -0,0 +1,356 @@ +This file contains text that used to be in the cartridge itself, but +I'm getting increasingly anxious about cartridge space so I'm moving +it out ot a separate file. + +--- + +main loop sequence +================== +1. level_frame +2. events +3. merge new_events into events +4. update bg intangibles +5. move ships (player first) +6. move bullets (player first) +7. calculate collisions + 1. pship on eship + 2. ebullet on pship + 3. pbullet on eship +8. update fg intangibles +9. check for end of level + +draw order +---------- +bottom to top: +1. intangibles_bg +2. player bullets +3. player ships +4. enemy ships +5. enemy bullets +6. intangibles_fg + +notes +----- +intangibles_fg move()s after +all collisions and other moves +are processed. if an intangible +is added to the list as a result +of a collision or move, it will +itself be move()d before it is +drawn. + +data-driven items +================= +guns and bullets both allow the +most common behaviors to be +expressed with data alone. +ships only need a movement +algorithm expressed. + +guns +---- +* t - metatable for bullet type. + fired once in the bullet's + default direction per shot. +* enemy - if true, fired bullets + are flagged as enemy bullets. +* icon - sprite index of an + 8x8 sprite to display in the + hud when the player has this + gun. default is 20, a generic + crosshair bullseye thing. +* cooldown - min frames between + shots. +* ammo, maxammo - permitted + number of shots. 0 is empty + and unfireable. maxammo = 0 + will cause a divide by zero + so don't do that. if nil, + ammo is infinite. + +default guns manage ammo and +cooldown in shoot, then call +actually_shoot to create the +projectile. override only +actually_shoot to change +projectile logic while keeping +cooldown and ammo logic. + +bullets +------- +* dx, dy - movement per frame. + player bullets use -dy + instead. +* enemyspd - multiplier for dx + and dy on enemy bullets. + default is 0.5, making enemy + shots much easier to dodge +* damage - damage per hit; + used by ships +* sprite - sprite index. +* x_off, y_off - renamed for + the next two vars. may revert +* center_off_x - the horizontal + centerpoint of the bullet, + for positioning when firing. + assume a pixel's coordinates + refer to the upper left corner + of the pixel; the center of + a 2-width bullet with an + upper left corner at 0 is 1, + not 0.5. +* top_off_y, bottom_off_y - + also for positioning when + firing. positive distance from + top or bottom edge to image. + top_off_y will usually be 0, + bottom_off_y will not be when + bullets are smaller than + the sprite box. +* width, height - measured in + full sprites (8x8 boxes), not + pixels. used for drawing. + +bullets despawn when above or +below the screen (player or +enemy bullets, respectively). + +by default, bullets despawn +when they hit something. +override hitship to change this. + +ships +____ + +ships move by calculating +momentum, then offsetting their +position by that momentum, then +clamping their position to the +screen (horizontally only for +ships that autoscroll). ships +that autoscroll (slip==true) +then slide down by scrollspeed. +fractional coordinates are ok. +after movement, ships lose +momentum (ship.drag along each +axis). abs(momentum) can't +exceed ship.maxspeed. + +ships gain momentum by acting +like a player pushing buttons. +the player ship actually reads +buttons for this. + +act -- returns new acceleration: +dx, dy, shoot_spec, shoot_main. +dx and dy are change in momentum +in px/frame. this is controls +only -- friction is handled in +ship:move (`drag` value). + +ships hitting another ship take +1 damage per frame of overlap. +ships hitting a bullet check +bullet.damage to find out how +much damage they take. damage +is applied to shields, then hp. +damaged ships flash briefly - +blue (12) if all damage was +shielded, white (7) if hp was +damaged. a ship that then has 0 +or less hp calls self:die() and +tells the main game loop to +remove it. + +shieldcooldown is the interval +between restoring shield points. +shieldpenalty is the delay +before restoring points after +any damage, reset to this value +on every damaging hit (whether +it is absorbed by the shield or +not) -- shield behaves like +halo and other shooters in its +heritage, where it recovers if +you avoid damage for a while. +not that there is any safe cover +in this kind of game. + +ships do not repair hp on their +own. negative-damage bullets +are treated as 0, but a bullet +can choose to repair the ship +it hits in its own hitship +method, or otherwise edit it +(changing weapons, refilling +weapon ammo). powerups are +therefore a kind of bullet. + +levels +====== + +a level is a table mapping +effective frame number to +functions. when a level starts, +it sets lframe ("level frame") +and distance to 0. + +every frame, level_frame +increments lframe by 0x0.0001. +then if the level is not frozen, +it increments distance by 1.0 +and runs the function in the +level table for exactly that +frame number (if any). distance +is therefore "nonfrozen frames", +and is used to trigger level +progress. lframe always +increments. ships are encouraged +to use lframe to control +animation and movement, and may +use distance to react to level +progress separately from overall +time. remember to multiply +lframe-related stuff by 0x0001. + +a special sentinel value, eol, +marks the end of the level. +(the level engine doesn't know +when it's out of events, so +without eol, the level will +simply have no events forever.) +when it finds eol, level_frame +throws away the current level +and tells the main loop that it +might be done. the main loop +agrees the level is over and the +player has won when the level +has reached eol and there are +no more enemy ships, enemy +bullets, or background events +remaining. player ships, player +bullets, and intangibles are +not counted. + +level freezing +-------------- +the level is frozen when the +global value freeze > 0. +generally, something intending +to block level progress (a +miniboss, a minigame, etc.) +increments freeze and prepares +some means of decrementing it +when it no longer wants to block +level progress. + +most commonly, we want to block +until some specific ship or +group of ships has died. for +these ships, override ship:die +to decrement freeze. make sure +to set ship.dead in any new +ship:die method so anything else +looking at it can recognize +the ship as dead. + +for anything else, you probably +want an event to figure out when +to unfreeze. + +levels start at 1 +----------------- + +distance is initialized to 0 +but gets incremented before the +first time the engine looks for +events. therefore, the first +frame of the level executes +level[1]. since levelframe +executes before anything else, +level[1] sets up the first frame +drawn in the level. the player +does not see a blank world +before level[1] runs. +level[1] can therefore be used +to reconfigure the player ship, +set up backgrounds, start music, +kick off some kind of fade-in +animation, etc. + + +events +====== +the global list "events" stores +0-argument functions which are +called every frame. if they +return true, they are removed +from the list and not run again; +if they return false, they stay +and will be called in later +frames. the level does not end +while the events table is +nonempty. + +events are most commonly used +to set up something for later +(for example, blip uses an event +to remove the fx_pallete from +the flashing ship when the blip +expires), but can also be used +to implement a "level within a +level" that does something +complicated until it's done. if +you froze the level when +creating the event, remember +to thaw it (freeze -= 1) on all +paths that return true. + +to do complex stuff in events, +use a closure or a metatable +that specifies __call. + +to avoid editing the events +list while it is being iterated, +events that create new events +must add those events to +new_events rather than events. +new_events is only valid during +the "event execution" stage, so +events created at any other time +must go directly on events +without using new_events. + +intangibles +=========== + +the intangibles_fg and +intangibles_bg lists contain +items with :move and :draw. +like ships and bullets, they +move during _update60 and +draw during _draw. they are +not checked for collisions. + +intangibles_bg moves/draws +before anything else moves or +draws. intangibles_fg +moves/draws last. this controls +whether your intangible object +draws in front of or behind +other stuff. you probably want +intangibles_bg for decorative +elements and intangibles_fg +for explosions, score popups, +etc. + +there's no scrolling background +engine but intangibles_bg could +be used to create one, including +using the map (otherwise unused +in this engine) for the purpose. + +intangibles do not prevent the +level from ending. like bullets +and ships, if :move returns +true, they are dropped.