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

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

问题描述

我想开发一个2D角色扮演游戏中的Java小程序。现在我有一个简单的椭圆形,玩家可以使用左,右,向上和向下移动,对小程序的边界冲突阻止他们。问题是,我想(通过2000X 2000px)创建区域,玩家可以移动的一个巨大的世界。不过,我想他们只看到600px的由屏幕的400X在同一时间。如果他们继续前进吧,我想在屏幕跟着他们,同样为向上,向下和向左。谁能告诉我如何做到这一点?这是我的code到目前为止:

 进口java.awt中的*。
进口java.awt.event.KeyEvent中;
进口java.applet.Applet中;
进口java.awt.event.KeyListener;
进口的javax.swing *。

公共类主要扩展的Applet实现Runnable,的KeyListener
{
    私人图像数据库图像;
    私人显卡DBG;
    线T1;
    INT X = 0;
    INT Y = 0;
    INT preVX = X;
    INT preVY = Y;
    INT半径= 40;
    布尔的keyReleased = FALSE;

    公共无效的init()
    {
        的setSize(600,400);

    }

    公共无效启动()
    {

        addKeyListener(本);
        T1 =新主题(本);
        t1.start();
    }

    公共无效的destroy()
    {
    }

    公共无效停止()
    {
    }

    公共无效漆(图形G)
    {
        //播放器
        g.setColor(Color.RED);
        g.fillOval(X,Y,半径,半径);
    }

    公共无效更新(图形G)
    {

        数据库图像=的createImage(this.getSize()宽,this.getSize()的高度。);
        DBG = dbImage.getGraphics();
        //初始化缓冲区
        如果(数据库图像== NULL)
        {
        }

        //在背景画面清晰
        dbg.setColor(的getBackground());
        dbg.fillRect(0,0,this.getSize()宽度,this.getSize()高度。);

        //绘制背景元素
        dbg.setColor(getForeground());
        油漆(DBG);
        //绘制图像在屏幕上
        g.drawImage(数据库图像,0,0,这一点);
    }

    @覆盖
    公共无效的run()
    {
        而(真)
        {
            // X ++;
            重画();

            尝试
            {
                t1.sleep(17);
            }
            赶上(例外五)
            {
            }
        }
    }

    公共布尔CheckCollision(字符串DIR)
    {
        如果(X LT; = 0&安培;&安培; dir.equals(L))
        {
            X = preVX;
            返回true;
        }
        否则如果(γ&所述; = 0&安培;&安培; dir.equals(U))
        {
            Y = preVY;
            返回true;
        }
        否则如果(X GT; =(的getWidth() - 半径)及&安培; dir.equals(R))
        {
            的System.out.println(的getWidth());
            X = preVX;
            返回true;
        }
        否则如果(γ> =(的getHeight() - 半径)及&安培; dir.equals(D))
        {
            Y = preVY;
            返回true;
        }
        返回false;
    }

    @覆盖
    公共无效键pressed(KeyEvent e而)
    {
        开关(e.getKey code())
        {
        案例KeyEvent.VK_RIGHT:
            如果(!CheckCollision(R))
            {
            X + = 4;
            preVX = X;
            }
            打破;
        案例KeyEvent.VK_LEFT:
            如果(!CheckCollision(L))
            {
            x  -  = 4;
            preVX = X;
            }
            打破;
        案例KeyEvent.VK_UP:
            如果(!CheckCollision(U))
            {
            Ÿ -  = 4;
            preVY = Y;
            }
            打破;
        案例KeyEvent.VK_DOWN:
            如果(!CheckCollision(D))
            {
            Y + = 4;
            preVY = Y;
            }
            打破;
        }

    }

    @覆盖
    公共无效调用keyReleased(KeyEvent的为arg0)
    {
        // TODO自动生成方法存根

    }

    @覆盖
    公共无效的keyTyped(KeyEvent的为arg0)
    {
        // TODO自动生成方法存根

    }
}
 

解决方案

这是滚动的可视面积,在虚拟世界是很大的一个基本的例子,然后在视图区。

此基本保持了若干参数。它保持在世界何处的顶部/视图的左边的点是与世界中的玩家位置

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

该示例还使用的BufferedImage#getSubImage 来使其更容易呈现。你可以计算出地图视图的偏移位置为好,但归结为需求...

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

