Slick 2D 是一个轻量级、跨平台的 Java 2D 游戏引擎。
上学期的 Java 课程期末大作业我一直打算写一个游戏,研究了半天游戏引擎,最终选定了 Slick2D。要说明的是,对于大型游戏,它还比较单薄;但是对于一般的游戏已经足够了,也非常适合游戏开发者进行入门和练习。Slick2D 是基于 LWJGL 的 2D 游戏引擎,提供对状态、图像、动画、粒子、声音、字体、音乐、控制等等的支持,但是本身不是一个物理引擎。如果想搭配物理引擎使用,推荐 JBox2D。然而,如果你的游戏需要的物理效果不是很复杂,尝试一下自己写物理引擎也未尝不可。我的项目只需要用到球体的二维碰撞,于是干脆自己写了一个,非常有意思,也可以学到很多东西。
下载和基本的介绍可以参考官网。它的完整 API 文档在可以在这里找到。
开发环境搭建
文件准备
需要分别下载 Slick2D(12.8MB) 和 LWJGL(5.8MB) 两部分组件。
添加库文件
为了使用 Slick2D,你需要把库文件添加到 IDE。使用「Add External Libraries」或者类似功能(有的 IDE 可能需要先创建一个 Project 才能选择 Libraries),把下载的文件中slick/lib
中的slick.jar
,以及lwjgl-x.x.x/jar
目录下的全部jar
文件全部添加到 IDE 即可。
设置 VM Options
最后还需要把 LWJGL 的 native(位于lwjgl-x.x.x/native/
目录下)链接到 Java 虚拟机。LWJGL 是基于 OpenGL 的,而这些文件就描述了有关 OpenGL 的信息。先把这些文件放到你的项目目录中,然后找到你的 IDE 的 VM Options 设定,在里面填入如下内容:
-Djava.library.path="path/to/lwjgl-x.x.x/native/<linux|macosx|solaris|windows>"
注意要把其中的路径替换为真实路径。根据实际操作系统,选择 linux, maxosx, solaris 或者 windows 的其中一个即可。
Hello, World
为了测试开发环境是否搭建正确,可以用一个简单的 Hello, World 级程序测试一下。
假设我们的主类叫做HelloWorld
,可以添加如下代码进行测试:
import org.newdawn.slick.AppGameContainer;
import org.newdawn.slick.BasicGame;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.SlickException;
public class HelloWorld extends BasicGame {
public HelloWorld(String title) {
super(title);
}
public void init(GameContainer container) throws SlickException {
}
public void update(GameContainer container, int delta)
throws SlickException {
}
public void render(GameContainer container, Graphics graphics)
throws SlickException {
graphics.drawString("Hello, World!", 100, 100);
}
public static void main(String[] args) {
AppGameContainer app = new AppGameContainer(new HelloWorld("Hello World"));
app.setDisplayMode(800, 600, false);
app.start();
}
}
如果能正常显示 FPS 和 “Hello, World!” 字样,则说明 Slick2D 配置正确。
示例程序说明
这一部分很重要,弄懂这个简单的示例程序是理解游戏开发的第一步。
BasicGame
:我们的主类继承了BasicGame
类。BasicGame 是 Slick2D 提供的一种基本游戏类型。对应的还有StateBasedGame
,在下节我们会讲到。init
:这个方法在第一次创建场景的时候会自动被调用,一般用于初始化常数、载入资源等等。其中GameContainer
就是游戏「容器」,可以理解为整个游戏窗口。update
和render
:这两个方法很重要。我们玩游戏的时候都了解 FPS 的概念,即每秒的帧数。因为游戏的画面不是静止的,所以实际上程序是通过「逐帧重绘」的方式向我们呈现画面的:每秒绘制 60 次(假如 FPS 为 60),每次根据需要改变绘制的内容,从而呈现出动画效果。- Slick2D 也是这么做的。游戏运行的时候,每次绘制之前,系统会自动调用
update
方法来更新数据,然后自动调用render
方法来绘制,周而复始,不断循环。通过 update-render-update-render 这样调用,来最终形成我们需要的效果。所以,你的任务就是提供这两个方法的实现。 每次调用
update
方法的时间差并不是一定的(甚至都不一定是均匀的),这取决于系统的性能和一些随机因素的影响。为了解决这个问题,引入了update
方法的参数delta
。它代表了本次调用update
和上次调用update
的时间差,有的时候,我们需要这个时间差才能决定update
的具体内容(比如移动的距离)。在例子中,我们在
render
函数中干的事情就是渲染一个字符串,使用 Slick2D 提供的drawString
方法。这个方法的两个整数参数代表字符串的位置。游戏坐标系以 (0,0) 为左上角,(宽,高) 为右下角,和我们习惯的笛卡尔坐标系的原点位置(左下角)不同,这个要注意一下。- 而最后在
main
函数中,我们设置分辨率为 800 x 600,并启动游戏。