Hyperspace Intro Animation on Pico-8


Pico-8 HyperspaceAn in development game that is heavy on perspective and animation, needed a little something extra for it’s intro and cut scenes. The solution was to create a hyperspace star field effect with individual, animated pixels.

My first attempt at the effect was to start each pixel at the screens center and randomly animate the stars outward, the result was less than satisfactory, either the range of the animation was too narrow or it was erratic.

The solution was to at initialization, create two tables, one for Y and one for y with randomly generated  locations on the screen. Interestingly, to limit the resolution of the values in Pico8, we set the upper limit as a parameter of rnd(x) and subtract an amount to set the negative limit of the range, for example :

for i=1,stars do -- Generate the two co-ordinate tables used to store each stars x and y
	add(starx,((rnd(256)-128))) -- 256 - 128 gives us a resolution between positive 128 and negative 128 i.e. the size of our screen
	add(stary,((rnd(256)-128)))
end

The remainder of the _init() function comprises of mostly table and variable declarations. The other statement I would like to point out in the global var: a=0.0001. This tiny number is used reduce the larger random numbers in the X and Y tables to near zero, or in other words, the center of the screen. Using a multiplier later on, we’ll see how these small numbers are used animate out each star.

function _init()
	center = 64 -- Set the center of the screen, the starting point for each star
	stars = 200 -- Number of stars to be generated
	starx={} -- Create the x co-ordinates table for each star
	stary={} -- Create the x co-ordinates table for each star
	oldx = 0 -- Used to store x co-ordinates before they get animated
	oldy = 0 -- Used to store x co-ordinates before they get animated
	
	x_vol = 0 -- These two variables are used to accelerate the randomly created points for each star
	y_vol = 0
	
	
	a=0.0001 -- This itty bitty number basiclly reduces the large random x,y positions to near zero and then slowly brings them up to the full number
	
	for i=1,stars do -- Generate the two co-orindate tables used to store each stars x and y
		add(starx,((rnd(256)-128))) -- 256 - 128 gives us a resolution between positive 128 and negative 128 i.e. the size of our screen
		add(stary,((rnd(256)-128)))
	end
	
	star_array_x = {} -- Empty tables to populate with the final rendered pixel position
	star_array_y = {}
end

Animating the Stars

The last part of this particle animation cart is the gen_stars() function that is called by Pico-8’s _draw() function. Now we take the previously established  x_vol and y_vol variables and randomly increment them with the tiny “a” var.

x_vol+=rnd(3*a) -- Here's the magic for the star acceleration, an iterated tiny number that controls the speed of the stars
y_vol+=rnd(3*a)

X_vol and y_vol are used by used by the indexes in the position tables to produce a slightly varying starting point for each star but each position is very close 0, the starting point. As each starx[i] and stary[i] are incremented, the differences grow  and the stars start to separate.

But first, we store the original location of each coordinate in a holding var.

oldx = starx[i] -- Storing the original position of each star
oldy = stary[i]
		
star_array_x[i] = center + (starx[i] * x_vol) /2 -- Putting all the calculations together to write each stars x and y
star_array_y[i] = center + (stary[i] * y_vol) /2

Now we can put it altogether into the gen_stars() function. I added little secondary animation sequence using the stored original coordinates to simulate coming out of hyperspace.

function gen_stars() -- Called by _draw
	for i=1, stars do -- Start the star loop
		
		x_vol+=rnd(3*a) -- Here's the magic for the star acceleration, an iterated tiny number that controls the speed of the stars
		y_vol+=rnd(3*a)
		
		oldx = starx[i] -- Storing the original position of each star
		oldy = stary[i]
		
		star_array_x[i] = center + (starx[i] * x_vol) /2 -- Putting all the calculations together to write each stars x and y
		star_array_y[i] = center + (stary[i] * y_vol) /2

		-- Do the 2nd star wave when each a point off screen
		if(star_array_x[i]>128 or star_array_y[i]>128 or star_array_x[i] < 0 or star_array_y[i] < 0) then
			x_vol+=rnd(1*a)
			y_vol+=rnd(1*a)
			starx[i] = rnd(256)-128
			stary[i] = rnd(256)-128
			starx[i]=oldx 
			stary[i]=oldy 
			star_array_x[i] = center + (starx[i] * x_vol) / 15
			star_array_y[i] = center + (stary[i] * y_vol) / 15
		end
		
		pset(star_array_x[i], star_array_y[i] , 7) -- write the pixels!
	end	
end

The full cart is available over at Github, thanks for reading!

Leave a Reply

Your email address will not be published. Required fields are marked *