Skip to content

Instantly share code, notes, and snippets.

@FoamyGuy
Created November 14, 2021 22:54
Show Gist options
  • Save FoamyGuy/f4a57c6fd1752abe4b109b53aa5007ff to your computer and use it in GitHub Desktop.
Save FoamyGuy/f4a57c6fd1752abe4b109b53aa5007ff to your computer and use it in GitHub Desktop.
/**
* Author: Michael Hadley, mikewesthad.com
* Asset Credits:
* - Tuxemon, https://github.com/Tuxemon/Tuxemon
*/
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
parent: "game-container",
pixelArt: true,
physics: {
default: "arcade",
arcade: {
gravity: {y: 0}
}
},
scene: {
preload: preload,
create: create,
update: update
}
};
const game = new Phaser.Game(config);
let cursors;
let player;
let showDebug = false;
let keyA;
let keyS;
let keyD;
let keyW;
const AREA_OUTSIDE = "Outside";
const AREA_BUILDING_0 = "Building0";
let CUR_AREA = AREA_OUTSIDE;
let tileset;
let aboveLayer;
let worldLayer;
let belowLayer;
let doorLayer;
let belowCollider;
let worldCollider;
let doorOverlaps = [];
let doorGroup;
let debugGraphic;
let map;
function getPropertyValue(object, property_name) {
if (object.hasOwnProperty("properties")) {
for (let i = 0; i < object.properties.length; i++) {
if (object.properties[i].name === property_name) {
return object.properties[i].value;
}
}
}
return undefined;
}
function showArea(game, area_name, spawn_obj_name) {
console.log(map.getTileLayerNames());
if (aboveLayer !== undefined) {
console.log("Need to destroy:");
console.log(CUR_AREA);
belowLayer.destroy();
aboveLayer.destroy();
worldLayer.destroy();
//map.destroyLayer(CUR_AREA + "/Below Player");
//map.destroyLayer(CUR_AREA + "/World");
//map.destroyLayer(CUR_AREA + "/Above Player");
console.log(map.getTileLayerNames());
//game.physics.remove(doorGroup);
doorGroup.clear(true, true);
game.physics.world.removeCollider(belowCollider);
game.physics.world.removeCollider(worldCollider);
for (let i = 0; i < doorOverlaps.length; i++){
doorOverlaps[i].destroy()
}
doorOverlaps = [];
//debugGraphic.destroy();
}
CUR_AREA = area_name
if (spawn_obj_name === undefined) {
spawn_obj_name = "Spawn Point";
}
console.log("area: " + CUR_AREA);
console.log(map.getTileLayerNames());
// Parameters: layer name (or index) from Tiled, tileset, x, y
belowLayer = map.createLayer(CUR_AREA + "/Below Player", tileset, 0, 0);
worldLayer = map.createLayer(CUR_AREA + "/World", tileset, 0, 0);
aboveLayer = map.createLayer(CUR_AREA + "/Above Player", tileset, 0, 0);
doorLayer = map.getObjectLayer(CUR_AREA + "/Doors")['objects'];
console.log("world layer");
console.log(worldLayer);
worldLayer.setCollisionByProperty({collides: true});
belowLayer.setCollisionByProperty({collides: true});
console.log("layer depth:");
console.log(belowLayer.depth);
// By default, everything gets depth sorted on the screen in the order we created things. Here, we
// want the "Above Player" layer to sit on top of the player, so we explicitly give it a depth.
// Higher depths will sit on top of lower depth objects.
aboveLayer.setDepth(10);
// Object layers in Tiled let you embed extra info into a map - like a spawn point or custom
// collision shapes. In the tmx file, there's an object layer with a point named "Spawn Point"
const spawnPoint = map.findObject(CUR_AREA + "/Objects", obj => obj.name === spawn_obj_name);
player.x = spawnPoint.x;
player.y = spawnPoint.y;
// Watch the player and worldLayer for collisions, for the duration of the scene:
worldCollider = game.physics.add.collider(player, worldLayer);
belowCollider = game.physics.add.collider(player, belowLayer);
doorLayer.forEach(door => {
console.log("door: ");
console.log(door);
// TODO: why is hardcoding +16 needed here?
let door_body = doorGroup.create(door.x + 16, door.y + 16, "door");
door_body.body.width = door.width;
door_body.body.height = door.height;
door_body.visible = false;
//console.log(door_body.height)
//console.log(door_body.body.height)
doorOverlaps.push(game.physics.add.overlap(player, door_body, function (args) {
//console.log(args)
//console.log("player touching door_0");
console.log(getPropertyValue(door, "change_map"));
showArea(game, getPropertyValue(door, "change_map"));
}));
});
debugGraphic = game.physics.world.createDebugGraphic();
// Create worldLayer collision graphic above the player, but below the help text
const graphics = game.add
.graphics()
.setAlpha(0.75)
.setDepth(20);
worldLayer.renderDebug(graphics, {
tileColor: null, // Color of non-colliding tiles
collidingTileColor: new Phaser.Display.Color(243, 134, 48, 255), // Color of colliding tiles
faceColor: new Phaser.Display.Color(40, 39, 37, 255) // Color of colliding face edges
});
}
function preload() {
this.load.image("tiles", "img/tilemap_packed.png");
this.load.tilemapTiledJSON("map", "maps/map_0.json");
// An atlas is a way to pack multiple images together into one texture. I'm using it to load all
// the player animations (walking left, walking right, etc.) in one image. For more info see:
// https://labs.phaser.io/view.html?src=src/animation/texture%20atlas%20animation.js
// If you don't use an atlas, you can do the same thing with a spritesheet, see:
// https://labs.phaser.io/view.html?src=src/animation/single%20sprite%20sheet.js
//this.load.atlas("atlas", "https://mikewesthad.github.io/phaser-3-tilemap-blog-posts/post-1/assets/atlas/atlas.png", "https://mikewesthad.github.io/phaser-3-tilemap-blog-posts/post-1/assets/atlas/atlas.json");
this.load.atlas("atlas", "img/char_0.png", "img/char_0.json");
}
function create() {
map = this.make.tilemap({key: "map"});
console.log(map.getTileLayerNames());
// Parameters are the name you gave the tileset in Tiled and then the key of the tileset image in
// Phaser's cache (i.e. the name you used in preload)
tileset = map.addTilesetImage("tilemap_packed", "tiles");
//console.log(door_0_obj);
// Create a sprite with physics enabled via the physics system. The image used for the sprite has
// a bit of whitespace, so I'm using setSize & setOffset to control the size of the player's body.
player = this.physics.add
.sprite(0, 0, "atlas", "misa-front")
.setSize(16, 16)
.setOffset(0, 0);
player.setDepth(1);
console.log("depth: ");
console.log(player.depth);
doorGroup = this.physics.add.staticGroup();
showArea(this, AREA_BUILDING_0);
/*const door_0_obj = map.findObject("Doors", obj => obj.name === "door_0");
door_0_group = this.physics.add.staticGroup();
door_0_body = door_0_group.create(door_0_obj.x+16, door_0_obj.y+16, "door_0");
//door_0_body.setScale(door_0_obj.polygon[1][0]/16, door_0_obj.polygon[2][1]/16);
door_0_body.body.width = door_0_obj.width;
door_0_body.body.height = door_0_obj.height;
door_0_body.setOrigin(0);
//door_0_body.body.setOrigin(0)
door_0_body.visible = false;*/
/*this.physics.add.overlap(player, door_0_body, function (args) {
//console.log(args)
//console.log("player touching door_0");
console.log(getPropertyValue(door_0_obj, "change_map"));
});*/
// Create the player's walking animations from the texture atlas. These are stored in the global
// animation manager so any sprite can access them.
const anims = this.anims;
console.log(anims.generateFrameNames("atlas", {prefix: "char_0/char_0_back_walk/", start: 1, end: 3, zeroPad: 4}));
anims.create({
key: "misa-left-walk",
frames: anims.generateFrameNames("atlas", {prefix: "char_0/char_0_left_walk/", start: 1, end: 3, zeroPad: 4}),
frameRate: 10,
repeat: -1
});
anims.create({
key: "misa-right-walk",
frames: anims.generateFrameNames("atlas", {prefix: "char_0/char_0_right_walk/", start: 1, end: 3, zeroPad: 4}),
frameRate: 10,
repeat: -1
});
anims.create({
key: "misa-front-walk",
frames: anims.generateFrameNames("atlas", {prefix: "char_0/char_0_front_walk/", start: 1, end: 3, zeroPad: 4}),
frameRate: 10,
repeat: -1
});
anims.create({
key: "misa-back-walk",
frames: anims.generateFrameNames("atlas", {prefix: "char_0/char_0_back_walk/", start: 1, end: 3, zeroPad: 4}),
frameRate: 10,
repeat: -1
});
const camera = this.cameras.main;
camera.startFollow(player);
camera.setBounds(0, 0, map.widthInPixels, map.heightInPixels);
cursors = this.input.keyboard.createCursorKeys();
keyA = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.A);
keyS = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.S);
keyD = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.D);
keyW = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.W);
camera.zoom = 2
console.log(camera.zoom)
// Help text that has a "fixed" position on the screen
/*this.add
.text(16, 16, 'Arrow keys to move\nPress "D" to show hitboxes', {
font: "18px monospace",
fill: "#000000",
padding: { x: 20, y: 10 },
backgroundColor: "#ffffff"
})
.setScrollFactor(0)
.setDepth(30);*/
// Debug graphics
/*this.input.keyboard.once("keydown-D", event => {
// Turn on physics debugging to show player's hitbox
this.physics.world.createDebugGraphic();
// Create worldLayer collision graphic above the player, but below the help text
const graphics = this.add
.graphics()
.setAlpha(0.75)
.setDepth(20);
worldLayer.renderDebug(graphics, {
tileColor: null, // Color of non-colliding tiles
collidingTileColor: new Phaser.Display.Color(243, 134, 48, 255), // Color of colliding tiles
faceColor: new Phaser.Display.Color(40, 39, 37, 255) // Color of colliding face edges
});
});*/
}
function update(time, delta) {
const speed = 175;
const prevVelocity = player.body.velocity.clone();
// Stop any previous movement from the last frame
player.body.setVelocity(0);
// Horizontal movement
if (keyA.isDown) {
player.body.setVelocityX(-speed);
} else if (keyD.isDown) {
player.body.setVelocityX(speed);
}
// Vertical movement
if (keyW.isDown) {
player.body.setVelocityY(-speed);
} else if (keyS.isDown) {
player.body.setVelocityY(speed);
}
// Normalize and scale the velocity so that player can't move faster along a diagonal
player.body.velocity.normalize().scale(speed);
// Update the animation last and give left/right animations precedence over up/down animations
if (keyA.isDown) {
player.anims.play("misa-left-walk", true);
} else if (keyD.isDown) {
player.anims.play("misa-right-walk", true);
} else if (keyW.isDown) {
player.anims.play("misa-back-walk", true);
} else if (keyS.isDown) {
player.anims.play("misa-front-walk", true);
} else {
player.anims.stop();
// If we were moving, pick and idle frame to use
if (prevVelocity.x < 0) player.setTexture("atlas", "char_0/char_0_left_walk/0001");
else if (prevVelocity.x > 0) player.setTexture("atlas", "char_0/char_0_right_walk/0001");
else if (prevVelocity.y < 0) player.setTexture("atlas", "char_0/char_0_back_walk/0001");
else if (prevVelocity.y > 0) player.setTexture("atlas", "char_0/char_0_front_walk/0001");
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment