《Android游戏开发详解》——第3章,第3.6节图形

3.6 图形
Android游戏开发详解
基于文本的程序很容易构建,但是基于文本的游戏已经过时了。在本节中,我们将介绍如何使用Java类库中的类(尤其是javax.swing包中的类),来创建一个图形用户界面(Graphical User Interface ,GUI)。你会发现,尽管添加一个简单的用户界面很直接,但GUI是一个很大的主题。我将只是提供一个快速的介绍,完全只是创建一个窗口和显示一个基于Java的游戏所需要的基础知识。如果你想要学习Swing的更多知识,并且要创建专业的应用程序,请访问如下所示的教程:http://docs.oracle.com/javase/tutorial/ uiswing/TOC.html

3.6.1 JFrame简介
当在Java中开发一款图形化应用程序的时候,我们首先要创建一个叫作JFrame对象(从javax.swing.JFrame导入)的窗口。这个窗口中是一个内容面板(想象一下窗口面板),我们可以向其中添加各种UI元素,例如,按钮、滚动条和文本区域。

内容面板的默认布局叫作BorderLayout。它允许我们将UI元素放置到5个区域中的一个,如图3-3所示。

图3-3所示的这5个区域中的每一个,都只能容纳一个UI元素,这意味着,BorderLayout只支持5个元素;然而,这对我们来说不是问题,因为我们只需要一个名为JPanel的元素。

JPanel对象是一个简单的、空的容器,我们可以将其添加到一个BorderLayout的某个区域中。我们可以在单个的JPanel对象上绘制想要让玩家看到的任何内容,就像是在画布上绘图一样。例如,考虑一下图3-4所示的屏幕截图。这个屏幕截图取自TUMBL游戏的一个正在开发的版本,这款游戏是我所开发的第一款游戏。你所看到的一切,从玩家的分数、暂停按钮到角色以及加血,都绘制到一个单个的JPanel上。

3.6.2 说明坐标系统
当我们在计算机上处理图形的时候,使用一个基于像素的x、y坐标系统。此外,我们还把左上角的像素当作原点(0, 0)。这意味着,如果屏幕上的分辨率是1 920像素×1 080像素的话,右下角的像素的坐标是(1 919, 1 079)。

3.6.3 创建一个JFrame
现在,我们已经讨论了构建图形化应用程序所需了解的一切内容。开始动手吧。

创建一个名为FirstGraphics的Java项目,并且创建一个名为FirstFrame的类,它带有一个完整的main方法。然后,通过给main方法添加如下所示的代码行(确保导入了javax.swing.JFrame),我们创建了一个JFrame对象。

JFrame frame = new JFrame("My First Window");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(480, 270);
frame.setVisible(true);

此时,你的FirstFrame类应该如程序清单3.14所示。

程序清单3.14 FirstFrame类

01 import javax.swing.JFrame;
02
03 public class FirstFrame {
04    
05    public static void main(String[] args) {
06        JFrame frame = new JFrame("My First Window");
07        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
08        frame.setSize(480, 270);
09        frame.setVisible(true);
10    }
11
12 }

运行这个FirstFrame类,应该会看到图3-5所示的结果。

注意,所出现的窗口带有一个“My First Window”标题。显然,这个内容面板(图3-5中的灰色区域)目前是空的。

在前面小节的非图形化的示例中,只要JVM执行了程序的最后一行代码,程序就结束了。但图形化应用程序并不是这样的。JFrame甚至会在最后一行代码之后持续,就像这个窗口所展示的那样。通过点击退出按钮来结束该程序。

让我们确保理解在定义JFrame的4行代码(程序清单3.14的第6行到第9行)中发生了什么。在第6行,我们使用定制的构造方法,创建了一个名为frame的新的JFrame对象。这允许我们为自己的窗口设置标题。

接下来,在第7行,我们指定了当窗口关闭的时候应该发生什么情况。当用户关闭窗口的时候,我们想要让整个程序结束,因此,我们从JFrame类向setDefaultCloseOperation()方法传入了一个名为EXIT_ON_CLOSE的公有的int(还记得吧,点运算符用来访问另一个类中的公有方法和变量)。

第8行直接告诉窗口调整其大小,以便成为480像素宽、270像素高。一旦完成了这一步,在第9行调用setVisible()方法就使得该帧出现在屏幕上。

3.6.4 添加一个JPanel
现在,我们有了一个JFrame,是时候添加其内容面板了。要做到这一点,我们将创建一个名为MyPanel的新类。该类将会是使用继承创建的JPanel的一个定制版本,因此,我们必须扩展JPanel,先导入java.swing.JPanel。

将程序清单3.15所示的代码复制到你的MyPanel类中。一旦运行了该程序,我们将讨论它。别忘了如第1行、第2行和第4行所示,添加适当的导入。

程序清单3.15 MyPanel类

01 import java.awt.Color;
02 import java.awt.Graphics;
03
04 import javax.swing.JPanel;
05
06 public class MyPanel extends JPanel {
07
08    @Override
09    public void paintComponent(Graphics g){
10        g.setColor(Color.BLUE);
11        g.fillRect(0, 0, 100, 100);
12        
13        g.setColor(Color.GREEN);
14        g.drawRect(50, 50, 100, 100);
15      
16        g.setColor(Color.RED);
17        g.drawString("Hello, World of GUI", 200, 200);
18      
19        g.setColor(Color.BLACK);
20        g.fillOval(250, 40, 100, 30);
21    }
22  
23 }

现在必须回头看看FirstFrame类,构造MyPanel的一个实例,并且将其添加到内容面板的一个区域中。通过在main方法的底部添加如下所示的代码行,来做到这一点。

MyPanel panel = new MyPanel(); // Creates new MyPanel object.
frame.add(BorderLayout.CENTER, panel); // Adds panel to CENTER region.

更新后的FirstFrame类应该如程序清单3.16所示(注意第1行的import语句)。

程序清单3.16 更新后的FirstFrame类

01 import java.awt.BorderLayout;
02
03 import javax.swing.JFrame;
04
05 public class FirstFrame {
06    
07    public static void main(String[] args) {
08        JFrame frame = new JFrame("My First Window");
09        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
10        frame.setSize(480, 270);
11        frame.setVisible(true);
12      
13        MyPanel panel = new MyPanel();  // Creates new MyPanel Object
14        frame.add(BorderLayout.CENTER, panel);  // adds panel to CENTER region
15    }
16
17 }

运行FirstFrame,将会看到图3-6所示的界面。

3.6.5 术语解释
在讨论发生了什么之前,我们需要先解释一些术语。还记得吧,我们可以在JFrame的内容面板区域添加各种图形化的元素。这些图形化的元素叫作微件(widget),它们属于一类叫作JComponent的泛型对象。这意味着,JPanel以及在基于Swing的图形化应用程序中使用的其他的图形化元素,都是一种类型的部件(component)。

3.6.6 理解MyPanel
我现在要解释当运行程序的时候发生了什么,首先来说明MyPanel类。回头去看看程序清单3.15,你还会记得MyPanel扩展了JPanel(程序清单3.15的第6行)。这就是说,MyPanel是JPanel的一个子类;换句话说,它是泛型的JPanel类的一个更加具体的版本。也就是说,MyPanel继承了属于JPanel的所有共有的方法(由此,MyPanel通过继承成为JPanel的一个特定类型)。

有一个继承的方法名为paintComponent()。它是描述部件应该如何渲染的一个方法。我们想要控制这个方法,以便可以告诉程序一个MyPanel对象应该如何显示。为了做到这点,我们在自己的MyPanel类中声明了paintComponent()方法,并且添加了一个@Override修饰符(在第8行),通过这种方法,让编译器知道我们要使用自己的方法来替代已有的paintComponent()方法。

在这个方法paintComponent()内部,我们使用所提供的Graphic对象g,调用了8个方法(程序清单3.15中的第10行到第20行)。

