Tick Tech toe is a huge project for the starters who want to learn how to build sports. It’s easy to understand but gives you the opportunity to know about the game estate, player turn, winning logic, and user input.
In this tutorial, you will learn how to prepare TIC-TAC-TOE by using phaser.jsA sharp, entertainment and open source framework to make 2D games in the browser.
If you are new to Phaser.js, don’t worry. We will go through everything by step. Finally, you will have a working game that you can play, distribute or build.
You can Play the game here To get the realization of what you are going to build.
The table of content
What is phaser.js?
Phaser.js is a free and open source javascript game framework. This helps developers to make HTML5 games that work in web browsers. Handle things such as presenting a physic graphics, detection, and running a game loop.
You can use a phase to create an easy game like Pong and Tick Tech or Modern Plateframers and Roll players. It supports both canvas and web GL rendering, so your games will easily run on most devices.
Project Setup
Create a folder for your project and add two files: index.html
And game.js
. The HTML loads the file feaser and the Javascript file contains the game logic. Here is the storage With the created code.
What is here index.html
File should look like:
html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Tic Tac Toe — Phaser 3title>
<meta name="viewport" content="width=device-width,initial-scale=1" />
<style>
html, body { height: 100%; margin: 0; background: #0f172a; display: grid; place-items: center; }
#game { box-shadow: 0 10px 30px rgba(0,0,0,.35); border-radius: 12px; overflow: hidden; }
.hint { color: #e2e8f0; margin-top: 10px; font-size: 14px; text-align: center; opacity: .85; }
style>
<script src="https://cdn.jsdelivr.net/npm/phaser@3.60.0/dist/phaser.min.js">script>
head>
<body>
<div id="game">div>
<div class="hint">Click a cell to play. Tap “Restart” to start over.div>
<script src="./game.js">script>
body>
html>
It sets a simple HTML page, loads the CDN from CDN, and indicates you game.js
File #game
The container is the place where the Phaser Game Canvas will enter.
How to configure the game configuration
Faser Games are created from a configuration object that explains things like width, height, background color, and which works to load, create and update the game.
(() => {
const GRID = 3;
const CELL = 120;
const BOARD = GRID * CELL;
const HUD = 72;
const WIDTH = BOARD;
const HEIGHT = BOARD + HUD;
let scene;
let board;
let currentPlayer;
let gameOver;
let gridGfx;
let overlayGfx;
let marks = ();
let statusText;
let restartText;
const config = {
type: Phaser.AUTO,
parent: "game",
width: WIDTH,
height: HEIGHT,
backgroundColor: "#ffffff",
scale: { mode: Phaser.Scale.FIT, autoCenter: Phaser.Scale.CENTER_BOTH },
scene: { preload, create, update }
};
new Phaser.Game(config);
We begin to explain permanently for grid size and cell size. config
Objects tells the phaser that they make and use a game with these dimensions preload
For, for, for,. create
And update
We will explain the functions.
Method to pre -load assets
Since we are pulling everything with the Physeria’s graphics and text tools, we do not need to load any external images or sounds.
function preload() {
}
This is a place holder that lets call the Phaser preload
Before the game begins.
How to make a game scene
create
The function runs once at the beginning of the scene. Here we draw the grid, set up early state, and add UI elements.
function create() {
scene = this;
gridGfx = scene.add.graphics({ lineStyle: { width: 4, color: 0x000000 } });
overlayGfx = scene.add.graphics();
drawGrid();
initGame();
statusText = scene.add.text(WIDTH / 2, BOARD + 12, "Player X's turn", {
fontSize: "20px",
color: "#111",
fontFamily: "Arial, Helvetica, sans-serif"
}).setOrigin(0.5, 0);
restartText = scene.add.text(WIDTH / 2, BOARD + 38, "Restart", {
fontSize: "18px",
color: "#2563eb",
fontFamily: "Arial, Helvetica, sans-serif"
}).setOrigin(0.5, 0).setInteractive({ useHandCursor: true });
restartText.on("pointerup", hardReset);
scene.input.on("pointerdown", onPointerDown, scene);
}
We created two Graphics
Object: One for a static grid and the other for one line. Then we called drawGrid()
And initGame()
To set the gameboard. Status text and reacher buttons are placed under the grid. We also heard with clicks in the board pointerdown
.
How to pull the grid
The grid is made of two vertical and two horizontal lines.
function drawGrid() {
gridGfx.strokeLineShape(new Phaser.Geom.Line(CELL, 0, CELL, BOARD));
gridGfx.strokeLineShape(new Phaser.Geom.Line(CELL * 2, 0, CELL * 2, BOARD));
gridGfx.strokeLineShape(new Phaser.Geom.Line(0, CELL, BOARD, CELL));
gridGfx.strokeLineShape(new Phaser.Geom.Line(0, CELL * 2, BOARD, CELL * 2));
}
We use Phaser.Geom.Line
To describe the start and end points of each line and then stretch with them strokeLineShape
.
How to start the game and reset
initGame
Function compiles a new game, and hardReset
It is said when the start button is clicked again.
function initGame() {
board = Array.from({ length: GRID }, () => Array(GRID).fill(""));
currentPlayer = "X";
gameOver = false;
overlayGfx.clear();
for (const t of marks) t.destroy();
marks = ();
setStatus("Player X's turn");
}
function hardReset() {
initGame();
}
function setStatus(msg) {
statusText && statusText.setText(msg);
}
The board is represented by 2D array full of empty wires. Begins as the current Player X, and marks
The arrows look at the text object so we can clean them on the reset.
How to handle the player input
When the player clicks on a cell, we determine its row and column and check if the move is correct or not.
function onPointerDown(pointer) {
if (gameOver) return;
if (pointer.y > BOARD) return;
const col = Math.floor(pointer.x / CELL);
const row = Math.floor(pointer.y / CELL);
if (!inBounds(row, col)) return;
if (board(row)(col) !== "") return;
placeMark(row, col, currentPlayer);
const win = checkWin(board);
if (win) {
gameOver = true;
drawWinLine(win);
setStatus(`Player ${currentPlayer} wins!`);
return;
}
if (isFull(board)) {
gameOver = true;
setStatus("Draw! No more moves.");
return;
}
currentPlayer = currentPlayer === "X" ? "O" : "X";
setStatus(`Player ${currentPlayer}'s turn`);
}
This ensures that we only work only if the game does not end, the click is inside the board, and the selected cell is empty. After marking, we test the win or draw before bending.
How to make marks on the board
We display an X or O in the center of the Click Cell.
function inBounds(r, c) {
return r >= 0 && r < GRID && c >= 0 && c < GRID;
}
function placeMark(row, col, player) {
board(row)(col) = player;
const cx = col * CELL + CELL / 2;
const cy = row * CELL + CELL / 2;
const t = scene.add.text(cx, cy, player, {
fontSize: Math.floor(CELL * 0.66) + "px",
color: "#111111",
fontFamily: "Arial, Helvetica, sans-serif"
}).setOrigin(0.5);
marks.push
}
The points are calculated so that the text is focused in the cell. We store the text Object in this marks
So array, so it can be removed when resetting.
How to test a winner
We check the rows, columns and the Akhtar to see if the current player has three consecutive consecutive consecutive.
function checkWin(b) {
for (let r = 0; r < GRID; r++) {
if (b(r)(0) && b(r)(0) === b(r)(1) && b(r)(1) === b(r)(2)) {
return { kind: "row", index: r };
}
}
for (let c = 0; c < GRID; c++) {
if (b(0)(c) && b(0)(c) === b(1)(c) && b(1)(c) === b(2)(c)) {
return { kind: "col", index: c };
}
}
if (b(0)(0) && b(0)(0) === b(1)(1) && b(1)(1) === b(2)(2)) {
return { kind: "diag" };
}
if (b(0)(2) && b(0)(2) === b(1)(1) && b(1)(1) === b(2)(0)) {
return { kind: "anti" };
}
return null;
}
If one wins, we return an item by describing the winning line so that it can be drawn.
How to detect drawbacks
If every cell is full and there is no winner, the game ends in draw.
function isFull(b) {
for (let r = 0; r < GRID; r++) {
for (let c = 0; c < GRID; c++) {
if (b(r)(c) === "") return false;
}
}
return true;
}
It looses on every cell and if one is empty, it returns wrong.
How to pull the winning line
A red line has been drawn on the winning cells.
function drawWinLine(res) {
overlayGfx.clear();
overlayGfx.lineStyle(6, 0xef4444, 1);
const pad = 14;
const half = CELL / 2;
if (res.kind === "row") {
const y = res.index * CELL + half;
overlayGfx.strokeLineShape(new Phaser.Geom.Line(pad, y, BOARD - pad, y));
} else if (res.kind === "col") {
const x = res.index * CELL + half;
overlayGfx.strokeLineShape(new Phaser.Geom.Line(x, pad, x, BOARD - pad));
} else if (res.kind === "diag") {
overlayGfx.strokeLineShape(new Phaser.Geom.Line(pad, pad, BOARD - pad, BOARD - pad));
} else if (res.kind === "anti") {
overlayGfx.strokeLineShape(new Phaser.Geom.Line(BOARD - pad, pad, pad, BOARD - pad));
}
}
})();
Coordinator is calculated based on a type of win to ensure that the line goes through the right cells.
Great Now open index.html
And you can start playing games!
The final views
Now you have made a full -fledged tech toe game in Phaser.com. This includes 3×3 grid, turn turn, win the win with a feature line, draw the draw, and resume button. The code uses basic game development concepts such as input handling, game estate management, and rendering, which you can use in major projects.
If you enjoy online games, check out Game BoostThe final market for concerts. You can find Fortnite accounts With special skins, with other famous sports options such as Guru a Garden, Kalash of Klens, and more.