从零开始重写KOK1(万王之王1) —— (1)让人物可在地图上使用鼠标跑动

从飞信裸辞已经2个月了,因为对游戏的爱,和做出好玩的游戏这个梦想。《Windows游戏编程大师技巧》(以下简称《大师》)这书已经读完,DEMO也都搞清楚了,为了确实的掌握2D游戏的技术,决定完成一个完整的KOK1咒术师打钱坑的DEMO,也是作为我踏入游戏开发行业的简历附加DEMO。【广告】对游戏有爱的游戏公司(北京)缺人(2D/3D游戏程序员)的话请随时把我拉走。这个系列文章将记载在这个DEMO开发过程中的一点一滴,废话不说了,进入正题。

 

0. 本期功能

(1)人物可以在地图上通过鼠标右键控制走动

(2)地图可以卷动,并且人物不会超过边界

(3)人物在站立和跑动时会有相应的动画

(4)人物在站立和跑动时会面向适当的方向

(5)鼠标有动画,并且无法移出窗口

 

截图:

KOK1_1

 

可直接运行版本 >>下载页地址<<

 

1. 开发工具与语言

在学习《大师》的时候,他主要是用C实现的,并且在性能敏感的位置穿插了一些汇编代码,我的示例最开始也是用C来写,并且贯彻作者多使用全局变量的做法,但当逻辑逐渐复杂了之后,太多的函数与全局变量使得开发效率受到了不小的影响,所以这个DEMO我使用C/C++来写,主要的对象按类来封装,对于性能方面没有过多的注意,以后再重构和优化吧。本文的开发环境是VS2010,DirectX 8.1 SDK,图形部分使用DirectDraw7。

 

2. 主要对象

目前的DEMO主要有以下几个对象:

GameScreen - 游戏屏幕,就是用户窗口的客户区,这个类提供游戏屏幕相关的属性,如宽高、左上角在世界地图的坐标、以及一个视频控制器。

Map - 游戏地图,这个类提供了地图相关的属性,如每个小图块的宽高,地图数据数组,横向和纵向有多少块小图块。还有地图的初始化(Init)、每一帧绘制(Draw)、释放(Release)的方法。

Player - 玩家,这个类提供了玩家相关的属性,如玩家位图的宽高,在屏幕绘制的左上角坐标,在世界地图的坐标,跑动速度,目标坐标等等,同时也提供了初始化(Init)、每一帧绘制(Draw)、释放(Release)的方法。

Bitmap24 - 24位位图,这个类提供了对24位位图的读取功能,把字节顺序调整为正序,并且改为32BPP的格式。详细的实现方法可见我前面的两篇文章:32BPP窗口模式下24位位图的像素操作(1) 32BPP窗口模式下24位位图的像素操作(2)

VideoManger - 视频管理器,这个类封装了DirectDraw7的相关操作,如创建表面、裁剪表面、从位图中取元素等。

MouseManager - 鼠标管理器,这个类封装了DirectInput的相关操作,以获取最新的鼠标情况,详细的实现方式在前面的这篇文章里:使用dinput鼠标的相对模式达到绝对定位

Controller - 操作管理器,这个类分离了用户的操作与游戏里的逻辑。Controller::ProcessRequest()将在每帧调用,用来处理用户操作,并调用这个管理器封装的相关逻辑操作,如PlayerMove()。

 

3. 全局流程

(1)流程很简单,首先就是创建窗口,并且调整好窗口的大小和位置,为什么还要调整呢,原因和解决方案在这篇文章里:确定窗口实际用户区的一些问题

(2)就是在窗口创建好了之后,在主消息循环开始之前,进行我们所需要的对象的初始化工作。

(3)然后开始主消息循环,这里要注意使用PeekMessage,并且Peek后REMOVE掉,否则将不是一个真正实时的游戏循环。在主消息循环里执行我们的游戏逻辑。

 

(4)最后在主循环退出后释放所有资源。

 

4. 角色动画的实现

鼠标动画的绘制非常简单,请下载一看源码就知道了,地图的实现方法就是在一个大表面上来取一块放在显存里,也很简单,这里都不再赘述了。

 

角色动画涉及8个方向和两个状态(站立和跑动)的动画。所以我们要准备好(8*站立动画帧数 + 8*跑动动画帧数)个表面,并且有两个动画索引数组。准备好后,我们可以考虑到实现角色动画无法就是判断在当前游戏帧,我们应该把上面那么多个表面其中的哪一个写到显存里去。因素有3:

(1)Direction - 人物朝向

(2)AnimationIndex - 人物动画当前索引

(3)Status - 人物状态是在站立还是跑动

 

首先分析人物朝向。人物朝向是受玩家给出的目标移动指令后才做改变的,所以可以考虑在Controller::PlayerMove()执行时来修改这个值。

 

接着是人物动画索引。这个可以在人物绘制时处理,在每次绘制完成后,将这个索引加1即可。

 

最后是Status。这个更简单了,必然是在用户做出操作后来修改。

 

因为以上3因素已经都有归属了,所以在每一帧,我们只要根据3因素画出相应的表面即可 。

 

5. 总结

至此,本期的功能都实现,但还有以下主要不足:

(1)目前角色的移动是将当前角色坐标和目标坐标做比对,然后在X和Y上都加上RunSpeed,而实际应该是求出向量,在向量上增加RunSpeed。这样角色移动的速度就更符合逻辑了。

(2)因为这个DEMO的图像都是我从游戏里截图出来的(PS了很久啊~~),所以帧数相当低。

 

6. 源码下载

>>下载地址页<< 资源分是1,有兴趣和诚意的朋友下吧。

 

7.下一期将完成除了现在地表图像的绘制,还要在地图上绘制可以阻挡住人物的护栏、石头等物体,以及人物可以自动绕过障碍的寻路逻辑。

  • 0
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
在Java项目中,使用I/O流的步骤通常如下: 1. 创建I/O流对象:根据需要读写的数据类型和数据源/目的地,创建对应的I/O流对象,如FileInputStream、FileOutputStream、BufferedReader、BufferedWriter等。 2. 读写数据:使用I/O流对象提供的方法,读写数据,如read()、write()、readLine()等。 3. 关闭I/O流:在读写完数据后,需要调用close()方法关闭I/O流对象,以释放占用的资源和关闭文件。 下面是一个读取文件内容并显示的例子: ```java import java.io.BufferedReader; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; public class ReadFileDemo { public static void main(String[] args) { try { FileInputStream fileInputStream = new FileInputStream("test.txt"); //创建文件输入流 InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream); //创建字符输入流 BufferedReader bufferedReader = new BufferedReader(inputStreamReader); //创建带缓冲区的字符输入流 String line; while ((line = bufferedReader.readLine()) != null) { //逐行读取文件内容 System.out.println(line); //显示每行内容 } bufferedReader.close(); //关闭输入流 } catch (IOException e) { e.printStackTrace(); } } } ``` 这个例子中,首先创建了一个FileInputStream对象,用于读取文件内容。然后使用InputStreamReader将字节流转化为字符流,并创建了一个BufferedReader对象,带缓冲区地读取字符流。最后,逐行读取文件内容,并显示在控制台上,最后关闭输入流。 当然,I/O流的使用场景非常广泛,不仅仅局限于读取文件内容。它还可以用于网络传输、数据库操作、图像处理等方面。具体使用方式和步骤根据情况而异。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值