Graphics对象每次可以绘制一项内容,并且它像笔刷一样工作。首先使用setColor()方法选择一种颜色,并且告诉Graphics对象,使用几个绘制和填充方法之一来绘制什么。

setColor()方法接受一个Color对象,我们可以通过Color类来获取该对象(这个类保存了很多Color对象作为公有变量,我们可以使用点运算符来引用它)。注意,对于每种颜色有两个变量,一个全部都是大写,一个全部都是小写。它们总是为你返回相同的 颜色。

作为一般性的规则,以单词draw开头的方法只是绘制想要的形状的框架。另一方面,以单词fill开头的方法,将会绘制整个形状。例如,g.drawRect(50, 50, 100, 100)将会绘制一个方形的边框,其左上角位于(50, 50),并且其边长为100个像素。

请通过如下的链接,访问Graphics类的Method Summary,以了解在paintComponent()方法中调用的方法的更多的信息,以及参数的具体含义:http://docs.oracle.com/javase/7/ docs/api/java/ awt/ Graphics.html

3.6.7 回到FirstFrame
现在,我们来解释在MyPanel中发生了什么,让我们先来讨论在程序清单3.16中添加到FirstFrame类中的两行代码。

MyPanel panel = new MyPanel(); // Creates new MyPanel object.
frame.add(BorderLayout.CENTER, panel); // Adds panel to CENTER region.

第一行代码使用熟悉的语法创建了一个新的MyPanel对象。然后,第二行将其添加到图3-3所示的中心区域(Center)。注意,空的区域并不占用空间。

一旦MyPanel对象添加到了JFrame,其paintComponent方法就会自动调用。这意味着,我们不必明确地要求panel来绘制自己。这就是为什么我们能够看到图3-6所示的各种图形。

确保自己再次回顾代码,以理解如何能够得到甚至让毕加索感到骄傲的惊人的艺术品。

时间: 2024-09-21 10:04:27

《Android游戏开发详解》——第3章,第3.6节图形的相关文章

《Android游戏开发详解》一第2章 Java基础知识

第2章 Java基础知识 Android游戏开发详解第1章内容完全是成为Java程序员的准备工作.在本章中,你将编写自己的第一个Java程序(包括一款简单的游戏),并学习如何把游戏的角色.加血(power-up)以及其他实体表示为Java对象.

《Android游戏开发详解》——第2章,第2.2节设置开发机器

2.2 设置开发机器 Android游戏开发详解 在开始编写简单点的Java程序和构建令人兴奋的游戏之前,我们必须在自己的机器上安装一些软件.然而,这个过程有点枯燥且颇费时间,但是,为了让第一个程序开始运行,这些代价都是值得的. 2.2.1 安装Eclipse 我们将利用一个集成开发环境(Integrated Development Environment,IDE)来编写Java/Android应用程序.IDE是一种工具的名称,它能够帮助我们轻松地编写.构建和运行程序. 我们将要使用的IDE叫作

《Android游戏开发详解》——第1章,第1.9节训练到此结束

1.9 训练到此结束Android游戏开发详解如果你已经学到了这里,恭喜你!你已经完成了进入美丽的.复杂的并且偶尔令人沮丧的编程世界的第一步.但是,在编写一些Java代码之前,你还不能自称为一名Java程序员.因此,快打开你的计算机并且开始学习第2章,在那里,我们要构建一些Java程序了.

《Android游戏开发详解》——第2章,第2.8节对象的基础知识

2.8 对象的基础知识Android游戏开发详解我们已经应用了第1章中介绍过的概念来编写和运行一些非常简单的Java程序.接下来,我们将把注意力转向对象,它使得我们能够编写更加复杂和强大的程序. 什么是对象?以你看待现实世界中的物体的方式来思考Java对象,这么做是有帮助的.对象所拥有的属性,我们称之为状态(state)和行为(behavior). 让我们以手机为例子.你的手机拥有状态,它可能是黑色的,并且可能打开了电源开关.这些属性可以帮助我们描述手机以形成其状态.手机还会有行为.它可能能够播

