PICO-8 Tweetcart Studies

Back to main menu


Blue Vertigo

Author: Michał Rostocki (@von_rostock)
Link: https://twitter.com/von_rostock/status/1220430044054663168

Blue Vertigo

Display Palette

0
-15
1
-13
-4
12
6
7

Summary

This is a very nice tunnel effect that uses colours from the secret palette. It’s basically a plasma with the intensity of the colours boosted for the segments closer to the camera.

If you’re unfamiliar with plasmas, it’s an effect where you keep throwing different sin, cos, and similar functions on top of each other until you get a random-looking, but contiguous, output. See the plasmas page for some more info on this effect.

Most pico-8 games call cls() at the start of every frame, but this effect just leaves the existing screen alone and draws over the top of it. The pictures below shows which pixels are actually drawn every frame, and also how this looks when starting up. Doing this (instead of using cls() and redrawing everything) ensures that the screen will always be in a good-looking state, so there’s no need to call flip() at the end of each rendering loop. See the cls-vs-dithering page for some more info on this technique.

Pictures

The existing frame is updated each loop (rather than using cls() to start fresh).

When starting up it takes a short while to hit every pixel on the screen.

This shows how many pixels are actually drawn each loop. Note all the empty space in the middle of the lit-up areas.

Each line segment is drawn in a spiral, looping from the centre out

This is the effect but with less twisting in the plasma. The plasma creates the illusion of ridges and valleys, when the tunnel's totally smooth!

Tweet code

fillp(23130)s=sin::_::for r=16,128 do
pal(r%6,({-15,1,-13,-4,12,6,7})[r%6],1)j=16/r+t()/8p=64+r/4*cos(j)q=64+r/4*s(j)circ(p,q,30-r,0)g,h=p+r,q
for u=0,1,r/1400 do
w=s(u)k=abs(s(u*2+j+s(j))-w)*min(r/20,3)l=r-k
x=p+l*cos(u)y=q+w*l
line(g,h,x,y,k+flr(k+.5)*16)g,h=x,y
end
end
goto _

Breakdown

-- typical 0101,1010 fill, in binary it looks like this:
--    0101
--    1010
--    0101
--    1010
fillp(23130)

-- start rendering loop
::_::

-- loop through every radius from 16 to 128
for r=16,128 do
  -- nice colour ramp.
  -- negative numbers are a short way to access the
  --  secret palette
  pal(r%6,({-15,1,-13,-4,12,6,7})[r%6],1)

  -- the time, offset by where in the tunnel we're
  --  currently drawing. deeper into the tunnel is
  --  future in time
  j=16/r+t()/8

  -- x centre of tunnel
  p=64+r/4*cos(j)
  -- y centre of tunnel
  q=64+r/4*sin(j)

  -- black centre circle.
  -- circ() ignores when r<0
  circ(p,q,30-r,0)

  -- g,h==x,y points for the initial line segment below
  g,h=p+r,q

  -- loop 0->1 on each radius from middle to outside of
  --  the tunnel
  for u=0,1,r/1600 do
    w=sin(u)

    -- k == the plasma for this line seg. of the tunnel
    --
    -- abs(sin(u*3+j+sin(j))-w) is a typical plasma
    --  pattern, just throw sin/cos on top of each other
    --  until it looks good~!
    -- `u` is where we are around the circle so the u*3
    --  affects how many separate 'tentacles' we have.
    -- `j` is time relative to how deep in the tunnel we
    --  are.
    --
    -- *min(r/20,3) because the pattern gets more
    --  vibrant (the brighter colours are added) as the
    --  tunnel gets closer to the camera
    k=abs(sin(u*3+j+sin(j))-w)*min(r/20,3)

    -- l == current radius of the tunnel, this changes
    --  based on the plasma value and is why the
    --  brighter colours stick out towards the centre of
    --  the tunnel, while the darker colours sink into
    --  the walls
    l=r+k

    -- centre of the tunnel + _current_ radius * cos(u)
    x=p+l*cos(u)
    -- centre of the tunnel + _current_ radius * sin(u)
    y=q+w*l

    -- draw this line segment
    line(g,h,x,y,k+flr(k+.5)*16)

    -- draw from this line segment to the next~
    g,h=x,y
  end
end

-- because the screen never hits a bad-looking state,
--  there's no need to use flip here! :D
goto _