robotank/client-hodejs/simplehunter.ts
Sascha Nitsch 51f0415617 initial im
2025-03-03 02:17:50 +01:00

132 lines
No EOL
4.2 KiB
TypeScript

import { RobotStatus } from "./robotstatus";
import { RoboBase } from "./robobase";
class SimpleHunter extends RoboBase {
targetX: number = 0;
targetY: number = 0;
fireCoolDown: number = 0;
mode: string = "SCAN";
ready() {
console.log("simpleHunter is ready");
this.cmd.radarMin = -1;
this.cmd.radarMax = -1;
this.sendCmd();
}
start() {
console.log("simulation started");
this.targetX = Math.random() * (this.width - 20) + 10;
this.targetY = Math.random() * (this.height - 20) + 10;
console.log("target", this.targetX, this.targetY);
}
driveToTarget(status: RobotStatus) {
const dx = this.targetX - status.posX;
const dy = this.targetY - status.posY;
const dir = Math.atan2(dx, -dy) * 180 / Math.PI;
const dst = Math.sqrt(dx * dx + dy * dy);
let rot = dir - status.orientation;
if (rot < -180) {
rot += 360;
}
if (rot > 180) {
rot -= 360;
}
rot = Math.min(Math.max(-90, rot), 90);
let desiredSpeed = 1;
if (this.mode === 'SCAN') {
if (dst < 30) {
desiredSpeed = dst / 40;
}
} else {
if (dst < 75) {
desiredSpeed = dst - 50 / 25;
}
}
const speedDiff = Math.sin(rot * Math.PI / 180.0);
// desired speed of left chain
let dsl = desiredSpeed + speedDiff;
// desired speed of right chain
let dsr = desiredSpeed - speedDiff;
// prevent overflows, reduce to limits but keep relative difference if possible
if (dsl > 1) {
dsr -= Math.max(dsl - 1, -1);
dsl = 1;
} else if (dsr > 1) {
dsl -= Math.max(dsr - 1, -1);
dsr = 1;
}
this.cmd.powerLeft = dsl;
this.cmd.powerRight = dsr;
// close and slow enough?
if (dst < 5 && Math.abs(status.chainSpeedLeft) < .1 && Math.abs(status.chainSpeedRight) < .1 && this.mode === 'SCAN') {
this.targetX = Math.random() * (this.width - 20) + 10;
this.targetY = Math.random() * (this.height - 20) + 10;
console.log("target reached, new target", this.targetX, this.targetY);
}
}
statusReady(status: RobotStatus) {
this.driveToTarget(status);
if (this.fireCoolDown > 0) {
this.fireCoolDown -= this.deltaTime;
}
if (status.contactPoints && status.contactPoints.length > 0) {
status.contactPoints.forEach((cp) => {
// adjust angle by radar rotation
const angle = (cp.angle + status.radarPos) % 360;
// global angle from position
let newTargetAngle = angle + status.orientation;
if (newTargetAngle >= 360) {
newTargetAngle -= 360;
}
if (newTargetAngle < 0) {
newTargetAngle += 360;
}
this.targetX = Math.sin(newTargetAngle * Math.PI / 180)* (cp.dist - 50) + status.posX;
this.targetY = -Math.cos(newTargetAngle * Math.PI / 180)* (cp.dist - 50) + status.posY;
this.cmd.gunTarget = angle;
console.log("enemy at", this.targetX, this.targetY, "dist", cp.dist, "angle", angle);
this.mode = 'SEEK';
this.cmd.radarMin = angle - 20;
this.cmd.radarMax = angle + 20;
// shoot if aimed close enough
if (cp.dist < 100 && cp.dist > 25) {
console.log("diff", angle, status.gunOrient, Math.abs((angle-status.gunOrient)%360));
if (this.fireCoolDown <= 0 && (Math.abs(angle-status.gunOrient) < 2)) {
this.cmd.fire = true;
console.log("fire", cp.dist);
this.fireCoolDown = 10;
}
}
});
} else {
if (this.mode === 'SEEK') { // lost track
this.cmd.radarMin = (this.cmd.radarMin + 359.5) % 360;
this.cmd.radarMax = (this.cmd.radarMax + .5) % 360;
//console.log("seek radar", this.cmd.radarMin, this.cmd.radarMax);
if (this.cmd.radarMax - this.cmd.radarMin > 180) {
this.cmd.radarMin = -1;
this.cmd.radarMax = -1;
this.mode = 'SCAN';
console.log("scan");
}
}
}
if (status.causedDamage > 0) {
console.log("we hit with damage", status.causedDamage);
}
this.sendCmd();
}
lost() {
console.log("we lost");
this.disconnect();
}
won() {
console.log("we won");
this.disconnect();
}
}
var simpleHunter = new SimpleHunter("targetPractise", "scout");
simpleHunter.connect();