如何让玩家角色和世界同时滚动?

时间:2012-09-04 18:40:55

标签: java swing camera awt

如何让播放器和世界同时滚动? 因为不管我做什么总是有一点延迟...... 我的观点是:我的游戏是2d sidescroller(terraria / minecraft / rpg)游戏,我需要能够将地形与世界一起移动...

Player.java

package game.test.src;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;

import javax.swing.ImageIcon;

    public class Player {

        static final int MOVE_UP = 0, MOVE_DOWN = 1, MOVE_LEFT= 2, MOVE_RIGHT = 3;
        private World world;

        private Rectangle playerRect;
        private Image playerImg;

        //Block Variables
        private int hoverX, hoverY;
        private boolean hovering = false;

        protected static int xDirection;
        protected static int yDirection;
        private Weapon weapon;

        public Player(World world){
            this.world = world;
            playerImg = new ImageIcon("H:/2D game test/Game test 2/src/game/test/src/images/Character.png").getImage();
            playerRect = new Rectangle(50, 0, 10, 36);
            weapon = new Weapon(weapon.PICKAXE);
        }
        private static void setXDirection(int d){
            xDirection = d;

        }
        private static void setYDirection(int d){
            yDirection = d;

        }
        public void update()
        {
            move();
            checkForCollision();

        }
        private void checkForCollision() {



        }
        private void move()
        {
            playerRect.x += xDirection;
            playerRect.y += yDirection;
            gravity();
        }
        private void gravity()
        {
            for(int i=0;i<world.arrayNum; i++)
            {
                if(!world.isSolid[i])
                {
                    setYDirection(1);

                }
                else if(world.isSolid[i] && playerRect.intersects(world.blocks[i]))
                {
                    setYDirection(0);
                }
            }
        }
        //MotionEvents

        public void mousePressed(MouseEvent e)
        {

        }

        public void mouseReleased(MouseEvent e)
        {

        }

        public void mouseClicked(MouseEvent e)
        {

        }

        public void mouseMoved(MouseEvent e)
        {
            int x = e.getX();
            int y = e.getY();
            int px = playerRect.x;
            int py = playerRect.y;
            for(int i = 0; i < world.arrayNum; i++)
            {
                if(weapon.isEquipped(Weapon.PICKAXE) &&
                        x > world.blocks[i].x && x < world.blocks[i].x + world.blocks[i].width && 
                        y > world.blocks[i].x && y < world.blocks[i].y + world.blocks[i].height && world.isSolid[i] && 
                        (world.blocks[i].x + (world.blocks[i].width / 2) ) <= (px + playerRect.width/2) + weapon.WEAPON_RADIUS &&
                        (world.blocks[i].x + (world.blocks[i].width / 2) ) >= (px + playerRect.width/2) - weapon.WEAPON_RADIUS &&
                        (world.blocks[i].y + (world.blocks[i].height / 2) ) <= (py + playerRect.height/2) + weapon.WEAPON_RADIUS &&
                        (world.blocks[i].y + (world.blocks[i].height / 2) ) >= (py + playerRect.height/2) - weapon.WEAPON_RADIUS)

                {
                    hovering = true;
                    hoverX = world.blocks[i].x;
                    hoverY = world.blocks[i].y;
                    break;
                }
                else
                    hovering = false;
            }
        }
        public void mouseDragged(MouseEvent e)
        {

        }
        public void mouseEntered(MouseEvent e)
        {

        }
        public void mouseExited(MouseEvent e)
        {

        }

        //Drawing Methods
        public void draw(Graphics g)
        {
            g.drawImage(playerImg, playerRect.x, playerRect.y, null);
            if(hovering)
                drawBlockOutline(g);

        }

        private void drawBlockOutline(Graphics g)
        {
            g.setColor(Color.black);
            g.drawRect(hoverX, hoverY, world.blocks[0].width,world.blocks[0].height);
        }



        private class Weapon
        {
            public static final int UNARMED = 0;
            public static final int PICKAXE = 1; 
            public static final int GUN = 2;

            public int CURRENT_WEAPON;

            public int WEAPON_RADIUS;

            public Weapon(int w)

            {
                switch(w)
                {
                    default:
                        System.out.println("No weapon selected");
                        break;
                    case UNARMED:
                        CURRENT_WEAPON = UNARMED;
                        WEAPON_RADIUS = 100;
                        break;

                    case PICKAXE:
                        CURRENT_WEAPON = PICKAXE;
                        WEAPON_RADIUS = 100;
                        break;

                    case GUN:
                        CURRENT_WEAPON = GUN;
                        WEAPON_RADIUS = 100;
                        break;

                }

            }

            public void selectWeapon(int w)
            {
                switch(w)
                {
                    default:
                        System.out.println("No weapon selected");
                        break;
                    case UNARMED:
                        CURRENT_WEAPON = UNARMED;
                        WEAPON_RADIUS = 100;
                        break;

                    case PICKAXE:
                        CURRENT_WEAPON = PICKAXE;
                        WEAPON_RADIUS = 100;
                        break;

                    case GUN:
                        CURRENT_WEAPON = GUN;
                        WEAPON_RADIUS = 100;
                        break;

                }

            }

            public boolean isEquipped(int w)

            {
                if(w == CURRENT_WEAPON)
                {
                    return true;
                }
                else
                    return false;



            }


        }
        public void moveMap(){
            for(Rectangle r : world.blocks){
                r.x += xDirection;
                r.y += yDirection;
            }
        }
        public static void stopMoveMap(){
            setXDirection(0);
            setYDirection(0);
        }
        private static void setXDirection1(int dir){
            xDirection = dir;
        }
        private static void setYDirection1(int dir){
            yDirection = dir;
        }

        public static void navigatePlayer(int nav){
            switch(nav){
                default:
                    System.out.println("default case entered... Doing nothing.");
                    break;
                case MOVE_UP:
                    setYDirection1(-1);
                    break;
                case MOVE_DOWN:
                    setYDirection1(1);
                    break;
                case MOVE_LEFT:
                    setXDirection1(-1);
                    break;
                case MOVE_RIGHT:
                    setXDirection1(1);
                    break;
            }
        }
    }

