Explore Free Casual Game Tutorials – GameDev Academy https://gamedevacademy.org Tutorials on Game Development, Unity, Phaser and HTML5 Fri, 07 Apr 2023 09:17:35 +0000 en-US hourly 1 https://wordpress.org/?v=6.1.1 https://gamedevacademy.org/wp-content/uploads/2015/09/cropped-GDA_logofinal_2015-h70-32x32.png Explore Free Casual Game Tutorials – GameDev Academy https://gamedevacademy.org 32 32 Free Course – Create Interactable Objects in Unreal Engine https://gamedevacademy.org/unreal-interactable-tutorial/ Fri, 10 Feb 2023 01:00:00 +0000 https://gamedevacademy.org/?p=19826 Read more]]>

Master stories and simple game interactions in Unreal Engine by making a single system applicable to multiple objects. You can also extend the material covered here by checking out the full course below!

CREATE A WALKING SIMULATOR IN UNREAL ENGINE

About

In this free tutorial, instructor Daniel Buckley will walk you through the beginning steps of creating interactable objects in the popular Unreal Engine. Using the Blueprints Visual Scripting system, you’ll learn how to create and set up a player that detects interactable objects made with the blueprints class and a custom event that initiates interaction. Regardless of your game project pursuits, these skills for building interactable objects will provide you with new ways to express yourself creatively and add interactions via the Blueprints Visual Scripting system!

New to Unreal?  Consider downloading our free Unreal Engine 101 course!

BUILD GAMES

FINAL DAYS: Unlock 250+ coding courses, guided learning paths, help from expert mentors, and more.

]]>
Best Puzzle Game Tutorials – Building Games to Test the Mind https://gamedevacademy.org/best-puzzle-game-tutorials/ Wed, 25 Jan 2023 09:41:48 +0000 https://gamedevacademy.org/?p=15510 Read more]]> Who’s not familiar with classic puzzle games like Tetris, Breakout, Snake, Minesweeper, Sudoku, or even recent ones such as Candy Crush and Baba Is You? Now imagine you coding your own version of these games. Wouldn’t that be awesome?

Regardless of where your skill levels lie, puzzle games are a great game genre to explore – not only are they a staple of games in general, but come with some unique coding challenges! In this article, we’re going to strive to showcase some of the best puzzle game tutorials available using famous game engines like Unity, Unreal Engine, and Godot.

Let’s dive into some tutorials on how to implement these puzzle games!

How to Make Minesweeper in Unity

Right off the bat, you’ll learn how to make a minesweeper using Unity with a very detailed approach. Unity is a real-time development platform for game creation, being also used for interactive simulations, animation, and even films.

In this tutorial by Zigurous, he walks you through the creation of the game board and cells using sprites, how to keep track of the state of the game and winning condition, besides all the logic needed for flagging and revealing the cells (with the number of neighboring mines or blank) plus displaying the bombs for those cells corresponding to the mines of the game. And just like that, you’ll have implemented one of the most classic games yourself!

Topics Covered:

  • Project creation
  • Importing sprites
  • Scene setup
  • Cells and game board
  • Flag, reveal, and mine exploding scripting
  • Win state

Duration: 1.5 hours of video training

Access now: How to Make Minesweeper in Unity

Make a Brick Breaker Game in Unity

Based on the Breakout game, this tutorial by Imphenzia brings you a Unity complete implementation of a brick breaker game. Your goal in a brick breaker game is to destroy all the bricks on the screen by hitting them with a ball you bounce back and forth with a paddle.

In this detailed walkthrough especially thought out for beginners, the instructor describes the whole game creation process, explaining what variables and prefabs are, how to create the game objects and apply physics to them, how to go over a state machine for the game, and also how to design the menu screens aiming to make the transitions between states in the game as smooth and sensible as possible for the player.

Topics Covered:

  • Creating the ball object
  • Bouncing the ball
  • Ball velocity and collision logic
  • Paddle movement
  • Positioning bricks
  • Game states
  • UI panels
  • Score and game over
  • Resetting the game

Duration: 2 hours of video training

Access now: Make a Brick Breaker Game in Unity

Block Puzzle Mobile Game – Unity Tutorial

This tutorial series by CodePlanStudio teaches you how to implement a block puzzle for mobile devices with Unity in a thorough step-by-step way. To earn points in a block puzzle game you need to clear lines both horizontally and vertically by filling them with shapes. The instructor shows you how to set up the project, import the needed assets, design the start screen, create the game screen with the shapes being randomly generated for the player to select and drop onto the grid, as well as line completion plus winning condition implementation.

Topics Covered:

  • Importing the game assets into Unity
  • UI/menu screens
  • Displaying the grids and the shapes
  • Random shape creation logic
  • Dragging and dropping the shapes onto the grid
  • Line completion checking to update the score
  • Winning and game over logic

Duration: 8.5 hours of video training

Access now: Block Puzzle Mobile Game – Unity Tutorial

How to Make Tetris in Unity

Here’s another tutorial from Zigurous, where he shows you how to make a Tetris game using Unity. Tetris is a tile-matching puzzle game, where the player’s objective is to prevent the blocks from stacking up to the top of the screen by clearing lines for as long as possible. The completed lines will then disappear, giving room for the player to proceed with moving and placing the blocks around.

In this video, the presenter shows you all the setting up of the sprites and scenes, as well as the spawning of the blocks, and how to move them around and rotate them. As an extra feature, he implements what’s called ghost pieces which indicate where the blocks are going to land before they actually hit that spot, thus helping the player visualize the best place to lay each block down.

Topics Covered:

  • Project creation
  • Importing sprites
  • Scene and tilemap setup
  • Spawning, movement, and rotation of the blocks
  • Locking the blocks on the grid
  • Line clearing
  • Game over restart
  • Ghost pieces

Duration: 2 hours of video training

Access now: How to Make Tetris in Unity

Create 2048 in Unity

In this short tutorial series from Tarodev, you’ll implement a nice-looking 2048 game with Unity. 2048 is a sliding tile puzzle game where you combine tiles with the same number together to sum them up and try reaching number 2048. You can keep playing the game until there are no more blank tiles in the grid, therefore creating even larger numbers. The instructor shows in this 2-videos tutorial how to set up the grid, how to create the tiles, code the logic for shifting and merging the tiles, and also check if the player’s won after each move.

Topics Covered:

  • Creating the grid
  • Dynamic background
  • Spawning tiles
  • Adding a game manager
  • Shifting and merging the tiles
  • Win condition

Duration:hour of video training

Access now: Create 2048 in Unity

Sliding Puzzle Game in Unity

In this tutorial series, BenBonk presents to us how to make a sliding puzzle game in Unity. The game consists of finding your way to the black star while avoiding the red spikes. Over the 3 parts of this series, you’ll see how to set up the project, create the player, obstacles, and goal sprites, plus all the scripting for the player movement and collision with the walls or obstacles. Moreover, the instructor goes over adding an animation for when the player touches the spikes for a more shocking effect, then the game resets. He ends the tutorial by polishing the game up and testing it with you.

Topics Covered:

  • Setting up the project
  • Game objects and sprites
  • Player movement
  • Creating the walls
  • Colliders
  • Obstacles and goal
  • Level logic implementation
  • Animations
  • Win state

Duration: 1 hour of video training

Access now: Sliding Puzzle Game in Unity

Develop a Puzzle Platformer Game – Unity

This Unity tutorial by Zenva Academy walks you through the creation of a puzzle platformer game, where the player has to unlock the colored doors by taking the specified keys that are dispersed around the level scenes, steering clear of the spikes, blades, and acid pits all the while.

The instructor guides you through the creation of the levels, sprites, and collision logic necessary for the implementation of a more puzzle-oriented platformer game full of obstacles. You’re also going to learn how to save your current progress and how to load and move between the scenes of the level you’re in, not to mention that you’ll acquire a lot of game designing skills from this course!

Topics Covered:

  • Designing the levels
  • Player controllers
  • Tilemap collisions
  • Adding ladders
  • Collecting keys
  • Unlocking doors
  • Scene transitions
  • Saving and loading

Duration: 2 hours of video training

Access now: Develop a Puzzle Platformer Game – Unity

Make a Game like Candy Crush using Unity and C#

In this tutorial series, Mister Taft Creates implements a game like Candy Crush in Unity. He’s also got versions of it for two other game engines (Godot and Game Maker Studio 2), in case you want to test it out in a different environment. Candy Crush is a match-three puzzle game where you need to clear as many rows and/or columns as possible in but a few moves.

The instructor covers a lot of features in this comprehensive series, ranging from implementing an opening screen to having wrapped candies and icing tiles, diverse level structures and goals, level selection, a pause screen, a star classification system for each level, and much more!

Topics Covered:

  • Setting up the board
  • Moving the pieces
  • Finding a match
  • Generating bombs
  • Detecting deadlock
  • Scoring system
  • Score bar and goals
  • Level goals
  • End game conditions
  • Animating the sprites
  • Adding icing tiles and chocolate pieces
  • Level selection

Duration: 20.5 hours of video training

Access now: Make a Game like Candy Crush using Unity and C#

Unity 15 Puzzle Tutorial

This brief tutorial series by Kee Gamedev shows you how to make a 15 puzzle game in Unity. The 15 puzzle is a sliding puzzle game having 14 numbered tiles in a 4×4 square where the goal is to arrange a shuffled initial set of the tiles in ascending order, by sliding the tiles around using the only vacant space available on the grid. The instructor goes over all the necessary setup and logic through the 2 videos of this series.

Topics Covered:

  • Grid and sprites setup
  • Logic scripting
  • Moving the tiles
  • Shuffling the tiles

Duration: 30 minutes of video training

Access now: Unity 15 Puzzle Tutorial

How to Make Snake in Unity

With this tutorial, Zigurous guides you through the making of the 2D arcade game Snake in Unity. In this game, the player controls a snake which is basically a line on the screen that grows in length as it eats fruits and its own body is a primary obstacle.

The instructor builds the game scene, makes the snake a rigid body, adds the walls as colliders, implements the logic for eating the food, and he concludes the tutorial by automatically resetting the game each time the player touches either one of the walls or the own body of the snake as that means game over.

Topics Covered:

  • Scene setup
  • Snake movement
  • Placing the food
  • Growing the snake
  • Game over reset

Duration: 45 minutes of video training

Access now: How to Make Snake in Unity

Sudoku Unity Tutorial

This tutorial series from CodePlanStudio teaches you how to implement Sudoku in Unity. Sudoku’s objective is to fill the 9×9 grid with digits from 1 to 9 in a way that there are no repeated numbers in each column, row, and each 3×3 subgrid as well.

In this series, you’ll be guided through the complete implementation of a Sudoku game, from creating and populating the grid to attributing numbers and notes to each cell. Further, he goes over adding the known features to the game, such as timer, pause menu, and difficulty level selection, plus win and game over screens as well as how to place ads in your game and release it on Google Play Store.

Topics Covered:

  • Creating and populating the grid
  • Difficulty level selection
  • Assigning numbers to the cells
  • Game over screen
  • Timer
  • Pause menu
  • Adding notes to the cells
  • Win popup window
  • Ads integration

Duration: 9 hours of video training

Access now: Sudoku Unity Tutorial

Jigsaw Puzzle – Unreal Engine 4 Tutorial

In this tutorial series, Ryan Laley creates a jigsaw puzzle game with Unreal Engine 4. Over the 8 videos of the series, Ryan shows you how to separate each piece from the material pattern he starts with in order to control every individual piece by itself, then how to generate the logic behind the game and set the puzzle screen.

On the left-hand side, he puts all the pieces of the jigsaw in a scrambled order, while on the right the player will be able to place the squares in a grid until they complete the game. Additionally, he tests the game with 3 different images to demonstrate how to switch between the puzzles and restart the game.

Topics Covered:

  • Initial setup in Unreal Engine
  • Controlling each individual piece
  • Creating the jigsaw blueprint
  • Setting up the puzzle screen
  • Clicking and dragging the pieces around the screen
  • Winning logic
  • Reset and progress labels
  • Puzzle selection

Duration: 1.5 hours of video training

Access now: Jigsaw Puzzle – Unreal Engine 4 Tutorial

Make a Puzzle Game in Unreal Engine

Here’s a tutorial from Zenva Academy featuring the process of making a puzzle game in Unreal Engine. In this course, the instructor will show you how to design a turn-based game where the player can collect followers while having to avoid obstacles to reach the end goal. As whenever the player moves all other objects move as well, you have to figure out where to go to steer clear of the red blade obstacle as you go around the room assembling followers.

By implementing this project, you’ll learn about blueprint parenting so to facilitate implementation when moving the player and the other elements of the game. You’ll also go through displaying texts to the player, besides adding the options of restarting and quitting the game.

Topics Covered:

  • Project setup
  • Player blueprint
  • Moving the player
  • Creating obstacles
  • Collecting multiple followers
  • Lighting manipulation
  • End goal

Duration: 2 hours of video training

Access now: Make a Puzzle Game in Unreal Engine

Make Your First 2D Grid-based Game from Scratch in Godot

This tutorial series from Emilio teaches you how to make a 2D grid-based game with Godot, a versatile open-source 2D and 3D game engine. The purpose of this game is to drag the blue boxes onto the red spaces.

You’ll learn how to set up the sprites and camera along with how to make the player, walls, and boxes nodes aside from setting up collisions between them. Emilio explains in detail his choices on the design of the game and continuously tests his progress with you throughout the videos. In the second video of the series, the instructor shows you how to add an animation for the player movement to be smoother and improves upon the UI displays to have a more polished version of the game.

Topics Covered:

  • Setting up sprites
  • Camera and zoom
  • Making the player
  • Boxes and walls
  • Setting up collisions
  • Win condition
  • UI labels and dialog
  • Testing

Duration: 48 minutes of video training

Access now: Make Your First 2D Grid-based Game from Scratch in Godot

I Made Baba Is You in Unity

To close this article, go check Akshay Goel‘s journey in making his version of Baba is You with Unity within 48 hours as an extra motivation to implement a game you like in your own way. Baba Is You is a game where you can change the rules by which you play, as they are blocks you can interact with. By manipulating the rules, you can alter how the game works and thus reach the flag or whatever object you set as goal.

In this video, you’ll see Akshay creating his own assets and sprites, going through the logic of the grid and collision setting, plus the editing of the game levels. You will also accompany him while he’s compiling the rules for the game and making them affect the game world!

Duration: 12 minutes

Access now: I Made Baba Is You in Unity

Summary

And there you have some of the best puzzle game tutorials available. Whether you’re a beginner or an experienced developer, puzzle games are a fantastic genre, and one that requires some interesting coding techniques to achieve. These tutorials should help you take those first steps, and let you discover new ways to make your players think.

However, there are an ludicrous amounts of the kinds of puzzles you can have in your games – so by no means is this list exhaustive. Don’t forget to continue to explore further learning resources – and good luck with your future games!

BUILD GAMES

FINAL DAYS: Unlock 250+ coding courses, guided learning paths, help from expert mentors, and more.

]]>
Best Sandbox Tutorials – A Guide to Creative Gameplay https://gamedevacademy.org/best-sandbox-tutorials/ Wed, 25 Jan 2023 08:58:40 +0000 https://gamedevacademy.org/?p=15521 Read more]]> Sandbox games are a hugely popular gaming genre, giving players the freedom to explore and interact with a game world without being restricted by objectives or strict progression limits. Popularized by the endless creativity of Minecraft and similar procedurally-generated sandboxes, the genre is also a popular way for coders to test their game design skills by implementing new mechanics.

As such, the first big project that many budding game developers choose to take on is a sandbox game where they and their players can experiment with game mechanics in an open world. We’ve compiled some of the best sandbox game tutorials available, providing you with all the help you need to create a huge open world and begin your sandbox experimentation!

Why Learn To Make A Sandbox Game?

Sandbox games like Minecraft and Roblox are all about creativity – there aren’t any set objectives that players have to follow, giving them the freedom to do whatever they want within the game’s world. In turn, that gives developers the chance to create an open-world playground for players to experiment with and explore their creativity. 

As such, designing a sandbox game is less about giving players things to do and more about giving them a set of tools and an open world to explore, then letting them run wild. This is an exciting challenge to take on – rather than creating a set path for players to follow, a sandbox requires you to create a world that’s open-ended, explorable and enjoyable for players to exercise their creativity within. 

Sandboxes are also a great way to master new skills in game design since they involve a number of mechanics that can be applied to other projects. Physics engines, NPCs, enemies, lighting, procedural world generation and more are all common aspects of sandboxes, so creating your own sandbox can help you learn a variety of new systems and mechanics.

In short, sandboxes are an ideal way for you to explore new mechanics, work on your game design skills and exercise your imagination without having to implement them within a rigid framework.

The tutorials below will help you to master a number of key programming skills and game mechanics needed to create your very own sandbox game. Most of these are designed for beginners, meaning that whatever your experience level, you’ll be able to easily follow along with the tutorial and steadily build a sandbox game from the ground up!

2D Procedural Maps For Beginners

One of the most common traits of sandbox games like Minecraft and Terraria is a procedurally-generated world – in other words, a game world that’s generated at random. This mechanic ensures that sandboxes have a high level of replayability since no two playthroughs will be the same – players will always have a new world to explore and interact with.

As such, the 2D Procedural Maps For Beginners tutorial from Zenva Academy is a great place to start your sandbox development journey. The tutorial shows you how to create your own procedurally generated 2D worlds in Unity, laying the foundations of your sandbox with an endlessly explorable and replayable world. 

All you’ll need is a basic understanding of Unity and C#, making it an excellent choice for beginners. You’ll also have the chance to massively expand your C# knowledge through this course thanks to the variety of topics it covers.

Key Topics Covered:

  • Generating noise maps in Unity
  • Understanding noise settings for different effects
  • Calculating biomes based on noise map data
  • Organizing biome data with Scriptable Objects
  • Instantiating 2D tiles based on biome data
  • Implementing a player controller

Duration: 1 hour, 30 minutes of video tutorials.

The Complete Procedural Terrain Generation Course

If you’re more inclined to make a 3D sandbox than a 2D one, then this alternative Zenva tutorial is the one for you. The Complete Procedural Terrain Generation Course will help you to create highly explorable, randomly-generated worlds complete with different biomes and environment types to create diverse locations for your players to explore. 

In addition, the tutorial includes a section on managing world generation alongside performance to ensure a positive game experience for your players.

Adding a third dimension to your procedural world adds another layer of complexity to the process of generating a random world, so this course is naturally slightly longer and more complicated than the 2D option above. However, it’s still very beginner-friendly, with no prerequisites other than basic Unity and C# skills to get you started.

Key Topics Covered:

  • Generating noise maps to determine the shape of the terrain
  • Utilizing noise maps as height maps to produce terrain
  • Applying gradient textures to a mesh based on terrain shape
  • Setting up heat maps and moisture maps based on the terrain height
  • Combining various data elements to algorithmically determine biomes
  • Using biome types to determine how trees spawn

Duration: Roughly 3 hours, 35 minutes of video tutorials

Creating A Physics Playground

Another common element of sandbox games is a physics engine that allows players to interact with and manipulate objects, the environment and other characters in fun and inventive ways. In order to learn how to implement game physics successfully, try checking out Unity’s own tutorial on the subject – the Creating A Physics Playground series.

This series starts out with a prototype for complex physic-based gameplay, providing free assets and a step-by-step guide to replicating the Unity team’s prototype. You’ll then have the opportunity to explore new physics elements, experimenting with new mechanics and prefabs to create your own version of the physics sandbox.

This is a great way to learn how to program game physics with Unity for use in your sandbox game, ensuring your players can find fun and unique ways to interact with your game world.

Key Topics Covered:

  • Programming physics in Unity
  • Prefab Installation
  • Explosion particle systems
  • Cinemachine
  • Rigibody 
  • Post-processing volumes
  • Spawning and despawning objects

Duration: A short 11 minute tutorial available on YouTube, or a longer tutorial and additional resources on Unity Learn.

Let’s Make A 2D Sandbox Game!

Two of the best-known sandbox games are Minecraft and Terraria, which take a similar approach to sandbox gameplay by providing players with an open, procedurally-generated world and various resources to craft new items and equipment with. To help new sandbox developers create their own game in this style, Eren Can’t provides a handy tutorial series.

The “Let’s Make A 2D Sandbox Game!” series provides you with a step-by-step guide to creating an exploration and crafting-based sandbox game from start to finish. Beginning with procedurally generating terrain and caves to lay the foundations of your world, then adding new elements like biomes, movement, inventory systems and more, this tutorial has everything you need to start creating your own sandbox.

The series is on the longer side, clocking in at over 13 hours in total, but this comprehensive guide is a fantastic way to master sandbox game mechanics. This makes it a great entry point for beginners, especially since everything is covered in a logical, step-by-step process.

Key Topics Covered

  • Generating the game world, with terrain, caves, trees, biomes and more
  • Optimizing your game world for a smooth player experience
  • Movement and animation for the player character
  • Camera control 
  • Lighting
  • Inventory systems and UI 
  • Tools and interactable items 

Duration: Roughly 13 hours, 25 minutes of video tutorials (or less if you skip the inventory tutorial series included in the playlist)

Create And Manage Huge Game Worlds

One of the challenges of sandbox game development is that the huge, open, procedurally generated world that often forms the basis of the game can be complex to create and manage. As such, it takes some specific skills to first create an open world that players will have fun exploring and interacting with, then balancing this world with game performance to ensure smooth gameplay.

To this end, the Create And Manage Huge Worlds tutorial shows you exactly how to set up, generate and design huge worlds in Unity, then learn how to efficiently control them. You’ll learn how to use terrain tools to generate your world, then split it into chunks for easier management. In addition, the tutorial teaches you how to manage performance and optimize gameplay.

You’ll need a basic-to-intermediate knowledge of Unity and C# for this course, meaning that slightly more experienced coders may get more use out of it than complete novices. However, it’s still highly accessible and easy to follow thanks to its step-by-step guides – so while it may take beginners slightly longer to get to grips with the skills here, it’s still a great way to learn about sandbox world design.

Key Topics Covered:

  • Working with height maps and texture paints to create beautiful terrains
  • Splitting your terrain up into manageable chunks
  • Showing and hiding chunks based on their distance from the camera
  • Understanding “Level of Detail” (LOD) and use it for efficient rendering
  • Implementing fog effects to hide chunk transitions

Duration: Roughly 55 minutes of video tutorials 

How To Make Minecraft In Unity

Since Minecraft is one of the most iconic examples of sandbox game design, one of the best ways to learn how to create a sandbox yourself is by imitating this iconic game as your first project. If the imitation approach appeals to you, then the How To Make Minecraft In Unity tutorial from Poncho may be the option for you.

The tutorial is split into two parts, with Part 1 showing you how to begin creating your game’s world. This video covers chunk creation, mesh generation and random block generation to create a procedural world as the base for your sandbox.

Part 2 shifts its focus from the world to characters and objects, showing you how to create objects, start scripts, control a player character and alter game physics to prevent players from getting stuck. 

These two videos form a nice, short demonstration that helps you to quickly master the process of generating a Minecraft-style block-based world and begin populating it with characters and objects. As such, it’s a great way for beginners to master sandbox-related mechanics and build their first game world, or for more experienced game developers to learn new skills in procedural generation to add new tools to their skillset.

Key Topics Covered:

  • Creating a Minecraft-like world through procedural generation
  • Creating and coding chunks to manage your game world
  • Generating a mesh 
  • Rigidbody character controllers
  • Player movement and camera control 
  • Altering game physics 
  • Object creation and scripting 

Duration: Two tutorial videos, the first lasting just under 23 minutes and the second lasting around 20 minutes.

Conclusion

Creating a sandbox game can be a challenge, partly because of the complex procedural generation processes and other mechanics that are involved. It’s also because creating an open world for players to invent their own objectives and playstyles within is very different from the usually tightly-scripted process of game design.

However, with the tutorials above, you should be well on your way into mastering the sandbox genre. As such a broad genre, there’s also always more to explore – so after these tutorials, don’t be surprised if you find even more to learn from!

BUILD GAMES

FINAL DAYS: Unlock 250+ coding courses, guided learning paths, help from expert mentors, and more.

]]>
Kaboom.js Tutorials – Complete Guide for Easy Game Dev https://gamedevacademy.org/kaboom-js-tutorials/ Sat, 21 Jan 2023 05:11:59 +0000 https://gamedevacademy.org/?p=14977 Read more]]> Do you want an easy-to-use game framework to build your dream projects?

Kaboom.js is a relative newcomer to the game development scene, but it is already making a big splash – especially among indie creators. This JavaScript-based library was made specifically with games in mind, in the same vein of frameworks such as Phaser or Pixi.js. However, there are many aspects that have made it stand above its competitors and worth your time checking out.

In this article, we’re going to introduce you to Kaboom.js and show you how you can get started learning this new tool.

Let’s get started!

What is Kaboom.js?

As mentioned, Kaboom.js is a JavaScript library in the vein of HTML5 games, which use the browser to render games made with it. The library was made with the idea of simplicity, but comes with many important game development features – such as layering, collision detection, input handling, and more. Regardless, though, the goal is to allow novice developers to create game scenes as quickly as possible.

Game objects in Kaboom.js are conveniently rendered with a component-based system. This means they’re extremely easy to manipulate and apply behaviors too. The behaviors can include everything from simple game mechanics like health to basic movement-based animations – so each game object essentially suits object oriented programming principles.

Beyond this, it is worth noting Kaboom.js is also an available template for Replit – a popular, in-browser coding environment. This means its well-suited for developers who aren’t interested in setting up local development environments or just want to play around with the library.

Key Pros of Kaboom.js

Why should you use Kaboom.js? Below, we’re going to explore what makes Kaboom.js stand out and how, as a developer, you can benefit from the advantages Kaboom.js offers.

Screenshot of the Kaboom.js playground

Fast and lightweight

Unfortunately, not everyone has a computer that can run game engines such as Unity or Unreal Engine – which both are pretty process intensive programs. However, Kaboom.js does not require a great computer and can be used even with low-end laptops. In fact, due to its incorporation with Replit, as mentioned above, you really only need a browser if you’re intent on using it – not even a code editor is required.

Likewise, because of how lightweight it is, games made with Kaboom.js run very smoothly as well. This means you don’t have to get hung up too much on optimization. Instead, your games will likely run quickly right out of the box, leaving you more time to focus on what matters.

No dependencies

Many frameworks and libraries out there require several layers of dependencies to be able to run properly. If you forget the dependency, or more tragically, if the dependency has a breaking change, your game isn’t going to work.

Kaboom.js doesn’t require any sort of dependencies. While you certainly can add packages such as webpack, natively you just need to import the Kaboom.js library itself. Once that is added, you won’t have the extra worry of maintaining the dependencies. This helps Kaboom.js achieve its goal of making it quick to setup and allowing you to dive straight into the fun stuff of actually making the game.

Cross-platform compatible

Since Kaboom.js is specifically for creating browser-based games, this means that there are no platform limitations. If the device can connect to the internet, your players can play it from anywhere.

For you as a developer, this means two things. First, this helps you avoid messy setups of needing multiple game versions just to have it available for multiple platforms. Second, this opens you up for a wider audience since you can tap into different sorts of players. All in all, though, this is a boon that makes it much easier for you to get the game into multiple different hands.

Simplicity

If you’ve ever tried to read documentation for frameworks or libraries before, you’ll know they can get rather complicated. If you don’t believe us, just go check out Unity’s documentation. While certainly this is fine for experienced developers, beginner developers are going to find this a nightmare.

Kaboom.js was designed to eliminate this problem and be as simple as possible. Not only does this help with keeping it lightweight, but makes the documentation much, much easier to understand when you’re just a beginner. This, in turn, just makes development itself easier.

Additionally, it comes with the extra benefit that this documentation can more easily be maintained as the library is updated. This means you won’t be reading old information that was relevant five versions ago.

Specifically made for beginners

As you might have seen from the previous points, beginners were at the heart of the design choices for Kaboom.js. Everything about the library is made to benefit beginners who have never made a game before. While there is a need for JavaScript experience before diving in, this is a much lower point of entry compared to heftier engines.

Thus, you’re only going to need a few tutorials to get the gist of how Kaboom.js works – and soon be able to develop your own projects with it.

Active development

Over the years, many HTML5 frameworks have come and gone. For others that remain, the development can often be slow and new versions, bug fixes, and features are few and far between. While many of these frameworks still technically work, the lack of developer support can eventually become a hindrance.

Kaboom.js, on the other hand, is very actively and caringly developed. Though we don’t expect them to break their principles of simplicity, improvements to the library come frequently. Thus, you can be assured the library will be supported for whatever time it needs for you to build your project.

Screenshot of the Kaboom.js GitHub page

What can you make with Kaboom.js?

Being based on HTML5 (i.e. for the browser), projects made with Kaboom.js do have limitations – as our browsers and internet are only so powerful no matter which JS library we’re talking about. So, you shouldn’t expect to make any kind of AAA game with the library. Kaboom.js was also specifically made for 2D development, so 3D graphics are kind of off the menu as well.

Past these two minor limitations, though, Kaboom.js does not put any further obstacles in your way. You can build small games in just about every genre, and only your imagination is there to hold you back. This includes everything from platformers to adventure games to old-style retro games like Breakout, Super Mario Bros.Space Invaders, and so forth.

If you want to explore the full scope of what people have already made, you can check out Kaboom.js made games below:

Kaboom.js & JavaScript Tutorials

Ready to create games with Kaboom.js? Check out the links of tutorials below which cover Kaboom.js, JavaScript for HTML5 development, and the game development process.

BUILD GAMES

FINAL DAYS: Unlock 250+ coding courses, guided learning paths, help from expert mentors, and more.

]]>
Drawing Sprites with SFML & C++ – Game Dev Tutorial https://gamedevacademy.org/sfml-cpp-sprites-tutorial/ Mon, 19 Dec 2022 01:00:27 +0000 https://gamedevacademy.org/?p=12495 Read more]]>

You can access the full course here: Discover SFML for C++ Game Development

Want more coding topics for a school environment? The Zenva Schools platform which offers online courses, classroom management tools, reporting, pre-made course plans, and more for teachers.

Drawing Sprites

We’ve seen how to draw a basic shape but realistically, most of our games will use more than shapes. We will want to place graphics, icons, and other images into our games and we do so via Sprites. Setting up a Sprite is generally done in two steps with SFML: first, we load in a texture, then we create a sprite and pass in the texture. Once we have the sprite set up, we can set attributes such as the size and position and then display it by drawing it into the window during the run loop.

In our project, we should create a folder called assets that contains any assets needed in our game. We only have 4 so there’s no need to further divide the assets folder. Copy the “enemy.png” and “background.png” images, the “damage.ogg” audio file, and the “Arial.ttf” font files from your provided files and paste them into the assets folder. We will only work with the Enemy.png image for now. To create a texture, we first create a texture variable and then call the loadFromFile() function, passing in the path to the file as a string. It returns true if successful and false otherwise so we should perform a boolean test to see if the load was successful. In our main function, write this code after the code to create the window and before the run loop:

sf::Texture texture;
if (!texture.loadFromFile("assets/enemy.png")) {
  std::cout << "Could not load enemy texture" << std::endl;
  return 0;
}

This will create a variable of type sf::Texture and load the image into it. If the load fails, we print an error message and return. Sometimes, the load for an asset fails for some unknown reason so we should handle any errors properly. You will need to #include <iostream> at the top of main.cpp as well. Once we have the texture, we can create a sprite object called enemySprite and pass in the texture like this:

sf::Sprite enemySprite;
enemySprite.setTexture(texture);

The sprite will only be as big as the image provided and will default to be at position (0,0) or in the upper left corner. We can change the position like this:

enemySprite.setPosition(sf::Vector2f(100,100));

Which brings the sprite 100 pixels out from the left and 100 pixels out from the right and increase the size of the sprite by scaling it like this:

enemySprite.scale(sf::Vector2f(1,1.5));

This will scale the width of the sprite by 1 (no change) and scale the height to 1.5x its original height. Notice how both functions take an sf::Vector2f as inputs and each needs an x and y value. In order to draw the sprite, we change the draw code to this:

window.clear();
window.draw(enemySprite);
window.display();

We always have to clear the window before drawing anything and display the window after we draw to it.

BUILD GAMES

FINAL DAYS: Unlock 250+ coding courses, guided learning paths, help from expert mentors, and more.

Transcript

What’s up everyone? Welcome to our tutorial on Drawing Sprites. Here we’ll get a quick intro into what sprites are from a game context and how to create and use them in SFML.

So this is actually a two step process, the first thing we need to do is create a texture object. Once we have that we can create a sprite from it and then we can set the position and the scale. So let’s head to the code and get started. Alright, so just a quick heads up again, I took all the code from the previous section, not that we really did very much and put it in old code and I’ll continue to do this with each new section.

Alright, so what is a sprite from a game context? Well essentially, a sprite is gonna be an object in the game that has an image associated with it. So this is really the main difference between let’s say shapes and sprites in games is that a sprite has an image and a shape just has well a shape. It just has its boundaries, it has some sort of code to dictate what shape those boundaries will take on, be of circles, square, rectangle, etc.

So in our case, the background of our game and the enemy itself, those are both going to be sprites, we’re not really gonna be working with shapes very much. So like I said this is a two step process. The first thing we need to do is load in a texture and a texture needs an image to load. So that’s why I had you load in your assets folder. So your project should look like this, sfml project, you have your codes, and then you have your assets folder with the items in it. We’ll use the ttf as a font later on. Same with the damage.ogg, that’s for sound. For now we’ll at least want the enemy.png because that’s what we’re gonna be working with here. Okay, so as long as we have it in our project assets /enemy.png, then we can load it in like this.

Okay, first thing that we’ll need to do is create a texture itself so we’ll do sf, Texture, texture. Okay, now a texture just like the Render Window is part of the SFML Graphics library. Anytime you need a new module, you’ll need to load it in here. Okay, so we have a texture object, we actually don’t need to call a constructor, set it equal to a texture or anything like that. Once we create the object, we have access to it immediately and we need to call the load from file function, like this texture.load From file, oops! Not load from stream we want load from file.

Okay, and then we’re going to pass in the path to the file. So in this case this is gonna be “assets/ “enemy “.png”. Now this is actually gonna return true or false based on the success or failure. So we’re gonna say something like if text actually, we’ll say if not texture.load from file, then maybe we’ll just print out some message and return. So let’s just close that off and this should actually be in here.

Okay, so in this case, what we can do is something like Standard c out, I actually don’t think we have the iOS stream library so I’m just gonna include that now. Include your stream. Okay, good stuff. Okay, so now what we’ll do is c out something like “Could not load, “enemy texture”. Okay, and then we’re just going to end it.

All right and because we really want the game to only run if the texture is loaded, we’re actually gonna return false. Cool, so as long as this is the case oh actually you know what? This is returning will turn zero. Okay, so as long as the texture is loaded, so as long as this doesn’t return zero, then we have a texture rather an image loaded into this texture, and now we can use it with a Sprite. So to do that, we’ll do basically the same process as with the texture, we need to create the sprite object first, Sprite and we’ll call this like enemySprites or something.

Okay, and then we’re going to call upon the enemySprite . setTexture function and then we’re I’m just going to pass in the texture that we loaded. Okay, so this will associate a texture with a Sprite. So now the sprite is created It has a texture and we can draw it. We don’t know exactly what size or position well we do know what position it will be in which will be 00 by default which will be upper left corner and the size will be exactly the size of the image itself. We can modify that later on, and which we’ll do in just a minute here.

Okay, so just using the default values, if we want to draw this to the window, we simply call upon the window.draw and then pass in the Sprite. So in this case, enemySprite. Okay, cool. So we’ll get this Save, and let’s run the code, let’s see what happens. So clear it, let’s compile it, and then let’s run it and now you can see that we have this little sprite in our game.

Obviously there are some issues here it’s getting cut off so the screen is not big enough to begin with. Also, this is kind of in the top left corner, we might not want it there and might not be quite big enough. Okay, so this is all stuff that we can just maybe let’s do a 500 by 500 window. That way we have enough size to draw most of the things that we need. Then if we go to rerun it, we should probably see that’s not gonna take up the whole screen anymore. It’s just take up a part of it. So maybe we don’t want it in the top left. Maybe we want it kind of a bit centered.

So what we can do is maybe move it about 100 pixels to the right and 100 pixels down, might put it roughly in the center, okay. So what we can do is take this enemy sprite, enemySprite, okay and we can set the position of it. So, this is gonna take in an a Vector two f object like this SF Vector two f which will take in a vector two dimensional float, and this will need a width and a height or an X and Y value. So in this case, we’ll just do a 100 and 100. Okay, if we go to lets close this off, we go to rerun it.

Okay, so recompile it, again, every time you make a change, you have to recompile it, you can see that this has now moved, we can also change the height, let’s kind of make this guy a little bit taller, but we won’t necessarily change the width of it. So what we can do is lets close that up do the enemySprite . And we can scale it. Okay, weirdly enough, you can’t assign a specific width and height, you actually have to scale things.

Okay, so in this case, we’re going to again pass in a vector2f, capital V, Vector two f, okay and then we’re going to pass in the amount by which we want to scale the x and the amount by which we want to scale the y. So the x is going to remain exactly the same. So we’ll just do one, the y however, we want to change the height, maybe we’ll do like a 1.5 and see how that works out.

Okay, so we’ll go back to here. Well, I guess we don’t need to clear it. We’ll just kind of recompile and we’ll rerun it and now you can see that this guy is horribly stretched, but at least the scaling worked. Now there are plenty of other things that we can do with Sprites but this will be pretty much the extent of what we’re gonna do in this course with our Sprites.

One last thing to note before moving on to the next section is that the sprites bounding box is actually this whole rectangle. Weirdly enough, the bounding box doesn’t follow the image like this. This is gonna be the bounding box. So when when it comes to detecting mouse clicks on the sky, even if you click up here, it’s technically within the bounding box. So that’s going to register a click. Okay, we’ll get more into that a little bit later on. Just wanted to make you guys aware now. Okay, we’ll close this up.

Otherwise, that’s it. So in this section, we covered two things, loading in textures, and the second creating sprites and assessing their attributes. Definitely Feel free to play around with this. Maybe try to load in your background. See how well you can do with that. When you’re ready to move on, we’ll do pretty much the same thing but with text. So stay tuned for that. Thanks for watching and see you guys in the next one

Interested in continuing? Check out the full Discover SFML for C++ Game Development course, which is part of our C++ Programming Bundle.

For teachers, you can also try Zenva Schools which offers online learning suitable for K12 school environments and offers a wide array of topics including Python, web development, Unity, and more.

]]>
Free Course – Create an Unreal BALLOON POPPER Game https://gamedevacademy.org/unreal-balloon-popper-tutorial/ Fri, 16 Dec 2022 01:00:38 +0000 https://gamedevacademy.org/?p=19286 Read more]]>

Expand your knowledge of Unreal Engine’s Blueprints Visual Scripting system and start building your very own balloon popper game – no coding from scratch or C++ knowledge required! You can also extend the material covered here by checking out the full course below!

UNREAL ENGINE MINI-PROJECTS

About

With the help of instructor Daniel Buckley and this Unreal Engine tutorial, you will learn crucial techniques for developing your own powerful games using visual scripting – a beginner-friendly way to approach programming. With simple projects, you can practice manipulating objects, scripting, and working with algorithms in a way that prepares you for many different kinds of future, real-world projects. You’ll discover a variety of essential techniques for working with Unreal Engine, including how to detect and deal with user input, use coding principles like loops, and much more.

Regardless of what sort of game you wish to make, these Unreal Engine skills will ensure you’re ready with the core foundations needed to build platformers, FPS games, action RPGs, and beyond.

New to Unreal Engine? Enroll in UNREAL ENGINE 101 – 3D GAME CREATION on our website and find quick access to additional resources!

BUILD GAMES

FINAL DAYS: Unlock 250+ coding courses, guided learning paths, help from expert mentors, and more.

]]>
How to Process Swipe Movements for Mobile Games in Unity https://gamedevacademy.org/mobile-swipe-movement-tutorial/ Sun, 27 Nov 2022 01:00:28 +0000 https://coding.degree/?p=549 Read more]]>

You can access the full course here: Build a Mobile Road Crossing Game

Player Setup

In this lesson, we’re going to be setting up a Player GameObject*; this is going to be the object which is going to act as our player.

*(A GameObject is the base class for all entities in Unity that you can attach various different components onto.)

Creating A GameObject

Let’s open up the Assets > Sprites folder,

Sprites added to Unity Assets folder

… and drag our player sprite into the Hierarchy.

Player sprite added to Unity Hierarchy

This is going to create a brand new GameObject called Player.

Object renamed to Player in Hierarchy

Adding Components

We’re going to create a new empty GameObject (Right-click > Create Empty)

Unity Create Empty object selected from Menu

(It’s generally good practice to have the most parent object to be empty as it allows you to finely adjust the child sprite position and pivot.)

We’re going to rename this GameObject as “Player”, and reset its position to 0, 0, 0.

Unity Inspector with new, reset player object

And then, we’re going to rename our player sprite to “Sprite”

Player sprite circled in Unity Hierarchy

and drag it in as a child of “Player”.

Sprite made child of Empty Player game object in Unity Hierarchy

Make sure that the Sprite position is at 0,0,0 as well.

Player sprite transform component

To render this object on top of the Ground sprite, we’re going to change the sorting layer from “Default” over to “Objects“.

Player Sprite added to Objects layer in Unity Inspector

Now we’re going to create a new C# script called “Player”. In our Scripts (Assets > Scripts) folder, Right-click > Create > C# Script:

Unity Create menu with C# Script selected

Player script in Unity Assets

Select the Player script, and drag that into the Player Inspector.

Player script added to Unity Player game object

To add in a Box 2D Collider, click “Add Component” > type “Box” > select “Box Collider 2D“.

Unity Add Component window with Box Collider 2D selected

Box Collider 2D as seen in Unity Inspector

And then, bring the size on X and Y down to 0.5 in order to make the object a bit smaller than the actual sprite.

Box Collider 2D with Size changed to 0.5

Player demonstrating collider in Unity

We’re now going to add a Rigidbody2D. To do that, click on Add Component > type “Rigid” > select “Rigidbody 2D

Unity Rigidbody 2D component circled in Search

Rigidbody 2D for Player in Unity Inspector

Let’s also make a Box Collider 2D a Trigger, so that we can actually go through other colliders.

Is Trigger checked for Box Collider 2d

And down in our Rigidbody 2D, change Body Type from “Dynamic” to “Kinematic”. Kinematic behavior basically prevents the Rigidbody2D from reacting to gravity or applied forces.

Rigidbody 2D set to Kinematic for Player

Finally, let’s go ahead up in the Inspector and change the Tag of the player over to “Player“.

Player tag added to Player in Unity

Save the settings, and then go over to the Prefabs folder, drag Player in as a Prefab so you can use it in the future levels.

Player dragged to Unity Prefabs folder

Swipe Detection – Part 1

In this lesson, we’re going to begin setting up the ability for our game to detect touches for moving the player.

Creating A GameManager

Let’s create a new C# script called SwipeDetection in the Scripts folder.

SwipeDetection script in Unity Assets

We’re going to create a new empty gameObject, and rename it to _GameManager.

Create Empty game object option in Unity menu

We will then attach the SwipeDetection script to _GameManager.

Swipe Detection Script added to GameManager

Adding Swipe Detection Functionality

Inside of the SwipeDetection script, we’re going to check if we have swiped the finger left/right/up, and move towards the direction of the swipe.

First of all, we need to create a variable to store our Player so that we can, later on, tell it to move:

public Player player;

Next, we need to create a Vector2 that tells us the first touchpoint of your finger on the screen, and we’ll check to see if it’s left, up, or right.

public Player player;
private Vector2 startPos;

Then we need to create another variable to set how many pixels do we have to swipe in order for it to be detected. We’re going to set this a public integer with a default value of 20.

public Player player;
private Vector2 startPos;
public int pixelDistToDetect = 20;

And lastly, we need to create a boolean to check if we have a finger down.

public Player player;
private Vector2 startPos;
public int pixelDistToDetect = 20;
private bool fingerDown;

Using these variables, we’re going to check to see if we have pressed a finger down in the Update function.

void Update()
{
    if(fingerDown == false && Input.touchCount > 0 && Input.touches[0].phase == TouchPhase.Began)
}

To detect if a finger is down for the first time correctly, we put three different conditions:

  • Is the fingerDown currently set to false?
  • Is Input.touchCount* greater than 0? (*Input.touchCount will increase as more touches are detected on the screen at a time.)
  • Has the first touch (touches[0]) just Began?  (= Is this the first frame the finger is down?)
void Update()
{
    if(fingerDown == false && Input.touchCount > 0 && Input.touches[0].phase == TouchPhase.Began)
    {
        // If so, we're going to set the startPos to the first touch's position, 
        startPos = Input.touches[0].position;
        // ... and set fingerDown to true to start checking the direction of the swipe.
        fingerDown = true;
    }
}

If the finger is down, then we can start checking which direction the finger moves into. For example, if the finger ends up moving away from the start position along the y-axis, it means it just swiped upwards.

//Is our finger touching the screen?
if (fingerDown)
{
    //Did we swipe up?
    if(Input.touches[0].position.y >= startPos.y + pixelDistToDetect)
    {
         fingerDown = false;
         Debug.Log("Swipe up");
    }
}

Now for testing purposes, we’re going to duplicate this code and use it in terms of the mouse. So instead of Input.touches[], we’re going to use Input.GetMouseButtonDown to detect mouse clicks.

//Testing for PC
if (fingerDown && Input.GetMouseButtonDown(0))
{
    startPos = Input.mousePosition;
    fingerDown = true;
}
if (fingerDown)
{
    //Is the current mouse position 'pixelDistToDetect' away from 'startPos' on y-axis?
    if(Input.mousePosition.y >= startPos.y + pixelDistToDetect)
    {
         fingerDown = false;
         Debug.Log("Swipe up");
    }
}

Let’s save it and press Play.

Swipe demo in Unity for movement

You can see that the Debug.Log works as intended as you click and drag upwards.

However, if your mouse moves off the screen, the script will not be able to calculate the next touch position correctly and return these errors.

Console IndexOutofRangeException errors in Unity

To prevent this, we need to reset the startPos by setting fingerDown to false whenever our mouse button is up.

//If the mouse button is up,
if(fingerDown && Input.GetMouseButtonUp(0))
{
    //startPos will be reset
    fingerDown = false;
}

We can also add the same functionality for touch inputs. Note that we need to check if the first finger is released from the screen, i.e. if the TouchPhase is set as ‘Ended‘.

//If the finger is released from the screen,
if(fingerDown && Input.touchCount > 0 && Input.touches[0].phase == TouchPhase.Ended)
{
    //startPos will be reset
    fingerDown = false;
}

Swipe Detection – Part 2

In this lesson, we’re going to be adding in left and right swipe detections.

Inside of SwipeDetection.cs, we’re going to add else if statements below where we detect if our finger swiped upwards:

//Is our finger touching the screen?
if (fingerDown)
{
    //Did we swipe up?
    if(Input.touches[0].position.y >= startPos.y + pixelDistToDetect)
    {
         fingerDown = false;
         Debug.Log("Swipe up");
    }
}

So to detect left and right swipes, we can detect the change in x-position of Input.touches:

//Is our finger touching the screen?
if (fingerDown)
{
    //Did we swipe up?
    if(Input.touches[0].position.y >= startPos.y + pixelDistToDetect)
    {
         fingerDown = false;
         Debug.Log("Swipe up");
    }
    //Did we swipe left?
    else if(Input.touches[0].position.x <= startPos.x - pixelDistToDetect)
    {
         fingerDown = false;
         Debug.Log("Swipe left");
    }
    //Did we swipe right?
    else if(Input.touches[0].position.x >= startPos.x + pixelDistToDetect)
    {
         fingerDown = false;
         Debug.Log("Swipe right");
    }

}

If you save and hit Play, you’ll see that Debug.Log works as intended:

Console showing swipe detection in Unity

Moving Player

We’re going to replace Debug.Log and start actually moving our player. To do that, let’s first open up Player.cs and declare these variables.

public class Player : MonoBehaviour
{
     //Stores how long it takes to get from one tile to the other
     public float moveSpeed;
     //Where is this player trying to get to
     private Vector3 targetPos;
}

Inside the Start function, we’re going to set the target position to be the current position, i.e. transform.position:

