I'm developing a 2D game in Java using Java Swing, and I've run into an issue with my player character's attack animation. The player has both movement and attack animations:
Movement sprites: 16x16 pixels Attack sprites: 80x80 pixels The movement animations work perfectly, and the player displays at the correct size. However, when I trigger the attack animation, the player sprite becomes very small, even though the attack sprites are larger than the movement sprites. The player goes through the complete axe attack animation however he becomes extremely small during the animation. Any insight would be greatly appreciated thanks !
Here's the relevant code from my Player class: package entity;
import java.awt.Graphics2D; import java.awt.Image; import java.awt.Rectangle; import java.awt.image.BufferedImage; import java.io.IOException; import javax.imageio.ImageIO; import main.GamePanel; import main.KeyHandler; import object.Axe_Object; import object.SuperObject; public class Player extends Entity{ public BufferedImage spriteSheet; public BufferedImage spriteSheetAxe; GamePanel gp; KeyHandler keyH; public int screenX; public int screenY; public SuperObject currentWeapon; // Player inventory and Game Mechanics private Inventory inventory; // Arrays to hold animation frames for each direction public BufferedImage[] upFrames = new BufferedImage[8]; public BufferedImage[] downFrames = new BufferedImage[8]; public BufferedImage[] leftFrames = new BufferedImage[8]; public BufferedImage[] rightFrames = new BufferedImage[8]; // Arrays to hold attacks animations public BufferedImage[] upAxeFrames = new BufferedImage[12]; public BufferedImage[] downAxeFrames = new BufferedImage[12]; public BufferedImage[] leftAxeFrames = new BufferedImage[12]; public BufferedImage[] rightAxeFrames = new BufferedImage[6]; private int frameIndex = 0; // To track the current frame private int frameCounter = 0; // control fame rate of animation private int frameDelay = 5; // How many game loops before switching frame public int numberOfKeys = 0; public Player(GamePanel gp, KeyHandler keyH) { this.gp = gp; this.keyH = keyH; screenX = gp.screenWidth / 2 - (gp.tileSize / 2); screenY = gp.screenHeight / 2 - (gp.tileSize / 2); solidArea = new Rectangle(8, 16, 16, 16); // x, y, width, height solidAreaDefaultX = solidArea.x; solidAreaDefaultY = solidArea.y; inventory = new Inventory(); setDefaultValues(); loadSpriteSheet(); loadPlayerImages(); loadPlayerAxeAttackImages(); } private void loadSpriteSheet() { try { spriteSheet = ImageIO.read(getClass().getResourceAsStream("/player/walk.png")); spriteSheetAxe = ImageIO.read(getClass().getResourceAsStream("/player/axesprite.png")); } catch (IOException e) { System.out.println("There was an error in loading the spritesheet"); e.printStackTrace(); } } private void loadPlayerImages() { int x = 3; int upY = 18; int downY = 13; int rightY = 3; int leftY = 8; for (int i = 0; i < 8; i++) { upFrames[i] = grabImage(x, upY, gp.originalTileSize, gp.originalTileSize); downFrames[i] = grabImage(x, downY, gp.originalTileSize, gp.originalTileSize); rightFrames[i] = grabImage(x, rightY, gp.originalTileSize, gp.originalTileSize); leftFrames[i] = grabImage(x, leftY, gp.originalTileSize, gp.originalTileSize); x += 5; } } // THIS IS THE PART CAUSING PROBLEMS private void loadPlayerAxeAttackImages() { int x = 3; int upY = 18; int downY = 13; int rightY = 3; int leftY = 8; // Load all up frames images for right swing rightAxeFrames[0] = grabImageAxeAttack(1, 1, 80, 80 ); rightAxeFrames[1] = grabImageAxeAttack(2, 1, 80, 80 ); rightAxeFrames[2] = grabImageAxeAttack(3, 1, 80, 80 ); rightAxeFrames[3] = grabImageAxeAttack(4, 1, 80, 80); rightAxeFrames[4] = grabImageAxeAttack(5, 1, 80, 80 ); rightAxeFrames[5] = grabImageAxeAttack(6, 1, 80, 80 ); } public void setDefaultValues() { worldX = gp.tileSize * 10; worldY = gp.tileSize * 10; speed = 7; direction = "down"; // PLAYER STATUS level = 1; maxNumberOfHP = 6; currentHp = maxNumberOfHP ; strength = 1; // The more strenght he has, the more damage he gives. dexterity = 1; // The more dexterity he has, the less damage he receives. attack = 4; defense = 1; exp = 0; nextLevelExp = 5; coin = 0; currentWeapon = new Axe_Object(); } public BufferedImage grabImage(int col, int row, int width, int height) { int x = (col * 16) - 16; int y = (row * 16) - 16; //System.out.printf("X coordinates: " + x + ", Y coordinates:", y); //System.out.println("Width: " + width + ", Height: " + height); return spriteSheet.getSubimage(x, y, width, height); } public BufferedImage grabImageAxeAttack(int col, int row, int width, int height) { int x = (col * 80) - 80; int y = (row * 80) - 80; //System.out.printf("X coordinates: " + x + ", Y coordinates:", y); //System.out.println("Width: " + width + ", Height: " + height); return spriteSheetAxe.getSubimage(x, y, width, height); } public void checkForObject() { for (int i = 0; i < gp.obj.length; i++) { if (gp.obj[i] != null) { if (this.gp.cChecker.objectCollision(this, gp.obj[i])) { // System.out.println("INTERSECTION BETWEEN PLAYER OBJECT"); pickUpObject(gp.obj[i]); // Pick up object if collided gp.obj[i] = null; // Remove object from the map break; } } } } private void pickUpObject(SuperObject obj) { // TODO Auto-generated method stub if (obj != null) { String objName = obj.name; switch (objName) { case "Key": gp.playSoundEffect(1); numberOfKeys++; break; } inventory.addItem(obj); System.out.println(obj.name + " picked up!"); } } public void update() { if (keyH.showInventory == true) { inventory.showInventory(); } if (keyH.upPressed == true || keyH.downPressed == true || keyH.leftPressed == true || keyH.rightPressed == true) { if (keyH.upPressed == true) { direction = "up"; //worldY -= speed; } else if (keyH.downPressed == true) { direction = "down"; //worldY += speed; } else if (keyH.leftPressed == true) { direction = "left"; // worldX -= speed; } else if (keyH.rightPressed == true) { direction = "right"; //worldX += speed; } // Check tile collision collisionOn = false; gp.cChecker.checkTile(this); if (collisionOn == false) { switch(direction) { case "up": worldY -= speed; break; case "down": worldY += speed; break; case "left": worldX -= speed; break; case "right": worldX += speed; break; } } checkForObject(); // Update animation frame if player is moving frameCounter++; if (frameCounter >= frameDelay) { // Pass to next state of animation frameCounter = 0; frameIndex++; if (frameIndex >= 6) { frameIndex = 0; } } } else { frameIndex =0; } } public void draw(Graphics2D g2) { //g2.fillRect(screenX, screenY, gp.tileSize, gp.tileSize); BufferedImage image = null; switch (direction) { case "up": image = upFrames[frameIndex]; if (attack()) { System.out.println("The player just attacked up"); image = upAxeFrames[frameIndex]; } break; case "down": image = downFrames[frameIndex]; if (attack()) { System.out.println("The player just attacked down"); image = downAxeFrames[frameIndex]; } break; case "left": image = leftFrames[frameIndex]; if (attack()) { System.out.println("The player just attacked left"); image = leftAxeFrames[frameIndex]; } break; case "right": image = rightFrames[frameIndex]; if (attack()) { System.out.println("The player just attacked right"); image = rightAxeFrames[frameIndex]; } break; } g2.drawImage(image, screenX, screenY, gp.tileSize, gp.tileSize, null); } @Override public boolean attack() { // TODO Auto-generated method stub if (keyH.weaponAttack) { return true; } return false; } }