Currently doing some prep work for a video. Went through the changelog and I wanted to report two issues.
- I noticed this change in v0.2.4c
Fixed: exported label alpha is 0 for colour 0 |
Seems like this bug persists. This is what the Porklike cart image looks like exported with v0.2.5e

- It is possible to export a cart image that features "secret" colors. However, this doesn't work in reverse. If you re-import that very same file the "secret" colors revert to the default palette. Would love for this function to support the full color range.

left: Shape of Mind cart image exported in v0.2.5e
right: what the p8.png looks like if you re-import that same image
Obviously, not a high-priory issue. But might be worth looking into at the next convenient opportunity.
This is the year you find out if Santa is really real. You and your siblings are staying up late to finally get proof. The light are out, but you're not scared!
Game Play
Requires mouse. Hold down left mouse button to turn on flashlight. Drag mouse across screen to catch Santa in the act. Press ❎ to snap a picture.
Credits
Up on the Housetop composed by Benjamin Hanby
Midilib flute by @ericb https://www.lexaloffle.com/bbs/?tid=49487
Flashlight effect informed by @Krystman https://www.lexaloffle.com/bbs/?tid=46286
Fizzle fader borrowed from @DrPete https://www.lexaloffle.com/bbs/?tid=29862
Everything else by @bikibird
Created for the



My second ChatGPT game.
I will note any changes I made to its code but otherwise, all code and comments were created by ChatGPT with prompts in order listed.
Prompts:
- Pico-8 basic game code
- Add player using pset, with movement control
- Add enemy at random spot at the edge of the screen, enemy should attack player within 30 pixels
- Player shoots at enemy using pset
- Enemy moves toward middle of screen
- What should I add to my game?
- It told me to add player and enemy health text display and something to happen when player or enemy dies
- Add health display
- How can I improve this code?
- It said:
- Add more enemy types, each with their own behavior and appearance. For example, you could add a faster enemy that moves towards the player even if they are not close, or a stronger enemy that takes more hits to defeat.
- It said:


Some usernames have spaces in them and thus are impossible to @ (Alex K. for example). I thought while creating an account it didn't even let you add spaces anyways so I don't know how they got those usernames. Not sure exactly how it could be fixed but it's annoying trying to reply to somebody who is literally impossible to reply to.



Hello.
As I'm experimenting with 8-bit compression, I came across an anomaly that I feel deserves some attention.
Try this code:
cls() a=chr(6) b="⁶" ?ord(a) ?ord(b) |
I created the ⁶ by typing in immediate mode, printh(chr(6),"@clip")
and then in the source-code pressing CTRL+V.
My question is how can BOTH of these be the same character and - is this an error of some kind ?
Because if you type out in immediate mode, print(chr(6))
you won't get that symbol back. You can only get that symbol if you use printh()
Because if for some reason this is correct, it means that you are NOT saving a single byte per character in your source-code, that you are in fact using an extended unknown set to create that special character of 6, yes ?
The bug is this. You cannot get a visual for printing a character < ASCII of 16, however you CAN if you transfer it solely to the clipboard and then use CTRL+V. There is still no way to print it. It should appear either way you access it for output or at least give you an option of doing so with an obscure poke() or direct extcmd().