public class Player : MonoBehaviour
{
     //Stores how long it takes to get from one tile to the other
     public float moveSpeed;
     //Where is this player trying to get to
     private Vector3 targetPos;

     void Start ()
     {
          targetPos = transform.position;
     }
}

Next, we’re going to create a new public void function called Move, which is going to carry over a Vector3 (move direction) as a parameter.

Then we can update our target position by this given move direction.

public void Move (Vector3 moveDirection)
{
     targetPos += moveDirection;
}

Now, inside the Update function, we need to actually move our player towards the target position using Vector3.MoveTowards.

private void Update ()
{
     //Move towards the target
     transform.position = Vector3.MoveTowards(transform.position, targetPos, moveSpeed * Time.deltaTime);
}

Note that moveSpeed is multiplied by Time.deltaTime to convert the speed unit from per frame to per second. Let’s save the Player script and go back to SwipeDetection.cs. 

We’re now going to replace all the Debug.Log with the player script’s Move function, passing in a direction to move towards.

//Is our finger touching the screen?
if (fingerDown)
{
    //Did we swipe up?
    if(Input.touches[0].position.y >= startPos.y + pixelDistToDetect)
    {
         fingerDown = false;
         //Move upwards
         player.Move(Vector3.up);
    }
    //Did we swipe left?
    else if(Input.touches[0].position.x <= startPos.x - pixelDistToDetect)
    {
         fingerDown = false;
         //Move left
         player.Move(Vector3.left); 
    }
    //Did we swipe right?
    else if(Input.touches[0].position.x >= startPos.x + pixelDistToDetect)
    {
         fingerDown = false;
         //Move right
         player.Move(Vector3.right); 
    }

}

Lastly, we’re going to assign a value for PixelDistToDetect, and link our Player gameObject into the player property.

Unity Swipe Detection with Player added to Script in Inspector

If we hit Play, we can now swipe up, left, right to move our player.

Swipe detection demo in Unity

Transcript

Player Setup

Welcome back everyone, in this lesson, we are going to be working on setting up a Player GameObject. This is going to be the object, which is going to act as our player. We’ll be moving it for our level, and it will be able to interact with various different things.

So, first of all our scene view here, let’s go down to sprites photo, and I’m gonna drag in our player’s sprite right here. Okay, drag then into the hierarchy, and it has been created here in a scene. Now we’re not going to be actually having our sprite as the main parent object, instead we’re gonna be using an empty game object as the parent.

So here in the hierarchy, I’m gonna right click create empty, I’m gonna call this one player, and I’m gonna set the position to be zero, zero, zero, so is nice and centered in the middle of the screen here. We can then select our player sprite, I’m gonna rename this to be sprite, and I’m gonna drag that in as a child of player, making sure that the position is at zero, zero, zero as well.

Now on our player sprite here, let’s also change the sorting layer from default over to objects, since we do want this to be rendered on top of the ground sprites. And on our play a main object now, what we can do is start attaching all of our components that we need. So, first of all, we need a player script, and this is going to manage moving the player and interacting with various different things.

So over in our scripts folder, what I’m gonna do is a right click and create a brand new C-sharp script called player. We can then go to our player object and attach that script as a component, okay? So, wait for that script to compile, select our player, and drag that player script on, there we go. Next we want to add in a Collider, and we’re gonna add component, and for our character here, let’s add in a Box Collider 2D.

Now by default, it’s gonna be a bit larger than the actual sprite, because the sprite bands do have quite a bit of padding on the side. So what we’re gonna do, is we’re gonna bring the size on the X down to probably around, let’s just say 0.5, and we could also maybe go a 0.5 on the Y as well, because really, we are only going to be detecting hits and all that with the coins, with the flag, with the cars, when the player is on the tile where it’s gonna be hit pretty much, so the clod doesn’t really matter too much. I just recommend making it a bit smaller than the actual sprite, to allow for some leeway.

And in order for us to be able to actually detect collisions, one of the objects that are colliding or triggering need to have a rigid body component, need to have that physics component attached. So we’re gonna go add components, and we gonna go Rigidbody 2D, and while we’re at it, let’s also make a Box Collide 2D a trigger, so that we can actually go through things and bounce off objects.

And down in our Rigidbody 2D, we don’t want to give the player any sort of mass, or any sort of velocity or gravity, we want our player to pretty much be how it is right now, but with a Rigidbody 2D component. And what we can do of that, is go up to where it says body type, and change that from dynamic to kinematic. And kinematic basically means that it’s got the Rigidbody 2D attached, we have access to the properties, but it’s not going to be affected by physics. Objects can push our player, gravity is not gonna be affecting it, so we have total control over where it goes, and how it interacts with everything. So, those are the components that we are going be attaching to our player.

Finally, let’s go ahead up in the Inspector here and change the tag of the player over to play here. You should have a player tag by default, and this is gonna be used for the coin, the car, and go to detect when they are hitting the player, okay? So they know that the object they’re colliding with, is the player. Okay, we can save that.

Now let’s go over to our prefabs folder and just drag that player in as a prefab so we can use it in future levels, and that is it. If we look in the game view now, you can see we have our player on screen, and of course, when we are actually creating our game, in the future lessons, we’re going to be having a sort of portrait mode aspect ratio, because this game is going to be targeted towards mobile phones, and you’re going to play it with your phone upright.

So, right now the resolution or not the resolution, but the aspect ratio is 16 by nine, meaning that, it is your default monitor size, so we’re gonna be resizing that later on with the device simulator. And in fact, we’re gonna be working on the devicing later in the next lesson, so we can actually get those mobile aspect ratios set up and ready to go.

So, thanks for watching and I’ll see you all in the next lesson.

Swipe Detection – Part 1

Welcome back everyone. In this lesson we are going to begin setting up the ability for our game to detect touches, thus moving the player forwards, left or right, okay.

So let’s begin by going to the scripts folder and creating a brand new C# script here. And this one is gonna be called Swipe Detection, okay. We can go ahead and create a new game object here in the hierarchy. We’re gonna create an empty object and this one is gonna be called _GameManager. Okay. It’s just where I like to store all my scripts on a game manager object here, such as Swipe Detection, you have any sort of overall management scripts.

And what we’re gonna do then is we are just gonna double click on this script to open it up inside of Visual Studio. Okay, and here we are, so first of all, what I’m gonna do is just delete these standard if functions since we can add those in later on when we need them.

And inside of this script, what were you going to be doing is detecting when we have put our finger down on the screen. And once that happens, we are gonna check to see if we have swiped the finger left, right or up. If we have swiped it up, we’re gonna move forward. If we swipe it left, we’re gonna move left. And if we swipe it right, we’re gonna move right. Okay. And this is gonna basically allow you to select anywhere on the screen to swipe. Okay. You don’t have to go in the center of the screen and swipe left or right. You can go to the bottom left of the screen and swipe right, and it’s gonna move you right.

So what we’re gonna do, first of all, is create a few variables. First of all, we’re gonna create a public player variable here. So make sure it is of type class player, which is the name of the script that we created a few lessons ago. And this is gonna basically store our player so that we can later on tell it to move once we have detected a certain swipe.

Next, we need to create a private vector2. And this is going to be for the startPos. Okay. And by start position, this basically means where is your finger touchdown on the screen for the first time, okay. And then from there, we’ll check to see if it’s left, up or right.

Then we need to create another public variable, public float. Actually, we may say public integer, and this is going to basically be how many pixels do we have to swipe in order for this to be detected? So this is gonna be called pixelDistToDetect. And by default, let’s make this equal to around, we’ll make it 20, okay, so you don’t have to swipe far. You only have to move your finger a little bit in a certain direction in order to have it detected.

And one more variable we need to create is going to be a private boolean. And this is going to basically be true or false for if we have a finger down. Okay. So I’m gonna hold this one fingerDown. And if we touch that finger down, that’s gonna be set the true. So once that is true, we can then detect if we’re swiping left, right or up.

Okay, so now what we need to do is create the update function. So void update, and inside here, we want to, first of all, check to see if we have pressed that finger down. So what we want to do is go if the finger down equals equals false. So if our finger is currently not down, and input .touchCount is greater than zero, so do we now have a finger on the screen? And is that finger, which is touching the screen, is that the first frame that it is down on the screen?

So for this, we can go input, Oops, not that big line of text, we just want to go and input.touches, and touches is an array. So we want to get the first touch out of that array, .phase equals equals TouchPhase.Began. Okay. So this is quite a big enough statement. We have three different conditions.

First of all, we’re checking to see if fingerDown is equal to false. Then we’re checking to see if we have more than zero touches on the screen. And then we’re checking to see if the first touch on the screen, if this is the first frame it is down. And if so, we are gonna go startPos equals Input.touches[0].position, okay. So the position on the screen where you’re touching down, and then we also want to go fingerDown equals true. And there we go. That’s how we detect basically if a finger is down for the first time. We set fingerDown to true and we set the start position to be where we put our finger down.

So, let’s save that, go down to the next line here. And the rest of this code is gonna be, if a finger is down on the screen, so, if fingerDown in this begin of statement right here, we then want to see, first of all, have we swiped upwards? Have we swiped our finger up, and to check that, we can go if the input.touches[0].position.Y, if this Y position is greater than or equals to our startPos.Y plus the pixel distance to detect, then this is gonna register as a swipe up.

So what we can do here is go fingerDown equals false, and then go Debug.log. And this is gonna be “Swipe up”. Okay, so, we have detected a swipe up, and as a matter of fact, we should be able to test this out inside of the editor, because right now we are checking for touch inputs, and since we are making this on a computer, we need a way of actually testing this out with our mouse. And what we’re gonna do is at the bottom here, at the bottom of the if statement oh, I mean the update function, I’m gonna go // and this is gonna be for TESTING, okay.

And in here, we’re gonna go if fingerDown equals equals false. So basically we’re doing the same code we have right here.

And as a bit of a challenge, I want you to go ahead and see if you can sort of duplicate this code we have right here, but use it in terms of the mouse, okay? You might need to look up some stuff online if you’re not too sure on certain things on how to get the mouse position, but I want you to have a go at this and then we’ll be right back to see how you done.

Okay, welcome back. I hope you had a go at that. So let’s have a look at how we can do this. So for detecting, first of all, if our finger or our mouse is down, we want to go if fingerDown equals equals false, and the Input.GetMouseButtonDown(0), so this is gonna be true on the frame. The left mouse button down, the left mouse button is down. And then if our finger is down, we just want to see if the Input.mousePosition.Y is greater than or equals to startPos.Y plus the pixel distance to detect.

Okay. So we’re just using Input.GetMouseButtonDown and Input.mousePosition for the different values. Okay? So we can save this, return to the Unity editor, and let’s go to our game manager object right here. We don’t have to give it a player. So let’s just go ahead and press play, and let’s try and swipe upwards. Okay. So it done that by default, don’t know why, but if we click and drag swipe up, if I swipe left.

Now you’ll see you might get a lot of errors like this. And the reason why is because there is some problems when it comes to actually checking to see if the finger is down. Maybe if you don’t move it in the correct position, or you move it in different direction, it doesn’t calculate things right.

What we need to do is make it so that if our finger is all of a sudden up or if our mouse button is up and off the screen, set finger down to false and reset the start position. So here we are going to create a new if statement called if fingerDown and Input.GetMouseButtonUp(0) for the left mouse button, then what we want to do is just go, oops, here, what we want to do is just set fingerDown, equals false, okay, that’s what we want to do there.

So if we go back to the editor and press play again, you should see that these errors are no longer appearing. So if we swipe up, there we go. Swipe down, nothing happens. We can swipe left, nothing happens, swipe right, nothing happens. Sometimes you may get a swipe up if you swipe right, so what we can do in that sense is change the pixels distance to detect, let’s change this to maybe 50. And now if we swipe up, we have to swipe a bit further in order for it to detect.

But if we swipe left and right, you should see that you’re not really getting any swipe ups, unless it’s on a bit of an angle. Okay? So, we’ve got swiping up. I’m gonna keep our pixel distance to detect at 50 here. And let’s also add in this little bit of code for the finger down in terms of touch.

So here, we’re just gonna go: If fingerDown and Input.touchCount is greater than zero and Inputs.touches, the first touch… So touches array with zero here for the first one, .phase equals equals TouchPhase.ended. Okay? So when the finger is released from the screen, here what we want to do is just go, like before, fingerDown equals false. And remember that we are creating two sets of code here, one for our touch inputs on a mobile device, and one for using the mouse for testing it out here inside of Unity. Okay. So we’ve got swiping up done.

Now in the next lesson, we are gonna be working on getting swiping left and swiping right. As well as having a player actually move around when they have been swiped. So see you all then in the next lesson.

Swipe Detection – Part 2

Welcome back everyone. In this lesson, we are going to be continuing on with our swipe detection script right here detecting when we have pressed our mouse or finger down on the screen and swiped up, left, or right. So in this lesson, we are gonna be adding in left and right swipe detections.

So to do this, we can go down to where we check and see if our finger is down and here is where we detect if we are touching and swiping upwards, now to detect the left, we can just go here, else if and then we can go input.touches[0].position.x is less than or equal to startPos.y minus the pixelDistToDetect. Okay, and if this is the case, we can go fingerDown = false and then go Debug.Log and in here, we want to go Swipe left and for swiping right.

We can go else if Input.touches[0].pos.x is greater than or equals to StartPos.y, oh, .x; actually, and in fact, let’s go here and change this StartPos.y to StartPos.x since we do wanna go along the horizontal axis, not the vertical for left and right back here, we can go, so if our touch position.x is greater than or equal to StartPos x plus the pixelDistanceToDetect. Then we want to go finger down equals false and then, not finger, finger down, so fingerDown equals false and Debug.log swipe right.

Okay, so that is how we can set it up for touch input, now, as bit of a challenge, go ahead and try, go down here where we have our input for our mouse and set it up for that. Okay, go ahead and I’ll be right back to see how you done.

Okay, I hope you had a go at that, pretty much it is the exact same as we done previously where all we had to do was change originally where it says Input.touches[0].position to be Input.mousePosition. Whatever in order to get the position of the mouse rather than the position of the touch.

So, we can save that, return to the Unity Editor and if we press play- in fact, let’s clear this first, press play, you should that we can swipe up in order to get the swipe up detections, we can swipe left, we can swipe right, and there we go.

So, left, right, up, and nothing for down, but we’ll get a right for down and since we are going on a bit of an angle, so there you go, we can swipe up to move forward, swipe left to move right, or swipe left to move left I mean, and swipe right to move right.

Now, how do we actually set it up so our player moves in that way, well, what we can do, is open up our player script by double-clicking on it, I’m gonna remove these start an update functions here and what we’re gonna do first of all is create some variables.

So, first of all, let’s get a public float moveSpeed, now a moveSpeed is going to define how long it takes to get from one tile to the other, so if we swipe left, it moves left one tile and how fast is it gonna get from that tile to the left one then we need a private Vector3 for the target position, so targetPos is basically going to be where is this player trying to get to and inside of the Start function. We can just set the targetPos to be whatever our existing position is right now since we don’t want the player moving anywhere at the start.

And then what we want to do is create a new function called public void Move and inside of the Move function here, it is going to carry over a parameter of a Vector3 called moveDirection, okay, and this is just going to be either up, left, or right, and inside of here. What we’re going to do is basically just go targetPos plus equals moveDirection, okay, and that’s all we want to do for this and we’ve set our target position but how do we actually move toward that target position?

Well, over inside of the update function we can go ahead and create that now so we can just go void Update and inside of here, we just want to over time, move towards our target position, so here we’ll go transform.position equals vector3.MoveTwards our current position is gonna be transform.position and our target is going to be the target position and we want to move at a move rate of moveSpeed multiplied by Time.deltaTime.

We are multiplying by Time.deltaTime in order to convert it from whatever our move speed is per frame to per second, so, if you do have varying frame rates, you’ll still be moving at the same speed.

Okay, so back over in our swipe detection script now, what we can do is go up to where we’re debug logging all of these swipe up, swipe left, and swipe right. And I’m gonna delete the swipe up here and I’m gonna replace this with player.Move and inside here. We need to give it a move direction, so I’m gonna go vector3.up and vector3.up is just a vector that is zero on the x, one on the y and zero on the zed.

Okay, so, it’s just one on the y up, for swipe left, we can just go player.Move and then give that a vector3.left to swipe left, in order to move left I mean, and then for right, we can go player.Move and give that one there a vector3.right.

