繁体   English   中英

在一个小型Java游戏中处理两个While循环

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM