Skip to content

Commit

Permalink
finished project
Browse files Browse the repository at this point in the history
  • Loading branch information
Garen7 committed Nov 5, 2019
1 parent f604522 commit 658b220
Show file tree
Hide file tree
Showing 4 changed files with 207 additions and 30 deletions.
21 changes: 21 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "chrome",
"request": "launch",
"name": "Localhost",
"url": "http://localhost:8080",
"webRoot": "${workspaceFolder}"
},
{
"type": "chrome",
"request": "launch",
"name": "Local File",
"file": "${workspaceFolder}/index.html"
}
]
}
10 changes: 10 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<!doctype html>
<html>
<head>
<script src="p5.min.js"></script>
<script src="sketch.js"></script>
</head>

<body style="margin:0;padding:0">
</body>
</html>
3 changes: 3 additions & 0 deletions p5.min.js

Large diffs are not rendered by default.

203 changes: 173 additions & 30 deletions sketch.js
Original file line number Diff line number Diff line change
@@ -1,55 +1,150 @@
const NORTH = 1
const SOUTH = 2
const EAST = 4
const WEST = 8
//#region cell bit data
const NORTH = 0x1
const SOUTH = 0x2
const EAST = 0x4
const WEST = 0x8
const ALLDIRECTIONS = [NORTH, SOUTH, EAST, WEST]
const OPPOSITE = {} // {NORTH:SOUTH} would actually be {NORTH:2} because javascipt :(
OPPOSITE[NORTH] = SOUTH
OPPOSITE[SOUTH] = NORTH
OPPOSITE[EAST] = WEST
OPPOSITE[WEST] = EAST

const RED = 0x10
const GREEN = 0x20
const BLUE = 0x40
const ALLCOLORS = [RED, GREEN, BLUE]

const GOAL = 0x80
//#endregion

//#region maze settings
const CELLSIZE = 30
let cellcount= 0
const WALLTHICKNESS = 8
const COLORSATURATION = 100
const SPEEDMOD = 10
//#endregion

//#region globals
let myMaze
let racers
//#endregion

//#region events
function setup(){
createCanvas(innerWidth, innerHeight)
background(256)
strokeWeight(6)

let myMaze = new Maze(10, 10)
let mazeWidth = int(width/CELLSIZE) - 1 //dont know why I need the - 1 but I do
let mazeHeight = int(height/CELLSIZE)
//calculate speed, we scale off the average length of a side rather than the area
frameRate(SPEEDMOD * (mazeWidth+mazeHeight)/2 / CELLSIZE)
myMaze = new Maze(mazeWidth, mazeHeight)
racers = []
for(const color of ALLCOLORS){
racers.push(new Racer(myMaze, int(random(mazeWidth)), int(random(mazeHeight)), color))
}

myMaze.updateImage()
}

function draw(){
for(let r of racers){
r.update()
}
myMaze.updateImage()
}
//#endregion

//#region helpers
//fisher-yates
function shuffle(arr){
let randomIndex, tmp

for(let index = arr.length; index > 0; index--){
randomIndex = random(index)

tmp = arr[randomIndex]
arr[randomIndex] = arr[index]
arr[index] = tmp
}

return arr
}

//dfs cause im lazy
function pathfind(x, y, maze, _backwards){ //if you see a _ before a variable name it means treat it as private
//base case
if(maze.cells[x][y] & GOAL){
return (_backwards ? [OPPOSITE[_backwards]] : null) //if no backwards then thers no path since we started on the goal
}

let randomDirections = shuffle([...ALLDIRECTIONS])
let result

//for all neighbors
for(const dir of randomDirections){
if(dir == _backwards || !(maze.cells[x][y] & dir)){
continue
}
switch(dir){
case NORTH:
result = pathfind(x, y-1, maze, OPPOSITE[dir])
break;
case SOUTH:
result = pathfind(x, y+1, maze, OPPOSITE[dir])
break;
case EAST:
result = pathfind(x+1, y, maze, OPPOSITE[dir])
break;
case WEST:
result = pathfind(x-1, y, maze, OPPOSITE[dir])
break;
}
if(result){
if(_backwards){
result.push(OPPOSITE[_backwards])
}
return result
}
}

//no path
return null
}
//#endregion

