I was trying to replicate the Pacman game and I came up with the player animation, then turn around according to where required and open and close the mouth in a loop. I wrote the code, and it works correctly as required. Only that it opens and closes its mouth when I hold down the keys (W, A, S, D) and not always. I don't understand where the mistake is .. This is my code for now:
package playerAnimation;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JPanel;
import javax.swing.Timer;
public class Animation extends JPanel implements ActionListener, KeyListener {
Timer tm = new Timer(1,this);
private String playerDirection="Right";
private int playerX;
private int playerY;
private int playerSpeedX;
private int playerSpeedY;
private int spriteCounter = 0;
private int spriteNum = 1;
public BufferedImage playerUp, playerDown, playerLeft, playerRight, playerClosedMouth;
public BufferedImage imagePlayer = null;
public void getPlayerImage() {
try {
playerUp = ImageIO.read(getClass().getResourceAsStream("/player/imageUp.png"));
playerDown = ImageIO.read(getClass().getResourceAsStream("/player/imageDown.png"));
playerLeft = ImageIO.read(getClass().getResourceAsStream("/player/imageLeft.png"));
playerRight = ImageIO.read(getClass().getResourceAsStream("/player/imageRight.png"));
playerClosedMouth = ImageIO.read(getClass().getResourceAsStream("/player/closed.png"));
}catch(IOException e ) {
e.printStackTrace();
}
}
Timer timer = new Timer(1,this);
public Animation() {
getPlayerImage();
tm.start();
addKeyListener(this);
setFocusable(true);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(imagePlayer,playerX,playerY,null);
}
public void actionPerformed(ActionEvent e) {
playerX=playerX playerSpeedX;
playerY=playerY playerSpeedY;
repaint();
}
public void keyPressed(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_W) {
if(spriteNum==1) {
imagePlayer=playerUp;
}
if(spriteNum==2) {
imagePlayer=playerClosedMouth;
}
playerSpeedX=0;
playerSpeedY=-1;
}
if(e.getKeyCode() == KeyEvent.VK_D) {
if(spriteNum==1) {
imagePlayer=playerRight;
}
if(spriteNum==2) {
imagePlayer=playerClosedMouth;
}
playerSpeedX=1;
playerSpeedY=0;
}
if(e.getKeyCode() == KeyEvent.VK_A) {
if(spriteNum==1) {
imagePlayer=playerLeft;
}
if(spriteNum==2) {
imagePlayer=playerClosedMouth;
}
playerSpeedX=-1;
playerSpeedY=0;
}
if(e.getKeyCode() == KeyEvent.VK_S) {
if(spriteNum==1) {
imagePlayer=playerDown;
}
if(spriteNum==2) {
imagePlayer=playerClosedMouth;
}
playerSpeedX=0;
playerSpeedY=1;
}
spriteCounter ;
if(spriteCounter>10) {
if(spriteNum==1) {
spriteNum=2;
}
else if(spriteNum==2) {
spriteNum=1;
}
spriteCounter=0;
}
}
public void keyTyped(KeyEvent e) {
}
public void keyReleased(KeyEvent e) {
}
}
And the main:
package playerAnimation;
import javax.swing.JFrame;
public class Main {
public static void main(String[] args) {
Animation player = new Animation();
JFrame Window = new JFrame();
Window.setTitle("playerAnimation");
Window.setSize(600,400);
Window.setVisible(true);
Window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Window.add(player);
}
}
Here are the photos:
CodePudding user response:
Welcome to SO. Please read the comments in the code to follow the changes made to display the basic packman player animation.
See the todo comments for more enhancment recommendations:
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.*;
public class Animation extends JPanel implements ActionListener, KeyListener {
private int playerX , playerY, playerSpeedX, playerSpeedY;
private boolean isMouthOpen; //flag to toggle mouth open / closed
private static final Dimension P_SIZE = new Dimension(600,400);
public BufferedImage playerUp, playerDown, playerLeft, playerRight, playerClosedMouth, imagePlayer;
//publicly available images for the MRE
private static final String IMAGE_UP ="https://i.stack.imgur.com/wD64A.png",
IMAGE_DOWN ="https://i.stack.imgur.com/am6PQ.png",
IMAGE_LEFT ="https://i.stack.imgur.com/5Pjqm.png",
IMAGE_RIGHT = "https://i.stack.imgur.com/sVD6m.png",
IMAGE_CLOSED = "https://i.stack.imgur.com/Kkw83.png"
;
public void getPlayerImage() {
try {
playerUp = ImageIO.read(new URL(IMAGE_UP));
playerDown = ImageIO.read(new URL(IMAGE_DOWN));
playerLeft = ImageIO.read(new URL(IMAGE_LEFT));
playerRight = ImageIO.read(new URL(IMAGE_RIGHT));
playerClosedMouth = ImageIO.read(new URL(IMAGE_CLOSED));
}catch(IOException e ) {
e.printStackTrace();
}
}
public Animation() {
getPlayerImage();
//initialize player image, location and speed
imagePlayer = playerRight;
playerX = 100; playerY = 100; playerSpeedX = 1; playerSpeedY = 0;
isMouthOpen = true;
addKeyListener(this);
setFocusable(true);
Timer tm = new Timer(100,this);
tm.start();
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
//if mouth is open - draw mouth closed and vice versa
BufferedImage image = isMouthOpen ? playerClosedMouth : imagePlayer;
g.drawImage(image, playerX, playerY, this);
}
@Override
public void actionPerformed(ActionEvent e) {
checkBounds();
playerX=playerX playerSpeedX;
playerY=playerY playerSpeedY;
isMouthOpen = ! isMouthOpen; //toggle mouth flag
//todo add control parameters to allow toggling mouth at a different rate
repaint();
}
//use key presses to change direction and player image
//todo: use key binding instead of KeyListener
@Override
public void keyPressed(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_W) {
playerSpeedX=0;
playerSpeedY=-1;
imagePlayer=playerUp;
}
if(e.getKeyCode() == KeyEvent.VK_D) {
playerSpeedX=1;
playerSpeedY=0;
imagePlayer=playerRight;
}
if(e.getKeyCode() == KeyEvent.VK_A) {
playerSpeedX=-1;
playerSpeedY=0;
imagePlayer=playerLeft;
}
if(e.getKeyCode() == KeyEvent.VK_S) {
playerSpeedX=0;
playerSpeedY=1;
imagePlayer=playerDown;
}
}
private void checkBounds(){
//todo change direction when player hits bounds
}
@Override
public void keyTyped(KeyEvent e) { }
@Override
public void keyReleased(KeyEvent e) { }
@Override
public Dimension getPreferredSize() {
return P_SIZE;
}
public static void main(String[] args) {
Animation player = new Animation();
JFrame window = new JFrame();
window.setTitle("Player Animation");
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.add(player);
window.pack();
window.setVisible(true);
}
}
CodePudding user response:
The mouth animation only takes place when I hold down the keys
if you want the animation to happen without holding the keys, then the logic to toggle the image needs to move to the Timer ActionListener so it changes at the same time you change the location of the image.
The (untested) logic might look something like:
if(e.getKeyCode() == KeyEvent.VK_W) {
playerOpenMouth = playerUp;
playerSpeedX=0;
playerSpeedY=-1;
}
...
And the logic to toggle the open/closed mouth image in the ActionListener might look something like:
if (openMouth)
imagePlayer = playerOpenMouth;
else
imagePlayer = playerClosedMouth;
openMouth = !openMouth;
playerX = playerX playerSpeedX; // use white space to improve readability
playerY = playerY playerSpeedY;
repaint();
