# Simple Rain in PICO-8

Hi there!
This is my first tutorial on PICO-8. Today we’re gonna make a simple rain particle system. I will not focus too much on token count but just show you how to make a particle system with a pool that can create a simple rain effect.

Let’s get started.

Start by entering the following. You probably already know this, but _INIT() is for game initialization, _DRAW() is the draw-loop and _UPDATE() is the update-loop.

We clear the screen to a black color at every frame. This is done by CLS(0).

Let’s get started on the particle system.

Create a new function called new_particle_system that takes in a count of elements as the max particles allowed at a time.

Inside the function we will create a local variable called _pool:

``_pool={}``

Next up we need to create a particle function. Go to a new tab or scroll down and write the following:

``````function new_particle()
local _x,_y=0,0
local _xspeed,_yspeed=0,0
local _done=true
end``````

This is the basics of the particle class, we have an y-speed an x-speed and two positions (x,y). Now let’s add a return statement below _done=true:

``````
function new_particle()
local _x,_y=0,0
local _xspeed,_yspeed=0,0
local _done=true
return {
launch=function(x,y,xspd,yspd)
if _done then
_x,_y,_xspeed,_yspeed,_done=x,y,xspd,yspd,false
return true
end
end,
update=function()
if (_done) return
_x+=_xspeed
_yspeed+=0.92
_y+=_yspeed
if _y>127 then
_done=true
end
end,
draw=function()
if (_done) return
line(_x,_y,_x+_xspeed,_y+_yspeed,7)
end
}
end``````

Above return an object with the following functions:
launch() – for launching the particle with x-position, y-position, x-speed and y-speed.
update() – for updating the position and the current speed of the particle.
draw() – for drawing the particle as a line with both speeds applied.

Let’s take a closer look at the functions:
launch starts by checking if _done is true. This means that we’re allowed to use the particle, so if that is the case we set all the variables to the inputs and set _done to false. We then return true. The return true will hopefully make sense later on.
update also starts by checking if _done and then we dismiss the function if that is the case. No reason to calculate anything if the particle isn’t supposed to show. After that we apply the _xspeed to _x and we apply gravity (0.92) to _yspeed. Then we check if the particle has left the screen (after 127 on y) and set _done to true if that is the case.
draw starts by dismissing if the particle is done. Else it will draw a line from _x,_y to _x+_xspeed, _y+_yspeed.

Cool! That’s all we need for the particle.

Let’s go to the particle system function and work some magic there.
Let’s initialize the particle pool by doing the following:

``````for i=1,maxparticles do
_pool[i]=new_particle()
end``````

LUA’s arrays starts at index 1 so that’s the reason why we do it from i=1 and not i=0.

Now that we have initialized the pool we can return the object with the following functions: rain(), update(), draw().

``````return {
rain=function()
end,
update=function()
end
draw=function()
end
}``````

The above code shows how return the object with functions declared inside. Now let’s fill out the blanks:

``````rain=function()
local rand=rnd(5)
for i=1,maxparticles do
if _pool[i].launch(rnd(127),-rand,0,rand) then
return
end
end
end``````

The rain function sets a random number between 0 and 5, loops through all particles and dismisses the function in case a particle’s launch function has been called. The call to launch randomly places the particle at an x-position inside the screen and above the screen by -rand (remember PICO-8’s coordinate system is top-left (0,0) to bottom-right (127,127)). We also set the x-speed to 0 and the y-speed to rand.

Now let’s create the update function, it’s pretty straight-forward:

``````update=function()
for i=1,maxparticles do
_pool[i].update()
end
end``````

The draw function is more or less the same except that we call draw instead of update:

``````for i=1,maxparticles do
_pool[i].draw()
end``````

And that’s it. Now let’s put it to use…

Go back to your main tab (or where you placed the initial functions and write the following:

``````function _init()
particlesys=new_particle_system(512)
end

function _draw()
cls(0)
particlesys.draw()
end

function _update()
particlesys.rain()
particlesys.update()
end``````

Go to the console and type in run and see it in action.

Next up is extending the particle systems with sparks!
{"ft_lang_label":"__label__en","ft_lang_prob":0.7547685,"math_prob":0.938119,"size":4350,"snap":"2022-27-2022-33","text_gpt3_token_len":1107,"char_repetition_ratio":0.16958122,"word_repetition_ratio":0.022955524,"special_character_ratio":0.25287357,"punctuation_ratio":0.11388286,"nsfw_num_words":0,"has_unicode_error":false,"math_prob_llama3":0.99437875,"pos_list":[0],"im_url_duplicate_count":[null],"WARC_HEADER":"{\"WARC-Type\":\"response\",\"WARC-Date\":\"2022-08-07T21:55:27Z\",\"WARC-Record-ID\":\"<urn:uuid:66861c31-978d-418d-aa5f-1d4e62c1c218>\",\"Content-Length\":\"23945\",\"Content-Type\":\"application/http; msgtype=response\",\"WARC-Warcinfo-ID\":\"<urn:uuid:78c8dea4-0d72-4dd1-b139-3b1b8b8fbb3e>\",\"WARC-Concurrent-To\":\"<urn:uuid:16b8267a-a161-406a-ba21-7a0bb6f7f43d>\",\"WARC-IP-Address\":\"46.30.213.53\",\"WARC-Target-URI\":\"http://lassehonnens.dk/simple-rain-in-pico-8/\",\"WARC-Payload-Digest\":\"sha1:VOU7342KGLNWGJYRZV5V6ULY6LOYGLSH\",\"WARC-Block-Digest\":\"sha1:POYT6ADV5NIRZCDAJENAJGARXD6DYEPS\",\"WARC-Identified-Payload-Type\":\"text/html\",\"warc_filename\":\"/cc_download/warc_2022/CC-MAIN-2022-33/CC-MAIN-2022-33_segments_1659882570730.59_warc_CC-MAIN-20220807211157-20220808001157-00115.warc.gz\"}"}