I've been building a game via the API, and in my quest to figure out what savegame systems I can use (if any) I wrote a little script to dump the contents of _ENV. This seems to list the API, both documented and otherwise, so I thought folks might find it useful.
So far the only undocumented feature I've found and successfully used is clip3d, which you can use to set a clipping volume for subsequent voxel rendering operations. It doesn't seem to get reset every time you run a game, so be sure to clean up after yourself :)
Parameters seem to be x0, y0, z0, x1, y1, z1
Anyway, here's the rest of the dump:
[hidden]
flip: [function]
trace: [function]
__type: [function]
_activate_objects_yieldable: [function]
_activate_objects: [function]
_add_method: [function]
_add_val_names_from_table: [function]
_blit: [function]
_class_16: table: 0x1cc93810
_class_func_16: [function]
_clear_all_lua_data: [function]
_draw_legacy_hud: [function]
_draw_map: [function]
_draw_messages: [function]
_draw_objects_yieldable: [function]
_draw_objects: [function]
_draw: [function]
_end_of_program: 1
_extract_upvalues: [function]
_fetch_function_by_name: [function]
_fetch_table_by_name: [function]
_functions_at_boot: [table]
_G: [table]
_get_frames_skipped: [function]
_get_menu_item_selected: [function]
_get_newable_elf_class: [function]
_get_num_elves: [function]
_get_world_actors: [function]
_head_id: -2
_init_room_state_instances: [function]
_last_room_at_draw: table: 0x1cc93798
_mainloop: [function]
_mark_actor_newed: [function]
_mark_cpu: [function]
_menuitem: [function]
_move_all_elves_yieldable: [function]
_move_room_flow: [function]
_move_world_post: [function]
_move_world: [function]
_mt_actor: [table]
_mt_resource: [table]
_name_val: [table]
_non_saveable: [table]
_num_functions: 295
_obj_4: table: 0x1cc93798
_p8_program: [function]
_pausemenu: [table]
_read_global_variables: [function]
_read_world_objects: [function]
_record_callback_bits: [function]
_record_functions_at_boot: [function]
_record_table_functions: [function]
_remove_dead_objects: [function]
_restore_upvalues: [function]
_set_fps: [function]
_set_mainloop_exists: [function]
_spawn_worker: [function]
_startframe: [function]
_uc: 2
_update_buttons: [function]
_update_multi: [function]
_update_objects: [function]
_update_voxatron_buttons: [function]
_update120: [function]
_update60: [function]
_val_name: [table]
_validate_head_class: [function]
_VERSION: Lua 5.2
_vvmp_id: 16
_write_global_variables: [function]
_write_world_objects: [function]
?: -1632.5
?: -18402.5
?: -19008.5
?: -20032.5
?: -20128.5
?: -20192.5
?: -24351.5
?: -2560.5
?: -25792.5
?: -26208.5
?: -2624.5
?: 0
?: 0.5
?: 1
?: 2
?: 20767.5
?: 20927.5
?: 21845.5
?: 23130.5
?: 3
?: 31455.5
?: 32125.5
?: 3855.5
?: 4
?: 5
?: 6943.5
abs: [function]
add: [function]
all: [function]
ANIMATION: 8
assert: [function]
atan2: [function]
ATOMIZE_ON_DEATH: 0.0043
ATTACK_BOTTOM: 0.0041
ATTACK_DAMAGE: 15
ATTACK_SIDES: 0.004
ATTACK_TOP: 0.004
band: [function]
BASE_P0: 8
BASE_P1: 9
BASE_TYPE: 7
bbsreq: [function]
blit_voxmap: [function]
bnot: [function]
bor: [function]
BOUNCE: 21
box: [function]
boxfill: [function]
btn: [function]
btnp: [function]
BULLET: 9
button_pressed: [function]
button: [function]
bxor: [function]
camera: [function]
cartdata: [function]
cd: [function]
ceil: [function]
chr: [function]
circ: [function]
circfill: [function]
clip: [function]
clip3d: [function]
cls: [function]
clv: [function]
cocreate: [function]
COLLECT_BOTTOM: 0.0041
COLLECT_SIDES: 0.004
COLLECT_TOP: 0.004
collectgarbage: [function]
COLLIDE_BULLETS: 0.0041
COLLIDE_GROUND: 0.0041
COLLIDE_PARENT: 0.0043
COLLIDE_SIBLINGS: 0.0043
color: [function]
coresume: [function]
cos: [function]
costatus: [function]
COUNT_AS_MONSTER: 0.0042
count: [function]
cstore: [function]
cursor: [function]
del: [function]
deli: [function]
DENSITY: 5
dget: [function]
dofile: [function]
DOOR: 4
draw_voxmap: [function]
dset: [function]
EMITTER: 10
error: [function]
exit: [function]
EXPEL_ACTORS: 20.0042
EXPLODE_ON_DEATH: 0.0042
export: [function]
extcmd: [function]
FACING_TURN_SPEED: 17
fget: [function]
fillp: [function]
flip: [function]
flr: [function]
folder: [function]
foreach: [function]
FRICTION: 11
fset: [function]
get_actors: [function]
get_display_camera: [function]
get_id: [function]
get_key_type_index: [function]
get_room: [function]
get_type_index: [function]
get_value_string: [function]
get_world_camera: [function]
getmetatable: [function]
GRAVITY: 14
HEADING_TURN_SPEED: 18
HEIGHT: 4
help: [function]
HOISTABLE: 0.004
holdframe: [function]
import: [function]
info: [function]
init_id_table: [function]
init_val_name_table: [function]
io_read_boolean: [function]
io_read_int32: [function]
io_read_string: [function]
io_read_uint8: [function]
io_write_boolean: [function]
io_write_int32: [function]
io_write_string: [function]
io_write_uint8: [function]
ipairs: [function]
is_array_key: [function]
is_valid: [function]
JUMP_FREQ: 10
JUMP_HEIGHT: 9
LENGTH: 3
line: [function]
line3d: [function]
LIQUID_Z: 9
load_checkpoint: [function]
load: [function]
loadfile: [function]
LOCK_FACING: 0.004
LOCK_X: 0.004
LOCK_Y: 0.004
LOCK_Z: 0.004
login: [function]
logout: [function]
ls: [function]
lshr: [function]
mag: [function]
map: [function]
mapdraw: [function]
max: [function]
memcpy: [function]
memset: [function]
menuitem: [function]
mget: [function]
mid: [function]
min: [function]
mkdir: [function]
MONSTER: 7
MORTALITY: 7
MOVE_STYLE_P: 19
MOVE_STYLE: 12
mset: [function]
music: [function]
MUSIC: 11
next: [function]
ord: [function]
oval: [function]
ovalfill: [function]
pack: [function]
pairs: [function]
pal: [function]
palt: [function]
pcall: [function]
peek: [function]
peek2: [function]
peek4: [function]
pget: [function]
PICKUP: 5
play_music: [function]
play_sound: [function]
PLAYER: 6
POINTS: 6
poke: [function]
poke2: [function]
poke4: [function]
print_table: [function]
print: [function]
printable: [function]
printh: [function]
printio: [function]
PROP: 0
pset: [function]
PUSHABLE: 0.0039
radio: [function]
rawequal: [function]
rawget: [function]
rawlen: [function]
rawset: [function]
read_key: [function]
read_table: [function]
read_value: [function]
record_non_saveables: [function]
rect: [function]
rectfill: [function]
reload: [function]
reset: [function]
rnd: [function]
ROOM: 1
rotl: [function]
rotr: [function]
run: [function]
save_checkpoint: [function]
save: [function]
scoresub: [function]
select: [function]
serial: [function]
set_display_camera: [function]
set_draw_slice: [function]
set_draw_target: [function]
set_map_draw_mode: [function]
set_pico8_cart: [function]
set_room: [function]
set_world_camera: [function]
setmetatable: [function]
sfx: [function]
sget: [function]
sgn: [function]
shl: [function]
shr: [function]
shutdown: [function]
sin: [function]
SOUND: 12
spawn: [function]
SPEED: 8
sphere: [function]
split: [function]
spr: [function]
SPREAD_OUT: 0.0042
sqrt: [function]
srand: [function]
sset: [function]
sspr: [function]
STANDABLE: 0.0039
stat: [function]
stop_music: [function]
stop_sound: [function]
stop: [function]
sub: [function]
t: [function]
TEAM: 13
test_obj_1: [function]
THROWABLE: 0.0039
ti: 4
time: [function]
tline: [function]
tonum: [function]
tonumber: [function]
tostr: [function]
tostring: [function]
total: 0
trace: [function]
TURN_SPEED: 18
TURN_STYLE: 16
type: [function]
unpack: [function]
vget: [function]
vset: [function]
WIDTH: 2
write_key: [function]
write_literal: [function]
write_table: [function]
write_value: [function]
xpcall: [function]
yield: [function]



Previously, gonengazit found some infinite token exploits here and zep fixed them, but looks like they're not all gone yet - I stumbled upon one that still happens:
x=[[[[]] put your infinite tokens here... --]] |
Seems like it happens because pico8 supports recursive block comments, and uses the same code to also parse long strings recursively.
But lua then parses the long string non-recursively and executes the code that pico8 thought was part of the string.
Pico8 probably should only parse block comments recursively, not long strings.

Hello.
I did a fresh install of PICO-8 0.2.5E. I then ran `INSTALL_GAMES".
"Frog Home" has a syntax error and can't start.
See on the cart page: https://www.lexaloffle.com/bbs/?tid=2796
Looks like local dy+=...
should be replaced with dy+=...
. Did something change with how PICO-8 processes locals?


Port of PICO-8 Celeste to Retro Gadgets
Retro Gadgets is a video game about building all sorts of retro-styled devices with all the clicky buttons and other goodies, and I noticed two things:
- The screens have a square aspect ratio
- The CPUs are programmed with Lua
Commence bad idea.
After a week or so of borderline masochism, I managed to port PICO-8 Celeste to Retro Gadgets using the original Lua code, spritesheets, music and sound data, along with writing some quick scripts to do syntax conversion from PICO-8 Lua to standard Lua, and to get the map and flag data out.
The entire game is beatable from start to finish, and functions identically to the PICO-8 version apart from minor visual quirks.
Retro Gadgets: https://store.steampowered.com/app/1730260/Retro_Gadgets/
My Celeste gadget for Retro Gadgets: https://steamcommunity.com/sharedfiles/filedetails/?id=2899096562
Technical details:
- Partial reimplementation of the PICO-8 API (only the bare minimum Celeste requires)






Out of curiosity, I was testing to confirm that the new limit on length of audio recordings via extcmd("audio_rec") was per-instance and not per-session ... and discovered that the length of recording I got was 2 minutes instead of the 8 minutes listed in the v0.2.5d changelog.
An 8-minute limit makes sense to me but a 2-minute one doesn't, so I'm assuming this is an error of some sort.
edit: confirmed fixed in v0.2.5g.


Revising my previous post and reopening as this now does seem like some kind of bug introduced in 0.2.5d/e.
On PICO-8 0.2.5e Raspberry Pi build running on EmuELEC 4.6 on the Gameforce Chi, select any local PICO-8 game from the game collection. You hear the PICO-8 startup sound and can even control the games (verified by pressing X to start a game and hearing the game music/sounds), but the screen on the Gameforce just shows "Loading..." even though everything is clearly loaded.
Originally I had marked this as not a PICO-8 bug, but it does now seem to be a bug introduced in the latest version. I first rolled back to 0.2.4c, which was the version I had been running previously, and it worked fine. Then I updated to 0.2.5c, and that also didn't exhibit this behavior. Updating once again to 0.2.5e reintroduces this behavior - games load, startup sounds play, game controls work, pause menu works, but PICO-8 is not drawn to the screen.
I'm not sure whether this is specific to EmuELEC with the Raspberry Pi build or if it's also an issue running on a Raspberry Pi (my Pi is currently in storage so I can't test it). Happy to try & dig anything out of the EmuELEC log files that might be helpful for debugging!











Puzstel Storm
A match-3 puzzle game featuring Pastel Storm and friends.
How to Play
Use the arrow keys to move the cursor and press Z to swap tiles.

Arrange the tiles to create matching groups of 3 or more.

After every 5th swap, the matching groups will break, awarding you 5 points per tile.

The remaining tiles will fall and new ones will enter from the top.
Chaining
If the falling tiles create a new matching group, a chain starts. A 2-chain is worth double points, and a 3-chain is triple points etc...




~Mittens~
A City Park Snowglobe by ohhcurtains
A link to play the game on itch.io
Feed the birds, sit on benches, and search for your grandson's lost mittens.
Relax and explore a pretty pixel-art park underneath a flock of cardinals which display flocking behaviors.
Created for the Advent Calendar Jam 2022.
~Controls~
⬆️⬇️⬅️➡️: Walk
🅾️: Throw Bread
❎: Confirm/Interact
~Thanks~
bikibird
TheTomster
tinyevilwizard







We're back with another 12 days of PICO-8 surprises. Every day a different game, animation, or coal-related nonsense will be revealed!
Happy Holidays!
Dec 14th: Mittens by ohhcurtains - https://www.lexaloffle.com/bbs/?tid=50645
Dec 15th: Santa Scouts by bikibird - https://www.lexaloffle.com/bbs/?tid=50669
Dec 16th: Freezing Knights by tinyevilwizard - https://www.lexaloffle.com/bbs/?tid=50683
Dec 17th: Avery's Angling Adventure by TheTomster - https://www.lexaloffle.com/bbs/?tid=50691
Dec 18th: Puffy Coats by bikibird - https://www.lexaloffle.com/bbs/?tid=50699
Dec 19th: Santa's Elf Workout by tinyevilwizard - https://www.lexaloffle.com/bbs/?tid=50717





Sharing this post I wrote up a few days ago for cleaning up my code and reducing token costs:
https://blog.giovanh.com/blog/2022/12/11/jinja2-as-a-pico-8-preprocessor/
In summary:
- Constants would be a very useful language feature to have
- Pico-8 doesn't have it and doesn't let you extend its preprocessor
- You can roll your own and it works great



Controls
- Arrow keys: move the cursor
- X: swap blocks
- C: manually raise blocks
Overview
QuantAttack is a match-2 type action puzzle game. Blocks are cleared by lining up two blocks of the same type vertically.

While the basic rules are this simple, QuantAttack introduces a fresh twist on block-clearing puzzlers. Some blocks are unique, and players must discover hidden patterns to clear them.

There are more than 40 patterns of such block combinations, and finding and mastering them is the fastest way to improve.



I found a minor (except that to me it's kinda major) bug concerning puny font.
It seems to only affect PICO-8 when loading or reloading - whenever I save in an external source and reload, or when I boot up the console, all the puny font disappears.

EDIT: Never mind, turns out it was that _ENV thing. Thanks zep lexaloffle!