- Press f or b to move forword or backword.
- Press l or r to rotate left or right
Make sure you click on the canvas to start.
The HTML file:
<head>
<script type="text/javascript" src="arrow.js"> </script>
<script type="text/javascript" src="axis.js"> </script>
<script type="text/javascript" src="target.js"> </script>
<script type="text/javascript" src="ui.js"> </script>
</head>
<body>
<canvas id="board" width=500 height=500 style="border:2px solid"></canvas>
<p>
<ul>
<li> Press <b>f</b> or <b>b</b> to move forword or backword.
<li> Press <b>l</b> or <b>r</b> to rotate left or right
<l> Make sure you click on the canvas to start.
</ul>
<script>
'use strict'
var canvas = document.getElementById('board');
canvas.tabIndex=0;
canvas.addEventListener("keypress", Keypress);
var ctx = canvas.getContext('2d');
var arrow = new Arrow(canvas.width/2, canvas.height/2);
var arrow2 = new Arrow(canvas.width/2,canvas.height/4);
var axis = new Axis(canvas);
var target = new Target(canvas);
DrawScene();
</script>
</body>
arrow.js
'use strict'
let POINTS = [[100,105],[120,105],[120,100],[130,110],
[120,120],[120,115],[100,115]];
class Arrow {
constructor(x,y) {
let tmp = this.FindCenter();
this.CenterX = tmp[0];
this.CenterY = tmp[1];
this.rotation = 0;
this.xPos = x;
this.yPos = y;
this.theta = 0;
}
ChangeAngle(amt) {
this.rotation += amt;
this.rotation %= 360;
this.theta = this.rotation * Math.PI/180;
}
X() {
return this.xPos;
}
Y() {
return this.yPos;
}
FindCenter() {
let sumX = 0;
let sumY = 0;
for (let i = 0; i < POINTS.length; i++) {
sumX += POINTS[i][0];
sumY += POINTS[i][1];
}
let cx = sumX/POINTS.length;
let cy = sumY/POINTS.length;
return ([cx, cy]);
}
Forward(){
this.Move(1);
}
Backward() {
this.Move(-1);
}
Move(sign) {
this.xPos += sign * 2 * Math.cos(this.theta);
this.yPos += sign * 2 * Math.sin(this.theta);
}
Display(ctx) {
ctx.save();
ctx.translate(this.xPos, this.yPos);
// rotate the arrow
ctx.rotate(this.theta);
// move the arrow to the center of rotation
ctx.translate(-this.CenterX, -this.CenterY);
ctx.beginPath()
ctx.moveTo(POINTS[0][0],POINTS[0][1]);
for (let i =0; i < POINTS.length; i++) {
ctx.lineTo(POINTS[i][0],POINTS[i][1])
}
ctx.lineTo(POINTS[0][0],POINTS[0][1]);
ctx.closePath();
ctx.stroke();
ctx.restore()
}
}
axis.js
'use strict'
class Axis{
constructor (canvas) {
this.width = canvas.width;
this.height = canvas.height;
this.ctx = canvas.getContext('2d');
}
Display() {
this.ctx.strokeColor = "black";
this.ctx.beginPath();
this.ctx.moveTo(0, this.height/2);
this.ctx.lineTo(this.width, this.height/2);
this.ctx.moveTo(this.width/2, 0);
this.ctx.lineTo(this.width/2, this.height);
this.ctx.stroke();
this.ctx.closePath();
}
}
target.js
'use strict'
const SCALE_MIN = 1;
const SCALE_MAX = 10;
class Target{
constructor(canvas) {
this.width = canvas.width;
this.height = canvas.height;
this.ctx = canvas.getContext('2d');
this.x = Math.floor(Math.random()*this.width);
this.y = Math.floor(Math.random()*this.height);
this.scale = 1;
this.MaxDistance = this.Distance([0,0],[this.width, this.height]);
}
Distance(a,b) {
let dx = a[0] - b[0];
let dy = a[1] - b[1];
return Math.sqrt(dx*dx +dy*dy);
}
SetScale(arrow) {
let arrowPos = [arrow.X(), arrow.Y()];
let myPos = [this.x,this.y];
let distanceToArrow = this.Distance(arrowPos,myPos);
let pct = distanceToArrow/this.MaxDistance;
let scale = SCALE_MIN * (1-pct) + SCALE_MAX * pct;
this.ctx.scale(scale,scale);
}
Display(arrow) {
this.ctx.save();
this.ctx.translate(this.x, this.y);
this.SetScale(arrow)
this.ctx.strokeStyle = "black";
for(let radius=12; radius> 0; radius-= 3) {
if (radius%2 == 0) {
this.ctx.fillStyle = "yellow";
} else {
this.ctx.fillStyle = "red";
}
this.ctx.beginPath();
this.ctx.arc(0,0,radius, 0, 2*Math.PI);
this.ctx.fill()
this.ctx.stroke();
this.ctx.closePath();
}
this.ctx.restore();
}
}
ui.js
'use strict'
function Keypress(evnt) {
switch(event.key) {
case 'l':
arrow.ChangeAngle(-3);
break;
case 'r':
arrow.ChangeAngle(3);
break;
case 'f':
arrow.Forward();
break;
case 'b':
arrow.Backward();
break;
}
DrawScene();
}
function RandomUpdate(arrow) {
let value = Math.floor(Math.random() * 10);
switch(value) {
case 1: arrow.Backward(); break;
case 4:
case 5:
case 2: arrow.ChangeAngle(3); break;
case 3: arrow.ChangeAngle(-3); break;
default : arrow.Forward(); break;
}
}
function DrawScene( ) {
ctx.clearRect(0,0,canvas.width, canvas.height);
axis.Display();
arrow.Display(ctx);
RandomUpdate(arrow2);
arrow2.Display(ctx);
target.Display(arrow);
}