公共类MiddleEarth {

    公共静态无效的主要(字串[] args){
        新MiddleEarth();
    }

    公共MiddleEarth(){
        EventQueue.invokeLater(新的Runnable(){
            @覆盖
            公共无效的run(){
                尝试 {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                }赶上(ClassNotFoundException的| InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException前){
                }

                JFrame的框架=新的JFrame(测试);
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(新的BorderLayout());
                frame.add(新WorldPane());
                frame.pack();
                frame.setLocationRelativeTo(空);
                frame.setVisible(真正的);
            }
        });
    }

    公共类WorldPane继承JPanel {

        私人BufferedImage的地图;
        私人的BufferedImage方;
        私人点视口;
        私人点partyPoint;
        私人BufferedImage的观点;

        公共WorldPane(){
            尝试 {
                地图= ImageIO.read(的getClass()的getResource(/ MiddleEarth.jpg)。);
                党= ImageIO.read(的getClass()的getResource(/ 8BitFrodo.png));

                视口=新点(0,(map.getHeight()/ 2) -  100);
                partyPoint =新点(party.getWidth()/ 2,(map.getHeight()/ 2)); //虚拟点...

            }赶上(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),货仓);

            am.put(goRight,新AbstractAction(){
                @覆盖
                公共无效的actionPerformed(ActionEvent的E){
                    moveParty(10,0);
                }
            });
            am.put(goLeft,新AbstractAction(){
                @覆盖
                公共无效的actionPerformed(ActionEvent的E){
                    moveParty(-10,0);
                }
            });

            am.put(党团,新AbstractAction(){
                @覆盖
                公共无效的actionPerformed(ActionEvent的E){
                    moveParty(0,-10);
                }
            });
            am.put(仓库,新AbstractAction(){
                @覆盖
                公共无效的actionPerformed(ActionEvent的E){
                    moveParty(0,10);
                }
            });

        }

        保护无效moveParty(INT xDelta,诠释yDelta){
            partyPoint.x + = xDelta;
            partyPoint.y + = yDelta;
            来看= fromWorld(partyPoint);
            如果(view.x>的getWidth() - (party.getWidth()/ 2)){
                viewPort.x + = xDelta;
                如果(viewPort.x +的getWidth()> map.getWidth()){
                    viewPort.x = map.getWidth() - 的getWidth();
                    partyPoint.x = map.getWidth() - (party.getWidth()/ 2) -  1;
                }
                无效();
            }否则如果(view.x&其中; party.getWidth()/ 2){
                viewPort.x + = xDelta;
                如果(viewPort.x℃,){
                    viewPort.x = 0;
                    partyPoint.x =(party.getWidth()/ 2);
                }
                无效();
            }
            的System.out.println(查看+,+的getHeight());
            如果(view.y>的getHeight() - (party.getHeight()/ 2)){
                viewPort.y + = yDelta;
                如果(viewPort.y +的getHeight()> map.getHeight()){
                    viewPort.y = map.getHeight() - 的getHeight();
                    partyPoint.y = map.getHeight() - (party.getHeight()/ 2) -  1;
                }
                无效();
            }否则如果(view.y&其中; party.getHeight()/ 2){
                viewPort.y + = yDelta;
                如果(viewPort.y℃,){
                    viewPort.y = 0;
                    partyPoint.y =(party.getHeight()/ 2);
                }
                无效();
            }
            重画();
        }

        @覆盖
        公共无效无效(){
            鉴于= NULL;
            super.invalidate();
        }

        公共BufferedImage的getView(){

            如果(图==空&安培;&安培;的getWidth()大于0&安培;&安培;的getHeight()大于0){

                视图= map.getSubimage(viewPort.x,viewPort.y,的getWidth(),的getHeight());

            }

            返回查看;

        }

        @覆盖
        公共维度的get preferredSize(){
            返回新尺寸(400,400);
        }

        @覆盖
        保护无效paintComponent(图形G){
            super.paintComponent方法(G);
            Graphics2D的G2D =(Graphics2D的)g.create();
            如果(图!= NULL){
                g2d.drawImage(getView(),0,0,这一点);

                点实= fromWorld(partyPoint);

                INT X = real.x  - (party.getWidth()/ 2);
                INT Y = real.y  - (party.getHeight()/ 2);
                g2d.drawImage(党,X,Y,这一点);
            }
            g2d.dispose();
        }

        保护点fromWorld(点WP){

            点P =新的点();

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

            返回磷;

        }
    }
}
 

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.

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

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小程序游戏2D窗口滚动的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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