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();