You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

437 lines
12 KiB

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;
}
}