// Toggle this to disable the room hiding / layer scale, so you can see the extent of the map easily!
const debug = false;
// Tile index mapping to make the code more readable
const TILES = {
TOP_LEFT_WALL: 3,
TOP_RIGHT_WALL: 4,
BOTTOM_RIGHT_WALL: 23,
BOTTOM_LEFT_WALL: 22,
TOP_WALL: [
{ index: 39, weight: 4 },
{ index: 57, weight: 1 },
{ index: 58, weight: 1 },
{ index: 59, weight: 1 }
],
LEFT_WALL: [
{ index: 21, weight: 4 },
{ index: 76, weight: 1 },
{ index: 95, weight: 1 },
{ index: 114, weight: 1 }
],
RIGHT_WALL: [
{ index: 19, weight: 4 },
{ index: 77, weight: 1 },
{ index: 96, weight: 1 },
{ index: 115, weight: 1 }
],
BOTTOM_WALL: [
{ index: 1, weight: 4 },
{ index: 78, weight: 1 },
{ index: 79, weight: 1 },
{ index: 80, weight: 1 }
],
FLOOR: [
{ index: 6, weight: 20 },
{ index: 7, weight: 1 },
{ index: 8, weight: 1 },
{ index: 26, weight: 1 },
]
};
class Example extends Phaser.Scene
{
activeRoom;
dungeon;
map;
player;
cursors;
cam;
layer;
lastMoveTime = 0;
preload ()
{
this.load.setBaseURL('https://cdn.phaserfiles.com/v355');
// Credits! Michele "Buch" Bucelli (tilset artist) & Abram Connelly (tileset sponser)
// https://opengameart.org/content/top-down-dungeon-tileset
this.load.image('tiles', 'assets/tilemaps/tiles/buch-dungeon-tileset-extruded.png');
}
create ()
{
// Note: Dungeon is not a Phaser element - it's from the custom script embedded at the bottom :)
// It generates a simple set of connected rectangular rooms that then we can turn into a tilemap
// 2,500 tile test
// dungeon = new Dungeon({
// width: 50,
// height: 50,
// rooms: {
// width: { min: 7, max: 15, onlyOdd: true },
// height: { min: 7, max: 15, onlyOdd: true }
// }
// });
// 40,000 tile test
this.dungeon = new Dungeon({
width: 200,
height: 200,
rooms: {
width: { min: 7, max: 20, onlyOdd: true },
height: { min: 7, max: 20, onlyOdd: true }
}
});
// 250,000 tile test!
// dungeon = new Dungeon({
// width: 500,
// height: 500,
// rooms: {
// width: { min: 7, max: 20, onlyOdd: true },
// height: { min: 7, max: 20, onlyOdd: true }
// }
// });
// 1,000,000 tile test! - Warning, takes a few seconds to generate the dungeon :)
// dungeon = new Dungeon({
// width: 1000,
// height: 1000,
// rooms: {
// width: { min: 7, max: 20, onlyOdd: true },
// height: { min: 7, max: 20, onlyOdd: true }
// }
// });
// Creating a blank tilemap with dimensions matching the dungeon
this.map = this.make.tilemap({ tileWidth: 16, tileHeight: 16, width: this.dungeon.width, height: this.dungeon.height });
// addTilesetImage: function (tilesetName, key, tileWidth, tileHeight, tileMargin, tileSpacing, gid)
var tileset = this.map.addTilesetImage('tiles', 'tiles', 16, 16, 1, 2);
this.layer = this.map.createBlankLayer('Layer 1', tileset);
if (!debug)
{
this.layer.setScale(3);
}
// Fill with black tiles
this.layer.fill(20);
// Use the array of rooms generated to place tiles in the map
this.dungeon.rooms.forEach(function (room) {
var x = room.x;
var y = room.y;
var w = room.width;
var h = room.height;
var cx = Math.floor(x + w / 2);
var cy = Math.floor(y + h / 2);
var left = x;
var right = x + (w - 1);
var top = y;
var bottom = y + (h - 1);
// Fill the floor with mostly clean tiles, but occasionally place a dirty tile
// See "Weighted Randomize" example for more information on how to use weightedRandomize.
this.map.weightedRandomize(TILES.FLOOR, x, y, w, h);
// Place the room corners tiles
this.map.putTileAt(TILES.TOP_LEFT_WALL, left, top);
this.map.putTileAt(TILES.TOP_RIGHT_WALL, right, top);
this.map.putTileAt(TILES.BOTTOM_RIGHT_WALL, right, bottom);
this.map.putTileAt(TILES.BOTTOM_LEFT_WALL, left, bottom);
// Fill the walls with mostly clean tiles, but occasionally place a dirty tile
this.map.weightedRandomize(TILES.TOP_WALL, left + 1, top, w - 2, 1);
this.map.weightedRandomize(TILES.BOTTOM_WALL, left + 1, bottom, w - 2, 1);
this.map.weightedRandomize(TILES.LEFT_WALL, left, top + 1, 1, h - 2);
this.map.weightedRandomize(TILES.RIGHT_WALL, right, top + 1, 1, h - 2);
// Dungeons have rooms that are connected with doors. Each door has an x & y relative to the rooms location
var doors = room.getDoorLocations();
for (var i = 0; i < doors.length; i++)
{
this.map.putTileAt(6, x + doors[i].x, y + doors[i].y);
}
// Place some random stuff in rooms occasionally
var rand = Math.random();
if (rand <= 0.25)
{
this.layer.putTileAt(166, cx, cy); // Chest
}
else if (rand <= 0.3)
{
this.layer.putTileAt(81, cx, cy); // Stairs
}
else if (rand <= 0.4)
{
this.layer.putTileAt(167, cx, cy); // Trap door
}
else if (rand <= 0.6)
{
if (room.height >= 9)
{
// We have room for 4 towers
this.layer.putTilesAt([
[ 186 ],
[ 205 ]
], cx - 1, cy + 1);
this.layer.putTilesAt([
[ 186 ],
[ 205 ]
], cx + 1, cy + 1);
this.layer.putTilesAt([
[ 186 ],
[ 205 ]
], cx - 1, cy - 2);
this.layer.putTilesAt([
[ 186 ],
[ 205 ]
], cx + 1, cy - 2);
}
else
{
this.layer.putTilesAt([
[ 186 ],
[ 205 ]
], cx - 1, cy - 1);
this.layer.putTilesAt([
[ 186 ],
[ 205 ]
], cx + 1, cy - 1);
}
}
}, this);
// Not exactly correct for the tileset since there are more possible floor tiles, but this will
// do for the example.
this.layer.setCollisionByExclusion([ 6, 7, 8, 26 ]);
// Hide all the rooms
if (!debug)
{
this.layer.forEachTile(function (tile) { tile.alpha = 0; });
}
// Place the player in the first room
var playerRoom = this.dungeon.rooms[0];
this.player = this.add.graphics({ fillStyle: { color: 0xedca40, alpha: 1 } }).fillRect(0, 0, this.map.tileWidth * this.layer.scaleX, this.map.tileHeight * this.layer.scaleY);
this.player.x = this.map.tileToWorldX(playerRoom.x + 1);
this.player.y = this.map.tileToWorldY(playerRoom.y + 1);
if (!debug)
{
this.setRoomAlpha(playerRoom, 1); // Make the starting room visible
}
// Scroll to the player
this.cam = this.cameras.main;
this.cam.setBounds(0, 0, this.layer.width * this.layer.scaleX, this.layer.height * this.layer.scaleY);
this.cam.scrollX = this.player.x - this.cam.width * 0.5;
this.cam.scrollY = this.player.y - this.cam.height * 0.5;
this.cursors = this.input.keyboard.createCursorKeys();
var help = this.add.text(16, 16, 'Arrows keys to move', {
fontSize: '18px',
padding: { x: 10, y: 5 },
backgroundColor: '#ffffff',
fill: '#000000'
});
help.setScrollFactor(0);
var gui = new dat.GUI();
gui.addFolder('Camera');
gui.add(this.cam, 'scrollX').listen();
gui.add(this.cam, 'scrollY').listen();
gui.add(this.cam, 'zoom', 0.1, 4).step(0.1);
gui.add(this.cam, 'rotation').step(0.01);
gui.add(this.layer, 'skipCull').listen();
gui.add(this.layer, 'cullPaddingX').step(1);
gui.add(this.layer, 'cullPaddingY').step(1);
gui.add(this.layer, 'tilesDrawn').listen();
gui.add(this.layer, 'tilesTotal').listen();
}
update (time, delta)
{
this.updatePlayerMovement(time);
var playerTileX = this.map.worldToTileX(this.player.x);
var playerTileY = this.map.worldToTileY(this.player.y);
// Another helper method from the dungeon - dungeon XY (in tiles) -> room
var room = this.dungeon.getRoomAt(playerTileX, playerTileY);
// If the player has entered a new room, make it visible and dim the last room
if (room && this.activeRoom && this.activeRoom !== room)
{
if (!debug)
{
this.setRoomAlpha(room, 1);
this.setRoomAlpha(this.activeRoom, 0.5);
}
}
this.activeRoom = room;
// Smooth follow the player
var smoothFactor = 0.9;
this.cam.scrollX = smoothFactor * this.cam.scrollX + (1 - smoothFactor) * (this.player.x - this.cam.width * 0.5);
this.cam.scrollY = smoothFactor * this.cam.scrollY + (1 - smoothFactor) * (this.player.y - this.cam.height * 0.5);
}
// Helpers functions
setRoomAlpha(room, alpha)
{
this.map.forEachTile(function (tile) {
tile.alpha = alpha;
}, this, room.x, room.y, room.width, room.height)
}
isTileOpenAt (worldX, worldY)
{
// nonNull = true, don't return null for empty tiles. This means null will be returned only for
// tiles outside of the bounds of the map.
var tile = this.map.getTileAtWorldXY(worldX, worldY, true);
if (tile && !tile.collides)
{
return true;
}
else
{
return false;
}
}
updatePlayerMovement (time)
{
var tw = this.map.tileWidth * this.layer.scaleX;
var th = this.map.tileHeight * this.layer.scaleY;
var repeatMoveDelay = 100;
if (time > this.lastMoveTime + repeatMoveDelay) {
if (this.cursors.down.isDown)
{
if (this.isTileOpenAt(this.player.x, this.player.y + th))
{
this.player.y += th;
this.lastMoveTime = time;
}
}
else if (this.cursors.up.isDown)
{
if (this.isTileOpenAt(this.player.x, this.player.y - th))
{
this.player.y -= th;
this.lastMoveTime = time;
}
}
if (this.cursors.left.isDown)
{
if (this.isTileOpenAt(this.player.x - tw, this.player.y))
{
this.player.x -= tw;
this.lastMoveTime = time;
}
}
else if (this.cursors.right.isDown)
{
if (this.isTileOpenAt(this.player.x + tw, this.player.y))
{
this.player.x += tw;
this.lastMoveTime = time;
}
}
}
}
}
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
backgroundColor: '#2a2a55',
parent: 'phaser-example',
pixelArt: true,
roundPixels: false,
scene: Example
};
const game = new Phaser.Game(config);
// Minified & modified dungeon generator at mikewesthad/dungeon (fork of nickgravelyn/dungeon)
!function(t,o){"object"==typeof exports&&"object"==typeof module?module.exports=o():"function"==typeof define&&define.amd?define([],o):"object"==typeof exports?exports.Dungeon=o():t.Dungeon=o()}("undefined"!=typeof self?self:this,function(){return function(t){function o(r){if(e[r])return e[r].exports;var i=e[r]={i:r,l:!1,exports:{}};return t[r].call(i.exports,i,i.exports,o),i.l=!0,i.exports}var e={};return o.m=t,o.c=e,o.d=function(t,e,r){o.o(t,e)||Object.defineProperty(t,e,{configurable:!1,enumerable:!0,get:r})},o.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return o.d(e,"a",e),e},o.o=function(t,o){return Object.prototype.hasOwnProperty.call(t,o)},o.p="",o(o.s=1)}([function(t,o,e){"use strict";Object.defineProperty(o,"__esModule",{value:!0});var r={EMPTY:0,WALL:1,FLOOR:2,DOOR:3};o.default=r},function(t,o,e){"use strict";t.exports=e(2).default},function(t,o,e){"use strict";function r(t){return t&&t.__esModule?t:{default:t}}function i(t,o){if(!(t instanceof o))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(o,"__esModule",{value:!0});var n=function(){function t(t,o){var e=[],r=!0,i=!1,n=void 0;try{for(var h,a=t[Symbol.iterator]();!(r=(h=a.next()).done)&&(e.push(h.value),!o||e.length!==o);r=!0);}catch(t){i=!0,n=t}finally{try{!r&&a.return&&a.return()}finally{if(i)throw n}}return e}return function(o,e){if(Array.isArray(o))return o;if(Symbol.iterator in Object(o))return t(o,e);throw new TypeError("Invalid attempt to destructure non-iterable instance")}}(),h=function(){function t(t,o){for(var e=0;e0&&void 0!==arguments[0]?arguments[0]:{};i(this,t);var e=o.rooms||{};e.width=Object.assign({},m.rooms.width,e.width),e.height=Object.assign({},m.rooms.height,e.height),e.maxArea=e.maxArea||m.rooms.maxArea,e.maxRooms=e.maxRooms||m.rooms.maxRooms,e.width.min<3&&(e.width.min=3),e.height.min<3&&(e.height.min=3),e.width.max0;)this.generateRoom(),r-=1;for(var i=0;i=this.width||o>=this.height?null:this.roomGrid[o][t][0]}},{key:"getMappedTiles",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};return t=Object.assign({},{empty:0,wall:1,floor:2,door:3},t),this.tiles.map(function(o){return o.map(function(o){return o===l.default.EMPTY?t.empty:o===l.default.WALL?t.wall:o===l.default.FLOOR?t.floor:o===l.default.DOOR?t.door:void 0})})}},{key:"addRoom",value:function(t){if(!this.canFitRoom(t))return!1;this.rooms.push(t);for(var o=t.top;o<=t.bottom;o++)for(var e=t.left;e<=t.right;e++)this.roomGrid[o][e].push(t);return!0}},{key:"canFitRoom",value:function(t){if(t.x<0||t.x+t.width>this.width-1)return!1;if(t.y<0||t.y+t.height>this.height-1)return!1;for(var o=0;or.maxArea);return new u.default(t,o)}},{key:"generateRoom",value:function(){for(var t=this.createRandomRoom(),o=150;o>0;){var e=this.findRoomAttachment(t);if(t.setPosition(e.x,e.y),this.addRoom(t)){var r=this.findNewDoorLocation(t,e.target),i=n(r,2),h=i[0],a=i[1];this.addDoor(h),this.addDoor(a);break}o-=1}}},{key:"getTiles",value:function(){for(var t=Array(this.height),o=0;o0&&a0&&s2&&void 0!==arguments[2]?arguments[2]:{},r=e.onlyOdd,h=void 0!==r&&r,a=e.onlyEven,s=void 0!==a&&a;return h?n(t,o):s?i(t,o):Math.floor(Math.random()*(o-t+1)+t)}function i(t,o){t%2!=0&&tt&&o--;var e=(o-t)/2;return 2*Math.floor(Math.random()*(e+1))+t}function n(t,o){t%2==0&&t++,o%2==0&&o--;var e=(o-t)/2;return 2*Math.floor(Math.random()*(e+1))+t}function h(t){return t[r(0,t.length-1)]}Object.defineProperty(o,"__esModule",{value:!0}),o.randomInteger=r,o.randomEvenInteger=i,o.randomOddInteger=n,o.randomPick=h},function(t,o,e){"use strict";function r(t,o){if(!(t instanceof o))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(o,"__esModule",{value:!0});var i=function(){function t(t,o){for(var e=0;et.right)&&(!(this.bottomt.bottom)))}},{key:"isConnectedTo",value:function(t){for(var o=this.getDoorLocations(),e=0;et.width-1||r.y<0||r.y>t.height-1)&&t.tiles[r.y][r.x]==h.default.DOOR)return!0}return!1}}]),t}();o.default=a},function(t,o,e){"use strict";function r(t){var o=t.roomGrid.map(function(t){return t.map(function(t){return(""+t.length).padStart(2)})});console.log(o.map(function(t){return t.join(" ")}).join("\n"))}function i(t){var o,e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};e=Object.assign({},{empty:" ",emptyColor:"rgb(0, 0, 0)",wall:"#",wallColor:"rgb(255, 0, 0)",floor:"_",floorColor:"rgb(210, 210, 210)",door:".",doorColor:"rgb(0, 0, 255)",fontSize:"15px"},e);for(var r="",i=[],n=0;n
Scan to open on your mobile device
// Toggle this to disable the room hiding / layer scale, so you can see the extent of the map easily! const debug = false; // Tile index mapping to make the code more readable const TILES = { TOP_LEFT_WALL: 3, TOP_RIGHT_WALL: 4, BOTTOM_RIGHT_WALL: 23, BOTTOM_LEFT_WALL: 22, TOP_WALL: [ { index: 39, weight: 4 }, { index: 57, weight: 1 }, { index: 58, weight: 1 }, { index: 59, weight: 1 } ], LEFT_WALL: [ { index: 21, weight: 4 }, { index: 76, weight: 1 }, { index: 95, weight: 1 }, { index: 114, weight: 1 } ], RIGHT_WALL: [ { index: 19, weight: 4 }, { index: 77, weight: 1 }, { index: 96, weight: 1 }, { index: 115, weight: 1 } ], BOTTOM_WALL: [ { index: 1, weight: 4 }, { index: 78, weight: 1 }, { index: 79, weight: 1 }, { index: 80, weight: 1 } ], FLOOR: [ { index: 6, weight: 20 }, { index: 7, weight: 1 }, { index: 8, weight: 1 }, { index: 26, weight: 1 }, ] }; class Example extends Phaser.Scene { activeRoom; dungeon; map; player; cursors; cam; layer; lastMoveTime = 0; preload () { this.load.setBaseURL('https://cdn.phaserfiles.com/v355'); // Credits! Michele "Buch" Bucelli (tilset artist) & Abram Connelly (tileset sponser) // https://opengameart.org/content/top-down-dungeon-tileset this.load.image('tiles', 'assets/tilemaps/tiles/buch-dungeon-tileset-extruded.png'); } create () { // Note: Dungeon is not a Phaser element - it's from the custom script embedded at the bottom :) // It generates a simple set of connected rectangular rooms that then we can turn into a tilemap // 2,500 tile test // dungeon = new Dungeon({ // width: 50, // height: 50, // rooms: { // width: { min: 7, max: 15, onlyOdd: true }, // height: { min: 7, max: 15, onlyOdd: true } // } // }); // 40,000 tile test this.dungeon = new Dungeon({ width: 200, height: 200, rooms: { width: { min: 7, max: 20, onlyOdd: true }, height: { min: 7, max: 20, onlyOdd: true } } }); // 250,000 tile test! // dungeon = new Dungeon({ // width: 500, // height: 500, // rooms: { // width: { min: 7, max: 20, onlyOdd: true }, // height: { min: 7, max: 20, onlyOdd: true } // } // }); // 1,000,000 tile test! - Warning, takes a few seconds to generate the dungeon :) // dungeon = new Dungeon({ // width: 1000, // height: 1000, // rooms: { // width: { min: 7, max: 20, onlyOdd: true }, // height: { min: 7, max: 20, onlyOdd: true } // } // }); // Creating a blank tilemap with dimensions matching the dungeon this.map = this.make.tilemap({ tileWidth: 16, tileHeight: 16, width: this.dungeon.width, height: this.dungeon.height }); // addTilesetImage: function (tilesetName, key, tileWidth, tileHeight, tileMargin, tileSpacing, gid) var tileset = this.map.addTilesetImage('tiles', 'tiles', 16, 16, 1, 2); this.layer = this.map.createBlankLayer('Layer 1', tileset); if (!debug) { this.layer.setScale(3); } // Fill with black tiles this.layer.fill(20); // Use the array of rooms generated to place tiles in the map this.dungeon.rooms.forEach(function (room) { var x = room.x; var y = room.y; var w = room.width; var h = room.height; var cx = Math.floor(x + w / 2); var cy = Math.floor(y + h / 2); var left = x; var right = x + (w - 1); var top = y; var bottom = y + (h - 1); // Fill the floor with mostly clean tiles, but occasionally place a dirty tile // See "Weighted Randomize" example for more information on how to use weightedRandomize. this.map.weightedRandomize(TILES.FLOOR, x, y, w, h); // Place the room corners tiles this.map.putTileAt(TILES.TOP_LEFT_WALL, left, top); this.map.putTileAt(TILES.TOP_RIGHT_WALL, right, top); this.map.putTileAt(TILES.BOTTOM_RIGHT_WALL, right, bottom); this.map.putTileAt(TILES.BOTTOM_LEFT_WALL, left, bottom); // Fill the walls with mostly clean tiles, but occasionally place a dirty tile this.map.weightedRandomize(TILES.TOP_WALL, left + 1, top, w - 2, 1); this.map.weightedRandomize(TILES.BOTTOM_WALL, left + 1, bottom, w - 2, 1); this.map.weightedRandomize(TILES.LEFT_WALL, left, top + 1, 1, h - 2); this.map.weightedRandomize(TILES.RIGHT_WALL, right, top + 1, 1, h - 2); // Dungeons have rooms that are connected with doors. Each door has an x & y relative to the rooms location var doors = room.getDoorLocations(); for (var i = 0; i < doors.length; i++) { this.map.putTileAt(6, x + doors[i].x, y + doors[i].y); } // Place some random stuff in rooms occasionally var rand = Math.random(); if (rand <= 0.25) { this.layer.putTileAt(166, cx, cy); // Chest } else if (rand <= 0.3) { this.layer.putTileAt(81, cx, cy); // Stairs } else if (rand <= 0.4) { this.layer.putTileAt(167, cx, cy); // Trap door } else if (rand <= 0.6) { if (room.height >= 9) { // We have room for 4 towers this.layer.putTilesAt([ [ 186 ], [ 205 ] ], cx - 1, cy + 1); this.layer.putTilesAt([ [ 186 ], [ 205 ] ], cx + 1, cy + 1); this.layer.putTilesAt([ [ 186 ], [ 205 ] ], cx - 1, cy - 2); this.layer.putTilesAt([ [ 186 ], [ 205 ] ], cx + 1, cy - 2); } else { this.layer.putTilesAt([ [ 186 ], [ 205 ] ], cx - 1, cy - 1); this.layer.putTilesAt([ [ 186 ], [ 205 ] ], cx + 1, cy - 1); } } }, this); // Not exactly correct for the tileset since there are more possible floor tiles, but this will // do for the example. this.layer.setCollisionByExclusion([ 6, 7, 8, 26 ]); // Hide all the rooms if (!debug) { this.layer.forEachTile(function (tile) { tile.alpha = 0; }); } // Place the player in the first room var playerRoom = this.dungeon.rooms[0]; this.player = this.add.graphics({ fillStyle: { color: 0xedca40, alpha: 1 } }).fillRect(0, 0, this.map.tileWidth * this.layer.scaleX, this.map.tileHeight * this.layer.scaleY); this.player.x = this.map.tileToWorldX(playerRoom.x + 1); this.player.y = this.map.tileToWorldY(playerRoom.y + 1); if (!debug) { this.setRoomAlpha(playerRoom, 1); // Make the starting room visible } // Scroll to the player this.cam = this.cameras.main; this.cam.setBounds(0, 0, this.layer.width * this.layer.scaleX, this.layer.height * this.layer.scaleY); this.cam.scrollX = this.player.x - this.cam.width * 0.5; this.cam.scrollY = this.player.y - this.cam.height * 0.5; this.cursors = this.input.keyboard.createCursorKeys(); var help = this.add.text(16, 16, 'Arrows keys to move', { fontSize: '18px', padding: { x: 10, y: 5 }, backgroundColor: '#ffffff', fill: '#000000' }); help.setScrollFactor(0); var gui = new dat.GUI(); gui.addFolder('Camera'); gui.add(this.cam, 'scrollX').listen(); gui.add(this.cam, 'scrollY').listen(); gui.add(this.cam, 'zoom', 0.1, 4).step(0.1); gui.add(this.cam, 'rotation').step(0.01); gui.add(this.layer, 'skipCull').listen(); gui.add(this.layer, 'cullPaddingX').step(1); gui.add(this.layer, 'cullPaddingY').step(1); gui.add(this.layer, 'tilesDrawn').listen(); gui.add(this.layer, 'tilesTotal').listen(); } update (time, delta) { this.updatePlayerMovement(time); var playerTileX = this.map.worldToTileX(this.player.x); var playerTileY = this.map.worldToTileY(this.player.y); // Another helper method from the dungeon - dungeon XY (in tiles) -> room var room = this.dungeon.getRoomAt(playerTileX, playerTileY); // If the player has entered a new room, make it visible and dim the last room if (room && this.activeRoom && this.activeRoom !== room) { if (!debug) { this.setRoomAlpha(room, 1); this.setRoomAlpha(this.activeRoom, 0.5); } } this.activeRoom = room; // Smooth follow the player var smoothFactor = 0.9; this.cam.scrollX = smoothFactor * this.cam.scrollX + (1 - smoothFactor) * (this.player.x - this.cam.width * 0.5); this.cam.scrollY = smoothFactor * this.cam.scrollY + (1 - smoothFactor) * (this.player.y - this.cam.height * 0.5); } // Helpers functions setRoomAlpha(room, alpha) { this.map.forEachTile(function (tile) { tile.alpha = alpha; }, this, room.x, room.y, room.width, room.height) } isTileOpenAt (worldX, worldY) { // nonNull = true, don't return null for empty tiles. This means null will be returned only for // tiles outside of the bounds of the map. var tile = this.map.getTileAtWorldXY(worldX, worldY, true); if (tile && !tile.collides) { return true; } else { return false; } } updatePlayerMovement (time) { var tw = this.map.tileWidth * this.layer.scaleX; var th = this.map.tileHeight * this.layer.scaleY; var repeatMoveDelay = 100; if (time > this.lastMoveTime + repeatMoveDelay) { if (this.cursors.down.isDown) { if (this.isTileOpenAt(this.player.x, this.player.y + th)) { this.player.y += th; this.lastMoveTime = time; } } else if (this.cursors.up.isDown) { if (this.isTileOpenAt(this.player.x, this.player.y - th)) { this.player.y -= th; this.lastMoveTime = time; } } if (this.cursors.left.isDown) { if (this.isTileOpenAt(this.player.x - tw, this.player.y)) { this.player.x -= tw; this.lastMoveTime = time; } } else if (this.cursors.right.isDown) { if (this.isTileOpenAt(this.player.x + tw, this.player.y)) { this.player.x += tw; this.lastMoveTime = time; } } } } } const config = { type: Phaser.AUTO, width: 800, height: 600, backgroundColor: '#2a2a55', parent: 'phaser-example', pixelArt: true, roundPixels: false, scene: Example }; const game = new Phaser.Game(config); // Minified & modified dungeon generator at mikewesthad/dungeon (fork of nickgravelyn/dungeon) !function(t,o){"object"==typeof exports&&"object"==typeof module?module.exports=o():"function"==typeof define&&define.amd?define([],o):"object"==typeof exports?exports.Dungeon=o():t.Dungeon=o()}("undefined"!=typeof self?self:this,function(){return function(t){function o(r){if(e[r])return e[r].exports;var i=e[r]={i:r,l:!1,exports:{}};return t[r].call(i.exports,i,i.exports,o),i.l=!0,i.exports}var e={};return o.m=t,o.c=e,o.d=function(t,e,r){o.o(t,e)||Object.defineProperty(t,e,{configurable:!1,enumerable:!0,get:r})},o.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return o.d(e,"a",e),e},o.o=function(t,o){return Object.prototype.hasOwnProperty.call(t,o)},o.p="",o(o.s=1)}([function(t,o,e){"use strict";Object.defineProperty(o,"__esModule",{value:!0});var r={EMPTY:0,WALL:1,FLOOR:2,DOOR:3};o.default=r},function(t,o,e){"use strict";t.exports=e(2).default},function(t,o,e){"use strict";function r(t){return t&&t.__esModule?t:{default:t}}function i(t,o){if(!(t instanceof o))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(o,"__esModule",{value:!0});var n=function(){function t(t,o){var e=[],r=!0,i=!1,n=void 0;try{for(var h,a=t[Symbol.iterator]();!(r=(h=a.next()).done)&&(e.push(h.value),!o||e.length!==o);r=!0);}catch(t){i=!0,n=t}finally{try{!r&&a.return&&a.return()}finally{if(i)throw n}}return e}return function(o,e){if(Array.isArray(o))return o;if(Symbol.iterator in Object(o))return t(o,e);throw new TypeError("Invalid attempt to destructure non-iterable instance")}}(),h=function(){function t(t,o){for(var e=0;e0&&void 0!==arguments[0]?arguments[0]:{};i(this,t);var e=o.rooms||{};e.width=Object.assign({},m.rooms.width,e.width),e.height=Object.assign({},m.rooms.height,e.height),e.maxArea=e.maxArea||m.rooms.maxArea,e.maxRooms=e.maxRooms||m.rooms.maxRooms,e.width.min<3&&(e.width.min=3),e.height.min<3&&(e.height.min=3),e.width.max 0;)this.generateRoom(),r-=1;for(var i=0;i =this.width||o>=this.height?null:this.roomGrid[o][t][0]}},{key:"getMappedTiles",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};return t=Object.assign({},{empty:0,wall:1,floor:2,door:3},t),this.tiles.map(function(o){return o.map(function(o){return o===l.default.EMPTY?t.empty:o===l.default.WALL?t.wall:o===l.default.FLOOR?t.floor:o===l.default.DOOR?t.door:void 0})})}},{key:"addRoom",value:function(t){if(!this.canFitRoom(t))return!1;this.rooms.push(t);for(var o=t.top;o<=t.bottom;o++)for(var e=t.left;e<=t.right;e++)this.roomGrid[o][e].push(t);return!0}},{key:"canFitRoom",value:function(t){if(t.x<0||t.x+t.width>this.width-1)return!1;if(t.y<0||t.y+t.height>this.height-1)return!1;for(var o=0;o r.maxArea);return new u.default(t,o)}},{key:"generateRoom",value:function(){for(var t=this.createRandomRoom(),o=150;o>0;){var e=this.findRoomAttachment(t);if(t.setPosition(e.x,e.y),this.addRoom(t)){var r=this.findNewDoorLocation(t,e.target),i=n(r,2),h=i[0],a=i[1];this.addDoor(h),this.addDoor(a);break}o-=1}}},{key:"getTiles",value:function(){for(var t=Array(this.height),o=0;o 0&&a 0&&s 2&&void 0!==arguments[2]?arguments[2]:{},r=e.onlyOdd,h=void 0!==r&&r,a=e.onlyEven,s=void 0!==a&&a;return h?n(t,o):s?i(t,o):Math.floor(Math.random()*(o-t+1)+t)}function i(t,o){t%2!=0&&t t&&o--;var e=(o-t)/2;return 2*Math.floor(Math.random()*(e+1))+t}function n(t,o){t%2==0&&t++,o%2==0&&o--;var e=(o-t)/2;return 2*Math.floor(Math.random()*(e+1))+t}function h(t){return t[r(0,t.length-1)]}Object.defineProperty(o,"__esModule",{value:!0}),o.randomInteger=r,o.randomEvenInteger=i,o.randomOddInteger=n,o.randomPick=h},function(t,o,e){"use strict";function r(t,o){if(!(t instanceof o))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(o,"__esModule",{value:!0});var i=function(){function t(t,o){for(var e=0;e t.right)&&(!(this.bottom t.bottom)))}},{key:"isConnectedTo",value:function(t){for(var o=this.getDoorLocations(),e=0;e t.width-1||r.y<0||r.y>t.height-1)&&t.tiles[r.y][r.x]==h.default.DOOR)return!0}return!1}}]),t}();o.default=a},function(t,o,e){"use strict";function r(t){var o=t.roomGrid.map(function(t){return t.map(function(t){return(""+t.length).padStart(2)})});console.log(o.map(function(t){return t.join(" ")}).join("\n"))}function i(t){var o,e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};e=Object.assign({},{empty:" ",emptyColor:"rgb(0, 0, 0)",wall:"#",wallColor:"rgb(255, 0, 0)",floor:"_",floorColor:"rgb(210, 210, 210)",door:".",doorColor:"rgb(0, 0, 255)",fontSize:"15px"},e);for(var r="",i=[],n=0;n