Log In  
Follow
hypothete
Follow

Hi all,

I'm writing a short graphical text adventure for the PICO-8, and a few weeks ago I determined that I needed a vector graphics editor capable of outputting PICO-8 code. I've created a web app called GMagic that lets you make vector drawings on a canvas, then export Lua functions for drawing them. I also provide the functions for drawing polygons and polylines:

ptstr() (needed for the functions):

function ptstr(s)
    local data={}
    local wip=''
    for i=1,#s do
        r=sub(s,i,i)
        if(r==',') then
            add(data,wip+0)
            wip=''
        else
            wip=wip..r
        end
    end
    add(data,wip+0)
    return data
end

Polygon:

function poly(r,c,p)
    local t=ptstr(r)
    --based off alienryderflex.com/polygon_fill
    --t=table x1,y1,x2,y2...
    --c=colors (hex)
    --p=pattern
    local pc=#t/2
    local px={}
    local py={}
    local my=127--miny
    local xy=0  --maxy
    --split out xy lookups
    for i=1,#t-1,2 do
        add(px,t[i])
        add(py,t[i+1])
        if(t[i+1]<my) my=t[i+1]
        if(t[i+1]>xy) xy=t[i+1]
        if(i<#t-2) then
            if(p) fillp(p)
            line(t[i],t[i+1],t[i+2],t[i+3],c)
            fillp()
            --yield()
        end
    end
    --scan down the screen
    for y=my,xy do
        local nx={}
        --build a list of nodes
    local n=0
    local j=pc
    for i=1,pc do
        if((py[i]<y and py[j]>=y)
            or(py[j]<y and py[i]>=y)) then
            add(nx,(px[i]+(y-py[i])/(py[j]-py[i])*(px[j]-px[i])))
        end
        j=i
    end
    --bubblesort nodes
    local k=1
    while(k<#nx) do
        if(nx[k]>nx[k+1]) then
            nx[k],nx[k+1]=nx[k+1],nx[k]
            if(k>1) then
                k-=1
            end
        else
            k+=1
        end
    end
    --fill the pixels
    for l=1,#nx-1,2 do
        local d=nx[l]
        local e=nx[l+1]
        if(d>=127) break
        if(e>0) then
            if(d<0) d=0
            if(e>127) e=127
            if(p) fillp(p)
            line(d,y,e,y,c)
            fillp()
        end
    end
 end
 --yield()
end


Polyline:

function pline(r,c,p)
    local t=ptstr(r)
    for i=1,#t-2,2 do
        if(p) fillp(p)
        line(
            t[i],
            t[i+1],
            t[i+2],
            t[i+3],
            c
        )
        fillp()
    end
    --yield()
end

If you want to read more about GMagic or check out some sample screenshots, you can view the Github repository here. If you end up using GMagic for a cart, I'd love to hear about it!

EDIT 6/24: I can't believe I forgot to include ptstr()! I've added it above, and to the Lua sample in the repo.

P#61467 2019-02-02 18:26 ( Edited 2019-06-24 21:48)

Hi all, I wanted to share with you an experiment I've been working on called World of Pico. It uses the GPIO pins to transfer map data from a JavaScript context to the cart, allowing for essentially unlimited maps for exploration when the cart is hosted on a webpage. The demo has 3 maps, but I can see this technique being used in combination with a map server, and eventually allowing for interactivity between the client and server.

The method of data transfer is very similar to how P8T by seleb works. Different values on pin 0 of the GPIO tell the JS app or the cart whose turn it is to read and update the following pin values. If you want to explore the source code or read more about the transfer technique, please check out the GitHub repo.

Thanks for taking a look!

P#60611 2019-01-06 00:29

Cart #46130 | 2017-11-11 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA
19

This is a demo using the fill patterns introduced in 0.1.11 as a way of dithering between two or more colors. Use the buttons to adjust spread of the gradient, the number of sample circles drawn per frame, and the radius of the circles.

The way it works is I have a gradient table, a fill pattern table, and a spread value. I'm going to draw 500 circles randomly each screen refresh, and each circle is going to use two colors and a fill pattern as its fill. The circle's colors are determined by the nearest and next nearest colors on the gradient based on some measurement, in this case the proportion of the spread to the shortest distance from a circle to one of three bouncing points.

I set up a table of fill patterns that I generated from a 4x4 ordered dithering matrix. There's a good description of ordered dithering here. Here's the matrix I used:

 1   9   3  11
13   5  15   7
 4  12   2  10
16   8  14   6

To make a table of fill pattern values, I iterated over the 4x4 matrix 16 times, and if each cell was higher than the count i, I flipped a corresponding bit in a 16-bit binary number. This gives us 16 binary numbers to pass to the fillpattern method:

pat={
  0b1111111111111111,
  0b0111111111111111,
  0b0111111111011111,
  0b0101111111011111,
  0b0101111101011111,
  0b0101101101011111,
  0b0101101101011110,
  0b0101101001011110,
  0b0101101001011010,
  0b0001101001011010,
  0b0001101001001010,
  0b0000101001001010,
  0b0000101000001010,
  0b0000001000001010,
  0b0000001000001000
}

The fill pattern for each circle is then determined by the circle's position between one color and the next along the gradient. So if the circle lands between two colors, it will use pat[7] or pat[8], but if it's centered on a color it uses pat[1].

P#46131 2017-11-11 02:11 ( Edited 2017-11-11 07:16)


Simple Voronoi diagram generator. I was trying to see if I could get a speed boost from writing pixel values directly to the video RAM, but regardless the fill walking through all the pixels is still very slow. Any ideas on how I could speed things up?

--voronoi diagram
--by hypothete
points={}

function makepoints()
    for i=1,16 do
        e=rnd(128)
        f=rnd(128)
        add(points,{
            x=e,
            y=f,
            c=rnd(255)
        })
    end
end

function jitter()
    for i=1,#points do
        p=points[i]
        p.x+=rnd(2)-1
        p.y+=rnd(2)-1
    end
end

function near(pts,b)
    nt=nil --nearest pt
    nd=4096--dist to nt
    for i=1,#pts do
        a=pts[i]
        nl=(b.x-a.x)^2 + (b.y-a.y)^2
        --dist leaving off sqrt
        if(nl<nd)then
            nd=nl
            nt=a
        end
    end
    return nt
end

function drawvoro()
    for i=0,63 do
        for j=0,127 do
            k=i+64*j --x+y*w = 1d position
            z={x=i*2,y=j}
            np=near(points,z)
            if(np) then
                memset(0x6000+k,np.c,0x1)
            end
        end
    end
end

function _init()
    makepoints()
    drawvoro()
end

function _update()
    if(btnp(5)) then
        jitter()
        drawvoro()
    end
end
P#28059 2016-09-05 19:57 ( Edited 2016-09-07 04:34)

This is a simple simulation of Bracewell probes, AI-guided spacecraft that explore star clusters, looking for life and intelligence. Most of what I experimented with in this cartridge was depth-based sorting for drawing and hacky 3D projection techniques.

P#28019 2016-09-04 13:27 ( Edited 2016-09-10 21:57)

Hi all, this is my unfinished Ludum Dare 36 submission (http://ludumdare.com/compo/ludum-dare-36/?uid=20847). I started building the game with the day/night system and text menus; by the time I was 40 hours in I realized that I hadn't found the game mechanic and decided to call it quits. Still learned a ton, though.

Quick shout out to geckojsc for the lua coroutine dialog system tutorial: https://www.lexaloffle.com/bbs/?tid=3833 I used a lot of the work here with a few tweaks to build the textboxes and in-game menu. One issue I'd like to address in the future is a more terse way of setting up actors and conditional scripts. I feel like when Pico-8 cartridges reach a length of ~1000 chars or so, things start to get really messy in terms of source code organization. Additionally, there were a few functions that I had trouble "hoisting" and I couldn't figure out why. If anyone has pointers on how to simplify the data structures I'm using or specifically better use of tables, please let me know. Thanks for taking a look!

P#27581 2016-08-28 17:56 ( Edited 2016-08-30 16:21)

Follow Lexaloffle:        
Generated 2021-07-27 20:34:49 | 0.087s | Q:19