bombs away

testing bomb arc wondered what the curve looks like after a few seconds. I'm not a violent person, somehow I was just curious about the physics. (although hugely simplified here)

by Laurens Maneschijn

HTML

<div class="_template plane">🛪</div>
<div class="_template bomb">💣</div>

<button id="button_restart">restart</button>
<button id="button_start">start</button>
<button id="button_stop">stop</button>

<div id="main"></div>

CSS

#main {
    position: relative;
}

.plane,
.bomb {
    display: inline-block;
    position: absolute;
    width: 1em;
    height: 1em;
}

._template {
    display: none;
}

JavaScript

var raf;
var plane;
var bombs = [];
var framecnt = 0;

function init() {
	framecnt = 0;
	plane = {
		x: 0,
		y: 0,
		vx: 1,
		vy: 0
	};
	bombs = [];
}

function loop_start() {
	window.cancelAnimationFrame(raf);
	raf = window.requestAnimationFrame(loop_tick);
}

function loop_stop() {
	window.cancelAnimationFrame(raf);
}

function loop_next() {
	window.cancelAnimationFrame(raf);
	raf = window.requestAnimationFrame(loop_tick);
}

function loop_tick() {
	framecnt++;
	update();
	draw();
	loop_next();
}

function update() {
	plane.x += plane.vx;
	plane.y += plane.vy;
	if (plane.x % 10 == 0) {
		bombs.push({
			x: plane.x,
			y: plane.y,
			vx: plane.vx,
			vy: plane.vy
		});
	}
	bombs.forEach(function(b) {
		// simulate gravity:
		b.vy += 0.1;
		// simulate air friction:
		b.vx *= 0.95;
		b.vy *= 0.95;
		// update position:
		b.x += b.vx;
		b.y += b.vy;
	});

}

function draw() {
	var $_template_plane = $('._template.plane');
	var $_template_bomb = $('._template.bomb');
	$('#main').empty();
	$('#main').append(framecnt);
	$('#main').append('<pre>plane:' + otostr(plane) + '</pre>');
	if (bombs[0]) {
		$('#main').append('<pre>bombs[0]:' + otostr(bombs[0]) + '</pre>');
	}
	var $plane = $_template_plane.clone().removeClass('_template');
	$plane.css({
		left: plane.x,
		top: plane.y
	});
	$plane.appendTo($('#main'));
	bombs.forEach(function(b) {
		var $bomb = $_template_bomb.clone().removeClass('_template');
		$bomb.css({
			left: b.x,
			top: b.y
		});
		$bomb.appendTo($('#main'));
	});
}

// boilerplate lib stuff:

function fix(n, d) {
	var d = Math.max(1, Math.pow(10, d));
	return Math.round(n * d) / d;
}

function otostr(o) {
	return `
vx:${fix(o.vx,3)}
vy:${fix(o.vy,3)}
x:${fix(o.x,3)}
y:${fix(o.y,3)}
`;
}


init();
$('#button_restart').click(function() {
	init();
	loop_start();
});
$('#button_start').click(function() {
	loop_start();
});
$('#button_stop').click(function() {
	loop_stop();
});