Log In  
Follow
Felice

derp.

I'm a prematurely-retired professional video game programmer. I have some health problems that ruin my concentration and keep me from doing the kind of programming people will pay you for. PICO-8 is really nice for me, because the limited scope of the platform tends to keep the scope of problems and solutions limited enough for my limited concentration to cope with. I don't think I'll ever manage to produce a game for PICO-8, but it sure is fun just to play with.

(If I've just handed you some ideas or advice, probably for the fifth time this week, and you're getting sick of my doing that, then I have a couple of things I should say: first of all, you should let me know, because I know unwelcome advice is annoying and I don't want to be annoying; but also, second, try not to be too irritated with me, because giving advice is the only way I still feel like I can be a productive member of the video game developer community. I mean well, I swear.)

Oh, and about the avatar... once upon a time, I chose a nice little image of Miku in glasses for my avatar, purely because it struck me as adorable. However, I kept it because I discovered it helped to identify and keep away those useless people who would judge a book by its cover. This is that avatar, but hand-pixeled into low-res, pico-8 palette format.

Sample code for getting dead coroutine's stack trace
by Felice
SHOW MORE

Yo @zep! I think I had a decent brainwave! And I think it's a good bang-for-buck in terms of using existing functionality to get something really useful.

How hard would it be to add a command to the command prompt that simply does what #include does at runtime, i.e. executes some external PICO-8-compatible Lua in the current runtime environment?

For instance, I could load @Mot's cool variable inspector, which is a live, ephemeral dev/debug tool, without having to cut and paste the code in three parts into the command line manually:

> #include inspector.lua
loading inspector.lua
> dinsp(myvar)
[debugging intensifies]

I think #include or even include might be a bit cumbersome for something a dev might want to type often, though. I thought of other alternatives like `import, but I think use might be the shortest verb that still makes sense in the context of an ephemeral-use tool. If we combine that short keyword with functionality that automatically tries to append .lua, that really cuts down the typing necessary at runtime:

> use inspector
loading inspector.lua

I'd also suggest that the command try .p8 and .p8.png as well (not sure about order among the three), but it would only grab the lua section of the cart. This would make working on the dev tool itself a lot easier. It'd just be necessary for a tool author who wants a main loop to create it themself, rather than relying on _update/_draw, which they shouldn't be including since it would overwrite the game's functions.

Another option might be a single-char prefix, similar to ?, to execute something, maybe ! like chatbot commands, and simultaneously switching the filename from a noun to a verb:

> !inspect
loading inspect.p8

That'd really be concise and quick.

So, anyway...

Whatcha think?

😄
🙏🏻

P#142475 2024-03-05 23:25 ( Edited 2024-03-06 05:11)

SHOW MORE

I realized that stat() is basically a peek() analogue for system status registers.

To my knowledge, there is currently no functionality attached to the second arg onwards.

Would it be a good idea to let stat(index, n) return an n-tuple just like peek(addr, n) does?

It'd allow simplifications like this:

_update60()
  -- mouse stats
  _mx,_my,_mb=stat(32,3)

  -- or keep a fifo list of the last second's worth of mouse stats:
  deli(_m,#m)
  ins(_m,1,{stat(32,3)})
  print(_m[16][3]) -- print the buttons 0.25 seconds ago

  -- or take a snapshot of all stat() values at the start of _update()
  -- (probably silly but you can imagine subsets being useful)
  _statshot={stat(1,255)}
end

_init()
  -- fifo used above
  _m={} for i=1,60 do _m[i]=0 end
end

Seems like a simple little QoL thing, I hope?

P#137729 2023-11-21 18:18 ( Edited 2023-11-21 18:26)

SHOW MORE

I notice mapdraw(), the deprecated name for map() got removed from jelpi.p8 at some point, but it's still being used in cast.p8.

Also, I see band() in jelpi.p8 when we want people using the & operator instead.

@zep

Maybe set up a script to grep the demos for the known-deprecated functions and just add new patterns whenever something is deprecated, then run the script before the each publish?

P#136159 2023-10-21 09:53 ( Edited 2023-10-21 21:08)

SHOW MORE

Yo @zep,

By default, split(str) has a go at each split element to see if it's possibly a number, presumably using tonum(elem). You can disable this with split(str, false) or split(str, delim_or_width, false).

Unfortunately, unlike tonum(str, 1), you can't hint the format of the number, like I could by saying tonum("fe", 1) to get 254 aka 0xfe. I tried replacing the split() boolean arg with a number, but it didn't seem to get passed through.

I don't know if you're actually using tonum() inside split(), so maybe I'm assuming too much, but if you are, could you just pass any numeric conversion flag direct to it? That'd let us convert hex directly to numbers with something like split("baadf00d", 4, 1) returning {-17747,-483}.

P#128642 2023-04-17 03:27 ( Edited 2023-04-17 03:28)

SHOW MORE

Hey @zep,

Do I remember right? I think when I asked for state-changing funcs like color() or clip() to return the previous state, I'm pretty sure poke() (and its 2/4 friends) was one of them. Seems like it always returns 0 now.

(Also, if it's meant to return the previous state, remember to return a tuple of old values if you're given a tuple of new values.)

P#127708 2023-03-28 12:49 ( Edited 2023-03-28 12:51)

SHOW MORE

@zep

Okay, so the functionality is there, but you forgot to add it to the list you get if you type config by itself. Currently this is all you get:

> config
config [setting]

available settings:
volume
theme
gif_len
gif_reset_mode
gif_scale
screenshot_scale
splore_filter
tab_width

Might wanna check and make sure there aren't any other additions you've missed adding here.

P#125296 2023-02-04 08:48

SHOW MORE

Hey @zep,

I tried exporting and running an app, didn't do anything special except to load up a working cart and type "export blahblah.bin" and then run the resulting executable from the blahblah.bin/windows/ folder, and the window came up offscreen.

I used some tools and also some estimates to figure out where the app actually came up, and I'm pretty sure it's because I have a rather uncommon desktop arrangement.

Here's an image showing my desktop arrangement from Windows' display settings, with all of the extra info I found/deduced annotated and the position of the exported app when it launches. I hope this helps you figure out where you, e.g. copy/pasted some math and flipped or repeated a coordinate:

(sorry, it's hard to write with a mouse)

Also, just in case it matters, I launched the app from a windows explorer window on the center/primary monitor.

Let me know if I can offer up any more info to help you track this down.

P#123422 2023-01-01 09:28 ( Edited 2023-01-01 09:47)

SHOW MORE

The post formatter is putting the "@user" concept at too high a priority. It screws up Mastodon links, and also adds an extra space for no reason I can tell. Edit: Even on this line, the "@user" placeholder has an extra space in front of it that I didn't type.

Here's a link to one of your posts, just pasted as plaintext, to use as an example of how garbled it can get:

https://mastodon.social/@zep/109507080931110623

Here it is as an inline code blurb https://mastodon.social/@zep/109507080931110623.

Here it is inside a code block:

https://mastodon.social/@zep/109507080931110623

This is what I actually typed, as an image:

P#123327 2022-12-30 20:30 ( Edited 2022-12-30 20:36)

SHOW MORE

Just gonna repeat what I said on mastodon:


@zep
I just had what MIGHT be a good idea. Emphasis on "MIGHT".

Currently PICO-8 does not honor the concept of insert/overwrite mode like DOS used to. Indeed, many programs don't.

How about using the [Ins] key to toggle puny mode?

This post was brought to you by People Like You and Me Who Hate Doing Ctrl-key Sequences™.


Also it'd be nice if you followed this common PC editor convention so I won't need to fake it with AutoHotKey:

shift-del = cut
shift-Ins = paste
ctrl-ins   = copy

So much easier to use on the fly. I learned this and never went back to ctrl-x/c/v.

P#123323 2022-12-30 20:18 ( Edited 2022-12-31 05:06)

SHOW MORE

Hey @zep,

I think it'd be really nice to allow us to swap in the 32-color Picotron palette, which has the 16-color PICO-8 palette plus the revised upper 16 colors that you've been carefully tweaking for Picotron's system palette.

I'm gonna bet that the iteration you're doing with them to improve usefulness would be really nice for PICO-8 games, and would additionally homologize the two platforms with respect to color palettes.

Maybe just a single bit somewhere that swaps out the secret palette for Picotron's 16..31 colors?

Or, I suppose, you could subdivide one of the two ranges. You'd still want an enable bit though, since people rely on index bits 4,5,6 not mattering.

In fact, what the enable bit could do would be to switch to using the same indices 0..31 Picotron uses, instead of 0..15 and 128..143 on PICO-8, and then that's just the Picotron system palette. Basically a Picotron-palette mode.

That'd make using the extra colors a lot less cumbersome than using the current secret palette, though the original secret palette could still live above 128 at the same time too, in which case all the enable bit would do would be to put picotron_pal[16..31] into pico8_pal[16..31] and everything else would remain the same.

I dunno, just throwing out ideas here. What do you think? Does any of this sound reasonable?

P#122137 2022-12-10 02:29 ( Edited 2022-12-10 03:00)

SHOW MORE

Yo @zep,

It'd be nice if draw_tabs were one of the options in the config command.

Indeed, it would probably be a good idea to do a once-over on the whole config.txt and see what else would be good to add to the command.

I say this because someone noted on Discord that there's no way to make tab characters visible on the edu version. Probably among other things that people on the edu version would benefit from.

Personally, I love visible tab characters, so I want everyone to have the option to try them.

Edit: as requested below, for anyone unsure what I'm talking about, here's a sample image with draw_tabs set to 1 (and also tab_width set to 2). Note the wine-colored vertical line at the left edge of the tab characters, which also neatly masquerade as scope guides.


(Also edit: Woo, BBS thread #50000.)

P#119943 2022-11-01 13:33 ( Edited 2022-11-04 16:28)

SHOW MORE

It's not intuitive that these two blobs of code have different token costs, even though they do exactly the same thing:

local a = 1    --  3 tokens: a, =, 1

local b        --  1 token:  b
b = 1          -- +3 tokens  b, =, 1 -> total 4 tokens

I think the disconnect here is that the b in local b is being treated in the cost analysis as a variable reference, which it isn't, because the variable isn't referenced or assigned. It's just forward-declaring a conceptual attribute of the variable (its name), like the zero-cost local keyword does (its scope).

The reason why this bothers me is that I often find myself doing stupid stuff so I can do tuple assignments to save a token, which makes my code ugly. Gross stuff like re-using existing vars or function args, rather than declaring a new local, so I can put them all on the same tuple-assigning line without having to split out a new token-stealing "local" declaration that wouldn't work inline with the tuple assignment.

Here's a really-contrived example you'd never actually write, but hey, I need an example:

function if_period_at_start_move_to_end( s )
  assert(#s >= 2)

  local p                 -- this forward declaration is necessary
  p, s = s[1], sub(s, 2)  -- because we can't mix declare-assign with re-assign here

  if p == "." then
    -- put it where it should be
    s = s..p
  else
    -- phew it wasn't a period, put it back
    s = p..s
  end
  return s
end

Granted I could simply use two new vars when I take the potential period off of the front of the string, thereby allowing myself to merge the local declaration into the tuple assignment, but I guess that just feels like stack clutter to me. I know, nit-picky, but still... it's the little things.

Anyway, unless there's some reason why it would be bad to nix the cost of an empty declaration, would this be an acceptable tweak? I did try to think of some harm or abuse that could come of being able to forward-declare a bazillion locals for free, but the only problem I could see would be in the head of the author who did it.

And, like... at heart, the argument is just that local a = 1 and local a; a = 1 are functionally identical, which I'd hope would be enough in the first place. The rest of the above is just me trying even harder to make a case which I think is already made.

P#119651 2022-10-27 14:20

SHOW MORE

Yo @zep,

I realize returning nil out of bounds is less "friendly"-seeming, but after reading another post in here, I realized it's way more useful.

For one thing, it should make this work:

plain_text = "my thing that is mine"
label = ""
for c in all(plain_text) do
  if c == ' ' then
    label ..= '_'
  else
    label ..= c
  end
end
print( label )  -- "my_thing_that_is_mine"

(Right now it never stops because the iterator keeps seeing "" instead of the nil it needs to terminate.)

And for another, returning a nil is much more likely to alert a programmer that their code is probably malfunctioning than returning an empty string. Accessing out of bounds is usually erroneous and should therefore trigger errors.

I realize some apps are probably already abusing the fact that you get an empty string when referencing past the end of the string, but really that's a bad programming pattern to be teaching people anyway. It's lazy, you should know where the end of the string is and stop there instead of expecting the OS/API to be your nanny and stop you from walking off of a cliff.

Presumably this should apply to negative offsets as well, meaning negative offsets big enough to go back past the start of the string.

P#119528 2022-10-25 00:37 ( Edited 2022-10-25 01:04)

SHOW MORE

@zep

Every now and then I get directed to a BBS post with a cart that I genuinely to see, but which is making my headphones screech into my ears because it's so loud.

Thing is, I already have both my system volume and my app-specific browser volume set to sensible levels for all other content, so I can't reasonably dial down the volume pre-emptively.

Unfortunately, sometimes it's appropriate for a game to do something loud, albeit briefly, so I wouldn't expect you to limit it in the player either.

Really, I think the solution is to have a slider of some sort on the web player. Even if it's limited to 8 different levels, like PICO-8 is internally, that'd help.

Maybe if the user right-clicks (or presses and holds) on the speaker icon, it pops up a slider that can be adjusted?

I dunno if it should be persistent and/or global. For reference, Youtube seems to be both, i.e. the most recent change you made becomes the default for the next video, regardless of how many windows you have open with different settings.

Thanks!

P#111981 2022-05-18 06:30 ( Edited 2022-05-18 06:31)

SHOW MORE

@zep

Hey! Remember when I suggested putting next in the globals, since we could get to it anyway by doing next=pairs{}? You did! And that's been great!

Would it be okay to get inext the same way? It seems to be present, since I can get it by (similarly) doing inext=ipairs{}, and it seems to work the same way, just limited to index,value instead of key,value.

It's just not officially exposed.

I'm asking because there's a token saved when you switch from the first to the second implementation here:

for k,v in pairs(t) do ... end
for i,v in ipairs(t) do ... end

-- these are a little less clear to the reader but they work the same and save a token
for k,v in next,t do ... end
for i,v in inext,t do ... end

Technically it also shaves a couple of cycles off of the loop setup by inlining the return tuple from pairs()/ipairs(), but it's really the token savings that would be handy in some cases.

P#109951 2022-04-09 09:47 ( Edited 2022-04-09 10:57)

SHOW MORE

I don't know if this is expected behavior, but I thought I should ask:

Is it expected that stringifying the table var/ref will give different results when it has a (blank?) metatable attached?

P#109433 2022-03-30 18:59 ( Edited 2022-03-30 20:41)

SHOW MORE

> Changed: Controller inputs are accepted even when PICO-8 is not the foreground application

PLEASE change this back. This is totally counter to how apps are supposed to work in a windowing environment. If an app doesn't have focus, the whole point is that it's not the one receiving input.

This is causing problems for me already because I can't safely pause a PICO-8 game while I play something else that uses a controller.

P#105889 2022-01-29 11:11 ( Edited 2022-01-29 11:15)

SHOW MORE

I saw @zep's tweetcart and wanted to fiddle with it to produce something like the pattern on the bag he showed in the thread. I use Voronoi cells to apply multiple patterns to each image.

Unfortunately, with the limited resolution, our eyes can't pick out patterns unless they are at least half the size of the screen and very regular, so I had to use a limited number of cells with a reduced amount of randomness in each pattern. It sorta works, but it'd be way more effective on a hi-res screen with more cells.

Cart #rajadadaji-0 | 2022-01-01 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA
5

P#104012 2022-01-01 12:28 ( Edited 2022-01-01 12:44)

SHOW MORE

Yo @zep,

On discord and here on the BBS, we get a lot of people who basically need to get to the auto-backup of a cart they've lost somehow. It'd spare a lot of time writing blurbs like this if people could simply type "backups" and have it work like the "folder" command except it drops them in the 'backups' folder instead of 'carts'.

P#95618 2021-08-03 16:39 ( Edited 2021-08-03 16:40)

SHOW MORE

In all but one case I can think of, PICO-8 specifies screen rectangles as X1,Y1-X2,Y2 (inclusive).

The case where it doesn't is clip(x,y,w,h).

This has always bugged me. But worse, I noticed recently that the virtual hardware registers for the clip rect are actually set up like the other API calls: X1,Y1-X2,Y2 (inclusive), which means the API is actually translating between the paradigms.

Now I realize clip() can't suddenly change to work the other way, but...

What if we had a new command next to it called clp(x1,y1,x2,y2) that worked the same as everything else, worked like the virtual hardware, returned the same values you'd get by peeking the virtual hardware registers, etc., and simply marked clip() as deprecated, much like mapdraw() is deprecated?

It would hardly be the only abbreviated API call, e.g. sgn().

What do you think, @zep?

P#95332 2021-07-27 09:18 ( Edited 2021-07-27 09:58)

View Older Posts
Follow Lexaloffle:          
Generated 2024-03-19 03:04:02 | 0.103s | Q:52