class Robot { constructor(height, width, x, y, scene, name = 'enemy', speed = SPEED_BEGIN, speedReload = SPEED_RELOAD_BEGIN, range = RANGE_BEGIN, damage = DAMAGE_BEGIN, lNode = []) { this.speedBonus = 1; this.attackBonus = 1; this.name = name; this.height = height; this.width = width; this.x = x; this.y = y; this.life = new HealthBar(scene, selectWord("LIFE", "VIE"), this.width * 2, this.width / 3, this.x, this.y - this.width, LIFE, 0x008000); this.shield = new HealthBar(scene, selectWord("SHIELD", "BOUCLIER"), this.width * 2, this.width / 3, this.x, this.y - this.width * 1.5, SHIELD, 0x0000FF); this.canAttack = true; this.missile = new Missile(scene, 'bullet', this.width / 5, this.width / 4); scene.add.existing(this.missile); this.addScene(scene); this.lNode = lNode; this.setSpeed(speed); this.setSpeedReload(speedReload); this.setRange(range); this.setDamage(damage); this.setX(this.x); this.setY(this.y); this.team = undefined; } addScene(scene) { this.scene = scene; if (this.name === 'enemy') { this.circle = this.scene.add.image(this.x, this.y, 'enemy').setOrigin(0.5, 0.5).setInteractive(); } else { this.circle = this.scene.add.image(this.x, this.y, 'myBot').setOrigin(0.5, 0.5).setInteractive(); } this.circle.displayWidth = this.width; this.circle.displayHeight = this.height; this.circle.on('pointerdown', () => this.click()); } click() { if (this.circleRange === undefined) { this.drawRange(); } else { this.eraseRange(); } this.doEvent(); } addEvent(eventClick, contextClick) { this.eventClick = eventClick; this.contextClick = contextClick; } doEvent() { if (this.eventClick !== undefined && this.contextClick !== undefined) { this.eventClick.call(this.contextClick, this); } } addShield(shield) { this.shield.increase(shield); } setX(x) { this.x = x; this.life.setX(this.x); this.shield.setX(this.x); this.circle.setX(this.x); this.drawCircleRange(); } setY(y) { this.y = y; let yLife = this.y - this.width; let yShield = this.y - this.width * 1.5; if (yLife < 0) { yShield = this.y + this.width - this.shield.height; yLife = this.y + this.width * 1.5 - this.shield.height; } else { if (yShield < 0) { yShield = yLife; yLife = this.y + this.width - this.shield.height; } } this.life.setY(yLife); this.shield.setY(yShield); this.circle.setY(this.y); this.drawCircleRange(); } setTint(color) { this.circle.setTint(color); } clearTint() { this.circle.clearTint(); } setTarget(target) { this.target = target; } updateTarget() { if (this.verifyTarget()) this.setTargetPos(this.target.x, this.target.y); } setTargetPos(x, y) { } setDamage(damage = this.damage) { this.damage = damage + DAMAGE_BASE; } setRange(range = this.range) { this.range = range + RANGE_BASE; this.drawCircleRange(); } setSpeed(speed = this.speed) { this.speed = speed + SPEED_BASE; } setSpeedReload(speedReload = this.speedReload) { this.speedReload = speedReload + SPEED_RELOAD_BASE; } setAttackBonus(amount) { this.attackBonus = amount; } increaseSpeedBonus(amount) { this.speedBonus += amount; } decreaseSpeedBonus(amount) { this.speedBonus -= amount; console.log(this.speed); } advanceToTarget() { if (this.verifyTarget()) { this.advanceTo(this.target); } return false; } advanceTo(target) { if (target.x !== this.x || target.y !== this.y) { let x = false; let y = false; let velocity = this.getVelocity(target); let newX = velocity[0] + this.x; let newY = velocity[1] + this.y; if ((velocity[0] >= 0 && newX >= target.x) || (velocity[0] <= 0 && newX <= target.x)) { this.setX(target.x); x = true; } else this.setX(this.x + velocity[0]); if ((velocity[1] >= 0 && newY >= target.y) || (velocity[1] <= 0 && newY <= target.y)) { this.setY(target.y); y = true; } else this.setY(this.y + velocity[1]); return !(x && y); } return false; } fleeFromTarget() { if (this.verifyTarget()) { return this.fleeFrom(this.target) } return false; } fleeFrom(target) { if (this.target.x !== this.x || this.target.y !== this.y) { let velocity = this.getVelocity(target, true); if (velocity[0] >= 0 && this.x - this.width / 2 <= 0) { this.setX(this.width / 2); } else if (velocity[0] <= 0 && this.x + this.width / 2 >= WIDTH_MAP) this.setX(WIDTH_MAP - this.width / 2); else this.setX(this.x - velocity[0]); if (velocity[1] >= 0 && this.y - this.width / 2 <= 0) this.setY(this.height / 2); else if (velocity[1] <= 0 && this.y + this.width / 2 >= WIDTH_MAP) this.setY(WIDTH_MAP - this.height / 2); else this.setY(this.y - velocity[1]); return true; } return false; } getVelocity(target, calcul = false) { let velocity = []; let diffX = target.x - this.x; let diffY = target.y - this.y; if (diffX === 0 && diffY === 0) { } let hypot = Math.hypot(diffX, diffY); velocity[0] = diffX / hypot * SPEED * this.speed * this.speedBonus * SPEED_GAME; // Velocity X velocity[1] = diffY / hypot * SPEED * this.speed * this.speedBonus * SPEED_GAME; // Velocity Y if (calcul) { if (this.x + this.width / 2 + velocity[0] > WIDTH_MAP || this.x - this.width / 2 - velocity[0] < 0) { velocity[1] += velocity[0] * Math.sign(velocity[1]); velocity[0] = 0; } else { if (this.y + this.width / 2 - velocity[1] > WIDTH_MAP || this.y - this.width / 2 + velocity[1] < 0) { velocity[0] += velocity[1] * Math.sign(-velocity[0]); velocity[1] = 0; } } } return velocity; } attackTarget(percentBonus = 0) { if (this.verifyTarget()) { if (this.canAttack) this.attack(this.target, percentBonus); return true; } return false; } verifyTarget() { if (this.haveTarget()) { if (!this.target.isAlive()) { this.setTarget(null); return false; } return true; } return false; } attack(target, percentBonus) { this.canAttack = false; this.missile.setPosition(this.x, this.y).setVisible(true); this.missile.setRotation(Math.atan2(this.y - this.target.y, this.x - this.target.x) - 3.14 / 2); this.scene.sound.play('shot'); let duration = this.calcDistance(this.target) * WIDTH_MAP / 1000 / SPEED_GAME; this.scene.tweens.add({ targets: this.missile, x: target.x, y: target.y, ease: 'Linear', duration: duration, onComplete: () => this.finishAttack(target, percentBonus) }); this.scene.time.addEvent({ delay: SPEED_RELOAD / this.speedReload / SPEED_GAME, callback: this.reload, callbackScope: this }); } finishAttack(target, percentBonus) { if (target.beAttack(this.damage * this.attackBonus * DAMAGE * percentBonus, this.team)) { this.setTarget(null); } this.missile.setVisible(false); if (this.attackBonus !== 1) { this.setAttackBonus(1); } } reload() { this.canAttack = true; } beAttack(damage, team) { let diff = this.shield.decrease(damage); let style = {font: HEIGHT_DAMAGE.toString() + 'px stencil', fill: "#ffff00"}; let text = this.scene.add.text(this.x, this.y, damage.toString(), style).setOrigin(0, 1); this.scene.tweens.add({ targets: text, x: this.x + 30, y: this.y - 50, alpha: 0, duration: DURATION_DAMAGE, ease: 'Sine.easeOut', onComplete: () => text.destroy() }) this.scene.sound.play('hit'); console.log('HIT'); if (diff > 0) { console.log("Shield Broken"); this.life.decrease(diff); } this.addScore(team) return this.die(); } addScore(team) { if (team !== undefined) { team.addScore(SCORE_HIT); if (this.life.value === 0) { team.addScore(SCORE_KILL); } } } isTargetInRange(percentRange = 1) { if (this.haveTarget()) { return this.calcDistance(this.target) <= this.range * RANGE * percentRange; } return false; } calcDistance(robot) { return Math.hypot(robot.x - this.x, robot.y - this.y); } isAlive() { return this.life.value > 0; } die() { if (this.life.value === 0) { if (this.circleRange !== undefined) this.circleRange.destroy(); this.circle.destroy(); this.shield.destroy(); this.life.destroy(); return true; } return false; } haveTarget() { return this.target != null; } read() { this.verifyTarget(); for (let i = 0; i < this.lNode.length; i++) { if (this.lNode[i].do(this)) { break; } } } addNode(node) { this.lNode.push(node); } drawRange() { this.circleRange = this.scene.add.graphics(); this.drawCircleRange(); } eraseRange() { this.circleRange.clear(); this.circleRange = undefined; } drawCircleRange() { if (this.circleRange !== undefined) { this.circleRange.clear(); let color = COLOR_GREEN; let thickness = 4; let alpha = 1 / 3; this.circleRange.lineStyle(thickness, color, alpha); let radius = this.range * RANGE; this.circleRange.strokeCircle(this.x, this.y, radius); color = COLOR_ORANGE; alpha = 2 / 3; this.circleRange.lineStyle(thickness, color, alpha); radius = this.range * RANGE * 2 / 3; this.circleRange.strokeCircle(this.x, this.y, radius); color = COLOR_RED; alpha = 1; this.circleRange.lineStyle(thickness, color, alpha); radius = this.range * RANGE / 3; this.circleRange.strokeCircle(this.x, this.y, radius); } } cleanNodes() { this.lNode = []; } setNodes(lNode) { this.cleanNodes(); lNode.forEach(node => this.addNode(node)); } setVisible(boolean) { this.circle.setVisible(boolean); this.life.setVisible(boolean); this.shield.setVisible(boolean); if (this.circleRange !== undefined) { this.circleRange.setVisible(boolean); } } getTreeJson() { let json = '{' + toJson("type", "waria"); json += '"lNode":['; this.lNode.forEach(node => json += node.getTreeJson() + ','); json = endLineJson(json); json += ']}'; return json; } }