๐Ÿ—บ๏ธPhaser, Map Design & Scenes

Creating captivating and immersive maps is a crucial part of designing engaging Portals in Sunflower Land. To begin designing your map, follow the steps outlined below:

1. Download Sunnyside Pack

Obtain the Sunnyside Pack: Sunflower Land utilizes assets from the Sunnyside pack to design land, water, and buildings. Purchase and download this pack, and locate the Tileset > spr_tileset_sunnysideworld_16px.png file. This file will serve as the foundation for your map design.

2. Setup Tiled Map editor

Download Tiled: Tiled is a free map editor widely used for designing game maps. Visit the official Tiled website at https://www.mapeditor.org/ to download the latest version of Tiled. While the details of working with Tiled are beyond the scope of this guide, we recommend exploring beginner tutorials and videos to familiarize yourself with its features and functionality.

You will want to set up a new map, using the Sunnyside tileset above as the tileset https://www.youtube.com/watch?v=IHmF_bRpOAE

3. Design your layers

It is time to get creative and design your map. You can include unique terrain, resources, paths, decorations and much more!

Naming Conventions for Map Layers: When designing your map, it's helpful to adhere to a consistent naming convention for the layers you create. Here are some recommended naming conventions for your map layers:

  • "Water": This layer is dedicated to placing water tiles on your map.

  • "Ground": Use this layer for the primary ground tiles, forming the base layer of your map.

  • "Path": This layer can be used to create paths or trails for players to navigate.

  • "Decorations Base": This layer serves as the foundation for decorative elements in your map.

  • "Building Base": Use this layer as the base for buildings and structures in your map.

You do not need to follow these conventions, but they will help you collaborate with others.

We will also include support for layers rendering in-front of players. To render a layer in front of a player you can name it "Decorations Layer 2", "Decorations Layer 3", "Decorations Layer 4", "Building Layer 2", "Building Layer 3" or "Building Layer 4".

By using the recommended naming conventions for decoration and building layers, you can ensure that objects appear correctly in relation to the player character. For example, if you want a player to walk behind a tree, place the tree on a higher-numbered decoration or building layer.

4. Add Collisions

Set up a Collision Object Layer: Create a new object layer in Tiled called "Collision."

In this layer, you can draw rectangles that act as collision objects.

These shapes will prevent players from walking through them, keeping players within specific boundaries and preventing them from passing through objects or walls.

5. Export Map

Exporting the Map: Once you have completed your map design in Tiled, go to "File" > "Export As" and save the file as map.json. It is crucial to use the JSON format when saving your map. This file will contain all the necessary information about your map's layout, objects, and collision boundaries.

You can then place this file inside of your Github Repo.

Phaser Setup

Next up we will need to initialise Phaser, the game engine that allows players to walk around and explore your map.

You will want to update the code in your entry point file to initialise Phaser. See the example Mushroom Forest setup below.

import React, { useEffect, useRef, useState } from "react";
import { Game, AUTO } from "phaser";
import NinePatchPlugin from "phaser3-rex-plugins/plugins/ninepatch-plugin.js";
import VirtualJoystickPlugin from "phaser3-rex-plugins/plugins/virtualjoystick-plugin.js";

import { Preloader } from "features/world/scenes/Preloader";
import { MushroomForestScene } from "./MushroomForestScene";
import { OFFLINE_FARM } from "features/game/lib/landData";

export const MushroomForest: React.FC = () => {
  const [loaded, setLoaded] = useState(false);
  const game = useRef<Game>();

  const scene = "mushroom_forest";

  const scenes = [Preloader, MushroomForestScene];

  useEffect(() => {
    const config: Phaser.Types.Core.GameConfig = {
      type: AUTO,
      fps: {
        target: 30,
        smoothStep: true,
      },
      backgroundColor: "#000000",
      parent: "phaser-example",

      autoRound: true,
      pixelArt: true,
      plugins: {
        global: [
          {
            key: "rexNinePatchPlugin",
            plugin: NinePatchPlugin,
            start: true,
          },
          {
            key: "rexVirtualJoystick",
            plugin: VirtualJoystickPlugin,
            start: true,
          },
        ],
      },
      width: window.innerWidth,
      height: window.innerHeight,

      physics: {
        default: "arcade",
        arcade: {
          debug: true,
          gravity: { y: 0 },
        },
      },
      scene: scenes,
      loader: {
        crossOrigin: "anonymous",
      },
    };

    game.current = new Game({
      ...config,
      parent: "game-content",
    });

    game.current.registry.set("initialScene", scene);

    game.current.registry.set("initialScene", scene);
    game.current.registry.set("gameState", OFFLINE_FARM);

    setLoaded(true);

    return () => {
      game.current?.destroy(true);
    };
  }, []);

  const ref = useRef<HTMLDivElement>(null);

  return (
    <div>
      <div id="game-content" ref={ref} />
    </div>
  );
};

Once you have update the base React component, you will create a new Scene.

import mapJson from "assets/map/mushroom_forest.json";
import { SceneId } from "features/world/mmoMachine";
import { BaseScene } from "features/world/scenes/BaseScene";

export class MushroomForestScene extends BaseScene {
  sceneId: SceneId = "mushroom_forest";

  constructor() {
    super({
      name: "mushroom_forest",
      map: { json: mapJson },
      audio: { fx: { walk_key: "dirt_footstep" } },
    });
  }

  preload() {
    super.preload();

    // Ambience SFX
    if (!this.sound.get("nature_1")) {
      const nature1 = this.sound.add("nature_1");
      nature1.play({ loop: true, volume: 0.01 });
    }

    // Shut down the sound when the scene changes
    this.events.once("shutdown", () => {
      this.sound.getAllPlaying().forEach((sound) => {
        sound.destroy();
      });
    });
  }

  async create() {
    this.map = this.make.tilemap({
      key: "mushroom_forest",
    });

    super.create();
  }
}

Notice on line 1 that we have imported the newly created JSON file

How to use a custom tileset?

Do you want to use custom assets on your map such as biomes or themes? You can do so inside of your Scene configuration by specifying a tileset property.

If you are using proprietary assets, ensure you are hosting them on a protected server.

Inside of Preloader.ts you will want to update the tileset that points to wherever your tileset is located.

      // Phaser assets must be served from an URL
      this.load.image(
        "tileset",
        `https://custom-uploaded-url/tileset.png`
      );

Last updated