World.java

package game.test.src;

import java.awt.Graphics;
import java.awt.Image;
import java.awt.Rectangle;

import javax.swing.ImageIcon;

public class World {

    public Rectangle[] blocks;
    public boolean[] isSolid;
    public Image[] blockImg;
    public final int arrayNum = 500;

    //Block Images
    public Image BLOCK_GRASS, BLOCK_DIRT, BLOCK_STONE, BLOCK_SKY;

    private int x, y, xDirection, yDirection;;

    //map navigation
    static final int PAN_UP = 0, PAN_DOWN = 1, PAN_LEFT= 2, PAN_RIGHT = 3;

    public World(){
        BLOCK_GRASS = new ImageIcon("H:/2D game test/Game test 2/src/game/test/src/images/tile_grass.png").getImage();
        BLOCK_DIRT = new ImageIcon("H:/2D game test/Game test 2/src/game/test/src/images/tile_dirt.png").getImage();
        BLOCK_STONE = new ImageIcon("H:/2D game test/Game test 2/src/game/test/src/images/tile_stone.png").getImage();
        BLOCK_SKY = new ImageIcon("H:/2D game test/Game test 2/src/game/test/src/images/tile_sky.png").getImage();
        blocks = new Rectangle[500];
        blockImg = new Image[500];
        isSolid = new boolean[arrayNum];
        loadArrays();
    }

    private void loadArrays(){
        for(int i = 0; i < arrayNum; i++){
            if(x >= 500){
                x = 0;
                y += 20;
            }
            if(i >= 0 && i < 100){
                blockImg[i] = BLOCK_SKY;
                isSolid[i] = false;
                blocks[i] = new Rectangle(x, y, 20, 20);
            }
            if(i >= 100 && i < 125){
                blockImg[i] = BLOCK_GRASS;
                isSolid[i] = true;
                blocks[i] = new Rectangle(x, y, 20, 20);
            }
            if(i >= 125 && i < 225){
                blockImg[i] = BLOCK_DIRT;
                isSolid[i] = true;
                blocks[i] = new Rectangle(x, y, 20, 20);
            }
            if(i >= 225 && i < 500){
                blockImg[i] = BLOCK_STONE;
                isSolid[i] = true;
                blocks[i] = new Rectangle(x, y, 20, 20);
            }
            x += 20;
        }
    }

    public void draw(Graphics g){
        for(int i = 0; i < arrayNum; i++){
            g.drawImage(blockImg[i], blocks[i].x, blocks[i].y, null);
        }
    }

    public void moveMap(){
        for(Rectangle r : blocks){
            r.x += xDirection;
            r.y += yDirection;
        }
    }
    public void stopMoveMap(){
        setXDirection(0);
        setYDirection(0);
    }
    private void setXDirection(int dir){
        xDirection = dir;
    }
    private void setYDirection(int dir){
        yDirection = dir;
    }
    public void navigateMap(int nav){
        switch(nav){
            default:
                System.out.println("default case entered... Doing nothing.");
                break;
            case PAN_UP:
                setYDirection(-1);
                break;
            case PAN_DOWN:
                setYDirection(1);
                break;
            case PAN_LEFT:
                setXDirection(-1);
                break;
            case PAN_RIGHT:
                setXDirection(1);
                break;
        }
    }
}

GamePanel.java

package game.test.src;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.swing.JPanel;

public class GamePanel extends JPanel implements Runnable {
    //Double buffering
    private Image dbImage;
    private Graphics dbg;
    //JPanel variables
    static final int GWIDTH = 500, GHEIGHT = 400;
    static final Dimension gameDim = new Dimension(GWIDTH, GHEIGHT);
    //Game variables
    private static final int DELAYS_BEFORE_YIELD = 10; 
    private Thread game;
    private volatile boolean running = false;
    private long period = 6*1000000; //ms -> nano
    //Game Objects
    World world;
    Player p1;
    public GamePanel(){
        world = new World();
        p1 = new Player(world);

        setPreferredSize(gameDim);
        setBackground(Color.WHITE);
        setFocusable(true);
        requestFocus();
        //Handle all key inputs from user
        addKeyListener(new KeyAdapter(){
            @Override
            public void keyPressed(KeyEvent e){
                if(e.getKeyCode() == KeyEvent.VK_LEFT){
                    Player.navigatePlayer(Player.MOVE_LEFT);
                    world.navigateMap(World.PAN_LEFT);
                }
                if(e.getKeyCode() == KeyEvent.VK_RIGHT){
                    Player.navigatePlayer(Player.MOVE_RIGHT);
                    world.navigateMap(World.PAN_RIGHT);
                }
                if(e.getKeyCode() == KeyEvent.VK_UP){
                    Player.navigatePlayer(Player.MOVE_UP);
                    world.navigateMap(World.PAN_UP);
                }
                if(e.getKeyCode() == KeyEvent.VK_DOWN){
                    Player.navigatePlayer(Player.MOVE_DOWN);
                    world.navigateMap(World.PAN_DOWN);
                }
            }
            @Override
            public void keyReleased(KeyEvent e){
                Player.stopMoveMap();
                world.stopMoveMap();                
            }
            @Override
            public void keyTyped(KeyEvent e){

            }

        });
        addMouseListener(new MouseAdapter()
        {
            @Override
            public void mousePressed(MouseEvent e)
            {

            }
            @Override
            public void mouseReleased(MouseEvent e)
            {

            }
            @Override
            public void mouseClicked(MouseEvent e)
            {

            }
        });
        addMouseMotionListener(new MouseAdapter()
        {
            public void mouseMoved(MouseEvent e)
            {
                p1.mouseMoved(e);
            }
            public void mouseDragged(MouseEvent e)
            {

            }
            public void mouseEntered(MouseEvent e)
            {

            }
            public void mouseExited(MouseEvent e)
            {

            }

        });

    }

    public void run(){
        long beforeTime, afterTime, diff, sleepTime, overSleepTime = 0;
        int delays = 0;
        while(running){
            beforeTime = System.nanoTime();
            gameUpdate();
            gameRender();
            paintScreen();
            afterTime = System.nanoTime();
            diff = afterTime - beforeTime;
            sleepTime = (period - diff) - overSleepTime;
            //if sleepTime is between peiod and 0, then sleep
            if(sleepTime < period && sleepTime > 0)
            {
                try{
                    Thread.sleep(sleepTime/1000000L);
                    overSleepTime = 0;
                }catch(InterruptedException ex){
                    Logger.getLogger(GamePanel.class.getName()).log(Level.SEVERE, "EXCEPTION");
                }
            }
            //the diff was greater than the period
            else if(diff > period)
            {
                overSleepTime = diff - period;
            }
            else if(++delays >= DELAYS_BEFORE_YIELD)
            {
                Thread.yield();
                delays = 0;
                overSleepTime = 0;
            }
            //the loop took less time than expected
            else
            {
                overSleepTime = 0;
            }
        }
    }

    private void gameUpdate(){
        if(running && game != null){
            world.moveMap();
            p1.update();
        }
    }

    private void gameRender(){
        if(dbImage == null){ // Create the buffer
            dbImage = createImage(GWIDTH, GHEIGHT);
            if(dbImage == null){
                System.err.println("dbImage is still null!");
                return;
            }else{
                dbg = dbImage.getGraphics();
            }
        }
        //Clear the screen
        dbg.setColor(Color.WHITE);
        dbg.fillRect(0, 0, GWIDTH, GHEIGHT);
        //Draw Game elements
        draw(dbg);
    }

    /* Draw all game content in this method */
    public void draw(Graphics g){
        world.draw(g);
        p1.draw(g);
    }

    private void paintScreen(){
        Graphics g;
        try{
            g = this.getGraphics();
            if(dbImage != null && g != null){
                g.drawImage(dbImage, 0, 0, null);
            }
            Toolkit.getDefaultToolkit().sync(); //For some operating systems
            g.dispose();
        }catch(Exception e){
            System.err.println(e);
        }
    }

    public void addNotify(){
        super.addNotify();
        startGame();
    }

    private void startGame(){
        if(game == null || !running){
            game = new Thread(this);
            game.start();
            running = true;
        }
    }

    public void stopGame(){
        if(running){
            running = false;
        }
    }

    private void log(String s){
        System.out.println(s);
    }
}

感谢您的帮助!

0 个答案:

没有答案