diff --git a/src/de/miaurizius/jgame2d/core/enums/Direction.java b/src/de/miaurizius/jgame2d/core/enums/Direction.java index d7bd825..09e6e45 100644 --- a/src/de/miaurizius/jgame2d/core/enums/Direction.java +++ b/src/de/miaurizius/jgame2d/core/enums/Direction.java @@ -5,6 +5,14 @@ public enum Direction { UP, DOWN, LEFT, - RIGHT + RIGHT; -} + public Direction getOpposite() { + return switch (this) { + case UP -> DOWN; + case DOWN -> UP; + case LEFT -> RIGHT; + case RIGHT -> LEFT; + }; + } +} \ No newline at end of file diff --git a/src/de/miaurizius/jgame2d/core/handlers/KeyHandler.java b/src/de/miaurizius/jgame2d/core/handlers/KeyHandler.java index 09fbea0..fe21f14 100644 --- a/src/de/miaurizius/jgame2d/core/handlers/KeyHandler.java +++ b/src/de/miaurizius/jgame2d/core/handlers/KeyHandler.java @@ -10,7 +10,7 @@ import java.awt.event.KeyListener; public class KeyHandler implements KeyListener { - public boolean upPressed, downPressed, leftPressed, rightPressed, spacePressed, shotKeyPressed; + public boolean upPressed, downPressed, leftPressed, rightPressed, spacePressed, shotKeyPressed, CTLKeyPressed; public GamePanel panel; public boolean debug; @@ -50,6 +50,7 @@ public class KeyHandler implements KeyListener { case KeyEvent.VK_S, KeyEvent.VK_DOWN -> downPressed = true; case KeyEvent.VK_A, KeyEvent.VK_LEFT -> leftPressed = true; case KeyEvent.VK_D, KeyEvent.VK_RIGHT -> rightPressed = true; + case KeyEvent.VK_CONTROL -> CTLKeyPressed = true; case KeyEvent.VK_SPACE -> spacePressed = true; //case KeyEvent.VK_F -> shotKeyPressed = true; @@ -276,6 +277,7 @@ public class KeyHandler implements KeyListener { case KeyEvent.VK_S, KeyEvent.VK_DOWN -> downPressed = false; case KeyEvent.VK_A, KeyEvent.VK_LEFT -> leftPressed = false; case KeyEvent.VK_D, KeyEvent.VK_RIGHT -> rightPressed = false; + case KeyEvent.VK_CONTROL -> CTLKeyPressed = false; case KeyEvent.VK_F -> shotKeyPressed = false; } } diff --git a/src/de/miaurizius/jgame2d/entity/Entity.java b/src/de/miaurizius/jgame2d/entity/Entity.java index 9e79a19..8e6801b 100644 --- a/src/de/miaurizius/jgame2d/entity/Entity.java +++ b/src/de/miaurizius/jgame2d/entity/Entity.java @@ -23,6 +23,7 @@ public class Entity { protected GamePanel panel; public BufferedImage up1, up2, down1, down2, left1, left2, right1, right2; public BufferedImage attackUp1, attackUp2, attackDown1, attackDown2, attackLeft1, attackLeft2, attackRight1, attackRight2; + public BufferedImage guardUp, guardDown, guardLeft, guardRight; public BufferedImage image, image2, image3; public Rectangle solidArea = new Rectangle(0, 0, 48, 48); public Rectangle attackArea = new Rectangle(0, 0, 0, 0); @@ -38,6 +39,7 @@ public class Entity { int dialogueIndex; public boolean collisionOn; public boolean invincible; + public boolean transparent; public boolean attacking; public boolean alive = true; public boolean dying; @@ -45,6 +47,7 @@ public class Entity { public boolean consumable; public boolean onPath; public boolean knockback; + public boolean guarding; public Direction knockbackDirection; // COUNTER @@ -181,16 +184,16 @@ public class Entity { if(invincible) { hpBarOn = true; hpBarCount = 0; - changeOpacity(graphics2d, 0.4f); + if(transparent) changeOpacity(graphics2d, 0.4f); } if(dying) dyingAnimation(graphics2d); if(type == EntityType.PLAYER || name.equals("orc")) { // only modify sprite render position for player because I dont know yet how monster attack sprite are gonna look if(attacking) graphics2d.drawImage(parseSpriteATK(), (direction == Direction.LEFT) ? screenX - panel.tileSize : screenX, (direction == Direction.UP) ? screenY - panel.tileSize : screenY, null); + else if(guarding) graphics2d.drawImage(parseSpriteGRD(), screenX, screenY, null); else graphics2d.drawImage(parseSprite(), screenX, screenY, null); } else graphics2d.drawImage(parseSprite(), screenX, screenY, null); - changeOpacity(graphics2d, 1f); } @@ -247,11 +250,18 @@ public class Entity { } public void damagePlayer(int attack) { if(panel.player.invincible) return; - panel.playSE(6); + boolean block = panel.player.guarding && panel.player.direction == this.direction.getOpposite(); int damage = attack - panel.player.defense; - panel.player.life -= Math.max(damage, 0); + if(block) { + panel.playSE(15); + damage = 0; + } else panel.playSE(6); + + panel.player.life -= Math.max(damage, (block ? 0 : 1)); + + if(damage != 0) panel.player.transparent = true; panel.player.invincible = true; } public void speak() { @@ -427,6 +437,14 @@ public class Entity { case RIGHT -> (spriteNum == 1) ? attackRight1 : attackRight2; }; } + BufferedImage parseSpriteGRD() { + return switch (direction) { + case UP -> guardUp; + case DOWN -> guardDown; + case LEFT -> guardLeft; + case RIGHT -> guardRight; + }; + } public BufferedImage initEntitySprites(String name) { try { return Utility.scaleImage(ImageIO.read(new FileInputStream("assets/" + name + ".png")), panel.tileSize, panel.tileSize); diff --git a/src/de/miaurizius/jgame2d/entity/Player.java b/src/de/miaurizius/jgame2d/entity/Player.java index a035d4b..f07d69c 100644 --- a/src/de/miaurizius/jgame2d/entity/Player.java +++ b/src/de/miaurizius/jgame2d/entity/Player.java @@ -18,6 +18,7 @@ public class Player extends Entity { KeyHandler keyH; public final int screenX; public final int screenY; + private int standCount; // STATE public boolean attackCancel; @@ -44,16 +45,25 @@ public class Player extends Entity { setDefaultValues(); getPlayerImage(); getPlayerAttackImage(); + getGuardImages(); } // DEFAULT public void update() { if(life > maxLife) life = maxLife; + // ATTACKING if(attacking) { attacking(); return; } + + // BLOCKING + if(keyH.CTLKeyPressed) { + guarding = true; + return; + } + // MOVEMENT if(keyH.upPressed || keyH.downPressed || keyH.leftPressed || keyH.rightPressed || keyH.spacePressed) { if(!keyH.spacePressed) { @@ -102,6 +112,7 @@ public class Player extends Entity { attackCancel = false; panel.keyH.spacePressed = false; + guarding = false; spriteCount++; if(spriteCount > 12) { @@ -110,6 +121,13 @@ public class Player extends Entity { else spriteNum = 0; spriteCount = 0; } + } else { + standCount++; + if(standCount == 20) { + spriteNum = 1; + standCount = 0; + } + guarding = false; } if(panel.keyH.shotKeyPressed && !projectile.alive) { @@ -123,6 +141,7 @@ public class Player extends Entity { invincibleCount++; if(invincibleCount > 60) { invincible = false; + transparent = false; invincibleCount = 0; } @@ -169,11 +188,10 @@ public class Player extends Entity { int damage = panel.monster[panel.currentMap.getIndex()][index].attack - defense; - if(damage > 0) { - panel.playSE(6); - life -= damage; - invincible = true; - } + panel.playSE(6); + life -= Math.max(damage, 0); + if(damage != 0) panel.player.transparent = true; + invincible = true; } public void damageMonster(int index, Entity attacker, int attack, int knockbackVal) { @@ -347,6 +365,12 @@ public class Player extends Entity { break; } } + public void getGuardImages() { + guardUp = initEntitySprites("player/guarding/boy_guard_up"); + guardDown = initEntitySprites("player/guarding/boy_guard_down"); + guardLeft = initEntitySprites("player/guarding/boy_guard_left"); + guardRight = initEntitySprites("player/guarding/boy_guard_right"); + } public int searchItemInInventory(String itemName) { for(int i = 0; i < inventory.size(); i++) { if(inventory.get(i).name.equals(itemName)) {