<div id=parent></div>
<footer><div id=version></div></footer>
html, body {
height: 100%;
}
body {
margin: 0;
padding: 0;
background: #111 url(https://labs.phaser.io/assets/sprites/phaser3-logo-small.png) no-repeat 0 20px;
color: #eee;
font: caption;
}
#version {
}
/* global colors, Phaser */
const { Overlaps } = Phaser.Geom.Rectangle;
const { Wrap } = Phaser.Math;
class Example extends Phaser.Scene {
controls;
map;
mapRect;
preload() {
this.load.atlas(
"bird",
"assets/animations/bird.png",
"assets/animations/bird.json"
);
this.load.image("melon", "assets/sprites/melon.png");
this.load.image("tiles", "assets/tilemaps/tiles/tmw_desert_spacing.png");
this.load.tilemapTiledJSON("map", "assets/tilemaps/maps/desert.json");
this.textures.once("addtexture-bird", () => {
this.anims.create({
key: "walk",
frames: this.anims.generateFrameNames("bird", {
prefix: "frame",
end: 9
}),
repeat: -1
});
});
}
create() {
this.map = this.make.tilemap({ key: "map" });
const { widthInPixels, heightInPixels } = this.map;
this.mapRect = new Phaser.Geom.Rectangle(
0,
0,
widthInPixels,
heightInPixels
);
this.map.createLayer("Ground", this.map.addTilesetImage("Desert", "tiles"));
this.add.image(0.5 * widthInPixels, 0.5 * heightInPixels, "melon");
this.add.sprite(64, 64, "bird").play("walk");
this.add
.sprite(widthInPixels - 64, heightInPixels - 64, "bird")
.play("walk")
.setFlipX(true);
// Guides
this.add
.graphics()
.lineStyle(2, colors.hexColors.white, 0.5)
.lineBetween(0, 0, widthInPixels, heightInPixels)
.lineBetween(0, heightInPixels, widthInPixels, 0)
.strokeEllipse(
0.5 * heightInPixels,
0.5 * widthInPixels,
heightInPixels,
widthInPixels,
64
);
this.cameras.main.setName("main");
this.cameras.add().setAlpha(0.8).setName("X");
this.cameras.add().setAlpha(0.8).setName("Y");
this.cameras.add().setAlpha(0.8).setName("XY");
this.cursors = this.input.keyboard.createCursorKeys();
const { left, right, up, down } = this.cursors;
const controlConfig = {
camera: this.cameras.main,
left: left,
right: right,
up: up,
down: down,
speed: 1
};
this.controls = new Phaser.Cameras.Controls.FixedKeyControl(controlConfig);
}
update(time, delta) {
this.controls.update(delta);
const { widthInPixels, heightInPixels } = this.map;
const [main, camX, camY, camXY] = this.cameras.cameras;
// Wrap the main camera view.
main.scrollX = Wrap(main.scrollX, -main.width, widthInPixels - main.width);
main.scrollY = Wrap(
main.scrollY,
-main.height,
heightInPixels - main.height
);
const { scrollX, scrollY } = main;
// Scroll the extra cameras.
camX.scrollX =
scrollX > 0 ? scrollX - widthInPixels : scrollX + widthInPixels;
camX.scrollY = scrollY;
camY.scrollX = scrollX;
camY.scrollY =
scrollY > 0 ? scrollY - heightInPixels : scrollY + heightInPixels;
camXY.scrollX = camX.scrollX;
camXY.scrollY = camY.scrollY;
// Update worldViews.
camX.preRender();
camY.preRender();
camXY.preRender();
// Hide cameras scrolled outside the world.
camX.visible = Overlaps(this.mapRect, camX.worldView);
camY.visible = Overlaps(this.mapRect, camY.worldView);
camXY.visible = Overlaps(this.mapRect, camXY.worldView);
// Wrap sprites.
Phaser.Actions.WrapInRectangle(
this.sys.displayList.getChildren(),
this.mapRect
);
}
}
class DebugCameraPlugin extends Phaser.Plugins.ScenePlugin {
boot() {
if (!this.systems.renderer.gameContext) {
throw new Error("CANVAS renderer only");
}
this.systems.events
.on("render", this.render, this)
.on("destroy", this.sceneDestroy, this);
}
render() {
const ctx = this.systems.renderer.gameContext;
ctx.font = "16px monospace";
ctx.textBaseline = "top";
const tx = 0;
let ty = 0;
for (const cam of this.systems.cameras.cameras) {
ctx.fillStyle = "rgba(0,0,0,0.5)";
ctx.fillRect(tx, ty, cam.width, 20);
ctx.fillStyle = "white";
ctx.fillText(this.describe(cam), tx, ty, cam.width);
ty += 20;
}
}
sceneDestroy() {
this.systems.events.off("render", this.render, this);
}
describe(cam) {
const { name, scrollX, scrollY, visible, worldView } = cam;
return (
(visible ? "• " : " ") +
`${name} ` +
`scroll=(${scrollX.toFixed(0)} ${scrollY.toFixed(0)}) ` +
`worldView=(${worldView.left.toFixed(0)} ${worldView.top.toFixed(
0
)} ${worldView.right.toFixed(0)} ${worldView.bottom.toFixed(0)})`
);
}
}
const config = {
type: Phaser.CANVAS,
width: 640,
height: 640,
// backgroundColor: colors.hexColors.green,
parent: "parent",
pixelArt: true,
scene: Example,
loader: {
baseURL: "https://labs.phaser.io/",
crossOrigin: "anonymous"
},
plugins: {
scene: [{ key: "DebugCamera", plugin: DebugCameraPlugin }]
}
};
const game = new Phaser.Game(config);
document.getElementById("version").textContent = `Phaser v${Phaser.VERSION}`;
This Pen doesn't use any external CSS resources.