Genuary 2023 Day 9 - Plants

January 09, 2023
pico-8 open-source
Genuary 2023 Day 9 - Plants
-- genuary #9 2023
-- plants
-- by carson kompon

-- credits: https://www.lexaloffle.com/bbs/?pid=80095
function linefill(ax,ay,bx,by,r,c)
	if(c) color(c)
	local dx,dy=bx-ax,by-ay
	-- avoid overflow
	-- credits: https://www.lexaloffle.com/bbs/?tid=28999
	local d=max(abs(dx),abs(dy))
	local n=min(abs(dx),abs(dy))/d
	d*=sqrt(n*n+1)
	if(d<0.001) return
	local ca,sa=dx/d,-dy/d
	-- polygon points
	local s={
		{0,-r},{d,-r},{d,r},{0,r}
	}
	local u,v,spans=s[4][1],s[4][2],{}
	local x0,y0=ax+u*ca+v*sa,ay-u*sa+v*ca
	for i=1,4 do
		local u,v=s[i][1],s[i][2]
		local x1,y1=ax+u*ca+v*sa,ay-u*sa+v*ca
		local _x1,_y1=x1,y1
		if(y0>y1) x0,y0,x1,y1=x1,y1,x0,y0
		local dx=(x1-x0)/(y1-y0)
		if(y0<0) x0-=y0*dx y0=-1
		local cy0=y0\1+1
		-- sub-pix shift
		x0+=(cy0-y0)*dx
		for y=y0\1+1,min(y1\1,127) do
			-- open span?
			local span=spans[y]
			if span then
				rectfill(x0,y,span,y)
			else
				spans[y]=x0
			end
			x0+=dx
		end
		x0,y0=_x1,_y1
	end
end

function plot_stem(x,y)
	add(stem,{
		x=x,y=y
	})
end

function get_bloom_pos()
	i=#stem
	bx=stem[i].x+sin(t()/4+i/8)*2
	by=stem[i].y+cos(t()/3+i/8)*2
	return bx,by
end

cls()

seed={x=63,y=0,c=2,spd=0,growing=false}
stem={}
pedals={}
blooming=false
bloom=0
growthy=120

pal({[0]=0,3,4,8,129,1,140,12,7},1)

cls(5)
::_::
	
	for i=1,999 do
		xx=rnd(128)
		yy=rnd(128)
		c=7.5-yy/32
		circfill(xx,yy,1,c)
	end
	circfill(63,999,900,1)
	
	if not seed.growing then
		seed.spd+=0.1
		seed.y+=seed.spd
		circfill(seed.x,seed.y,1,seed.c)
		if seed.y >= 100 then
			seed.growing=true
			growthy=seed.y
		end
	else
		if not blooming then
			growthy-=1
			if flr(growthy)%4==0 then
				plot_stem(seed.x+sin(t()/2)*4,growthy)
			end
			if(growthy<=40) blooming=true
		else
			
		end
	end
	
	for i=1,#stem do
		x1=stem[i].x
		y1=stem[i].y
		x2=x1
		y2=y1
		if i<#stem then
			x2=stem[i+1].x
			y2=stem[i+1].y
		elseif not blooming then
			x2=seed.x+sin(t()/2)*4
			y2=growthy
		end
		x1+=sin(t()/4+i/8)*2
		y1+=cos(t()/3+i/8)*2
		x2+=sin(t()/4+(i+1)/8)*2
		y2+=cos(t()/3+(i+1)/8)*2
		linefill(x1,y1,x2,y2,1,1)
	end
	
	if blooming then
		if bloom < 5 then
			bloom+=.2
			if bloom >= 5 then
				for i=1,8 do
					bx,by=get_bloom_pos()
					add(pedals,{
						x=0,y=0,
						dir=i/8,
						dots={},
						l=0,
						update=function(self)
							if(#self.dots<16 and self.l%6==0)self:plot()
							self.l+=1
							self.x+=cos(self.dir)*.5
							self.y+=sin(self.dir)*.5
							self.dir+=.008
							bx,by=get_bloom_pos()
							for i=1,#self.dots do
								x1=bx+self.dots[i].x
								y1=by+self.dots[i].y
								x2=x1
								y2=y1
								if i<#self.dots then
									x2=bx+self.dots[i+1].x
									y2=by+self.dots[i+1].y
								end
								x1+=sin(t()/4+i/8)
								y1+=cos(t()/3+i/8)
								x2+=sin(t()/4+(i+1)/8)
								y2+=cos(t()/3+(i+1)/8)
								linefill(x1,y1,x2,y2,1,14)
							end
						end,
						plot=function(self)
							add(self.dots,{
								x=self.x,
								y=self.y
							})
						end
					})
				end
			end
		else
			for p in all(pedals) do
				p:update()
			end
		end
		bx,by=get_bloom_pos()
		circfill(bx,by,bloom,2)
	end
	
	flip()
goto _