为了账号安全,请及时绑定邮箱和手机立即绑定

Java Applet Game 2D窗口滚动

/ 猿问

Java Applet Game 2D窗口滚动

慕容3067478 2019-10-21 15:34:48

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


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;

        }

 

查看完整描述

3 回答

?
青春有我

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


这基本上维护了许多参数。它保持了视图的顶部/左侧在世界上的位置以及玩家在世界上的位置。


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


这些示例还BufferedImage#getSubImage使渲染更容易。您也可以计算地图到视图的偏移位置,但这取决于需求...


//img3.mukewang.com/5dad5fd4000170f404450466.jpg

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;


        }

    }

}

分享编辑


查看完整回答
反对 回复 2019-10-21
?
12345678_0001

这就是我在引擎中所做的事情。


我将保留两个变量OffSetX,OffSetY


并计算它们的每一步,以使玩家居中。


OffSetX = 0;

OffSetY = 0;

if (MAP_WIDTH > WINDOW_WIDTH) {

    OffSetX = Math.round(WINDOW_WIDTH / 2 - obj.getX() - TILE_SIZE);

    OffSetX = Math.min(OffSetX, 0);

    OffSetX = Math.max(OffSetX, WINDOW_WIDTH - MAP_WIDTH);

}

if (MAP_HEIGHT > WINDOW_HEIGHT) {

    OffSetY = Math.round(WINDOW_HEIGHT / 2 - obj.getY() - TILE_SIZE);

    OffSetY = Math.min(OffSetY, 0);

    OffSetY = Math.max(OffSetY, WINDOW_HEIGHT - MAP_HEIGHT);

}

然后在该位置绘制地图,(OffSetX, OffSetY)即仅将这些添加到要绘制的对象的原始位置。


您可能要跳过不可见的渲染对象。


查看完整回答
反对 回复 2019-10-21
?
慕神8447489

线程“ AWT-EventQueue-0”中的异常java.lang.IllegalArgumentException:输入== null!在MiddleEarth $ WorldPane的javax.imageio.ImageIO.read(未知源)处。在MiddleEarth $ 1.run(MiddleEarth.java:39)的<init>(MiddleEarth.java:62)在java.awt.event.InvocationEvent.dispatch( java.awt.EventQueue.dispatchEventImpl(未知源)java.awt.EventQueue.access $ 200(java.awt.EventQueue $ 3.run中的未知源)(java.awt.EventQueue $ 3.run中的未知源) (未知源),位于java.security.AccessController.doPrivileged(本机方法)

查看完整回答
反对 回复 2019-10-21

添加回答

回复

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信