As a temporary side project, I hastily ported Randy Gaul ImpulseEngine to pico-8/LUA.
Requires a mouse
- left mouse button: create a random shape at mouse cursor or drag shapes
- right mouse button: show/hide world or body options
- button c: show/hide debug information
The physic engine is a direct port from Randy Gaul's work, detailled in a series of articles:
How to Create a Custom 2D Physics Engine
My contribution is mostly on a clean 2d vector and 2x2 matrix object oriented library.
It makes vector/matrix math very concise to work (and easy to port from C++ code!):
local v1,v2=vec(3,4),vec(5,6) local v3=v1+v2 -- rotation matrix local m=mat:make_r(0.4) local r=m*v3
Note: I don't plan to expand the library beyond this demo, feel free to make a game out of it!
The cart now include a context menu that could be fairly easily reused for other carts.
- Optimisation pass (currently supports ~4/5 objects max)
- initial revision
- added: support for circles
- fixed: force reset
- changed: left click now creates a new body
- added: right click menu to control world or object settings
Hastily crafted Asteroids clone complementary of the anti-aliased line thead:
- Added: Teleport ('c' button)! Up to 3 chances (sort of...) to get out of trouble
- Changed: inertia cranked up, use your thrusters!
- Changed: safe time is now 2s
- Changed: thrust is now 'up' only
- Fixed: Saucer Invasion!
- Fixed: incorrect font rendering
- Fixed: incorrect high score message on game over
- Changed: reduced number of rocks to 4
- Fixed: crash with dead player
- Changed: multiple rocks types
- Added: saucer!
- Added: highscore (saved in cart data)
- Added: multiple CRT effects (enjoy @Felice!)
- Bug: couple of chars incorrectly rendered
1.0f: temp. fix by @Felice (tks!)
1.0: initial release (did not work)
Not much really - using bits of my Pico 8 "game toolkit":
- anti-aliased circle fill (using mid-point error for the shading)
- multiple "CRT" shaders (find out how to switch between them!)
- a couple of future functions using yield
- vector font rendering
- Felice: anti-aliased line optimisation genius!
- Trammell Hudson: Asteroids font (https://trmm.net/Asteroids_font)
- Atari: for the art cover (my lawers are on the copyright case :)
This cart is just to provoke @zep (or any other true Pico-8 genius) into releasing a fast anti-aliasing demo cart!
The code is a LUA port of that paper:
Note: I don't get how an incremental line drawing routine (a la Bresenham) can be that slow (compared to the native version). 270% cpu usage for 16 lines sigh...
Suzie and Bob are trapped in a merciless world. Can you fight your way out?
- Random maps
- Multiple enemies
- Multiple weapons (but one at a time!)
- Loop-based difficulty
- Supports keyboard/mouse
- arrow keys: move & gun direction
- bttn 1: fire & lock direction
- bttn 2: pick up weapon
Mouse (selected in option menu):
- arrow keys: move
- mouse: gun direction
- left click: fire
- right click: pick up weapon
Note: any resemblance with a famous Vlambeer game must be purely accidental...
- fixed: woobly sprites
- fixed: actors stuck on corners
- fixed: warp in/out effect
- changed: impact feedback
- changed: health upgrade on loop
- fixed: unexpected god mode
- fixed: boss hp
- fixed: boss attack
- changed: tweaked game speed
- change:balanced high level gameplay (loop)
- preview version
2nd finished game (last was Thunderblade). Took 4 months to complete & refine.
Un-minified source available on Github:
All entities (actors, weapons, particles, levels) defined using json (worth 3500 tokens!). A lightweight parser (450 tokens) converts strings into lua tables.
Entities are created using a parent template with support for:
- lua references
- random values
- method & attributes override
Player weapon (and couple of other sprites) are rotated in real-time using an optimized sprite routine. It is fast enough to allow ~10+ sprites on screen (before tanking FPS!)
An actor map is maintained each frame. It allows immediate bullet/actors lookup.
Only player/npc collisions are checked to ensure player cannot zip through enemies.
A-* path is refreshed for a single npc per frame. It ensures a large number of npcs can be created without too much cpu stress.
Sprites are added to buckets matching their y pixel coordinate.
Saves both cpu and tokens as no global sort is required :]
Cart is minified using picotool (19k compressed). All json attributes are replaced by their short equivalent using output from minification script:
cat nuke.p8 | minify | replace > nuke_mini.p8
Missing In Action:
- RPG aspects (upgrades/xp/abilities...)
- Good music (for total lack of musical skills!!)
- Tyler Neylon: lua JSON parser
- James Coonradt (@gamax92): midi2pico
- Jakub Wasilewski (@krajzeg): Lighting by hand: the thin dark line serie
- Dan Sanderson: picotool minify
- collide sample by @zep
Back 30 years ago, After Burner and Thunderblade ruled the arcades.
As a kid, I only had an Amiga and near zero coding skills to produce very (very) weak clones.
Now a seasoned programmer with the mighty power of PICO-8, I can beat a Sega X board!
Chris Butler (player + tank sprites lifted from the C64 1989 version)
gamax92 for midi to pico-8 program
dw817 (david w) for image decompression code (http://writerscafe.org/dw817)
gazillions of buildings on screen!
Drawn using sprite sheet (2), you can tweak the level using colors:
8: enemy helicopter
9: Battleship boss
10: swtich to chase mode
11: switch to top-down mode
15: end_game (use carrefully!)
Title image is loaded from a stringified image, decompression done 'asynchronously' with yield.
Buildings are mostly drawn with many rectfill using a big checkerboard pattern to simulate windows/floors.
Everything is z-sorted (w actually ;) before being drawn. This 'zbuffer' is in charge of drawing every asset.
Game screen manager:
A light version of what I've extensively used during my XNA period. Allows nice decoupling between game loop and other loops (title, game over).
Used only for rare events (like player dying) to easily control animation and state changes.
PICO-8 is a fantastic platform. Forces you to keep things simple (say that to my dozen or so failed Unity attempts...)
token count is everything
Coroutines are unfortunately too slow to be used in the core game loop
Throw OOP techniques out. The nice class:method() construct eats up too many tokens - had to rewrite half of the code to stays within the limits :[
bnot-cheating the platform is way too easy (but resisted against!)
Did I say token count is everything?