Skip to content

Instantly share code, notes, and snippets.

@Willmo36
Last active March 14, 2019 14:46
Show Gist options
  • Save Willmo36/43917784e1ae201f2a8f444ce3ad9800 to your computer and use it in GitHub Desktop.
Save Willmo36/43917784e1ae201f2a8f444ce3ad9800 to your computer and use it in GitHub Desktop.
Basic trigonometry via tiny game
type Pair = [number, number];
type GameState = {
keyCode: number | null;
playerPos: Pair;
playerImg: HTMLImageElement;
enemyPos: Pair;
enemyImg: HTMLImageElement;
};
function game() {
//SETUP
let canvas = document.getElementById("canvas") as HTMLCanvasElement;
let context = canvas.getContext("2d")!;
canvas.width = 750;
canvas.height = 500;
let playerImg = new Image();
playerImg.src = "/assets/player.png";
let enemyImg = new Image();
enemyImg.src = "/assets/enemy.png";
document.addEventListener("keydown", e => {
gs.keyCode = e.keyCode;
});
document.addEventListener("keyup", () => {
gs.keyCode = null;
});
let gs: GameState = {
keyCode: null,
playerPos: [100, 100],
playerImg,
enemyPos: [400, 300],
enemyImg
};
const runLoop = () => {
requestAnimationFrame(() => loop(gs, context, runLoop));
};
runLoop();
}
function loop(gs: GameState, ctx: CanvasRenderingContext2D, done: Function) {
ctx.clearRect(0, 0, 500, 500);
gs.playerPos = nextPlayerPosition(gs);
//TRIG PART
//knowing 2/3 points (player & enemy) we can find the right angle point
let ra: Pair = [gs.playerPos[0], gs.enemyPos[1]];
//then we can figure out the opposite and adjacent lengths
let oppositeL = Math.max(gs.playerPos[1], ra[1]) - Math.min(gs.playerPos[1], ra[1]);
let adjacentL = Math.max(gs.enemyPos[0], ra[0]) - Math.min(gs.enemyPos[0], ra[0]);
//from these we can reverse tan fn to get the alpha angle (angle at the enemys side)
const alpha = Math.atan(oppositeL / adjacentL);
//using alpha we can figure out the beta, the angle on the players side
const beta = Math.PI - Math.PI / 2 - alpha;
//Have the player face the right angle so we can use the beta radians
const hozRotation = gs.playerPos[1] < gs.enemyPos[1] ? Math.PI : 0;
//then use the beta to face the enemy
const latRotation = beta * (gs.playerPos[1] < gs.enemyPos[1] ? -1 : 1);
const playerDimensions: Pair = [50, 50];
const playerOffsets: Pair = [playerDimensions[0] / 2, playerDimensions[1] / 2];
renderRightTriangle(ctx, gs, ra);
renderPlayer(ctx, gs, hozRotation, latRotation, playerOffsets, playerDimensions);
renderEnemy(ctx, gs);
done();
}
function renderEnemy(ctx: CanvasRenderingContext2D, gs: GameState) {
const enemyDimensions = [150, 150];
const enemyOffsets = [enemyDimensions[0] / 2, enemyDimensions[1] / 2];
ctx.drawImage(
gs.enemyImg,
gs.enemyPos[0] - enemyOffsets[0],
gs.enemyPos[1] - enemyOffsets[1],
enemyDimensions[0],
enemyDimensions[1]
);
}
function renderPlayer(
ctx: CanvasRenderingContext2D,
gs: GameState,
hozRotation: number,
latRotation: number,
playerOffsets: Pair,
playerDimensions: Pair
) {
ctx.save();
ctx.translate(gs.playerPos[0], gs.playerPos[1]);
ctx.rotate(hozRotation + latRotation);
ctx.drawImage(
gs.playerImg,
-playerOffsets[0],
-playerOffsets[1],
playerDimensions[0],
playerDimensions[1]
);
ctx.restore();
}
function renderRightTriangle(ctx: CanvasRenderingContext2D, gs: GameState, ra: Pair) {
ctx.save();
ctx.beginPath();
ctx.strokeStyle = "red";
ctx.moveTo(gs.playerPos[0], gs.playerPos[1]);
ctx.lineTo(ra[0], ra[1]);
ctx.stroke();
ctx.moveTo(gs.enemyPos[0], gs.enemyPos[1]);
ctx.lineTo(ra[0], ra[1]);
ctx.stroke();
ctx.moveTo(gs.enemyPos[0], gs.enemyPos[1]);
ctx.lineTo(gs.playerPos[0], gs.playerPos[1]);
ctx.stroke();
ctx.closePath();
ctx.restore();
}
function nextPlayerPosition(gs: GameState): Pair {
const changes = movement.get(gs.keyCode || 0) || [0, 0];
return [gs.playerPos[0] + changes[0], gs.playerPos[1] + changes[1]];
}
const UP = 38;
const DOWN = 40;
const LEFT = 37;
const RIGHT = 39;
const speed = 2;
const movement = new Map<number, Pair>([
[UP, [0, -speed]],
[DOWN, [0, speed]],
[LEFT, [-speed, 0]],
[RIGHT, [speed, 0]]
]);
game();
@Willmo36
Copy link
Author

example

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment