Skip to content

Commit

Permalink
forgot to push
Browse files Browse the repository at this point in the history
  • Loading branch information
mattieFM committed Oct 1, 2024
1 parent 69e2bf7 commit 284769e
Show file tree
Hide file tree
Showing 3 changed files with 247 additions and 25 deletions.
10 changes: 6 additions & 4 deletions www/mods/_rougeLike/demo.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,23 @@
<script src="../commonLibs/_common/util.js"></script>
<script src="mapController.js"></script>
<script>
let width = 100;
let height = 100;
let targetWidth = 10;
let width = 50;
let height = 50;
let targetWidth = 25;
function resetMap(){
const canvas = document.getElementById("viewport");
const context = canvas.getContext('2d');
context.clearRect(0, 0, canvas.width, canvas.height);
}
function drawMap(){
const map=new Region(0,0,width,height);
map.splitXDeep(5);
map.splitTillWidth(targetWidth,targetWidth);
map.drawAllChildrenOnCanvas();
map.drawAllDoors();
console.log(map);
}


</script>
</body>
</html>
Expand Down
242 changes: 230 additions & 12 deletions www/mods/_rougeLike/mapController.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,19 @@

MATTIE.util = MATTIE.util || {};

//the chance on each wall tile that the rest of the wall will not generate
const chanceForWallToCollapse = .05;
/** the min and max amount of wall that can collapse */
const [minCollapse,maxCollapse] = [2, 5];
const wallTile=1579;
const floorTiles = [1587]
const collapseTiles = [1661,1662,1663]
const floorTile=()=>floorTiles[Math.floor(Math.random()*floorTiles.length)];
const collapseTile=()=>collapseTiles[Math.floor(Math.random()*collapseTiles.length)];
const logging = false;
const defaultCanvasId = 'viewport';
/** the max depth to go to for width/height based splitting */
const maxDepthForWidthSplit = 10

/** @todo remove this when done testing */
function getRandomColor() {
Expand Down Expand Up @@ -55,6 +63,7 @@ class Tile {
}
}


