I was tinkering with the custom key repeat settings in 0x5f5c and 0x5f5d and I realized that they always seem to be expressed in 30ths of a second. Shouldn't this depend on whether or not the game has _update60(), or for games with custom loops, whether or not they've called _set_fps(60)?
I guess it's not a critical problem if it stays this way, it just seems like it ought to track the fps setting.
Hey @zep, me again. ;)
I looked through the rather comprehensive list at https://rosettacode.org/wiki/Bitwise_operations and couldn't spot anyone at all who had an operator for rotation, let alone find some kind of standard for it. Most languages use either a function or a textual operator (e.g. a ror b), but those end up making your expressions a lot larger and/or filled with whitespace.
WE COULD BE THE ONES TO SET THE STANDARD! :D
I'll just propose a few ideas. Note that I bring the "|" operator into some of them because normally people have to do rotates by or'ing together two shifted values.
rotl rotr ---------- ---------- a <<<< b a >>>> b a <<> b a <>> b -- I like these best, personally a >|> b a <|< b a |>> b a <<| b a >>| b a |<< b
I like <<> and <>> because they imply that part of the shift wraps back around. I also find them aesthetically pleasing.
Also, if this happens, please remember assignment operators and metamethods? :)
I was going through my old posts, gleefully marking bug after bug "resolved" (THANKS ZEP!:D), and ran across one I hadn't actually posted in the support section.
I know the chat section sees a lot of traffic and moves quickly, so I'm worried it was never seen, and I want to try posting it again in the right section, in hopes of seeing it added to 0.2.0 or a later version:
I'm trying to write a tool that has text editing, and I find that the devkit keyboard doesn't return a lot of the special keys that it easily could.
You're returning a string, so there's no reason why it has to be just one character. So pressing the Home key could simply return the string "home". No need for special characters, escape sequences, etc., since these verbose names would all be distinct from any single regular typed character.
I'm mainly thinking of the standard navigation cluster: up, down, left, right, ins, del, home, end, pgup, pgdn, but I'm sure there are others.
It'd also be nice if there were a second stat() value that had a bitmask of the modifier keys that are currently pressed, if the host has them. Like, left/right shift, left/right alt/cmd, maybe left/right win/opt, altgr, maybe capslock. Not crucial, but definitely helpful. It'd be nice to be able to support things like ^Z for undo in my tool.
I say all this because one of the things I love about PICO-8 is working entirely within PICO-8, so it's nice to write tools that work inside of the platform, but the devkit functionality is a little limited in this department.
There's currently no way to get the existing random seed, since srand() doesn't return anything.
Could it return the existing seed so we can temporarily change to a sub-system's ongoing seed, then restore it? Like this, for instance:
function handle_ai(ai) local old_seed=srand(ai.seed) ⋮ (stuff) ⋮ srand(old_seed) end
It's minor, since you can always keep your seeds in shadow values from the outset and manually set them each time, but it'd still be handy.
Presently, to load+run you literally have to load blahblah.p8 and then run.
Would it be a bother to run the "run" code through the same line parsing that handles "load", and then auto-run it afterward?
I ask because I was running a bunch of local carts from the command line and it was a tiny bother to have to do two steps each time.
...YES, I realize this is a very minor thing, but hey, why not mention it? The worst that happens is that it doesn't get implemented, right? XD
... uh... r—right...?
If we type "x = -6", the "-6" part requires two tokens, which I assume is because the version of Lua you use was still internally treating negative literals as positive literals with a unary-minus operation applied to them, e.g. "x = unm(6)".
However, using a negative literal in PICO-8 appears to have the same cycle cost as using a positive literal, as far as I can tell with my benchmarks. For instance, "x = y / -6" costs the same as "x = y / 6".
So basically we're being charged a token for an operation that doesn't actually seem to occur, and really shouldn't need to occur anyway.
Would it be possible to delete the token cost for unary-minus if it's being applied to a literal?
The alternative is that people in dire token straits will write "x = y / 0xfffa", which is just gross. :P
I think it's too late to suggest this, since you appear to have completely filled the printable characters with the kana glyphs, but just in case there's something to spare somewhere:
I just used one of the unicode thumb glyphs (👎,👍) and realized it'd be handy to have such glyphs in the PICO-8 character set.
I drew up some possible 7x5 PICO-8 glyphs for them:
You could type them with -/+ in glyph mode.
Even if they can't be fit into PICO-8 itself, the thumb-up might be good for the BBS, because I think a lot of people don't realize that's what the ★ glyph on BBS posts is for, given how seldom it seems to be used.
(I guess it's not a big deal if this isn't possible, though, since we can obviously just draw them manually.)
The built-in tuple "..." seems to confuse the syntax highlighter. Notice "END" isn't pink:
Not a big deal, but I figured you'd want to know.
Maybe a bug, maybe not. I just noticed that Ctrl+H goes to the start of the document (as with Ctrl+Home). On the other hand Ctrl+E goes to the end of the current line (as with plain End). Is this difference in behavior intentional? If so, no big deal. I just wanted to be sure it was intended vs. accidentally calling the wrong internal "home" or "end" function for one of them.
EDIT: Just as I posted this, I noticed that it's ^W/^E for line home/end, so I guess this probably isn't a bug. Disregard #2.
- fire up PICO-8
- switch to code editor
- type something like 123456789 and hit enter
- copy and paste that line few times to give yourself something to cursor through
- using the keyboard, navigate to the middle of one of these lines
- cursor up and down: should work normally
- click near the start or end of the line
- cursor up or down: will change the row properly but maintain the column from before the click
This is probably as easy to fix as just setting both the current and virtual column on mouse clicks.
Right now if you want to draw a line loop with the cool line(x,y) continuation method, you still have to do at least one line(x0,y0,x1,y1) first to make it work:
-- draw a simple triangle line(32,96,96,96) -- base line(64,32) -- right side line(32,96) -- left side
This isn't so bad if you're drawing the figure manually as I just did. But if you're, say, drawing an algorithmic figure's loop, you have to handle that first line conditionally within the loop:
-- draw a simple segmented circle local cx,cy,r=64,64,32 for a=0,1,0x.01 do local x,y=cx+cos(a)*r,cy+sin(a)*r if a==0 then line(x,y,x,y) -- sets the continuation point else line(x,y) -- continued from the last point end end
Or (not shown) you can remove the condition from the loop, but it requires doing math to get the first point outside of the loop and then calling line(x,y,x,y) as above before looping over the subsequent points.
All in all, neither is really better in terms of code than just drawing a series of distinct line(xi,yi,xj,yj) segments.
However, let's say line() with no args invalidates the last position. Let's also say that trying to continue via line(x,y) from an invalid position draws either nothing or just the one pixel, but it does update the last position. Suddenly everything gets a heck of a lot more concise and elegant:
-- draw a simple segmented circle local cx,cy,r=64,64,32 line() for a=0,1,0x.01 do line(cx+cos(a)*r,cy+sin(a)*r) end
This should be safe in terms of backcompat, because line() with no args doesn't currently do anything useful, and in fact I'd consider it an undocumented usage that would have been ill-advised to use anyway. Similarly, since there was no such thing as an invalid last point in the past, no one would have written line-continuation code that didn't first update it explicitly in a way that would still work with this change in place.
This call, with only one arg after the string:
print("hello world", anything_even_a_table_or_function_or_nil)
Behaves oddly and in a way that is not documented in the manual. It renders the string at the cursor and then exits without updating the cursor. It doesn't seem to use the extra argument at all.
The only thing I can see this being useful for is a text countup display, as seen in oldschool memory tests during BIOS startup on PCs. I can't imagine anyone has ever actually used it this way, though.
It'd be far better if this case were treated as if the user wanted the text colored, but didn't want to specify x,y coordinates because they wanted it to work like a regular, scrolling print():
print("I'm blue, da ba dee, da ba die", 12)
We had some back-and-forth on Discord about row-shifting effects and whether to do them with the CPU or by copying to sprite ram and using sspr. I came up with a pretty good function at the time for the CPU to do it in place, but I've since iterated on that to bring down the token count and also to optimize certain types of shifts.
This is a little demo wrapper built around that function. If anyone's interested in effects like this, I offer this up to them. Take a look at the full-fat version of the function in tab 1, and also at a low-fat version in tab 2, which is a little slower and lacks the edge-clamping feature, but uses about 2/3 of the tokens. You should be able to drop either version as-is into a game or demo and just use it right out of the box.
Performance: The full-fat version can apply a sine wave to the full screen at a cost of about 8-9% of a 30fps frame, while the low-fat version requires about 10-11%.
Token cost: The full-fat version is 155 tokens. The low-fat version is 96 tokens.
Limitations: To reduce token count and because this was written for someone to do a subtle water effect, I have no logic for shifting beyond +/-8 pixels (32 bits). It could be modified pretty easily to do so, it just doesn't right now. It would probably add maybe 1-2 dozen tokens to do so.
Is holdframe() intended to be a peer/complementary function to flip()?
I had it pointed out that I'd erroneously marked flip() as undocumented on the wiki, even though it is documented—I just suck at searching the manual. That reminded me to check holdframe(), to see if it was still undocumented, and it still is. It is, however, overtly called out in the changelog as having been added, so it's simultaneously documented and undocumented.
Is it intended that we're allowed to use it for custom game loops, or no? If we are, it'd be nice to have it documented in the manual. Otherwise I'll leave it in the nebulous wiki category of Undocumented API.
I discovered this while trying to reduce someone's not-quite-tweetcart, and I boiled it down to a simple repro case.
These compact lines both parse and function correctly:
But these don't:
Variable names don't seem to matter. I included versions with variable names swapped just so you know it's not the variable order at fault somehow.
Same thing happens both when executing editor/app code and at the shell prompt.
I tried on the BBS and the parser here isn't able to work it either.
I didn't try other operators, like *, /, or %.
Side note: On the same subject, would you mind adding ..= and ^= operators? I think that would make the set orthogonally-complete.
I was playing around with the slide effect on the volume for white noise and I realized that there was an awful lot of sputtering while it would ramp up the volume, but not while ramping down. It sounded as if maybe the waveform was being doubled in amplitude and thus clipping, or maybe something was messing up the randomizer. I really don't know. That's for @zep to figure out.
Here's a repro case, seems to work the same on the BBS as it did in the executable.
Pretty sure it's not local to my machine's audio hardware, but I'd appreciate others trying it and saying whether or not they hear the same issue.
Edit: Yeah, just checked out this post on my phone, it does the same thing there too. Definitely a bug.
Edit: Never mind, I think the sound driver on my system has some kind of volume compression enabled.
There seems to be something amiss with the SFX player code.
The cart below simply plays a single SFX. The SFX is a constant sine wave tone with a stepped volume envelope. The envelope steps up each half second, from 0 to 7, and then back down each half second, to 0.
On my PC, this results in the SFX immediately being nearly full volume, stepping up once, maybe twice, until it's actually full volume, and then remaining full volume almost until the end, when it then steps back down four times to medium volume and then abruptly turns off.
On the web player, it seems to be more symmetrical. I'm hearing it start at medium volume and step up four, maybe five times before holding steady for a while and then stepping back down four times to medium volume and abruptly turning off.
There was a discussion on twitter about not being able to get the stack trace for a dead coroutine, which is understandably frustrating. However, I was sure that I once figured out a way to do it, and I said so, but the code to do so is on a dead PC at the moment, so I had to spend some time figuring it out again.
This sample basically runs a coroutine that waits for 5 seconds and then does something fatal. Each frame it displays the known status and stack trace. Run it, you'll see.
I tried to set up the code to be as simple and understandable as possible, but if you have questions, please feel free to ask.
EDIT! For a VERY simple coroutine exception stack trace dump, see my follow-up post here
As simple as the subject.
- Write a cart that uses btnp().
- Run the cart.
- Press and hold a button to see it repeats.
- Hit esc to stop the cart.
- Enter 'resume' to resume the cart.
- Press and hold a button and see if it fails.
(Either that or key repeat isn't supposed to be a thing with btnp() and it only works right after you resume.)
This code is sufficient to show it:
boops=0 function _update() if btnp()!=0 then boops+=1 print("boop #"..boops) end end
Note: tested on win64 version.
The manual implies that the line-continuation syntax might allow for this...
line( 10,10, 20,10, 1 ) line( 20,20, 2 ) line( 10,20, 3 ) line( 10,10, 4 )
...which would make a rectangle with four differently-colored sides.
But PICO-8 seems to interpret line(x2,y2,col) as line(x1,y1,x2,0).
View Older Posts