feat: finished RandomMapGenerator, not fully tested

This commit is contained in:
Renge 2022-04-08 19:49:06 -04:00
parent 63f5a2a3a0
commit 86fabc2336
3 changed files with 119 additions and 33 deletions

View File

@ -54,12 +54,6 @@
33, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 35,
41, 42, 42, 42, 34, 34, 34, 34, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 43],
"entrances": [
{
"x": 0,
"y": 12,
"width": 3,
"alt_tile": [52, 54]
},
{
"x": 29,
"y": 12,
@ -117,12 +111,6 @@
"y": 11,
"width": 3,
"alt_tile": [52, 54]
},
{
"x": 29,
"y": 9,
"width": 3,
"alt_tile": [52, 54]
}
]
},

View File

@ -1,3 +1,4 @@
import { TiledTilemapData } from "../../Wolfie2D/DataTypes/Tilesets/TiledData";
import Vec2 from "../../Wolfie2D/DataTypes/Vec2";
import Debug from "../../Wolfie2D/Debug/Debug";
import { GameEventType } from "../../Wolfie2D/Events/GameEventType";
@ -7,14 +8,14 @@ import GameLevel from "./GameLevel";
export default class Tutorial extends GameLevel{
private map: TiledTilemapData;
loadScene(): void {
// Load resources
// this.load.tilemap("forest1", "shattered_sword_assets/tilemaps/Tutorial.json");
// let map = localStorage.getItem("map");
let rmg = new RandomMapGenerator("shattered_sword_assets/jsons/forest_template.json", 114514);
let map = rmg.getMap();
this.load.tilemapFromObject("forest1", map);
this.map = rmg.getMap();
this.load.tilemapFromObject("forest1", this.map);
this.load.spritesheet("player", "shattered_sword_assets/spritesheets/Hiro.json")
//load music here
@ -23,7 +24,7 @@ export default class Tutorial extends GameLevel{
startScene(): void {
// Add the level 1 tilemap
this.add.tilemap("forest1", new Vec2(2, 2));
this.viewport.setBounds(0, 0, 64*32, 20*32);
this.viewport.setBounds(0, 0, this.map.width*32, this.map.height*32);
this.playerSpawn = new Vec2(5*32, 9*32);

View File

@ -21,6 +21,8 @@ export default class RandomMapGenerator {
private gen: any;
private hasExit: boolean;
private minRoom: number;
private roomPlaced: number;
private exitFacing: Facing;
constructor(JSONFilePath: string, seed: any) {
let xhr = new XMLHttpRequest();
@ -42,6 +44,8 @@ export default class RandomMapGenerator {
this.gen = new gen(seed);
this.hasExit = false;
this.minRoom = this.template.minroom;
this.roomPlaced = 0;
this.exitFacing = this.getEntranceFacing(this.template.exit.entrances[0], this.template.exit.width);
this.template.rooms.forEach((room) => {
@ -88,18 +92,106 @@ export default class RandomMapGenerator {
let room = this.copyRoom(this.template.entrance, 0, 0);
this.rooms.push(room);
let facing = this.getEntranceFacing(this.template.entrance.entrances[0], this.template.entrance.width);
let position = new Vec2(this.template.entrance.entrances[0].x, this.template.entrance.entrances[0].y);
this.putNextRoom(position, this.getOppositeFacing(facing));
if (!this.hasExit)
throw new Error("Fail to generate a map with exit!");
// if (!this.hasExit)
// throw new Error("Fail to generate a map with exit!");
this.fillData();
return this.map;
}
private putNextRoom(): boolean {
private putNextRoom(position: Vec2, facing: Facing): boolean {
switch (facing) {
case Facing.LEFT:
position.x += 1;
break;
case Facing.RIGHT:
position.x -= 1;
break;
case Facing.UP:
position.y += 1;
break;
case Facing.DOWN:
position.y -= 1;
break;
default:
break;
}
if (this.roomPlaced >= this.minRoom && facing == this.exitFacing) {
this.putExitRoom(position);
return true;
}
let nextRoom = this.getRandomRoom(facing);
let nextPosition: Vec2 = undefined;
let thisEntrance: Entrance = undefined;
for (let index = 0; index < nextRoom.entrances.length; index++) {
const entrance = nextRoom.entrances[index];
if (this.getEntranceFacing(entrance, nextRoom.weight) == facing) {
let tmpPosition = new Vec2(position.x - entrance.x, position.y - entrance.y);
if (this.isValidRoom(tmpPosition, new Vec2(tmpPosition.x + nextRoom.width - 1, tmpPosition.y + nextRoom.height - 1))) {
thisEntrance = entrance;
nextPosition = tmpPosition;
}
}
}
if (!thisEntrance) {
return false;
}
let room = this.copyRoom(nextRoom, nextPosition.x, nextPosition.y);
this.rooms.push(room);
this.roomPlaced += 1;
if (this.hasExit && this.gen.range() <= 0.1) {
return false;
}
for (let index = 0; index < nextRoom.entrances.length; index++) {
const entrance = nextRoom.entrances[index];
if (entrance != thisEntrance) {
let facing = this.getEntranceFacing(entrance, nextRoom.width);
let position = new Vec2(nextPosition.x + entrance.x, nextPosition.y + entrance.y);
if (this.putNextRoom(position, this.getOppositeFacing(facing))) {
this.removeEntrance(room, entrance, facing);
}
}
}
return true;
}
private putExitRoom(position: Vec2): void {
position = new Vec2(position.x - this.template.exit.entrances[0].x, position.y - this.template.exit.entrances[0].y);
if (!this.isValidRoom(position, new Vec2(position.x + this.template.exit.width - 1, position.y + this.template.exit.height - 1))) {
throw new Error("Cannot put exit room!!! Position is invalid!!! Please check order of entrances in map template.");
}
let room = this.copyRoom(this.template.exit, position.x, position.y);
this.rooms.push(room);
this.hasExit = true;
}
private removeEntrance(room: Room, entrance: Entrance, facing: Facing): void {
let width = room.bottomRight.x - room.topLeft.x + 1;
if (facing == Facing.LEFT || facing == Facing.RIGHT) {
for (let index = 0; index < entrance.width; index++)
room.topLayer[(entrance.y + index) * width + entrance.x] = 0;
if (entrance.y > 0)
room.topLayer[(entrance.y - 1) * width + entrance.x] = entrance.alt_tile[0];
if (entrance.y + entrance.width <= (room.bottomRight.y - room.topLeft.y))
room.topLayer[(entrance.y + entrance.width) * width + entrance.x] = entrance.alt_tile[1];
}
else {
for (let index = 0; index < entrance.width; index++)
room.topLayer[(entrance.y) * width + entrance.x + index] = 0;
if (entrance.x > 0)
room.topLayer[(entrance.y) * width + entrance.x - 1] = entrance.alt_tile[0];
if (entrance.x + entrance.width <= (room.bottomRight.x - room.topLeft.x))
room.topLayer[(entrance.y) * width + entrance.x + entrance.width] = entrance.alt_tile[1];
}
}
private fillData() {
let width = this.maxX - this.minX + 1;
let height = this.maxY - this.minY + 1;
@ -144,7 +236,8 @@ export default class RandomMapGenerator {
this.map.layers[0].data = new Array(width * height).fill(this.template.background);
this.map.layers[1].data = new Array(width * height);
this.rooms.forEach((room) => {
for (let index = 0; index < this.rooms.length; index++) {
const room = this.rooms[index];
let roomWidth = room.bottomRight.x - room.topLeft.x + 1;
let roomHeight = room.bottomRight.y - room.topLeft.y + 1;
for (let i = 0; i < roomHeight; i++)
@ -152,19 +245,21 @@ export default class RandomMapGenerator {
this.map.layers[0].data[(room.topLeft.y + i) * width + room.topLeft.x + j] = room.bottomLayer[i * roomWidth + j];
this.map.layers[1].data[(room.topLeft.y + i) * width + room.topLeft.x + j] = room.topLayer[i * roomWidth + j];
}
})
}
}
private isValidRoom(topLeft: Vec2, bottomRight: Vec2): boolean {
this.rooms.forEach((room) => {
if (room.topLeft.x < bottomRight.x &&
room.bottomRight.x > topLeft.x &&
room.topLeft.y < bottomRight.y &&
room.bottomRight.y > topLeft.y)
return true;
})
for (let index = 0; index < this.rooms.length; index++) {
const room = this.rooms[index];
if (room.topLeft.x <= bottomRight.x &&
room.bottomRight.x >= topLeft.x &&
room.topLeft.y <= bottomRight.y &&
room.bottomRight.y >= topLeft.y)
return false;
}
console.warn("Found an invalid room! TopLeft:", topLeft.toString, "BottomRight:", bottomRight.toString);
return true;
}
private getEntranceFacing(entrance: Entrance, width: number): Facing {
if (entrance.x === 0)
@ -189,18 +284,20 @@ export default class RandomMapGenerator {
}
}
private getRandomRoom(value: number, facing: Facing): RoomTemplate {
private getRandomRoom(facing: Facing): RoomTemplate {
let array = this.getRoomArray(facing), weight = this.getRoomWeight(facing);
let value = this.gen(weight);
if (value >= weight)
throw new Error("Random number " + value + " is larger than total weight " + weight);
array.forEach((room) => {
for (let index = 0; index < array.length; index++) {
let room = array[index];
if (value < room.weight)
return room;
value -= room.weight;
})
throw new Error("Cannot find Room! \nRooms: " + JSON.stringify(array) + "\nValue: " + value);
}
throw new Error("Cannot find Room! \nValue: " + value + "\nRooms: " + JSON.stringify(array));
}
private getRoomArray(facing: Facing): Array<RoomTemplate> {