另一部<星际迷航>游戏(<复古>)(译文)
By robot-v1.0
本文链接 https://www.kyfws.com/games/another-star-trek-game-the-retro-one-zh/
版权声明 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
- 8 分钟阅读 - 3861 个词 阅读量 0另一部<星际迷航>游戏(<复古>)(译文)
原文地址:https://www.codeproject.com/Articles/28877/Another-Star-Trek-Game-The-Retro-One
原文作者:BadKarma
译文由本站 robot-v1.0 翻译
前言
The Star Trek game reworked, using a 2D retro look
使用2D复古外观重新制作了<星际迷航>游戏
介绍(Introduction)
阅读了迈克尔伯肯(Michael Birken)的文章后,人们不得不承认,再次证明只有一种要素可以创造出一款出色的游戏:游戏玩法.不是外观,不是声音.作为忠实的粉丝(*After reading the article of Michael Birken, one has to admit that it is again proven that there is only one ingredient that makes a good game: the gameplay. Not the looks, not the sound. As a huge fan of the*) [内向软件(*Introversion Software*)](http://www.introversion.co.uk/) 游戏都具有特殊的"旧"外观,我想为什么不将这种简单的复古外观添加到该游戏中.(*games, which all have a special 'old' look, I thought why not add this simple retro look to this game.*) 就像詹姆斯
柯伦(James Curran)所说的那样,迈克尔`伯肯(Michael Birken)的文章从上到下涵盖了整个游戏,对此我没有太多的了解.因此,我将重点关注构建类似于主机游戏的2D游戏(非主机)的差异.(Like James Curran stated, Michael Birken’s article covers the game from top to bottom, there isn’t much light I can shed over this. So, I will focus more on the differences of building a 2D game (which isn’t a console) that looks like a console game.)
背景(Background)
我需要解决的第一个问题是,我将在游戏中使用哪种技术. DirectX或OpenGL?第二个甚至更重要:由于这是我的第一个图形项目,我是否能够掌握所选技术并按时编写所有所需的代码?(The first question I needed to solve was, which technique I would use for the game. DirectX or OpenGL? The second was even more important: Since this is my first project on graphics, would I be able to master the chosen technique and write all the needed code for this on time?) 在网上寻找了一段时间后,我偶然发现了以下网站:(After looking for a while on the web, I stumbled upon the following site:) 艾里希特(IrrLicht) .这是一个免费的图形引擎,同时支持DirectX和OpenGL,这也解决了我的第一个问题.该引擎同时提供2D和3D模式,非常完美.我可以从2D开始,而无需更换引擎就可以转到3D.(. This is a free Graphics Engine that supports both DirectX and OpenGL, which also solved my first question. This engine provides both 2D and 3D modes, which is perfect. I could start in 2D, and move on to 3D without the need to change the engine.) 不使用控制台时最大的差异之一就是我们处理输入的方式.控制台程序是输入驱动程序.分析输入后,我们执行所需的逻辑,然后重新绘制屏幕. Windows(非控制台)程序是事件驱动程序.这意味着我需要分析事件并创建自己的输入来驱动游戏逻辑.而且,因为它是一个窗口,所以我需要自己绘制屏幕,并在等待输入的同时继续更新屏幕.(One of the largest differences when not using a console is the way we process inputs. A console program is an input-driven program. After analysing the input, we perform the required logic and then redraw the screen. A Windows (non console) program is an event-driven program. This means that I would need to analyse the events and create my own input to drive the game logic. And, because it’s a window, I would need to draw the screen myself and keep on updating the screen while waiting for input.)
使用代码之前(Before Using the Code)
如果要使用和编译此代码,则还需要IrrLicht SDK,可以将其下载(If you want to use and compile this code, you also need the IrrLicht SDK, this can be downloaded) 这里(here) .它包含您需要启动的所有内容,包括已经构建的DLL和lib.(. It contains everything you need to start, including an already built DLL and lib.) 将SDK放在磁盘上之后,您需要将包含文件和库文件的位置添加到Visual Studio.打开(After placing the SDK on your disk, you need to add the location of the include files and the library files to Visual Studio. Open the)选件(Options)下的菜单(menu under the)工具类(Tools)菜单.选择选项(menu. Select the option)项目与解决方案(Project and Solution)和子选项(and the sub option)VC ++目录(VC++ directories).(.)
使用代码(Using the Code)
现在您可以使用和编译此代码了.我从控制台项目模板开始;这具有将控制台用作输出和跟踪窗口的优点,这使得调试引擎更加容易.首先,我创建一个(You are now ready to use and compile this code. I have started from a console project template; this gives the advantage that the console will be used as the output and trace window, which makes it easier to debug the engine. In the main, I create a) Game
目的.该对象包含用于设置,运行和结束游戏的功能.(object. This object contains the functionality to setup, run, and end the game.)
int _tmain(int argc, _TCHAR* argv[])
{
Game* pTheGame = Game::getInstance();
if(pTheGame)
{
pTheGame->setupGame();
pTheGame->createData();
pTheGame->runGame();
pTheGame->endGame();
}
return 0;
}
的(The) setupGame()
方法创建游戏窗口和游戏行为.游戏行为将照顾游戏逻辑.我把游戏逻辑放在(method creates the game window and the game acts. The game acts will take care of the game logic. I have put the game logic in an) Act
目的.这个(object. This) Act
对象移交给一个(object is handed over to a) Director
目的.和这个(object. And, this) Director
对象将允许您在行为之间进行切换.此游戏中有以下三种行为:(object will allow you to switch between acts. There are three acts in this game:) IntroAct
,(,) PlayAct
和(, and) CreditsAct
.简介将绘制星际迷航徽标,并显示游戏目标. Play将包含实际的游戏,而当游戏结束时将调用Credits,以向我们的胜利船长致敬或为有史以来最伟大的飞船的毁灭而哭泣.我们需要的最后一个对象是(. The Intro will draw a Star Trek logo and will show the goal of the game. The Play will contain the actual game, while the Credits will be called when the game is over, to show tribute to our victorious captain or to weep over the destruction of the greatest starship ever. The last object we need is an) InputManager
.该对象会将IrrLicht引擎返回的事件转换为我们希望收到通知的输入.在我们的情况下,这些将是(. This object will convert the events returned by the IrrLicht engine to inputs we like to be notified about. In our case, these will be) KeyPress
事件.(events.)
为了发送(In order to send the) KeyPress
对于行为,我本可以使用一个简单的回调函数,但是我喜欢C#的委托概念.在C ++中,这可以由Functor完成.的(events to the acts, I could have used a simple callback function, but I like the delegate concept of C#. In C++, this can be done by a Functor. The) 提升图书馆(boost library) 提供了几个类来执行此操作,但是我不想使用boost(至少在本文中不这样).因此,我创建了自己的硬编码(provides several classes to do this, but I didn’t want to use boost (at least not for this article). So, I created my own hardcoded)函子(Functor)这份工作.(for this job.)
struct FKeyPressed
{
virtual ~FKeyPressed() {};
virtual bool operator()(EKEY_CODE) = 0;
};
template class KeyPressed : public FKeyPressed
{
public:
typedef bool (ACTOR::*FunctionType)(EKEY_CODE);
public:
KeyPressed(ACTOR* pActor, FunctionType pFunctor)
{
m_pActor = pActor;
m_pFunctor = pFunctor;
}
virtual ~KeyPressed() {};
virtual bool operator()(EKEY_CODE keyCode)
{
return (m_pActor->*m_pFunctor)(keyCode);
}
protected:
ACTOR* m_pActor;
FunctionType m_pFunctor;
};
的(The) Act
想要接收的对象(object that would like to receive) KeyPress
事件仅需要提供以下签名的功能:(events just needs to provide a function of the following signature:)
bool OnKeyPressed(EKEY_CODE keyCode);
在功能上(In the function) runGame
,将渲染屏幕.对我们来说,这意味着(, the screens are rendered. For us, this means the) draw
主动功能(function of the active) Act
将被称为.我们要么将所有内容都绘制在这里,我将为(will be called. Either we draw everything here, which I will do for both the) IntroAct
和(and the) CreditsAct
,因为数量不多,或者我们加载了一些(, because it isn’t much, or we load some) IDrawable
物体进入(objects into the) Act
.(.)
我用过两种(I have used two types of) IDrawable
,那些仍然是静态的,以及那些更加动态的.静态可绘制对象的一个示例是(, those that remain rather static, and those that are more dynamic. An example of a static drawable is the) ShipDisplay
.此类在屏幕右侧显示飞船和游戏的状态.始终需要绘制此信息.动态可绘制对象的一个示例是(. This class shows the status of the ship and the game on the right side of the screen. This information always needs to be drawn. An example of a dynamic drawable is the) Torpedo
,它会绘制一段时间,然后将其从屏幕上删除.这种类型,我称之为(, which will be drawn for some period of time and will be removed from the screen afterwards. This type, that I have called an) Animator
,实现(, implements the) IAnimator
界面,扩展了(interface, which expands the) IDrawable
接口.一个例子是(interface. An example of this is the) Phaser
类.的(class. The) Animator
提供绘制它并控制生命周期的所有代码.所以(provides all the code to draw it and to control the lifecycle. So, the) Phaser
只需添加不同之处.(only needs to add what is different.)
void Phaser::updateInfo(Info& rInfo)
{
if(rInfo.Alpha >= 0)
{
rInfo.Alpha += rInfo.Fade;
}
if(rInfo.Alpha >= 255)
{
rInfo.Alpha = 255;
rInfo.Fade = - rInfo.Fade;
}
}
当生命周期(When the lifecycle of the) Phaser
结束,(ends, the) endAnimator
叫做.在这种情况下(is called. In the case of the) Phaser
,目标船只被击中.(, the targeted vessel is hit.)
void Phaser::endAnimator()
{
if (m_pVessel)
{
m_pVessel->hitPhaser(m_iEnergy);
}
}
最困难的部分之一是实现控制台界面.的(One of the most difficult parts was to implement the console interface. The) Console
类处理外观和输入.每当按下Enter或Escape键时,(class handles the looks and the input. Whenever the Enter or Escape key is pressed, the) CommandManager
被触发.该管理器存储游戏输入所在的状态.(is triggered. This manager stores the state where the input of the game is in.)
enum Mode
{
WaitForCommand,
NavigateWaitForCourse,
NavigateWaitForDistance,
LaunchWaitForEnergy,
LaunchWaitForHit,
LaunchWaitForCourse,
LaunchWaitForCoordinates,
TransferWaitForEnergy,
ComputerWaitForCommand,
WaitForAnimation
};
的(The) CommandManager
验证输入并采取适当的措施,例如,让(validates the input and takes the appropriate action, e.g., let the) Enterprise
物体将能量传递到防护罩.第三类是(object transfer energy to the shields. The third class is the) Controller
,此对象实际上创建了(, this object actually creates the) Torpedo
要么(or) Phaser
动画师并将其添加到(animators and adds them to the) PlayAct
.功能(. The function) runEnemyAI
检查是否需要运行以及该区域中是否有敌方船只.有三艘船:(checks if there is a need to run and whether there are enemy vessels in the sector or not. There are three vessels:) Enterprise
,(,) KlingonShip
和(, and) StarBase
,这些都实现了(, which all implement the) IVessel
接口.(interface.)
兴趣点(Points of Interest)
首先,对于使用IrrLicht之类的出色库来绘制简单的控制台外观,我深表歉意.但是,更改字符相当容易(First, I would like to apologize for using a great library like IrrLicht to just draw a simple console look. But, it is fairly easy to change the characters)()到企业的2D图像.或者,您甚至可以走得更远,并使其成为完整的3D.也应该很容易更改(to a 2D image of the Enterprise. Or, you could go even further and make it full 3D. It should also be easy to change the) Controller
和(and) CommandManager
类以使其成为实时的,而不是基于回合的.(classes to make it real-time instead of turn-based.)
参考文献(References)
- 吸引我撰写第一篇文章的文章:(The article that dragged me into writing my first article:) 星际迷航1971文字游戏(Star Trek 1971 Text Game) 迈克尔`伯肯(Michael Birken)(by Michael Birken)
- 迈克`梅菲尔德的原始代码(Mike Mayfield’s original code) 我从那里大胆复制了帮助.(from where I have boldly copied the help.)
历史(History)
- 27(27)日(th)2008年8月-本文的第一版(August, 2008 - First release of this article)
许可
本文以及所有相关的源代码和文件均已获得The Code Project Open License (CPOL)的许可。
VC7.0 VC7.1 VC8.0 C++ VC6 Dev 新闻 翻译