-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathEnemy.java
More file actions
139 lines (135 loc) · 6.17 KB
/
Enemy.java
File metadata and controls
139 lines (135 loc) · 6.17 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
/**
* Final Game Enemy Class
* @Author Ilya Kononov
* @Date = January 22 2023
* This is the class for the Enemy of the game
* Houses the state/position of the player
*/
import java.awt.Rectangle;
import java.util.ArrayList;
public class Enemy {
private int x;
private int y;
private int angle;
private int health;
private int damage;
private Rectangle hitbox;
private char[][] maze;
private boolean inWall;
public Enemy(int x, int y, char maze[][], int level){
this.x = x;
this.y = y;
this.angle = 0;
this.health = Const.ENEMY_HEALTH + (level - 1) * Const.ENEMY_HEALTH_INCREMENT;
this.damage = Const.ENEMY_DAMAGE + (level - 1) * Const.ENEMY_DAMAGE_INCREMENT;
this.hitbox = new Rectangle(x, y, Const.ENEMY_DIMENSIONS, Const.ENEMY_DIMENSIONS);
this.maze = maze;
this.inWall = false;
}
// Getters and Setters
public int getX(){
return this.x;
}
public int getY(){
return this.y;
}
public int getAngle(){
return this.angle;
}
public int getHealth(){
return this.health;
}
public int getDamage(){
return this.damage;
}
public Rectangle getHitbox(){
return this.hitbox;
}
public boolean inWall(){
return this.inWall;
}
public void setCoords(int centerX, int centerY){
this.x = centerX - 55;
this.y = centerY - 55;
this.hitbox.setLocation(this.x, this.y);
}
// Methods to do with angles and movement
private double radians(int angle) {
return angle / 180d * Math.PI;
}
private int xChange() {
return (int)(Math.cos(radians(this.angle)) * Const.ENEMY_MOVEMENT_SPEED);
}
private int yChange() {
return (int)(Math.sin(radians(this.angle)) * Const.ENEMY_MOVEMENT_SPEED);
}
private int calculateAngle(int playerX, int playerY){
int angle = (int)(Math.atan((double)(this.y - playerY) / (this.x - playerX)) * (180 / Math.PI));
int raa = Math.abs(angle); // related acute angle
if (playerX >= this.x && playerY >= this.y) return raa;
else if (playerX < this.x && playerY >= this.y) return 180 - raa;
else if (playerX < this.x && playerY < this.y) return 180 + raa;
else return 360 - raa;
}
public boolean move(ArrayList<Player> players){
Player closestPlayer = null;
int closestDistance = 0;
// Finding the closest player and if they are within the detection range
for(Player player: players){
int playerDistance = (int)Math.sqrt(Math.pow(this.x - player.getX(), 2) + Math.pow(this.y - player.getY(), 2));
if(player.alive() && !(player.downed()) && (closestPlayer == null || closestDistance > playerDistance)){
closestPlayer = player;
closestDistance = playerDistance;
}
}
int tileX = (this.x + Const.ENEMY_DIMENSIONS / 2) / Const.TILE_DIMENSIONS;
int tileY = (this.y + Const.ENEMY_DIMENSIONS / 2) / Const.TILE_DIMENSIONS;
int x = this.x;
int y = this.y;
if(closestPlayer != null && !(closestPlayer.cloaked()) && closestDistance <= Const.ENEMY_RANGE || closestPlayer.cloaked() && closestDistance <= Const.ENEMY_RANGE - Const.CLOAK_REDUCTION){ // If there is a valid player close
this.angle = calculateAngle(closestPlayer.getX(), closestPlayer.getY());
x = this.x + xChange();
y = this.y + yChange();
this.hitbox.setLocation(x, y);
for(Integer[] adjacentTile: Const.ADJACENT_SQUARES){
int adjRectXTile = tileX + adjacentTile[0];
int adjRectYTile = tileY + adjacentTile[1];
if(adjRectXTile >= 0 && adjRectXTile <= maze.length - 1 && adjRectYTile >= 0 && adjRectYTile <= maze.length - 1){
Rectangle adjRect = new Rectangle(adjRectXTile * Const.TILE_DIMENSIONS, adjRectYTile * Const.TILE_DIMENSIONS, Const.TILE_DIMENSIONS, Const.TILE_DIMENSIONS);
if(adjRect.intersects(this.hitbox) && maze[adjRectYTile][adjRectXTile] == Const.WALL){ // Checking if enemy has collided with any walls
if(adjRect.contains(this.hitbox)){ // If the enemy somehow ended up fully inside the wall it will get deleted and respawned
this.inWall = true;
}else{ // If the player hit a wall
// These variables are to make sure the right collision spot is checked
int xDistance = (int)Math.abs(adjRect.getCenterX() - (x + Const.ENEMY_DIMENSIONS / 2));
int yDistance = (int)Math.abs(adjRect.getCenterY() - (y + Const.ENEMY_DIMENSIONS / 2));
Rectangle intersection = adjRect.intersection(this.hitbox);
// Horizontal
if(xChange() < 0 && xDistance >= yDistance && (int)intersection.getWidth() > 0){ // Enemy hit wall on its left
x = (int)(adjRect.getX() + Const.TILE_DIMENSIONS);
}else if(xChange() > 0 && xDistance >= yDistance && (int)intersection.getWidth() > 0){ // Enemy hit wall on its right
x = (int)(adjRect.getX() - Const.ENEMY_DIMENSIONS);
}
// Vertical
if(yChange() < 0 && yDistance >= xDistance && (int)intersection.getHeight() > 0){ // Enemy hit wall above it
y = (int)(adjRect.getY() + Const.TILE_DIMENSIONS);
}else if(yChange() > 0 && yDistance >= xDistance && (int)intersection.getHeight() > 0){ // Enemy hit wall below it
y = (int)(adjRect.getY() - Const.ENEMY_DIMENSIONS);
}
}
}
}
}
}
else{
return false;
}
this.x = x;
this.y = y;
this.hitbox.setLocation(this.x, this.y);
return true;
}
public void damage(int damage){
this.health = Math.max(0, this.health - damage);
}
}