In the previous post we've made use of the HUD and now our game is basically done, but it's missing a few things. We need to add a game over screen with a way to restart the game. We also want to add a screen when you just started the game, instead of just starting the game right away.
Game States
We're going to add a few game states to our game. We're going to have a gameState enum that will hold the different states of the game. We'll also have a variable that holds the current state of the game.
Add the following code right at the beginning of your main.ts file:
enum gameStates {
"PLAYING",
"PAUSED",
"GAME_OVER"
}
let gameState = gameStates.PAUSED;
This code creates an enum called gameStates that holds the different states of the game. We then create a variable called gameState that holds the current state of the game. We set the initial state to PAUSED.
Before we do anything with these states, we need a reset function. This function will be called right before we start the game. Add the following code to the bottom of your main.ts file:
function resetGame() {
lives = 3;
level = 1;
score = 0;
setHudValue("gameLives", lives);
setHudValue("gameLevel", level);
setHudValue("gameScore", score);
Player.x = app.screen.width / 2 - Player.width / 2;
Player.y = app.screen.height - 50;
bullets.forEach(bullet => app.stage.removeChild(bullet));
enemies.forEach(enemy => app.stage.removeChild(enemy));
bullets.length = 0;
enemies.length = 0;
setEnemySpawnInterval();
spawnEnemy();
}
This will set all the values to their initial starting values, clear the bullets and enemies from the stage and the arrays, reset the player's position, and set the enemy spawn interval. Then start the game by spawning an enemy.
Now that that's set, let's add a way to start the game.
Starting the game
We're going to add a new KeyHandler for that. Add the following code right after where we defined the KeyHandler for the left and right arrow keys:
KeyHandler(
"Enter",
() => {
if(gameState !== gameStates.PLAYING) {
if(gameState === gameStates.GAME_OVER) {
resetGame();
}
gameState = gameStates.PLAYING;
togglePauseText();
}
}
);
This code will start the game when the player presses the Enter key. If the game is not in the PLAYING state, it will set the game state to PLAYING. If the game is in the GAME_OVER state, it will reset the game and then set the game state to PLAYING.
But the player wouldn't know this, so we need some text to tell the player what to do. Add the following code right after where we defined the KeyHandlers
// A simple text style, 24px white text
const textsStyle = {
fontSize: 24,
fill: 0xFFFFFF
};
let startGameText = new PIXI.Text({
text: 'Press enter to start the game',
style: textsStyle
});
startGameText.y = 250;
function togglePauseText() {
if(gameState === gameStates.PAUSED || gameState === gameStates.GAME_OVER) {
// Since the text can change, we need to reposition it.
startGameText.x = app.screen.width / 2 - startGameText.width / 2;
app.stage.addChild(startGameText);
} else {
app.stage.removeChild(startGameText);
}
}
togglePauseText();
This code creates a new text object that says "Press enter to start the game" and positions it in the middle of the screen. It then creates a function called togglePauseText that will show or hide the text based on the current game state. It then calls this function to show the text when the game is paused or over.
Now, we would also like to pause the game.
Pausing the game
Add the following code right after where we defined the KeyHandler for the left and right arrow keys:
KeyHandler(
"Escape",
() => {
if(gameState !== gameStates.PAUSED) {
gameState = gameStates.PAUSED;
startGameText.text = 'Press enter to resume the game';
togglePauseText();
}
}
);
In this code we'll set the gameState to PAUSED when the player presses the Escape key. We'll also reuse the startGameText object and set the text to "Press enter to resume the game".
Using the game states
Great, now that we can toggle between PLAYING and PAUSED states, let's actually use these states, and have the game act accordingly.
If we're not in the PLAYING state, we don't want to set the playerSpeed when the player presses the left or right arrow keys. Add the following code into the KeyHandlers where we set the playerSpeedX to 500 or -500 for the left and right arrow keys:
if (gameState !== gameStates.PLAYING) {
return;
}
Also add the above code into the handler for the spacebar KeyHandler, so that the player can't shoot when the game is paused or over.
Next, update the if statement in the spawnEnemy function to look like this:
if(!document.hasFocus() || gameState !== gameStates.PLAYING) {
return;
}
And finally, the whole game loop doesn't need to fire if we're paused, add the following code right at the beginning of the game loop:
if(gameState !== gameStates.PLAYING) {
return;
}
Game Over
Now that we have a way to start and pause the game, let's add a game over screen.
Where now we have a console.log("Game Over"), we want to set the game state to GAME_OVER and show a game over text. Replace the console.log with the following code:
gameState = gameStates.GAME_OVER;
startGameText.text = 'Press enter to restart the game';
scoreText.text = `Score: ${score}`;
scoreText.x = app.screen.width / 2 - scoreText.width / 2;
app.stage.addChild(gameOverText);
togglePauseText();
app.stage.addChild(scoreText);
This code is using two more text objects that we haven't created that yet, lets do that.
Right after where we created the startGameText object, add the following code:
let gameOverText = new PIXI.Text({
text: 'GAME OVER',
style: textsStyle
});
gameOverText.x = app.screen.width / 2 - gameOverText.width / 2;
gameOverText.y = 200;
let scoreText = new PIXI.Text({
text: 'Score: 0',
style: textsStyle
});
scoreText.y = 300;
Now, we should be able to play the game, pause it, and restart it when we lose.
Conclusion
And that's it! You can now play the game, pause it, and restart it when you lose.
I am aware that this last part might have been a bit overwhelming, but I hope you managed to follow along and understand everything, don't forget you can always check out the full source code. If you have any questions or feedback, feel free to reach out to me on X or leave a comment below
And this is the final part of this small series, I hope you enjoyed it and learned something new. A small thing I'd like to point out while leaving you with this, is that this is a very basic game, and there are many ways to improve it. You could add more enemies, power-ups, different levels, and so on. I encourage you to experiment and try new things, that's how you learn and grow as a developer.
Also, the way this game is structured is not the best way to structure a game, but for the purpose of this tutorial, I wanted to keep it simple and in one file. In a future tutorial, I might show you how to structure a game in a more scalable way.
Thank you for reading all the way through this tutorial!
Accomplish more with the "Cult of Done"
Mr. Linxed ・ May 2
Don't forget to sign up to my newsletter to be the first to know about tutorials similar to these.
Top comments (25)
Dans Space Defender - partie 5, les états du jeu jouent un rôle essentiel pour gérer les transitions entre le menu, le gameplay et la fin de partie. Chaque état contrôle les actions, les sons et les graphismes associés, garantissant une expérience fluide et cohérente pour le joueur. De la même manière, Jeux Chicken Road propose une approche immersive où chaque étape du jeu est soigneusement conçue pour offrir divertissement et défi. Cette gestion structurée rend les deux jeux captivants et techniquement bien réalisés pour tous les amateurs de jeux.
In Space Defender Part 5, game states play a crucial role in managing different phases like start, play, pause, and game over. These states ensure smooth transitions and consistent gameplay logic, keeping the player engaged. Properly structured states make debugging easier and enhance performance by isolating specific functions. Similarly, Mega888 offers a structured gaming experience with well-designed interfaces that maintain engagement and balance. Both emphasize the importance of clear logic and smooth user interaction to create an enjoyable and seamless experience for players across all stages.
DelttaExecutor introduces Delta Executor, a powerful tool created to run Roblox scripts with full cross-platform support and access to a wide library of options. It promises a smooth and free experience, which makes it attractive for both beginners and experienced Roblox players. Still, as with any third-party executor, it’s important for users to stay cautious and aware of possible risks before using it.
👉 Visit the official website for more details
Really enjoyed this tutorial, especially how you broke everything down step by step—it makes it less overwhelming for beginners. I like that you also encouraged experimenting with improvements like new levels or power-ups, because that’s exactly how developers grow. On a side note, when I need some inspiration or just want to relax, I usually play what I consider the Best Game ever
, and it always gives me fresh ideas for creativity. Thanks again for sharing this guide!
PGSharp download provides an easy way to enhance your Pokémon GO gameplay with advanced GPS spoofing features. The app offers a user-friendly interface and does not require root access, making installation simple for most Android users. Once downloaded, PGSharp enables features like joystick control, auto-walk, and teleportation. It allows players to catch region-specific Pokémon, visit distant PokéStops, and join global events without leaving home, making Pokémon GO more flexible and fun.
I’m currently on the lookout for a complete and trusted collection of SNES cheats. Games like Super Metroid, Donkey Kong Country, Chrono Trigger, and Super Mario World were a huge part of my childhood, and I’d love to revisit them with some classic cheat codes.
I found a good start at GameMite’s SNES retro game cheats section, the site’s layout is clean and easy to browse, but I’m wondering if anyone here has used it extensively or knows of other reliable sources.
I've been playing a lot of Golf Solitaire recently and realized I don’t really have a solid golf solitaire card game strategy. Most of the time I’m just making moves as they come without thinking ahead, and it’s starting to affect my win rate. I’m curious—do you follow any specific strategies when you play? Is it smarter to clear columns first, or focus on keeping more card options open? How do you handle tough spots when no moves are obvious?
Lucky 33 is an exciting online gaming platform offering a variety of casino-style games. With smooth gameplay and engaging features, it provides players with a fun and rewarding experience every time they play.
Space Defender - Bölüm 5: Oyun Durumları'nda, menü, savaş ve yükseltme ekranları arasındaki geçişleri yönetmek oyun deneyimi için kritiktir. Benzer şekilde, Brawl Stars PC'de sorunsuz geçişler oynanışı geliştirir. Brawl brawl stars indir bluestacks ile PC'de oynamak için buraya tıklayın!
GCAIMX, the Goldman Sachs Capital Growth Fund - Institutional Class, is a mutual fund focused on achieving long-term capital growth by investing in a diversified portfolio of U.S. growth stocks. The fund aims to invest in companies with high growth potential across various sectors and industries, making it a suitable option for investors seeking exposure to growth opportunities in the stock market. Managed by Goldman Sachs Asset Management, GCAIMX uses an active management strategy, meaning that the fund managers continuously monitor the market and adjust the portfolio to maximize returns. The fund is an ideal choice for investors with a long-term investment horizon and a tolerance for market volatility.
Some comments may only be visible to logged-in visitors. Sign in to view all comments.