PICO-8
Screen Shake Demo
Follow along to learn how to control a screen shake effect!
In making this demo, we learn about controlling the camera.
This lesson focuses on VISUAL EFFECTS!
Challenges!
After following the lesson, take on some of these challenges to test your knowledge and skills!
1. Successfully implement this shake()
function into your own game.
2. Set different shake strengths in your game. For example: bigger collisions, bigger shakes.
3. Change the effect to only shake from left to right.
How to Shake the Screen Effect!
[ Video Coming Soon! ]
Explanation of Code!
function _init() --screen shake variables intensity = 0 shake_control = 5 end
As usual, we set the variables inside of the main
_init()
function, or if you are using multiple game states such as a main menu, game play, game over, etc. then you should put these variables inside of the init function for the state that will use this shake effect function.
There are only 2 variables that we decided to create outside of the shake effect function. Only one is necessary, but you could make more to have more control at customizing different types of shake effects within your game while still using the single shake function below.
intensity
= a number used for the current amount the screen will shake. It will always decrease back to zero (no shake).shake_control
= a number used for the starting shake intensity that will be added to intensity to begin the effect. This number can be used to adjust the strength of the shaking when you trigger the intensity.The necessary global variable (outside of the shake function) is
intensity
, however, you could create more than oneshake_control
variable for different strength shakes. Or you could simply add a number directly tointensity
without the use of extra variables.
function shake()
local shake_x=rnd(intensity) - (intensity /2)
local shake_y=rnd(intensity) - (intensity /2)
--offset the camera
camera( shake_x, shake_y )
--ease shake and return to normal
intensity *= .9
if intensity < .3 then intensity = 0 end
end
function shake()
= creates a custom function that can be called to run.
We begin by creating two local variables to be used only inside of this function.
shake_x
and shake_y
will be used to offset the camera by a certain amount in random directions.
rnd( intensity ) = will find a random number between 0 and the intensity number.
- (intensity/2) = will adjust the range of the random number to be positive or negative.
So we begin this function by setting an X and Y variables to be some number between half intensity in the negative, and half the intensity in the positive. We want the possibility of negative numbers because a negative X will move the camera left, and a negative Y will move the camera upwards. So allowing for a random positive and negative number, allows the camera to move in all 4 directions.
Next we set the camera to those offset X and Y variables.
camera( shake_x, shake_y )
= give camera a new position using the changing variables to cause the shaking look.
If you are adjusting the camera in your game already, for example to follow the player on the map (let's say using global cam_x and cam_y variables), then you can also add a shake like this:
camera( cam_x+shake_x , cam_y+shake_y )
Lastly, this function eases the shaking intensity back down to zero (no shake).
intensity *= .9
= multiplying by a fraction cuts back the intensity number by a certain percentage every time.
You could play around with this number (.9
) to change how long it takes the shaking to stop.
Lower the number to make the shaking stop faster. Raise the number to make the shaking last longer. Be careful, if you set it to 1 or more, the shaking will get stronger and never stop. So this number must be a decimal between 0 and 1.
The easing gets slower and slower the closer the intensity gets to zero, so we need to help it get there when it is close enough. We decided that .3 was close enough. So we check if the intensity is less than that and if so, then we force intensity back to zero.
if intensity < .3 then intensity = 0 end
This is the example code you'll want to use somewhere in your game update. We have removed the unnecessary code, that is specific to how we set up the demo.
function _update()
--run shake when intensity high
if intensity > 0 then shake() end
--up, increase shake
...
--down, decrease shake
...
--x, trigger shake
if btnp(❎) then intensity += shake_control end
--change face based on shake intensity
eye_size = 7+intensity/2
mouth_size = 2+intensity/2
end
The first thing you'll want to put in your update function is the
constant running of the shake()
function.
However we chose to only run the function if intensity
is activated.
if intensity > 0 then shake() end
= checks if intensity is more than zero, and runs the shake function.
You could remove the check and simply write shake()
because when intensity is zero, the screen will not shake anyway.
We skip over how we decided to demo a control of the shake strength with the up and down buttons.
So next let's look at how we trigger the shake. You may be surprised that we don't call the function to trigger it,
the function should already be running, or ready to run depending on the intensity
variable.
intensity += shake_control
= increases the intensity by a certain strength to trigger the shaking effect.
We chose to animate the eyes and mouth of our face in the demo to demonstrate how you could control objects in your game to react to the amount of shaking that you trigger.
eye_size = 7+intensity/2
Let's write that in a more generic way that you could apply to your game:
variable = default_number + intensity/2
So take whatever variable from the game object that you want to change. In this demo, we took the size of the eyes and mouth. Then we set it to it's default or minimum size and then add half of the intensity.
You could play around with the math completely. Subtracting would make the default number a maximum and shaking would make the eyes and mouth smaller. Or use the full intensity amount to make larger changes to your game object that is reacting with the shake. This is just an example, nothing is strict.
Just shaking the screen is cool, but some linked visual feedback to the shaking will really add something special to the gameplay, so get creative!
This is the example code you'll want to use somewhere in your draw function. We have removed the unnecessary code, that is specific to how we set up the demo, such as the function used to draw the Nerdy Teacher face and the on screen controls information.
function _draw()
cls( 12 )
circfill( 63, 63, 40, 6)
--below unaffected by shake
--after we reset the camera
camera()
--show demo controls
...
end
cls( 12 )
= clear the game screen and set the entire screen color to light blue (#12).
circfill( x, y, radius, color)
= draws a sprite at X and Y coordinates on the screen.
camera()
= resets the camera position to 0 X and 0 Y.
Anything you draw after resetting the camera will not be affected by the shake effect. However, be careful if your game adjusts the camera to follow the player around the map for example, because you will want to "reset" the camera to its current position rather than resetting it completely back to 0 X and 0 Y.
For example, let's say you are adjusting the camera normally using these variables, cam_x and cam_y, then you should reset the camera using only those same variables and not the shake variables:
camera( cam_x, cam_y )
We won't explain how we printed the demo controls to the screen, but if you play the demo, you will see an example of keeping some things fixed in position and not shaking, while others are shaking, by just drawing them after resetting the camera.
This code has been simplified from the demo so it's easier to copy paste into your own game, without the unnecessary draw code. If you do want that, it is still in the demo cart .png above.
--screen shake demo
--by nerdy teachers
function _init()
--screen shake variables
intensity = 0
shake_control = 5
end
function _update()
--run shake when intensity high
if intensity > 0 then shake() end
--up, increase shake
if btnp(⬆️)
and shake_control < 10 then
shake_control += 1
end
--down, decrease shake
if btnp(⬇️)
and shake_control > 0 then
shake_control -= 1
end
--x, trigger shake
if btnp(❎) then intensity += shake_control end
--change face based on shake intensity
eye_size = 7+intensity/2
mouth_size = 2+intensity/2
end
function _draw()
cls(12)
circfill( 63, 63, 40, 6)
--below unaffected by shake
--after we reset the camera
camera()
--show demo controls
print("intensity",2,2,7)
print(intensity,10,9,7)
print("shake",47,2,0)
print("❎",53,9,0)
print("shake_control",75,2,7)
print("⬆️/⬇️ = "..shake_control,85,9, 7)
end
function shake()
local shake_x=rnd(intensity) - (intensity /2)
local shake_y=rnd(intensity) - (intensity /2)
--offset the camera
camera( shake_x, shake_y )
--ease shake and return to normal
intensity *= .9
if intensity < .3 then intensity = 0 end
end
font