Java Applet 游戏 2D 窗口滚动 [英] Java Applet Game 2D Window Scrolling

查看:25
本文介绍了Java Applet 游戏 2D 窗口滚动的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在 Java Applet 中开发 2D RPG 游戏.现在我有一个简单的椭圆形,玩家可以使用向左、向右、向上和向下移动,与小程序边界的碰撞会阻止它们.问题是,我想创建一个玩家可以移动的巨大世界(2000 像素 x 2000 倍).但是,我希望他们一次只能看到 600 像素 x 400 倍的屏幕.如果他们继续向右移动,我希望屏幕跟随他们,向上、向下和向左也是如此.谁能告诉我如何做到这一点?到目前为止,这是我的代码:

I'm trying to develop a 2D RPG Game in a Java Applet. Right now I've got a simple oval that the player can use Left, Right, Up and Down to move, and collisions against the borders of the applet stops them. The problem is, I want to create a giant world(2000px by 2000x) of area that the player can move. However, I want them only to see 600px by 400x of the screen at one time. If they keep moving right, I want the screen to follow them, same goes for up, down and left. Can anyone tell me how to do this? Here is my code so far:

import java.awt.*;
import java.awt.event.KeyEvent;
import java.applet.Applet;
import java.awt.event.KeyListener;
import javax.swing.*;

public class Main extends Applet implements Runnable, KeyListener
{
    private Image dbImage;
    private Graphics dbg;
    Thread t1;
    int x = 0;
    int y = 0;
    int prevX = x;
    int prevY = y;
    int radius = 40;
    boolean keyReleased = false;

    public void init()
    {
        setSize(600, 400);

    }

    public void start()
    {

        addKeyListener(this);
        t1 = new Thread(this);
        t1.start();
    }

    public void destroy()
    {
    }

    public void stop()
    {
    }

    public void paint(Graphics g)
    {
        //player
        g.setColor(Color.RED);
        g.fillOval(x, y, radius, radius);
    }

    public void update(Graphics g)
    {

        dbImage = createImage (this.getSize().width, this.getSize().height);
        dbg = dbImage.getGraphics();
        // initialize buffer
        if (dbImage == null)
        {
        }

        // clear screen in background
        dbg.setColor(getBackground());
        dbg.fillRect(0, 0, this.getSize().width, this.getSize().height);

        // draw elements in background
        dbg.setColor(getForeground());
        paint(dbg);
        // draw image on the screen
        g.drawImage(dbImage, 0, 0, this);
    }

    @Override
    public void run()
    {
        while (true)
        {
            //x++;
            repaint();

            try
            {
                t1.sleep(17);
            }
            catch (Exception e)
            {
            }
        }
    }

    public boolean CheckCollision(String dir)
    {
        if (x <= 0 && dir.equals("L"))
        {
            x = prevX;
            return true;
        }
        else if (y <= 0 && dir.equals("U"))
        {
            y = prevY;
            return true;
        }
        else if (x >= (getWidth() - radius) && dir.equals("R"))
        {
            System.out.println(getWidth());
            x = prevX;
            return true;
        }
        else if (y >= (getHeight() - radius) && dir.equals("D"))
        {
            y = prevY;
            return true;
        }
        return false;
    }

    @Override
    public void keyPressed(KeyEvent e)
    {
        switch (e.getKeyCode())
        {
        case KeyEvent.VK_RIGHT:
            if (!CheckCollision("R"))
            {
            x += 4;
            prevX = x;
            }
            break;
        case KeyEvent.VK_LEFT:
            if (!CheckCollision("L"))
            {
            x -= 4;
            prevX = x;
            }
            break;
        case KeyEvent.VK_UP:
            if (!CheckCollision("U"))
            {
            y -= 4;
            prevY = y;
            }
            break;
        case KeyEvent.VK_DOWN:
            if (!CheckCollision("D"))
            {
            y += 4;
            prevY = y;
            }
            break;
        }

    }

    @Override
    public void keyReleased(KeyEvent arg0)
    {
        // TODO Auto-generated method stub

    }

    @Override
    public void keyTyped(KeyEvent arg0)
    {
        // TODO Auto-generated method stub

    }
}

推荐答案

这是滚动可视区域的基本示例,其中虚拟世界比可视区域大.

