Creating an Ionic Vue + Phaser App
Tags: phaser, ionic, vue, game
Published: 2023-09-08 17:41:36

---
title: Creating an Ionic Vue + Phaser App
published: true
description: If you're a web developer interested in building mobile games, here's how to use open source tools to get started! This is part one, focused on setting up a new app with Ionic, Vue, and Phaser for your mobile game.
tags: phaser, ionic, vue, game
series: Building a Mobile Game with Phaser and Ionic Vue
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kon5mwaze61csoe0j3mk.png
# Use a ratio of 100:42 for best results.
# published_at: 2023-09-04 21:24 +0000
---

I love playing video games, especially console and mobile games. I learned about [Phaser](https://phaser.io/) (an open source framework for building games with JavaScript) last year and have wanted to try out game development using the skills I already have as a web developer.

Turns out, it's easier than I expected! Thanks to Phaser, along with [Ionic](https://ionicframework.com/), [Capacitor](https://capacitorjs.com/), and [Vue](https://v3.vuejs.org/), I was able to get [a mobile game](https://github.com/ceceliacreates/ionitron-game) up and running on an iOS device working only a few hours here and there over two weeks.

![Ionitron game screenshot](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pppgucl74366qgv87no5.png)

## Blog Series Overview

> ❓**Are you interested in a video walkthrough version of this blog post?** Let me know in the comments! If there's enough interest I can put one together.

This blog series will walk through how to use Phaser, Ionic Vue, and Capacitor to build a mobile game of your own and run it on an actual mobile device. 

For this series, we'll make a simplified version of the Ionitron game linked above to illustrate the concepts you'll need to learn to make your own game.

The [source code for this tutorial is here](https://github.com/ceceliacreates/phaser-tutorial), and I'll reference specific commits throughout so you can see the specific changes for each section.

### What We're Building

This is a Vue mobile app built with Ionic Framework components that houses a Phaser game. We'll also use Capacitor to compile the app to native IOS and Android so it can run on mobile devices.

The app has the following features:

- A Play tab that launches the Phaser game for play
- An About tab that describes the game
- A Scores tab that shows your score history for the game

Let's get started!

## Table of Contents

- [Creating a new Ionic Vue app](#creating-a-new-ionic-vue-app)
  - [Setting up the Ionic CLI](#setting-up-the-ionic-cli)
  - [Starting a new app](#starting-a-new-app)
  - [Customizing Tabs](#customizing-tabs)
- [Adding Phaser to the app](#adding-phaser-to-the-app)
  - [Phaser Installation](#phaser-installation)
  - [Creating a Phaser game component](#creating-a-phaser-game-component)
  - [Creating Phaser launch function](#creating-phaser-launch-function)
  - [Creating our first Phaser Scene](#creating-our-first-phaser-scene)
  - [Putting it all together](#putting-it-all-together)
- [What's Next](#whats-next)


## Creating a new Ionic Vue app

First we'll create a new Ionic Vue app using the Tabs starter template.

I'll use the [Ionic CLI](https://ionicframework.com/docs/intro/cli) for this, but you can also use the [Ionic VS Code Extension](https://ionicframework.com/docs/intro/vscode-extension) if you prefer.

Install the Ionic CLI:

```bash
npm install -g @ionic/cli
```

Then run the following to create a new app:

```bash
ionic start phaserGame tabs --type vue
```

Then, `cd` into the directory and run `ionic serve` to start the dev server and open the web version of our app in a browser. Switch your browser to mobile view using DevTools as you're working to see how the app will look on mobile.

![Screenshot of tabs starter app](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tl1uvyy20h9jzfjh8cjr.png)

We now have an Ionic Vue app with three tabs on the bottom for navigation.

Change the tab names to "Play", "About", and "Scores", and update the router and file names to correspond with the new names. Feel free to update the icons as well.

You'll need to change the following files:

- `src/router/index.ts`
- All the files in `src/views`

> [Here is the git commit](https://github.com/ceceliacreates/phaser-tutorial/commit/e909da30857c811695fceb2ed850e9df446f2e53) with the changes for this section.

## Adding Phaser to the app

### Phaser Installation

Phaser has an NPM package we can install into our project.

Run `npm install phaser`. This will add the dependency to your `package.json`.

```json
"dependencies": {
...
"phaser": "^3.60.0",
}
```
> [Here is the git commit](https://github.com/ceceliacreates/phaser-tutorial/commit/c6192d56b075a86e86ff6dfd75c1cfe548cea221) with the changes for this section.

### Creating a Phaser game component

Let's create a component that will manage launching our Phaser game.

Create a `PhaserContainer.vue` file inside `src/components`.

This component will contain the following:

- A button to start the game
- A `div` that will be the parent for the Phaser game
- A click handler for the button that hides the button and runs a Phaser launch command

Add the following `template` to your `PhaserContainer` component:

```js
// src/components/PhaserContainer.vue

<template>
    <div id="game">
      <ion-button v-if="showButton" @click="handleClickStart">Start</ion-button>
    </div>
</template>
```

The id of "game" on the `div` will be passed to Phaser so it knows what HTML element is the parent for our game.

Now add the following `script` to your component:

```js
// src/components/PhaserContainer.vue

<script setup lang="ts">
import { ref } from 'vue'
import { IonButton } from '@ionic/vue';
import { Game} from 'phaser';

// binds to the v-if on our button to toggle visibility
const showButton = ref(true)

// Creates the new Phaser Game instance
function launch() {
// We'll fill this in later
}

function handleClickStart() {
  // hides launch button
  showButton.value = false;

  // Runs the launch function
  launch();
}
</script>
```

We'll also add some styling to make our button in the middle of the screen.

```js
// src/components/PhaserContainer.vue

<style scoped>
#game {
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
  margin: 0;
}
</style>
```

Now our `PhaserContainer` component is ready! We just need to add it to our `PlayPage` view.

```js
// src/views/PlayPage.vue

<template>
  <ion-page>
    <ion-header>
      <ion-toolbar>
        <ion-title>Play</ion-title>
      </ion-toolbar>
    </ion-header>
    <ion-content :fullscreen="true">
      <ion-header collapse="condense">
        <ion-toolbar>
          <ion-title size="large">Play</ion-title>
        </ion-toolbar>
      </ion-header>
      <PhaserContainer/>
    </ion-content>
  </ion-page>
</template>

<script setup lang="ts">
import { IonPage, IonHeader, IonToolbar, IonTitle, IonContent } from '@ionic/vue';
import PhaserContainer from '@/components/PhaserContainer.vue';
</script>
```
> [Here is the git commit](https://github.com/ceceliacreates/phaser-tutorial/commit/ca9586ff011bf008c13bf1ba0bf15c936cc5d439) with the changes for this section.

### Creating Phaser launch function

Our `PhaserContainer` component is working, but nothing happens when we click "Start" because we still need to write our `launch()` function. Let's do that next!

Our `launch()` function returns a new `Phaser.Game` object with the configuration for our game, as well as the scene(s) for the game.

To keep our component clean and enforce separation of concerns, let's move our `launch()` function to a separate file.

Create a new `game` directory within `src` with a new `game.js` file.

> Note: While Phaser does have some TypeScript support, I ran into several issues when trying to use Phaser with TS. For simplicity, we'll use JS for our Phaser game code.

Within this file, add the following code:

```js
// src/game/game.js

import { Game, AUTO, Scale} from "phaser";

export function launch() {
    return new Game({
      type: AUTO,
      scale: {
        mode: Scale.RESIZE,
        width: window.innerWidth * window.devicePixelRatio,
        autoCenter: Scale.CENTER_BOTH,
        height: window.innerHeight * window.devicePixelRatio,
      },
      parent: "game",
      backgroundColor: "#201726",
      physics: {
        default: "arcade",
      },
      scene: MainScene,
    });
  }
```

There are several things happening here, so let's break them down.

- We are returning a Phaser `Game` object that contains a configuration object.
- The type of `AUTO` means that Phaser will detect if it should use WebGL or Canvas to render the game
- The [scale property](https://rexrainbow.github.io/phaser3-rex-notes/docs/site/scalemanager/) handles our sizing and display. The `Scale.RESIZE` mode means the game will resize to fit the parent window. If you want your game to always have the same aspect ratio, use `Scale.FIT` instead.
- `Scale.CENTER_BOTH` means the game is centered both vertically and horizontally within the parent
- Using `window.innerWidth * window.devicePixelRatio` and the corresponding height values will make the game dynamic to the window, and ensure quality rendering on high-DPI (retina) displays
- The `parent` value is the id of our parent `div` HTML element
- We're setting a `backgroundColor` for the game, this is optional
- We're setting a [Physics engine type](https://photonstorm.github.io/phaser3-docs/Phaser.Physics.html) of `arcade`. This is suitable for simple games and is more performant for mobile.

The last property is `scene`, and this defines the scenes in our game.

Scenes are a core concept in Phaser and other game dev frameworks. You can think of Scenes like Views in a web app, but with some additional flexibility. Your player will navigate between Scenes, and sometimes multiple Scenes can run simultaneously.

We'll explore more about Scenes later in this series. For now, we'll start with a single Main Scene to start the game.

> [Here is the git commit](https://github.com/ceceliacreates/phaser-tutorial/commit/22922670ab4572035b807d5ab2b3c9f1ab1610fe) with the changes for this section.

### Creating our first Phaser Scene

We've passed a value of `MainScene` to our `scene` property for our game, so let's create that next.

In the same `game.js` file, update your Phaser import statement to include `Scene`.

```js
// src/game/game.js

import { Game, AUTO, Scale, Scene} from "phaser";
```

Next, add the following code, again in the same file.

```js
// src/game/game.js

export class MainScene extends Scene {
    constructor () {
      super({ key: 'MainScene' })
    }
  
    create () {
        this.add.text(100, 100, "Hello Phaser!", {
            font: "24px Courier",
            fill: "#ffffff",
        });
    }

  }
```

Scenes in Phaser are classes that extend the [Phaser Scene class](https://photonstorm.github.io/phaser3-docs/Phaser.Scene.html). The key 'MainScene' is how we'll reference this scene in our game.

The `create()` block is one of the Phaser lifecycle methods. We'll learn more about other lifecycle methods in later posts in this series.

For now, know that we are using the `create()` block to add some initial text to our game. The first two parameters `100, 100` refers to the x and y coordinates of the text.

> [Here is the git commit](https://github.com/ceceliacreates/phaser-tutorial/commit/6dc0f966ffb5726ab687fee12c612e1ffa3d4f79) with the changes for this section.

### Putting it all together

The last thing we need to do is update our `PhaserContainer` component to use our new launch function and Phaser scene.

Update the `script` tag to import the `launch()` function, and remove the the function declaration within the component. 

```js
// src/components/PhaserContainer.vue

<script setup lang="ts">
import { ref } from 'vue'
import { IonButton } from '@ionic/vue';
import { launch } from '@/game/game.js';

// binds to the v-if on our button to toggle visibility
const showButton = ref(true)

function handleClickStart() {
  // hides launch button
  showButton.value = false;

  // Runs the launch function
  launch();
}
</script>
```

Now we when we click 'Start', our Phaser game launches!

![Screenshot of app in browser with "Hello Phaser" text on screen](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bmoxlcow7d42ht2eqlv1.png)

> [Here is the git commit](https://github.com/ceceliacreates/phaser-tutorial/commit/0ecb4cd1319951f1572e89956100d357ff25e7db) with the changes for this section.

## What's Next

In the next post in this series, we'll make our game more interesting and learn more about Phaser concepts like Scenes, Game Objects, Physics, Assets, and more.

Stay tuned!