0.前言
本例子取自cping1982早期公开的一个AVG源码,loon-simple-20090212,里面带了6个游戏。这次我们要分析的是AVGSimple这个游戏。截图如下:
下载地址:http://code.google.com/p/loon-simple/downloads/list
声明一下,这个程序不是我写的,是cping1982写的。本人在这里斗胆分析一下高手5年前写的代码,一来是提高自己,二来也是给众多小白以信心和勇气,分析完源码你会发现用java写一个AVG游戏还是不难的。
如果你无法访问google code,也可在本文文末下载我已经加上了注释的版本。
原作者的博客上有3篇文章,可谓说相当好。说的东西都是点到为止,需要读者自己去结合源码细细品味。
Java版AVG游戏开发入门[0]——游戏模式转换中的事件交互
Java版AVG游戏开发入门[1] —— CG的绘制
Java版AVG游戏开发入门示例[3]——脚本引擎的制作及应用
我这里稍微再详细的分析一点源码。
1. 游戏模式转换
IControl的抽象化是关键,可以避免像STG雷霆行动那样冗长的if else分支判断现在处于哪种模式,使得扩展更简单。其实我们看一下这张序列图可以发现,一切的东西都是绘制到画布上的(AVGCanvas.paint方法),只是“如何画”这个逻辑给分散到了不同的IControl子类里。而AVG.setControl可以达到方便的切换模式的作用。
IControl有这些子类
Title 标题模式
Script 游戏中模式(采用了脚本系统)
AqueductGame 水渠贯通小游戏模式
IControl有如下这些方法可供子类实现
invoke 转换控制器接口
draw 画图
mouseMoved 鼠标处理
mousePressed 鼠标处理
keyPressed 键盘处理
这样添加新的模式就很简单了,各个模式之间相对做到解耦,而且功能也都有了。
2. CG
就是实现IControl各个子类的draw方法。如何画?主要步骤就是先画背景图,再画前景。
下面举1例
2.1 Title的绘制
public void draw(Graphics g) {
//1.先绘制背景图
graphics.drawImage(title, 0, 0, null);
//2.画窗体蓝色背景
Message.setWindowMessage(graphics, MESSAGE_LINE_X1, MESSAGE_LINE_Y1,
MESSAGE_LINE_X2, MESSAGE_LINE_Y2);
//3.画窗体边框
Message.setWindowFrame(graphics, MESSAGE_LINE_X1, MESSAGE_LINE_Y1,
MESSAGE_LINE_X2, MESSAGE_LINE_Y2);
//4.画菜单选项
for (int i = 0; i < messages.length; i++) {
// 选中
if (i == selectFlag) {
// 变更字体颜色。
graphics.setColor(Color.white);
// 设定浮标。
Message.setWindowBuoyageMessage(selectFlag, 160, 34, graphics,
MESSAGE_LINE_X1, MESSAGE_LINE_Y1,
MESSAGE_LINE_X2 + fontSize + 2, MESSAGE_LINE_Y2
+ fontSize + 40);
// 未选中
} else {
graphics.setColor(Color.gray);
}
//一个字一个字的画出来
for (int k = 0; k < messages[i].length(); k++) {
Utility.drawDefaultString(messages[i].substring(k, k + 1).toString(), graphics, font * k + left, i
* (font + fontSize) + font + top, 1, font);
}
}
g.drawImage(screen, 0, 0, null);
g.dispose();
}
用的是RPG Maker XP格式的窗体图。
第一步简单,把背景图画出来即可。
第二步如图,A区绘制窗体蓝色背景,会有一个比例扩大。
第三步如图,需要将B区的通过比例换算分8步画出来(上,下,左,右,还有4个角)
第四步画菜单选项。需要根据鼠标的移动高亮选中的菜单项。
同时,mouseMoved方法处理鼠标的移动,赋值selectFlag,以待下一次绘图时高亮菜单选项。
public void mouseMoved(MouseEvent e) {
super.mouseMoved(e);
int k = (Control.mouse.y - top) / (font + fontSize);
//如果鼠标太上面
if (k < 0) {
return;
}
//如果鼠标太下面
if (k >= messages.length) {
return;
}
//赋值selectFlag,以待下一次绘图时高亮菜单选项
for (int l = 0; l < messages.length; l++) {
if (l == k) {
selectFlag = k;
continue;
}
}
//如果鼠标x轴在框内,则标记“选中”
if ((double) Control.mouse.x > this.MESSAGE_LINE_X1
&& (double) Control.mouse.x < this.MESSAGE_LINE_X1
+ (double) this.MESSAGE_LINE_X2
&& (double) Control.mouse.y > this.MESSAGE_LINE_Y1
&& (double) Control.mouse.y < this.MESSAGE_LINE_Y1
+ (double) this.MESSAGE_LINE_Y2) {
select = true;
} else {
select = false;
}
}
3. 脚本系统
脚本系统的运用一方面可以使得开发效率提高,bug更少,另一方面可以使得后期维护简单。脚本系统一旦成熟,不懂java的人也可以维护甚至开发一个新的游戏。
比如下面脚本显示背景,再显示了2个人物(xiaoyanyan和ranmin)。
cg del
gb image/ghost.png
cg chara/xiaoyanyan.png 0
cg chara/ranmin.png 200
cgwait
原理和之前Title画面类似,主要就是nextScript方法执行脚本,赋给变量(修改model层),而draw方法根据变量不同来画图(view层)。两个方法搭配,比较好的实现了MVC模式。
修改model层
private synchronized int nextScript(final int index, final String s) {
//......
for (j = index; j < scriptContent.length; j++) {
//显示信息
if (messageFlag.equalsIgnoreCase("mes")) {
isMessage = true;
break;
}
//背景
if (messageFlag.equalsIgnoreCase("gb")) {
if (objectFlag == null) {
return index;
}
if (objectFlag.equalsIgnoreCase("none")) {
cg.setBackgroundCG(null);
} else {
cg.setBackgroundCG(Utility.loadImage(objectFlag));
}
continue;
}
//人物
if (messageFlag.equalsIgnoreCase("cg")) {
if (objectFlag == null) {
return index;
}
if (objectFlag.equalsIgnoreCase("del")) {
//删除原有人物
if (orderFlag != null) {
cg.removeImage(orderFlag);
} else {
cg.clear();
}
} else {
//添加人物
int x = 0, y = 0;
if (orderFlag != null) {
x = Integer.parseInt(orderFlag);
}
if (gotoFlag != null) {
y = Integer.parseInt(gotoFlag);
}
cg.addImage(objectFlag, x, y);
}
continue;
}
}
}
view层
public void draw(final Graphics g) {
//1.画背景,带晃动
if (cg.getBackgroundCG() != null) {
if (shakeNumber > 0) {
//通过随机数,达到图片在小范围内晃动效果
graphics.drawImage(cg.getBackgroundCG(),
shakeNumber / 2 - Control.rand.nextInt(shakeNumber),
shakeNumber / 2 - Control.rand.nextInt(shakeNumber), null);
} else {
graphics.drawImage(cg.getBackgroundCG(), 0, 0, null);
}
}
//2.画人物
for (int i = 0; i < cg.getCharas().size(); i++) {
Chara chara = (Chara) cg.getCharas().get(i);
graphics.drawImage(chara.getCharacterCG(), chara.getX(), chara
.getY(), null);
}
}
附件有比较详细的注释,可以参考。
- 大小: 6.9 KB
- 大小: 6.8 KB
- 大小: 2.9 KB
- 大小: 354.4 KB
- 大小: 243.5 KB
- 大小: 4.3 KB
分享到:
相关推荐
HTML5开发围住神经猫游戏,,最经典的一款HTML5游戏
MIPI相关的协议。DSI和CSI协议
OWASP测试指南第四版比起第三版在三个方面更加改善了: 这份指南整合了另外两个旗舰级的OWASP文档:开发者指南和代码评估指南。我们重新编排了章节和测试顺序,目的就是通过测试和代码评估来达到开发者指南中描述的...
第1章 预备知识 1.1 机器语言与汇编语言 1.1.1 机器语言 1.1.2 汇编语言 1.1.3 书中使用符号的说明 1.2 Intel系列机简介 1.2.1 Intel 80X86微处理器简介 1.2.2 Intel 80X86微处理...附录Ⅵ 汇编连接程序错误信息
使用burpsuite对移动app抓包分析 阅读更多 测试移动APP的联网请求,需要获取路径或者参数的时候,使用该工具burpsuite非常方便! 要求: 移动终端和PC处于同一个wlan环境下
官方正式稳定版
i2c-read:(在 adb shell中使用) $ adb root $ adb remount $ adb push i2c /system/bin $ adb shell # i2c-read -b 第几条i2c 设备slave地址 寄存器地址 例如: # i2c-read -b 2 0x26 0x00 seven-square:(模拟器,...
iperf测试吞吐量工具,可以测试wifi,LAN,USB等吞吐量,有win和linux的版本
精美的时间轴制作软件,制作简单易用,精美
setuna乃截图神器~方便大家制作时查看参考图片
(USB移动存储设备使用记录查看器)可用于查看本机的USB移动存储设备使用记录。可查看的设备有:U盘、移动硬盘、MP3、SD卡……等。
1、深入理解linux虚拟内存管理.pdf2、深入理解计算机系统.pdf3、[深入linux内核架构].professional_linux_kernel_architecture.pdf4、Using the GNU Compiler Collection (GCC).chm5、OReilly Understanding the ...
基于Bootstrap与jQuery-validate的个人封装检验框架demo,拥有良好的UI与用户体验
这是一篇有关USB3.0协议的中文讲解。
centos6.8 64位安装oracle 11g需要的全部文件part3
centos6.8 64位安装oracle 11g需要的全部文件
这是一片关于充电的一个规范,大家可以看看
ARM体系的汇编指令详解,DDI0406B_arm_architecture_reference_manual_errata_markup_8_0
centos6.8 64位安装oracle 11g需要的全部文件part4