JavaFX图像重影快速移动

时间:2014-12-21 21:37:57

标签: java image swing javafx-8

我偶然发现了一个问题:如果图像在屏幕上高速移动,则渲染错误会产生重影效果。我认为我们可以排除我的显示器问题,因为这种类型的机芯在摆动时完美无缺(具有相同的帧速率)。

看起来像:enter image description here

代码(从3个类合并):

import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import java.awt.Dimension;
import java.awt.Toolkit;


public class Constructor extends Application{

        Image player, shot;
        static Dimension screen = new Dimension(Toolkit.getDefaultToolkit().getScreenSize());
        static int wid = screen.width;
        static int hei = screen.height;
        static boolean up, down, left, right, rotleft , rotright;
        static double x = (wid/2)-109;
        static double y = (hei/1.5)-132;
        static double velx = 0, vely = 0, velx2 = 0, vely2 = 0;
        static double forspeed = 0, sidespeed = 0;
        static int rotat = 0;

        public void load(){
                player = new Image("res/sprite.png");
        }

        @Override
        public void start(final Stage frame) throws Exception{

                load();

                frame.setTitle("DEFAULT");
                frame.initStyle(StageStyle.UNDECORATED);

                Group root = new Group();              
                final ImageView ship = new ImageView();
                ship.setImage(player); 
                root.getChildren().add(ship);

            frame.setScene(new Scene(root,  wid,  hei, Color.BLACK));

                frame.addEventHandler(KeyEvent.KEY_PRESSED, new EventHandler<KeyEvent>(){
                        public void handle(KeyEvent key) {
                          if(key.getCode()==KeyCode.W)
                                   up = true;
                          if(key.getCode()==KeyCode.S)
                                   down = true;
                          if(key.getCode()==KeyCode.Q)
                                   left = true;
                          if(key.getCode()==KeyCode.E)
                                   right = true;
                          if(key.getCode()==KeyCode.A)
                                   rotleft = true;
                          if(key.getCode()==KeyCode.D)
                                   rotright = true;

                        }
                });
                frame.addEventHandler(KeyEvent.KEY_RELEASED, new EventHandler<KeyEvent>(){
                        public void handle(KeyEvent key) {
                          if(key.getCode()==KeyCode.ESCAPE)
                          {
                              frame.close();
                                  System.exit(0);  
                          }
                          if(key.getCode()==KeyCode.W)
                                   up = false;
                          if(key.getCode()==KeyCode.S)
                                   down = false;
                          if(key.getCode()==KeyCode.Q)
                                   left = false;
                          if(key.getCode()==KeyCode.E)
                                   right = false;
                          if(key.getCode()==KeyCode.A)
                                   rotleft = false;
                          if(key.getCode()==KeyCode.D)
                                   rotright = false;

                        }
                });
                frame.setAlwaysOnTop(true);
                frame.setHeight(hei);
                frame.setWidth(wid);
                frame.setResizable(false);
                frame.setFullScreen(true);
                frame.show();

                 new AnimationTimer() {
                    @Override
                    public void handle(long now) {

                        gameloop();
                        ship.setTranslateX(x);
                        ship.setTranslateY(y);
                        ship.setRotate(rotat);
                    }
                }.start();
        }

        public static void gameloop(){
        if(Shared.up)
                forspeed += 1;
        if(Shared.down)
                forspeed -= 1;
        if(Shared.right)
                sidespeed += 1;
        if(Shared.left)
                sidespeed -= 1;

        if(Shared.rotleft)
                rotat -=3;
        if(Shared.rotright)
                rotat +=3;

        velx = Math.cos(Math.toRadians(rotat-90))*forspeed + Math.cos(Math.toRadians(rotat))*sidespeed;
        vely = Math.sin(Math.toRadians(rotat-90))*forspeed + Math.sin(Math.toRadians(rotat))*sidespeed;

        if(!Shared.up && !Shared.down)
        {
                if(forspeed > 0)
                        forspeed -= 0.2;
                else if (forspeed < 0)
                        forspeed += 0.2;
        }
        if(!Shared.right && !Shared.left)
        {
                if(sidespeed > 0)
                        sidespeed -= 0.2;
                else if (sidespeed < 0)
                        sidespeed += 0.2;
        }

        x += velx;
        y += vely;

        screencolisions();
        }

