package game.entity.player;
import game.entity.enemies.Enemy;
import game.tilesets.TileMap;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import javax.imageio.ImageIO;
public class Player extends MapObject {
// Reference
private ArrayList<Enemy> enemies;
// player stuff
private int lives;
private int health;
private int maxHealth;
private int damage;
private int jabDamage;
private boolean knockback;
private boolean flinching;
private long flinchCount;
private int score;
private boolean doubleJump;
private boolean alreadyDoubleJump;
private double doubleJumpStart;
private ArrayList<WaveAttack> waveattack;
private long time;
// actions
private boolean dashing;
private boolean attacking;
private boolean upattacking;
private boolean charging;
private boolean teleporting;
private int chargingTick;
// animations
private ArrayList<BufferedImage[]> sprites;
private final int[] NUMFRAMES = {
// frame actions
};
private final int[] FRAMEWIDTHS = { 40, 40, 80, 40, 40, 40, 80, 40, 40, 40,
40 };
private final int[] FRAMEHEIGHTS = { 40, 40, 40, 40, 40, 80, 40, 40, 40,
40, 40 };
private final int[] SPRITEDELAYS = { -1, 3, 2, 6, 5, 2, 2, 2, 1, -1, 1 };
private Rectangle ar;
private Rectangle aur;
private Rectangle cr;
// animation actions
private static final int IDLE = 0;
private static final int WALKING = 1;
private static final int ATTACKING = 2;
private static final int JUMPING = 3;
private static final int FALLING = 4;
private static final int UPATTACKING = 5;
private static final int JABBING = 6;
private static final int DASHING = 7;
private static final int KNOCKBACK = 8;
private static final int DEAD = 9;
private static final int TELEPORTING = 10;
// emotes
private BufferedImage confused;
private BufferedImage suprised;
private static final int NONE = 0;
private static final int CONFUSED = 1;
private static final int SUPRISED = 2;
private int emote = NONE;
public Player(TileMap tm) {
super(tm);
ar = new Rectangle(0, 0, 0, 0);
ar.width = 30;
ar.height = 20;
aur = new Rectangle((int) x - 15, (int) y - 45, 30, 30);
cr = new Rectangle(0, 0, 0, 0);
cr.width = 50;
cr.height = 40;
width = 30;
height = 30;
cwidth = 15;
cheight = 38;
moveSpeed = 1.6;
maxSpeed = 1.6;
stopSpeed = 1.6;
fallSpeed = 0.15;
maxFallSpeed = 4.0;
jumpStart = -4.8;
stopJumpSpeed = 0.3;
doubleJumpStart = -3;
damage = 2;
jabDamage = 1;
facingRight = true;
lives = 3;
health = maxHealth = 5;
// load sprites
try {
BufferedImage spritesheet = ImageIO.read(getClass()
.getResourceAsStream("/Entity/Player/PlayerSprites.gif/"));
int count = 0;
sprites = new ArrayList<BufferedImage[]>();
for (int i = 0; i < NUMFRAMES.length; i++) {
BufferedImage[] bi = new BufferedImage[NUMFRAMES[i]];
for (int j = 0; j < NUMFRAMES[i]; j++) {
bi[j] = spritesheet.getSubimage(j * FRAMEWIDTHS[i], count,
FRAMEWIDTHS[i], FRAMEHEIGHTS[i]);
}
sprites.add(bi);
count += FRAMEHEIGHTS[i];
}
// emotes
spritesheet = ImageIO.read(getClass().getResourceAsStream(
"/HUD/Emotes.gif/"));
confused = spritesheet.getSubimage(0, 0, 14, 17);
suprised = spritesheet.getSubimage(14, 0, 14, 17);
} catch (Exception e) {
e.printStackTrace();
}
waveattack = new ArrayList<WaveAttack>();
setAnimation(IDLE);
/***
* JukeBox.load("/SFX/playerjump.mp3", "playerjump");
* JukeBox.load("/SFX/playerlands.mp3", "playerlands");
* JukeBox.load("/SFX/playerattack.mp3", "playerattack");
* JukeBox.load("/SFX/playerhit.mp3", "playerhit");
* JukeBox.load("/SFX/playercharge.mp3", "playercharge");
*/
}
public void init(ArrayList<Enemy> enemies, ArrayList<WaveAttack> waveattack) {
this.enemies = enemies;
this.waveattack = waveattack;
}
public int getHealth() {
return health;
}
public int getMaxHealth() {
return maxHealth;
}
public void setEmote(int i) {
emote = i;
}
public void setTeleporting(boolean b) {
teleporting = b;
}
public void setJumping(boolean b) {
if (knockback)
return;
if (b && !jumping && falling && !alreadyDoubleJump) {
doubleJump = true;
}
jumping = b;
}
public void setAttacking() {
if (knockback)
return;
if (charging)
return;
if (up && !attacking)
upattacking = true;
else
attacking = true;
}
public void setJabbing() {
if (knockback)
return;
if (charging)
return;
charging = true;
// JukeBox.play("playercharge");
chargingTick = 0;
}
public void setDashing(boolean b) {
if (!b)
dashing = false;
else if (b && !falling) {
dashing = true;
}
}
public boolean isDashing() {
return dashing;
}
public void setDead() {
health = 0;
stop();
}
public String getTimeToString() {
int minutes = (int) (time / 3600);
int seconds = (int) ((time % 3600) / 60);
return seconds < 10 ? minutes + ":0" + seconds : minutes + ":"
+ seconds;
}
public long getTime() {
return time;
}
public void setTime(long t) {
time = t;
}
public void setHealth(int i) {
health = i;
}
public void setLives(int i) {
lives = i;
}
public void gainLife() {
lives++;
}
public void loseLife() {
lives--;
}
public int getLives() {
return lives;
}
public void increaseScore(int score) {
this.score += score;
}
public int getScore() {
return score;
}
public void hit(int damage) {
if (flinching)
return;
// JukeBox.play("playerhit");
stop();
health -= damage;
if (health < 0)
health = 0;
flinching = true;
flinchCount = 0;
if (facingRight)
dx = -1;
else
dx = 1;
dy = -3;
knockback = true;
falling = true;
jumping = false;
}
public void reset() {
health = maxHealth;
facingRight = true;
currentAction = -1;
stop();
}
public void stop() {
left = right = up = down = flinching = dashing = jumping = attacking = upattacking = charging = false;
}
private void getNextPosition() {
if (knockback) {
dy += fallSpeed * 2;
if (!falling)
knockback = false;
return;
}
double maxSpeed = this.maxSpeed;
if (dashing)
maxSpeed *= 1.75;
// movement
if (left) {
dx -= moveSpeed;
if (dx < -maxSpeed) {
dx = -maxSpeed;
}
} else if (right) {
dx += moveSpeed;
if (dx > maxSpeed) {
dx = maxSpeed;
}
} else {
if (dx > 0) {
dx -= stopSpeed;
if (dx < 0) {
dx = 0;
}
} else if (dx < 0) {
dx += stopSpeed;
if (dx > 0) {
dx = 0;
}
}
}
// cannot move while attacking, except in air
if ((attacking || upattacking || charging) && !(jumping || falling)) {
dx = 0;
}
// charging
if (charging) {
chargingTick++;
if (facingRight)
dx = moveSpeed * (3 - chargingTick * 0.07);
else
dx = -moveSpeed * (3 - chargingTick * 0.07);
}
// jumping
if (jumping && !falling) {
// sfx.get("jump").play();
dy = jumpStart;
falling = true;
// JukeBox.play("playerjump");
}
if (doubleJump) {
dy = doubleJumpStart;
alreadyDoubleJump = true;
doubleJump = false;
// JukeBox.play("playerjump");
for (int i = 0; i < 6; i++) {
waveattack.add(new WaveAttack(tileMap, x, y + cheight / 4,
WaveAttack.DOWN));
}
}
if (!falling)
alreadyDoubleJump = false;
// falling
if (falling) {
dy += fallSpeed;
if (dy < 0 && !jumping)
dy += stopJumpSpeed;
if (dy > maxFallSpeed)
dy = maxFallSpeed;
}
}
private void setAnimation(int i) {
currentAction = i;
animation.setFrames(sprites.get(currentAction));
animation.setDelay(SPRITEDELAYS[currentAction]);
width = FRAMEWIDTHS[currentAction];
height = FRAMEHEIGHTS[currentAction];
}
public void update() {
time++;
// check teleporting
if (teleporting) {
waveattack.add(new WaveAttack(tileMap, x, y, WaveAttack.UP));
}
// update position
boolean isFalling = falling;
getNextPosition();
checkTileMapCollision();
setPosition(xtemp, ytemp);
if (isFalling && !falling) {
// JukeBox.play("playerlands");
}
if (dx == 0)
x = (int) x;
// check done flinching
if (flinching) {
flinchCount++;
if (flinchCount > 120) {
flinching = false;
}
}
// wave attack
for (int i = 0; i < waveattack.size(); i++) {
waveattack.get(i).update();
if (waveattack.get(i).shouldRemove()) {
waveattack.remove(i);
i--;
}
}
// check attack finished
if (currentAction == ATTACKING || currentAction == UPATTACKING) {
if (animation.hasPlayedOnce()) {
attacking = false;
upattacking = false;
}
}
if (currentAction == JABBING) {
if (animation.hasPlayed(5)) {
charging = false;
}
cr.y = (int) y - 20;
if (facingRight)
cr.x = (int) x - 15;
else
cr.x = (int) x - 35;
if (facingRight)
waveattack.add(new WaveAttack(tileMap, x + 30, y,
WaveAttack.RIGHT));
else
waveattack.add(new WaveAttack(tileMap, x - 30, y,
WaveAttack.LEFT));
}
for (int i = 0; i < enemies.size(); i++) {
Enemy e = enemies.get(i);
// check attack
if (currentAction == ATTACKING && animation.getFrame() == 3
&& animation.getCount() == 0) {
if (e.intersects(ar)) {
e.hit(damage);
}
}
// check upward attack
if (currentAction == UPATTACKING && animation.getFrame() == 3
&& animation.getCount() == 0) {
if (e.intersects(aur)) {
e.hit(damage);
}
}
// check charging attack
if (currentAction == JABBING) {
if (animation.getCount() == 0) {
if (e.intersects(cr)) {
e.hit(jabDamage);
}
/*
* if(e.intersects(this)) { e.hit(chargeDamage); }
*/
}
}
// collision with enemy
if (!e.isDead() && intersects(e) && !charging) {
hit(e.getDamage());
}
if (e.isDead()) {
// JukeBox.play("explode", 2000);
}
}
// set animation
if (teleporting) {
if (currentAction != TELEPORTING) {
setAnimation(TELEPORTING);
}
} else if (knockback) {
if (currentAction != KNOCKBACK) {
setAnimation(KNOCKBACK);
}
} else if (health == 0) {
if (currentAction != DEAD) {
setAnimation(DEAD);
}
} else if (upattacking) {
if (currentAction != UPATTACKING) {
// JukeBox.play("playerattack");
setAnimation(UPATTACKING);
aur.x = (int) x - 15;
aur.y = (int) y - 50;
} else {
if (animation.getFrame() == 4 && animation.getCount() == 0) {
for (int c = 0; c < 3; c++) {
waveattack.add(new WaveAttack(tileMap, aur.x
+ aur.width / 2, aur.y + 5, WaveAttack.UP));
}
}
}
} else if (attacking) {
if (currentAction != ATTACKING) {
// JukeBox.play("playerattack");
setAnimation(ATTACKING);
ar.y = (int) y - 6;
if (facingRight)
ar.x = (int) x + 10;
else
ar.x = (int) x - 40;
}
} else {
if (animation.getFrame() == 4 && animation.getCount() == 0) {
for (int c = 0; c < 3; c++) {
if (facingRight)
waveattack.add(new WaveAttack(tileMap, ar.x + ar.width
- 4, ar.y + ar.height / 2, WaveAttack.RIGHT));
else
waveattack.add(new WaveAttack(tileMap, ar.x + 4, ar.y
+ ar.height / 2, WaveAttack.LEFT));
}
} else if (charging) {
if (currentAction != JABBING) {
setAnimation(JABBING);
}
} else if (dy < 0) {
if (currentAction != JUMPING) {
setAnimation(JUMPING);
}
} else if (dy > 0) {
if (currentAction != FALLING) {
setAnimation(FALLING);
}
} else if (dashing && (left || right)) {
if (currentAction != DASHING) {
setAnimation(DASHING);
}
} else if (left || right) {
if (currentAction != WALKING) {
setAnimation(WALKING);
}
} else if (currentAction != IDLE) {
setAnimation(IDLE);
}
animation.update();
// set direction
if (!attacking && !upattacking && !charging && !knockback) {
if (right)
facingRight = true;
if (left)
facingRight = false;
}
}
}
public void draw(Graphics2D g) {
// draw emote
if (emote == CONFUSED) {
g.drawImage(confused, (int) (x + xmap - cwidth / 2), (int) (y
+ ymap - 40), null);
} else if (emote == SUPRISED) {
g.drawImage(suprised, (int) (x + xmap - cwidth / 2), (int) (y
+ ymap - 40), null);
}
// draw energy particles
for (int i = 0; i < waveattack.size(); i++) {
waveattack.get(i).draw(g);
}
// flinch
if (flinching && !knockback) {
if (flinchCount % 10 < 5)
return;
}
super.draw(g);
}
}