JSFiddle - React, Tailwind, and code Playground
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/pixi.js/4.2.2/pixi.min.js"></script>
<div id="capture_focus" />
CSS
body {
padding: 0;
margin: 0;
}
#capture_focus {
position: absolute;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0);
}
JavaScript
var Degree = Math.PI / 180;
var showDebugOverlays = false;
var Turret = {
gunAngle: -10 * Degree,
maxGunAngle: 85 * Degree,
adaptedGunXOffset: null,
rotateToTarget: function (target) {
var delta = Vec.subtract(this.position, target.position);
var dist = Vec.length(delta);
var angle = Vec.angle(delta);
theta = Math.asin(this.adaptedGunXOffset / dist) + this.gunAngle;
this.rotation = -(angle + theta);
this.updateGunRay(target);
},
setGunAngle: function (angle) {
var angle = this.clampGunAngle(angle);
this.gunAngle = angle;
this.gun.rotation = angle;
// Account for the fact that the origin of the gun also has an y offset
// relative to the turret origin
var extraXOffset = this.gun.position.y * Math.tan(angle);
var gunXOffset = this.gun.position.x + extraXOffset;
// This equals "a * cos(δ')" in the angle formula
this.adaptedGunXOffset = gunXOffset * Math.cos(-angle);
if (showDebugOverlays) {
// Show x offsets
this.removeChild(this.xOffsetOverlay);
this.removeChild(this.extraXOffsetOverlay);
this.xOffsetOverlay = addRect(this, 0, 0, this.gun.position.x, 1, 0xf6ff00);
this.extraXOffsetOverlay = addRect(this, this.gun.position.x, 0, extraXOffset, 1, 0xff00ae);
}
},
rotateGun: function (angleDelta) {
this.setGunAngle(this.gunAngle + angleDelta);
},
updateGunRay: function (target) {
var delta = this.gun.toLocal(target.position);
var dist = Vec.length(delta);
this.gun.removeChild(this.gun.ray);
this.gun.ray = makeLine(0, 0, 0, -dist);
this.gun.addChildAt(this.gun.ray, 0);
},
clampGunAngle: function (angle) {
if (angle > this.maxGunAngle) {
return this.maxGunAngle;
}
if (angle < -this.maxGunAngle) {
return -this.maxGunAngle;
...