Log In  

Just another mad coder.

We're all mad. I'm mad. You're mad, you must be - or you wouldn't have come here.

Find my books and biographical works HERE:


With the understanding that Pico-8 graphics will always use memory location 0x6000-x0FFFF (hexadecimal memory location), then what new resolutions could be added by ZEP without using any additional memory ?

Well, quite a few actually.

(128 x 128 / 2) = 8192

Let's look at the primary resolution which is 128x128 pixels with a maximum of 16-color choices. Now be aware a new palette was found for it so you can change any of these 16-colors to really 32-colors, but you cannot change the TINT, either R G or B of any of them. They are a fixed color set from the 32 shown above. And despite this palette you can only view 16 of them at a time - conventionally.

With "hardware" tweaks you can have more on the screen at a time.

But this article is not going to cover that. Instead it is going to cover what CAN be done with those 0x2000 or 8192-bytes of memory for graphics and where any pixel can be any other colored pixel. This primary resolution uses 2-horizontal pixels to make up one byte.

So the next resolution available would be 64x128 wide-pixels to give you a true 256-colors per pixel.

(64 x 128 x 1) = 8192

Here you can see a much larger palette with long pixels double-size across yet it is also uses a fixed palette, in this case 216-colors derived from 6-shades of red, 6-shades of green, and 6-shades of blue. While it might be possible to use any portion of extended memory to hold a custom palette, that is not covered in this article. Where a single pixel representing a single byte. Still only using 8192-bytes of memory.

(64 x 64 x 2) = 8192

The next resolution from here is 64x64 both wide and tall pixels to give you a true 65536-colors per pixel or 32-shades of red, 64-shades of green, and 32-shades of blue with a single pixel representing in this case =2= bytes of memory. Still only using 8192-bytes of memory.

So we now have more colors. Let's reverse this and get more pixels once again still only using 8192-bytes of memory.

The next resolution is 128 pixels across by 256-pixels down.

(128 x 256 / 4) = 8192

Using the 32-color palette above you are now limited to only showing 4-colors on the screen at a time although in truth you should be able to pick out which of the 32-palette for each of the 4-color slots. Where 4-long pixels represent a single byte. Still only using 8192-bytes of memory.

For wide-screen monitors or cellphones you can have this 256 pixels across by 128-pixels down with no distortion of the actual pixel shape:

(256 x 128 / 4) = 8192

Although you can see quite clearly this breaks the perfect square Cosy™ resolution and may not be feasible to do considering the interface and current display. Yet if it were limited to only appearing for the output of the cart, I think this could be done. Like the resolution above it also only allows 4-colors on the screen at one time. Where 4-pixels represents a single byte. Still only using 8192-bytes of memory.

The last would be one I would really like to see. True 1-bit graphics, black and white.

(256 x 256 / 8) = 8192

This gives you a whopping 256x256 pixels maintaining the square shape and square pixels with the ability to choose from the 32-palette any of the 2-colors available displayed here, default of BLACK (color #0) and WHITE (color #7). Where 8-pixels represent a single byte. Still only using 8192-bytes of memory.

And that's it ! Likely you can see additional ways of cutting up that 8192-bytes of memory for graphics and I think I've only touched the surface of this. Here is hoping @zep will in the future allow for some of these added resolution modes which of course could vary from one cart to the next.

For more information on colors, resolutions, and the hardware they run on, see this WIKIPEDIA comprehensive chart.


Hope This Helps !

P#110888 2022-04-26 16:13 ( Edited 2022-04-27 05:16)


Instead of buying an RG-351 or other gaming device, I settled on purchasing a gaming controller called the RAZER KISHI that allows you to place your cellphone in the middle and you can use the joystick accordingly.


While it works perfectly everywhere else including emulation of other games like Super Nintendo and Sony Playstation for the RetroArch, it is not configured correctly for the Pico-8 system when run from Google Chrome.

For instance the BLUE does nothing at all. Instead arrow key controls are done by the RED sliding joystick above that.

In the GREEN, The (A) and (B) control the (A) and (B) for Pico-8 just fine. The (X) and (Y) also do (A) and (B) but not auto-fire.

May I suggest, @zep, that the RED joystick which has very fine movement be used to control a virtual mouse, perhaps even showing a dot on the 128x128 screen. In pressing down on the joystick (which does register as a unique button), it counts as a LEFT mouse click.

In the PURPLE joystick, the same as a virtual mouse as it too has very fine movement, once again optional dot, independent of movement from RED, appearing in the 128x128 screen. In pressing down on THIS joystick it counts as a RIGHT mouse click.

Have the BLUE control arrow keys as normal and have keys (X) and (Y) instead be auto-fire for (A) and (B).

The double-boxes button nestled between the RED and BLUE could register as a BACKSPACE keypress and/or player #2 (O) as it appears to be a left-facing arrow on my KISHI.

The triple-lined button below the PURPLE could register as a TAB keypress and/or player #2 (X) as it appears to be a right-facing arrow on my KISHI.

The stylish X button (X-Box) just below the BLUE could register as the ENTER keypress (pause) as it appears to be the icon of a HOME on my KISHI.

With the left and right triggers located above the RED and GREEN, you are given 4 in all, two to each side. These could count as LEFT and RIGHT for player #2 and player #3.

Finally the option to hide the touch-screen controls. This could be done by tapping quickly twice in the bottom-right-hand corner of the Pico-8's screen. Double-tap the same area again to return the visual controls.

Also to allow zoom of any scale. 1x1 1.25x1 2x2 2.25x2 etc.

P#110720 2022-04-22 15:47 ( Edited 2022-04-22 20:09)

Cart #p8birthday-0 | 2022-04-19 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA

(v01 04-19-22)
TO LOAD THIS PICO-8 CART, in immediate mode, type: load #p8birthday

You may need to squint your eyes a bit to remove the flicker. :)






P#110513 2022-04-19 18:19

I know this has been mentioned before and while Pico-8 enjoys 5+ years of its release, is it still not capable of exporting to native Android APK format ?

export {cart}.apk

Or is there some easy method to do so effectively, possibly converting both the export of Pico-8 from HTML and JS to an APK ?

export {cart}.html
P#110425 2022-04-18 19:13 ( Edited 2022-04-18 19:14)

Cart #s23pages-1 | 2022-03-25 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA
TO LOAD THIS PICO-8 CART, in immediate mode, type: load #s23pages

Back in QBasic for DOS there was a resolution you could have that gave you 16-pages to store your 320x200 16-color graphic screens. Zero (0) was the main display and 1-15 were storage locations. It was invoked by typing: screen 7 and you could copy screens using pcopy(a,b)

When I first wrote S1 I made heavy use of these additional 15-pages and stored all kinds of information there, not just graphics but including map data and script data converted to pixels and back to numbers again as actual variable space was small.

While we have no requirement for this today you still might need additional pages to draw and recall information from for your 64x64 pixel carts. So I wrote this cart and set of functions to assist in this.

In it you can record and recall a 64x64 pixeled screen (totaling 2048-bytes each) to any of 23-graphic pages that are stored in memory. It uses no arrays or variable space.

You have 5-functions.

The first initializes the 64x64 resolution mode and forces all drawn elements to maintain within that area, it is called: set64x64() and uses no arguments.

The second clears the 64x64 screen at any time. You cannot use CLS() as if you are using pages -1 to -3, it would clear those as well as this is still part of your 128x128 screen despite only viewing 64x64 pixels. It is called: cls64(c) and uses one optional argument for screen color. But is not required.

The third copies any of the 23 pages either to the main screen or back again. It is called: pcopy(a,b) and uses numbers as pages and memory information as listed thus:

  • -7 = the bottom-right-hand corner of sprites (64x64)
  • -6 = the bottom-left-hand corner of sprites (64x64)
  • -5 = top-right-hand corner of sprites (64x64)
  • -4 = top-left-hand corner of sprites (64x64)
  • -3 = bottom-right-hand corner of screen (not seen with 64x64 resolution)
  • -2 = bottom-left-hand corner of screen (also not seen)
  • -1 = top-right-hand corner of screen (not seen)
  • 0 = Your normal 64x64 display
  • 1 = Memory location 0x8000
  • 2 = Memory location 0x8800
  • 3 = Memory location 0x9000
  • 4 = Memory location 0x9800
  • 5 = Memory location 0xA000
  • 6 = Memory location 0xA800
  • 7 = Memory location 0xB000
  • 8 = Memory location 0xB800
  • 9 = Memory location 0xC000
  • 10 = Memory location 0xC800
  • 11 = Memory location 0xD000
  • 12 = Memory location 0xD800
  • 13 = Memory location 0xE000
  • 14 = Memory location 0xE800
  • 15 = Memory location 0xF000
  • 16 = Memory location 0xF800

So if you used pcopy(16,0) that would copy the screen memory from storage #16 back to the visible screen.

To save the current screen to storage #16 you would reverse the numbers, pcopy(0,16)

The fourth function is just like the 3rd except that it forces debug information to appear. It is called: pcopydebug(a,b) and uses the same arguments as pcopy(a,b)

The fifth function returns you to normal 128x128 pixeled graphic mode. It is called: end64x64() and uses no arguments.

In running this demo cart, all 23-pages are filled with randomly colored circles that do not repeat each other to prove it works correctly.

use the arrow keys to navigate copying that particular page number to the main screen. Obviously nothing APPEARS to change for page # 0 as that is your visual page.

Press 🅾️ to remove the 64x64 resolution and return back to 128x128 resolution in addition to copying the spritesheet straight to the screen to show how screens # -4 to #-7 are stored. You must press CTRL+R from here to rerun the cart.

Press ❎ at any time to turn on and off the debug information.

The debug information is interpreted thus:

  • M[1] = The memory location to copy FROM.
  • M[2] = The memory location to copy TO.
  • X[1] = If this is 1 then it is adding 64-pixels to get the right-most side of the screen or spritesheet.
  • X[2] = the same as X[1] except it will always be zero since we are just viewing the main screen.

If you are running in immediate mode, you can press [ESC] to return back to 128x128 mode and see pages # -1 to -3 appearing on the main screen.

If there is a desire, I could make a 128x128 pixel version of this library.

Further if you have any questions or suggestions, feel free to enter them below. Thanks !

P#109122 2022-03-25 00:52 ( Edited 2022-03-25 15:54)

Cart #c32_string-0 | 2022-03-22 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA
TO LOAD THIS PICO-8 CART, in immediate mode, type: load #c32_string

This is a continuation of a project I worked on last Spring back to effect 32-colors out of Pico-8 and at a pixel-level where the screen is 64x128 in size.


Unlike the first version, this one does not fill up the spritesheet and instead has a single function, "show32pic()" of 82-tokens or 197-chars that takes the included single string located in the sourcecode of 8192-characters and draws out the 64x128x32 picture with the correct decompressed image.

This total code compresses at 4587-bytes or uses 29% of a total 15616-bytes to maintain posting online as a clipboard file or PNG file.

If you would like me to write a tool for yourself and others to use that can convert a 24- or 32-bit PNG or JPG to this new 32-color format for new 64x128 pixeled logo screens to your Pico-8 carts, I can do so, just ask.

Further if you have any questions or suggestions, feel free to enter them below. Thanks !

P#109003 2022-03-22 04:31 ( Edited 2022-03-22 06:09)

@zep (and other Piconians), I was understanding that the .GIF size saved in Pico-8 when you save a video, the size of the saved .GIF was cut down in size considerably from previous versions. I am not seeing that HERE in version 0.2.4b.

Here are 2-identical videos. One is saved in Pico-8 with no changes, the other, VirtualDUB, both saved at 33.3fps, the same listed in the Pico-8 documentation.

To see these two videos running perfectly and simultaneously together, for FIREFOX, press ALT-D, CTRL+C, CTRL+N, CTRL+V, and the ENTER key. To close this window again, press CTRL+W.

^^ SAVED IN PICO-8: (2.00mb)


Click SAVE IMAGE AS on either of these pictures to examine them and their size if you like.

I am not marking this as an error as it does not come into conflict with the system itself, just the filesize of recorded videos. Does anyone know why there is such a filesize difference ?

P#108974 2022-03-21 18:42 ( Edited 2022-03-22 23:25)

(v12 03-29-22)

Cart #fillp_editor-12 | 2022-03-29 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA
TO LOAD THIS PICO-8 CART, in immediate mode, type: load #fillp_editor



  • Updated main code to paste properly even if from an outside source like internet or notepad.
  • Updated demo code with helpful notes inside the code to explain exactly how it works. (SEE BELOW).


  • Fixed CRASH when attempting to scroll empty field.
  • Fixed overlapping sprite information.


  • New method for manipulation of pattern blocks.
  • Overhaul button state recognition and reaction code.
  • Improved extra button view. No longer do 2-special buttons appear at one time.
  • Added mirror-X and mirror-Y.
  • Added 90-degree rotation.


  • Added ability to scroll pattern in edit. thank you, @beanborg for the suggestion!
    To use hold down the ❎ key and press an arrow in the direction you wish to scroll the pattern. Pattern will wrap around edges.


  • Pattern can now be seen changing above you as you enter it.
  • Added INVERT button in bottom-right-hand corner.
  • Added 2-line information below to show exactly what code creates the visible pattern above.
  • Adjusted code slightly for new visual margins and information.
    ? if you come across a bug or there is something you would like changed or added, please let me know!

This program will let you not only create single 4x4 patterns and see them as you enter them, but you can have a whole set, up to 256 if you like ! and even includes the unique 3-flags of TRANSPARENCY, SPRITE, and GLOBAL for each FILLP() pattern.

With new suggestion by beanborg you can now hold down the ❎ key and scroll with wrap ability. Just hold down the ❎ key and while it is held, press the arrow in the direction you want to scroll your pattern.


  • Use arrow keys to navigate 4x4 frame. Cursor does not wrap but hits edges where additional commands can be seen.
  • press 🅾️ to plot or unplot pixel in the 4x4 field.
  • Hold ❎ and arrow keys to scroll the 4x4 field with wrap-around pixels. Release when complete.
  • Move the cursor to the far left vertical center to highlight PREV which when 🅾️ is pressed will go to the previous pattern. You have 256-patterns available to work with and will wrap from 1 to 256 and vice-versa.
  • Move the cursor to the far right vertical center to highlight NEXT which when 🅾️ is pressed will go to the next pattern. Same as above will wrap around.
  • Move the cursor to the far left on the 1st vertical pixel and INV-X will appear. When 🅾️ is pressed will take the 4x4 pixels and invert them horizontally.
  • Move the cursor to the far right on the 1st vertical pixel and INV-Y will appear. When 🅾️ is pressed will take the 4x4 pixels and invert them vertically.
  • Move the cursor to the far right on the 4th vertical pixel and ROTATE will appear. When 🅾️ is pressed will take the 4x4 pixels and rotate them 90-degrees to the right.
  • Move the cursor to the far left on the negative one vertical pixel and TRANSP will appear. When 🅾️ is pressed this will turn on/off the TRANSPARENT flag for this pattern. When this bit is active, the second color is not drawn.
  • Move the cursor to the far right on the negative one vertical pixel and SPRITE will appear. When 🅾️ is pressed this will turn on/off the SPRITE flag for this pattern. When this bit is active, the fill pattern is applied to sprites (SPR, SSPR, MAP, TLINE).
  • Move the cursor to the far left on the "5th" vertical pixel and GLOBAL will appear. When 🅾️ is pressed this will turn on/off the GLOBAL flag for this pattern. When this bit is active, the secondary palette mapping is also applied by all draw functions that respect fill patterns (CIRC, CIRCFILL, LINE).
  • Move the cursor to the far right on the "5th" vertical pixel and INVERT will appear. When 🅾️ is pressed every 4x4 pixel in the field will turn to their opposite. On to off and off to on. Click again to revert back.
  • Move the cursor to the center on the "5th" vertical pixel and EXPORT will appear. When 🅾️ is pressed your pattern or series of patterns (if you have more than one) will be exported. See ADDITIONAL below.
  • Move the cursor to the center on the negative one vertical pixel and IMPORT will appear. When 🅾️ is pressed the clipboard is scanned for the exact code you earlier pasted to read in and convert back to where it can be edited in my FILLP EDITOR. See ADDITIONAL below.

Note the two programming lines below the 4x4 grid seen above. This shows what value FILLP() has for the pattern you are working on and the 3-numbers above, Binary, Hexadecimal, and Decimal also appear and change every time you add or remove a pixel. As you can see in RECTFILL() you can have a pattern appear as 2-colors by adding a new colored multiplied by 16. In this case it is color 13 (violet) combined with color 12 (aqua).

Be aware that all Pico-8 patterns are not OR but AND. They REMOVE pixels from a solid pattern, not the other way around. If you want to draw a pattern but have it OR, draw what you want first, then select the INVERT button.

If there is a need to do this backwards where the results in the grid appear the same but the actual data saved and the pattern appearing above is the opposite for transparent-flagged sprites, i can do so. I could add a menu item with the regular MENUITEM() to optionally reverse the storage for transparent patterns. Just ask.


This pattern editor has the ability of both importing and exporting patterns.

To EXPORT your pattern or more than one if you have created more than one, move the cursor until it is in the horizontal center and then move the cursor until it is in the "5th" vertical position. The word, "EXPORT" will appear. Press 🅾️ and you will be asked some questions.

The first is, EXPORT TO HEX OR DEC? Any time the screen turns black and you have a question, you can change your answer from ? by pressing any of the 4-arrow keys. ⬆️ or ➡️ will select the next choice. ⬇️ or ⬅️ will select the previous answer.

In this instance you have choices of ? HEX DEC and ABORT

HEX means when you EXPORT the numbers will be listed in hexadecimal notation. DEC means they will be decimal and if you click ON the top-left-hand corner pixel, the number will be negative. Select ABORT of course to cancel this.

The next is, BASE ZERO OR ONE? Once again use the arrow keys to navigate the choices. In this instance you have choices of ? ZERO ONE and once again ABORT

Choose ZERO if you want your array to be preceded by [0]= to force the first element to appear at array position zero, IE: patd={[0]=n1,n2,etc}

Choose ONE which is default where normal LUA arrays start at 1 (one). IE: patd={n1,n2,etc}

Make your choice again with the 🅾️ key.

If you are ONLINE a 3rd choice will appear. PRESS CTRL+C NOW! Well not really so much a question. Nonetheless from here press CTRL+C then select DID SO and 🅾️.

COPIED TO CLIPBOARD will appear. Select NICE and 🅾️.

CTRL+V WILL PASTE will appear. Select GOTCHA to confirm you understand and press 🅾️.

Then you will return back to the editor. Be aware the arrays are PATH[] for hexadecimal and PATD for decimal.

To use this in any Pico-8 code, merely press CTRL+V to paste as was instructed.

For instance, let's say you made:


EXPORT those two patterns.

Now start a new Pico-8 session by either ending FILLP EDITOR or starting a new task, and type out the following in source code:

((press CTRL+V HERE))

The print() command will move the cursor out of the way of the rectangle.

Your code should now appear as:


Notice that the 1st pattern has a fractional number. That is because if you look at the two patterns above, the 1st one has the "T" flag lit for TRANSPARENT as we set it.

RUN or press CTRL+R to run this program and be aware of the output:

You can see that the dark blue peeks through because of the transparency flag set for this pattern. While you cannot change the background color in this pattern, you CAN change the foreground by changing the last line thus:
And there you have RED with transparent pattern.

To see the next pattern, if you change the next-to-last line to read, 1 instead of 0 (zero) you will have:


You will have the 2nd pattern with the exception that the background color is BLACK.

To force a background color for the output, merely add a new number multiplied by 16.

So you would get the following:

rectfill(0,0,31,31) ...

rectfill(0,0,31,31,7+2*16) ...

rectfill(0,0,31,31,2+7*16) ...

rectfill(0,0,31,31,14) ...

rectfill(0,0,31,31,4+8*16) ...

To load existing pattern data, copy the entire single programming line to the clipboard, it can be from any source including Pico-8, Online web browser, or even Notepad. Run this program again. This time move the pointer all the way up to select IMPORT. Follow the instructions there including to press CTRL+V to authorize paste text. Provided it is exactly as you pasted it earlier, it will be loaded back in the editor where you can make further changes.

Here is a sample program that includes the data clipped from the FILLP()Editor and makes use of transparent patterns. Press 🅾️ to do a fancy screen wipe with patterns and change the screen.

(v4 03-29-22)

Cart #fillp_demo-4 | 2022-03-29 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA
TO LOAD THIS PICO-8 CART, in immediate mode, type: load #fillp_demo



  • Added helpful notes for all of code.
  • Slowed down the animation effect slightly so it can be seen better.

Here is the pattern table used in the demo if you'd like to examine it in the editor:


To do so, left mouse button triple click to highlight it. Press CTRL+C. Then run my editor. Select IMPORT and examine all unique patterns.

Hope This Helps ! If you have any questions or suggestions, feel free to enter them below. :)

P#108945 2022-03-20 20:41 ( Edited 2022-03-29 23:23)

Cart #outline_diverse-1 | 2022-03-16 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA
TO LOAD THIS CART IN PICO-8, type in immediate mode, load #outline_diverse

Years ago when I first got the IBM-pc, I was quite interested in 8x8 pixel artwork and even though I was limited to black and white, I managed to write up a little paint program that self-modified GWBASIC to create strings of 8x8 pixeled images using multiple stringed plot() for each of the letters A-Z.

If instead I pressed the CTRL key followed by a letter I could enter in a new 1-bit 8x8 pixel definition or replace an old one. To save my 26-images I just saved the .BAS program.

Years later when color was introduced I modified my program and built from it a massive system called, "Tilemaster." The version for BlitzMAX I wrote I still use to today, and in it, I have a function I call Outline Diverse or (outdiv()).

In it take a single string of up to 9-characters and draws an outline for a sprite based upon a 3x3 field.

You of course are welcome to develop your own outlines, using the format for a single number:

256 128 064 ▄ ▄ ▄
032 016 008 ▄ ▄ ▄
004 002 001 ▄ ▄ ▄


For instance, this pattern creates what I called a BRICK shadow. It not only creates a shadow that is X+1 and Y+1 of the image but also X+1,Y+0 and X+0,Y+1. Doing so gives a more full outline. It's numerical equivalent is 8+2+1 or 11.

You can include the center square as well (16) to have the outline replace the actual image with a single color as well. This is useful to make enemy targets flash white or red or what have you. This choice is included in the demo above. GLOW lights up all 9-outline points and gives you not just your sprite turned to one-color but a perfect outline around it as well.

In execution:

Use the ⬅️ and ➡️ arrow keys to move the sprite left and right.
Use the ⬆️ and ⬇️ arrow keys to change the sprite image. You can make more if you like.
Use the 🅾️ key to change the outline type, be aware you can add your own.
Use the ❎ key to change the color of the outline, 16-color choices.

The CPU shows how much map() is taking with a / key showing actual CPU usage which is quite small at maximum 1%.

And there you have it !

The function included is called, outline() at 75 tokens or 176-chars and uses the following arguments:

