Last active
August 7, 2016 21:28
-
-
Save cjhin/afbed2cf6df0068676d2205b76df0e66 to your computer and use it in GitHub Desktop.
city
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<meta charset="utf-8"> | |
<body> | |
<canvas id="canvas" width="960" height="500"></canvas> | |
</body> | |
<script> | |
/* | |
Basically playing around with a couple of graphics things with the canvas: | |
- manually drawing cubes | |
- but mostly faking them :P, they're all missing backs and bottoms | |
- manually translating a 3d space to a 2d space, using classical perspective stuff | |
- auto generating cubes, creating a "city" with blocks and streets and things | |
*/ | |
var color_right = "#888"; | |
var color_left = "#888"; | |
var color_front = "#AAA"; | |
var color_top = "#CCC"; | |
var color_road = "#666"; | |
var canvas = document.getElementById('canvas'); | |
var ctx = canvas.getContext("2d"); | |
// *0.8 : so that the buildings don't fall off the bottom of the canvas | |
var canvasHeight = canvas.height * 0.9; | |
var canvasWidth = canvas.width; | |
// x and z are the physical coordinates of the terminusPoint | |
// adjusting y effectively adjusts the "height/angle" of the viewer | |
var terminusPoint = { | |
x: canvasWidth / 2.0, | |
z: 800, | |
y: 190 /* this is of the visual canvas, not the physical point in space */ | |
}; | |
// translate to 3d | |
// z = 0 is "close", z = 100 is "far" | |
// width is x size, depth is z size | |
// basically calculate the front and the back sides, then connect all the dotes | |
// assume that the x/z coordinates define the bottomLeftFront corner | |
var drawBuilding = function(x, z, width, depth, height) { | |
ctx.strokeStyle = "black"; | |
var zModFront = (terminusPoint.z - z)/terminusPoint.z; | |
var pixelHeightFront = zModFront * height; | |
var pixelWidthFront = zModFront * width; | |
var bottomLeftFront = { | |
x: terminusPoint.x + (zModFront * (x - terminusPoint.x)), | |
y: terminusPoint.y + (zModFront * (canvasHeight - terminusPoint.y)) | |
}; | |
var topLeftFront = { | |
x: bottomLeftFront.x, | |
y: bottomLeftFront.y - pixelHeightFront | |
}; | |
var topRightFront = { | |
x: topLeftFront.x + pixelWidthFront, | |
y: topLeftFront.y | |
}; | |
var bottomRightFront = { | |
x: topRightFront.x, | |
y: bottomLeftFront.y | |
}; | |
var zModBack = (terminusPoint.z - z - depth)/terminusPoint.z; | |
var pixelHeightBack = zModBack * height; | |
var pixelWidthBack = zModBack * width; | |
var bottomLeftBack = { | |
x: terminusPoint.x + (zModBack * (x - terminusPoint.x)), | |
y: terminusPoint.y + (zModBack * (canvasHeight - terminusPoint.y)) | |
}; | |
var topLeftBack = { | |
x: bottomLeftBack.x, | |
y: bottomLeftBack.y - pixelHeightBack | |
}; | |
var topRightBack = { | |
x: topLeftBack.x + pixelWidthBack, | |
y: topLeftBack.y | |
}; | |
var bottomRightBack = { | |
x: topRightBack.x, | |
y: bottomLeftBack.y | |
}; | |
// right side | |
drawPolygon([topRightFront, topRightBack, bottomRightBack, bottomRightFront], color_right); | |
// left side | |
drawPolygon([topLeftFront, topLeftBack, bottomLeftBack, bottomLeftFront], color_left); | |
// "top of building" | |
drawPolygon([topLeftFront, topLeftBack, topRightBack, topRightFront], color_top); | |
// "front of building" | |
drawPolygon([topLeftFront, topRightFront, bottomRightFront, bottomLeftFront], color_front); | |
}; | |
// points must be in consecutive order of drawing | |
var drawPolygon = function(points, fill_color) { | |
ctx.beginPath(); | |
ctx.moveTo(points[0].x, points[0].y); | |
for(var i=1; i<points.length; i++) { | |
ctx.lineTo(points[i].x, points[i].y); | |
} | |
// close the shape | |
ctx.lineTo(points[0].x, points[0].y); | |
ctx.closePath(); | |
ctx.stroke(); | |
ctx.fillStyle = fill_color; | |
ctx.fill(); | |
} | |
// return an array of buildings | |
var generateCity = function() { | |
var cityArray = []; | |
var plotSize = 60; | |
var streetSize = 25; | |
var buildingSize = plotSize - streetSize; | |
for(var j=0; j < parseInt((terminusPoint.z - plotSize)/plotSize); j++) { | |
for(var i = 0; i<parseInt(canvasWidth/plotSize); i++) { | |
var randHeight = Math.random()*90 + 10; | |
if(Math.random() > 0.95) { randHeight += 70; } | |
if(Math.random() > 0.97) { randHeight += 170; } | |
// to make buildings go into blocks of 2x2 | |
var xBlockModifier = 0; | |
var yBlockModifier = 0; | |
if(i % 2 == 0) { xBlockModifier += streetSize; } | |
if(j % 2 == 0) { yBlockModifier = streetSize; } | |
cityArray.push({ | |
x: i*plotSize + xBlockModifier, z: j*plotSize + yBlockModifier, w: buildingSize, d: buildingSize, h: randHeight | |
}); | |
} | |
} | |
return cityArray; | |
}; | |
var buildings = generateCity(); | |
var sortBuildings = function(arrayToSort) { | |
var arrayToReturn = []; | |
for(var i=0; i < arrayToSort.length; i++) { | |
var currItem = arrayToSort[i]; | |
var destIdx = arrayToReturn.length; | |
for(var j=0; j < arrayToReturn.length; j++) { | |
var compItem = arrayToReturn[j]; | |
if((currItem.z > compItem.z) || | |
(Math.abs(currItem.x - canvasWidth / 2.0) > Math.abs(compItem.x - canvasWidth / 2.0) && currItem.z == compItem.z)) { | |
destIdx = j; | |
break; | |
} | |
} | |
arrayToReturn = arrayToReturn.slice(0,destIdx).concat([currItem]).concat(arrayToReturn.slice(destIdx,arrayToReturn.length)) | |
} | |
return arrayToReturn; | |
}; | |
var sorted_buildings = sortBuildings(buildings); | |
// first draw the roads | |
ctx.strokeStyle = "grey"; | |
var bottomSceneLeft = { | |
x: 38, | |
y: canvasHeight - 9 | |
}; | |
var topSceneLeft = { | |
x: terminusPoint.x - 50, | |
y: terminusPoint.y + 30 | |
}; | |
var topSceneRight = { | |
x: terminusPoint.x + 50, | |
y: terminusPoint.y + 30 | |
}; | |
var bottomSceneRight = { | |
x: canvasWidth - 38, | |
y: canvasHeight - 9 | |
}; | |
drawPolygon([bottomSceneLeft, topSceneLeft, topSceneRight, bottomSceneRight], color_road); | |
for(var i=0; i<sorted_buildings.length; i++) { | |
var b = sorted_buildings[i]; | |
drawBuilding(b.x, b.z, b.w, b.d, b.h); | |
} | |
</script> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment