Genuary 2023 Day 13 - Something you've always wanted to learn

January 13, 2023
pico-8 open-source
Genuary 2023 Day 13 - Something you've always wanted to learn
-- genuary #13 2023
-- something you've always wanted to learn
-- by carson kompon
-- resource: https://datagenetics.com/blog/july22018
points={}
col=1.1
drag=0.999
grav=0
objs={}

function create_obj(pts,c)
	obj={
		pts=pts,c=c,
		sticka={},stickb={},sticklen={}
	}
	ptlen=#pts
	if ptlen>1 then
		for i=1,ptlen do
			nxt=1+(i)%ptlen
			obj.sticka[i]=i
			obj.stickb[i]=nxt
			dx=pts[i].x-pts[nxt].x
			dy=pts[i].y-pts[nxt].y
			obj.sticklen[i]=sqrt((dx*dx)+(dy*dy))
		end
	end
	add(objs,obj)
end

function objs_update_points()
	for i=1,#objs do
		a=objs[i]
		for j=1,#a.pts do
			o=a.pts[j]
			vx=(o.x-o.xprev)*drag
			vy=(o.y-o.yprev)*drag
			mdx=mx-o.x
			mdy=my-o.y
			if ((mdx*mdx)+(mdy*mdy))<64 then
				vx+=(mx-lmx)/3
				vy+=(my-lmy)/3
			end
			o.xprev=o.x
			o.yprev=o.y
			o.x+=vx
			o.y+=vy
			o.y+=grav
		end
	end
end

function objs_constrain_points()
	for i=1,#objs do
		a=objs[i]
		for j=1,#a.pts do
			o=a.pts[j]
			if o.x>(128-o.r) then
				o.x=128-o.r
				o.xprev=o.x+(vx*col)
			elseif o.x<o.r then
				o.x=o.r
				o.xprev=o.x+(vx*col)
			end
			if o.y>(128-o.r) then
				o.y=128-o.r
				o.yprev=o.y+(vy*col)
			elseif o.y<o.r then
				o.y=o.r
				o.yprev=o.y+(vy*col)
			end
		end
	end
end

function objs_update_sticks()
	for i=1,#objs do
		a=objs[i]
		for j=1,#a.sticka do
			o=a.pts[a.sticka[j]]
			par=a.pts[a.stickb[j]]
			dx=o.x-par.x
			dy=o.y-par.y
			dist=sqrt((dx*dx)+(dy*dy))
			am=((dist-a.sticklen[j])/dist)/2
			o.x-=dx*am
			o.y-=dy*am
			par.x+=dx*am
			par.y+=dy*am
		end
	end
end

function objs_draw()
	for i=1,#objs do
		a=objs[i]
		if #a.pts > 1 then
			for j=1,#a.sticka do
				lx1=a.pts[a.sticka[j]].x
				ly1=a.pts[a.sticka[j]].y
				lx2=a.pts[a.stickb[j]].x
				ly2=a.pts[a.stickb[j]].y
				line(lx1,ly1,lx2,ly2,a.c)
			end
		end
		for j=1,#a.pts do
			o=a.pts[j]
			circfill(o.x,o.y,o.r,a.c)
		end
	end
end

function create_point(x,y,xprev,yprev)
	xprev=xprev or x+rnd(2)-1
	yprev=yprev or y+rnd(2)-1
	return {
		x=x,y=y,r=1.5,
		xprev=xprev,yprev=yprev,
	}
end

--[[
for i=1,20 do
	px=rnd(128)
	py=rnd(128)
	ppx=px+(rnd(2)-1)*5
	ppy=py+(rnd(2)-1)*5
	p=create_point(px,py,ppx,ppy)
	ang=rnd()
	dst=6+rnd()*16
	create_point(
		px+cos(ang)*dst,
		py+sin(ang)*dst,
		px,py,p
	)
end
]]--

poke(0x5f2d, 1)
lmx=stat(32)
lmy=stat(33)

for i=1,6 do
	pts={}
	basept=create_point(rnd(128),rnd(128))
	add(pts,basept)
	siz=2+rnd(2)\1
	for j=1,siz do
		add(pts,create_point(basept.x+rnd(64)-32,basept.y+rnd(64)-32))
	end
	create_obj(pts,i)
end

::_::
	cls()
	
	mx=stat(32)
	my=stat(33)
	mc=stat(34)
	
	objs_update_points()
	objs_constrain_points()
	objs_update_sticks()
	objs_draw()
	
	circfill(mx,my,1,7)
	
	lmx=mx
	lmy=my
	
	flip()
goto _