408 lines
15 KiB
Java
408 lines
15 KiB
Java
package de.miaurizius.jgame2d.entity;
|
|
|
|
import de.miaurizius.jgame2d.core.*;
|
|
import de.miaurizius.jgame2d.core.enums.Direction;
|
|
import de.miaurizius.jgame2d.core.enums.EntityType;
|
|
import de.miaurizius.jgame2d.core.enums.GameState;
|
|
import de.miaurizius.jgame2d.core.handlers.KeyHandler;
|
|
import de.miaurizius.jgame2d.entity.item.KeyObj;
|
|
import de.miaurizius.jgame2d.entity.item.ShieldWoodObj;
|
|
import de.miaurizius.jgame2d.entity.item.SwordNormalObj;
|
|
import de.miaurizius.jgame2d.entity.projectile.FireballObj;
|
|
|
|
import java.awt.*;
|
|
|
|
public class Player extends Entity {
|
|
|
|
KeyHandler keyH;
|
|
public final int screenX;
|
|
public final int screenY;
|
|
|
|
// STATE
|
|
public boolean attackCancel;
|
|
public boolean lightUpdated;
|
|
|
|
public Player(GamePanel panel, KeyHandler keyH) {
|
|
super(panel);
|
|
this.keyH = keyH;
|
|
|
|
name = "player";
|
|
type = EntityType.PLAYER;
|
|
|
|
screenX = panel.screenWidth/2 - panel.tileSize/2;
|
|
screenY = panel.screenHeight/2 - panel.tileSize/2;
|
|
|
|
solidArea = new Rectangle();
|
|
solidArea.x = 12;
|
|
solidArea.y = 20;
|
|
solidAreaDefaultX = solidArea.x;
|
|
solidAreaDefaultY = solidArea.y;
|
|
solidArea.width = 24;
|
|
solidArea.height = 24;
|
|
|
|
setDefaultValues();
|
|
getPlayerImage();
|
|
getPlayerAttackImage();
|
|
}
|
|
|
|
// DEFAULT
|
|
public void update() {
|
|
if(life > maxLife) life = maxLife;
|
|
|
|
if(attacking) {
|
|
attacking();
|
|
return;
|
|
}
|
|
// MOVEMENT
|
|
if(keyH.upPressed || keyH.downPressed || keyH.leftPressed || keyH.rightPressed || keyH.spacePressed) {
|
|
if(!keyH.spacePressed) {
|
|
if(keyH.upPressed) direction = Direction.UP;
|
|
else if(keyH.downPressed) direction = Direction.DOWN;
|
|
else if(keyH.leftPressed) direction = Direction.LEFT;
|
|
else direction = Direction.RIGHT;
|
|
}
|
|
|
|
// CHECK TILE COLLISION
|
|
collisionOn = false;
|
|
panel.collisionH.checkTile(this);
|
|
|
|
// CHECK OBJECT COLLISION
|
|
int objIndex = panel.collisionH.checkObject(this, true);
|
|
pickObject(objIndex);
|
|
|
|
// CHECK ENTITY COLLISION
|
|
int npcIndex = panel.collisionH.checkEntity(this, panel.npc[panel.currentMap.getIndex()]);
|
|
interactNPC(npcIndex);
|
|
|
|
// CHECK MONSTER COLLISION
|
|
int monsterIndex = panel.collisionH.checkEntity(this, panel.monster[panel.currentMap.getIndex()]);
|
|
interactMonster(monsterIndex);
|
|
|
|
// CHECK INTERACTIVE TILE COLLISION
|
|
int iTileIndex = panel.collisionH.checkEntity(this, panel.iTile[panel.currentMap.getIndex()]);
|
|
|
|
// CHECK EVENT
|
|
panel.eventH.checkEvent();
|
|
|
|
if(!collisionOn && !keyH.spacePressed) {
|
|
switch (direction) {
|
|
case UP -> worldY -= speed;
|
|
case DOWN -> worldY += speed;
|
|
case LEFT ->worldX -= speed;
|
|
case RIGHT -> worldX += speed;
|
|
}
|
|
}
|
|
|
|
if(keyH.spacePressed && !attackCancel) {
|
|
panel.playSE(7);
|
|
attacking = true;
|
|
spriteCount = 0;
|
|
}
|
|
|
|
attackCancel = false;
|
|
panel.keyH.spacePressed = false;
|
|
|
|
spriteCount++;
|
|
if(spriteCount > 12) {
|
|
if(spriteNum == 1) spriteNum = 2;
|
|
else if(spriteNum == 2) spriteNum = 1;
|
|
else spriteNum = 0;
|
|
spriteCount = 0;
|
|
}
|
|
}
|
|
|
|
if(panel.keyH.shotKeyPressed && !projectile.alive) {
|
|
projectile.set(worldX, worldY, direction, true, this);
|
|
panel.projectileList.add(projectile);
|
|
panel.playSE(10);
|
|
}
|
|
|
|
// INVINCIBLE COUNTER
|
|
if(!invincible) return;
|
|
invincibleCount++;
|
|
if(invincibleCount > 60) {
|
|
invincible = false;
|
|
invincibleCount = 0;
|
|
}
|
|
|
|
if(life <= 0) {
|
|
panel.gameState = GameState.GAMEOVER;
|
|
panel.ui.commandNum = -1;
|
|
panel.stopMusic();
|
|
panel.playSE(12);
|
|
}
|
|
}
|
|
|
|
// INTERACTION
|
|
public void pickObject(int index) {
|
|
if(index == 999 || panel.obj[panel.currentMap.getIndex()][index] == null) return;
|
|
|
|
// PICKUP ONLY ITEMS
|
|
if(panel.obj[panel.currentMap.getIndex()][index].type == EntityType.PICKUP) {
|
|
panel.obj[panel.currentMap.getIndex()][index].use(this);
|
|
panel.obj[panel.currentMap.getIndex()][index] = null;
|
|
return;
|
|
}
|
|
// OBSTACLES
|
|
if(panel.obj[panel.currentMap.getIndex()][index].type == EntityType.OBSTACLE) {
|
|
if(!keyH.spacePressed) return;
|
|
attackCancel = true;
|
|
panel.obj[panel.currentMap.getIndex()][index].interact();
|
|
return;
|
|
}
|
|
// INVENTORY ITEMS
|
|
else {
|
|
if(!canObtainItem(panel.obj[panel.currentMap.getIndex()][index])) {
|
|
panel.ui.addMessage("Your inventory is full!");
|
|
return;
|
|
}
|
|
panel.playSE(1);
|
|
panel.ui.addMessage("Picked up " + panel.obj[panel.currentMap.getIndex()][index].name + "!");
|
|
}
|
|
panel.obj[panel.currentMap.getIndex()][index] = null;
|
|
}
|
|
|
|
public void interactMonster(int index) {
|
|
if(index == 999) return;
|
|
if(invincible || panel.monster[panel.currentMap.getIndex()][index].dying || !panel.monster[panel.currentMap.getIndex()][index].alive) return;
|
|
|
|
int damage = panel.monster[panel.currentMap.getIndex()][index].attack - defense;
|
|
|
|
if(damage > 0) {
|
|
panel.playSE(6);
|
|
life -= damage;
|
|
invincible = true;
|
|
}
|
|
|
|
}
|
|
public void attacking() {
|
|
if(attackCancel) return;
|
|
spriteCount++;
|
|
if(spriteCount <= 5) spriteNum = 1;
|
|
if(spriteCount > 5 && spriteCount <= 25) {
|
|
spriteNum = 2;
|
|
int currentWorldX = worldX;
|
|
int currentWorldY = worldY;
|
|
int solidAreaWidth = solidArea.width;
|
|
int solidAreaHeight = solidArea.height;
|
|
|
|
switch(direction) {
|
|
case UP -> worldY -= attackArea.height;
|
|
case DOWN -> worldY += attackArea.height;
|
|
case LEFT -> worldX -= attackArea.width;
|
|
case RIGHT -> worldX += attackArea.width;
|
|
}
|
|
solidArea.width = attackArea.width;
|
|
solidArea.height = attackArea.height;
|
|
|
|
int monsterIndex = panel.collisionH.checkEntity(this, panel.monster[panel.currentMap.getIndex()]);
|
|
damageMonster(monsterIndex, attack, currentWeapon.knockbackVal);
|
|
|
|
int iTileIndex = panel.collisionH.checkEntity(this, panel.iTile[panel.currentMap.getIndex()]);
|
|
interactTile(iTileIndex);
|
|
|
|
worldX = currentWorldX;
|
|
worldY = currentWorldY;
|
|
solidArea.width = solidAreaWidth;
|
|
solidArea.height = solidAreaHeight;
|
|
|
|
}
|
|
if(spriteCount > 25) {
|
|
spriteNum = 1;
|
|
spriteCount = 0;
|
|
attacking = false;
|
|
}
|
|
}
|
|
public void damageMonster(int index, int attack, int knockbackVal) {
|
|
if(index == 999) return;
|
|
if(panel.monster[panel.currentMap.getIndex()][index].invincible) return;
|
|
|
|
int damage = attack - panel.monster[panel.currentMap.getIndex()][index].defense;
|
|
|
|
if(damage > 0) {
|
|
panel.playSE(5);
|
|
if(knockbackVal > 0) knockback(panel.monster[panel.currentMap.getIndex()][index], knockbackVal);
|
|
panel.monster[panel.currentMap.getIndex()][index].life -= damage;
|
|
panel.monster[panel.currentMap.getIndex()][index].invincible = true;
|
|
}
|
|
|
|
panel.monster[panel.currentMap.getIndex()][index].damageReaction();
|
|
if(panel.monster[panel.currentMap.getIndex()][index].life <= 0) {
|
|
panel.monster[panel.currentMap.getIndex()][index].dying = true;
|
|
panel.ui.addMessage("Gained +" + panel.monster[panel.currentMap.getIndex()][index].exp + " XP!");
|
|
exp += panel.monster[panel.currentMap.getIndex()][index].exp;
|
|
checkLevelUp();
|
|
}
|
|
}
|
|
public void knockback(Entity entity, int knockbackVal) {
|
|
entity.direction = direction;
|
|
entity.speed += knockbackVal;
|
|
entity.knockback = true;
|
|
}
|
|
|
|
public void interactTile(int index) {
|
|
if(index == 999 || !panel.iTile[panel.currentMap.getIndex()][index].destructible || panel.iTile[panel.currentMap.getIndex()][index].invincible) return;
|
|
if(!panel.iTile[panel.currentMap.getIndex()][index].meetItemReq(this)) return;
|
|
panel.iTile[panel.currentMap.getIndex()][index].playSE();
|
|
panel.iTile[panel.currentMap.getIndex()][index].life--;
|
|
panel.iTile[panel.currentMap.getIndex()][index].invincible = true;
|
|
generateParticle(panel.iTile[panel.currentMap.getIndex()][index], panel.iTile[panel.currentMap.getIndex()][index]);
|
|
if(panel.iTile[panel.currentMap.getIndex()][index].life == 0) panel.iTile[panel.currentMap.getIndex()][index] = panel.iTile[panel.currentMap.getIndex()][index].getDestroyedForm();
|
|
}
|
|
|
|
public void interactNPC(int index) {
|
|
if(index == 999) return;
|
|
//if(!panel.keyH.spacePressed) return; //Only uncomment if text should only appear if player hits space
|
|
attackCancel = true;
|
|
panel.gameState = GameState.DIALOGUE;
|
|
panel.npc[panel.currentMap.getIndex()][index].speak();
|
|
}
|
|
public void speak() {
|
|
//This method only exists for character specific things later...
|
|
super.speak();
|
|
}
|
|
|
|
// BACKGROUND JOBS
|
|
public void checkLevelUp() {
|
|
if(exp < nextLevelExp) return;
|
|
level++;
|
|
nextLevelExp = nextLevelExp*2;
|
|
maxLife += 2;
|
|
strength++;
|
|
dexterity++;
|
|
attack = getAttack();
|
|
defense = getDefense();
|
|
panel.playSE(8);
|
|
|
|
panel.gameState = GameState.DIALOGUE;
|
|
panel.ui.currentDialogue = "You are level " + level + " now!\nYou feel stronger!";
|
|
}
|
|
public void selectItem() {
|
|
int itemIndex = panel.ui.getItemIndex(panel.ui.playerSlotCol, panel.ui.playerSlotRow);
|
|
if(itemIndex >= inventory.size()) return;
|
|
Entity selectedItem = inventory.get(itemIndex);
|
|
if(selectedItem.type == EntityType.WEAPON) {
|
|
currentWeapon = selectedItem;
|
|
getAttack();
|
|
getPlayerAttackImage();
|
|
}
|
|
if(selectedItem.type == EntityType.SHIELD) {
|
|
currentShield = selectedItem;
|
|
getDefense();
|
|
}
|
|
if(selectedItem.type == EntityType.LIGHT) {
|
|
if(currentLight == selectedItem) currentLight = null; else currentLight = selectedItem;
|
|
lightUpdated = true;
|
|
}
|
|
if(selectedItem.consumable)
|
|
if(selectedItem.use(this))
|
|
if(selectedItem.amt > 1) selectedItem.amt--; else inventory.remove(selectedItem);
|
|
}
|
|
public void setDefaultPositions() {
|
|
worldX = panel.tileSize * 23;
|
|
worldY = panel.tileSize * 21;
|
|
direction = Direction.DOWN;
|
|
}
|
|
public void restoreLife() {
|
|
life = maxLife;
|
|
invincible = false;
|
|
}
|
|
|
|
// SETTING THINGS UP
|
|
public void setDefaultValues() {
|
|
worldX = panel.tileSize * 23;
|
|
worldY = panel.tileSize * 21;
|
|
|
|
defaultSpeed = 4;
|
|
speed = defaultSpeed;
|
|
direction = Direction.DOWN;
|
|
|
|
// PLAYER STATUS (1 heart = 2 lives)
|
|
maxLife = 6;
|
|
life = maxLife;
|
|
level = 1;
|
|
strength = 1;
|
|
dexterity = 1;
|
|
exp = 0;
|
|
nextLevelExp = 5;
|
|
coins = 500;
|
|
currentWeapon = new SwordNormalObj(panel);
|
|
currentShield = new ShieldWoodObj(panel);
|
|
projectile = new FireballObj(panel);
|
|
attack = getAttack();
|
|
defense = getDefense();
|
|
|
|
// INVENTORY
|
|
inventory.clear();
|
|
inventory.add(currentWeapon);
|
|
inventory.add(currentShield);
|
|
inventory.add(new KeyObj(panel));
|
|
}
|
|
public int getAttack() {
|
|
attackArea = currentWeapon.attackArea;
|
|
return attack = strength * currentWeapon.attackValue;
|
|
}
|
|
public int getDefense() {
|
|
return defense = dexterity * currentShield.defenseValue;
|
|
}
|
|
public void getPlayerImage() {
|
|
up1 = initEntitySprites("player/boy_up_1");
|
|
up2 = initEntitySprites("player/boy_up_2");
|
|
down1 = initEntitySprites("player/boy_down_1");
|
|
down2 = initEntitySprites("player/boy_down_2");
|
|
left1 = initEntitySprites("player/boy_left_1");
|
|
left2 = initEntitySprites("player/boy_left_2");
|
|
right1 = initEntitySprites("player/boy_right_1");
|
|
right2 = initEntitySprites("player/boy_right_2");
|
|
}
|
|
public void getPlayerAttackImage() {
|
|
switch(currentWeapon.weaponType) {
|
|
case SWORD:
|
|
attackUp1 = initEntitySprites("player/attack/boy_attack_up_1", panel.tileSize, panel.tileSize * 2);
|
|
attackUp2 = initEntitySprites("player/attack/boy_attack_up_2", panel.tileSize, panel.tileSize * 2);
|
|
attackDown1 = initEntitySprites("player/attack/boy_attack_down_1", panel.tileSize, panel.tileSize * 2);
|
|
attackDown2 = initEntitySprites("player/attack/boy_attack_down_2", panel.tileSize, panel.tileSize * 2);
|
|
attackLeft1 = initEntitySprites("player/attack/boy_attack_left_1", panel.tileSize * 2, panel.tileSize);
|
|
attackLeft2 = initEntitySprites("player/attack/boy_attack_left_2", panel.tileSize * 2, panel.tileSize);
|
|
attackRight1 = initEntitySprites("player/attack/boy_attack_right_1", panel.tileSize * 2, panel.tileSize);
|
|
attackRight2 = initEntitySprites("player/attack/boy_attack_right_2", panel.tileSize * 2, panel.tileSize);
|
|
break;
|
|
case AXE:
|
|
attackUp1 = initEntitySprites("player/attack/boy_axe_up_1", panel.tileSize, panel.tileSize * 2);
|
|
attackUp2 = initEntitySprites("player/attack/boy_axe_up_2", panel.tileSize, panel.tileSize * 2);
|
|
attackDown1 = initEntitySprites("player/attack/boy_axe_down_1", panel.tileSize, panel.tileSize * 2);
|
|
attackDown2 = initEntitySprites("player/attack/boy_axe_down_2", panel.tileSize, panel.tileSize * 2);
|
|
attackLeft1 = initEntitySprites("player/attack/boy_axe_left_1", panel.tileSize * 2, panel.tileSize);
|
|
attackLeft2 = initEntitySprites("player/attack/boy_axe_left_2", panel.tileSize * 2, panel.tileSize);
|
|
attackRight1 = initEntitySprites("player/attack/boy_axe_right_1", panel.tileSize * 2, panel.tileSize);
|
|
attackRight2 = initEntitySprites("player/attack/boy_axe_right_2", panel.tileSize * 2, panel.tileSize);
|
|
break;
|
|
}
|
|
}
|
|
public int searchItemInInventory(String itemName) {
|
|
for(int i = 0; i < inventory.size(); i++) {
|
|
if(inventory.get(i).name.equals(itemName)) {
|
|
return i;
|
|
}
|
|
}
|
|
return 999;
|
|
}
|
|
public boolean canObtainItem(Entity item) {
|
|
int i = searchItemInInventory(item.name);
|
|
if(item.stackable) {
|
|
if(i != 999) {
|
|
inventory.get(i).amt++;
|
|
return true;
|
|
} else if(inventory.size() != maxInvSize) {
|
|
inventory.add(item);
|
|
return true;
|
|
}
|
|
} else if(inventory.size() != maxInvSize) {
|
|
inventory.add(item);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
}
|