简体   繁体   中英

Smooth movement in Java

I'm making a simulation in a 3D environment. So far, I have the movements of all the creatures, but it is not "smooth". I've tried quite a few things but was horribly wrong. Now I just have no idea what to do. I was thinking of implementing a vector (not vector class) but don't really know how.

import env3d.EnvObject;
import java.util.ArrayList;

abstract public class Creature extends EnvObject
{

/**
 * Constructor for objects of class Creature
 */
public Creature(double x, double y, double z)
{
    setX(x);
    setY(y);
    setZ(z);
    setScale(1);
}

public void move(ArrayList<Creature> creatures, ArrayList<Creature> dead_creatures)
{                
    double rand = Math.random();
    if (rand < 0.25) {
        setX(getX()+getScale());
        setRotateY(90);
    } else if (rand < 0.5) {
        setX(getX()-getScale());
        setRotateY(270);
    } else if (rand < 0.75) {
        setZ(getZ()+getScale());
        setRotateY(0);
    } else if (rand < 1) {
        setZ(getZ()-getScale());
        setRotateY(180);
    }                

    if (getX() < getScale()) setX(getScale());
    if (getX() > 50-getScale()) setX(50 - getScale());
    if (getZ() < getScale()) setZ(getScale());
    if (getZ() > 50-getScale()) setZ(50 - getScale());

    // collision detection
    if (this instanceof Fox) {
        for (Creature c : creatures) {
            if (c.distance(this) < c.getScale()+this.getScale() && c instanceof Tux) {
                dead_creatures.add(c);
            }
        }
    }
}        

}

import env3d.Env;
import java.util.ArrayList;

/**
 * A predator and prey simulation.  Fox is the predator and Tux is the prey.
 */
public class Game
{
private Env env;    
private boolean finished;

private ArrayList<Creature> creatures;

/**
 * Constructor for the Game class. It sets up the foxes and tuxes.
 */
public Game()
{
    // we use a separate ArrayList to keep track of each animal. 
    // our room is 50 x 50.
    creatures = new ArrayList<Creature>();
    for (int i = 0; i < 55; i++) {
        if (i < 5) {
            creatures.add(new Fox((int)(Math.random()*48)+1, 1, (int)(Math.random()*48)+1));        
        } else {
            creatures.add(new Tux((int)(Math.random()*48)+1, 1, (int)(Math.random()*48)+1));
        }
    }
}

/**
 * Play the game
 */
public void play()
{

    finished = false;

    // Create the new environment.  Must be done in the same
    // method as the game loop
    env = new Env();

    // Make the room 50 x 50.
    env.setRoom(new Room());

    // Add all the animals into to the environment for display
    for (Creature c : creatures) {
        env.addObject(c);
    }

    // Sets up the camera
    env.setCameraXYZ(25, 50, 55);
    env.setCameraPitch(-63);

    // Turn off the default controls
    env.setDefaultControl(false);

    // A list to keep track of dead tuxes.
    ArrayList<Creature> dead_creatures = new ArrayList<Creature>();

    // The main game loop
    while (!finished) {            

        if (env.getKey() == 1)  {
            finished = true;
         }

        // Move each fox and tux.
        for (Creature c : creatures) {
            c.move(creatures, dead_creatures);
        }

        // Clean up of the dead tuxes.
        for (Creature c : dead_creatures) {
            env.removeObject(c);
            creatures.remove(c);
        }
        // we clear the ArrayList for the next loop.  We could create a new one 
        // every loop but that would be very inefficient.
        dead_creatures.clear();

        // Update display
        env.advanceOneFrame();
    }

    // Just a little clean up
    env.exit();
}


/**
 * Main method to launch the program.
 */
public static void main(String args[]) {
    (new Game()).play();
}

}

You haven't shown enough of your program. Basically, if you want animation to be smooth, and you want to do it yourself (as opposed to using JavaFX or something), then you need to do lots of inter-frames. So rather than advancing an entire timer tick, advance a 10th of a timer tick, move everything on a screen a tiny bit, and then advance again. You should have the background redraw happening every 10th of a second for smooth animation.

As vy32 mentioned, we need to see more of your code. But it looks like you are missing timing code.

What you probably want to do is check the time each iteration of your game loop and then sleep for a certain amount of time to achieve some desired frame rate. Otherwise your game loop will run hundreds of thousands of times a second.

Alternatively, you should be advancing your creatures by a distance that is proportional to the amount of time that has elapsed since the previous frame.

Here is an example of a very simple regulated loop ("fps" is the desired framerate):

private long frameLength = 1000000000 / fps;

public void run() {
    long ns = System.nanoTime();
    while (!finished) {

        //Do one frame of work
        step();

        //Wait until the time for this frame has elapsed
        try {
            ns += frameLength;
            Thread.sleep(Math.max(0, (ns - System.nanoTime())/10000000));
        } catch (InterruptedException e) {
            break;
        }
    }
}

It should be very easy to retrofit this into your game loop.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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