function outline(s,x,y,t,c,h,v)
-- draw sprite outline using
-- the following variables:
-- s=sprite #
-- x=sprite's x-position
-- y=sprite's y-position

-- t=type of outline (binary)
--   this is a single number
--   from 0-511 thus:
--   256 128 064 █ █ █
--   032 016 008 █ █ █
--   004 002 001 █ █ █

-- c=color of outline
-- h=sprite size across, def 1
-- v=sprite size down  , def 1
-- (both variables of h + v
--  are optional)

H + V are optional and yes you can give a shadow or outline to a bigger sprite, just use a number greater than one for either H or V. H=2 and V=2 or instance will use a sprite that is 16x16 pixels.

If you have any questions, feel free to ask.

P#108762 2022-03-16 21:32 ( Edited 2022-03-17 03:37)

Hey, can one of you solve this ? It doesn't make sense to me.

This code:

function doit(x,y,d,r,c)local b,e,h,v,a=x,x-r,y if d==1then b=y e=y-r h=x elseif d==2then e=x+r elseif d==3then b=y e=y+r h=x end for i=b,e,sgn(e-b)*2do a=b-i
if(d==2or d==3)a=i-b

Runs correctly. THIS code, however, does not. All I did was move the if(d==2 or d==3) to the line above.

function doit(x,y,d,r,c)local b,e,h,v,a=x,x-r,y if d==1then b=y e=y-r h=x elseif d==2then e=x+r elseif d==3then b=y e=y+r h=x end for i=b,e,sgn(e-b)*2do a=b-i if(d==2or d==3)a=i-b

I get a SYNTAX error.

Any ideas on what the problem is ?

P#108680 2022-03-15 18:56 ( Edited 2022-03-15 20:04)

Cart #field_of_view-4 | 2022-03-15 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA
TO LOAD THIS PICO-8 CART, type in immediate mode: load #field_of_view


  • made them all tweetcard sized functions!
  • made beam bigger.
  • allows for different types of beams.
  • made beam comparison smaller and faster code,
  • uses less cpu.

I have coded this so the two primary elements of drawing the beam and checking to see if there is a collision with the beam are now small functions.

The drawbeam() function for instance is 280-characters and the inbeam() function is 225-characters which returns TRUE if there is a collision.

-- draw solid or dotted beam:
function drawbeam(x,y,d,r,c,s) (131-tokens or 280-characters)
-- x=sprite's x-position
-- y=sprite's y-position
-- d=direction sprite is
-- facing:
--   0=left, 1=up, 2=right,
--   3=down
-- r=radius of beam in pixels
-- c=color to plot
-- s=spacing:
--   1=normal, more cpu
--   2=dotted, less cpu
-- check to see if player is
-- in sight of beam. returns
-- true if this is the case.
-- assumes sprites are 8𝘹8
-- pixels:
function inbeam(h,v,x,y,d,r) (121-tokens or 225-chars)
-- h=player horizontal
-- v=player vertical
-- x=enemy horizontal
-- y=enemy vertical
-- d=direction beam is facing:
--   0=left, 1=up, 2=right,
--   3=down
-- r=radius of beam in pixels

It was recently discussed, asking for a method of Line Of Sight for a game. The responses involving atan2() and sqrt() were rather confusing for me to understand, so I thought it about it in my head, basically 4-triangles. And decided to write my own here.

Based upon a cart I wrote earlier to determine finger swipes or mouse movements on the Pico-8 screen.


While it does not use a circle for line of sight, it still gives you the triangle view which you want your enemies to have, and it does it using only two commands, abs() and /2 quite simply, divided by 2. it is =NOT= scanning any pixels at all, collision is determined entirely through two math functions - so you could have the cone's pixels turned off but still be able to register collisions in it.

The code should also be easy to read as I have given helpful comments for every part of it.

It also only uses 2% of your CPU with cone view visible and 0% of your CPU when cone view is not visible, so you could definitely have a whole bunch of baddies running around still with their line of sight, determining if they can see the player or not even if you cannot see their field of view.

In this cart you use the arrow keys for navigation, 🅾️ to turn on and off the view cone for the enemy, and ❎ key to swap between moving the player and the enemy. Pressing an arrow direction for the enemy also faces them in that direction.

The field of view is seen as a simple dotted field and turns bright red if the player is in the line of sight.

And there you have it ! No complex calculations, works perfectly. Examine fully documented source for details.

If you have any questions, feel free to let me know.

P#108625 2022-03-14 21:40 ( Edited 2022-03-16 01:35)

Now that I am finally writing music in Pico-8, I would like to request from @zep that you can play beyond 32-notes with SFX().

Already the LOOP marker will count past this but it does not start to play the next SFX, instead it is silent before restarting.