《Android游戏开发详解》——第3章,第3.7节里程碑

3.7 里程碑Android游戏开发详解介绍完这个示例,我们也就结束了本书的第3章和第1部分.如果你一直在学习,那么应该已经了解了编程的基础知识,掌握了Java基础并且学习了高级的面向对象设计概念.Java游戏开发就在前面,它肯定是一个巨大的挑战甚至会带来更多的兴奋. 在我们继续学习之前,我想要提醒你,Java是一种庞大的编程语言.尽管我已经试图尽可能地向你介绍在开发Java和Android游戏的时候可能会遇到的所有概念,但我还是没办法公正地对待这门语言.如果你有兴趣学习Java的更多知识以及更

《Android游戏开发详解》——第2章,第2.1节面向对象编程

2.1 面向对象编程Android游戏开发详解Java是一种面向对象编程语言.在面向对象的范型中,我们以对象的形式来表示数据,以帮助我们形成概念并沟通思路.例如,在构建视频共享Web应用程序的时候,我们可能要创建一个User对象来表示每个用户账户(及其所有的数据,例如,用户名.密码.上传的视频等).使用一个Video对象来表示每一个上传的视频,其中的很多视频都组织到一个Playlist对象中. 考虑到整洁.健壮的代码更容易阅读和理解,面向对象编程允许我们将相关的数据组织到一起.为了了解这一思路,

《Android游戏开发详解》——第2章,第2.14节隐藏变量

2.14 隐藏变量Android游戏开发详解注意,到目前位置,我们能够以两种不同的方式来修改Phone对象的状态.我们能够使用点运算符直接访问其变量,并且分配显式的值:还能够使用Phone对象提供的行为来间接地修改Phone对象的状态. 如果能够直接深入到myPhone对象,取出其信息并修改,我们说对象的变量是暴露的.从现在开始,我们将禁止暴露变量,基于很多原因,暴露变量可能会有问题. 例如,如果某人试图给一个变量分配一个非法的(或者不符合逻辑的)值,会怎么样呢?如下的代码对Java程序来说可能

《Android游戏开发详解》——第2章,第2.6节构建一个简单的计算器程序

2.6 构建一个简单的计算器程序Android游戏开发详解现在,我们已经尝到了甜头,让我们回过头来看看第1章介绍过的一些概念,并且构建一个简单的计算器程序.让我们给出一些动手实践的指导,来构建一个新的Java程序.请记住如下的主要步骤. ① 创建一个新的Java项目(将其命名为SecondProject). ② 在src文件夹中创建一个新的类(将其命名为SimpleCalculator). ③ 创建一个main方法. 如果任何时候你碰到困难,应该参考前面的小节.一旦按照上面的步骤进行,应该会看到

《Android游戏开发详解》——第1章,第1.6节函数(在Java中称为“方法”更好)

1.6 函数(在Java中称为"方法"更好)Android游戏开发详解让我们将目前为止所学到的所有内容组合起来,并且讨论编程的一个重要方面,即函数. 函数是一组规则.特别地,函数应该接受一个值并且输出一个相应的结果.以一个数学函数为例. f(x)=3x +2 输入是任意的数值x,输出是3x +2的结果 例如,f(1)=3(1)+2=5在Java中,我们可以定义一个非常类似的函数.如下的函数将接受一个float类型的输入,并且输出计算3x+2的结果. 程序清单1.6 Java函数 1 f

《Android游戏开发详解》——第3章,第3.4节多态

3.4 多态Android游戏开发详解你可能会问,为什么我们必须创建一个接口和一个类,来定义一个单个的King类呢?你可能会告诉自己,现在Human接口还真的做不了太多事情,你说的绝对没错. 使用接口允许我们创建一类对象,但是,在学习多态之前,我们很难意识到这对程序来说意味着什么. 来看一下如下所示的方法. public void feed(Human h) { System.out.println("Feeding Human!"); h.eat(); } 该方法可以接受一个单个的H