Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/375.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java游戏在玩家移动时变慢_Java - Fatal编程技术网

Java游戏在玩家移动时变慢

Java游戏在玩家移动时变慢,java,Java,我正在尝试用Java编写我的第一个游戏。我学习了一些教程,学习了如何使用画布加载和更新背景,以及如何加载和移动播放器精灵。我分别做了这两个动作,效果很好,但当我把这两个动作放在一起并试图移动玩家时,游戏速度会减慢到无法进行的程度。这只发生在我按下箭头键移动玩家时;如果我快速点击箭头键,游戏实际上运行“平稳”。经过一段时间的测试,我确信在每一帧重新绘制背景时会出现问题。如有任何其他改进,也将不胜感激 代码(全部): Game.Java: 包装游戏 import Level.Level; impor

我正在尝试用Java编写我的第一个游戏。我学习了一些教程,学习了如何使用画布加载和更新背景,以及如何加载和移动播放器精灵。我分别做了这两个动作,效果很好,但当我把这两个动作放在一起并试图移动玩家时,游戏速度会减慢到无法进行的程度。这只发生在我按下箭头键移动玩家时;如果我快速点击箭头键,游戏实际上运行“平稳”。经过一段时间的测试,我确信在每一帧重新绘制背景时会出现问题。如有任何其他改进,也将不胜感激

代码(全部):

Game.Java: 包装游戏

import Level.Level;
import Player.Player;
import Sprites.SpriteSheetLoader;
import java.awt.Canvas;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
import javax.swing.JFrame;

public class Game extends Canvas implements Runnable {

    // Set dimensions of the game.
    public static final int HEIGHT = 320;
    public static final int WIDTH = 480;
    public static final int SCALE = 2;
    public static Dimension GAME_DIM = new Dimension(WIDTH * SCALE, HEIGHT * SCALE);

