Log In  

i made a spooky scene to test if i could generate visual details procedurally — yes, i could

Cart #spooky_decogen_berodajuya-0 | 2022-12-06 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA

before i could create the full scene, i made a fake screenshot in a pixel art editor
so i could look at the picture and imagine which commands i would need to add the details

behind the scenes

warning: long text

i added details by selecting tiles that should have added details, storing the tile numbers as variables on a code page (the 2nd one), then programming on the next (3rd) codepage how the tiles should be decorated.
the last (4th) code page has only the main loop, and the first one has no code because it's for a bit of extra documentation.

the decogen…draw() (decoration generation draw) function checks every tile for if it's one of the special tiles, and then decorates if it is.
each tile has distinct decorations, so they have very different approaches to being decorated:

  • pillars are generated from the base (the only pillar sprite in the spritesheet).
    they check for a ledge above to know how long the pillar should be.
    when they hit it, the rest of the pillar is drawn from top to bottom, with three parts
    • the base sprite but mirrored, is the capital (the top)
    • a dark line shades the capital
    • a rectangle connects the base and the capital
  • every brick wall tile on the map checks if it is below a ledge tile.
    if it is, it draws a shaded row of bricks below the ledge
    using a one-off character that i made in my one-off character creator
  • the lamp's decoration has two parts
    • the pole is almost like a pillar, but in reverse:
      the lamp checks the tiles below the bulb (the only lamp sprite) until it hits the floor,
      then it draws the pole. it has four parts
      • mirrored base sprite as capital
      • line that shades the capital
      • rectangle that connects the pillar
      • base sprite used as-is for the base
    • the emission lines are just six lines that get drawn next to the bulb — no checks needed
  • the door has only its bottom tile in the spritesheet.
    the part above gets generated — no checks needed.
    it has 4 parts
    • the top third of the door is another one-off character
    • the row of bricks above is another one-off character, but only the bright pixels
    • the single dark pixel of the brick row is drawn with pset()
    • i added a black outline to the left and right of the door
      using 2 lines
  • the clock is also getting decorated with no checks. the decoration has 3 parts
    • a black filled circle for the clock face
    • a bright hollow circle for the outline
    • because the filled circle overdrawed the clock hands,
      the clock hands sprite gets replaced
  • every cloud tile checks if it has an empty background tile to its left or right.
    if it has, it draws a line to complete the outline
before after


this scene uses 18 out of 63 sprites from the first sprite page
at the cost of 563 out of 8192 tokens.

if i had drawn the decorations in the spritesheet, i would have saved all tokens — at the cost of 22 more sprites

  • 4 more pillar sprites
    • 1 long connecting piece
    • 3 tile variations of the capital (the top of the pillar)
      • capital below light ledge
      • capital below dark ledge
      • capital below lamp
  • 6 sprites for the emission lines around the lamp
  • 1 sprite for the top part of the door
  • 9 sprites for the clock face and surrounding wall
  • 2 sprites to complete the outlines of the clouds

the original 18 sprites with these 22 more sprites would be 40 sprites. this would leave only 23 more sprites on the first sprite page

P#121947 2022-12-06 22:14


Here now, @Sosasees.

If you use poke(0x5f2e,1) inside your code, when it exits you can edit your sprites in the color set you chose via your _draw() function.

Use pal() either in your code or immediate mode or type RUN with no palette changes to return back to your normal colors.

P#121958 2022-12-07 01:20

thank you @dw817 very much for the tip.
this was very useful for 'new profile picture 2023-01-01' and will be very useful later

P#123646 2023-01-04 14:30

i was now a programmer of PICO-8 cartridges
for long enough that
i am convinced that
almost every programmer of PICO-8 cartridges
has invented procedural visuals generation

because i have played cartridges that use procedural visuals generation
that were made long before this one — and newer ones, where i am convinced that the creator has never seen this post

P#123647 2023-01-04 14:34 ( Edited 2023-01-04 14:39)

Yes Autotiling and drawing extra bits is very helpful. feels really broad honestly, like adjusting how you draw sprites or just completely adding new stuff for various effects

P#123648 2023-01-04 15:32

[Please log in to post a comment]

Follow Lexaloffle:          
Generated 2023-01-27 13:19:18 | 0.023s | Q:19