Okay, and we wanna go down here and do the exact same for our mouse detection and there we go, okay, so now what we can do is save that and return to the Unity Editor and all we need to do here is select our player, we need to go to where our move speed is and change this to something, so, what do we want to set this to, well.

We wanna move tiles pretty fast, so I’m going to set this to maybe something around five, we can then select our Game Manager and drag our player in to the player property here, so it is now linked to the player.

Press play and let’s just see how it goes. We can swipe up, there we go, player moves up, swipe left, player moves left, swipe right, player moves right and we can keep swiping up, left, right as much as we wish.

But as you can see, the camera is not following the player, so in the next lesson, we are gonna work on it so that our camera can actually follow our player. And we’ll make it as well so that our player cannot go off-screen because watch this, I can go right again and I can keep swiping right and if you look at our player game object, look at the x position. You’ll see that our player keeps on moving to the right, we don’t want that, we want the player to only be able to move within a certain bound on the left and right axis.

Okay, so, in the next lesson, we’ll set up our camera and we’ll set up clamping our player position, so, thanks for watching and I’ll see you all in the next lesson.

Interested in continuing? Check out the full Build a Mobile Road Crossing Game course, which is part of our Mobile Game Development Mini-Degree.

]]>
Create a Ski Mini-Game in Unity for Beginners https://gamedevacademy.org/unity-ski-mini-game-tutorial/ Wed, 10 Aug 2022 04:33:57 +0000 https://gamedevacademy.org/?p=18484 Read more]]> While Unity is a fantastic tool, there are a lot of aspects to it. From learning C# coding principles to simply knowing how to use the features Unity offers, it can seem like a daunting task to go from complete beginner to making your first project. What if there was a middle ground, though?

In this tutorial, we’re going to do just that: explore the middle ground. We’ll be creating a ski mini-game project in Unity that uses collisions as its core mechanic – one of the primary tools you’ll need to be able to make many kinds of games. While some basic Unity experience is advised, the explanations here are perfect for those still setting out on their Unity journey and looking for an easy game to start with!

Let’s dive into it!

Project Files

You can find the source code files for the project done in this tutorial available for download here.

BUILD GAMES

FINAL DAYS: Unlock 250+ coding courses, guided learning paths, help from expert mentors, and more.

Getting Started

First off, with Unity open, let’s create a new Scene called “Collisions” and set up a new Plane for the ground:

Setting up a new Plane for the ground

To create a slope, we’ll rotate the plane by 35 degrees on the x-axis as follows:

Rotating the plane by 35 degrees

Let’s then create our Player using the primary Sphere and Cube. These model meshes should be contained in an empty parent GameObject.

Creating the Player

Player hierarchy in the scene

We can also create a Tree by adding a Cube and scaling it up along the y-axis:

Creating a Tree

Now we can position our Main Camera to be looking down at our Player from the top of the hill.

Positioning the camera to look down at the Player

Moving The Player

In order for the Player GameObject to be affected by gravity, we need to add a Collider and a Rigidbody component to it.

Adding a Collider and a Rigidbody to the Player

Note that the Freeze Rotation settings are enabled for all three axes (x,y,z) inside the Rigidbody component. This prevents our Player from tipping over and rolling instead of sliding down the hill.

One last thing we need to do is to reduce the Friction between the colliders so that it looks like we’re sliding down on a slippery surface.

To do this, create a new Physic Material (right-click in Project window > Create > Physic Material):

Creating a new Physic Material

And set the Static Friction to be zero:

Setting the Static Friction to zero

And apply it to our Player (Collider) and the Ground and the Tree by dragging it straight into the Scene view.

Applying the Physic Material to the Player and Ground

Applying the Physic Material to the Tree

Setting up the Player Controller

In order to move the player left and right, we need to set up the Player Controller (that is, the C# script attached to the Player GameObject):

Player Controller

Let’s open up the script and declare the following variables:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerController : MonoBehaviour
{
    public float moveForce;     // Force applied when we move left or right.
    public Rigidbody rig;       // A referene to our Rigidbody component.
}

Update vs FixedUpdate

The Update function is a built-in function that comes with MonoBehaviour class. Since it gets called every frame, it is useful to implement any game script that needs to be constantly updated.

However, doing physics calculations in the Update function is not recommended, as you will get inconsistent results across different devices. This is because each device comes with different frame rates.

Hence when dealing with Rigidbody, we recommend using FixedUpdate instead of Update. By simulating physics in every fixed frame (e.g. 60 fps), we can yield consistent results across varying devices:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerController : MonoBehaviour
{
    public float moveForce;     // Force applied when we move left or right.
    public Rigidbody rig;       // A referene to our Rigidbody component.

    // Called 60 times a second.
    // Similar to the Update function, but used for physics calculations.
    void FixedUpdate ()
    {
    }
}

Player Input

Inside the FixedUpdate function, we’re going to register our player’s input on whether to move left or right.

We can use Input.GetAxis (built-in function) to get the value of the horizontal axis, which is by default mapped to the left and right arrow keys. The value will be in the range of -1 (left) to 1 (right):

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerController : MonoBehaviour
{
    public float moveForce;     // Force applied when we move left or right.
    public Rigidbody rig;       // A referene to our Rigidbody component.

    // Called 60 times a second.
    // Similar to the Update function, but used for physics calculations.
    void FixedUpdate ()
    {
        // Get the horizontal input.
        // 0 = nothing
        // 1 = right
        // -1 = left
        float xInput = Input.GetAxis("Horizontal");
    }
}

We’re then going to add force to our Player GameObject based on our input:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerController : MonoBehaviour
{
    public float moveForce;     // Force applied when we move left or right.
    public Rigidbody rig;       // A referene to our Rigidbody component.

    // Called 60 times a second.
    // Similar to the Update function, but used for physics calculations.
    void FixedUpdate ()
    {
        // Get the horizontal input.
        // 0 = nothing
        // 1 = right
        // -1 = left
        float xInput = Input.GetAxis("Horizontal");

        // Add force based on our input.
        rig.AddForce(Vector3.right * xInput * moveForce);
    }
}

Coding the Tree Script

Let’s begin work on our Tree’s behavior by attaching a new script to the Tree GameObject:

Creating a script for the Tree GameObject

We’re going to add the OnCollisionEnter function inside the script, which is called when the collider has begun touching another rigidbody or collider:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Tree : MonoBehaviour
{
    // Called when another object collides with us.
    void OnCollisionEnter (Collision collision)
    {
    }
}

When we hit the tree, we can change the color of the tree by accessing the MeshRenderer component’s material.color property:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Tree : MonoBehaviour
{
    public Color hitColor;      // The color we want to set when we get hit.
    public MeshRenderer mr;     // A reference to the MeshRenderer component.

    // Called when another object collides with us.
    void OnCollisionEnter (Collision collision)
    {
        // Set our color to be "hitColor".
        mr.material.color = hitColor;
    }
}

Ensure the HitColor property is set in the Inspector after saving the script:

Setting the HitColor property in the Inspector

Now you can test it out in Play mode and duplicate the tree to complete the level:

Testing the game in Play mode

Duplicating the Tree object

Conclusion

And that covers the basics of this beginner’s ski game with Unity! Well done on making it to the end!

While a very small project, being able to work with colliders and physics will have huge implications for your future game projects. Of course, you can also expand your skills by expanding this project. Try adding collectibles for the player to get along their path down the slope. Then try adding some sort of scoring so you can render win and game over conditions. If you’re up for a real challenge, you can even explore ways to make the level loop! The sky is the limit here.

Regardless, we hope that you can apply the physics of sliding objects down surfaces and avoiding obstacles learned here to your future projects – and mostly that you had fun while following this tutorial!

Want to learn more about farming sims? Try our complete Unity Mini-Projects – C# Fundamentals course.

BUILD YOUR OWN GAMES

Get 250+ coding courses for

$1

AVAILABLE FOR A LIMITED TIME ONLY

]]>
How to Set Up Crops in Unity for Farming Games https://gamedevacademy.org/unity-farm-crop-tutorial/ Tue, 09 Aug 2022 09:59:24 +0000 https://gamedevacademy.org/?p=16425 Read more]]> Since the success of Stardew Valley, farming sims are more popular than ever before – and it doesn’t take much development experience to make them.

In this Unity tutorial, we’re going to cover how to set up the most essential component of farming-based games: planting crops. This tutorial will be based around a grid-based, top-down 2D project, but many of these concepts can be retrofitted as needed for 3D as well.

While some basic Unity experience is required, including knowledge of how to set up top-down 2D player characters, these explanations will be very beginner-friendly!

If you’re ready to start learning farming mechanics, let’s dive into Unity!

Project Files

While you’ll need to set up your own Unity project, we have included a full copy of the code files used in this tutorial, as well as sprite assets used.

Download Project Files Here

BUILD GAMES

FINAL DAYS: Unlock 250+ coding courses, guided learning paths, help from expert mentors, and more.

Setting up Crop Data

To start our tutorial off, we’re first going to set up our crop data and our game manager that will control the entire aspect of how crops are planted. We will be setting up our data based around a top-down, 2D game with grid-based, interactable tiles.

Data Setup

To start, let’s create a new C# script called “CropData”. This script is going to contain all the information specific to the crop we grow.

This script isn’t going to be attached to any GameObject. Instead, we want to create an asset for each of the different types of crop. To do this, simply replace MonoBehaviour with ScriptableObject and use the CreateAssetMenu property to create a menu item for it.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu(fileName = "Crop Data", menuName = "New Crop Data")]
public class CropData : ScriptableObject
{
}

This will allow us to right-click on the Project window to create a new Crop Data asset.

Unity Create Menu showing New Crop Data menu item

We’re going to create one for “Wheat”.

Crops will display different sprites depending on the number of days it has grown for. Let’s declare the following variables inside the script to track these sprites, as well as a few other details related to the crop (such as sell price):

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu(fileName = "Crop Data", menuName = "New Crop Data")]
public class CropData : ScriptableObject
{
    public int daysToGrow;
    public Sprite[] growProgressSprites;
    public Sprite readyToHarvestSprite;

    public int purchasePrice;
    public int sellPrice;
}

Now we can save the script and go back to the Editor to start filling out the crop data for Wheat. You can fill whatever data you want, but we used:

  • Days to Grow: 6
  • Grow Progress Sprites & Ready To Harvest Sprite: With the course files, we includes our wheat crop sprite which we sliced from a single sprite.
  • Purchase Price: 20
  • Sell Price: 35

Unity Inspector showing crop data for Wheat

GameManager

To manage the crops, we will create a new C# script called “GameManager“. We need to know primarily what the current day is, how much money we have, and what crop we want to plant.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using TMPro;

public class GameManager : MonoBehaviour
{
    public int curDay;
    public int money;
    public CropData selectedCropToPlant;
}

We can set up a Singleton for this script so that we can easily access this script from other scripts as well.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using TMPro;

public class GameManager : MonoBehaviour
{
    public int curDay;
    public int money;
    public CropData selectedCropToPlant;

    // Singleton
    public static GameManager instance;

    void Awake ()
    {
        // Initialize the singleton.
        if(instance != null && instance != this)
        {
            Destroy(gameObject);
        }
        else
        {
            instance = this;
        }
    }
}

Now we want to implement the following functionalities:

  • Whenever a new day takes over, we will trigger an event to notify the crops to grow.
  • We can purchase, plant, and harvest crops

Let’s create some dummy functions first:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using TMPro;

public class GameManager : MonoBehaviour
{
    public int curDay;
    public int money;
    public int cropInventory;

    public CropData selectedCropToPlant;

    public event UnityAction onNewDay;

    // Singleton
    public static GameManager instance;

    void Awake ()
    {
        // Initialize the singleton.
        if(instance != null && instance != this)
        {
            Destroy(gameObject);
        }
        else
        {
            instance = this;
        }
    }

    // Called when a crop has been planted.
    // Listening to the Crop.onPlantCrop event.
    public void OnPlantCrop (CropData cop)
    {
    }

    // Called when a crop has been harvested.
    // Listening to the Crop.onCropHarvest event.
    public void OnHarvestCrop (CropData crop)
    {
    }

    // Called when we want to purchase a crop.
    public void PurchaseCrop (CropData crop)
    {
    }

    // Do we have enough crops to plant?
    public bool CanPlantCrop ()
    {
    }

    // Called when the buy crop button is pressed.
    public void OnBuyCropButton (CropData crop)
    {
    }
}

Crop Script

Next, let’s set up the ability to actually grow our crops.

Crop Variables

Let’s create a new C# script called “Crop“. This is going to spawn in the crops once we put the seeds down.

First of all, we need to declare the variables and make sure to set up UnityEngine.Events so we can automatically trigger events when we plant or harvest a crop:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;

public class Crop : MonoBehaviour
{
    private CropData curCrop;
    private int plantDay;
    private int daysSinceLastWatered;

    public SpriteRenderer sr;

    public static event UnityAction<CropData> onPlantCrop;
    public static event UnityAction<CropData> onHarvestCrop;
}

Harvesting & Watering

We can then keep track of the number of days that the crop has been planted (i.e. Crop Progress), by subtracting plantDay from GameManager.curday.

Let’s return a boolean to check if the crop is old enough for harvesting.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;

public class Crop : MonoBehaviour
{
    private CropData curCrop;
    private int plantDay;
    private int daysSinceLastWatered;

    public SpriteRenderer sr;

    public static event UnityAction<CropData> onPlantCrop;
    public static event UnityAction<CropData> onHarvestCrop;

    // Returns the number of days that the crop has been planted for.
    int CropProgress ()
    {
        return GameManager.instance.curDay - plantDay;
    }

    // Can we currently harvest the crop?
    public bool CanHarvest ()
    {
        return CropProgress() >= curCrop.daysToGrow;
    }
}

Now, when we harvest the crop, we’re going to invoke the onHarvestCrop event and destroy the crop gameObject. At the same time, we’ll also add our water function, which simply changes daysSinceLastWatered to 0.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;

public class Crop : MonoBehaviour
{
    private CropData curCrop;
    private int plantDay;
    private int daysSinceLastWatered;

    public SpriteRenderer sr;

    public static event UnityAction<CropData> onPlantCrop;
    public static event UnityAction<CropData> onHarvestCrop;

    // Called when the crop has been watered.
    public void Water ()
    {
        daysSinceLastWatered = 0;
    }

    // Called when we want to harvest the crop.
    public void Harvest ()
    {
        if(CanHarvest())
        {
            onHarvestCrop?.Invoke(curCrop);
            Destroy(gameObject);
        }
    }

    // Returns the number of days that the crop has been planted for.
    int CropProgress ()
    {
        return GameManager.instance.curDay - plantDay;
    }

    // Can we currently harvest the crop?
    public bool CanHarvest ()
    {
        return CropProgress() >= curCrop.daysToGrow;
    }
}

Note that the question mark next to the unity event (onHarvestCrop?.Invoke) allows us to invoke it only if we have functions listening to the event. This effectively prevents errors from popping up.

When the crop has progressed, we can check if the crop is ready to be harvested. If it is, then we should change the sprite of the crop.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;

public class Crop : MonoBehaviour
{
    private CropData curCrop;
    private int plantDay;
    private int daysSinceLastWatered;

    public SpriteRenderer sr;

    public static event UnityAction<CropData> onPlantCrop;
    public static event UnityAction<CropData> onHarvestCrop;

    // Called when the crop has progressed.
    void UpdateCropSprite ()
    {
        int cropProg = CropProgress();

        if(cropProg < curCrop.daysToGrow)
        {
            sr.sprite = curCrop.growProgressSprites[cropProg];
        }
        else
        {
            sr.sprite = curCrop.readyToHarvestSprite;
        }
    }

    // Called when the crop has been watered.
    public void Water ()
    {
        daysSinceLastWatered = 0;
    }

    // Called when we want to harvest the crop.
    public void Harvest ()
    {
        if(CanHarvest())
        {
            onHarvestCrop?.Invoke(curCrop);
            Destroy(gameObject);
        }
    }

    // Returns the number of days that the crop has been planted for.
    int CropProgress ()
    {
        return GameManager.instance.curDay - plantDay;
    }

    // Can we currently harvest the crop?
    public bool CanHarvest ()
    {
        return CropProgress() >= curCrop.daysToGrow;
    }
}

New Day

When a new day takes over, we will increment the daySinceLastWatered, and destroy the crop if it has been more than 3 days.

If it hasn’t, then we can call UpdateCropSprite.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;

public class Crop : MonoBehaviour
{
    private CropData curCrop;
    private int plantDay;
    private int daysSinceLastWatered;

    public SpriteRenderer sr;

    public static event UnityAction<CropData> onPlantCrop;
    public static event UnityAction<CropData> onHarvestCrop;

    // Called when a new day ticks over.
    public void NewDayCheck ()
    {
        daysSinceLastWatered++;

        if(daysSinceLastWatered > 3)
        {
            Destroy(gameObject);
        }

        UpdateCropSprite();
    }

    // Called when the crop has progressed.
    void UpdateCropSprite ()
    {
        int cropProg = CropProgress();

        if(cropProg < curCrop.daysToGrow)
        {
            sr.sprite = curCrop.growProgressSprites[cropProg];
        }
        else
        {
            sr.sprite = curCrop.readyToHarvestSprite;
        }
    }

    // Called when the crop has been watered.
    public void Water ()
    {
        daysSinceLastWatered = 0;
    }

    // Called when we want to harvest the crop.
    public void Harvest ()
    {
        if(CanHarvest())
        {
            onHarvestCrop?.Invoke(curCrop);
            Destroy(gameObject);
        }
    }

    // Returns the number of days that the crop has been planted for.
    int CropProgress ()
    {
        return GameManager.instance.curDay - plantDay;
    }

    // Can we currently harvest the crop?
    public bool CanHarvest ()
    {
        return CropProgress() >= curCrop.daysToGrow;
    }
}

Initial Values

Finally, we will set up the initial values for the variables when we first plant the crop (i.e. curCrop, plantDay, daysSinceLastWatered).

Once they’re set, we can update the crop sprite and invoke the onPlantCrop event.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;

public class Crop : MonoBehaviour
{
    private CropData curCrop;
    private int plantDay;
    private int daysSinceLastWatered;

    public SpriteRenderer sr;

    public static event UnityAction<CropData> onPlantCrop;
    public static event UnityAction<CropData> onHarvestCrop;

    // Called when the crop has been planted for the first time.
    public void Plant (CropData crop)
    {
        curCrop = crop;
        plantDay = GameManager.instance.curDay;
        daysSinceLastWatered = 1;
        UpdateCropSprite();

        onPlantCrop?.Invoke(crop);
    }

    // Called when a new day ticks over.
    public void NewDayCheck ()
    {
        daysSinceLastWatered++;

        if(daysSinceLastWatered > 3)
        {
            Destroy(gameObject);
        }

        UpdateCropSprite();
    }

    // Called when the crop has progressed.
    void UpdateCropSprite ()
    {
        int cropProg = CropProgress();

        if(cropProg < curCrop.daysToGrow)
        {
            sr.sprite = curCrop.growProgressSprites[cropProg];
        }
        else
        {
            sr.sprite = curCrop.readyToHarvestSprite;
        }
    }

    // Called when the crop has been watered.
    public void Water ()
    {
        daysSinceLastWatered = 0;
    }

    // Called when we want to harvest the crop.
    public void Harvest ()
    {
        if(CanHarvest())
        {
            onHarvestCrop?.Invoke(curCrop);
            Destroy(gameObject);
        }
    }

    // Returns the number of days that the crop has been planted for.
    int CropProgress ()
    {
        return GameManager.instance.curDay - plantDay;
    }

    // Can we currently harvest the crop?
    public bool CanHarvest ()
    {
        return CropProgress() >= curCrop.daysToGrow;
    }
}

Event Listeners

We now need to register listeners for the events we made. Right now the events are invoked, but there are no functions listening to them.

Let’s open up the GameManager script, and subscribe to the events inside OnEnable.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using TMPro;

public class GameManager : MonoBehaviour
{
    public int curDay;
    public int money;
    public int cropInventory;

    public CropData selectedCropToPlant;

    public event UnityAction onNewDay;

    // Singleton
    public static GameManager instance;

    void OnEnable ()
    {
        Crop.onPlantCrop += OnPlantCrop;
        Crop.onHarvestCrop += OnHarvestCrop;
    }

    void OnDisable ()
    {
        Crop.onPlantCrop -= OnPlantCrop;
        Crop.onHarvestCrop -= OnHarvestCrop;
    }
  ...
}

Here we can define what to execute when onPlantCrop and onHarvestCrop are invoked.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using TMPro;

public class GameManager : MonoBehaviour
{
    public int curDay;
    public int money;
    public int cropInventory;

    public CropData selectedCropToPlant;

    public event UnityAction onNewDay;

    // Singleton
    public static GameManager instance;

    void OnEnable ()
    {
        Crop.onPlantCrop += OnPlantCrop;
        Crop.onHarvestCrop += OnHarvestCrop;
    }

    void OnDisable ()
    {
        Crop.onPlantCrop -= OnPlantCrop;
        Crop.onHarvestCrop -= OnHarvestCrop;
    }


    // Called when a crop has been planted.
    // Listening to the Crop.onPlantCrop event.
    public void OnPlantCrop (CropData cop)
    {
        cropInventory--;
    }

    // Called when a crop has been harvested.
    // Listening to the Crop.onCropHarvest event.
    public void OnHarvestCrop (CropData crop)
    {
        money += crop.sellPrice;
    }
}

Planting Crops

Last but not least, we need to be able to plant crops, so we will set up an Interact function that can be called by the player whenever they interact with the tiles we can plant on.

Tile Interaction

On any script that is controlling your field tiles, add in the Interact function (which will ultimately be invoked by your player character in whatever manner you choose):

// Called when the player interacts with the tile.
public void Interact ()
{
    if(!tilled)
    {
        Till();
    }
    else if(!HasCrop() && GameManager.instance.CanPlantCrop())
    {
        PlantNewCrop(GameManager.instance.selectedCropToPlant);
    }
    else if(HasCrop() && curCrop.CanHarvest())
    {
        curCrop.Harvest();
    }
    else
    {
        Water();
    }
}

After this, we’ll create a new function called PlantNewCrop, which takes a parameter of CropData (which is the crop we want to plant).

Planting should only occur if the tile is tilled.

// Called when we interact with a tilled tile and we have crops to plant.
void PlantNewCrop (CropData crop)
{
    if(!tilled)
        return;

    curCrop = Instantiate(cropPrefab, transform).GetComponent<Crop>();
    curCrop.Plant(crop);

    GameManager.instance.onNewDay += OnNewDay;
}

Note that we’re subscribing to the GameManager’s OnNewDay event here rather than OnEnable, because not every tile needs to listen to the event. We want to subscribe to it once we have a crop planted.

Next, we’ll create a function for Till and Water, where we will switch the tile’s sprite.

// Called when we interact with a grass tile.
void Till ()
{
    tilled = true;
    sr.sprite = tilledSprite;
}

// Called when we interact with a crop tile.
void Water ()
{
    sr.sprite = wateredTilledSprite;

    if(HasCrop())
    {
        curCrop.Water();
    }
}

If we no longer have any crop on this tile, then we just want to reset the tile and unsubscribe from the OnNewDay event.

If we do have a crop planted and a new day occurred, then we need to trigger the crop’s NewDayCheck:

// Called every time a new day occurs. 
// Only called if the tile contains a crop.
void OnNewDay ()
{
    if(curCrop == null)
    {
        tilled = false;
        sr.sprite = grassSprite;

        GameManager.instance.onNewDay -= OnNewDay;
    }
    else if(curCrop != null)
    {
        sr.sprite = tilledSprite;
        curCrop.NewDayCheck();
    }
}

Finishing Up

Let’s save this script and go to the Editor to test it out.

Make sure that the Crop script has the sprite renderer assigned:

Unity Inspector showing Crop with the Sprite Renderer

Save the Crop GameObject as a prefab and assign sprites to your tile object. We’ve included an example of our FieldTile script so you can see how we did it, but your results will vary.

Unity showing crop-based Prefabs for tutorial

Unity Inspector showing FieldTile example script

Finally, we can set up the GameManager with the public variables filled in.

Unity Inspector showing farming-based Game Manager

We can now till the ground, water the ground, and plant crops!

Screenshot of farming sim made with Unity

Conclusion

And that covers the basics of setting up farming mechanics for farming sim games! Congratulations for making it through!

As mentioned, farming is very popular, and it can add variety to tried and true genres. However, keep in mind our way is not the only way. Depending on your own game project, you may need to adapt these systems. However, we’ve designed these systems to be expandable and fit in with most top-down, 2D games.

From here, though, you can try out tons of other features using the same fundamentals. Perhaps you want to have livestock, which you can also set up as Scriptable Objects and utilize the Unity events system to also have an invokable Interact function. Or, maybe you want to create a farming sim on an alien world where the crops can be poisonous! The choice is yours!

Regardless, we hope you’ve expanded your horizons with farming, and we wish you the best of luck with your future projects!

Want to learn more about farming sims? Try our complete Construct a Micro-Farming RPG course.

]]>
How to Create a Multi-Platform Idle Clicker Game with Phaser https://gamedevacademy.org/phaser-tutorial-how-to-create-an-idle-clicker-game/ Thu, 23 Jun 2022 13:52:49 +0000 https://gamedevacademy.org/?p=2642 Read more]]> Since the dominance of mobile games in the industry, no genre is more popular than the idle clicker.

In this tutorial, we’re going to use the well-established Phaser 2 framework – which offers cross-platform capabilities – to build an idle clicker game where you “attack” monsters to progress in the game. Of course, we’ll also set up the ability to buy auto-clickers that will “attack” monsters for you as well.

If you’re ready to explore this in-demand genre, let’s learn!

What is an idle click game?

Also known as clicker and incremental games, these type of games have you clicking something repeatedly or idling to gain some form of currency (e.g. cookies, money, energy) which you then use to buy upgrades. It’s a very simple concept at the core, but quite addictive!

Clicker games were first made popular in 2013 with a game called Cookie Clicker. Since then many games have been created in this genre, the themes and flavor of these games vary widely. From cookies to fantasy rpg, sci fi, farming, sand castles, etc.

One such clicker game that I’ve played quite a bit is Clicker Heroes, it’s a fantasy RPG style game where you click various monsters to progress. In this tutorial, we are going to build the foundations of a clicker game similar to Clicker Heroes that you can build upon and add your own style and flair.

Screenshot of Clicker Heroes game

Tutorial source code

You can download the tutorial source code here.

BUILD GAMES

FINAL DAYS: Unlock 250+ coding courses, guided learning paths, help from expert mentors, and more.

Getting started

Source Control

The first thing that I do when starting any project is create a folder, and initialize it for git source control. If you don’t already have git, you can download it for your OS from the official site. With any software development, it is critical to have backups. Using source control, specifically git, is a much more robust and safe solution than simply copying or zipping your files periodically. It’s also important to do micro commits, save your progress in very small increments so that you can roll back to any point if you find that you’ve added some new code that is breaking everything. Also it prepares your codebase automatically for upload to a service like github or bitbucket. There are many things beyond simply committing your code that you can do with git, if you are new to git I encourage you to checkout the Git and Github Fundamentals course at Zenva Academy.

After installing git for your system, open the folder you created in a command window, and simply type git init  and it will be ready to go.

Gathering Art

We need to get some sprites for the monsters. A great site to find free art that you can use for your projects is OpenGameArt.org. Much of the artwork is either public domain or licensed to the Creative Commons. A quick search and I’ve found a resource with a variety of monster sprites. This particular set is licensed under CC BY SA 3.0 which basically means that you must give credit to the original authors, and any modifications you make must be shared under the same license. There are other licensing options available to artists, and some do not allow the use of the resources in commercial applications, so be sure to check the licensing on the site.

OpenGameArt.org website with CC-BY-SA 3.0 license highlighted

The monster images that I’ve chosen come in various sizes, each with 4 frames representing various damage states. For this game, we don’t really need the extra damage states, so I have cropped all of the images to just the first frame. For the purposes of this tutorial, I think that 1 image per monster is all that we’ll need. It would be nice if these monsters were animated, but the single image works well for a placeholder right now.

In addition to the monsters, we’ll need some rpg icons for the upgrades and loot. It’s not likely that we’ll use all 496 images in this set, but we can prune the collection later before we are ready to release of the ones that we don’t use. We’ll also need something to use as a background for our world, this forest scene will do nicely.

You’ll find all of the sprites in the assets/images folder of the companion source code to this project. If you’re downloading your own selection of images to use, place them in there as well.

Reminder: Once you’ve added your files, go ahead and commit them to source control.

Setup Phaser

You’ll need to download Phaser, you can either clone the github repo or download the release or use something like Bower to install it. Phaser games are web based games, so first we need a HTML page to host it. Create a file called index.html in the root of your project folder and put this for the contents.

<!doctype html>
<html>
    <head>
        <meta charset="utf-8">
        <title>Click of the Titans</title>
        <style>body {margin: 0;padding: 0;}</style>

        <script src="lib/phaser.min.js"></script>

        <script src="src/game.js"></script>
    </head>
    <body>

    </body>
</html>

Reminder: micro commits, commit your index.html file right now!

You may have noticed that we added a reference to game.js located in the src folder. We don’t have that file yet, let’s create it now.

var game = new Phaser.Game(800, 600, Phaser.AUTO, '');

game.state.add('play', {
    preload: function() {
        game.load.image('skeleton', 'assets/allacrost_enemy_sprites/skeleton.png');
    },
    create: function() {
        var skeletonSprite = game.add.sprite(450, 290, 'skeleton');
        skeletonSprite.anchor.setTo(0.5, 0.5);
    },
    render: function() {
        game.debug.text('Adventure Awaits!', 250, 290);
    }
});

game.state.start('play');

In Phaser, everything starts with an instance of the Game class. We are passing it the width and height of the game screen that we want as well as the renderer. Phaser supports both Canvas and WebGL based rendering, Phaser.AUTO tells it to pick based on what’s available in the browser (WebGL if available).

In the preload phase of our “play” game state we are going to load up one of our monster images so that we can have something to show other than a blank screen. Each state in Phaser has several phases in its lifecycle, and preload  is one of the first.

Next up is create , after assets are loaded, it’s safe to create sprites using them. The Sprite is one of the main game objects in Phaser, most everything that you create in the game world will generally have a sprite involved. Adding a sprite takes a few parameters: the x & y coordinates of where it should be located on the screen, and a key that can be used to reference it later. We’re also going to change the anchor for the sprite to the center of the image. The anchor is the point in space where the sprite is positioned or rotated around. By default the anchor is set to the top left most point of the image 0, 0  I ususally like to work with the anchor in the center of the image, because if I want to spin the sprite, I want it to spin around the center instead of the top left (like a wheel).

Finally, render  is one of the last phases in the lifecycle, it happens after update (we don’t need update for this game). Most of the time Phaser handles rendering internally, but for now we’ll just add some fun text to make our screen more exciting.

Reminder: now’s a great time to commit your file!

Running your game

We’re almost ready to fire up Phaser and see what we have, except that it’s not just as simple as clicking on index.html and loading it in your browser. Due to security restrictions the browser will not allow you to load assets asynchronously. For that reason you need to run a server, or load the files in a different manner. PhotonStorm has posted an article listing several options for servers, however if loading the software to run a server isn’t something that you are interested in, I have another option. If you are running Google Chrome, you can actually setup your game to run as a Chrome application quite easily. Doing this elevates your game out of the browser sandbox (and actually gives you a set of APIs to access native systems such as the file system and networking) and these restrictions no longer apply. There are however a different set of security restrictions involving resources located outside of the files packaged with the app. Depending on how you want to distribute your final product, creating a Chrome app may be a great choice. I’ll include the basic files needed to launch this as a Chrome App, if you are interested in learning more I encourage you to read more at the official documentation.

Once you launch your game, you should see this:

New Phaser game with Skeleton and "Adventure Awaits" message

Now you know that Phaser is up and running. We’ve loaded a sprite and written a bit of text to the screen! We’re almost done 🙂 … well not quite, but we’re ready to start actually making a game.

Setting the Stage

The first thing that we want to do is get rid of that boring black background and bring our world to life. In the preload  method, add all of the images that make up the forest background. There happen to be four different images for this because it is designed to be used as a parallax scrolling background. Typically this type of background is used in side scrolling platformer games, but it gives us the option of doing an animation effect later.

this.game.load.image('forest-back', 'assets/parallax_forest_pack/layers/parallax-forest-back-trees.png');
this.game.load.image('forest-lights', 'assets/parallax_forest_pack/layers/parallax-forest-lights.png');
this.game.load.image('forest-middle', 'assets/parallax_forest_pack/layers/parallax-forest-middle-trees.png');
this.game.load.image('forest-front', 'assets/parallax_forest_pack/layers/parallax-forest-front-trees.png');

In the create  method since we have 4 different images that make up the background, we’ll create a Group of TileSprite objects. Using a javascript array of the image keys, we can use the built in forEach method to quickly and elegantly create all four in the correct order.

var state = this;

this.background = this.game.add.group();
// setup each of our background layers to take the full screen
['forest-back', 'forest-lights', 'forest-middle', 'forest-front']
    .forEach(function(image) {
        var bg = state.game.add.tileSprite(0, 0, state.game.world.width,
            state.game.world.height, image, '', state.background);
        bg.tileScale.setTo(4,4);
    });

A TileSprite is a type of image that is meant to be repeated or tiled over a large area. To create one you need to pass it not only the x & y coordinates, but also a width and height for how big the area that it needs to cover should be. Just like the Sprite, you give it the image key to use. The final parameter that we pass it is our group, so that each one is automatically added to the background group. We want the background to cover the whole screen, so we’ll pass in the game world’s width and height. Also, in this case, our image isn’t really meant to be tiled like a mosaic, so we’ll scale the tiling so that it looks more like one image (play with the scale numbers to see what I mean about the tiling).

Let’s take a moment to talk about the group that we created. Groups are an extremely powerful feature of Phaser that are capable of a whole lot more than just the name suggests. At the very base level, they act as a collection, sort of like an array, and they have several methods available for traversing and manipulating the items in the collection. Another important aspect of groups is that the children of the group are positioned, rotated, and scaled all relative to the group itself. If we set group.x = 10; then it will move all of the children over by 10 as well. The position of the children is relative meaning that if a child item also has it’s x coord set to 10, then it will actually be placed at x 20 on the screen (assuming that the group itself is not a child of another parent that isn’t at 0,0). We will use groups extensively in our game and I encourage you to read the documentation to find out more about all of the methods and properties that are available.

Reminder: time to commit your files!

The Army of Darkness

After setting the stage, the next thing we need is something to attack. Time to unleash the horde of monsters that we’ve collected. In order to be able to use all of our monsters, we need to load each image. Let’s change the preload  section of our play  state to do just that. Each one needs a key to reference it by, and the path to the image file.

    this.game.load.image('aerocephal', 'assets/allacrost_enemy_sprites/aerocephal.png');
    this.game.load.image('arcana_drake', 'assets/allacrost_enemy_sprites/arcana_drake.png');
    this.game.load.image('aurum-drakueli', 'assets/allacrost_enemy_sprites/aurum-drakueli.png');
    this.game.load.image('bat', 'assets/allacrost_enemy_sprites/bat.png');
    this.game.load.image('daemarbora', 'assets/allacrost_enemy_sprites/daemarbora.png');
    this.game.load.image('deceleon', 'assets/allacrost_enemy_sprites/deceleon.png');
    this.game.load.image('demonic_essence', 'assets/allacrost_enemy_sprites/demonic_essence.png');
    this.game.load.image('dune_crawler', 'assets/allacrost_enemy_sprites/dune_crawler.png');
    this.game.load.image('green_slime', 'assets/allacrost_enemy_sprites/green_slime.png');
    this.game.load.image('nagaruda', 'assets/allacrost_enemy_sprites/nagaruda.png');
    this.game.load.image('rat', 'assets/allacrost_enemy_sprites/rat.png');
    this.game.load.image('scorpion', 'assets/allacrost_enemy_sprites/scorpion.png');
    this.game.load.image('skeleton', 'assets/allacrost_enemy_sprites/skeleton.png');
    this.game.load.image('snake', 'assets/allacrost_enemy_sprites/snake.png');
    this.game.load.image('spider', 'assets/allacrost_enemy_sprites/spider.png');
    this.game.load.image('stygian_lizard', 'assets/allacrost_enemy_sprites/stygian_lizard.png');

In the create  method is where we’ll want to create Sprite objects for these images so that they can exist in the game world. Much like the background images, it’s faster and easier to read if we put all the information that we need to load into an array. This time however, we need more than just the image key. We’re going to want to display the name of the monster on the screen below it, so that the player knows what they are facing. To do this we’ll create an array of objects that has a name property suitable for display, as well as the image key.

var monsterData = [
    {name: 'Aerocephal', image: 'aerocephal'},
    {name: 'Arcana Drake', image: 'arcana_drake'},
    {name: 'Aurum Drakueli', image: 'aurum-drakueli'},
    {name: 'Bat', image: 'bat'},
    {name: 'Daemarbora', image: 'daemarbora'},
    {name: 'Deceleon', image: 'deceleon'},
    {name: 'Demonic Essence', image: 'demonic_essence'},
    {name: 'Dune Crawler', image: 'dune_crawler'},
    {name: 'Green Slime', image: 'green_slime'},
    {name: 'Nagaruda', image: 'nagaruda'},
    {name: 'Rat', image: 'rat'},
    {name: 'Scorpion', image: 'scorpion'},
    {name: 'Skeleton', image: 'skeleton'},
    {name: 'Snake', image: 'snake'},
    {name: 'Spider', image: 'spider'},
    {name: 'Stygian Lizard', image: 'stygian_lizard'}
];

After that, we’ll need to create the actual sprites for them in order to render them in the game world. Time for another group!

this.monsters = this.game.add.group();

var monster;
monsterData.forEach(function(data) {
    // create a sprite for them off screen
    monster = state.monsters.create(1000, state.game.world.centerY, data.image);
    // center anchor
    monster.anchor.setTo(0.5);
    // reference to the database
    monster.details = data;

    //enable input so we can click it!
    monster.inputEnabled = true;
    monster.events.onInputDown.add(state.onClickMonster, state);
});

When it comes to sprites, groups have a special method create that we can use. For other game objects we need to create them using the normal game factories, and add them as children to the group, the create method only works for sprites. It takes the normal sprite parameters; position and image key, but also lets you pass in a flag as to whether or not the sprite “exists”. This parameter is most often used in object pooling, which we’ll cover a bit later. Each sprite we’ll set the anchor to the center, and set a reference to our monsterData item so that we can reference it later (to display the name).

We’re also going to want to be able to click the monsters (it’s a *click*er game after all), we can tell Phaser to register click events by setting inputEnabled to true. Doing so will enable several input events, we’re interested in what happens when we click the mouse button down (or tap it). For that we’ll tell it to use the onClickMonster  method of our state, and that it should be called in the context of our state (javascript “this”). We haven’t created that method yet, we’ll do that in a minute.

In this game, we only ever want to face one monster at a time, so we need a reference to the monster that we are currently facing. Another cool feature of a group is that we can let Phaser randomly select one using getRandom() . Then set the position of the monster to roughly the center of the screen, a little off so that we have room for some other things later.

this.currentMonster = this.monsters.getRandom();
this.currentMonster.position.set(this.game.world.centerX + 100, this.game.world.centerY);

Next we can modify our render method so that we can show the name of the monster that we are up against.

render: function() {
    game.debug.text(this.currentMonster.details.name,
        this.game.world.centerX - this.currentMonster.width / 2,
        this.game.world.centerY + this.currentMonster.height / 2);
}

Finally, we need to add that onClickMonster  handler so that something happens when we click them. For now, we’ll just change out the monster on each click so that we can test running through our list (epic insta-kill!). Each click we’ll set the currentMonster to another random one, and position it in the center of the screen. We’ll move the other monster off screen so that we can’t see it at the same time.

onClickMonster: function() {
    // reset the currentMonster before we move him
    this.currentMonster.position.set(1000, this.game.world.centerY);
    // now pick the next in the list, and bring him up
    this.currentMonster = this.monsters.getRandom();
    this.currentMonster.position.set(this.game.world.centerX + 100, this.game.world.centerY);
},

Reminder: time to commit your files again!

Phaser 3 game with tentacle dragon enemy in scene

Clicking For Great Justice

Obviously just clicking to cycle through the monsters isn’t much of a gameplay element. Instead we need to simulate RPG combat by clicking and dealing damage to the monsters. In order to deal damage, we need to know something about our player. The main hero of this game isn’t directly represented by a sprite on the screen, so we will just create a plain javascript object to hold useful information about them. Add this to the bottom of the create phase:

// the main player
this.player = {
    clickDmg: 1,
    gold: 0
};

Also in order to be able to kill the monsters, they need to have some health to damage. Let’s go back to our monster database from before, and add a maxHealth attribute to each one. For now, for the values of maxHealth, I’ve just chosen somewhat arbitrary numbers, by looking at the sprite and just making a few tougher than the others. Later we can get deeper into gameplay and balance out the toughness of the monsters. I also adjusted the spacing so that it looks a little more like a table and is easier to edit.

var monsterData = [
    {name: 'Aerocephal',        image: 'aerocephal',        maxHealth: 10},
    {name: 'Arcana Drake',      image: 'arcana_drake',      maxHealth: 20},
    {name: 'Aurum Drakueli',    image: 'aurum-drakueli',    maxHealth: 30},
    {name: 'Bat',               image: 'bat',               maxHealth: 5},
    {name: 'Daemarbora',        image: 'daemarbora',        maxHealth: 10},
    {name: 'Deceleon',          image: 'deceleon',          maxHealth: 10},
    {name: 'Demonic Essence',   image: 'demonic_essence',   maxHealth: 15},
    {name: 'Dune Crawler',      image: 'dune_crawler',      maxHealth: 8},
    {name: 'Green Slime',       image: 'green_slime',       maxHealth: 3},
    {name: 'Nagaruda',          image: 'nagaruda',          maxHealth: 13},
    {name: 'Rat',               image: 'rat',               maxHealth: 2},
    {name: 'Scorpion',          image: 'scorpion',          maxHealth: 2},
    {name: 'Skeleton',          image: 'skeleton',          maxHealth: 6},
    {name: 'Snake',             image: 'snake',             maxHealth: 4},
    {name: 'Spider',            image: 'spider',            maxHealth: 4},
    {name: 'Stygian Lizard',    image: 'stygian_lizard',    maxHealth: 20}
];

Phaser sprites come with both Health and LifeSpan components built in that provide all of the features that we need in order to get combat working. They provide us with a damage()  and heal()  method and take into account health and maxHealth in those methods. When you apply damage and the health drops to 0 (or below) it will automatically call kill()  and fire the onKilled  event. Similarly, there is a  revive()  method that allows you to bring a monster back from the dead fully healed. When a monster is revived, it fires the onRevived event. We will hook into those events to drop loot and change monsters. Inside the loop that creates the monster sprites, let’s set the health component based on the value in our data array.

// use the built in health component
monster.health = monster.maxHealth = data.maxHealth;

// hook into health and lifecycle events
monster.events.onKilled.add(state.onKilledMonster, state);
monster.events.onRevived.add(state.onRevivedMonster, state);

Next update the onClickMonster  method to deal damage to the monster based on the player’s clickDmg  attribute. When the monster’s health reaches 0, it will be killed.

onClickMonster: function(monster, pointer) {
    // apply click damage to monster
    this.currentMonster.damage(this.player.clickDmg);
}

Clicking on a monster will do damage, but it’s important to provide feedback to the player that this is happening. No one likes to click things and see nothing happen, it feels broken. Also, I think it’s time to get rid of the debug text and use an actual text object to display the monster’s name and health. Add these 2 Text objects to your create method. Again we’ll create another group so that moving the monster information around is easy. Creating Text objects is relatively straight forward, like most display objects you provide it the position on the screen (or relative to its parent), but instead of an image key, you pass it the string that you want to display. Optionally you can send in font styling data to change how it’s displayed. This font style information is very similar to standard HTML Canvas fonts.

this.monsterInfoUI = this.game.add.group();
this.monsterInfoUI.position.setTo(this.currentMonster.x - 220, this.currentMonster.y + 120);
this.monsterNameText = this.monsterInfoUI.addChild(this.game.add.text(0, 0, this.currentMonster.details.name, {
    font: '48px Arial Black',
    fill: '#fff',
    strokeThickness: 4
}));
this.monsterHealthText = this.monsterInfoUI.addChild(this.game.add.text(0, 80, this.currentMonster.health + ' HP', {
    font: '32px Arial Black',
    fill: '#ff0000',
    strokeThickness: 4
}));

Back in our onClickMonster  event, we want to update the text now to reflect the monster’s new health.

// update the health text
this.monsterHealthText.text = this.currentMonster.alive ? this.currentMonster.health + ' HP' : 'DEAD';

When a monster is killed it fires the onKilled  event, we want to push it back off screen and then select a new monster and revive them. The revive method optionally takes a health parameter that will set the health of the monster to the value provided. It then sets alive, visible, and exists to true, and then fires the onRevived event. Add the onKilledMonster  method to our state now.

onKilledMonster: function(monster) {
    // move the monster off screen again
    monster.position.set(1000, this.game.world.centerY);

    // pick a new monster
    this.currentMonster = this.monsters.getRandom();
    // make sure they are fully healed
    this.currentMonster.revive(this.currentMonster.maxHealth);
},

When a monster is revived, we want to get them into position on the screen, and reset the monster display text to reflect the new monster. After the kill handler, let’s add the onRevivedMonster  event handler to our state as well. Here we move the monster to the center area of the screen and update our text objects to reflect the new information.

onRevivedMonster: function(monster) {
    monster.position.set(this.game.world.centerX + 100, this.game.world.centerY);
    // update the text display
    this.monsterNameText.text = monster.details.name;
    this.monsterHealthText.text = monster.health + 'HP';
},

Ok, now we can see what is happening, and that is good. It still doesn’t quite feel exciting enough though, I think we can add more. For every click, let’s display the damage that we’re doing. For that, we’ll want to create a pool of text objects. Each click we need to display the damage number for a short period and then it should disappear. Instead of creating a new text object for each click (which we could do), it’s better to create a bunch up front and just change the properties. The reason is that in almost all programming situations, especially in JavaScript, creating new objects is an expensive operation. Not something that you want to be doing a lot of every frame. Let’s create a pool of about 50 text objects (I think I can do 30 clicks / second so that’s a decent buffer). The following should go in your create  method.

this.dmgTextPool = this.add.group();
var dmgText;
for (var d=0; d<50; d++) {
    dmgText = this.add.text(0, 0, '1', {
        font: '64px Arial Black',
        fill: '#fff',
        strokeThickness: 4
    });
    // start out not existing, so we don't draw it yet
    dmgText.exists = false;
    dmgText.tween = game.add.tween(dmgText)
        .to({
            alpha: 0,
            y: 100,
            x: this.game.rnd.integerInRange(100, 700)
        }, 1000, Phaser.Easing.Cubic.Out);

    dmgText.tween.onComplete.add(function(text, tween) {
        text.kill();
    });
    this.dmgTextPool.add(dmgText);
}

As you can see in order to create a pool of damage text objects to use we didn’t have to do anything special. We used the groups that we already know and love. A standard for loop will help us create 50 of them, and we’ll set them all to exists = false  so that they don’t render on the screen until we tell them to. Next, we’re going to add another super powerful tool in Phaser’s arsenal, a Tween. A tween allows you to modify various properties of an object over time. It uses one of several mathematical equations to “ease” these values from start to finish and create animation effects. For the damage text, we want it to fly out from where it was clicked in a random direction and also fade out so that by the time that it reaches its destination, it can no longer be seen. In the to  method of the tween, we set the final values that we want the alpha, y and x properties of the object to be, the starting values will be the values of the object when the tween begins. The second parameter is the time that it should take to complete the tween, we’ll set it to 1000 (the value is in milliseconds, so 1 second). The final parameter is the Easing equation that we want to use. When a tween animation is completed, an event is fired, we can hook into there and kill()  the text object (effectively setting it back to exists = false ).

Now we’ll turn these on so that clicking to do damage is really exciting. Every time we click, we’ll grab the first available dmgText object (i.e. not killed) from the group using getFirstExists(false) , the false tells the group that we want one that doesn’t exist. Then update the text to reflect the current click damage. We need to reset the alpha property from when the tween had adjusted it, and we want to start this one at the spot where the player clicked. Then we’ll start the tween again, and get our animation.