    private BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_ARGB);
    private int[] pixels = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();

    public SpriteSheetLoader loader;
    public Screen screen;
    public Level level;
    public InputHandler input = new InputHandler(this);
    public Player player = new Player();

    private boolean running = false;
    private boolean moving = true;

    private int FPS = 60;
    private long targetTime = 1000 / FPS;

    // Set character's starting position at the center.  I have no idea why I had to add the "- 50" to each value.
    public int x = GAME_DIM.width / 2 - 50;
    public int y = GAME_DIM.height / 2 - 50;

    public int xScroll = 0;
    public int yScroll = 0;

    public int col = 0;
    public int row = 0;

    public int ticks = 0;
    public int frame = 0;

    public static void main(String[] args) {

        Game game = new Game();
        game.setPreferredSize(new Dimension(GAME_DIM));
        game.setMaximumSize(new Dimension(GAME_DIM));
        game.setMinimumSize(new Dimension(GAME_DIM));

        JFrame frame = new JFrame("Valkyrie Game");

        frame.add(game);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setResizable(true);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);

        game.start();

    }

    public void start() {
        running = true;
        new Thread(this).start();
    }

    public Game() {

    }

    public void init() {

        loader = new SpriteSheetLoader();
        screen = new Screen(WIDTH, HEIGHT);

        level = new Level(16, 16);

    }

    public void run() {
        init();

        long start, elapsed, wait;

        while (running) {

            start = System.nanoTime();

            render();
            tick();

            elapsed = System.nanoTime() - start;
            //System.out.println("Elapsed: " + elapsed);

            wait = targetTime - elapsed / 1000000;
            if(wait < 0) {
                wait = 5;
            }

            try {
                Thread.sleep(wait);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
    }

    public void stop() {
        running = false;
    }

    public void tick() {

        // Movement
        if (input.right) {
            xScroll++;
            player.setAnimation(player.walkRight);
            //x++;
            row = 2;

            ticks++;
            if(ticks < 10) {
                frame = 1;
            } else if(ticks == 10) {
                frame = 2;
            } else if(ticks == 20) {
                frame = 3;
            } else if(ticks == 30) {
                frame = 2;
            } else if(ticks == 40) {
                frame = 1;
            } else if(ticks == 50) {
                ticks = 0;
                frame = 0;
            }

            moving = true;

        } else if (input.left) {
            xScroll--;
            player.setAnimation(player.walkLeft);
            //x--;
            row = 1;

            ticks++;
            if(ticks < 10) {
                frame = 1;
            } else if(ticks == 10) {
                frame = 2;
            } else if(ticks == 20) {
                frame = 3;
            } else if(ticks == 30) {
                frame = 2;
            } else if(ticks == 40) {
                frame = 1;
            } else if(ticks == 50) {
                ticks = 0;
                frame = 0;
            }

            moving = true;

        } else if (input.up) {
            yScroll--;
            player.setAnimation(player.walkUp);
            //y--;
            row = 3;

            ticks++;
            if(ticks < 10) {
                frame = 1;
            } else if(ticks == 10) {
                frame = 2;
            } else if(ticks == 20) {
                frame = 3;
            } else if(ticks == 30) {
                frame = 2;
            } else if(ticks == 40) {
                frame = 1;
            } else if(ticks == 50) {
                ticks = 0;
                frame = 0;
            }

            moving = true;

        } else if (input.down) {
            yScroll++;
            player.setAnimation(player.walkDown);
            //y++;
            row = 0;

            ticks++;
            if(ticks < 10) {
                frame = 1;
            } else if(ticks == 10) {
                frame = 2;
            } else if(ticks == 20) {
                frame = 3;
            } else if(ticks == 30) {
                frame = 2;
            } else if(ticks == 40) {
                frame = 1;
            } else if(ticks == 50) {
                ticks = 0;
                frame = 0;
            }

            moving = true;

        }

        if (!input.down && !input.left && !input.right && !input.up) {
            player.setAnimation(player.stand);
            frame = 0;
            ticks = 1;
            moving = false;
        }

        //System.out.println("Tick: " + ticks);

    }

    public void render() {
        BufferStrategy bs = getBufferStrategy();
        if (bs == null) {
            createBufferStrategy(3);
            requestFocus();

            return;
        }

        do {
            Graphics g = bs.getDrawGraphics();
            try {
                for (int i = 0; i < ticks; i++) {

                    g.drawImage(image, 0, 0, getWidth(), getHeight(), null);
                    g.drawImage(player.Player(frame, row), x, y, null);

                    level.renderBackground(xScroll, yScroll, screen);

                    for (int y = 0; y < this.screen.h; y++) {
                        for (int x = 0; x < screen.w; x++) {
                            pixels[x + (y * WIDTH)] = screen.pixels[x + (y * screen.w)];
                        }
                    }
                }
            } finally {
                g.dispose();
            }
            bs.show();
            this.update(bs.getDrawGraphics());
        } while (bs.contentsLost());

//        Graphics g = bs.getDrawGraphics();
//        
//        g.dispose();
//        bs.show();
    }

}
Screen.Java:

package Game;

import Sprites.Sprite;

public class Screen {

    public int w, h;
    int xOffset = 0;
    int yOffset = 0;
    public int[] pixels;

    public Screen(int w, int h) {
        this.w = w; // 480
        this.h = h; // 320

        pixels = new int[w * h];  // 153600
    }

    public void renderSprite(int xPos, int yPos, Sprite sprite) {

        int height = sprite.h;
        int width = sprite.w;

        xPos -= xOffset;
        yPos -= yOffset;

        for(int y = 0; y < height; y++) {
            if(yPos + y < 0 || yPos + y >= h) continue;

            for(int x = 0; x < width; x++) {
                if(xPos + x < 0 || xPos + x >= w) continue;

                int col = sprite.pixels[x + (y * height)];
                if(col != -65281 && col < 0) pixels[(x + xPos) + (y + yPos) *w]= col;
            }
        }

    }

    public void setOffs(int xOffs, int yOffs) {
        xOffset = xOffs;
        yOffset = yOffs;
    }
}
Sprite.Java:

package Sprites;

import Game.Game;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;

public class Sprite {

    public int w, h;
    public int[] pixels;

    public static BufferedImage sprite = null;

    public Sprite(int w, int h) {
        this.w = w;
        this.h = h;
        pixels = new int[w * h];
    }

    public void clear(int color) {
        for(int i = 0; i < pixels.length; i++) {
            pixels[i] = color;
        }
    }

    private static BufferedImage spriteSheet;
    private static final int TILE_SIZE = 80;

    public static BufferedImage loadSprite() {



        try {

            sprite = ImageIO.read(Game.class.getResource("/valkyrie.png"));

        } catch (IOException e) {
            e.printStackTrace();
        }

        return sprite;

    }

    public static BufferedImage getSprite(int xGrid, int yGrid) {

        if(spriteSheet == null) {
            spriteSheet = loadSprite();
        }

        // xGrid and yGrid refer to each individual sprite
        return spriteSheet.getSubimage(xGrid * TILE_SIZE, yGrid * TILE_SIZE, TILE_SIZE, TILE_SIZE);

    }

}
包精灵;
进口游戏。游戏;
导入java.awt.image.buffereImage;
导入java.io.IOException;
导入javax.imageio.imageio;
公共级雪碧{
公共int w,h;
公共整数[]像素;
公共静态缓冲区映像精灵=null;
公共雪碧(int w,int h){
这个.w=w;
这个,h=h;
像素=新整数[w*h];
}
公共空白清除(整型颜色){
对于(int i=0;i
虽然我无法完整地阅读代码,但您似乎没有执行双重缓冲,这会严重影响性能

在程序的相关部分尝试以下操作:

JFrame frame = new JFrame("Valkyrie Game");
frame.add(game);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setResizable(true);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
frame.setDoubleBuffered(true); //added line, rest is the same

game.start();

你真的应该用定时器。它会解决你所有的问题

每勾一次,你都会重新画出你需要的东西

每勾一次,你应该检查一下,哪些键被按下了,哪些键没有按下,而不是添加监听器。要保持跟踪,您必须始终记住“之前”按下的键

您甚至可以创建两个计时器,一个用于图形重画,另一个用于游戏逻辑


即使计时器可能会被延迟,通常的方法是找出经过了多少时间(例如System.nanoTime),并计算您应该转发多少游戏逻辑以保持游戏始终不带标签且流畅。

这需要双缓冲。任何有很多事情在进行的游戏都需要双重缓冲


这是大量代码,请您将其简化为您认为导致问题的原因?我相信它在Game.java的渲染方法中或Level.java中的某个地方
package Player;

import Animation.Animation;
import Sprites.Sprite;
import java.awt.image.BufferedImage;

public class Player {

    // Images for each animation
    private BufferedImage[] walkingLeft = {Sprite.getSprite(0, 1), Sprite.getSprite(1, 1), Sprite.getSprite(2, 1)}; // Gets the upper left images of my sprite sheet
    private BufferedImage[] walkingRight = {Sprite.getSprite(0, 2), Sprite.getSprite(1, 2), Sprite.getSprite(2, 2)};
    private BufferedImage[] walkingUp = {Sprite.getSprite(0, 3), Sprite.getSprite(1, 3), Sprite.getSprite(2, 3)};
    private BufferedImage[] walkingDown = {Sprite.getSprite(0, 0), Sprite.getSprite(1, 0), Sprite.getSprite(2, 0)};
    private BufferedImage[] standing = {Sprite.getSprite(1, 0)};

    // These are animation states.
    public Animation walkLeft = new Animation(walkingLeft, 10);
    public Animation walkRight = new Animation(walkingRight, 10);
    public Animation walkUp = new Animation(walkingUp, 10);
    public Animation walkDown = new Animation(walkingDown, 10);
    public Animation stand = new Animation(standing, 10);

    // This is the actual animation
    public Animation animation = stand;

    public BufferedImage Player(int x, int y) {

        BufferedImage player = Sprite.getSprite(x, y);

        return player;

    }

    public void update() {

        animation.update();

    }

    public void render() {



    }

    public void setAnimation(Animation animation) {
        this.animation = animation;
    }

}
package Sprites;

import Game.Game;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;

public class Sprite {

    public int w, h;
    public int[] pixels;

    public static BufferedImage sprite = null;

    public Sprite(int w, int h) {
        this.w = w;
        this.h = h;
        pixels = new int[w * h];
    }

    public void clear(int color) {
        for(int i = 0; i < pixels.length; i++) {
            pixels[i] = color;
        }
    }

    private static BufferedImage spriteSheet;
    private static final int TILE_SIZE = 80;

    public static BufferedImage loadSprite() {



        try {

            sprite = ImageIO.read(Game.class.getResource("/valkyrie.png"));

        } catch (IOException e) {
            e.printStackTrace();
        }

        return sprite;

    }

    public static BufferedImage getSprite(int xGrid, int yGrid) {

        if(spriteSheet == null) {
            spriteSheet = loadSprite();
        }

        // xGrid and yGrid refer to each individual sprite
        return spriteSheet.getSubimage(xGrid * TILE_SIZE, yGrid * TILE_SIZE, TILE_SIZE, TILE_SIZE);

    }

}
JFrame frame = new JFrame("Valkyrie Game");
frame.add(game);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setResizable(true);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
frame.setDoubleBuffered(true); //added line, rest is the same

game.start();