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