《Java 2D游戏编程入门》—— 1.3 使用主动渲染

简介: 前面的示例使用了一种叫做被动渲染(passive rendering)的技术。该应用程序在paint()方法中重新绘制自身,但是,由Swing库来决定什么时候调用该方法。事件分派线程处理Swing组件的渲染,而这并不由你来控制。尽管这对于常规应用程序来说很好,但对于游戏不推荐这么做。

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

1.3 使用主动渲染

前面的示例使用了一种叫做被动渲染(passive rendering)的技术。该应用程序在paint()方法中重新绘制自身,但是,由Swing库来决定什么时候调用该方法。事件分派线程处理Swing组件的渲染,而这并不由你来控制。尽管这对于常规应用程序来说很好,但对于游戏不推荐这么做。

要处理渲染,可以使用BufferStrategy类,但这需要对应用程序的结构做一些修改。这将允许应用程序把渲染代码放在一个单独的线程中,并且由整个进程来控制。

把游戏代码放在paint()方法之外,通常有3个理由。首先,在paint()方法中不应该有任何需要很长的执行时间或阻塞时间的代码,因为这会阻止GUI接受绘制事件。其次,要使用全屏独占模式的话,渲染代码需要在一个不同的线程中。最后,并且也是最重要的原因,当从头开始处理绘制的时候,渲染代码会更快一些。为了利用主动渲染的好处,不管是在窗口还是全屏模式下,都要创建一个定制的渲染线程。

正如你在第一个示例中看到的那样,没有什么实用的方法将绘制代码放入到一个JPanel绘制方法中,却从定制的渲染线程调用该代码。为了在一个定制的循环中处理绘制,我们可以使用BufferStrategy类。这个类用来执行双缓冲(double-buffering)和页交换模式(page-flipping)。

如图1.2所示,双缓冲用来避免在进行绘制的时候,看到一幅图像的实际绘制过程。在内存中绘制图像,然后一次性复制整个图像,这样,绘制的过程就不会被看到。

可以在全屏独占模式下使用的页交换模式也采用了同样的思路,但是,它保持了两个离屏图像,并且直接从一个缓冲到另一个缓冲交换视频指针。通过这种方式,没有绘制到屏幕上的那个图像,可以被清除并重绘。当绘制完成的时候,指针再次交换,将新的图像绘制到屏幕上,如图1.3所示。

通过使用BufferStrategy类,程序是全屏模式并使用页交换模式,还是程序是窗口模式并使用双缓冲,都无关紧要了——这些技术都会在幕后处理。为了在一个渲染循环中使用BufferStrategy,用getDrawGraphics()方法创建一个图形对象。这个图形对象将会绘制到离屏表面。一旦这个图形对象变得可用,它的使用方法完全像传入到JPanel类的paint()方法中的图形对象一样。

ed89d269f093eb6d9301c2107ebf9983991b0e54

调用contentsLost()来确保离屏表面可用,这一点也是很重要的。一些操作系统允许用户通过Alt-Tab方式离开全屏应用程序,这会导致离屏图像变得不可用。

show()方法执行双缓冲/图像复制或者页交换模式/指针交换来显示图像。注意,这段代码包含在try/finally语句块中。和其他绘制代码不同,因为这个图形对象已经创建了,所以当渲染循环完成的时候,必须要丢弃它。不调用Graphics.dispose()方法的话,将会导致内存泄露以及程序崩溃。

应当总是确保调用dispose()来清理图形对象。

// The bs object is a BufferStrategy object, and
// will be explained later in the chapter
public void gameLoop() {
    do {
      do {
        Graphics g = null;
        try {
          g = bs.getDrawGraphics();
          g.clearRect( 0, 0, getWidth(), getHeight() );
          render( g );
        } finally {
          if( g != null ) {
            g.dispose();
          }
        }
      } while( bs.contentsRestored() );
      bs.show();
    } while( bs.contentsLost() );
相关文章
|
9天前
|
监控 安全 Java
Java中的多线程编程:从入门到实践####
本文将深入浅出地探讨Java多线程编程的核心概念、应用场景及实践技巧。不同于传统的摘要形式,本文将以一个简短的代码示例作为开篇,直接展示多线程的魅力,随后再详细解析其背后的原理与实现方式,旨在帮助读者快速理解并掌握Java多线程编程的基本技能。 ```java // 简单的多线程示例:创建两个线程,分别打印不同的消息 public class SimpleMultithreading { public static void main(String[] args) { Thread thread1 = new Thread(() -> System.out.prin
|
14天前
|
Java 大数据 API
14天Java基础学习——第1天:Java入门和环境搭建
本文介绍了Java的基础知识,包括Java的简介、历史和应用领域。详细讲解了如何安装JDK并配置环境变量,以及如何使用IntelliJ IDEA创建和运行Java项目。通过示例代码“HelloWorld.java”,展示了从编写到运行的全过程。适合初学者快速入门Java编程。
|
21天前
|
存储 安全 Java
🌟Java零基础-反序列化:从入门到精通
【10月更文挑战第21天】本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
60 5
|
18天前
|
安全 Java 调度
Java中的多线程编程入门
【10月更文挑战第29天】在Java的世界中,多线程就像是一场精心编排的交响乐。每个线程都是乐团中的一个乐手,他们各自演奏着自己的部分,却又和谐地共同完成整场演出。本文将带你走进Java多线程的世界,让你从零基础到能够编写基本的多线程程序。
30 1
|
24天前
|
Java 数据处理 开发者
Java多线程编程的艺术:从入门到精通####
【10月更文挑战第21天】 本文将深入探讨Java多线程编程的核心概念,通过生动实例和实用技巧,引导读者从基础认知迈向高效并发编程的殿堂。我们将一起揭开线程管理的神秘面纱,掌握同步机制的精髓,并学习如何在实际项目中灵活运用这些知识,以提升应用性能与响应速度。 ####
43 3
|
26天前
|
Java
Java中的多线程编程:从入门到精通
本文将带你深入了解Java中的多线程编程。我们将从基础概念开始,逐步深入探讨线程的创建、启动、同步和通信等关键知识点。通过阅读本文,你将能够掌握Java多线程编程的基本技能,为进一步学习和应用打下坚实的基础。
|
27天前
|
Java
[Java]Socket套接字(网络编程入门)
本文介绍了基于Java Socket实现的一对一和多对多聊天模式。一对一模式通过Server和Client类实现简单的消息收发;多对多模式则通过Server类维护客户端集合,并使用多线程实现实时消息广播。文章旨在帮助读者理解Socket的基本原理和应用。
21 1
|
6月前
|
安全 Java
从零开始学习 Java:简单易懂的入门指南之不可变集合、方法引用(二十六)
从零开始学习 Java:简单易懂的入门指南之不可变集合、方法引用(二十六)
|
5月前
|
存储 Java API
Java——Stream流(1/2):Stream流入门、Stream流的创建(认识Stream、体验Stream流、Stream流的使用步骤、获取Stream流的方法)
Java——Stream流(1/2):Stream流入门、Stream流的创建(认识Stream、体验Stream流、Stream流的使用步骤、获取Stream流的方法)
83 0
下一篇
无影云桌面