星空之翼游戏的设计与实现
摘要 本毕业设计开发的《星空之翼》是一款纵版飞行射击类游戏。游戏采用组件式架构。整个游戏由主程序模块、游戏引擎模块、地图编辑器模块和声音引擎模块4个相对独立的模块组成,其中声音引擎采用的是一个开源声音引擎irrklang。本毕业设计用到的技术有多线程编程、嵌入式数据库(SQLite)编程和XML。
《星空之翼》游戏采用C#语言编写,设计时采用模块化的设计思想,模块间相对独立,耦合度小,便于今后的并行开发。实现时充分考虑了代码的重用性和功能的灵活性和可扩展性。玩家可以通过地图编辑器制作自己的关卡,自定义敌人和游戏背景;游戏的程序和游戏数据分离,使用户可以很方便的修改游戏素材;同时通过替换其中的游戏引擎模块就可以方便的实现游戏升级。
关键词 游戏引擎,模块化,多线程,XML,嵌入式数据库
The Design and Implementation of “Star Wings”
Abstract
"Star Wings" is a vertical version of flight shooting game. We design the project with component-based architecture. The project consists of four relative dependent modules: main program module, the game engine module, the map editor module and sound engine module. The sound engine here uses an open source sound engine, named irrklang. The technologies involved in our project include: multi-thread programming, embedded database (SQLite) programming and XML.
“Star Wings” is developed by C#. The whole project adopts modularizing design method, the modules are relative independent, coupling degree of the modules is relative low, it is feasible for parallel developing in the future. We full considered the code reusability and flexibility and expansibility of functions. Players can use map-editor to create custom levels, custom enemies and custom game background. The game logic separates from the data, by which players can change their favorite materials, like planes, without rewriting the codes. At the same time, game update can be done just by replacing the game engine module.
Keywords game engine, modularity, multi-thread, XML, embedded database
目录
第一章 概述
1.1 课题背景
1.2背景知识
1.2.1 游戏引擎
1.2.2 多线程
1.2.3 嵌入式数据库sqlite介绍
1.2.4 XML
1.2.5单例模式(singleton)
1.2.6 碰撞检测
1.2.7 游戏循环体
1.2.8静态类
1.3 毕设意义
第二章 游戏的总体分析与设计
2.1 设计构想
2.1.1 游戏定位
2.1.2 游戏需求
2.1.3 游戏扩展
2.2 模块划分
2.3 开发工具
第三章 游戏的详细设计
3.1 游戏引擎模块
3.2 地图编辑器模块
3.3 主程序模块
3.4 游戏主循环
3.5 碰撞检测
3.6 地图格式与精灵图片处理
3.7声音引擎
3.8 模块间的关系
结论
毕业设计总结
未来的工作
在信息技术高速发展的今天,电子游戏已经深入人们的日常生活,成为老少皆宜的娱乐方式。人类爱玩的天性是驱动电脑游戏硬件和软件技术不断向前发展的根本动力之一。电脑发展经历了半个多世纪,电子游戏也产生了半个多世纪,各种各样的游戏出现在历史的舞台上,一个新游戏在展现完自己辉煌一刻后,又被新的游戏推进尘封在历史的角落里。新游戏像雨后春笋般涌现,随着游戏技术的不断发展,游戏的容量越来越大,使用的技术越来越复杂,但游戏开发最基本的技术是相同的,本设计通过C#开发一款纵版飞行射击类游戏,来研究游戏程序的架构,试图编写一个能够代表飞行射击类游戏的通用软件,可以完全改变游戏的内容,而不用重复开发,游戏的架构能够很好的支持游戏的不断地修正和改变。
游戏开发向来都是C和C++的天下,是因为C 和C++是直接编译派系,在操作系统上运行很快。而java和C#是中间编译派系,运行速度慢,但是可以方便平台移植。随着计算机硬件技术的快速发展,因运算速度导致的差距不断减小,java和C#也可以开发一些游戏,毫不疑问未来java和C#会在游戏开发市场占有一席之位,根据TIOBE开发语言排行榜2011年5月的排名来看最新的前五名分别是Java、C、C++、C#、PHP,其中java同比增长了0.2%,C#同比增长了2.75%,而C降低了2.02%,C++降低了1.23%,其中C#更是取得新的历史高点,C#语言从2000年6月发布以来占有率不断缓慢上升,作为微软全力推行的语言,C#的占有率相信会不断缓慢上升,他来源于C和C++,同时借鉴了Visual Basic、Java、Delphi的特性。微软为C#推出了XNA和Xbox360游戏引擎,相信用C#开发的游戏会不但涌现。
1.1 课题背景
《星空之翼》属于射击类游戏,这里所说的射击类,并非是类似《CS》的模拟射击(枪战),而是指纯的飞机射击,由玩家控制各种飞行物(主要是飞机)完成任务或过关的游戏。具体属于科幻飞行模拟游戏(Science-Simulation Game)。游戏的内容为非现实的科幻的,游戏视觉版面为纵版。其中最经典的是《雷电》, 因操作简单,节奏明快,受到了广大玩家的欢迎,可以说是老少皆宜的游戏了。《雷电》在电子游戏中有这相当数量的变种,有着庞大的爱好者,在3D游戏网页游戏流行的今天,《雷电》还是被不断的变种,最新的变种是《雷电OL》和《QQ雷电》。最初的《雷电》有个缺点是只有固定的关卡,游戏玩家无法进行真正意义上DIY(Do It Yourself) ,如果玩家通关后,对该游戏的热情就会大大降低。尽管官方提供了地图编辑器,那个地图编辑器只能采用默认提供的精灵控件。
网络上有大量的《雷电》变种游戏的源代码,其中主要是用C语言和C++语言编写的,少量的是用VB语言和Java语言编写的,用C#语言编写的源代码几乎没有,唯一找到一个是北风网网友编写《勇者斗恶龙》源码,《勇者斗恶龙》游戏仅仅是一个Demo,可以这么说连Demo都不是,太过于简易。
《星空之翼》游戏采用C#语言编写,使用面向对象和模块化的编程思想。玩家可以通过地图编辑器制作自己的关卡,游戏的程序和游戏数据分离,通过替换其中的模块组件就可以实现游戏的升级,《星空之翼》还提供了默认的关卡,默认的游戏剧情小说。《星空之翼》结合默认的游戏剧情和高度自定义地图地图编辑器,不但给玩家娱乐享受,还可以充分发挥玩家的主动性,玩家可以编写出比默认游戏剧情更好的游戏。
此次毕业设计通过对《星空之翼》游戏的设计与实现,深入学习游戏的内部架构,模块化的编程思想,应用程序可扩展性,多线程编程,嵌入式数据库和XML的使用。
1.2背景知识
1.2.1 游戏引擎
游戏引擎是执行游戏中公有任务的程序代码,以前的游戏的容量很小,大都以兆(M)计,每款游戏开发都是从头编写代码,期间存在着大量的重复劳动,耗时耗力。随着技术的发展,开发人员总结出一些规律,在同类题材的游戏中,有大量的相似的代码可以重复使用。为了减少游戏的开发周期和开发费用,慢慢将这些通用的代码进行模块化,方便重用,简化游戏的开发过程。
游戏引擎根据代码的组织方式分为不同的游戏引擎架构,游戏引擎架构是游戏引擎的骨架,常见的三种引擎架构方法为:
(1) 基类根形式构架。基类根形式构架是以基本的几个抽象服务提供接口类为基础,并以接口与实现相分离为原则,来进行引擎实现,提供的实现类在引擎内部创建,而将接口供给用户使用。这种构架模式的优点是结构清晰,实现灵活,可以适应比较大的变化,适合于做一些较大且有跨平台需求的引擎,但是该架构依赖于基本的抽象类的继承关系,导致引擎内部类继承了无用的功能而变得虚大,况且接口的通用性使得实现的效率不高,导致整体效率偏低。
(2) 结构化构架。结构化构架采用的方法是将游戏引擎内部的模块以结构化的形式组合,并以API的形式提供接口,这种构架模式的优点是效率高,接口简单清晰,适合于做一些速度要求比较高的引擎,但是缺点是其模块之间耦合度高,不易修改。
(3) 组件形式构架。组件形式构架是把不同功能的模块做成互相独立的系统,模块内部可以使用任何构架方式,只需要提供相应的接口即可。引擎以模块管理器为核心,支持插件形式组件增加方式,可以将新增的功能组件以插件的形式来插入系统工作,这种构架方式极其灵活,且模块内效率比较高,所以某些大型商用游戏引擎采用这种方式,但这种方式设计比较困难,实现比较复杂,需要大量的开发经验。
1.2.2 多线程
由于游戏的特殊性,游戏对实时性,操作性,画面质量有较高的要求特别是实时性,如果一个游戏不能实时处理,那么基本可以断定一个游戏失败了。
什么是进程?
当一个程序开始运行时,它就是一个进程,进程包括运行中的程序和程序所使用到的内存和系统资源。而一个进程又是由多个线程所组成的。
什么是线程?
线程是程序中的一个执行流,每个线程都有自己的专有寄存器(栈指针、程序计数器等),但代码区是共享的,即不同的线程可以执行同样的函数。
什么是多线程?
多线程是指程序中包含多个执行流,即在一个程序中可以同时运行多个不同的线程来执行不同的任务,也就是说允许单个程序创建多个并行执行的线程来完成各自的任务。
多线程的好处:
可以提高CPU的利用率。在多线程程序中,一个线程必须等待的时候,CPU可以运行其它的线程而不是等待,这样就大大提高了程序的效率。
多线程的不利方面:
线程也是程序,所以线程需要占用内存,线程越多占用内存也越多; 多线程需要协调和管理,所以需要CPU时间跟踪线程;线程之间对共享资源的访问会相互影响,必须解决竞用共享资源的问题;线程太多会导致控制太复杂,最终可能造成很多Bug;
在《星空之翼》游戏中采用多线程来提高游戏运行速度。
1.2.3 嵌入式数据库sqlite介绍
SQLite是一款轻型的开源数据库。它的设计目标是嵌入式的,在很多嵌入式产品中使用了它,它占用资源非常的低。SQLite能够支持Windows/Linux/Unix等等主流的操作系统,同时能够跟很多程序语言相结合,比如 Tcl、C#、PHP、Java等,还有ODBC接口,同样比起Mysql、PostgreSQL这两款开源世界著名的数据库管理系统来讲,它的处理速度比他们都快。
轻便、无需计算机服务支持和跨平台的SQLite有着广泛的应用,谷歌浏览器(Chrome)就使用了SQlite来存储用户信息和操作。
《星空之翼》游戏中采用SQLite来存储游戏数据,方便游戏各模块之间的的通信。同时便于游戏的扩充。
1.2.4 XML
XML(Extensible Markup Language)即可扩展标记语言,它与HTML一样,都是SGML(Standard Generalized Markup Language,标准通用标记语言)。Xml是Internet环境中跨平台的,依赖于内容的技术,是当前处理结构化文档信息的有力工具。
《星空之翼》游戏中采用XML对游戏程序的各项参数进行自定义配置。
1.2.5单例模式(singleton)
单例模式(singleton)顾名思义,就是只有一个实例。单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。这个类称为单例类。
单例模式的要点有三个:
(1) 是某个类只能有一个实例;
(2) 是它必须自行创建这个实例;
(3) 是它必须自行向整个系统提供这个实例。
在《星空之翼》游戏中盟友的管理,敌人的管理,盟友武器的管理,敌人武器的管理和冲突检测的管理都必须确保只有一个实例。
1.2.6 碰撞检测
《星空之翼》游戏中碰撞是最关键的技术,因为飞行射击类游戏说白了就是碰撞的游戏——躲避敌人的子弹或飞机,同时用自己的子弹去碰撞敌人。游戏中的碰撞检测方式有很多,不同的算法之间主要是在精度和速度之间权衡。碰撞检测的算法归纳为3类:
(1) 范围检测:将游戏中的物体划分为规则的几何范围,如果两物体的范围相交,则判断两物体相撞。
(2) 颜色检测:取出物体中所有像素点的颜色和当前物体所在区域的像素点的颜色,两者进行AND运算,判断结果。
(3) 路线检测:通过行进路线来检测是否发生碰撞。使用向量来进行判断。
在《星空之翼》游戏中采用范围检测中的矩形检测方法。
1.2.7 游戏循环体
在游戏设计和开发中,尤其是引擎开发中,逻辑循环是一个重要组成部分,循环决定了游戏的基础逻辑和运行方式。常见的游戏循环方式有五种:
(1) 自身式循环:自身式循环比较容易理解,比如一个精灵控件,自己内部实现一个循环,来不停的检测和执行逻辑,开发者都不需要去单独做什么,只需要new出来它们自己就会执行逻辑了,这种方式非常便捷和方便,开发起来也相对容易,互相之间没有任何关系,此时需要借助单例之类的设计模式来解决互相的结合问题。
(2) 链条式循环:自身逻辑存在各自的循环消耗问题,为了减少消耗,可以将各自的循环逻辑统一到一个循环中,基本的原理是将各个循环体放入到一个大循环中,然后从第一个开始执行循环逻辑,只执行一次,然后下一个,到底以后回来继续执行。
(3) 子树式循环:子树循环顾名思义,使用树状结构来处理循环逻辑,我们实际应用中还有可以分为:活动子树式循环和固定子树循环.
(4) 区间式循环:区间式循环原理是将游戏系统各个部分拆分开,挂入不同的循环结构中,在区间式循环中,分拆最消耗性能的部分,到另外一个线程(或循环结构)中完成循环。
(5) 组合式循环:组合式循环是组合前四种循环方式,实际应用都是结合前四种方式一起使用。
1.2.8静态类
《星空之翼》游戏中有很多数据需要在各个类之间共享,静态类可以满足类之间的数据共享。静态类是不能实例化的,我们直接使用它的属性与方法,静态类最大的特点就是共享。
静态类就是在class关键字前加入了static关键字,基本语法是static Class ClassName{} 。静态类有几个特点:
(1) 静态类只能包括静态成员
(2) 类本身无法被实例化,也就是不能创建静态类的对象
(3) 静态类无法被继承
(4) 无法包含实例构造方法
创建静态类的时候,必须注意到以上四点。静态类所提供的数据成员和方法成员具有唯一性,就如同使用了全局变量,所以比较适合封装公用的成员。
1.3 毕设意义
本次毕业设计通过对《星空之翼》游戏的设计与实现,掌握制作一个游戏软件的方法,以及制作游戏软件的整个流程,制作游戏软件的步骤。
在开发《星空之翼》游戏中,对游戏架构进行分析、探索和实践。学习了游戏开发设计思想,程序架构,数据结构和算法,特别是对程序的扩展型有了直观的认识。本毕业设计体现面向对象的编程思想和模块化设计思想,本毕业设计用到多线程编程、嵌入式数据库(SQLite)编程和XML技术。本次毕业设计不但对大学四年所学的专业基础知识进行了复习、巩固和提高。而且学习了新的技术知识和思考解决问题的方法。
本次毕业设计对软件可扩展性和灵活性进行了探索和研究,《星空之翼》游戏能够代表飞行射击这一类的游戏,完全可以通过更改其中的精灵素材和设置,将《星空之翼》改变成为另一个的纵版飞行射击类游戏。
第二章 游戏的总体分析与设计
2.1 设计构想
由于游戏的特殊性,游戏的设计总是在开发的过程中被不断地修正和改变,因此游戏开发时常做无用功,把自己已经写好的东西推倒重来。为了避免过多的无用功,必须使代码模块强内聚、松耦合。在本设计中一定程度体现面向对象的思想和模块化编程带来的好处。在代码编写中,极力避免在面向对象的开发环境中进行面向过程的代码编写。
随着游戏开发的不断推进,延续的变更会使游戏的整体结构日渐紊乱,使程序难以理解和维护,所以在游戏的设计中,特别是在前期的设计中,我给游戏的核心给予足够的重视,多角度的全面分析,不要贪多求快,盲目过早进入具体的外部效果设计。
在本设计中游戏的整体采用组件式构架。不同功能的模块做成互相独立的系统,模块内部可以使用任何构架方式,只需要提供相应的接口即可。
2.1.1 游戏定位
《星空之翼》是一款纵向卷轴的飞行射击类的2D游戏。《星空之翼》的游戏定位是游戏DIY爱好者,游戏玩家可以自行控制游戏的各种元素。可以修改整个战场的背景、敌人、自己的战机等等,还可以使用自己的图片制作游戏精灵,支持游戏中的精灵元素更改。并提供扩展支持。采用模块设计,可以多人同时完成游戏的开发。地图文件采用嵌入式数据库SQLite,可以对地图文件进行加密。游戏窗口的大小游戏的地图决定,如果当前游戏的窗口与地图窗口不一致,游戏会自动更改游戏的窗口。游戏的各种界面参数保存在XML配置文件中。
2.1.2 游戏需求
《星空之翼》是一个纵向卷轴的2D游戏,游戏玩家的操作有6个按键,分别是 上、下、左、右、机枪、导弹回车键暂停/继续。游戏运行环境为.NET Framework2.0。星空之翼的关卡是采用提前读取的方式,不采用动态提取的方法。玩家飞机在开火,吃奖品,或者被击毁的时候有相应的提示音,游戏完成后会根据游戏玩家的信息显示历史积分榜。游戏的关卡与程序独立,通过配置文件来决定关卡的进行。通过地图编辑器完成关卡的内容。
2.1.3 游戏扩展
游戏的扩展性决定游戏能否长期被玩家追捧。在本设计中最大可能提供游戏的扩展性,如提供地图编辑器,玩家可以自己设计优秀的地图文件。玩家可以将自行设计的精灵图片放入的资源文件中从而改变游戏的敌人和背景。关卡文件采用的是嵌入式数据库SQLite,在后续的开发中可以添加新的游戏元素,从而完成游戏的升级。游戏主程序与地图编辑器是独立的两个模块,他们通过地图文件进行通信。游戏的内核是单独的DLL文件,在独立的工程里完成设计,可以不断修改其中的算法从而使游戏的运行速度更快,效果更好。
2.2 模块划分
《星空之翼》游戏的模块分为:
(1) 游戏引擎模块:负责游戏精灵的管理、游戏世界的计数器、游戏的冲突检测、图像渲染和粒子系统。
(2) 地图编辑器模块:负责游戏地图的创建和修改。
(3) 主程序模块:负责游戏的流程的控制和玩家的交互。
(4) 声音引擎模块:负责播放游戏的各种声音。
2.3 开发工具
本毕业设计采用的开发工具是Microsoft Visual Studio 2005
游戏开发使用的语言是C#
游戏需要运行的环境是.net framework 2.0
第三章 游戏的详细设计
3.1 游戏引擎模块
图3.1 游戏精灵类图 |
游戏引擎采用的是基类根形式构架。游戏引擎包括游戏精灵的管理、游戏世界的计数器、游戏的冲突检测、图像渲染和粒子系统。
游戏引擎最基本的类是精灵类(sprite)。敌人(Enemy)、盟友(Ally)、敌人武器(EnemyWeapons)、盟友武器(AllyWeapons)都从精灵类继承。
精灵动画类(Movie)封装类精灵的图片动画。
游戏引擎中有很多设计成单例模式的类。
(1) 对于所有的敌机,设计一个敌机管理类(EnermyManagement),由于整个游戏中只有敌机管理类,类设计采用单例模式。
(2) 对于所有的盟友,设计一个盟友管理类(AllyManagement),类设计采用单例模式。
(3) 对于所有的敌机武器,设计一个敌机武器管理类(EnermyWeaponsManagement),类设计采用单例模式。
(4) 对于所有的主角武器,设计一个主角武器管理类(AllyWeaponsManagement),类设计采用单例模式。
图3.2 游戏引擎中的管理类 |
(5) 设计一个碰撞检测类(CollisionSystem),类设计采用单例模式。
在游戏引擎中定义了一个GameConfig的静态类,用于共享游戏中的公共数据。
public static class GameConfig
{ public static int GameWordWidth = 800; //游戏世界的视觉宽度
public static int GameWordHeight = 600; //游戏世界的视觉高度
public static int GameWordTime = 1; //游戏世界的时间
public static int GameMode =0; //游戏世界的状态
}
3.2 地图编辑器模块
地图编辑器,顾名思义,就是用来编辑地图的工具,如果玩过《魔兽争霸》或《帝国时代2》、《英雄无敌》的话,应该会知道这几款游戏都附有地图编辑工具,可提供玩家自行编辑地图关卡,地图编辑器就具有类似的功能。
按部就班的按游戏设计者的安排进行游戏,固然会获得一些乐趣。但是否曾经想过玩自己设计的游戏呢?《星空之翼》的地图编辑器给了我们机会,不需要复杂的编程,只要有创意,短时间内就能学会并获得玩自己设计的纵向卷轴的飞行射击类游戏的乐趣。
地图编辑器模块最重要的是确定地图文件的存储格式,在探索地图文件存储格式中经历了4种方案,分别为:自定义二进制文件、XML文件、类的序列化和数据库。最后结合游戏要求和自身技术水平选择了嵌入式数据库(SQLite)。
(1) 自定义二进制文件:由于本身技术水平限制,不能很好的存储变化较大的二进制文件,最后放弃了这种地图文件组织方式。
(2) XML文件:由于XML对玩家过于透明,玩家很容易修改地图文件,导致地图文件极其不稳定,因此放弃了自定义二进制文件
(3) 类的序列化:类的序列化可以很好的组织地图文件,但是考虑到以后的地图文件的存储格式会发生改变,扩展性不强,每次修改都要修改类的定义
(4) 数据库:考虑到随着游戏开发的不断推进,延续的变更会使游戏的整体结构日渐紊乱,使程序难以理解和维护,游戏地图是游戏主程序与地图编辑器联系的纽带,要延续地图的稳定性,采用了数据库可以一定程度上,保持游戏地图的稳定性。最开始选择的数据库是access,可是考虑到许多玩家的电脑不一定安装了access的驱动,因此放弃access,很高兴找到SQLite数据库,SQLite太好了,只要一个System.Data.SQLite.dll就可以了使用该数据库。
目前地图文件主要存储的信息有两个,一个是静态的地图背景,另一个是动态的敌人。还包括一些配置信息。地图编辑器大体上分为两区域,一个是游戏地图的控件菜单区,另一个是游戏地图编辑区。在控件菜单区可以选择背景和精灵两种类别,通过背景玩家可以加载自己喜欢的背景Tile,然后添加到地图中。通过精灵可以添加自定义的敌人,可以设置敌人的运动方式、速度、攻击力,生命值,攻击模式。
图3.3 添加背景和精灵 |
在地图编辑器模块为了提高图形资源的复用,利用一小块一小块的图形(也就是tile)拼成一个大的完整的地图。在本设计中采用的Tile是矩形。在地图编辑器中定义了Sprite控件、Tile类、Map类。
(1) Sprite控件:是一个自定义的不规则控件。
(2) Tile类:Tile类中定义了该Tile在整个地图世界的坐标(X,Y)、大小(Width, Height)和所代表的精灵图片。
图3.4 添加精灵 |
(3) Map类:Map类定义了整个游戏世界尺寸(Width,Height)、Tile链表MapTiles和一系列地图操作方法。
在整个地图编辑器中最重要的3个难点是Sprite控件,游戏世界尺寸的动态变化和地图的读取和存储。
(1) Sprite控件:制作的方法是定义一个方法CalculateControlGraphicsPath来获得图片的边界。然后在Sprite_Load方法中设定Sprite控件的背景图片,设定Region属性为背景图片的边界。就可以得到不规则的控件了。
(2) MapTiles链表:由于地图的尺寸需要不断改变,因此采用一维的List来存储游戏世界的二维可变Tile。
(3) 地图文件的读取和存储:由于地图文件采用的是SQLite数据库,因此地图的存储和读取也就是数据库的存储与读取。其中重要一点的是精灵图片采用的是GIF格式,要对普通的Gif文件处理,将不需要的部分镂空。镂空的方法是用PhotoShop的魔棒工具去除需要镂空的部分。
3.3 主程序模块
游戏主程序模块是整个游戏的核心,游戏主程序负责游戏的流程的控制和玩家的交互。在游戏主程序模块的重点有:
1. C#多线程编程
2. XML配置游戏信息
3. 全局键盘
4. 玩家交互
5. 地图管理
游戏的主程序采用了多线程,不同的子线程完成不同的工作。不同的线程又不同的调用周期。主程序创建了4个子线程,分别为warTimethread(战场计数器线程)、paintthread(战场打印线程)、managementthread(战场管理线程)、updatethread(战场更新线程)。
1. 战场计数器线程:主要完成整个游戏世界时间的记录。
2. 战场打印线程:完成对整个游戏所有的打印工作,包括游戏背景、敌人、盟友、敌人武器、盟友武器、爆炸效果和粒子系统图像的打印。
3. 战场管理线程:主要完成的是游戏的碰撞检测和游戏精灵的运动。
4. 战场更新线程:主要完成的是游戏世界游戏精灵的清理和再生。
游戏主程序采用XML配置游戏的名称、版本、游戏界面的高度和宽度。在《星空之翼》游戏中定义了一个SystemConfig类来操作游戏配置文件。
《星空之翼》提供了老板键Ctrl+F2。老板键用的技术使用了键盘钩子。在《星空之翼》游戏中定义了一个HookDll类,HookDll用于处理全局键盘事件。在游戏运行时是先安装了键盘钩子,就可以使用Ctrl+F2隐藏显示游戏界面的窗口。游戏退出后卸载钩子。
玩家可以根据自己的喜好设定玩家战机的初始装备和操作方法。
图3.5 自定义玩家信息 |
游戏玩家可以将自行设计的游戏地图加载到游戏中,游戏主程序会根据地图的尺寸改变自身的大小。游戏玩家的可以中途修改游戏的操作。
图3.6 游戏界面 |
游戏的基本流程是:游戏初始化—读取配置文件—选择游戏模式--开始游戏—结束游戏—保存配置
3.4 游戏主循环
图3.7 游戏主循环 |
游戏主程序核心是一个游戏主循环(Game Loop),游戏主循环(Game Loop)是每个游戏中最重要的一部分。游戏都是由更新状态、处理数据、播放音乐、更换地图和处理动画来构成。最能解释游戏主循环的就是固定的FPS(每秒帧数),例如,每次刷帧,地图向下移动1个像素,人物向上移动2个像素。而能引起这种的更新的一般是由两种行为引起的:
(1) 事件驱动(用户输入)
(2) 固定时间的FPS(每秒帧数)
《星空之翼》游戏采用的游戏主循环为组合式的游戏循环。在程序中玩家交互循环是事件驱动引起的,在游戏启动的情况下,游戏每隔33毫秒执行一次战场打印,每隔1毫秒执行一次战场计数,每隔10毫秒执行一次碰撞检测,每隔150执行一次游戏更新。游戏各子线程完成各自任务,相互配合,共同完成游戏的主循环。
3.5 碰撞检测
《星空之翼》采用最简单的碰撞检测算法矩形碰撞检测。最开始采用的是一个非常简单的算法A,经过多次测试,发现有些情况不能检测出碰撞,最后采用算法B.
(1) 算法A
图3.8 碰撞检测算法A |
x1 + w1 > x2 限定第一个矩形的右边线在第二个矩形的左边线右边
x1 < x2 + w2 限定第一个矩形的左边线在第二个矩形的右边线左边
这样下来,就限定了两个矩形在X方向上投影必然相交。同理
y1 + h1 > y2 限定第一个矩形的下边线在第二个矩形的上边线下面
y1 < y2 + h2 限定第一个矩形的上边线在第二个矩形的下边线上边
这样下来,就限定了两个矩形在Y方向上投影必然相交。综合起来就可以简单进行碰撞检测了。
判断(x1 + w1 > x2 && x1 < x2 + w2 && y1 + h1 > y2 && y1 < y2 + h2)是否为真,如果为真,则发生了碰撞。
(2) 算法B
图3.9碰撞检测算法B |
算法B能够检测出倾斜矩形间的碰撞检测,在碰撞检测的精度上提高了。可以采用的方法有两个,一个是采用的方法是依次判断矩形A的四边是否与矩形B相交。另一个是依次判断矩形的四个点在另一个矩形里。《星空之翼》采用的是第一种方式。
if (((p1.X - q1.X) * (q2.Y - q1.Y) - (q2.X - q1.X) * (p1.Y - q1.Y)) * ((q2.X - q1.X) * (p2.Y - q1.Y) - (p2.X - q1.X) * (q2.Y - q1.Y)) >= 0)
{
if (((q1.X - p1.X) * (p2.Y - p1.Y) - (p2.X - p1.X) * (q1.Y - p1.Y)) * ((p2.X - p1.X) * (q2.Y - p1.Y) - (q2.X - p1.X) * (p2.Y - p1.Y)) >= 0)
{ return true; }
}
return false;
3.6 地图格式与精灵图片处理
在《星空之翼》游戏中地图文件格式为*.map,实际上的地图文件格式为*.db,一个地图文件就是一个SQLite数据库文件,目前每个地图文件包括3个表Level,Sprite,LevelSprite。
(1) Level:描述了当前游戏关卡的游戏界面的尺寸、背景图片、故事剧情信息、地图尺寸等信息。
(2) Sprite:存储了当前关卡里所有的精灵的详细信息。
(3) Levelsprite:存储了当前关卡敌人、陨石和动态背景的具体的详细信息,包括生命值、攻击力、运动速度、运动模式、攻击模式、出现地点等详细信息。
在地图编辑器生成地图时,会将Level、Sprite和LevelSprite表的信息加入到地图文件中,然后在游戏主程序读取地图信息。
《星空之翼》精灵采用的原始图片为GIF格式,由于精灵通常都是不规则的图片,因此要对原始GiF处理,一种处理的方法是用Photoshop的魔棒工具去除透明背景。
将GIF文件加载到Photoshop中,选择魔棒工具,用魔棒工具点击GIF背景部分,魔棒工具会自动选择出背景部分,按DEL键删除背景,透明背景处理完成后另存为Gif格式,就可以的到透明的GIF背景图片。也可以使用专门的GIF透明背景处理小工具Ulead GIF Animator。
3.7声音引擎
Irrlicht是一款开源免费的声音引擎,Irrlicht引擎是一个用C++书写的高性能实时的3D引擎,可以应用于C++程序或者.NET语言中。在c#中使用Irrlicht很简单,引用irrKlang.NET.dll就可以了使用Irrlicht声音引擎了。使用的方法很简单,两行代码就可以播放声音了。
ISoundEngine engine = new ISoundEngine(); //定义引擎
engine.play2D("one.mp3"); //播发声音
在《星空之翼》游戏中主要用Irrlicht声音引擎播放游戏中的各种声音。
3.8 模块间的关系
整个游戏的组织方式是组件形式构架,游戏引擎、地图编辑器、游戏主程序、声音引擎是互相独立的系统,模块内部可以使用任何构架方式。这样的组织方式是比较灵活,可以同时进行开发,便于后续的开发。游戏主程序是整个模块的核心。
(1) 游戏主程序和地图编辑器:游戏主程序与地图编辑器之间用通过地图文件,地图编辑器创建修改地图文件,游戏主程序读取地图文件。
(2) 游戏主程序与游戏引擎:游戏主程序与游戏引擎的关系是最密切的,游戏主程序读取地图内容放进游戏引擎相关的类中,游戏引擎将处理的结果返回到游戏主程序中在显示出来。
(3) 游戏主程序与声音引擎:游戏主程序根据游戏引擎返回的结果,播放相应的游戏声音。
结论
毕业设计总结
《星空之翼》游戏开发时采用模块化的设计思想主要体现在:游戏引擎、游戏主程序和地图编辑器可以同时进行开发;对游戏引擎的算法进行优化,不会影响游戏主程序的运行;只要游戏地图格式不变,对地图编辑器的任何更改都不会影响游戏的运行;
《星空之翼》游戏开发时充分考虑了代码的重用性、功能的灵活性和可扩展性主要表现在:《星空之翼》的游戏引擎包含了纵版飞行射击类游戏所必须需的公用代码,只要是纵版飞行射击类游戏都可以直接引用《星空之翼》的游戏引擎;游戏主程序可以自行根据地图尺寸修改游戏本身的配置,玩家可以自行设置操作方法和游戏初始状态。地图编辑器可以设置游戏精灵攻击力、生命值、运动速度、运动模式和攻击模式等信息;游戏引擎采用面向对象体系结构设计原则,有很好的扩展性。《星空之翼》游戏地图采用的是嵌入式数据库SQLite,未来可以根据游戏的需求,改变游戏地图格式。因此地图格式有很好的扩展性。
未来的工作
由于时间紧迫,整个游戏开发有许多不如人意的地方,未来有许多需要改进的地方。下面例举出存在的不足和未来需要改进的地方:
(1) 在游戏引擎中,需要完善各个类之间的访问权限,需要丰富相应的构造函数满足不同条件下的需求。
(2) 在游戏引擎中,需要优化碰撞检测算法和粒子系统算法。
(3) 在游戏引擎中,需要为游戏精灵添加人工智能,让游戏精灵在游戏中运行得更好。
(4) 在地图编辑器中,需要解决地图文件读取的时间过长,需要减少地图文件占用的空间过大的问题。
(5) 在地图编辑器中,为地图文件添加密码选项,满足不同DIY爱好者的需求。
(6) 完善游戏主程序占用资源过高的问题,提高整个游戏的视觉效果和声音效果。
本文相关源码与论文下载 作者其他源码下载