[英]Handle two While-loop's in a small Java-game
我一直在搞乱CanvasPaint库,我想做一个不错的小游戏,我可以根据用户输入在其中移动一个圆圈。
我的方法是创建两个同时运行的While循环,第一个寻找用户的新输入,第二个移动圆圈。
抱歉,由于我缺乏发布此类代码的经验,但是我才刚刚开始Java编码。
问题:我的“方向”变量始终为0,我无法获得任何值:(
package canvas;
import java.awt.Color;
import java.util.Scanner;
import TestPackage.CanvasPaint;
public class BilSpil extends Thread {
Scanner input = new Scanner (System.in);
private int direction;
public void run() { //First array, checking user-input
while(true) {
System.out.print("Direction: ");
direction = input.nextInt();
}
}
//Getter for user-input
public int getDirection() {
return direction;
}
public static void main(String[] args) {
(new BilSpil()).start();
BilSpil spilObject = new BilSpil(); //Create object of extended Thread.
int commands = (spilObject.direction); //Raw command-data for circle
//Game background
int yBg = 10;
CanvasPaint cp = new CanvasPaint(500,500);
cp.setBackground(Color.black);
for(int i = 0; i<50; i++) {
cp.setColor(Color.DARK_GRAY);
cp.paintLine(yBg, 500, yBg, 0); //Y-streger
cp.paintLine(500, yBg, 0, yBg); //X-streger
yBg += 10;
}
boolean gameIsLive = true;
int x = 245;
int y = 245;
cp.setColor(Color.CYAN);
cp.paintOval(x, y, 5, 5);
while(gameIsLive) { //Second while-loop, moving the circle
while(commands == 2) { //Down direction
cp.paintOval(x, y+10, 5, 5);
y += 10;
try{Thread.sleep(1000);}
catch (InterruptedException e) {}
cp.repaintFrame();
}
while(commands == 4) { //Left direction
cp.paintOval(x-10, y, 5, 5);
x -= 10;
try{Thread.sleep(1000);}
catch (InterruptedException e) {}
cp.repaintFrame();
}
while(commands == 8) { //UP direction
cp.paintOval(x, y-10, 5, 5);
y-= 10;
try{Thread.sleep(1000);}
catch (InterruptedException e) {}
cp.repaintFrame();
}
while(commands == 6) { //RIGHT direction
cp.paintOval(x+10, y, 5, 5);
x += 10;
try{Thread.sleep(1000);}
catch (InterruptedException e) {}
cp.repaintFrame();
}
}
}
}
如果您要使用while(true) { //do stuff };
, //do stuff
一部分必须包含一个break;
退出循环。
在while块中,您应该做的第一件事就是获取用户输入。 有多种选择,您应该选择其中一种:键盘,按钮等...
一旦知道了用户想要做什么,就应该使用开关,不要停顿(这很不正确,因为您不会离开他们):
while(gameIsLive) { //Second while-loop, moving the circle
commands = getUserInput();
switch (commands) {
case 2: { //Down direction
cp.paintOval(x, y+10, 5, 5);
y += 10;
try{Thread.sleep(1000);}
catch (InterruptedException e) {}
cp.repaintFrame();
} break;
case 4: { //Left direction
cp.paintOval(x-10, y, 5, 5);
x -= 10;
try{Thread.sleep(1000);}
catch (InterruptedException e) {}
cp.repaintFrame();
} break;
case 8: { //UP direction
cp.paintOval(x, y-10, 5, 5);
y-= 10;
try{Thread.sleep(1000);}
catch (InterruptedException e) {}
cp.repaintFrame();
} break;
case 6: { //RIGHT direction
cp.paintOval(x+10, y, 5, 5);
x += 10;
try{Thread.sleep(1000);}
catch (InterruptedException e) {}
cp.repaintFrame();
} break;
}
如果您告诉我们更多有关如何聆听用户输入以及用于显示游戏内容的信息,也许我们可以为您提供更多指导。
方向不变的原因是因为您有两个BilSpil
实例,并且正在从一个BilSpil
实例中检索方向。
(new BilSpil()).start();
BilSpil spilObject = new BilSpil(); //Create object of extended Thread.
int commands = (spilObject.direction); //Raw command-data for circle
要使此部分正常工作,您将必须执行以下操作:
BilSpil spilObject = new BilSpil(); //Create object of extended Thread.
spilObject.start();
int commands = (spilObject.direction); //Raw command-data for circle
您对direction
访问不是线程安全的,我想这会引发一些并发异常。
相反,我建议实现java.util.concurrent.Callable
因为您想返回一些东西
/**
* The Callable<V> interface allows you to define a Object V that you will
* return. In this case we are returning the integer object wrapper Integer
*/
public class BilSpil implements Callable<Integer> {
Scanner input = new Scanner(System.in);
/**
*Since we defined our class to implement Callable<Integer> we have to override
* the abstract method V call() throws Exception, and in our case it is of
*the type Integer
*/
@Override
public Integer call() throws Exception {
/**
*input.nextInt() will block and not return untill a integer is entered
* java autoboxes the int primitive to its wrapper class Integer automagically
*/
return input.nextInt();
}
我将所有内容移动到一个循环中并使用switch语句
public static void main(String[] args) {
//creates a executor service with a fixed number of threads
//that this ExecutorService can access
ExecutorService executor = Executors.newFixedThreadPool(10);
//submitting a callable runs it asynchronously, executor returns
//a Future object we can use later to get the returned value
//once the callable is done executing.
Future<Integer> userInput = executor.submit(new BilSpil());
int commands = 0;
...
while (gameIsLive) {
if(userInput.isDone()){
try {
commands = userInput.get().intValue();
} catch (InterruptedException ex) {
commands = 0;
} catch (ExecutionException ex) {
commands = 0;
}
userInput = executor.submit(new BilSpil());
}
switch(commands){
case 2:
y += 10;
break;
case 4:
x -= 10;
break;
case 8:
y -= 10;
break;
case 6:
x += 10;
break;
}
cp.paintOval(x, y, 5, 5);
cp.repaintFrame();
}
}
您可以做的另一种改进是摆脱魔术数字
public static final int MOVE_SPEED = 10;
public static final int DOWN = 2;
public static final int LEFT = 4;
public static final int UP = 8;
public static final int RIGHT = 6;
public static final int NO_INPUT = 0;
public static final long GAME_CLOCK = 1000L;
public static final int BODY_WIDTH = 5;
public static final int BODY_HEIGHT = 5;
...
while (gameIsLive) {
if(userInput.isDone()){
try {
commands = userInput.get().intValue();
} catch (InterruptedException ex) {
commands = NO_INPUT;
} catch (ExecutionException ex) {
commands = NO_INPUT;
}
userInput = executor.submit(new BilSpil());
}
switch(commands){
case DOWN:
y += MOVE_SPEED;
break;
case LEFT:
x -= MOVE_SPEED;
break;
case UP:
y -= MOVE_SPEED;
break;
case RIGHT:
x += MOVE_SPEED;
break;
}
cp.paintOval(x, y, BODY_WIDTH, BODY_HEIGHT);
cp.repaintFrame();
try{Thread.sleep(GAME_CLOCK);}
catch (InterruptedException e) {}
}
}
一些阅读材料:
http://docs.oracle.com/javase/tutorial/java/data/autoboxing.html http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ExecutorService.html
http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Future.html
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.