class Maze{
constructor(xSize, ySize){
this.cells = Array(xSize).fill().map(()=>Array(ySize).fill(0))

this.expand(int(random(xSize)), int(random(ySize)))

this.cells[int(random(xSize))][int(random(ySize))] |= GOAL
}

//dfs
expand(x, y){
let randomDirections = shuffle([...ALLDIRECTIONS])
let newX, newY, opposite
let newX, newY

//for all neighbors
for(const dir of randomDirections){
switch(dir){
case NORTH:
newX = x
newY = y + 1
opposite = SOUTH
newY = y - 1
break;
case SOUTH:
newX = x
newY = y - 1
opposite = NORTH
newY = y + 1
break;
case EAST:
newX = x + 1
newY = y
opposite = WEST
break;
case WEST:
newX = x - 1
newY = y
opposite = EAST
break;
}

Expand All @@ -61,41 +156,89 @@ class Maze{
//is the neighbor empty?
if(!this.cells[newX][newY]){
this.cells[x][y] |= dir
this.cells[newX][newY] |= opposite
this.cells[newX][newY] |= OPPOSITE[dir]
this.expand(newX, newY)
}
}
}

updateImage(){
//colors and goal
noStroke()
let cellRed, cellGreen, cellBlue
for(let x of Array(this.cells.length).keys()){
for(let y of Array(this.cells[x].length).keys()){
//colors
cellRed = 256 - COLORSATURATION * Math.sign(this.cells[x][y] & RED)
cellGreen = 256 - COLORSATURATION * Math.sign(this.cells[x][y] & GREEN)
cellBlue = 256 - COLORSATURATION * Math.sign(this.cells[x][y] & BLUE)
fill(cellRed, cellGreen, cellBlue)
square(CELLSIZE*x, CELLSIZE*y, CELLSIZE)

//goal
if(this.cells[x][y] & GOAL){
fill('black')
circle(CELLSIZE*(x+1/2), CELLSIZE*(y+1/2), CELLSIZE)
}
}
}

//now we can do the walls since we didnt want them to overlap
stroke(WALLTHICKNESS)
//north and west border
line(0, 0, CELLSIZE*this.cells.length, 0)
line(0, 0, 0, CELLSIZE*this.cells.length)
//run through each individual cell and check for a south and east wall
for(let x of Array(this.cells.length).keys()){
for(let y of Array(this.cells[x].length).keys()){
//debuggin
console.log(this.cells[x][y] + " at (" + x + ", " + y + ")")
if(this.cells[x][y] & SOUTH){
if(!(this.cells[x][y] & SOUTH)){
line(CELLSIZE*x, CELLSIZE*(y+1), CELLSIZE*(x+1), CELLSIZE*(y+1))
}
if(this.cells[x][y] & EAST){
if(!(this.cells[x][y] & EAST)){
line(CELLSIZE*(x+1), CELLSIZE*y, CELLSIZE*(x+1), CELLSIZE*(y+1))
}
}
}
}
}

//fisher-yates
function shuffle(arr){
let randomIndex, tmp
class Racer{
constructor(maze, x, y, color){
this.maze = maze //fun fact, this is only a reference to the maze not an actual copy
this.x = x
this.y = y
this.color = color
this.colorCell()

for(let index = arr.length; index > 0; index--){
randomIndex = random(index)
this.path = pathfind(x, y, maze)
}

tmp = arr[randomIndex]
arr[randomIndex] = arr[index]
arr[index] = tmp
update(){
if(this.path.length){
this.move(this.path.pop())
}
}

return arr
}
move(dir){
switch(dir){
case NORTH:
this.y--
break;
case SOUTH:
this.y++
break;
case EAST:
this.x++
break;
case WEST:
this.x--
break;
}

this.colorCell()
}

colorCell(){
this.maze.cells[this.x][this.y] |= this.color
}
}

0 comments on commit 658b220

Please sign in to comment.