A year of Pico-8 sketches
Hello everyone and happy new year! 2017 has been a hectic year, yet during this year, I got a few good things, such as finally getting a job in gamedev and getting inspired to make Pico-8 sketches.
I’m not going to introduce again (beware, french inside) that little fantasy console, but those last months, it got a few updates which sparked a new interest in me to write down some small carts for it.
After storing them in a folder I would regulary update with the latest sketch, I wondered what to do with them after a while. Only sharing them via GIFs on social networks is fine, but I also wanted to have them available to everyone to inspire themselves do better than me (that should be easy, that said, people like Rez or [Trasevol_Dog][traseveol] do miracles on the same platform!)
So, after zipping the sketch folder up and uploading, here are my Pico-8 sketches of the year 2017 : [link]
They’re licenced under Creative Commons Attribution-NonCommercial-ShareAlike 4.0, which means as long as you mention me (and the other people that did some of the routines I used such as electricGryphon) and don’t use them in commercial stuff, you’re allowed (and encouraged) to share and remix under the same licence.
To make stuff a bit easier for you, I’ll provide in the bottom of this post the source for the matrix and vector libraries I did over the year to allow me to easily make 3D scenes. I haven’t documented it yet, but it should get easy to do work with it. Have a look at how I used it through sketches to see how it’s used (mostly vec()
and mat()
calls with some vector/matrix maths.). Note that I created some utility functions like mat.scale
to easily create transformation matrices. If you have basic knowledge about the 3D projection process, you should be fine! :D
Anyway, I sure had fun making all those sketches, I hope I’ll be able to top this and make a better batch this year and why not?- a few bigger projects! Have a nice day and, again, a happy new year! See ya!
Link to 2017’s archive : [link]
As promised, here’s the matrix/vector library, released as CC0, designed for Pico-8.
-- vec3 and matrix44 library
-- Released as CC0 (https://creativecommons.org/publicdomain/zero/1.0/)
-- Adding a mention would be nice but not needed. o/
------------
-- vector --
------------
local vec = (function()
local vec_mt = {}
local function new(x,y,z)
local vec={t="vec",x=x,y=y,z=z,
str=function(v)
return "("..v.x..","..v.y..","..v.z..")"
end,
dot=function(v,v2)
return v.x*v2.x + v.y*v2.y + v.z*v2.z
end,
lensq=function(v)
return (v.x*v.x) + (v.y*v.y) + (v.z*v.z)
end,
len=function(v)
return sqrt(v:lensq())
end,
norm=function(v)
local vmax = v
return vmax/vmax:len()
end
}
setmetatable(vec,vec_mt)
return vec
end
vec_mt = {
__add = function(v,o)
if type(o) == "number" then
return new(v.x+o,v.y+o,v.z+o)
end
return new(v.x+o.x,v.y+o.y,v.z+o.z)
end,
__sub = function(v,o)
if type(o) == "number" then
return new(v.x-o,v.y-o,v.z-o)
end
return new(v.x-o.x,v.y-o.y,v.z-o.z)
end,
__mul = function(v,s)
return new(v.x*s,v.y*s,v.z*s)
end,
__div = function(v,s)
return new(v.x/s,v.y/s,v.z/s)
end,
}
local unit_x = new(1,0,0)
local unit_y = new(0,1,0)
local unit_z = new(0,0,1)
local zero = new(0,0,0)
return setmetatable({
new=new,
z=zero,
ux=unit_x,
uy=unit_y,
uz=unit_z
},{__call=function(_,x,y,z) return new(x,y,z) end})
end)()
----------------------
-- matrix (m[y][x]) --
----------------------
local mat = (function()
local new = nil
local mat_mt = {}
-- v[y][x]
local function mat_each(lmbda)
local a = {}
for y=1,4 do
a[y] = {}
for x=1,4 do
a[y][x] = lmbda(x,y)
end
end
return a
end
local function mat_i()
return new({
{1,0,0,0},
{0,1,0,0},
{0,0,1,0},
{0,0,0,1}})
end
local function mat_z()
return new({
{0,0,0,0},
{0,0,0,0},
{0,0,0,0},
{0,0,0,0}})
end
local function mat_det(m)
return (
m[1][1]*m[2][2]*m[3][3]*m[4][4] + m[1][1]*m[2][3]*m[3][4]*m[4][2] + m[1][1]*m[2][4]*m[3][2]*m[4][3]
+ m[1][2]*m[2][1]*m[3][4]*m[4][3] + m[1][2]*m[2][3]*m[3][1]*m[4][4] + m[1][2]*m[2][4]*m[3][3]*m[4][1]
+ m[1][3]*m[2][1]*m[3][2]*m[4][4] + m[1][3]*m[2][2]*m[3][4]*m[4][1] + m[1][3]*m[2][4]*m[3][1]*m[4][2]
+ m[1][4]*m[2][1]*m[3][3]*m[4][2] + m[1][4]*m[2][2]*m[3][1]*m[4][3] + m[1][4]*m[2][3]*m[3][2]*m[4][1]
- m[1][1]*m[2][2]*m[3][4]*m[4][3] - m[1][1]*m[2][3]*m[3][2]*m[4][4] - m[1][1]*m[2][4]*m[3][3]*m[4][2]
- m[1][2]*m[2][1]*m[3][3]*m[4][4] - m[1][2]*m[2][3]*m[3][4]*m[4][1] - m[1][2]*m[2][4]*m[3][1]*m[4][3]
- m[1][3]*m[2][1]*m[3][4]*m[4][2] - m[1][3]*m[2][2]*m[3][1]*m[4][4] - m[1][3]*m[2][4]*m[3][2]*m[4][1]
- m[1][4]*m[2][1]*m[3][2]*m[4][3] - m[1][4]*m[2][2]*m[3][3]*m[4][1] - m[1][4]*m[2][3]*m[3][1]*m[4][2])
end
local function mat_inv(m)
local d = m:det()
if d == 0 then return m end
local o = mat_i()
local m11,m12,m13,m14=m[1][1],m[1][2],m[1][3],m[1][4]
local m21,m22,m23,m24=m[2][1],m[2][2],m[2][3],m[2][4]
local m31,m32,m33,m34=m[3][1],m[3][2],m[3][3],m[3][4]
local m41,m42,m43,m44=m[4][1],m[4][2],m[4][3],m[4][4]
o[1][1] = (m22*m33*m44 + m23*m34*m42 + m24*m32*m43 - m22*m34*m43 - m23*m32*m44 - m24*m33*m42)
o[1][2] = (m12*m34*m43 + m13*m32*m44 + m14*m33*m42 - m12*m33*m44 - m13*m34*m42 - m14*m32*m43)
o[1][3] = (m12*m23*m44 + m13*m24*m42 + m14*m22*m43 - m12*m24*m43 - m13*m22*m44 - m14*m23*m42)
o[1][4] = (m12*m24*m33 + m13*m22*m34 + m14*m23*m32 - m12*m23*m34 - m13*m24*m32 - m14*m22*m33)
o[2][1] = (m21*m34*m43 + m23*m31*m44 + m24*m33*m41 - m21*m33*m44 - m23*m34*m41 - m24*m31*m43)
o[2][2] = (m11*m33*m44 + m13*m34*m41 + m14*m31*m43 - m11*m34*m43 - m13*m31*m44 - m14*m33*m41)
o[2][3] = (m11*m24*m43 + m13*m21*m44 + m14*m23*m41 - m11*m23*m44 - m13*m24*m41 - m14*m21*m43)
o[2][4] = (m11*m23*m34 + m13*m24*m31 + m14*m21*m33 - m11*m24*m33 - m13*m21*m34 - m14*m23*m31)
o[3][1] = (m21*m32*m44 + m22*m34*m41 + m24*m31*m42 - m21*m34*m42 - m22*m31*m44 - m24*m32*m41)
o[3][2] = (m11*m34*m42 + m12*m31*m44 + m14*m32*m41 - m11*m32*m44 - m12*m34*m41 - m14*m31*m42)
o[3][3] = (m11*m22*m44 + m12*m24*m41 + m14*m21*m42 - m11*m24*m42 - m12*m21*m44 - m14*m22*m41)
o[3][4] = (m11*m24*m32 + m12*m21*m34 + m14*m22*m31 - m11*m22*m34 - m12*m24*m31 - m14*m21*m32)
o[4][1] = (m21*m33*m42 + m22*m31*m43 + m23*m32*m41 - m21*m32*m43 - m22*m33*m41 - m23*m31*m42)
o[4][2] = (m11*m32*m43 + m12*m33*m41 + m13*m31*m42 - m11*m33*m42 - m12*m31*m43 - m13*m32*m41)
o[4][3] = (m11*m23*m42 + m12*m21*m43 + m13*m22*m41 - m11*m22*m43 - m12*m23*m41 - m13*m21*m42)
o[4][4] = (m11*m22*m33 + m12*m23*m31 + m13*m21*m32 - m11*m23*m32 - m12*m21*m33 - m13*m22*m31)
return o/d
end
local function mat_mul_vec(m,v,res)
local function slice(m,v,y)
return m[y][1]*v.x+m[y][2]*v.y+m[y][3]*v.z+m[y][4]*1
end
local vr = res or vec(0,0,0)
vr.x = slice(m,v,1)
vr.y = slice(m,v,2)
vr.z = slice(m,v,3)
return vr,slice(m,v,4)
end
local function mat_mul(m,m2)
local function mult(m,m2,x,y)
local acc = 0
for i=1,4 do
acc = acc+m[y][i]*m2[i][x]
end
return acc
end
local a = mat_z()
for y=1,4 do
a[y]={}
for x=1,4 do
a[y][x] = mult(m,m2,x,y)
end
end
return a
end
local function mat_scale(sx,sy,sz)
local m = mat_i()
m[1][1]=sx
m[2][2]=sy
m[3][3]=sz
return m
end
local function mat_trns(tx,ty,tz)
local m = mat_i()
m[1][4]=tx
m[2][4]=ty
m[3][4]=tz
return m
end
local function mat_rot(ax,ay,az)
local a = cos(ax)
local b = sin(ax)
local c = cos(ay)
local d = sin(ay)
local e = cos(az)
local f = sin(az)
local ad = a*d
local bd = b*d
local m = mat_z()
m[1][1] = c*e
m[1][2] = -c*f
m[1][3] = d
m[2][1] = bd*e+a*f
m[2][2] = -bd*f+a*e
m[2][3] = -b*c
m[3][1] = -ad*e+b*f
m[3][2] = ad*f+b*e
m[3][3] = a*c
m[4][4] = 1
return m
end
local function mat_proj(nr,fr, fov)
-- /180 because converting degrees to pico
local a = fov and (fov/360)/2
--local t = sin(a)/cos(a) s= 1/t
local s = fov and cos(a)/sin(a) or 1
local m = mat_z()
m[1][1],m[2][2] = s,s
m[3][3]=-(fr+nr)/(fr-nr)
m[3][4]=-(fr*nr)/(fr-nr)
m[4][3]=-1
return m
end
mat_mt = {
__add = function(m,m2)
return new(mat_each(function(x,y) return m[y][x]+m2[y][x] end))
end,
__sub = function(m,m2)
return new(mat_each(function(x,y) return m[y][x]-m2[y][x] end))
end,
__mul = function(m,o)
local t = type(o)
if t == "number" then
return new(mat_each(function(x,y) return m[y][x]*o end))
elseif t == "table" then
if o.t == "mat" then
return mat_mul(m,o)
elseif o.t == "vec" then
return mat_mul_vec(m,o)
end
end
flip()
return m
end,
__div = function(m,o)
local t = type(o)
if t == "number" then
return new(mat_each(function(x,y) return m[y][x]/o end))
end
return m
end
}
new = function(arr)
arr.det=mat_det
arr.inv=mat_inv
arr.t="mat"
arr.str = function(m)
local s = "["
for y=1,4 do
s = s..m[y][1]
for x=2,4 do
s = s.." "..m[y][x]
end
if y<4 then s = s.."\n" end
end
s = s.."]"
return s
end
setmetatable(arr, mat_mt)
return arr
end
return setmetatable({
new=new,
i=mat_i,
z=mat_z,
trans=mat_trns,
rot=mat_rot,
scale=mat_scale,
proj=mat_proj;
mul_vec=mat_mul_vec
},{__call=function(t,arr) return new(arr) end})
end)()