So it would be a single flag that appears before LOOP to show this SOUND has 64-notes instead of 32. And if THAT SFX had the flag set it would be 96 instead of 64.

You can see it here as a PINK button to select just before LOOP.

P#108335 2022-03-09 17:43 ( Edited 2022-03-09 18:58)

Cart #psychedelic_flappy-3 | 2022-03-08 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA
TO LOAD THIS CART in immediate mode, type: load #psychedelic_flappy

Having taken a look at @taxicomics excellent 280-character Flappy Bird:


I went about to see if I could write my own, where the game increases in speed depending upon your score, and managed to do so.

It's called "psychedelic" because the walls all use an interesting pattern depending upon your score.

Use the 🅾️ key to flap. I also tried to make it very much like the original FLAPPY game where you just tap the key and already the bird is bouncing up - that and the opening size. It also only has one set of walls you must pass so there is no chance for the game to be impossible with two openings too close to each other for the player to navigate.

The wall positions and patterns are the same every time so this game could for instance be speedrun with no unpredictable wall positions. Also the game speeds up for every point so eventually you have to have very good reflexes indeed for a higher score.

I am only checking the nose of FLAPPY so if your middle or back hits a wall, you are still safe and it does not count as a collision. You can tell when you do collide with the wall as the color suddenly goes red and you lose control of Flappy. Your final score will appear in the top-left-hand corner of the screen.

Press CTRL+R to start a new game at any time.

t=rnd g=1y=0z=0s=0r=rectfill::_::srand(s)fillp(t(-1))w=t(95)+16_set_fps(25+s)for i=128,-8,-g do cls()r(i,0,i+7,w-12)r(i,w+12,i+7,127)?s
if(pget(68,y)>0or y<-8or y>128)g=0pal(6,8)
z+=.2y+=z if(btnp(4)and g>0)z-=4
flip()end s+=1goto _

The code is currently at 125-tokens or 247-characters and there are no special characters in the sourcecode nor does it use the spritesheet as other Pico-8 tweet code Flappy Bird have done in the past so the game in its entirety can be both pasted and read from TWITTER with ease.

This is the 4th version and I think this is about as far as I can compress it.

My top score is 12. How high can YOU get ?

P#108196 2022-03-07 20:17 ( Edited 2022-03-08 03:27)

Cart #multitorch-0 | 2022-03-06 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA
TO LOAD THIS CART in immediate mode, type: load #multitorch

With the continued interest in torchlit effects, you are familiar with the post I made where you could have one torchlit effect for the center of the screen for the player:


Well this one is a little different and a bit more complex with 32-lamps although the code is explained in great detail for everyone to understand. in that it lets you have as many lights as you want in a 63x63 area map and they animate starting from darkness to brightness and back again.

Unlike other torch effects, this one does not change palette but uses a new set of tiles. So it is entirely possibly to use the code here to have a torchlit effect reveal something that normally was not seen earlier.

During the cart use the arrow keys to navigate and the 🅾️ button to light or unlit a lamp that you are atop. Press ❎ to turn on or off the flickering lights effect. A display of information is kept at the top in addition to showing you how many lamps you have left to light.

If you want to "win the game" turn on all the lamps and you will be notified when you have done so.

This source code is heavily remarked to explain exactly how everything works as I believe this is an important concept to be learned by all Piconians.

Thanks to @Krystman for showing multiple ways of accomplishing torchlit effects.

-- https://www.lexaloffle.com/bbs/?tid=46286

And to @professir showing multitorch could be done in a game setting:


If you have any questions, feel free to ask !

P#108117 2022-03-06 03:36 ( Edited 2022-03-06 05:54)

Cart #center_frame-0 | 2022-02-25 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA

Suppose you were watching a movie and it was not centered where in the middle of the screen but may even be off the edge or too far to the left. Well that's kind of what's happening here in Pico-8 when you run a cart Online.

At least for me in Firefox for Windows 10 I have to carefully move the right-sidebar to center vertically in on a Pico-8 game I want to play online and there is no way to center it perfectly horizontally.

Suggestion: Click anywhere in the field above or on the play button and it automatically centers the frame, not just vertically but horizontally as well introducing artificially increased boundaries from the left to pad it perfectly horizontally centered if need be. Add button option to "dim the lights," not turn them out entirely, for anything that is not the frame for an immersive game playing experience that does NOT require full-screen and you can still see the taskbar below.

P#107662 2022-02-25 22:38 ( Edited 2022-02-26 03:34)

Hi guys. There is another concern I have.

While it is certainly possible to run your cart at 30fps using _update() or 60fps using _update60() how do you go about arbitrary speeds like 13fps or 129fps and having the ability to change it during the execution of the cart ?

