Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Bolloxim/b710de050203c44aad43 to your computer and use it in GitHub Desktop.
Save Bolloxim/b710de050203c44aad43 to your computer and use it in GitHub Desktop.
A Pen by Andi Smithers.

Cutaway hemisphere - js canvas 2D

Started off as something else but now its a marble earth kind of thing. will be my star-raiders starbase

can do a lot more with the hemisphere rendering. If I have time can show gold ring, shadows and moons etc.. all cool stuff.

might make a solar system flyby once star-raiders is finished

version 0.2 added canvas rotate / translate to rotate around the y axis

version 0.3 added a core object that can be cycled through layers

A Pen by Andi Smithers on CodePen.

License.

<body>
<canvas id='hemisphere'></canvas>
</body>
// conceptualized and written by andi smithers
// copyright andi smithers.
// freely distributable in whole or in partial
// please retain credit and comment if distributed
// thank you.
// constant options
const focalDepth = 80;
const focalPoint = 256;
// variables
var centreX;
var centreY;
var mouseX;
var mouseY;
var spawnX;
var spawnY;
var frameCount=0;
var targetLayer = 0.25;
var layer = 0.25;
// test multiple groups
// initialization
function init()
{
// setup canvas and context
canvas = document.getElementById('hemisphere');
context = canvas.getContext('2d');
// set canvas to be window dimensions
resize();
// create event listeners
canvas.addEventListener('mousemove', mouseMove);
canvas.addEventListener('click', mouseClick);
window.addEventListener('resize', resize);
// initialze variables
}
// input functions
function mouseMove(event)
{
var rect = canvas.getBoundingClientRect();
mouseX = event.clientX - rect.left,
mouseY = event.clientY - rect.top
}
function mouseClick()
{
targetLayer-=0.25;
if (targetLayer <0.0) targetLayer = 0.75;
}
function resize()
{
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
// compute centre of screen
centreX = canvas.width/2;
centreY = canvas.height/2;
}
// rendering functions
function render()
{
context.fillStyle = 'black';
context.clearRect(0, 0, canvas.width, canvas.height);
RenderBlueMarble();
context.globalAlpha = 1.0;
context.font = '20pt Calibri';
context.fillStyle = 'rgb(255,255,255)';
context.textAlign = "center";
context.fillText('Hemi-Sphere 2D rendering', canvas.width/2, 20);
context.fillText('Blue Marble Cutaway', canvas.width/2, canvas.height-20);
context.font = '14pt Calibri';
context.fillText('(click to cycle layers)', canvas.width/2, 40);
}
function RenderBlueMarble()
{
// interporlate layer changes so its nice and smooth
var dx = targetLayer-layer;
layer+=dx*0.1;
// rotate
angle=(angle+0.01)%(Math.PI*2);
var x = centreX;
var y = centreY;
var radius = canvas.height/4;
if (angle>Math.PI*0.5 && angle<Math.PI*1.5) RenderCore(x, y, radius*layer, layer);
RenderHemisphere(x, y, radius, 4, '#0000ff');
if (!(angle>Math.PI*0.5 && angle<Math.PI*1.5)) RenderCore(x, y, radius*layer, layer);
}
function RenderCore(x, y, r, layer)
{
var outerColor = 'rgb(255,'+Math.floor(255-255*layer)+',0)';
angle=(angle+Math.PI)%(Math.PI*2);
RenderHemisphere(x, y, r, 1, outerColor);
angle=(angle+Math.PI)%(Math.PI*2);
}
// star base construction - eer well it was but its a cool blue marble demo for now
// to rotate horizontally switch out the x/y registers. I should probably make this generic .. however just want to use this for the starbase construction in star-raiders
var angle = 0;
function RenderHemisphere(x, y, rad, slices, outerColor)
{
// really bad hack to change orientation of the hemisphere
// rotate the object 90 degrees and then compensate for the centre x/y changes
context.save();
context.rotate(Math.PI*0.5);
context.translate(-x+y,-y-x);
m = 0.5522848;
// molten core
for (var r=rad; r>0; r-=(rad/slices))
{
tr =r*Math.cos(angle); // top hemisphere angle *rad
br =r*Math.cos(angle); // bottom angle *rad
xkr = m*r; // kappa * r
tkr = m*tr; // top height * kappa
bkr = m*br; // bottom height * kappa
context.beginPath()
context.moveTo(x+r, y)
context.bezierCurveTo(x+r, y-tkr, x+xkr, y-tr, x, y-tr) // top r
context.bezierCurveTo(x-xkr, y-tr, x-r, y-tkr, x-r, y) // top l
context.bezierCurveTo(x-r, y+bkr, x-xkr, y+br, x, y+br) // bot l
context.bezierCurveTo(x+xkr, y+br, x+r, y+bkr, x+r, y) // bot r
context.closePath();
context.lineWidth = 1;
context.fillStyle = 'rgb(255,' + Math.floor(255-r/rad*255) +',0)';
context.fill();
}
// drow the blue surface
var r = rad;
tr =r*Math.cos(angle+Math.PI); // top hemisphere angle *rad
br =r*Math.cos(angle+Math.PI); // bottom angle *rad
if (angle<Math.PI) br = r;
if (angle>Math.PI) tr = r;
xkr = m*r; // kappa * r
tkr = m*tr; // top height * kappa
bkr = m*br; // bottom height * kappa
context.beginPath()
context.moveTo(x+r, y)
context.bezierCurveTo(x+r, y-tkr, x+xkr, y-tr, x, y-tr) // top r
context.bezierCurveTo(x-xkr, y-tr, x-r, y-tkr, x-r, y) // top l
context.bezierCurveTo(x-r, y+bkr, x-xkr, y+br, x, y+br) // bot l
context.bezierCurveTo(x+xkr, y+br, x+r, y+bkr, x+r, y) // bot r
context.closePath();
context.lineWidth = 1;
context.fillStyle = outerColor;
context.fill();
context.restore();
}
// movement functions
function update()
{
}
// per frame tick functions
function animate()
{
frameCount++;
// movement update
update();
// render update
render();
// trigger next frame
requestAnimationFrame(animate);
}
// entry point
init();
animate();
body{
background:#000000;
margin: 0px;
padding: 0px;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment