# Convert “Shoot 'em Up in an Afternoon” to Phaser 3

**URL:** <https://phaser.discourse.group/t/convert-shoot-em-up-in-an-afternoon-to-phaser-3/12970>\
**Category:** Phaser 3\
**Created:** [March 3, 2023, 4:08pm UTC](https://phaser.discourse.group/t/convert-shoot-em-up-in-an-afternoon-to-phaser-3/12970 "2023-03-03T16:08:14Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![cdtenzi](https://avatars.discourse-cdn.com/v4/letter/c/9f8e36/32.png) [@cdtenzi](https://phaser.discourse.group/u/cdtenzi)\
**Post date:** [March 3, 2023, 4:08pm UTC](https://phaser.discourse.group/t/convert-shoot-em-up-in-an-afternoon-to-phaser-3/12970/1 "2023-03-03T16:08:14Z")

</div>

hello everybody!

I’m picking up this thread after 4 years because i just made the full [“shootem up in 1 afternoon” from Bryan Bibat](https://leanpub.com/html5shootemupinanafternoon/read) (which I loved), and started to migrate that Phaser 2.4 2015 code to a modern ES6+Phaser3 code.

I’m done now with the ES6 Javascript code migration, but want to migrate the API to Phaser 3.

I understand that it is completely different, and states are now scenes and so on. Despite this, I’d love some guidelines on how those old objects match now the new P3 API. Is there anyone here who has followed this path?

Thanks in advance!

---

<div class="post-metadata">

**Author:** ![samme](https://yyz2.discourse-cdn.com/free1/user_avatar/phaser.discourse.group/samme/32/5275_2.png) [@samme](https://phaser.discourse.group/u/samme)\
**Post date:** [March 3, 2023, 9:15pm UTC](https://phaser.discourse.group/t/convert-shoot-em-up-in-an-afternoon-to-phaser-3/12970/2 "2023-03-03T21:15:42Z")

</div>

**API Chains** in [Unofficial Help Center](https://helpcenter.phasereditor2d.com) may help with this. Some methods are similar, but Phaser 3 often uses config arguments.

## Overview

You can use `game.scene.add()` like Phaser 2’s `game.state.add()`, but it’s simpler IMO to add all scenes to the game config instead:

```javascript
new Phaser.Game(
  scene: [Boot, Preloader, MainMenu, Game]
);

```

In a scene you should use the scene’s own plugin, `this.scene`, not the Scene Manager, e.g.,

```
this.scene.start('Game');

```

## Draw Enemy Animation

You can create animations globally or (as in Phaser 2) on a sprite. For animations used on multiple sprites (enemies, explosions), it would be a little more efficient to use global animations.

In Phaser 3 animation frames can come from any texture, so you have to specify a texture key.

## Set Object Anchor

Phaser has `originX` and `originY` instead of `anchor`. Most game object types have a default origin of (0.5, 0.5) already, so you don’t need to set this.

## The Game Loop

There is no scene `render()` callback. There is a similar event callback, but you usually don’t need it.

## Apply Physics

Phaser 3 `this.physics` is the Arcade Physics scene plugin and `this.physics.world` is its simulation.

There is `physics.world.enable()`, but it’s usually more convenient to use the `physics.add` methods:

```
this.bullet = this.physics.add.sprite(400, 400, 'bullet');

```

This creates an Arcade Physics Sprite with extra methods and a physics body.

## Show Body Debug

This is done with `debug: true` in the scene or game Arcade Physics config instead.

## Collision

There’s no `kill()` in Phaser 3. Similar is `setActive(false).setVisible(false)`, but for physics sprites you should use

```
bullet.disableBody(true, true);

```

## Mouse/Touch Movement

There’s no `moveToPointer()`. Use `moveToObject()` instead.

## Firing Bullets

There’s no `keyboard.isDown()`. Create a key object in `create()` and then check its `isDown` in `update()`.

## Fire Rate etc.

I find it easier to create timer events for these things.

## How To Play message

There’s no game object `exists`, but `visible` would be similar here.

A timer event would be easier for this.

## Convert Bullets to Sprite Group

Use

```
this.bulletPool = this.physics.add.group();

```

There’s no `outOfBoundsKill` or similar. You could do this in scene `update()`:

```javascript
if (
  !Phaser.Geom.Rectangle.ContainsRect(
    this.physics.world.bounds,
    bullet.body
  )
) {
  bullet.disableBody(true, true);
}

```

Use `getFirstDead()` for `getFirstExists(false)`.

There’s no general game object `reset()`. `setActive(true).setVisible(true).setPosition(x, y)` would be similar. For physics sprites, use, e.g.,

```
bullet.enableBody(true, this.player.x, this.player.y - 20, true, true);

```

## Enemy Sprite Group

You could create global animations here instead.

```javascript
this.anims.create({
  key: 'greenEnemyFly',
  frames: this.anims.generateFrameNumbers('greenEnemy', { frames: [0, 1, 2] }),
  frameRate: 20,
  repeat: -1
});

```

```javascript
enemy.play('greenEnemyFly');

```

## Randomize Enemy Spawn

`this.enemyPool.countActive(false)` is the dead (inactive) count.

`Phaser.Math.RND` is the random number generator.

## Player Death

Check `this.player.active` or `this.player.visible`.

## Convert Explosions to Sprite Group

You could create global animations here instead.

## Refactoring create

There’s no Tile Sprite `autoScroll`, so keep the update code the same.

## Using Relative Values

`this.scale.width` and `this.scale.height` are the game dimensions.

## Enemy Health

Phaser 3 uses event emitters instead of signals. Game objects are also event emitters.

```javascript
enemy.once('animationcomplete', () => {
  enemy.play('fly');
});

```

But it would be easier to use chained animations instead of an event handler here:

```javascript
enemy.anims.chain('fly');

```

There’s no game object `health` in Phaser 3. You could use the `state` property for this:

```
enemy.state = BasicGame.ENEMY_HEALTH;

```

Then you need to do the damage calculations yourself.

## Win/Lose Conditions, Go back to Menu

There’s no need to destroy everything, because stopping the scene will do that.

```
this.scene.start('MainMenu');

```

## Diagonal Movement

I think this is supposed to be

```
shooter.rotation = shooter.body.velocity.angle();

```

## Boss Battle

I think you need only 1 boss sprite here.

## Sound Effects

MP3 audio is well supported now.

For single audio effects, skip `sound.add()` and use, e.g.,

```
this.sound.play('explosion');

```

instead.

## Restore original game flow

No need to destroy things. Stopping the scene will do that.

```
this.scene.start('MainMenu');

```
