1

我对 Java 比较陌生,一直在尝试模拟物体(比如汽车)在直线路径上的运动。我希望我的对象在输出中逐步移动,而不是只出现在行的最后一点。

我使用了 2 个类:Veh.java - 车辆对象和 SimuFrame.java - 来创建模拟环境。

我参考了一些在线教程的想法: http: //www.newthinktank.com/2012/07/java-video-tutorial-52/ (这模拟了小行星游戏。但是我希望我的物体直线移动而不是随机方向)

请帮助我了解我错在哪里以及下一步该怎么做..

非常感谢。

这是我的代码:

import java.awt.*;
import java.awt.event.*;


public class Veh extends Rectangle{

    int uLeftX, uLeftY; //upper LH Position for Rectangle
    static int height = 20;
    static int width = 20;
    int[] pathCoords=new int[1000]; 

    int startPosY;  // start position of the objet - anywhere on the left bounday of the frame.
    int goalPosY; // end position of the objet - anywhere on the right boundary of the frame.

//Constructor to Create a new Veh
    public Veh(int startPosY,int goalPosY){ 

    //Create a new rectangle vehicle from super class constructor
    super(0, startPosY, height, width);  

    this.startPosY=startPosY;

    this.goalPosY=goalPosY;

    this.pathCoords = Pathmove();

    }


    //Calculating the 1000 points on the line joining (0,startPosY) and  (goalPosY,999)
        int[] Pathmove(){

//Slope calculation
    float s=(float)(this.goalPosY-this.startPosY)/999;

    pathCoords[0]=this.startPosY;
        System.out.println("First xy pair is: 0," +this.pathCoords[0]);
    for(int m=1; m<1000; m++){
    pathCoords[m]= (int)(m*s)-(int)((m-1)*s)+ pathCoords[m-1];
    }
        return pathCoords;
    }

    //Function to move the Reactangular object along the line using the Y coordinate   values from Pathmove()

    void move(){
    int[] a = (int[])this.pathCoords.clone();
    for (int c=0; c<a.length;c++){
    this.setLocation(c,a[c]);
    }
    } 



} 

这是创建模拟环境的代码。

import javax.swing.*;
import java.awt.*;
import java.util.*;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class SimuFrame extends JFrame{

public static int frameWidth=1000;
public static int frameHeight=1000;

public static void main(String[] args){

new SimuFrame();
}

public SimuFrame(){
this.setSize(frameWidth,frameHeight);
this.setTitle("Path Planning Results");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

SimuObject SO=new SimuObject();
this.add(SO);
// Used to execute code after a given delay
// The attribute is corePoolSize - the number of threads to keep in 
// the pool, even if they are idle
ScheduledThreadPoolExecutor executor= new ScheduledThreadPoolExecutor(5);

executor.scheduleAtFixedRate(new RepaintTheFrame(this), 0L, 20L,    TimeUnit.MILLISECONDS); 

this.setVisible(true);

}

}

// Class implements the runnable interface
// By creating this thread I want to continually redraw the screen
// while other code continues to execute

class RepaintTheFrame implements Runnable{

SimuFrame theFrame;

public RepaintTheFrame(SimuFrame theFrame){
}

@Override
public void run() {

    theFrame.repaint();
    }

}

class SimuObject extends JComponent{

//Holds every Veh created

public ArrayList<Veh> vehs=new ArrayList<Veh>();

public SimuObject(){

    int startPosY = (int)(Math.random()*999);
    int goalPosY = (int)(Math.random()*999);
    vehs.add(new Veh(startPosY,goalPosY));

}

public void paint(Graphics g){

    // Allows me to make many settings changes in regards to graphics
    Graphics2D graphicSettings = (Graphics2D)g;
    // Draw a background that is as big as the Simu board
    graphicSettings.setColor(Color.WHITE);
    graphicSettings.fillRect(0, 0, getWidth(), getHeight());
    // Set rendering rules
    graphicSettings.setRenderingHint( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    // Set the drawing color to red
    graphicSettings.setPaint( Color.RED);
    // Cycle through all of the Rock objects
    for(Veh veh : vehs){
        // Move the vehicle
        veh.move();
        graphicSettings.draw(veh);

    }
}

}

4

2 回答 2

2

您的代码中有许多问题:

  • 您有一个 (swallowed) NullPointerException(NPE) in RepaintTheFrame.run(),这会导致每个javadocScheduledThreadPoolExecutor.scheduleAtFixedRate()只运行一次。scheduleAtFixedRate()

  • 你正在把你的车搬进来JComponent.paint()

    在任何图形框架中,框架都会自动调用重绘,通常是在 OS 事件上,例如移动窗口、将鼠标移到窗口上等。

    您的paint()方法应该只绘制。它不应该修改您的域模型。

  • 你的 move() 方法总是以车辆结束。这可能不是你的意图。您可能希望您的 move() 方法仅增加汽车的位置。

于 2013-07-12T14:23:37.443 回答
1

逐步从起始值移动到结束值称为插值。您需要在这里专门进行线性插值。它是最容易掌握的一种。

此页面将对您有很大帮助。

如果不喜欢插值,你可以像这样改变你的移动例程:

int index =0;
void move(){
    //int[] a = (int[])this.pathCoords.clone();
    if(index<this.pathCoords.length)    
        this.setLocation(c,pathCoords[index]);
    index+=1;
}

不知道你为什么在那里克隆阵列。应该没必要吧。

于 2013-07-12T14:42:07.200 回答