This is a basic example of scrolling viewable area, where the virtual world is large then the view area.

这基本上维护了一些参数.它保持世界上视图的顶部/左侧所在的点以及玩家在世界中的位置.

This basically maintains a number of parameters. It maintains the point where in the world the top/left of the view is and the players position within the world.

这些值被转换回现实世界坐标(其中 0x0 是可视区域的左上角).

These values are converted back to real world coordinates (where 0x0 is the top left corner of the viewable area).

示例还使用 BufferedImage#getSubImage 使其更易于渲染.您也可以计算地图到视图的偏移位置,但这归结为需要...

The examples also use BufferedImage#getSubImage to make it easier to render. You could calculate the offset position of the map to the view as well, but that comes down to needs...

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class MiddleEarth {

    public static void main(String[] args) {
        new MiddleEarth();
    }

    public MiddleEarth() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new WorldPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class WorldPane extends JPanel {

        private BufferedImage map;
        private BufferedImage party;
        private Point viewPort;
        private Point partyPoint;
        private BufferedImage view;

        public WorldPane() {
            try {
                map = ImageIO.read(getClass().getResource("/MiddleEarth.jpg"));
                party = ImageIO.read(getClass().getResource("/8BitFrodo.png"));

                viewPort = new Point(0, (map.getHeight() / 2) - 100);
                partyPoint = new Point(party.getWidth() / 2, (map.getHeight() / 2)); // Virtual Point...

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

            InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
            ActionMap am = getActionMap();

            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), "goRight");
            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), "goLeft");
            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), "goUp");
            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0), "goDown");

            am.put("goRight", new AbstractAction() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    moveParty(10, 0);
                }
            });
            am.put("goLeft", new AbstractAction() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    moveParty(-10, 0);
                }
            });

            am.put("goUp", new AbstractAction() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    moveParty(0, -10);
                }
            });
            am.put("goDown", new AbstractAction() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    moveParty(0, 10);
                }
            });

        }

        protected void moveParty(int xDelta, int yDelta) {
            partyPoint.x += xDelta;
            partyPoint.y += yDelta;
            Point view = fromWorld(partyPoint);
            if (view.x > getWidth() - (party.getWidth() / 2)) {
                viewPort.x += xDelta;
                if (viewPort.x + getWidth() > map.getWidth()) {
                    viewPort.x = map.getWidth() - getWidth();
                    partyPoint.x = map.getWidth() - (party.getWidth() / 2) - 1;
                }
                invalidate();
            } else if (view.x < party.getWidth() / 2) {
                viewPort.x += xDelta;
                if (viewPort.x < 0) {
                    viewPort.x = 0;
                    partyPoint.x = (party.getWidth() / 2);
                }
                invalidate();
            }
            System.out.println(view + "; " + getHeight());
            if (view.y > getHeight() - (party.getHeight() / 2)) {
                viewPort.y += yDelta;
                if (viewPort.y + getHeight() > map.getHeight()) {
                    viewPort.y = map.getHeight() - getHeight();
                    partyPoint.y = map.getHeight() - (party.getHeight() / 2) - 1;
                }
                invalidate();
            } else if (view.y < party.getHeight() / 2) {
                viewPort.y += yDelta;
                if (viewPort.y < 0) {
                    viewPort.y = 0;
                    partyPoint.y = (party.getHeight() / 2);
                }
                invalidate();
            }
            repaint();
        }

        @Override
        public void invalidate() {
            view = null;
            super.invalidate();
        }

        public BufferedImage getView() {

            if (view == null && getWidth() > 0 && getHeight() > 0) {

                view = map.getSubimage(viewPort.x, viewPort.y, getWidth(), getHeight());

            }

            return view;

        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(400, 400);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            if (map != null) {
                g2d.drawImage(getView(), 0, 0, this);

                Point real = fromWorld(partyPoint);

                int x = real.x - (party.getWidth() / 2);
                int y = real.y - (party.getHeight()/ 2);
                g2d.drawImage(party, x, y, this);
            }
            g2d.dispose();
        }

        protected Point fromWorld(Point wp) {

            Point p = new Point();

            p.x = wp.x - viewPort.x;
            p.y = wp.y - viewPort.y;

            return p;

        }
    }
}

这篇关于Java Applet 游戏 2D 窗口滚动的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