A year of Pico-8 sketches

Sphere

A WIP version of Sphere. One of my favorites sketches.[^1]

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]

Best of 9

A small selection of the year's sketches.

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

3D wave

The last sketch of year, only touched up a bit today

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)()