Skip to content

Instantly share code, notes, and snippets.

@gluschenko
Last active November 17, 2017 13:38
Show Gist options
  • Save gluschenko/10d8a66293be9314a999cf979f00f551 to your computer and use it in GitHub Desktop.
Save gluschenko/10d8a66293be9314a999cf979f00f551 to your computer and use it in GitHub Desktop.
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<style>
body
{
margin: 0;
}
</style>
</head>
<body>
<div>
<canvas id="LinesX" width="1366" height="662" style="display: block; background-color: #000;"></canvas>
</div>
<script>
var SelectedBody = -1;
var Objects = [];
function Point(x, y, velocityX, velocityY)
{
return {
x: x | 0,
y: y | 0,
velocityX: velocityX | 0,
velocityY: velocityY | 0
};
}
function Body(pos, mass, color)
{
this.id = Objects.length;
this.pos = pos;
this.mass = mass;
this.color = color;
this.getRadius = function(){
return Math.cbrt(this.mass * 0.75 / Math.PI);
//return Math.sqrt(Math.sqrt(this.mass / Math.PI));
};
}
function Orbit(A, B)
{
var e = LinesX;
var R = e.Distance(A.pos, B.pos);
var V = Math.sqrt(G * A.mass / R);
var Angle = e.GetAngle(B.pos, A.pos);
var dirV = e.RotatePoint(new Point(0, V), Angle);
B.pos.velocityX = dirV.x;
B.pos.velocityY = dirV.y;
}
var G = 6.67 * 1;
LinesX = {
Canvas: null,
Context: null,
Width: 0,
Height: 0,
Points: [],
Counter: 0,
mousePosition: new Point(0, 0),
FPSCount: 0,
FPSCountView: 0,
currentTime: 0,
Init: function(obj, struct){
var e = LinesX;
e.ApplyCanvas(obj);
e.Draw(0);
document.getElementById(obj).addEventListener("mousemove", function (event) {
e.mousePosition = e.getMousePosition(event);
}, false);
document.getElementById(obj).addEventListener("click", function (event) {
for(var i = 0; i < Objects.length; i++)
{
var B = Objects[i];
var r = B.getRadius();
var dist = e.Distance(B.pos, e.mousePosition);
if(dist <= r)
{
if(i != SelectedBody)
{
SelectedBody = i;
}
else
{
SelectedBody = -1;
}
return;
}
}
for(var i = 0; i < Objects.length; i++)
{
var A = Objects[i];
if(i == SelectedBody)
{
var m = Math.round(Math.random() * 100 + 1);
var B = new Body(new Point(e.mousePosition.x, e.mousePosition.y, 0, 0), m, "#fff");
Objects.push(B);
Orbit(A, B);
return;
}
}
var m = Math.round(Math.random() * 100 + 1);
var B = new Body(new Point(e.mousePosition.x, e.mousePosition.y, 0, 0), m, "#fff");
Objects.push(B);
event.preventDefault();
}, false);
/*Find(obj).addEventListener("contextmenu", function (event) {
e.Zoom *= 0.95;
e.OffsetX += (e.Width/2 - e.mousePosition.x) < 0 ? -10 : 10;
e.OffsetY += (e.Height/2 - e.mousePosition.y) < 0 ? -10 : 10;
e.Draw();
event.preventDefault();
}, false);*/
setInterval(function(){
e.FPSCountView = e.FPSCount * 2;
e.FPSCount = 0;
}, 500);
},
ApplyCanvas: function(obj){
var C = document.getElementById(obj);
LinesX.Canvas = C;
if(C.width != document.body.clientWidth && document.body.clientWidth != 0) C.width = document.body.clientWidth;
if(C.height != document.body.clientHeight && document.body.clientHeight != 0) C.height = document.body.clientHeight;
LinesX.Width = C.width;
LinesX.Height = C.height;
LinesX.Context = C.getContext("2d");
},
Draw: function(time){
dt = (time - LinesX.currentTime) / 1000;
LinesX.currentTime = time;
if(dt > 0.1)dt = 0;
LinesX.ApplyCanvas(LinesX.Canvas.id);
//
var ctx = LinesX.Context;
var w = LinesX.Width;
var h = LinesX.Height;
var e = LinesX;
var backColor = "rgba(0, 0, 0, 0.1)";
ctx.fillStyle = backColor;
ctx.fillRect(0, 0, w, h);
//
if(e.Counter == 0)
{
var A = new Body(new Point(w/2, h/2, 0, 0), 100000, "#fff");
Objects.push(A);
var C = new Body(new Point(w/2 + 100, h/2, 0, 0), 10000, "#fff");
Objects.push(C);
Orbit(A, C);
var D = new Body(new Point(w/2 - 100, h/2, 0, 0), 10000, "#fff");
Objects.push(D);
Orbit(A, D);
for(var i = 0; i < 100; i++)
{
var x = Math.round(Math.random() * w);
var y = Math.round(Math.random() * h);
var m = Math.round(Math.random() * 10 + 1);
var r = Math.round(Math.random() * 255);
var g = Math.round(Math.random() * 255);
var b = Math.round(Math.random() * 255);
var vx = 0; //Math.round(Math.random() * 20 - 10);
var vy = 0; //Math.round(Math.random() * 20 - 10);
var B = new Body(new Point(x, y, vx, vy), m, "rgb(" + r + ", " + g + ", " + b + ")");
Objects.push(B);
Orbit(A, B);
}
}
// Draw
for(var i = 0; i < Objects.length; i++)
{
var B = Objects[i];
var r = B.getRadius();
var selected = i == SelectedBody;
e.DrawCircle(B.pos, Math.round(r), !selected ? B.color : "#0f0");
//e.DrawText(B.pos, B.mass, 1);
}
//e.DrawCircle(e.mousePosition, 10, "#ff0");
// Move
for(var i = 0; i < Objects.length; i++)
{
var B = Objects[i];
var velX = 0;
var velY = 0;
for(var j = 0; j < Objects.length; j++)
{
var A = Objects[j];
if(A.id != B.id)
{
var R = e.Distance(A.pos, B.pos);
var RA = A.getRadius();
var RB = B.getRadius();
if(R > RA + RB)
{
if(R == 0)R = 1;
var F = G * (A.mass * B.mass) / (R * R);
var Angle = e.GetAngle(B.pos, A.pos);
var dirF = e.RotatePoint(new Point(F, 0), Angle);
velX += dirF.x / B.mass * dt;
velY += dirF.y / B.mass * dt;
}
else
{
var x = (B.mass > A.mass) ? B.pos.x : A.pos.x;
var y = (B.mass > A.mass) ? B.pos.y : A.pos.y;
var vx = (B.mass > A.mass) ? B.pos.velocityX : A.pos.velocityX;
var vy = (B.mass > A.mass) ? B.pos.velocityY : A.pos.velocityY;
B.color = (B.mass > A.mass) ? B.color : A.color;
B.pos = new Point(x, y, vx, vy);
B.mass = B.mass + A.mass;
Objects.splice(j, 1);
if(SelectedBody == j)
{
SelectedBody = i;
}
if(SelectedBody > j)
{
SelectedBody--;
}
}
}
}
B.pos.velocityX += velX;
B.pos.velocityY += velY;
//e.DrawLine(B.pos, new Point(B.pos.x + velX, B.pos.y + velY), "#00f");
//e.DrawLine(B.pos, new Point(B.pos.x + B.pos.velocityX, B.pos.y + B.pos.velocityY), "#ff0");
B.pos.x += B.pos.velocityX * dt;
B.pos.y += B.pos.velocityY * dt;
//if(B.pos.x < 0 || B.pos.x > w) B.pos.velocityX *= -1;
//if(B.pos.y < 0 || B.pos.y > h) B.pos.velocityY *= -1;
}
//
e.Counter++;
e.DrawText(e.Point(10, 30), e.FPSCountView + " FPS / Objects: " + Objects.length, 1);
e.FPSCount++;
//
/*setTimeout(function(){
e.Draw();
}, 30);*/
window.requestAnimationFrame(e.Draw);
},
Point: function(x, y){
return { x: x, y: y };
},
RotatePoint: function(point, degAngle){
var Angle = degAngle * (Math.PI/180); // 0.0174532925;
var x = point.x;
var y = point.y;
var rx = Math.round((x * Math.cos(Angle)) - (y * Math.sin(Angle)));
var ry = Math.round((x * Math.sin(Angle)) + (y * Math.cos(Angle)));
return new Point(rx, ry);
},
GetAngle: function(A, B){
var X1 = A.x, Y1 = A.y;
var X2 = B.x, Y2 = B.y;
var Angle = Math.atan2(Y2 - Y1, X2 - X1) * (180/Math.PI);
Angle = (Angle < 0) ? Angle + 360 : Angle;
return Math.round(Angle);
},
DrawLine: function(A, B, color)
{
var ctx = LinesX.Context;
ctx.beginPath();
ctx.moveTo(A.x, A.y);
ctx.lineTo(B.x, B.y);
ctx.lineWidth = 1;
ctx.strokeStyle = color;
ctx.stroke();
},
DrawCircle: function(pos, radius, color){
var ctx = LinesX.Context;
ctx.beginPath();
ctx.arc(pos.x, pos.y, radius, 0, 2 * Math.PI, false);
ctx.fillStyle = color;
ctx.fill();
},
DrawText: function(pos, text, scale){
if(scale > 0)
{
var ctx = LinesX.Context;
ctx.font = Math.round(scale * 14) + "px arial";
ctx.strokeStyle = "#000";
ctx.strokeText(text, pos.x + 1, pos.y + 1);
ctx.fillStyle = "#fff";
ctx.fillText(text, pos.x, pos.y);
}
},
Distance: function(A, B){
var dx = Math.abs(A.x - B.x);
var dy = Math.abs(A.y - B.y);
return Math.sqrt(dx * dx + dy * dy);
},
getMousePosition: function(moveEvent) {
var rect = LinesX.Canvas.getBoundingClientRect();
var x = moveEvent.clientX - rect.left;
var y = moveEvent.clientY - rect.top;
return new Point(x, y);
},
};
function in_array(what, where) {
for(var i = 0; i < where.length; i++)
{
if(what == where[i])
{
return true;
}
}
return false;
}
LinesX.Init("LinesX");
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment