拉伸游戏以适应屏幕尺寸并保持坐标系统

时间:2017-05-27 02:14:29

标签: java jframe jpanel

我正在尝试创建一个类似于此tutorial的游戏,您可以在其中找到源代码。在GameFrame中,有GamePanel。在GamePanel中,有StatsPanel和PlayPanel。 GameFnel和GamePanel分别是1280乘640,StatPaPanel在GamePanel的顶部是1280乘40,PlayPanel底部是PlayPanel的1280乘600.

但是,我希望让游戏全屏,但由于不同屏幕尺寸的差异,我不希望更改坐标系。所以这是我的问题:如何拉伸游戏以适应屏幕尺寸并保持坐标系参考?

我相信有可能将游戏渲染为图像,然后缩放以适应屏幕。通过这种方式,我仍然可以参考1280乘640边界框内的组件。我不知道在哪里以及如何实现这一点。

到目前为止我所尝试的内容(参考教程的源代码):

GameFrame(扩展JFrame)

构造

this.setLocation((int)((Toolkit.getDefaultToolkit().getScreenSize().getWidth()-WIDTH)/2),
            ((int)(Toolkit.getDefaultToolkit().getScreenSize().getHeight()-HEIGHT)/2));     
this.setSize(WIDTH,HEIGHT);

替换为:

this.setLocation(0,0);
this.setSize(Toolkit.getDefaultToolkit().getScreenSize());
this.setExtendedState(JFrame.MAXIMIZED_BOTH); 
this.setUndecorated(true);

GameManager(扩展线程)

run()方法:

gamePanel.repaintGame();

替换为:

gamePanel.repaint();

GamePanel(扩展JPanel)

repaintGame()方法:

public void repaintGame(){
    playPanel.repaint();
}

替换为paintComponent()方法:

public void paintComponent(Graphics g)
{
    super.paintComponent(g);
    playPanel.repaint();
    BufferedImage img = new BufferedImage(1280, 640, BufferedImage.TYPE_INT_RGB);
    g.drawImage(img, 0, 0, getWidth(), getHeight(), 0, 0, 1280, 640, null);
}

这些更改并未使游戏适应屏幕大小。虽然GameFrame和黑色GamePanel跨越屏幕大小,但StatsPanel和PlayPanel似乎仍保留在1280 x 640边界框中。

我对Java不太有经验,所以请原谅我的疏忽。

编辑:更改后的图像(忽略终端窗口):

Screenshot

评论了c0der的回答:

  

我的主要问题是维护坐标系。例如,点(500,300)在1920×1080屏幕上与其在1280×640屏幕中的位置不同。因此,我想知道是否可以将GamePanel及其组件StatsPanel和PlayPanel在整个屏幕GameFrame中拉伸为图像或其他方式。这样,点(500,300)将始终引用GamePanel中的(500,300),随后GamePanel将在屏幕上拉伸。我已将照片上传到我的帖子。我希望将游戏扩展到屏幕大小。

1 个答案:

答案 0 :(得分:0)

假设这是布局的良好表示:

import java.awt.Color;
import java.awt.Toolkit;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class GameFrame extends JFrame {

    public static final int WIDTH=1280;
    public static final int HEIGHT=640;

    public GameFrame(GamePanel gamePanel){

        //set frame to appear at the center of the screen
        this.setLocation((int)((Toolkit.getDefaultToolkit().getScreenSize().getWidth()-WIDTH)/2),
                ((int)(Toolkit.getDefaultToolkit().getScreenSize().getHeight()-HEIGHT)/2));

        this.setSize(WIDTH,HEIGHT);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setResizable(false);

        this.add(gamePanel);
        setVisible(true);
    }

    public static void main(String[] args) {

        new GameFrame(new GamePanel());
    }
}

class GamePanel extends JPanel{

    public static final int PLAY_PANEL_HEIGHT=640;
    public static final int STATS_HEIGHT=40;

    public GamePanel(){

        this.setSize(WIDTH, HEIGHT);
        setLayout(null);
        setBackground(Color.BLACK);

        JPanel statsPanel= new JPanel();
        statsPanel.setSize(GameFrame.WIDTH, STATS_HEIGHT);
        statsPanel.setLayout(null);
        statsPanel.setBackground(Color.CYAN);

        statsPanel.setLocation(0, 0);
        this.add(statsPanel);

        JPanel playPanel=new JPanel();
        playPanel.setSize(GameFrame.WIDTH, PLAY_PANEL_HEIGHT);
        playPanel.setLayout(null);
        playPanel.setBackground(Color.DARK_GRAY);
        playPanel.setLocation(0, STATS_HEIGHT);
        this.add(playPanel);
    }
}

按照评论中的说明进行更改,使其全屏显示:

public class GameFrame extends JFrame {

    public GameFrame(GamePanel gamePanel){

        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setResizable(false);
        this.add(gamePanel);

        setExtendedState(JFrame.MAXIMIZED_BOTH);
        setUndecorated(true);
        setVisible(true); //make sure you have means to close the window
    }

    public static void main(String[] args) {

        new GameFrame(new GamePanel());
    }
}

class GamePanel extends JPanel{

    public static final int STATS_HEIGHT=40;

    public GamePanel(){

        //using null layout manager requires that you manually handle all size or
        //other layout changes. a much better practice is to use layout manager
        setLayout(new BorderLayout());//use BorderLayout instead of null
        setBackground(Color.BLACK);

        JPanel statsPanel= new JPanel();
        //width is ignored for NORTH components of BorderLyayout
        statsPanel.setPreferredSize(new Dimension(0, STATS_HEIGHT));
        statsPanel.setLayout(null);
        statsPanel.setBackground(Color.CYAN);
        this.add(statsPanel, BorderLayout.NORTH);

        JPanel playPanel=new JPanel();
        //height is ignored for CENTER components of BorderLyayout
        playPanel.setPreferredSize(new Dimension(WIDTH, 0));
        playPanel.setBackground(Color.DARK_GRAY);
        this.add(playPanel, BorderLayout.CENTER);
    }
}

修改
拉伸图像意味着要么让每个像素变大,要么不控制,或者在你的情况下增加像素。
添加像素显然会将(500,300)坐标(作为示例)更改为其他内容。
我看到两个选择:
一个。无论帧大小如何,都要将GamePanel保持为固定大小。
湾根据实际大小动态计算坐标,而不是使用(500,300)等固定值。
我建议选择b。