Параллельные методы через многопоточность
Я пытаюсь сделать игру на Java, и я впервые имею дело с многопоточностью (ну, кроме одновременного воспроизведения музыки через класс Clip). У меня есть класс Canvas, расширяющий JPanel, но в классе Canvas у меня также есть класс Canvas. KeyListener для ввода, показано здесь:
private class myKeyListener implements KeyListener
{
public void keyPressed(KeyEvent keyEvent)
{
if(keyEvent.getKeyCode() == KeyEvent.VK_ESCAPE){System.exit (0);}
Thread thread3 = new Thread()
{
public void run() {
if(keyEvent.getKeyCode() == KeyEvent.VK_RIGHT){moveX(5, player1);}
if(keyEvent.getKeyCode() == KeyEvent.VK_LEFT){moveX(-5, player1);}
if(keyEvent.getKeyCode() == KeyEvent.VK_UP){moveY(-5, player1);}
if(keyEvent.getKeyCode() == KeyEvent.VK_DOWN){moveY (5, player1);}
}
};
Thread thread4 = new Thread()
{
public void run() {
if(keyEvent.getKeyCode() == KeyEvent.VK_D){moveX(5, player2);}
if(keyEvent.getKeyCode() == KeyEvent.VK_A){moveX(-5, player2);}
if(keyEvent.getKeyCode() == KeyEvent.VK_W){moveY(-5, player2);}
if(keyEvent.getKeyCode() == KeyEvent.VK_S){ moveY(5, player2);}
}
};
Thread thread5 = new Thread()
{
public void run() {
repaint();
}
};
thread3.start();
thread4.start();
thread5.start();
try{
thread3.join();
thread4.join();
thread5.join();
}
catch (Exception e){System.out.println(e);}
repaint();
}
public void keyReleased(KeyEvent keyEvent)
{
}
public void keyTyped(KeyEvent keyEvent)
{
}
}
Моя цель - сделать так, чтобы на холсте можно было одновременно перемещать обоих игроков (которые являются прямоугольниками). В настоящее время их можно перемещать только по одному, но ни в коем случае не одновременно. Я впервые имею дело с многопоточностью, поэтому заранее прошу прощения за ошибку новичка.
2 ответа
Решение
Вот код
Вам нужен всего один поток, чтобы сделать "игровой цикл".
import java.awt.*;
import java.awt.event.*;
import javax.swing.JPanel;
import java.util.ArrayList;
public class Canvas2 extends JPanel {
// attributes
private Rectangle player1;
private Rectangle player2;
private ArrayList<KeyEvent> log;
private boolean player1left = false;
private boolean player1right = false;
private boolean player1up = false;
private boolean player1down = false;
private boolean player2left = false;
private boolean player2right = false;
private boolean player2up = false;
private boolean player2down = false;
// constructor
public Canvas2() {
// initialize object
player1 = new Rectangle(50, 50, 50, 50);
player2 = new Rectangle(50, 50, 50, 50);
log = new ArrayList<KeyEvent>();
// set canavs background colour
setBackground(Color.white);
// add the key listener in the constructor of your canavas/panel
addKeyListener(new myKeyListener());
// ensure focus is on this canavas/panel for key operations.
setFocusable(true);
Thread gameLoop = new Thread() {
public void run() {
while (true) {
updatePlayers();
repaint();
pause(10);
}
}
};
gameLoop.start();
}
private void updatePlayers() {
if (player1left) {
moveX(-5, player1);
}
if (player1right) {
moveX(5, player1);
}
if (player1up) {
moveY(-5, player1);
}
if (player1down) {
moveY(5, player1);
}
if (player2left) {
moveX(-5, player2);
}
if (player2right) {
moveX(5, player2);
}
if (player2up) {
moveY(-5, player2);
}
if (player2down) {
moveY(5, player2);
}
}
// painting
public void paintComponent(Graphics graphics) {
super.paintComponent(graphics);
Graphics2D graphics2d = (Graphics2D) graphics;
graphics.setColor(Color.blue);
graphics2d.fill(player1);
graphics2d.fill(player2);
}
// function which essentially re-creates rectangle with varying x
// orientations. (x-movement)
public void moveX(int mutationDistance, Rectangle sampleObject) {
sampleObject.setBounds(sampleObject.x + mutationDistance,
sampleObject.y, sampleObject.width, sampleObject.height);
}
// function which essentially re-creates rectangle with varying y
// orientations. (y-movement)
public void moveY(int mutationDistance, Rectangle sampleObject) {
sampleObject.setBounds(sampleObject.x, sampleObject.y
+ mutationDistance, sampleObject.width, sampleObject.height);
}
// listener
private class myKeyListener implements KeyListener {
// implement all the possible actions on keys
public void keyPressed(final KeyEvent keyEvent) {
if (keyEvent.getKeyCode() == KeyEvent.VK_ESCAPE) {
System.exit(0);
}
if (keyEvent.getKeyCode() == KeyEvent.VK_RIGHT) {
player1right = true;
}
if (keyEvent.getKeyCode() == KeyEvent.VK_LEFT) {
player1left = true;
}
if (keyEvent.getKeyCode() == KeyEvent.VK_UP) {
player1up = true;
}
if (keyEvent.getKeyCode() == KeyEvent.VK_DOWN) {
player1down = true;
}
if (keyEvent.getKeyCode() == KeyEvent.VK_D) {
player2right = true;
}
if (keyEvent.getKeyCode() == KeyEvent.VK_A) {
player2left = true;
}
if (keyEvent.getKeyCode() == KeyEvent.VK_W) {
player2up = true;
}
if (keyEvent.getKeyCode() == KeyEvent.VK_S) {
player2down = true;
}
}
public void keyReleased(KeyEvent keyEvent) {
if (keyEvent.getKeyCode() == KeyEvent.VK_RIGHT) {
player1right = false;
}
if (keyEvent.getKeyCode() == KeyEvent.VK_LEFT) {
player1left = false;
}
if (keyEvent.getKeyCode() == KeyEvent.VK_UP) {
player1up = false;
}
if (keyEvent.getKeyCode() == KeyEvent.VK_DOWN) {
player1down = false;
}
if (keyEvent.getKeyCode() == KeyEvent.VK_D) {
player2right = false;
}
if (keyEvent.getKeyCode() == KeyEvent.VK_A) {
player2left = false;
}
if (keyEvent.getKeyCode() == KeyEvent.VK_W) {
player2up = false;
}
if (keyEvent.getKeyCode() == KeyEvent.VK_S) {
player2down = false;
}
}
public void keyTyped(KeyEvent keyEvent) {
}
}
public static void pause(int secs) {
try {
Thread.sleep(secs);
} catch (Exception e) {
e.printStackTrace();
}
}
}
import java.awt.*;
import java.awt.event.*;
import javax.swing.JPanel;
import java.util.ArrayList;
/**
* This code was originally by the user "UniBrain" from the website:
* http://forum.codecall.net/topic/74377-moving-graphics-across-up-and-down-a-jpanel/?p=652384
*
* but has been modified by me for my own purposes
*/
public class Canvas2 extends JPanel
{
//attributes
private Rectangle player1;
private Rectangle player2;
private ArrayList<KeyEvent> log;
//constructor
public Canvas2()
{
//initialize object
player1 = new Rectangle (50, 50, 50, 50);
player2 = new Rectangle (50, 50, 50, 50);
log = new ArrayList<KeyEvent>();
//set canavs background colour
setBackground (Color.white);
//add the key listener in the constructor of your canavas/panel
addKeyListener(new myKeyListener());
//ensure focus is on this canavas/panel for key operations.
setFocusable(true);
}
//painting
public void paintComponent(Graphics graphics)
{
super.paintComponent(graphics);
Graphics2D graphics2d =(Graphics2D)graphics;
graphics.setColor(Color.blue);
graphics2d.fill(player1);
graphics2d.fill(player2);
}
//function which essentially re-creates rectangle with varying x orientations. (x-movement)
public void moveX(int mutationDistance, Rectangle sampleObject)
{
sampleObject.setBounds(sampleObject.x + mutationDistance, sampleObject.y, sampleObject.width, sampleObject.height);
}
//function which essentially re-creates rectangle with varying y orientations. (y-movement)
public void moveY(int mutationDistance, Rectangle sampleObject)
{
sampleObject.setBounds(sampleObject.x, sampleObject.y + mutationDistance, sampleObject.width, sampleObject.height);
}
public void move(){
/*
* This method of keeping track of key events and using a loop is taken from the user Michael Meyers at
* http://stackru.com/questions/752999/how-do-i-handle-multiple-key-presses-in-java
*/
Thread thread1 = new Thread()
{
public void run() {
for(KeyEvent keyEvent: log){
if(keyEvent.getKeyCode() == KeyEvent.VK_RIGHT){moveX(5, player1);}
if(keyEvent.getKeyCode() == KeyEvent.VK_LEFT){moveX (-5, player1);}
if(keyEvent.getKeyCode() == KeyEvent.VK_UP){moveY (-5, player1);}
if(keyEvent.getKeyCode() == KeyEvent.VK_DOWN){moveY (5, player1);}
}
}
};
Thread thread2 = new Thread()
{
public void run() {
for(KeyEvent keyEvent: log){
if(keyEvent.getKeyCode() == KeyEvent.VK_D){moveX(5, player2);}
if(keyEvent.getKeyCode() == KeyEvent.VK_A){moveX(-5, player2);}
if(keyEvent.getKeyCode() == KeyEvent.VK_W){moveY(-5, player2);}
if(keyEvent.getKeyCode() == KeyEvent.VK_S){moveY(5, player2);}
}
}
};
//Starts the threads
thread1.start();
thread2.start();
//Waits for them to finish
try{
thread1.join();
thread2.join();
log = new ArrayList<KeyEvent>();
}
catch (Exception e){System.out.println(e);}
}
//listener
private class myKeyListener implements KeyListener
{
//implement all the possible actions on keys
public void keyPressed(KeyEvent keyEvent)
{
if(keyEvent.getKeyCode() == KeyEvent.VK_ESCAPE){System.exit (0);}
Thread thread3 = new Thread()
{
public void run() {
if(keyEvent.getKeyCode() == KeyEvent.VK_RIGHT){moveX(5, player1);}
if(keyEvent.getKeyCode() == KeyEvent.VK_LEFT){moveX(-5, player1);}
if(keyEvent.getKeyCode() == KeyEvent.VK_UP){moveY(-5, player1);}
if(keyEvent.getKeyCode() == KeyEvent.VK_DOWN){moveY (5, player1);}
}
};
Thread thread4 = new Thread()
{
public void run() {
if(keyEvent.getKeyCode() == KeyEvent.VK_D){moveX(5, player2);}
if(keyEvent.getKeyCode() == KeyEvent.VK_A){moveX(-5, player2);}
if(keyEvent.getKeyCode() == KeyEvent.VK_W){moveY(-5, player2);}
if(keyEvent.getKeyCode() == KeyEvent.VK_S){ moveY(5, player2);}
}
};
Thread thread5 = new Thread()
{
public void run() {
repaint();
}
};
thread3.start();
thread4.start();
thread5.start();
try{
thread3.join();
thread4.join();
thread5.join();
}
catch (Exception e){System.out.println(e);}
repaint();
}
public void keyReleased(KeyEvent keyEvent)
{
}
public void keyTyped(KeyEvent keyEvent)
{
}
}
public static void pause(int secs){
try{Thread.sleep(secs*0);} catch(Exception e){}
}
}
который затем выполняется этим классом
import javax.swing.JFrame;
import java.awt.Dimension;
/**
* This code was taken from the user "UniBrain" from the website:
* http://forum.codecall.net/topic/74377-moving-graphics-across-up-and-down-a-jpanel/?p=652384
*/
public class Display
{
public static void main ( String [ ] arguments )
{
JFrame frame = new JFrame("key listener demo");
Canvas2 panel = new Canvas2();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(panel);
frame.setContentPane(panel);
frame.setPreferredSize(new Dimension(800, 600));
frame.setLocationRelativeTo(null);
frame.setVisible(true);
frame.pack();
}
}