The reason ? Early arcade games such as VENTURE would make the game harder not just by making the enemies more aggressive but more importantly, actually upping the frames-per-second rate of the gameplay making it that much more difficult. I wanted to bring this option to Pico-8 as I have not seen any games yet that do this - where you can increase the framerate by any rate.

You can sort of do this in Pico-8 by NOT using _update() or _draw() and flip() yet ... how do you do write this cart WITH the standard _draw() and _update() ... and in fact is there some way to POKE a forced FPS for _update() and/or _draw() that can be as low as 1fps and exceed 60fps or even go up to something like 240fps ?

-- how to make this with
-- conventional _init() and
-- _draw() and _update() ?

function main()

-- from 1 to 16384
-- try 1, 16, 128, 1024, 16384

for y=0,127 do
  for x=0,127 do
    if c==speed then

P#107649 2022-02-25 17:48 ( Edited 2022-02-26 03:36)

I was wondering if there was a solution to this:

  if (b==2) then
      return true
end )

Now I know I can create a new function to return true, however is there a way do it internally within menuitem() itself ?

P#107599 2022-02-24 16:00 ( Edited 2022-02-24 16:11)

Cart #draw_vs_update-1 | 2022-02-13 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA
TO LOAD THIS CART in Pico-8, type in immediate mode, load #draw_vs_update

Press 🅾️ to swap between using _update() and _draw(). When in _draw() mode you may need to hold 🅾️ down a bit to get it to the opposite mode.

Yet this confuses me. Why is it that draw() runs faster than update() ?

And yes you can change it to update60() that does run faster, but still not as fast as draw().

P#106816 2022-02-13 02:53 ( Edited 2022-02-13 05:10)

Cart #map_cpu-1 | 2022-02-12 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA
TO LOAD THIS CART in immediate mode, type: load #map_cpu

Press 🅾️ to swap modes:

MODE_______________  CPU
0 = map() .........  12%
1 = rectfill() ....   1%
2 = for/end map ... 201%
3 = for/end fill ..  54%

I am not understanding how it is that map() is so much slower than rectfill() when on modes 2 it is only 4x slower than its fill counterpart, mode 3.

It is not the details which should be pretty straight-forward. I mean isn't rectfill() also plotting pixels just the same one each time when compared to map() ?

P#106753 2022-02-12 02:50 ( Edited 2022-02-12 03:11)

Cart #torchlit_view-3 | 2022-02-11 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA
TO LOAD THIS CART in immediate mode, type load #torchlit_view

As shadows and circular shadows are still rather popular at the moment, back in the day when I was coding in GFA I was working on a massive project called Scenario 2 RPGMaker. If you're curious, Scenario 1 was written in QBasic 1.0 while S2 was in GFA. I wanted to have all the interesting elements that you could find in RPG 95 at the time. One of which was a torchlit view.

The early Torchlit view I had in S1 was quite primitive based on early Ultima 3 where the screen was 9x9 tiles and all it did was draw a rough circle in 5x5 tiles to the center keeping the others black.

So with S2 and the knowledge I was not limited to tile movement alone, I gave it some more thought fully knowing drawing circles are super-slow, but rectangles were not. So the idea was to fill the screen with a solid color, then draw a filled rectangle to match the edges of the solid base for the circle I would create inside.

While this effect can be done many different ways, to me this was the easiest. And what I did was to record this 'torchlit' mask image to a different _dc() or display channel for maximum speed. Then I could use AND to plot it where black was not drawn and white was drawn as black.

This is very similar to what I am doing here and because it is not just a series of circles that fill and extend beyond the entire screen but two intelligent rectangles drawn to first fill the screen and the 2nd to match the edges of the beginning edges of the completely transparent circle in the center.

It should also not use too much CPU for you.

If desired I could make this a single function for custom use.

. . .

? ? ?

I am just now thinking there is a helluva better way to do this and should be <1% CPU. Tomorrow I'll post my findings on that.

Well ... after coding it, it was a bit faster, clearly not less than 1%, but it doesn't have that kind of interesting lingering pattern effect. Here, compare for yourself.

Cart #torchlit_view_mark_2-0 | 2022-02-11 | Code ▽ | Embed ▽ | No License

I definitely like the first one better despite it using more CPU.

And yes, this can be helpful. We can always learn from our mistakes. That is encouragement for all of you, never ever delete any code you write. Always try to save absolutely everything you write. While 95% of the old code you wrote you feel you may not need at the time, there is that 5% you'll be glad when you do.

However this is an interesting area to experiment in, Torchlit View. If I find something better and faster, I'll let you know.

P#106686 2022-02-11 04:34 ( Edited 2022-02-11 21:11)

View Older Posts
Follow Lexaloffle:        
Generated 2022-05-20 10:44:16 | 0.116s | Q:70