Java a moving animation (sprite)

2019-05-10 11:23发布

问题:

Hello i`ve got a problem: when i run this code i get this:

on some java forum they said i need to add Graphics2DObject.clearRect(x1, y1, x2, y2); (where`s x1 and y1 is coordinates of the image and x2 y2 is width height of the image.) when i add it to the code i get this:

The code(with added function):

Main:

import java.awt.*; 
import javax.swing.*;
public class Main {
    public static void main(String []args){
        Main b = new Main();
        b.run();
    }
    private Sprite sprite;
    private Animation a;
    private ScreenManager s;
    public double sk = 0;

    private static final DisplayMode modes1[] = {
        new DisplayMode(800, 600, 32, DisplayMode.REFRESH_RATE_UNKNOWN),
    };

    //load images and add scenes
    public void loadImages() {
        Image face1 = new ImageIcon("C:\\1.jpg").getImage();
        Image face2 = new ImageIcon("C:\\2.jpg").getImage();

        a = new Animation();
        a.addScene(face1, 50);
        a.addScene(face2, 50);

        sprite = new Sprite(a);
        sprite.setVelocityX(0.3f);
        sprite.setVelocityY(0.3f);


    }

    //main method called from main
    public void run() {
        s = new ScreenManager();
        try {
            DisplayMode dm = s.findFirstCompatibleMode(modes1);
            s.setFullScreen(dm);
            loadImages();
            movieLoop();
        }finally {
            s.restoreScreen();
        }
    }

    //play movie
    public void movieLoop() {
        long startingTime = System.currentTimeMillis();
        long cumTime = startingTime;

        while(cumTime - startingTime < 5000) {
            long timePassed = System.currentTimeMillis() - cumTime;
            cumTime += timePassed;
            update(timePassed);

            //draw and update the screen
            Graphics2D g = s.getGraphics();
            draw(g);
            g.dispose();
            s.update();

            try{
                Thread.sleep(20);
            }catch(Exception ex) {
                System.err.println("Error: " + ex);
            }
        }
    }


    // Graphics with new function
    public void draw(Graphics g) {
        g.drawImage(sprite.getImage(), Math.round(sprite.getX()), Math.round(sprite.getY()), null);
        if(sk != 1){
       g.clearRect(Math.round(sprite.getoX()),Math.round(sprite.getoY()),Math.round(sprite.getWidth()),Math.round(sprite.getHeight()));
        }else{
          sk = 1;
       }

    }

    //update sprite
    public void update(long timePassed) {
        if(sprite.getX() < 0) {
            sprite.setVelocityX(Math.abs(sprite.getVelocityX()));
        } else if (sprite.getX() + sprite.getWidth() >= s.getWidth()) {
            sprite.setVelocityX(-Math.abs(sprite.getVelocityX()));
        }

        if(sprite.getY() < 0) {
            sprite.setVelocityY(Math.abs(sprite.getVelocityY()));
        } else if (sprite.getY() + sprite.getHeight() >= s.getHeight()) {
            sprite.setVelocityY(-Math.abs(sprite.getVelocityY()));
        }

        sprite.oldX();
        sprite.oldY();
        sprite.update(timePassed);
    }


}

The sprite (movement class):

import java.awt.Image;

public class Sprite {

    private Animation a;
    private float x;
    private float y;
    private float vx;
    private float vy;
    private float ox;
    private float oy;


    //Constructor
    public Sprite(Animation a) {
        this.a = a;
    }


    // Get old x and y to delete them later

    public void oldX(){
       this.ox = x;
    }

    public void oldY(){
       this.oy = y;
    }

    public float getoX(){
       return ox;
    }
    public float getoY(){
       return oy;
    }



    //Change position
    public void update(long timePassed) {
        x += vx * timePassed;
        y += vy * timePassed;
        a.update(timePassed);
    }

    //get x position
    public float getX() {
        return x;
    }

    //get y position
    public float getY() {
        return y;
    }

    //set x position
    public void setX(float x) {
        this.x = x;
    }

    //set y position
    public void setY(float y) {
        this.y = y;
    }

    // get sprite width
    public int getWidth() {
        return a.getImage().getWidth(null);
    }

    // get sprite height
    public int getHeight() {
        return a.getImage().getHeight(null);
    }

    //get horizontal velocity
    public float getVelocityX() {
        return vx;
    }

    //get vertical velocity
    public float getVelocityY() {
        return vy;
    }

    //set horizontal velocity
    public void setVelocityX(float vx) {
        this.vx = vx;
    }

    //set vertical velocity
    public void setVelocityY(float vy) {
        this.vy = vy;
    }

    //get sprite/image
    public Image getImage() {
        return a.getImage();
    }
}

Screen manager class:

import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.image.BufferStrategy;
import javax.swing.JFrame;

public class ScreenManager {

    private GraphicsDevice vc;

    //Constructor // give vc access to monitor screen
    public ScreenManager() {
        GraphicsEnvironment e = GraphicsEnvironment.getLocalGraphicsEnvironment();
        vc = e.getDefaultScreenDevice();
    }

    //get all compatible DM's
    public DisplayMode[] getCompatibleDisplayModes() {
        return vc.getDisplayModes();
    }

    //compares DM passed in to vc and see if they match
    public DisplayMode findFirstCompatibleMode(DisplayMode modes[]) {
        DisplayMode goodModes[] = vc.getDisplayModes();

        for(int x = 0; x <modes.length; x++){
            for(int y = 0; y < goodModes.length; y++){
                if(displayModesMatch(modes[x], goodModes[y])) {
                    return modes[x];
                }
            }
        }
        return null;
    }

    //get current DM
    public DisplayMode getCurrentDisplayMode() {
        return vc.getDisplayMode();
    }