// grab a damage text from the pool to display what happened
var dmgText = this.dmgTextPool.getFirstExists(false);
if (dmgText) {
    dmgText.text = this.player.clickDmg;
    dmgText.reset(pointer.positionDown.x, pointer.positionDown.y);
    dmgText.alpha = 1;
    dmgText.tween.start();
}

Reminder: commit that code!

Demonic Essence enemy with damage displayed from attack

Phat Lootz

Killing monsters isn’t something that the player does just for sport, they’re in it for the rewards of gold and treasure. We need to drop some loot when the monster dies, let’s add a gold coin to our images loading in the preload method.

this.game.load.image('gold_coin', 'assets/496_RPG_icons/I_GoldCoin.png');

To start with, every monster will drop a single gold coin when it dies. The player will need to click on them to collect them, and so there could be quite a few laying around before they decide to do that. To create a pool of gold coins, again we’ll utilize the group. This time, since we’re creating a pool of sprites, we can use a special method called createMultiple. This method is very similar to the create  method in that it only creates sprites, for this one, it takes a new parameter, the number that you want to create. Since we’re not using a for loop this time to create them, we need a way to setup some defaults without having to loop through our newly created group, for that, we have another method called setAll. It takes the property and value and applies that to each object in the group. We also want to register the onInputDown handler, since adding a handler to an event is a method, we use callAll to execute the events.onInputDown.add  method on each child of the group.

// create a pool of gold coins
this.coins = this.add.group();
this.coins.createMultiple(50, 'gold_coin', '', false);
this.coins.setAll('inputEnabled', true);
this.coins.setAll('goldValue', 1);
this.coins.callAll('events.onInputDown.add', 'events.onInputDown', this.onClickCoin, this);

Again we need feedback in the UI so that we know that we are collecting gold. Add this text object to the create  method.

this.playerGoldText = this.add.text(30, 30, 'Gold: ' + this.player.gold, {
    font: '24px Arial Black',
    fill: '#fff',
    strokeThickness: 4
});

Now we can add our click handler for the coins. When a coin is clicked, the goldValue  of the coin is added to the player’s gold. We also have to update the UI so that we can see the change. Finally, we kill the coin so that it disappears back into our pool for reuse.

onClickCoin: function(coin) {
    // give the player gold
    this.player.gold += coin.goldValue;
    // update UI
    this.playerGoldText.text = 'Gold: ' + this.player.gold;
    // remove the coin
    coin.kill();
}

Next we need to add to the onKilledMonster  event so that we can actually drop these coins. Much like the dmgText objects, we’ll grab the first available coin and bring it to life positioning it somewhere randomly in the center-ish of the screen. We update the goldValue (even though we’re just setting it to 1 now) so that in the future we can drop different amounts of gold as we progress.

var coin;
// spawn a coin on the ground
coin = this.coins.getFirstExists(false);
coin.reset(this.game.world.centerX + this.game.rnd.integerInRange(-100, 100), this.game.world.centerY);
coin.goldValue = 1;

Dune Crawler enemy with Gold amount displayed in the upper left corner

As I mentioned earlier, the player has to click on the coins in order to collect them. After a few kills, if they don’t do that, the floor will become quite littered with gold. While piles of cash is always fun, eventually we might run out of new coins to spawn from our pool. What we need to do is automatically collect gold for the player after a short time so that the world doesn’t become cluttered.

To accomplish this, Phaser has a Timer object that we can use to create our own custom timed events. If the coin sits there not being clicked for 3 seconds, then we’ll “click” it for them, by firing the same onClickCoin  method that we use when they do click it. The timer event takes the duration, the handler, the context that the handler should fire in, and any other additional parameters that should be passed to the handler.

this.game.time.events.add(Phaser.Timer.SECOND * 3, this.onClickCoin, this, coin);

Since we are going to be calling the onClickCoin  method when the timer completes in addition to when the coin is clicked, we need to test and make sure that we don’t call it twice. If the player clicks the coin before the timeout, the timeout will still fire, but the gold will already be collected, and the coin already killed. We can add a simple test at the top of the function to make sure that when we collect this coin it is still alive.

if (!coin.alive) {
    return;
}

Reminder: commit the source, save your work!

Upgrades

I’m sure by now you’re tired of doing just 1 point of damage every click, and we’ve got nothing to spend our precious gold on! Time to create some upgrades. The upgrades menu is going to be a box, with some buttons inside that you can click on to buy things. For the background of the upgrades menu, we could use more art from the web, or create an image ourselves in a paint program, but instead we can utilize the HTML5 Canvas to build it for us. Instead of loading an image, Phaser has an object called BitmapData that creates a canvas for us. The result of the canvas can then be used in place of an image on a sprite. Instead of setting the key when it is loaded like with an image, instead we need to manually add it to Phaser’s asset cache. In the preload  method we will generate images (colored rectangles) for the background of the upgrades menu and also the buttons.

// build panel for upgrades
var bmd = this.game.add.bitmapData(250, 500);
bmd.ctx.fillStyle = '#9a783d';
bmd.ctx.strokeStyle = '#35371c';
bmd.ctx.lineWidth = 12;
bmd.ctx.fillRect(0, 0, 250, 500);
bmd.ctx.strokeRect(0, 0, 250, 500);
this.game.cache.addBitmapData('upgradePanel', bmd);

var buttonImage = this.game.add.bitmapData(476, 48);
buttonImage.ctx.fillStyle = '#e6dec7';
buttonImage.ctx.strokeStyle = '#35371c';
buttonImage.ctx.lineWidth = 4;
buttonImage.ctx.fillRect(0, 0, 225, 48);
buttonImage.ctx.strokeRect(0, 0, 225, 48);
this.game.cache.addBitmapData('button', buttonImage);

For the upgrades menu, we don’t need something as heavy as a sprite (with all the health and other stuff). Instead for things that are going to be purely user interface objects, it is better to use a Image. An Image object has the same transform information (position, scale, rotation) just not all the extra things that a sprite does. Instead of passing in an image key, we’ll pull the image out of the cache that we put it into earlier. The menu panel will also contain a group for the buttons, that way all of the buttons can follow the menu and be relative to its transforms. Because of the border on the background image, we’ll move the button group in a little bit.

this.upgradePanel = this.game.add.image(10, 70, this.game.cache.getBitmapData('upgradePanel'));
var upgradeButtons = this.upgradePanel.addChild(this.game.add.group());
upgradeButtons.position.setTo(8, 8);

Stygian Lizard enemy with newly added upgrade frame

Our first upgrade will be to the click damage so we can start killing faster. Let’s pick an icon from our library and add that to our image load.

this.game.load.image('dagger', 'assets/496_RPG_icons/W_Dagger002.png');

Phaser has another object in its bag of tricks, the Button object. A button is a subclass of an Image object that is designed to handle being clicked out of the box. It supports 4 different button states: Out, Over, Down, and Up. You can provide a spritesheet image with different looks for each of these states, it can make the button appear to actually be “pressed” for example, or change color when you hover over top of it. I’ve only generated a single background frame for our buttons for now, it still works fine without the other images. For the button we are going to add the icon, a label for what the upgrade is, and another text to display the gold cost for upgrading.

var button;
button = this.game.add.button(0, 0, this.game.cache.getBitmapData('button'));
button.icon = button.addChild(this.game.add.image(6, 6, 'dagger'));
button.text = button.addChild(this.game.add.text(42, 6, 'Attack: ' + this.player.clickDmg, {font: '16px Arial Black'}));
button.details = {cost: 5};
button.costText = button.addChild(this.game.add.text(42, 24, 'Cost: ' + button.details.cost, {font: '16px Arial Black'}));
button.events.onInputDown.add(this.onUpgradeButtonClick, this);

After creating the button, then add it to the buttons group.

upgradeButtons.addChild(button);

For now our button handler simply needs to test the one button that we have. First we’ll check that we can afford to purchase the upgrade, if we can then we’ll go through with it. We need to adjust the player’s gold from the cost, and update the UI to reflect that change. We also need to improve the player’s clickDmg attribute, and update the text on the button. Now we can spend our hard earned loot to get stronger!

onUpgradeButtonClick: function(button, pointer) {
    if (this.player.gold - button.details.cost >= 0) {
        this.player.gold -= button.details.cost;
        this.playerGoldText.text = 'Gold: ' + this.player.gold;
        this.player.clickDmg++;
        button.text.text = 'Attack: ' + this.player.clickDmg;
    }
}

Aerocephal enemy with Attack 21 as an upgrade

Now it’s time to add the second type of upgrade, the DPS upgrade. Until now the only way to deal damage to monsters is by directly clicking on them. While this is an important mechanic in our game, it can get tedious after a while. This is the part that makes this type of game fall into the “idle” genre. Players will continue to progress and deal damage to monsters even when they are not actively clicking them.

In order to add a new button, we need to repeat what we have, and change the effect of purchasing the upgrade. Doing this one button at a time will get unruly after a bit, so we want to create a database array of upgrades, just like we have for monsters. We’ll need the icon to display, the name of the upgrade, the level for the number of times that it has been upgraded, the cost in gold to upgrade, and a callback function that we can fire to provide a different effect for each upgrade.

var upgradeButtonsData = [
    {icon: 'dagger', name: 'Attack', level: 1, cost: 5, purchaseHandler: function(button, player) {
        player.clickDmg += 1;
    }},
    {icon: 'swordIcon1', name: 'Auto-Attack', level: 0, cost: 25, purchaseHandler: function(button, player) {
        player.dps += 5;
    }}
];

We need to add the dps property to our player, so that our purchase handler can take effect.

this.player = {
    clickDmg: 1,
    gold: 0,
    dps: 0
};

Now we can loop through our data and create all of our upgrade buttons in bulk. Because the buttons are about 48 pixels high, we’ll separate each one by 50. Instead of hard coding the text strings and icon, they will be populated from the data.

var button;
upgradeButtonsData.forEach(function(buttonData, index) {
    button = state.game.add.button(0, (50 * index), state.game.cache.getBitmapData('button'));
    button.icon = button.addChild(state.game.add.image(6, 6, buttonData.icon));
    button.text = button.addChild(state.game.add.text(42, 6, buttonData.name + ': ' + buttonData.level, {font: '16px Arial Black'}));
    button.details = buttonData;
    button.costText = button.addChild(state.game.add.text(42, 24, 'Cost: ' + buttonData.cost, {font: '16px Arial Black'}));
    button.events.onInputDown.add(state.onUpgradeButtonClick, state);

    upgradeButtons.addChild(button);
});

When we click an upgrade button now we need to increase its level and update the text to reflect the change. Then we’ll execute the purchaseHandler callback in the context of the state, passing the button and player along to the handler.

onUpgradeButtonClick: function(button, pointer) {
    if (this.player.gold - button.details.cost >= 0) {
        this.player.gold -= button.details.cost;
        this.playerGoldText.text = 'Gold: ' + this.player.gold;
        button.details.level++;
        button.text.text = button.details.name + ': ' + button.details.level;
        button.details.purchaseHandler.call(this, button, this.player);
    }
}

Ok, so we’re increasing both attack and dps (damage per second), but we haven’t setup dps to do anything yet. For dps to make sense, if we have 1 dps then after 1 second has passed we do 1 damage. Waiting the full second to apply any damage at all though is too choppy and slow. Instead we’ll update at 100ms (10 times a second). So, in order to apply 1 damage after 1 second, then we need to apply 0.10 damage every 100ms. Similar to the timer event that we used for the gold coins, there are also loop events that will repeat and call the handler at the duration over and over.

// 100ms 10x a second
this.dpsTimer = this.game.time.events.loop(100, this.onDPS, this);

Our dps handler is going to get called every 100ms whether we have upgraded or not. So we check if we have something to do first, if so, then make sure the monster is still alive to apply the damage. Then we’ll damage the monster and update the text to reflect the monster’s health. I don’t really want to display the decimals that might occur on the monster health from doing 10% damage, so we’ll round it for the display (not the actual health).

onDPS: function() {
    if (this.player.dps > 0) {
        if (this.currentMonster && this.currentMonster.alive) {
            var dmg = this.player.dps / 10;
            this.currentMonster.damage(dmg);
            // update the health text
            this.monsterHealthText.text = this.currentMonster.alive ? Math.round(this.currentMonster.health) + ' HP' : 'DEAD';
        }
    }
}

Reminder: don’t forget to commit!

Progression

Killing the same monsters over and over is boring. We need to keep increasing the difficulty so that the players can face a challenge and progress. Let’s add some world level stats to the preload  section.

// world progression
this.level = 1;
// how many monsters have we killed during this level
this.levelKills = 0;
// how many monsters are required to advance a level
this.levelKillsRequired = 10;

Each time we kill a monster now, we need to increase the kills stat. We also need to upgrade the monster’s health based on the level. With increased risk, comes increased reward, and we’ll also modify the coin value based on the world level as well. After 10 monsters have been killed, then we can progress to the next level.

onKilledMonster: function(monster) {
    // move the monster off screen again
    monster.position.set(1000, this.game.world.centerY);

    var coin;
    // spawn a coin on the ground
    coin = this.coins.getFirstExists(false);
    coin.reset(this.game.world.centerX + this.game.rnd.integerInRange(-100, 100), this.game.world.centerY);
    coin.goldValue = Math.round(this.level * 1.33);
    this.game.time.events.add(Phaser.Timer.SECOND * 3, this.onClickCoin, this, coin);

    this.levelKills++;

    if (this.levelKills >= this.levelKillsRequired) {
        this.level++;
        this.levelKills = 0;
    }

    // pick a new monster
    this.currentMonster = this.monsters.getRandom();
    // upgrade the monster based on level
    this.currentMonster.maxHealth = Math.ceil(this.currentMonster.details.maxHealth + ((this.level - 1) * 10.6));
    // make sure they are fully healed
    this.currentMonster.revive(this.currentMonster.maxHealth);
}

Since we’ll be getting a lot more money now, we also need to adjust the upgrade prices.

onUpgradeButtonClick: function(button, pointer) {
    // make this a function so that it updates after we buy
    function getAdjustedCost() {
        return Math.ceil(button.details.cost + (button.details.level * 1.46));
    }

    if (this.player.gold - getAdjustedCost() >= 0) {
        this.player.gold -= getAdjustedCost();
        this.playerGoldText.text = 'Gold: ' + this.player.gold;
        button.details.level++;
        button.text.text = button.details.name + ': ' + button.details.level;
        button.costText.text = 'Cost: ' + getAdjustedCost();
        button.details.purchaseHandler.call(this, button, this.player);
    }
}

Finally, we’ll add the level information to the UI so that the player knows how they are doing. By now adding text objects to reflect this information should be old hat to you!

// setup the world progression display
this.levelUI = this.game.add.group();
this.levelUI.position.setTo(this.game.world.centerX, 30);
this.levelText = this.levelUI.addChild(this.game.add.text(0, 0, 'Level: ' + this.level, {
    font: '24px Arial Black',
    fill: '#fff',
    strokeThickness: 4
}));
this.levelKillsText = this.levelUI.addChild(this.game.add.text(0, 30, 'Kills: ' + this.levelKills + '/' + this.levelKillsRequired, {
    font: '24px Arial Black',
    fill: '#fff',
    strokeThickness: 4
}));

We also need to update the level text when it changes inside the  onKilledMonster  method.

this.levelText.text = 'Level: ' + this.level;
this.levelKillsText.text = 'Kills: ' + this.levelKills + '/' + this.levelKillsRequired;

Spider enemy with various upgrades in Phaser 3 game

Reminder: commit commit commit

Finished the basics, what’s next?

What we’ve created here is a complete idle clicker RPG. Well, complete as in it’s playable. There’s still tons left to do in order to get this game turned into something that is really fun. In game development, they say that the last 10% of the work is the last 90% of your time. We’re pretty much 90% done I think 🙂

Here’s a list of things that would be great to add: (possibly in future tutorials)

  • monsters with animation
  • sounds & music!
  • more upgrades
  • critical hits
  • boss monsters
  • timed boost powers
  • different world backgrounds
  • achievements
  • leader boards

I hope that you have enjoyed this tutorial and making this game!

Please leave comments and questions below, I welcome any feedback and would love to see your games too!

]]>