[Tutorial] Mini Game 04 -- Game Structure and Game States
Hello everyone!
For the past few weeks we have been building this mini game and exploring different functionalities within lens studio as well. Check out our past tutorials here!
[Tutorial] Mini Game 01 -- Infinite Instantiation, Timer, and Randomization
[Tutorial] Mini Game 02 -- Duplicate & Recycle Textures and Materials
[Tutorial] Mini Game 03 -- Game States, UI Scores, and Persistent Storage
We’ve covered a lot of the functionality aspect in the past few weeks, today we will be focusing on polishing the project structure and make it easier to tweak.
Clean up the Code
Before we move on to making some changes, it is best to clean up our project a little bit. It will save us lots of headaches later looking for the right files and functions.
In our scripts, we shall create functions for most ‘events’. Such as when a cookie is ‘hit’ by mouth. Instead of calling everything in Update, we can create an onHit() function and call onHit() in Update.
We’ll do so for any code snippets as we see fit. There is no correct answer for how to organize your code, but having a lot of clearly defined functions is always recommended.
For example, later if you have to add an extra function when the object is hit, you can just find the onHit() function instead of going through the whole update and locate where hit is happening. As your project grows bigger, keeping it clean would become more and more essential.
We should also clean up the folders and name most of our assets as clear as possible. I’ll also change the script name of ObjectSpawner to Manager. Since at this point it does not only contain functions as a prefab spawner but also overall game states.
Take a look at the project at the bottom of this article to see in detail how the project has been refactored!
Game States
Game state is a very useful concept to use in order to keep our game logic clear and precise. It means that we call everything that needs to be changed when switching game state in one place. This is especially useful if you want the user to be able to play your game more than once because you can set up your reset logic here! We now have 3 different game states:
Before Game -- before the game starts. No stats should be on the screen but the ‘START’ button and START screen.
During Game-- after player press ‘START’ button, cookies start falling, ‘START’ screen disappears, and score number UI screen shows up.
End Game-- cookies don’t drop anymore, score number UI screen stays and ‘GAME OVER’ screen shows up with a restart button.
We should put our UI elements in 3 different Screen Transform objects and name them accordingly.
Then in our Update function in the Manager script, we’ll create a few variables for our SceneObject and game state:
//game state related
//@input SceneObject StartScreen
//@input SceneObject ScoreScreen
//@input SceneObject EndScreen
//0--BeforeGameStart 1--DuringGame 2--GameEnded
var gameState = 0;
Then we’ll create a function setState():
function setState(gameStateInt){
switch(gameStateInt){
case 0://before game start
script.StartScreen.enabled = true;
script.ScoreScreen.enabled = false;
script.EndScreen.enabled = false;
break;
case 1://during game
script.StartScreen.enabled = false;
script.ScoreScreen.enabled = true;
script.EndScreen.enabled = false;
break;
case 2://after game ended
script.StartScreen.enabled = false;
script.ScoreScreen.enabled = false;
script.EndScreen.enabled = true;
break;
}
}
Don’t forget to drag the corresponding SceneObjects into the slots from Inspector. Another thing to not forget is to delete everything else that is referring to similar objects. From our last project we have a GameOverScreen variable that gets turned on when the game ends, and a StartButton variable to disable when game starts, let’s delete them both.
We’ll remove our startGame() function earlier as well, and add these 2 new functions:
function onGameStart(){
startgame = true;
setState(1);
currentScore = 0;
missedScore = 0;
}
function onGameEnd(){
startgame = false;
setState(2);
}
We’ll call onGameStart() with Behavior as we did before:
global.behaviorSystem.addCustomTriggerResponse("START_GAME", onGameStart);
And we’ll call onGameEnd() in Update where missedScore is bigger than missedScoreMax:
if(missedScore >= missedScoreMax){
onGameEnd();
}
In the beginning of our script we’ll just put:
setState(0);
We’ll copy pasted the Behavior script in our Behavior object and replace TouchTarget with RestartButton instead. So now both StartButton and RestartButton will trigger onGameStart() function, which will set game state to 1 and start the game.
One last thing we need is to clear all the cookies when the game is over. We will do so by creating an array spawnedObjects, we add each cookie to the array when they are created, then destroy them from the array when game is over:
var spawnedObjects = [];
function spawnObject(){
//creating a copy of the prefab
var newObj = script.objectPrefab.instantiate(script.getSceneObject().getParent());
spawnedObjects.push(newObj);
…....
}
function clearSpawnedObjects(){
for(i=0; i < spawnedObjects.length; i ++){
spawnedObjects[i].destroy();
}
spawnedObjects = [];
}
function onGameEnd(){
clearSpawnedObjects();
...
}
We also have functions that destroy the cookies in our ObjectPrefab script from earlier. Let’s change them from .destroy() to .enabled = false, otherwise we’ll get an error (since we are trying to destroy an object that is already destroyed)
Check for Face
We also need to stop cookies from 'being hit' if there is no face in the scene. To do so we can add the Head component to the ObjectPrefab script on our Object Prefab.
//@input Component.Head headTracking
And we'll input our Head Binding object in scene to this slot on the inspector of our Object Prefab. Then hit 'Apply' on the prefab.
Then above the if statement that checks for the onHit() function, we'll add another check to only allow the if statement to run if there is a face in the scene:
if((distanceFromMouth < script.objectSpawner.api.getThreshold()) && !isHit
&& (script.headTracking.getFacesCount() > 0 )){
onHit();
}
Conclusion
In this tutorial we’ve learned some practices for keeping our project organized by creating functions and game states. We’ve also renamed our folders and cleaned up our resources. We created a restart button so our game loops itself.
Next week we will focus on refurbishing the art style for the game, fun stuff ahead!
Leave a comment if you have any questions or a cool project to share, stay tuned :)
--------
Download the finished project HERE!
amazing! cant wait ! thanks Nico S for the awesome work
I couldn't stop my self to try this! I made this candy theme hope you like it :)
Wow! Nice work Hamad! Love the helmet :)
Hey Jonathan Solichin
Glad you enjoyed it :)
Please do check my banana with dog head foot tracking lens i bet you will like it to
https://support.lensstudio.snapchat.com/hc/en-us/community/posts/360072218571-Banana-with-dog-head
very wonderful
thanks Nico S for the awesome work
I made this ice cream theme hope you like it
Hi Maha and Wolf
Such beautiful work from both of you! Keep up the good work ^_^
Thank you so much for superb explanation. Is it also good for below link?
https://support.lensstudio.snapchat.com/hc/en-us/community/posts/4408768212628-Squid-Games-Lens-epicapks