I've switched from KeyListeners to KeyBindings as instructed, however they still seem to do nothing. My keybinds are set up as to allow the left and right arrow keys to call a setDx() method in paddle.java which instructs the move() method to move the paddle.
gamePanel.java:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class gamePanel extends JPanel implements ActionListener {
paddle Paddle;
boolean ingame = true;
int delay = 1000;
Timer timer;
JLabel text = new JLabel("stuff here");
InputMap im = this.getInputMap(JPanel.WHEN_IN_FOCUSED_WINDOW);
ActionMap am = this.getActionMap();
public gamePanel() {
setBackground(Color.WHITE);
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), "RightArrow");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), "LeftArrow");
add(text);
text.setBounds(100, 100, 200, 300);
timer = new Timer(delay, this);
Paddle = new paddle();
timer.start();
}
#Override
public void paint(Graphics g) {
super.paint(g);
if (ingame) {
g.drawImage(Paddle.getImage(), Paddle.getX(), Paddle.getY(),
Paddle.getWidth(), Paddle.getHeight(), this);
}
}
#Override
public void actionPerformed(ActionEvent ae) {
Object obj = ae.getSource();
if (obj == timer) {
Paddle.move();
validate();
repaint();
}
}
public class ArrowAction extends AbstractAction {
private String cmd;
public ArrowAction(String cmd) {
this.cmd = cmd;
}
#Override
public void actionPerformed(ActionEvent e) {
if (cmd.equalsIgnoreCase("LeftArrow")) {
Paddle.setDx(-20);
} else if (cmd.equalsIgnoreCase("RightArrow")) {
Paddle.setDx(20);
}
}
}
/*
#Override
public void keyPressed(KeyEvent ke) {
int KeyCode = ke.getKeyCode();
if (KeyCode == KeyEvent.VK_LEFT) {
text.setText("key pressed");
Paddle.setDx(-20);
}
if (KeyCode == KeyEvent.VK_RIGHT) {
Paddle.setDx(20);
}
}
#Override
public void keyReleased(KeyEvent ke) {
int KeyCode = ke.getKeyCode();
if (KeyCode == KeyEvent.VK_LEFT) {
Paddle.setDx(0);
}
if (KeyCode == KeyEvent.VK_RIGHT) {
Paddle.setDx(0);
}
}
#Override
public void keyTyped(KeyEvent ke) {
}
*/
}
Paddle.java:
import java.awt.Image;
import java.awt.Rectangle;
import javax.swing.ImageIcon;
public class paddle {
int dx = 0;
int x, y;
int height, width;
Image image;
public paddle() {
ImageIcon ii = new ImageIcon("src/Paddle.png");
image = ii.getImage();
width = image.getWidth(null);
height = image.getHeight(null);
//dx = 20;
resetState();
}
public void setDx(int z) {
dx = z;
}
public void move() {
x += dx;
if (x <= 2) {
x = 2;
}
if (x >= (640 - getWidth())) {
x = (640 - getWidth());
}
}
public void resetState() {
x = 250;
y = 375;
}
public void setX(int x) {
this.x = x;
}
public int getX() {
return x;
}
public void setY(int y) {
this.y = y;
}
public int getY() {
return y;
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
Image getImage() {
return image;
}
Rectangle getRect() {
return new Rectangle(x, y, image.getWidth(null), image.getHeight(null));
}
}
If your KeyListener methods are not being called I suspect it's because the correct component does not have focus. It's difficult sometimes to manage what component has focus especially in a game, so I would suggest switching over to using key bindings which doesn't require components to have focus.
You never add the corresponding actions you the ActionMap
am.put("LeftArrow", new ArrowAction("LeftArrow"));
am.put("RightArrow", new ArrowAction("RightArrow"));
Also, if you don't repaint() in the actioPerformed of the ArrowAction, you won't see it update immediately, until repaint() is called by the Timer, which isn't very long, but still a miniscule delay.
Related
I'm making a top-down shooter game in java where I have a stationary player who can turn side to side and can shoot a gun at enemies that move to the center(where the player is). I have made different faces for each side when my player turns, but I'm not able to figure out how to switch the faces when I use the arrow keys. Here is my main panel:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
public class FinalPanel extends JPanel
{
private static final int FRAME = 1600;
private static final Color BACKGROUND = new Color(255, 255, 255);
private Player player;
private ImageIcon faces;
private ImageIcon playerFace = new ImageIcon("PlayerUpImage.png");
private BufferedImage myImage;
private Graphics myBuffer;
private Timer timer;
public FinalPanel()
{
myImage = new BufferedImage(FRAME, FRAME, BufferedImage.TYPE_INT_RGB);
myBuffer = myImage.getGraphics();
addKeyListener(new Key());
setFocusable(true);
}
private class Listener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
ImageIcon player = new ImageIcon("PlayerUpImage.png");
myBuffer.drawImage(player.getImage(), 800, 800, null);
repaint();
}
}
public void paintComponent(Graphics g)
{
super.paintComponenet(g);
g.drawImage(myImage, 0, 0, getWidth(), getHeight(), null);
}
private class Key extends KeyAdapter//The arrow keys make the player change directions and it replaces his face with a different animation to show the change in direction
{
public void keyPressed(KeyEvent e)
{
if(e.getKeyCode() == KeyEvent.VK_W)
{
playerFace = new ImageIcon("PlayerUpImage.png");
}
if(e.getKeyCode() == KeyEvent.VK_S)
{
playerFace = new ImageIcon("PlayerDownImage.png");
}
if(e.getKeyCode() == KeyEvent.VK_A)
{
playerFace = new ImageIcon("PlayerLeftImage.png");
}
if(e.getKeyCode() == KeyEvent.VK_D)
{
playerFace = new ImageIcon("PlayerRightImage.png");
}
repaint();
}
}
}
Player class:
import java.awt.*;
import javax.swing.*;
public class Player
{
//Private fields for player class
private int myX;
private int myY;
private int myXWidth;
private int myYWidth;
public Player()
{
myX = 775;
myY = 775;
myXWidth = 50;
myYWidth = 50;
}
public Player(int x, int y, int xWidth, int yWidth)
{
myX = x;
myY = y;
myXWidth = xWidth;
myYWidth = yWidth;
}
//I borrowed this health code from: https://stackoverflow.com/questions/9834609/how-to-make-a-player-class-that-holds-lives-inheritance//
int liveCount = 10;
public boolean damage() {
--liveCount;
return isDead();
}
public boolean isDead() {
return liveCount < 1;
}
public void boostLives(int moreLives) {
liveCount += moreLives;
}
//Accessor Methods//
public int getX()
{
return myX;
}
public int getY()
{
return myY;
}
public int getXWidth()
{
return myXWidth;
}
public int getYWidth()
{
return myYWidth;
}
//Modifier Methods//
public void setX(int x)
{
myX = x;
}
public void setY(int y)
{
myY = y;
}
public void setXWidth(int xWidth)
{
myXWidth = xWidth;
}
public void setYWidth(int yWidth)
{
myYWidth = yWidth;
}
}
I have some suggestions that might help:
Don’t use the variable faces, instead, have an ImageIcon called playerFace with a default direction of up
private ImageIcon playerFace = new ImageIcon(“PlayerUpImage.png”);
Your paint method could then look like this
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(playerFace.getImage(), 800, 800, null);
}
In your keyPressed method, all you have to do is change the player image and call the method repaint so that the panel calls the paintComponent method again:
public void keyPressed(KeyEvent e) {
//pressed d for example
if(e.getKeyCode() == KeyEvent.VK_D)
playerFace = new ImageIcon(“PlayerImageRight.png”);
... //if else’s for other keys
repaint();
}
Preferably, you’d want to have playerFaces as an attribute of the Player class with a getter method to get the playerFace direction (so making playerFace a variable of Player). But this is to get you started
You’ll also want to set up a frame instead of using your current variable FRAME
public FinalPanel() {
JFrame frame = new JFrame();
frame.setSize(1600, 1600);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(this);
frame.setVisible(true);
addKeyListener(new Key());
setFocusable(true);
}
When I run this code, the square is responding so slow, like the program was running on 2 fps. Can you tell me why is it so slow and how can i make it run faster? Additionally I'll say that I used to code in pygame (python) and there was a system that allowed me to set FPS, but i can't find anything like this in java if you could show me how to set FPS I would be grateful.
Thanks for answering.
package World;
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferStrategy;
public class Map {
private final String title = "The Lord of the Dungeon";
private final int width = 1600;
private final int height = width / 16 * 9;
private Player player = new Player(width / 2, height / 2, 50);
//class Player contains only: int x, int y, int width, int height
public Map () {
//generate map
}
public void draw () {
boolean running = true;
//Creating the frame.
JFrame frame = new JFrame(title);
frame.setSize(width, height);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setResizable(false);
frame.setVisible(true);
//Creating the canvas.
Canvas canvas = new Canvas();
canvas.setSize(width, height);
canvas.setBackground(Color.BLACK);
canvas.setVisible(true);
frame.add(canvas);
canvas.addKeyListener(new KeyListener() {
#Override
public void keyTyped(KeyEvent keyEvent) {
}
#Override
public void keyPressed(KeyEvent keyEvent) {
int keyCode = keyEvent.getKeyCode();
if (keyCode == KeyEvent.VK_W) {
player.setY(player.getY() - 10);
}
else if (keyCode == KeyEvent.VK_A) {
player.setX(player.getX() - 10);
}
else if (keyCode == KeyEvent.VK_S) {
player.setY(player.getY() + 10);
}
else if (keyCode == KeyEvent.VK_D) {
player.setX(player.getX() + 10);
}
}
#Override
public void keyReleased(KeyEvent keyEvent) {
}
});
canvas.addMouseListener(new MouseListener() {
#Override
public void mouseClicked(MouseEvent mouseEvent) {
}
#Override
public void mousePressed(MouseEvent mouseEvent) {
int mouseCode = mouseEvent.getButton();
if (mouseCode == 1) {
System.out.println("1");
}
}
#Override
public void mouseReleased(MouseEvent mouseEvent) {
}
#Override
public void mouseEntered(MouseEvent mouseEvent) {
}
#Override
public void mouseExited(MouseEvent mouseEvent) {
}
});
canvas.createBufferStrategy(3);
BufferStrategy bufferStrategy;
Graphics graphics;
while (running) {
bufferStrategy = canvas.getBufferStrategy();
graphics = bufferStrategy.getDrawGraphics();
graphics.clearRect(0, 0, width, height);
graphics.fillRect(player.getX(), player.getY(), player.getWidth(), player.getHeight());
bufferStrategy.show();
graphics.dispose();
}
}
}
here is Player class:
public class Player {
private int x;
private int y;
private int width;
private int height;
public Player (int x, int y, int width) {
this.x = x;
this.y = y;
this.width = width;
this.height = width / 9 * 16;
}
public int getX () {
return this.x;
}
public int getY () {
return this.y;
}
public int getWidth () {
return this.width;
}
public int getHeight () {
return this.height;
}
public void setX (int newX) {
this.x = newX;
}
public void setY (int newY) {
this.y = newY;
}
public void setWidth (int newWidth) {
this.width = newWidth;
this.height = newWidth / 9 * 16;
}
}
This question already has answers here:
How to use Key Bindings instead of Key Listeners
(4 answers)
Closed 5 years ago.
When VK_UP or VK_DOWN is pressed the Graphic g I created is not changing its position whatsoever. If someone could look and see if there is something wrong with my move method etc. Would really appreciate it.
Here is all my code so far:
package ping2;
import java.applet.Applet;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
public class Ping2 extends Applet implements Runnable, KeyListener{
final int WIDTH = 700, HEIGHT = 500;
Thread thread;
UserPaddle user1;
public void init() {
this.resize(WIDTH, HEIGHT);
this.addKeyListener(this);
user1 = new UserPaddle(1);
thread = new Thread(this);
thread.start();
}
public void paint(Graphics g) {
g.setColor(Color.black);
g.fillRect(0, 0, WIDTH, HEIGHT);
user1.draw(g);
}
public void update(Graphics g) {
paint(g);
}
public void run() {
for(;;) {
user1.move();
repaint();
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void keyPressed(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_UP) {
user1.setUpAccel(true);
}
else if(e.getKeyCode() == KeyEvent.VK_DOWN) {
user1.setDownAccel(true);
}
}
public void keyReleased(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_UP) {
user1.setUpAccel(false);
}
else if(e.getKeyCode() == KeyEvent.VK_DOWN) {
user1.setDownAccel(false);
}
}
public void keyTyped(KeyEvent arg0) {
}
}
package ping2;
import java.awt.*;
public class UserPaddle implements InterfaceBar{
double y, yVelocity;
boolean upAccel, downAccel;
int player1, x;
final double FRICTION = 0.90;
public UserPaddle(int player1) {
upAccel = false;
downAccel = false;
y = 210;
yVelocity = 0;
if(player1 == 1)
x = 20;
else
x = 660;
}
public void draw(Graphics g) {
g.setColor(Color.white);
g.fillRect(x, (int)y, 20, 80);
}
public void move() {
if(upAccel) {
yVelocity -= 2;
}else if(downAccel) {
yVelocity += 2;
}
//Automatically slows bar down if key not being pressed.
else if(!upAccel && !downAccel) {
yVelocity *= FRICTION;
}
}
public void setUpAccel(boolean input) {
upAccel = input;
}
public void setDownAccel(boolean input) {
downAccel = input;
}
public int getY() {
return (int)y;
}
}
package ping2;
import java.awt.Graphics;
public interface InterfaceBar {
public void draw(Graphics g);
public void move();
public int getY();
}
I have modified your move() a bit give it a try
move()
public void move() {
if(upAccel) {
yVelocity -= 2;
y = yVelocity;
}else if(downAccel) {
yVelocity += 2;
y = yVelocity;
}
}
I am having a problem with a stuck sprite as soon as I switch to another JPanel via CardLayout.
import java.awt.CardLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Game extends JFrame implements Runnable {
private viewA v1;
private viewB v2;
private viewC v3;
private viewD v4;
private Player player;
private CardLayout c1;
private JPanel contPanel;
// ############## VIEW A BUTTONLISTENER
public class ViewAButtonList implements ActionListener{
public void actionPerformed(ActionEvent ev){
try{
c1.show(contPanel, "1");
} catch (Exception ex){
ex.printStackTrace();
}
}
}
// ############## VIEW B BUTTON LISTENER
public class ViewBButtonList implements ActionListener{
public void actionPerformed(ActionEvent ev){
try{
c1.show(contPanel, "2");
} catch (Exception ex){
ex.printStackTrace();
}
}
}
// ############## VIEWC BUTTON ACTIONEVENT
public class ViewCButtonList implements ActionListener{
public void actionPerformed(ActionEvent ev){
try{
c1.show(contPanel, "3");
} catch (Exception ex){
ex.printStackTrace();
}
}
}
// ############## VIEW D BUTTON ACTION EVENT
public class ViewDButtonList implements ActionListener{
public void actionPerformed(ActionEvent ev){
try{
c1.show(contPanel, "4");
} catch (Exception ex){
ex.printStackTrace();
}
}
}
public Game() {
player = new Player();
// load player settings from server
// ..
// contPanel = new JPanel();
//load views v1 = new ViewA(Player); v2=new ViewB(Player); v3 = new ViewC(Player); v4 =new ViewD(Player);
c1 = new CardLayout();
contPanel.setLayout(c1);
contPanel.add(v1,"1");
contPanel.add(v2,"2");
contPanel.add(v3"3");
contPanel.add(v4,"4");
c1.show(contPanel, "2");
currPos =2;
this.add(contPanel);
setSize(652, 480);
setLocationRelativeTo(null);
setTitle("GAME");
setResizable(false);
setVisible(true);//go to end of view B (x=0), change to View A, close view B
// Create 4 of each button to place in each seperate view (to swtich back and forth)
// ................
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
new Game();
}
});
}
#Override public void run() { // TODO Auto-generated method stub
} }
Now.. everything works from the standpoint of switching between screens.. but my Player sprite gets stuck on screen after switch, but on initial load I can move the sprite around with the arrow keys. I am not sure if passing the Player on the new ViewA(Player) might be the culprit.. but I have a feeling that it is.. can't figure out what I am doing wrong..
Here's theplayer:
import java.awt.Image; import java.awt.Rectangle; import
java.awt.event.KeyEvent;
import java.util.ArrayList;
import javax.swing.ImageIcon;
public class Player {
private String playersprite = "playersprite.png";
private int dx;
private int dy;
private int x;
private int y;
private int width;
private int height;
private boolean isFired;
private boolean visible;
private Image image;
private ArrayList missiles;
public Player() {
ImageIcon ii = new ImageIcon(this.getClass().getResource(playersprite));
image = ii.getImage();
width = image.getWidth(null);
height = image.getHeight(null);
missiles = new ArrayList();
visible = true;
isFired=false;
//default spawn location
x = 600;
y = 400;
}
public void move() {
x += dx;
y += dy;
if(x<=0){x=0;} if(x>=640-20){x=640-20;} if(y<=0){y=0;}
if(y>=400){y=400;}
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public void setX(int x){
this.x=x;
}
public void setY(int y){
this.y=y;
}
public Image getImage() {
return image;
}
public ArrayList getMissiles() {
return missiles;
}
public void setVisible(boolean visible) {
this.visible = visible;
}
public boolean isVisible() {
return visible;
}
public Rectangle getBounds() {
return new Rectangle(x, y, 32, 32);
}
public void keyPressed(KeyEvent e) {
System.out.println("X: "+x+",Y: "+y);
int key = e.getKeyCode();
if (key == KeyEvent.VK_SPACE) {
if(isFired==false){
isFired=true;
fire();
} else return;
}
if (key == KeyEvent.VK_LEFT) {
dx = -2;
}
if (key == KeyEvent.VK_RIGHT) {
dx = 2;
}
if (key == KeyEvent.VK_UP) {
dy = -2;
}
if (key == KeyEvent.VK_DOWN) {
dy = 2;
}
}
public void fire() {
System.out.println("Player used weapon");
// missiles.add(new Missile(x, y));
}
public void keyReleased(KeyEvent e) {
int key = e.getKeyCode();
if (key == KeyEvent.VK_LEFT) {
dx = 0;
}
if (key == KeyEvent.VK_RIGHT) {
dx = 0;
}
if (key == KeyEvent.VK_UP) {
dy = 0;
}
if (key == KeyEvent.VK_DOWN) {
dy = 0;
}
if (key == KeyEvent.VK_SPACE) {
isFired=false;
}
} }
KeyListener require that the component they are registered are focusable AND have focus, this means that when you click something like a JButton focus moves to the button and the component with a KeyListener no longer has keyboard focus and therefore will no longer receive key events.
Instead, it is recommended that you use Key Bindings as this API has the capacity to overcome these limitations
I am supposed to make a little game simulation. in this game there are three button . when user click start tank and car will close each other in 90 degrees when user click shut button tank will throw bullet to car.
i made and a simulation for this. tank throw bullet to car but when bullet crash car i couldn't this. i just need increase score of how many times tank hit car.
here is the source code
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.JPanel;
public class Vehicle extends Thread {
private JPanel box;
private int XSIZE;
private int YSIZE;
private int time;
private int x;
private int y;
private int dx = 5;
private int dy = 5;
private int dim;
public Vehicle(JPanel b, int i) {
box = b;
this.dim = i;
if (i == 0) {
x = 0;
y = 100;
time = 1000;
XSIZE = 9;
YSIZE = 20;
} else {
time = 200;
y = box.getSize().height;
x = box.getSize().width / 2;
XSIZE = 6;
YSIZE = 10;
}
}
public void draw() {
Graphics g = box.getGraphics();
g.fillOval(x, y, XSIZE, YSIZE);
g.dispose();
}
public void moveHorizontal() {
if (!box.isVisible())
return;
Graphics g = box.getGraphics();
g.setColor(Color.BLUE);
g.setXORMode(box.getBackground());
g.fillOval(x, y, XSIZE, YSIZE);
x += dx;
Dimension d = box.getSize();
if (x < 0) {
x = 0;
dx = -dx;
}
if (x + XSIZE >= d.width) {
x = d.width - XSIZE;
dx = -dx;
}
g.fillOval(x, y, XSIZE, YSIZE);
g.dispose();
}
public JPanel getBox() {
return box;
}
public void setBox(JPanel box) {
this.box = box;
}
public void moveVertical() {
if (!box.isVisible())
return;
Graphics g = box.getGraphics();
g.setXORMode(box.getBackground());
g.fillOval(x, y, XSIZE, YSIZE);
y += dy;
Dimension d = box.getSize();
if (y < 0) {
y = 0;
dy = -dy;
}
if (y + YSIZE >= d.height) {
y = d.height - YSIZE;
dy = -dy;
}
g.fillOval(x, y, XSIZE, YSIZE);
g.dispose();
}
public void move(int i) {
if (i == 0) {
moveHorizontal();
} else {
moveVertical();
}
}
public int getYSIZE() {
return YSIZE;
}
public void setYSIZE(int ySIZE) {
YSIZE = ySIZE;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public int getXSIZE() {
return XSIZE;
}
public void setXSIZE(int xSIZE) {
XSIZE = xSIZE;
}
public void setY(int y) {
this.y = y;
}
public void run() {
try {
draw();
for (;;) {
move(dim);
sleep(time);
}
} catch (InterruptedException e) {
}
}
}
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.JPanel;
public class Bullet extends Thread {
private JPanel box;
private int XSIZE = 3;
public int getXSIZE() {
return XSIZE;
}
public void setXSIZE(int xSIZE) {
XSIZE = xSIZE;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
private int YSIZE = 1;
private int x;
private int y;
private int dx = 3;
public Bullet(JPanel b, Vehicle tank, Vehicle car) {
box = b;
x = tank.getX() + tank.getXSIZE();
if (x >= tank.getBox().getSize().width / 2)
dx = -dx;
y = tank.getY() + tank.getYSIZE() / 2;
;
}
public void draw() {
Graphics g = box.getGraphics();
g.fillOval(x, y, XSIZE, YSIZE);
g.dispose();
}
public void move() {
if (!box.isVisible())
return;
Graphics g = box.getGraphics();
g.setColor(Color.RED);
g.setXORMode(box.getBackground());
g.fillOval(x, y, XSIZE, YSIZE);
x += dx;
Dimension d = box.getSize();
if (x < 0) {
x = 0;
}
if (x + XSIZE >= d.width) {
x = d.width - XSIZE;
}
g.fillOval(x, y, XSIZE, YSIZE);
g.dispose();
}
public void run() {
try {
draw();
for (;;) {
move();
sleep(20);
}
} catch (InterruptedException e) {
}
}
}
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JLabel;
#SuppressWarnings("serial")
public class Tank_Shut_Car_ThreadFrame extends JFrame {
private JPanel canvas;
private boolean isOn = false;
private Vehicle tank;
private Vehicle car;
private JLabel score;
public static int sc = 0;
public Tank_Shut_Car_ThreadFrame() {
setResizable(false);
setSize(600, 400);
setTitle("Tank Shut Car");
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
Container contentPane = getContentPane();
canvas = new JPanel();
contentPane.add(canvas, "Center");
canvas.setLayout(null);
score = new JLabel("0");
score.setBounds(527, 11, 36, 14);
canvas.add(score);
JLabel lblScore = new JLabel("score");
lblScore.setBounds(481, 11, 36, 14);
canvas.add(lblScore);
JPanel p = new JPanel();
addButton(p, "Start", new ActionListener() {
public void actionPerformed(ActionEvent evt) {
if (!isOn) {
tank = new Vehicle(canvas, 0);
tank.start();
car = new Vehicle(canvas, 1);
car.start();
isOn = true;
}
}
});
addButton(p, "Shut", new ActionListener() {
public void actionPerformed(ActionEvent evt) {
if (isOn) {
Bullet bullet = new Bullet(canvas, tank, car);
bullet.start();
score.setText("" + sc);
}
}
});
addButton(p, "Close", new ActionListener() {
public void actionPerformed(ActionEvent evt) {
canvas.setVisible(false);
System.exit(0);
}
});
contentPane.add(p, "South");
}
public void addButton(Container c, String title, ActionListener a) {
JButton button = new JButton(title);
c.add(button);
button.addActionListener(a);
}
}
import javax.swing.JFrame;
public class Test {
public static void main(String[] args) {
JFrame frame = new Tank_Shut_Car_ThreadFrame();
frame.setVisible(true);
}
}
Okay, so I had a play around with this (just for fun)
Now, this is far from a "proper" or "complete" game engine, but it provides a basic idea of how it might be possible to mix a core thread engine with UI components.
Rather then pasting the entire code, I've uploaded the source it to Tank.zip
But the basic engine looks like this...
public class GameEngine extends Thread {
public static final Object ASSET_LOCK = new Object();
private List<GameAsset> lstAssets;
private GameScreen screen;
public GameEngine(GameScreen screen) {
// Let the thread die when the JVM closes
setDaemon(true);
// Want to be below the UI thread (personal preference)
setPriority(NORM_PRIORITY - 1);
// A list of game assests
lstAssets = new ArrayList<GameAsset>(25);
// A reference to the screen
this.screen = screen;
// Add global key listener, this is simpler to the trying to attach a key listener
// to the screen.
Toolkit.getDefaultToolkit().addAWTEventListener(new EventHandler(), AWTEvent.KEY_EVENT_MASK);
}
public GameAsset[] getAssets() {
synchronized (ASSET_LOCK) {
return lstAssets.toArray(new GameAsset[lstAssets.size()]);
}
}
/*
* Allows for assets to be added
*/
public void addAsset(GameAsset asset) {
synchronized (ASSET_LOCK) {
lstAssets.add(asset);
}
}
#Override
public void run() {
while (true) {
try {
sleep(40);
} catch (InterruptedException ex) {
}
synchronized (ASSET_LOCK) {
GameAsset[] assets = lstAssets.toArray(new GameAsset[lstAssets.size()]);
for (GameAsset asset : assets) {
if (lstAssets.contains(asset)) {
asset.update(this, screen);
}
}
screen.repaint(new ArrayList<GameAsset>(lstAssets));
}
}
}
/**
* Allows the removal of an asset...
*/
public void removeAsset(GameAsset asset) {
synchronized (ASSET_LOCK) {
lstAssets.remove(asset);
}
}
/**
* Key event handling...
*/
protected class EventHandler implements AWTEventListener {
#Override
public void eventDispatched(AWTEvent event) {
KeyEvent keyEvent = (KeyEvent) event;
if (keyEvent.getID() == KeyEvent.KEY_PRESSED) {
synchronized (ASSET_LOCK) {
GameAsset[] assets = lstAssets.toArray(new GameAsset[lstAssets.size()]);
for (GameAsset asset : assets) {
if (lstAssets.contains(asset)) {
asset.processKeyPressed(GameEngine.this, screen, keyEvent);
}
}
}
} else if (keyEvent.getID() == KeyEvent.KEY_RELEASED) {
synchronized (ASSET_LOCK) {
GameAsset[] assets = lstAssets.toArray(new GameAsset[lstAssets.size()]);
for (GameAsset asset : lstAssets) {
if (lstAssets.contains(asset)) {
asset.processKeyReleased(GameEngine.this, screen, keyEvent);
}
}
}
}
}
}
}
Swing is not thread safe. Events should be fired on the event-dispatching thread.
http://www.javamex.com/tutorials/threads/invokelater.shtml