java小游戏的初步学习笔记
一、Java 简介
二、Java 环境设定
三、Java 基本语法
四、Java 开发游戏的优劣
五、游戏开发中常用 Java API 包
六、参考资料
一、Java 简介
Java 是 SUN 公司研发的一门语言,自从1995年发布以来,它以其优越的面向对象思想及简便的功能得到了广泛的应用。微软总裁比尔•盖茨说:“Java是最卓越的程序设计语言”。1997 年开始,许多大学已经用 Java 取代 C 当作程序设计教学语言。现在到处都可见到 Java,Java 已经变成了程序员共通的语言。它已经渐渐地渗透到各领域,如果你是程序员,你可能迟早都会接触到 Java。然而 Java 到底什么呢?
Java 是一个类似 C++ 的面向对象程序设计语言。它和其他语言一样有自己的语法和撰写规则。我们经常提到的 Java 平台是由 Java 应用编程接口(API)和 Java 虚拟机(JVM)构成。Java API即Java为程序员提供的一套已经编译好的功能接口。
Java 虚拟机(JVM)是Java中最出色的设计之一,它是建立在CPU和OS的之上的一个虚拟平台。我们的Java程序并不是在本机操作系统上直接运行而是在Java虚拟机上执行,由Java VM 向本机操作系统进行解释。这样 Java 程序就可以在不同的平台上执行,也就是所谓的“一次编写,到处执行”。这就是说,任何安装有 Java VM 的计算机系统都可以运行 Java 程序,而不论最初开发应用程序的是何种计算机系统。比如你在 Window 平台下撰写的 Java 程序,可不做任何修改而直接在 Linux 平台上运行。不同的平台有不同的 Java VM 版本。Java 平台结构如下图的所示:
人们提到“学习Java”,通常他们指的是 Java 语言和 API。
二、Java 环境设定
为了能够编写并运行我们所编写的 Java 程序,我们需要在自己的本地机器中安装 JDK 开发包,JDK 是内置各种 Java 开发工具、Java 虚拟机、Java API 的一个压缩包。我们可从 java.sun.com 网站免费下载最新版本使用。这里要注意不同的系统平台 JDK 压缩包是有所出入的。下面介绍的方法我们是以 Windows 平台为基础。Linux 下的处理和这类似,只是文件扩展类型有所变化。
下载后的 JDK 是个执行文件,我们运行后可直接安装,缺省的安装路径是 C:\j2sdk1.4.1_02。为了能够让电脑找到你要运行的程序,JDK 会自动在你的系统环境变量中加入
JAVA_HOME= C:\j2sdk1.4.1_02
但是要想很方便的运行自己的程序,这还不够,我们还得自己设置系统的类路径。
类路径的设置方式可以是采用 javac 编译器命令和 java 解释器命令中的 -classpath 选项,或通过对设置 classpath 环境变量的来完成。在 Java 程序开发中,我们会大量引用到 Java 提供的 API 类库,所以要告诉电脑这些 Java API 所在的位置。classpath 就是帮我们寻找这些 Java 类路径的配置,如同 DOS 里面的 path 一样。
要成功编译和运作 Java 程序,我们还必须告诉电脑 JDK 中的编译器 javac.exe 和执行工具 java.exe 所在的路径。这两个工具是放在你的 JDK 安装目录的 bin 目录下,如:
C:\j2sdk1.4.1_02\bin
我们来看看电脑中具体的环境设置:
PATH=C:\j2sdk1.4.1_02\bin;c:\windows;c\windows\command
classpath=.; C:\j2sdk1.4.1_02\lib\tools.jar;d:\test
注意:classpath 中的“.”代表的是当前目录,可以让你在当前目录下编译自己的 class 而不会出错。D:\test 是我们自己指定的任意 class 放置路径。这样即使 Java 操作不在当前目录中,也可编译 d:\test 目录下的 Java 类。
三、Java 基本语法
编写 Java 程序的
编写 Java 程序的 IDE 工具很多,如 Eclipse、JCreator、JBuilder 都是很不错的工具。而最简单的方法是使用文本编辑器。下面我们就用文本编辑器创建一个 Java 应用程序,并以此为基础说说 Java 的基本语法,感受您的第一个 Java 程序所带来的成就感。在开始之前,您可先下载我们源程序 TestDate.java,或者手工输入:
package my.test;
import java.util.*;
/**
* 日期测试程序
* @author 天翼.李
*/
public class TestDate {
// 声明私有变量pass
private Date pass;
/**
* 打印日期方法,并初始化pass的值
*/
public void printDate()
{
// 调用日期函数
pass =new Date();
// 显示当前日期
System.out.println("当前日期:"+pass);
}
public static void main(String arg[]) {
// 初始化类TestDate
TestDate testDate = new TestDate();
testDate.printDate();
}
}
接着要编译程序
编译程序就是把java源程序转换为 Java VM 能够理解的字节码,这样,任何安装有 Java VM 的计算机就可以解释并运行该程序。我们在 Dos 窗口的命令行中输入下面命令,就可成功编译 TestDate.java 程序:
javac TestDate.java
解释并运行程序
Java 程序的解释和运行是指调用 Java VM 字节码解释器把 Java 字节码转换成与平台相关的机器码,以便您的计算机能够理解并运行该程序。在运行上面例子程序前我们先要在当前目录下新建 my 目录,并在 my 下面新建子目录test,并把我们编译过后的 TestDate.class 文件移到 test 下面。然后在 DOS 窗口的命令行输入:
java my.test.TestDate
在命令行上,您可以看到终端窗口显示如下:
为什么要新建这些子目录呢?下面的 package 机制将会告诉你一切。如果你认为有点麻烦了,也没关系,大部分的 Java IDE 会自动在你的系统中生成这些目录。或者你在理解了下面的 package 机制后,注释掉 package my.test,直接在当前目录下进行操作演示。
包(package)
每个人写的程序命名方法各异,如何有效的对这些名字进行管理,而不会出现重名的现象。Java 借鉴 Internet 域名地址的唯一性方法,引入了 package 机制。package 利用倒写的 Internet 域名,用点符号分隔每一个路径。这样保证不同功能的类库放入不同的目录之下。在此 package 相当于命名空间,不同命名空间的类不会相互干扰。在本地新建包路径时会按“.”符号来新建相应的子目录。上例中的:
package my.test;
相当于新建一个 my.test 的包,而此包就是按 my\test 的目录结构来分隔 TestDate 类和外界的类。所以上面我们编译后的 TestDate.class 文件要放置在目录 my\test 下面。
包除了命名分隔的功能外,还有一个功能,它能设置本命名空间对另一个命名空间类的访问权限。只有命名为 public 的类才能被另一个命名空间的类调用。在下面的权限小节我们将会看到 Java 几种权限划分方式。
Import
Import 和 package 是相对应的,package 主要管理的是自己类库,而 import 主要的是处理对另一个包中的类库调用。由于 package 机制隐藏了类库的可见性,要想引用另一个类库的中的类来实现相应的功能,我们就得知道这个类库所在的位置,也即要得到类库上的包路径。
程序开始时 Java 虚拟机会根据环境变量 classpath 来查找引用的包。如果没有找到,就到当前程序所在的目录查找,如果再没找到,程序运行就会出错。看到这,你是否明白了 classpath 所发挥的类库路径配置作用!Java 找到引用的路径后,会把路径指定的类全部加载到内存中去,这是 Java 的一大特色,用以加快开发者调用程序的速度。
import java.util.*;
为了新建 Date 类型的变量实现我们的显示当前日期功能,例子中我们就引用了 java.util 包,这里用的“*”代表这个包下的所有类,包括这个包下的 Date 类。如果我们只要引用 Date 这个类,也可这样写:
import java.util.Date;
这样程序运行过程中只要加载指定的类到内存中而不要加载所有的类。
如果大家对加载过程有兴趣,可尝试在执行程序时加入参数 –verbose,即:
java –verbose my.test.TestDate
屏幕上会显示所有引入内存中的类库名称。
面向对象
Java 是一种面向对象(OOP)的编程语言。在 Java 中,面向对象是以类的形式出现的,对象则是类的实例。所以要学习 Java 的类首先必须了解面向对象思想。
1、类
我们用修饰符“class”来表示类。它代表某一类事物的类型,其内封装了这一事物总的外观长相(数据成员)和行为举止(成员函数),如鸟类就可以是一个 class,其中就封装了鸟类的基本行为:飞行,也封装了鸟类的基本外观:都有翅膀。对类封装后,即使我们改变了类的一些代码,只要不改变其中被调用的方法,引用这个类方法的程序就不要修改。
类除了封装,第二个特点就是允许继承。我们通过关键字“extends”,就可让我们继承的类拥有父类的所有特点,并可产生自己的独有个性。比如:
class 候鸟类 extends 鸟类 {}
则候鸟类自动继承的鸟类的“飞行”行为,及“有翅膀”这个属性,而在此候鸟又可有自己的特点,如“一到冬季就往南飞”。这样我们大大减少了代码的编写工作,也方便了程序的理解与错误查找。我们在 Java 中把鸟类称为父类或超类,候鸟类称为子类。
下面来看看我们的程序:上例我们创建了一个叫 TestDate 的类,并封装了这个类的数据成员 pass 和成员函数 printDate。
public class TestDate{ //声明一个类
private Date pass; //类的变量的声明
public void printDate() {} //类的方法
}
声明一个类时使用了修饰符 public,说明了这个类可以被任何其他对象使用和扩展,而且与它的包无关,在上面 package 机制中我们也提到了这点。
如果类声明前没有任何修饰符,则默认为 friendly 类,即只有同一个 package 包中的对象才能使用该类。
2、对象
类还只是个抽象化的概念,并没有实在的东西存在。要想在 Java 程序中运用类,并引用类的方法和变量,我们必须实例化类为对象。在 Java 中万事万物都是对象,连 Java 本身也是对象。原则上没有实例化的类是不能使用的。
我们用 new 来创建类的一个实例,并不是所有的类都需要创建他的实例,方法和变量名前面带 static 关键字的静态方式,就可以不用创建这个类的实例,但是静态的方法只能引用静态的类变量,如上例中静态方法 main() 函数就不能直接引用非静态变量 pass。
TestDate testDate=new TestDate();
现在我们就可通过 testDate 对象引用 TestDate 类中显示当前日期的 printDate 方法:
TestDate.printDate();
访问权限
是不是类、方法、变量、任何人都可访问?非也。为了保护代码的安全性,Java 中使用了访问权限这一概念。在类、方法、变量前加上不同的修饰符,将会实现不同的访问权限。
public 任何人、在任何地方都可访问,即使访问者是另一个包中的类也可访问
protected 只能被同一个类或继承类中的所有方法访问,其他的类或包都不可访问
private 只能让同一个类中的所有方法访问
friendly 如果你没有声明任何修饰符,表示其权限为friendly,可以被同包内的所有类访问
变量
我们使用变量来说明类的基本属性。在使用变量前我们必须先进行声明和初始化。而且每一个变量都有其自己的数据类型。Java 中不同的数据类型变量在内存中有不同的表示方法,如 int 类型占32位,byte 占8位等:
private Date pass;
表示我们声明一个Date类型的私有变量。
pass=new Date();
表示初始化 pass 值为当前日期值。虽然 Java 会对没有初始化的变量赋初值为 null,但是这很容易造成程序逻辑错误。
在类中有两个特殊的变量: this 和 super,this 变量表示当前类对象本身,当类中有两个变量同名,其中一个属于当前类而另一个属于另一个类时或某个类需要将本身作为参数传递给某个方法时我们都有可能使用 this 变量。super 变量,表示当前类的父类。在继承了父类,而没有声明父类对象的前提要引用父类的方法或变量这个方法很有用。
方法
我们用方法来表示类的行为特征。方法除了自身的类型外还必须实现这个行为特征的代码,我们称之为方法体。方法还可接受来自外部的参数作用于本方法之内。如果方法类型非空,我们还必须在方法体中用return返回此方法的类型值。
public static void main(String arg[]) {
// 初始化类TestDate
TestDate testDate = new TestDate();
testDate.printDate();
}
此处声明了一个 void 类型的公有静态方法 main(),main 可接收 String 类型的参数。“{}”内的代码就是 main 的方法体,此方法体实现了 TestDate 类的初始化,并调用类中的 printDate() 方法。由于 main() 方法类型为空,系统默认返回值为 null,所以在方法体代码中可不返回类型值。
代码注释
代码注释是放置在源代码中描述这段代码功能的注释性文字说明。在 Java 中支持三种注释方式:双斜线注释、Doc 格式的注释和全文注释。
双斜线“//”通知编译器把从该斜线后开始到该行结束的所有内容看作文本进行处理,比如:
public void printDate()
{
// 注释:调用日期函数
pass =new Date();
// 注释:显示当前日期
System.out.println("当前日期:"+pass);
}
代码和说明文档不能很好的结合,一直是程序员很头痛的问题,而 Java 中引入 Doc 格式的注释解决了这一大难题。若要为您的程序生成文档,则应采用 Doc 格式注释符号(/** */) 把文本行括起来,以便 javadoc 工具识别。javadoc 工具会查找源文件所包含的 Doc 注释,并利用这些注释生成 API 文档。
/** * 打印日期方法,并初始化pass的值 */public void printDate()
{
// 注释:调用日期函数
pass =new Date();
// 注释:显示当前日期
System.out.println("当前日期:"+pass);
}
其中的
/** * 打印日期方法,并初始化pass的值 */
就是Doc格式注释方式。
全文注释如同双斜线(//)的注释,所不同的是双斜线(//)只注释当前行。而用/* */的形式可注释/* */之间的所有文字。
最后,大家要注意几点:
1、main()方法的特殊性
凡是应用程序中有一个 public class {} 的类并且包含 main() 函数,那这就是程序的入口点。main 必须声明为 static void main(String arg[]) 的形式。此处的 arg[] 字符串数组是接收的是执行用户输入的参数。如在 DOS 窗口执行:
java my.test.TestDate please
please 就会传入 args[] 中,我们只要在 main() 方法中加入判断用户输入的字符串实现代码。
2、Java的书写格式
Java 书写是自由格式,但是程序员都以 SUN 的代码规范为标准。包名用小写,类名首字大写,方法名首字小写。变量名一般小写。如果这些名字太长,可按字意大写第二个代表意义的首字母。如上面 printDate 中 Date 的首字母就用的大写。
四、Java 游戏开发的优劣
您是不是在一开始就有个疑惑,为什么我们要选用 Java 做为本系列游戏开发的语言?要想回答这个问题,我们得看看 Java 在游戏开发方面有哪些优势。
跨平台
“Write once, run everywhere!”这是 Java 最诱人的特点。大部分游戏我们必须依赖于其特定的平台而存在。但是 Java 编译后的文件是运行在 Java 虚拟机上的字节码。虚拟机是消除了 CPU 和 OS 的差异,我们一般只要对配置文件、批处理文件作相应修改即把你编写的游戏平滑移植到你想要的任何平台。你只要编写一个版本就可让全世界使用各种平台的游戏者玩到你的游戏。
网络模式
Java 拥有强大的网络功能,能很容易的和网页结合在一起发布到世界各地。游戏者只要通过浏览器就可体会到你游戏所带来的乐趣。这意味着,你的游戏将面临着拥有全世界的玩家这个巨大市场。
多人模式
Java 为程序开发提供了 java.net 包,该包提供了一组使程序开发者可以轻易实现基于 TCP/IP 的分布式应用系统。此外,Java 还提供了专门针对互联网应用的类库。这样你就可很方便的使你的游戏支持多人模式,任何玩家通过你的游戏都可和另一个地方的玩家进行游戏合作和对抗。
完全的面向对象
Java 是一种完全的面向对象语言,这意味着,你可在你的游戏中很方便扩展和继承你的代码,而不像结构化程序设计语言那样再重新开发新的类库。比如说你开发了某一类游戏的引擎,以后你再开发类似的游戏时几乎不要任何改动就可重新使用这个引擎,你要做的只是替换掉游戏中的图形、声音、动画等子系统。
简单易用
由于 Java 的结构类似于 C 和 C++,所以熟悉 C 与 C++ 语言的编程人员稍加学习就很容易掌握 Java 编程技术了。其次,Java 设计去除了 C 和 C++ 中令人费解的特性,Java 程序语言内置的有许多自动管理机制,比如自动内存管理机制,让你不会在程序中犯下大错,所以你可以很快地把程序写完,而如果使用其它语言必须要花更多时间。有资料显示,用 Java 写程序比用其它语言快了四到十倍。
稳定性
Java 对程序代码进行了很多的安全检测。使程序员撰写的通过编译的代码几乎不会发生错误。比如 Java 提供的真正的数组(Array),运行程序下标检查,另外,它在对象类型转换过程中将不会将任意数据进行转换,Java 的自动内存管理也大大减少了运行时的错误。
多线程(multithreading)机制
Java 是第一个把多线程和本身溶合在一起的 OOP 语言,多线程机制在 Java 中的编写和使用更加方便、容易。多线程能让游戏开发利用不同的线程实现各种不同的行为,它的同步机制也保证了对共享数据的正确访问。因此,使用 Java 语言可以非常轻松地实现网络上的实时交互行为。在网络游戏和大量动画的 Java 游戏开发中多线程将起到很大的作用。
强大的类库支持
Java 提供了广泛、标准、先进的 API。这些 API 包含了我们想要的所有功能。网络分布计算、数据库连接、GUI 设计、图形处理、声音处理等这些都有 API 了!我们可以利用这些API 轻易地写出功能强大的程序。而且一旦你学会了某个 Java API,在 Window 下和 Linux 下使用都是一样的。
Java 免费
SUN 提供 Java 相关的工具,让你可以开发与执行 Java 程序。你无须支付任何费用就可得到 Java 开发工具和 JDK 开发包。可能大家也许会笑,这个也算Java游戏开发的一大优点吗?然而,想想c/c++游戏开发上的对开发工具的庞大投资,你一定不会再笑Java免费所带来的经济利益了。
有优就有缺,Java语言做为一个新生语言在游戏开发中也有其自身的不足之处:
速度
Java 执行代码比 C++ 执行代码慢 10-20 秒,在游戏中这个看上去是个很大的缺陷。但是在现在处理器速度不断提高,Java 新的实时编译器“Just-in-time”和快速虚拟机的推出,两者之间的速度差距已经越来越小。
平台依赖性
由于 Java 虚拟机消除了平台的依赖性,所以使大家开发的依赖于某一平台特性的游戏便不能移植到别的平台去。比如,你的某一 Java 游戏利用了 Window 平台的 DirectX 特性,而在 Linux 平台下这一特性就不能使用了。
游戏开发资源
由于 Java 是个新生语言,游戏开发者大部分都还集中在 C、C++ 的阵营,Java 方面所能提供的游戏开发资源还是比较有限的,特别在国内的主推 J2EE、J2ME 的环境下。但是反过来想一想,这未尝不是个优点呢?网络时代只有掌握先者才能制胜。
五、游戏开发中用到的 Java 包
Java API 存放在安装时所用目录下。如果平台安装在 C:\j2sdk1.4.1_02中,API 就安装在 C:\j2sdk1.4.1_02\lib 和 C:\j2sdk1.4.1_02\jre\lib 下面,而相应的说明文档的存放目录就是 C:\j2sdk1.4.1_02\docs。我们能直接继承这些现成的可定制功能,以节约编程时间。
大家先来了解 J2SE 的基本结构图,并分析几个我们将会在游戏开发中常用到的 Java API 包:
java.awt
Java 的抽象窗口工具包java.awt(Abstract Windowing Toolkit)可以创建与平台无关、基于图形用户界面的程序。这里你可处理状态栏,事件和图形。这可是编写可视化的 Java 游戏的基础部分。Java.awt 还实现了图形、二维图形处理、拖放操作等功能。
java.awt.Graphics
java.awt.Graphics 为 java.awt 包处理图形的类库,而二维图形的绘制就是通过类 Graphics2D 对象来处理的。
java.awt.geom
游戏中二维空间的图形处理就是通过包 java.awt.geom 中的类库来实现的,此包中定义了许多基本几何图形,包括 Arc2D、Point2D、Line2D 等。它能帮我们很精确的定位图形的坐标。如 Point2D 对象就可定义二维空间上某一点的 X 和 Y 坐标的精确值。
Java.awt.color
从名字上大家就可看出,这个包是负责Java中的颜色的调配和显示。通过这个包中的Color类我们可很方便的变换游戏中的背景和前景等各种色彩的处理。
Swing
在新的 Java 版本中引入了新的图形界面类 Swing,它是 SUN 公司用来描述下一代图形界面的标准。其中包含了标签页、表格、树、特殊边框、微调等各种组件。还支持可插入观感(Pluggable look and feel —— PL & F),通过此类库可以让你定制自己的桌面,更换新的颜色方案,让窗口系统适应你的习惯和需要。
有经验的朋友可能会问,为什么在这里两个界面设计的类库都进行了介绍 Swing 不是在 AWT 基础上的功能加强吗?不错。Swing 是在 AWT 基础上加了不少新功能,使用 Swing 能做出比 AWT 更丰富的界面和图形效果,而且编程方式比 AWT 更简便更容易。但是 Swing 天生有个对游戏开发来说的缺点,它丰富的功能调用在运行时会比较占用资源。鱼与熊掌不能兼得,如果你想要更美的外观,建议使用 Swing 来处理游戏图形界面,如果你想要得到游戏比较快的速度,那最好使用 AWT 来开发游戏图形界面。
java media
有游戏,当然离不开媒体功能的支持。Java 内置了对多媒体支持的大部分类。
Java Media Framework API(简称JMF)并非单个类或包的说明,而是这些多媒体功能包的组合。包括声音播放包 Java Sound、二维图形处理包 Java 2D、三维图形处理包 Java 3D 等等。
java.applet
applet 是一种 Web 浏览器上的小程序,由于 Java applet 和 html 自动集成,才使得过去静态的主页变得更加生动活泼,Java 能引起大家的目光,applet 功不可没。applet 在开发主从架构和网络应用程序方面有不可比拟的优势。Java.applet 包含了运行这些小程序的类库。通过 applet 你的游戏程序可分发到网络上任何一个角落,玩家不再有安装游戏的烦恼,只要访问你的主页,applet 就会下载到本地自动安装。不安装而体会到远端游戏的声音、图像、动画和操作,相信这是很多人很乐意的事情。
java.io
java.io 包是处理 Java 输入、输出的接口包。它不仅包括本地文件系统的处理,还包含了网络上数据的输入,输出操作。
java.lang
这个包是 Java 所有包的基本,即使程序员没有使用任何一条引用这个包的代码,任何一个 Java 程序都会在开始时自动引入这个包中的所有类库。Java.lang 内含了 Java 中最基本的类,如对象、类、线程、异常、系统访问、系统资源的访问和系统运行时的处理等类,还包括一些常用的数学处理函数类,如 Math 类。
java.lang.Tread
这个类是 Java 线程处理类,线程也即单个的执行任务。每个线程在 Java 中表现为相应的实现代码。
java.net
Java 网络包内封装了所有运行于网络平台的协议和接口。利用 java.net 包我们读写远端网络数据如同读写本地系统数据一样方便。java.net 包能让我们很简便的就能实现强大的网络功能。在当今网络游戏开发大趋势之下,java.net 将会大大减化我们网络游戏开发进度。
java.util
这是 Java 基本数据结构包,包括如日期(Date)类型等在内的一些基本数据类型。
上面说的也只是 Java API 大家族的冰山一角,如果大家想要了解更多,可自行查找相关的 API 文档。在开发中我们也不可能记住所有的类,但是了解每个包的功能是必要的。如果在开发中你知道某个类的名字,可直接用“index”在 API 帮助文档中查找使用说明。但是如果你不知道相关的类名字,你就得依据这个类的功能在相关包中查找了。
六、参考资料
大家可在 这里 下载所有的源代码及演示程序。
SUN 公司的 JDK API 将是你很好的参考来源。
Robocode 中华联盟中有不少游戏编程的资料,并提供了 Robocode 这个编程游戏的下载。
IBM Java 区提供了极其完备的 Java 中文资料,是大家不得不去的一个地方。