1

我一直在搞乱 CanvasPaint 库,我想制作一个不错的小游戏,我可以根据用户输入在其中移动一个圆圈。

我的方法是创建 2 个同时运行的 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();
            }
        }

}

}

4

3 回答 3

0

方向没有改变的原因是因为你有两个实例,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

于 2013-10-01T22:10:41.987 回答
0

在 while 块中您应该做的第一件事是获取用户输入。有多种选择,您应该选择其中之一:键盘、按钮等...

一旦你知道用户想要做什么,你应该使用 switch 而不要使用 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;
    }

如果您告诉我们更多关于您希望如何听取用户输入以及您使用什么来显示游戏的信息,也许我们可以为您提供更多指导。

于 2013-10-01T21:46:22.757 回答
0

如果您要使用while(true) { //do stuff };,部分//do stuff必须包含 abreak;以退出循环。

于 2013-10-01T21:41:25.983 回答