        private static void screencolisions() {
                // LEFT RIGHT
                if(x < 0)
            {
                x = 0;
                sidespeed = 0;
            }
            else if (x+218 > Shared.wid)
            {
                x = Shared.wid-218;
                sidespeed = 0;
            }

                // UP DOWN
            if(y < 0)
            {
                y = 0;
                forspeed = 0;
            }
            else if (y+164 > Shared.hei)
            {
                y = Shared.hei-164;
                forspeed = 0;
            }

        }

        public static void main(String[] args){
                Application.launch(args);
    }
}

1 个答案:

答案 0 :(得分:0)

首先,你在Javafx中使用AWT课程。他们不是朋友(大部分时间)。

而不是使用Dimension和AWT工具包, 使用提供的Javafx Screen类

Screen screen = Screen.getPrimary();
wid = screen.getBounds().getWidth();
hei = screen.getBounds().getHeight();
// Visual bounds will be different depending on OS and native toolbars etc..
// think of it as desktop bounds vs whole screen

例如:

public class ScreenBounds extends Application {

    @Override
    public void start(Stage primaryStage) {
        Screen screen = Screen.getPrimary();
        System.out.println("ScreenBounds : " + screen.getBounds() + "\nVisualBounds : " +   screen.getVisualBounds());
        Platform.exit();
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        launch(args);
    }

}

打印:

compile-single:
run-single:
ScreenBounds : Rectangle2D [minX = 0.0, minY=0.0, maxX=1680.0, maxY=1050.0, width=1680.0, height=1050.0]
VisualBounds : Rectangle2D [minX = 0.0, minY=40.0, maxX=1680.0, maxY=1050.0, width=1680.0, height=1010.0]

正如您所描述的那样,您看不到语法错误。 虽然这个错误可能是因为你的变量是整数而不是像方法返回的双打;

ScheduledService Timer:

import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import javafx.concurrent.ScheduledService;
import javafx.concurrent.Task;
import javafx.util.Duration;

/**
 *
 * @author jdub1581
 */
public class NanoTimer extends ScheduledService<Void> {

    private final long ONE_NANO = 1000000000L;
    private final double ONE_NANO_INV = 1f / 1000000000L;

    private long startTime, previousTime;
    private double frameRate, deltaTime;
    private final NanoThreadFactory tf = new NanoThreadFactory();

    public NanoTimer() {
        super();
        this.setPeriod(Duration.millis(16));// equivalent to 60 fps
        this.setExecutor(Executors.newCachedThreadPool(tf));
    }

    public double getTimeAsSeconds() {
        return getTime() * ONE_NANO_INV;
    }

    public long getTime() {
        return System.nanoTime() - startTime;
    }

    public long getOneSecondAsNano() {
        return ONE_NANO;
    }

    public double getFrameRate() {
        return frameRate;
    }

    public double getDeltaTime() {
        return deltaTime;
    }

    private void updateTimer() {
        deltaTime = (getTime() - previousTime) * (1.0f / ONE_NANO);
        frameRate = 1.0f / deltaTime;
        previousTime = getTime();

    }

    @Override
    public void start() {
        super.start();
        if (startTime <= 0) {
            startTime = System.nanoTime();
        }
     }

    @Override
    public void reset() {
        super.reset();
        startTime = System.nanoTime();
        previousTime = getTime();
    }
    private boolean init = true;

    @Override
    protected Task<Void> createTask() {
        return new Task<Void>() {
            @Override
            protected Void call() throws Exception {                
                updateTimer();
                // perform NON UI calculations here

                return null;
            }
        };
    }

    @Override
    protected void succeeded() {
        super.succeeded();
        //update the UI here
    }

    @Override
    protected void failed() {
        getException().printStackTrace(System.err);

    }

    @Override
    public String toString() {
        return "ElapsedTime: " + getTime() + "\nTime in seconds: " + getTimeAsSeconds()
            + "\nFrame Rate: " + getFrameRate()
            + "\nDeltaTime: " + getDeltaTime();
    }

    /*==========================================================================
        creates a daemon thread for use
    */
    private class NanoThreadFactory implements ThreadFactory {

        public NanoThreadFactory() {
        }

        @Override
        public Thread newThread(Runnable r) {
            Thread t = new Thread(r, "NanoTimerThread");
            t.setDaemon(true);
            return t;
        }

    }
}//=============================================================================

无论你输入什么类,只需调用start方法,最好嵌套为私有类,因此可以在其中使用变量..或者根据需要重写..

我在这里使用它:My Cloth Simulation它可以很好地进行每帧50k +计算