/**
* @description a class representing a region of space on the map.
*/
Expand All @@ -67,6 +76,17 @@ class Region {
* @param {number} botY y cord for top right corner
*/
constructor(topX, topY, botX, botY, parent = null) {
/**
* @description an dict of left,right,up and down arrays of all regions this region directly connects to
* @type {{Region[]}}
*/
this.connectsTo = {
left:[],
right:[],
up:[],
down:[],
};

/**
* the upper left corner of the region
* @type {RougeLikePoint}
Expand All @@ -79,6 +99,12 @@ class Region {
* */

Check failure on line 99 in www/mods/_rougeLike/mapController.js

View workflow job for this annotation

GitHub Actions / build

Expected an assignment or function call and instead saw an expression
this.bottomRightCorner;

/**
* @description an array containing all other points that are not in the main rectangle
* @type {RougeLikePoint[]}
*/
this.otherPoints=[];

/** @description a variable that marks if this is the highest layer of the region IE: a region with no parent */
this.isRoot = false;

Expand Down Expand Up @@ -111,6 +137,36 @@ class Region {
this.checkRoot();
}

/**
*
* @param {Region[]} arr
* @param {*} canvasId
*/
static DrawArrayOntoCanvas(arr, canvasId = defaultCanvasId){
arr.forEach(region=>{
region.drawAllChildrenOnCanvas()
})
arr.forEach(region=>{
region.drawAllDoors()
})
}

/**
* @description return an array of all leafs in this region's children
* @returns {Region[]}
* */
getAllLeafs(){
if (!this.checkLeaf()) {
let arr = []
this.children.forEach((child) => {
arr = [...child.getAllLeafs(), ...arr]
});
return arr;
} else {
return [this]
}
}

/** @description draw all children onto the canvas */
drawAllChildrenOnCanvas(canvasId = defaultCanvasId) {
this.drawOnCanvas(canvasId);
Expand Down Expand Up @@ -156,9 +212,6 @@ class Region {
* @param {number} forceHorizontal above .5 to force a horizontal split, below to force a vertical
*/
split(minPercentageLeft = 20, percentagePadding = 10, forceHorizontal = undefined) {
// the total percentage of space that is not included in padding
const workablePercentage = 100 - (percentagePadding * 2);

const width = this.getWidth();
const height = this.getHeight();

Expand Down Expand Up @@ -215,6 +268,10 @@ class Region {
const bottomBoxLowerLeftCorner = this.bottomRightCorner;
const bottomRegion = new Region(bottomBoxUpperLeftCorner.x, bottomBoxUpperLeftCorner.y, bottomBoxLowerLeftCorner.x, bottomBoxLowerLeftCorner.y, this);

//add to eachother's connection array
bottomRegion.connectsTo.up.push(topRegion);
topRegion.connectsTo.down.push(bottomRegion);

const door = new RougeLikePoint(MATTIE.util.randBetween(minX + 2, maxX - 2), splitYLevel);
topRegion.doors.push(door);
bottomRegion.doors.push(door);
Expand Down Expand Up @@ -250,6 +307,10 @@ class Region {
const rightBoxLowerLeftCorner = this.bottomRightCorner;
const rightRegion = new Region(rightBoxUpperLeftCorner.x, rightBoxUpperLeftCorner.y, rightBoxLowerLeftCorner.x, rightBoxLowerLeftCorner.y, this);

//add to eachother's connection array
rightRegion.connectsTo.left.push(leftRegion);
leftRegion.connectsTo.right.push(rightRegion);

const door = new RougeLikePoint(splitXLevel, MATTIE.util.randBetween(minY + 2, maxY - 2));
leftRegion.doors.push(door);
rightRegion.doors.push(door);
Expand Down Expand Up @@ -280,15 +341,25 @@ class Region {
* @param {*} height the target height
* @returns null
*/
splitTillWidth(width, height) {
splitTillWidth(width, height, currentDepth=0) {
let force;
if (MATTIE.util.checkNumberInRange(this.getWidth(), 0, width)) return; force = 0;
if (MATTIE.util.checkNumberInRange(this.getHeight(), 0, height)) return; force = 1;
this.split(force);
const inWidth = MATTIE.util.checkNumberInRange(this.getWidth(), 0, width);
const inHeight = MATTIE.util.checkNumberInRange(this.getHeight(), 0, height);
if(logging)console.log(`width:${this.getWidth()}`)
if(logging)console.log(`Height:${this.getHeight()}`)
//if close to width goal force split
if (!inWidth && inHeight && (MATTIE.util.checkNumberInRange(this.getWidth(), 0, width*1.2)||currentDepth>3)) force = 0;
//if close to height goal force split
if (inWidth && !inHeight && (MATTIE.util.checkNumberInRange(this.getHeight(), 0, height*1.2)||currentDepth>2)) force = 1;
if(inWidth && inHeight) return;
if(currentDepth >= maxDepthForWidthSplit) return;


this.split(10,20,force);
if (!this.checkLeaf()) {
this.children.forEach((child) => {
// decrement by one and recurse
child.splitTillWidth(width, height);
child.splitTillWidth(width, height, currentDepth+1);
});
}
}
Expand Down Expand Up @@ -318,6 +389,24 @@ class Region {
getHeight() {
return Math.abs(this.upperLeftCorner.y - this.bottomRightCorner.y);
}

/**
* @description check if a point is within the bounds of the region
* @param {*} x
* @param {*} y
*/
isWithinBounds(x,y){
let inBounds = false;
//check if point in set of other points
if(this.otherPoints.some(point=>point.x==x&&point.y==y)) return true;

//check if x and y are in bounds
if(this.bottomRightCorner.x < x && this.upperLeftCorner.y < y) return false;
if(this.bottomRightCorner.y > y && this.upperLeftCorner.x > x) return false;

//thus in bounds
return true;
}
}

/**
Expand All @@ -339,10 +428,10 @@ class RougeLikeMap {
*/
constructor(width = 100, height = 100, x = 0, y = 0) {
/** @description the width of the map to be generated */
this.width = 50;
this.width = 25;

/** @description the width of the map to be generated */
this.height = 50;
this.height = 25;

/** @description x coordinate of the upper left corner */
this.upperLeftX = 0;
Expand Down Expand Up @@ -377,12 +466,13 @@ class RougeLikeMap {
*/
this.rooms=[];

let targetWidth = 13;
this.width = width;
this.height = height;
this.upperLeftX = x;
this.upperLeftY = y;
this.rootRegion = new Region(x,y,width,height);
this.rootRegion.splitXDeep(3);
this.rootRegion.splitTillWidth(targetWidth,targetWidth);
this.updateRegions();
this.updateTiles();
}
Expand All @@ -395,7 +485,9 @@ class RougeLikeMap {
};

this.regions.push(region);
if(region.checkLeaf()){this.rooms.push(region)};
region.children.forEach(child => {
if(child.checkLeaf()){this.rooms.push(child)};
this.regions.push(child);
this.updateRegions(child);
})
Expand Down Expand Up @@ -431,7 +523,8 @@ class RougeLikeMap {
/** @description rebuild mapTiles */
updateTiles() {
this.makeBlankTileSet();
this.regions.forEach(region => {
let rooms = [...this.rooms,this.rootRegion]
rooms.forEach(region => {
//draw top line
for (let x = region.upperLeftCorner.x; x < region.bottomRightCorner.x; x++) {
let y = region.upperLeftCorner.y;
Expand Down Expand Up @@ -476,3 +569,128 @@ class RougeLikeMap {
}

}

/**
* @description the main class for generating and controlling maps
*/
class DungeonMap {
/**
* @description
* @param {number} topX top left bound
* @param {number} topY top bound
* @param {number} bottomX bottom right bound
* @param {number} bottomY bottom bound
*/
constructor(topX, topY, bottomX, bottomY){
/**
* @description all the rooms of the dungeon
* @type {Region[]}
*/
this.rooms = [];

/**
* @description halls
* @type {Region[]}
*/
this.halls = [];

/** @description the min size of a room (width or height)*/
this.roomSizeMin=10;

/** @description the max size of a room (width or height)*/
this.roomSizeMax=20;

/** @description the minimum rooms in the dungeon */
this.minRoomsInDungeon=5;

/** @description the maximum rooms in the dungeon */
this.maxRoomsInDungeon=15;

/** @description the min padding between rooms */
this.minPaddingBetweenRooms = 3;
/** @description the max padding between rooms */
this.maxPaddingBetweenRooms = 8;

/** @description the region denoting the bounds of the map */
this.mapBounds = new Region(topX,topY,bottomX,bottomY);

//the min and max percentages of a region to use as a room
this.minPercentageUsed = .4;
this.maxPercentageUsed = 1;
}

/** @description generate random rooms */
_generateRandomRooms(){
const numberOfRoomsToSpawn = MATTIE.util.randBetween(this.minRoomsInDungeon,this.maxRoomsInDungeon);
for (let index = 0; index < numberOfRoomsToSpawn; index++) {
let room;

let i =0;
do {
let xMin = this.mapBounds.upperLeftCorner.x
let yMin = this.mapBounds.upperLeftCorner.y
let xMax = this.mapBounds.bottomRightCorner.x
let yMax = this.mapBounds.bottomRightCorner.y

let point1 = new RougeLikePoint(
MATTIE.util.lerp(xMin,xMax,MATTIE.util.randBetween(0,1)),
MATTIE.util.lerp(yMin,yMax,MATTIE.util.randBetween(0,1))
)

let point2 = new RougeLikePoint(
MATTIE.util.lerp(xMin,xMax,MATTIE.util.randBetween(0,1)),
MATTIE.util.lerp(yMin,yMax,MATTIE.util.randBetween(0,1))
)
room = new Region(point1.x,point1.y,point2.x,point2.y);
i++;
} while (!this.rooms.some(other=>other.isWithinBounds(room)) && i < 4)
this.rooms.push(room);
}
}

/** @description generate random rooms */
generateRandomRooms(){
const numberOfRoomsToSpawn = MATTIE.util.randBetween(this.minRoomsInDungeon,this.maxRoomsInDungeon);

//split our space if its not split up already
if(this.mapBounds.children.length==0)
this.mapBounds.splitTillWidth(11,11)

//extract all leaves and then randomly choose some
let arrOfRoomBounds = this.mapBounds.getAllLeafs();

let arrayOfChosenBounds = [];

//loop for each room to spawn
for (let index = 0; index < numberOfRoomsToSpawn; index++) {
let room;

//choose a region that has not been used yet
let chosenRegion = arrOfRoomBounds[MATTIE.util.randBetween(0,arrOfRoomBounds.length)];
while(arrayOfChosenBounds.indexOf(chosenRegion) != -1){
chosenRegion = arrOfRoomBounds[MATTIE.util.randBetween(0,arrOfRoomBounds.length)];
}
arrayOfChosenBounds.push(chosenRegion);

let xMin = chosenRegion.upperLeftCorner.x
let yMin = chosenRegion.upperLeftCorner.y
let xMax = chosenRegion.bottomRightCorner.x
let yMax = chosenRegion.bottomRightCorner.y

const alpha = MATTIE.util.randBetween(0,this.minPercentageUsed);
let topleftPoint = new RougeLikePoint(
MATTIE.util.lerp(xMin,xMax,alpha),
MATTIE.util.lerp(yMin,yMax,alpha)
)

Check failure on line 684 in www/mods/_rougeLike/mapController.js

View workflow job for this annotation

GitHub Actions / build

'room' is never reassigned. Use 'const' instead

const alpha2 = MATTIE.util.randBetween(0,this.minPercentageUsed-alpha);
let bottomRightPoint = new RougeLikePoint(
MATTIE.util.lerp(xMax,xMin,alpha2),
MATTIE.util.lerp(yMax,yMin,alpha2)
)

room = new Region(topleftPoint.x,topleftPoint.y, bottomRightPoint.x,bottomRightPoint.y);
this.rooms.push(room)
}
}
}
Loading

0 comments on commit 284769e

Please sign in to comment.