《Java 2D游戏编程入门》—— 1.6 修改显示模式

简介: onExitFullScreen()方法使用所保存的显示模式,将显示返回到窗口模式。这些方法的调用,是按照进入全屏模式时相反的顺序来进行的。由于只有在全屏模式中才可以修改显示模式,因此在更改显示模式之前必须先切换模式,并且在最初的显示模式重置之前,不能设置回窗口模式。

本节书摘来异步社区《Java 2D游戏编程入门》一书中的第1章,第1.6节,作者:【美】Timothy Wright(莱特),更多章节内容可以访问云栖社区“异步社区”公众号查看。

1.6 修改显示模式

要创建全屏的应用程序,需要修改显示模式。DisplayModeTest如图1.4所示,它使用了Swing组件。这个示例也位于javagames.render包中。如果你还没有编写过任何的Swing程序,一些代码可能会看上去很陌生。有很多相关的图书和教程可供参考,并且如果要详细介绍Swing所提供的所有功能,需要比这本书更大的篇幅。

a88ec3597669ffa4caf537d3117712aaba2b4c2f

这个示例应用程序列出了所有可用的屏幕分辨率,这允许用户在全屏模式之间来回切换,以使用任何可用的显示模式。这个示例不仅展示了使用Swing组件编程,而且这段代码还用来创建一个初始的游戏界面,以供在切换到全屏游戏之前使用。这使得用户可以使用常规的Swing组件来配置系统。

这个示例还包含了一个名为DisplayModeWrapper的内部类。尽管我并不痴迷于内部类,但这个类使得该示例更容易在单个文件中展示。我宁愿每个文件中只有一个类,在其他类的内部创建类以使它们可以访问私有方法这种做法很有趣,但为了简短起见,我还是另寻它途。包装类使用equals()方法只比较显示模式的宽度和高度,而不包括位深度或刷新速率。根据操作系统的不同,很多显示模式可能只是在位深度或刷新速率上有所差异:

  • 640×480 32 bit 59 Hz
  • 640×480 32 bit 60 Hz
  • 640×480 32 bit 75 Hz
  • 640×480 16 bit 59 Hz
  • 640×480 16 bit 60 Hz

由于该程序把显示模式创建为32位并且忽略了其他模式,因此16位的模式是不可用的。为了让软件决定使用哪种刷新速率,使用了REFRESH_RATE_UNKNOWN值。通过这种方式,只有640×480的显示模式会被使用,而其他的模式会被略过。

构造方法包含了保存当前显示模式所需的代码。在软件启动之前,这个模式和用户系统的显示模式进行匹配。当应用程序返回到窗口模式的时候,使用这个显示模式来离开全屏模式。

public DisplayModeExample() {  
  GraphicsEnvironment ge =
    GraphicsEnvironment.getLocalGraphicsEnvironment();
  graphicsDevice = ge.getDefaultScreenDevice();
  currentDisplayMode = graphicsDevice.getDisplayMode();
}```
getMainPanel()方法创建了Swing组件。其中列出了可用显示模式的一个下拉列表框,切换到全屏模式的一个按钮,以及切换回窗口模式的另一个按钮。listDisplayModes()方法把显示模式的一个列表,返回到前面所介绍的一个包装器类中。包装器不仅允许搜索列表以找到高度和宽度相匹配的模式,还覆盖了toString()方法以生成在下拉列表框中易于读取的值。

onEnterFullScreen()方法首先检查以确保支持全屏模式,然后切换到全屏模式,并且随后修改显示模式。getSelectedMode()方法真正地创建一个全新的DisplayMode,它带有一个未知的刷新频率,以便能够使用默认的刷新频率。

// DisplayModeExample.java
protected void onEnterFullScreen() {
  if( graphicsDevice.isFullScreenSupported() ) {
    DisplayMode newMode = getSelectedMode();
    graphicsDevice.setFullScreenWindow( this );
    graphicsDevice.setDisplayMode( newMode );
  }
}`
onExitFullScreen()方法使用所保存的显示模式,将显示返回到窗口模式。这些方法的调用,是按照进入全屏模式时相反的顺序来进行的。由于只有在全屏模式中才可以修改显示模式,因此在更改显示模式之前必须先切换模式,并且在最初的显示模式重置之前,不能设置回窗口模式。

package javagames.render;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
public class DisplayModeExample extends JFrame {
  class DisplayModeWrapper {
    private DisplayMode dm;
    public DisplayModeWrapper( DisplayMode dm ) {
      this.dm = dm;
    }
    public boolean equals( Object obj ) {
      DisplayModeWrapper other = (DisplayModeWrapper)obj;
      if( dm.getWidth() != other.dm.getWidth() )
        return false;
      if( dm.getHeight() != other.dm.getHeight() )
        return false;
      return true;
    }
    public String toString() {
      return "" + dm.getWidth() + " x " + dm.getHeight();
    }
  }
  private JComboBox displayModes;
  private GraphicsDevice graphicsDevice;
  private DisplayMode currentDisplayMode;
  public DisplayModeExample() {
    GraphicsEnvironment ge =
      GraphicsEnvironment.getLocalGraphicsEnvironment();
    graphicsDevice = ge.getDefaultScreenDevice();
    currentDisplayMode = graphicsDevice.getDisplayMode();
  }
  private JPanel getMainPanel() {
    JPanel p = new JPanel();
    displayModes = new JComboBox( listDisplayModes() );
    p.add( displayModes );
    JButton enterButton = new JButton( "Enter Full Screen" );
    enterButton.addActionListener( new ActionListener() {
      public void actionPerformed( ActionEvent e ) {
        onEnterFullScreen();
      }
    });
    p.add( enterButton );
    JButton exitButton = new JButton( "Exit Full Screen" );
    exitButton.addActionListener( new ActionListener() {
      public void actionPerformed( ActionEvent e ) {
        onExitFullScreen();
      }
    });
    p.add( exitButton );
    return p;
  }
  private DisplayModeWrapper[] listDisplayModes() {
    ArrayList<DisplayModeWrapper> list = new
      ArrayList<DisplayModeWrapper>();
    for( DisplayMode mode : graphicsDevice.getDisplayModes() ) {
      if( mode.getBitDepth() == 32 ) {
        DisplayModeWrapper wrap = new DisplayModeWrapper( mode );
        if( !list.contains( wrap ) ) {
          list.add( wrap );
        }
      }
    }
    return list.toArray( new DisplayModeWrapper[0] );
  }
  protected void createAndShowGUI() {
    Container canvas = getContentPane();
    canvas.add( getMainPanel() );
    canvas.setIgnoreRepaint( true );
    setDefaultCloseOperation( EXIT_ON_CLOSE );
    setTitle( "Display Mode Test" );
    pack();
    setVisible( true );
  }
  protected void onEnterFullScreen() {
    if( graphicsDevice.isFullScreenSupported() ) {
      DisplayMode newMode = getSelectedMode();
      graphicsDevice.setFullScreenWindow( this );
      graphicsDevice.setDisplayMode( newMode );
    }
  }
  protected void onExitFullScreen() {
    graphicsDevice.setDisplayMode( currentDisplayMode );
    graphicsDevice.setFullScreenWindow( null );
  }
  protected DisplayMode getSelectedMode() {
    DisplayModeWrapper wrapper =
       (DisplayModeWrapper)displayModes.getSelectedItem();
    DisplayMode dm = wrapper.dm;
    int width = dm.getWidth();
    int height = dm.getHeight();
    int bit = 32;
    int refresh = DisplayMode.REFRESH_RATE_UNKNOWN;
    return new DisplayMode( width, height, bit, refresh );
  }
  public static void main( String[] args ) {
    final DisplayModeExample app = new DisplayModeExample();
    SwingUtilities.invokeLater( new Runnable() {
      public void run() {
        app.createAndShowGUI();
      }
    });
  }
相关文章
|
1月前
|
XML Java 数据库连接
谈谈Java反射:从入门到实践,再到原理
谈谈Java反射:从入门到实践,再到原理
58 0
|
5天前
|
存储 Java
模式匹配魔法:Java 21中switch语句的巨大进化
模式匹配魔法:Java 21中switch语句的巨大进化
9 0
|
18天前
|
关系型数据库 Java 开发工具
Java入门高频考查基础知识9(15问万字参考答案)
本文探讨了Spring Cloud的工作原理,包括注册中心的心跳机制、服务发现机制,以及Eureka默认的负载均衡策略。同时,概述了Spring Boot中常用的注解及其实现方式,并深入讨论了Spring事务的注解、回滚条件、传播性和隔离级别。文章还介绍了MySQL的存储引擎及其区别,特别关注了InnoDB如何实现MySQL的事务处理。此外,本文还详细探讨了MySQL索引,包括B+树的原理和设计索引的方法。最后,比较了Git和SVN的区别,并介绍了Git命令的底层原理及流程。
29 0
Java入门高频考查基础知识9(15问万字参考答案)
|
18天前
|
存储 缓存 算法
Java入门高频考查基础知识4(字节跳动面试题18题2.5万字参考答案)
最重要的是保持自信和冷静。提前准备,并对自己的知识和经验有自信,这样您就能在面试中展现出最佳的表现。祝您面试顺利!Java 是一种广泛使用的面向对象编程语言,在软件开发领域有着重要的地位。Java 提供了丰富的库和强大的特性,适用于多种应用场景,包括企业应用、移动应用、嵌入式系统等。下是几个面试技巧:复习核心概念、熟悉常见问题、编码实践、项目经验准备、注意优缺点、积极参与互动、准备好问题问对方和知其所以然等,多准备最好轻松能举一反三。
46 0
Java入门高频考查基础知识4(字节跳动面试题18题2.5万字参考答案)
|
18天前
|
存储 算法 JavaScript
Java入门高频考查算法逻辑基础知识3-编程篇(超详细18题1.8万字参考编程实现)
解决这类问题时,建议采取下面的步骤: 理解数学原理:确保你懂得基本的数学公式和法则,这对于制定解决方案至关重要。 优化算法:了解时间复杂度和空间复杂度,并寻找优化的机会。特别注意避免不必要的重复计算。 代码实践:多编写实践代码,并确保你的代码是高效、清晰且稳健的。 错误检查和测试:要为你的代码编写测试案例,测试标准的、边缘情况以及异常输入。 进行复杂问题简化:面对复杂的问题时,先尝试简化问题,然后逐步分析和解决。 沟通和解释:在编写代码的时候清晰地沟通你的思路,不仅要写出正确的代码,还要能向面试官解释你的
32 0
|
18天前
|
存储 Java 编译器
Java入门高频考查基础知识2(超详细28题2.5万字答案)
多态是面向对象编程中的一个重要概念,它允许不同类的对象对同一消息作出不同的响应。在具体实现上,多态允许一个父类的引用指向其子类的对象,并根据实际指向的对象的类型来调用相应的方法。在 Java 中,多态可以通过以下几种方式实现:在同一个类中,方法名相同,但形参列表不同,实现了多态。子类可以重写(覆盖)其父类的方法,实现多态。在父类引用中调用该方法时,根据实际指向的子类对象的类型来调用相应的方法实现。
38 0
|
28天前
|
传感器 人工智能 数据可视化
Java智慧工地监管一体化云平台APP源码 SaaS模式
高支模监测:高支模立杆及倾斜角度,高支模立杆的荷载,架体的水平位移以及模板沉降情况,当检测数据超过预警值时,实时报警。
28 2
|
1月前
|
算法 Java
Java必刷入门递归题×5(内附详细递归解析图)
Java必刷入门递归题×5(内附详细递归解析图)
20 1
|
1月前
|
Java
Java入门必刷的基础题1(八道)
Java入门必刷的基础题1(八道)
20 0
|
1月前
|
分布式计算 Oracle Java
第一篇CSDN博客——Java入门指南:学习Java编程的第一步
第一篇CSDN博客——Java入门指南:学习Java编程的第一步