    //checks if two modes match each other
    public boolean displayModesMatch(DisplayMode m1, DisplayMode m2) {
        if(m1.getWidth() != m2.getWidth() || m1.getHeight() != m2.getHeight()) {
            return false;
        }

        if(m1.getBitDepth() != DisplayMode.BIT_DEPTH_MULTI && m2.getBitDepth() != DisplayMode.BIT_DEPTH_MULTI && m1.getBitDepth() != m2.getBitDepth()) {
            return false;
        }

        if(m1.getRefreshRate() != DisplayMode.REFRESH_RATE_UNKNOWN && m2.getRefreshRate() != DisplayMode.REFRESH_RATE_UNKNOWN && m1.getRefreshRate() != m2.getRefreshRate()) {
            return false;
        }

        return true;
    }

    //make frame full screen
    public void setFullScreen(DisplayMode dm) {
        JFrame f = new JFrame();
        f.setUndecorated(true);
        f.setIgnoreRepaint(true);
        f.setResizable(false);
        vc.setFullScreenWindow(f);

        if(dm != null && vc.isDisplayChangeSupported()) {
            try{
                vc.setDisplayMode(dm);
            }catch(Exception e) {System.out.println("");}
        }
        f.createBufferStrategy(2);

    }

    //we will set Graphics object = to this
    public Graphics2D getGraphics() {
        Window w = vc.getFullScreenWindow();
        if(w != null) {
            BufferStrategy s = w.getBufferStrategy();
            return (Graphics2D)s.getDrawGraphics();
        }
        else {
            return null;
        }
    }

    //updates display
    public void update() {
        Window w = vc.getFullScreenWindow();
        if(w != null) {
            BufferStrategy s = w.getBufferStrategy();
            if(!s.contentsLost()) {
                s.show();
            }
        }
    }

    //returns full screen window
    public Window getFullScreenWindow() {
        return vc.getFullScreenWindow();
    }

    //get width
    public int getWidth() {
        Window w = vc.getFullScreenWindow();
        if(w != null) {
            return w.getWidth();
        }
        else {
            return 0;
        }
    }

    //get height
    public int getHeight() {
        Window w = vc.getFullScreenWindow();
        if(w != null) {
            return w.getHeight();
        }
        else {
            return 0;
        }
    }

    //get out of full screen
    public void restoreScreen(){
        Window w = vc.getFullScreenWindow();
        if(w != null) {
            w.dispose();
            vc.setFullScreenWindow(null);
        }
    }

    //create image compatible with monitor
    public BufferedImage createCompatibleImage(int w, int h, int t) {
        Window win = vc.getFullScreenWindow();
        if(win != null) {
            GraphicsConfiguration gc = win.getGraphicsConfiguration();
            return gc.createCompatibleImage(w, h, t);
        }
        return null;
    }





}/////////END///////////

Animation class

import java.util.ArrayList;
import java.awt.Image;

public class Animation {

    private ArrayList scenes;
    private int sceneIndex;
    private long movieTime;
    private long totalTime;

    //Constructor
    public Animation() {
        scenes = new ArrayList();
        totalTime = 0;
        start();
    }

    //add scenes to the array list and set time for each scene
    public synchronized void addScene(Image i, long t) {
        totalTime += t;
        scenes.add(new Onescene(i, totalTime));
    }

    //start animation from beginning
    public synchronized void start() {
        movieTime = 0;
        sceneIndex = 0;
    }

    //change scenes
    public synchronized void update(long timePassed) {

        if(scenes.size() > 1 ) {
            movieTime += timePassed;

            if(movieTime >= totalTime) {
                movieTime = 0;
                sceneIndex = 0;
            }
            while(movieTime > getScene(sceneIndex).endTime) {
                sceneIndex++;
            }
        }
    }

    //get animations current scene
    public synchronized Image getImage() {

        if(scenes.size() == 0) {
            return null;
        }

        else {
            return getScene(sceneIndex).pic;
        }
    }

    //get scene
    private Onescene getScene(int x) {
        return (Onescene)scenes.get(x);
    }

    /////PRIVAT INNER CLASS/////
    private class Onescene{
        Image pic;
        long endTime;

        public Onescene(Image pic, long endTime) {
            this.pic = pic;
            this.endTime = endTime;
        }
    }






}////END/////

EDIT:

Could someone try running this code ?

Maybe You'll find the mistakes I made...

回答1:

Your loop looks a bit incorrect

       Graphics2D g = s.getGraphics();  
      while(cumTime - startingTime < 5000) {
        long timePassed = System.currentTimeMillis() - cumTime;
        cumTime += timePassed;
        update(timePassed);

        //draw and update the screen
        draw(g);
        g.dispose();
        s.update();

        try{
            Thread.sleep(20);
        }catch(Exception ex) {
            System.err.println("Error: " + ex);
        }
    }
}

also try this for your draw method.

// Graphics with new function
public void draw(Graphics g) {
    g.clearRect(0,0,800,600);
    g.drawImage(sprite.getImage(), Math.round(sprite.getX()), Math.round(sprite.getY()), null);
}


回答2:

clearRect goes before drawImage.



回答3:

I also had a problem with this and you need a "do while loop" in stead of while loop like this:

do{
        Graphics2D g = s.getGraphics();
        long timePassed = System.currentTimeMillis() - cumTime;
        cumTime += timePassed;
        update(timePassed);


        //draw and update
        draw(g);
        g.dispose();
        s.update();

        try{
            Thread.sleep(20);
        }catch(Exception ex){
            System.out.println("Can't sleep :(");
        }
    }
    while(cumTime - startingTime < 20000); //the Time

And the clearRect must be ABOVE the drawImage