使用SpriteLibrary开发角色扮演游戏(译文)
By robot-v1.0
本文链接 https://www.kyfws.com/games/using-spritelibrary-to-develop-a-role-playing-game-zh/
版权声明 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
- 23 分钟阅读 - 11050 个词 阅读量 0使用SpriteLibrary开发角色扮演游戏(译文)
原文地址:https://www.codeproject.com/Articles/1110409/Using-SpriteLibrary-to-develop-a-Role-Playing-Game
原文作者:BouncyTarget
译文由本站 robot-v1.0 翻译
前言
A sample Role Playing Game using SpriteLibrary to do the graphics
使用SpriteLibrary制作图形的角色扮演游戏示例
- 下载SpriteLibrary.zip-43.1 KB(Download SpriteLibrary.zip - 43.1 KB)
- 下载演示-1.2 MB(Download demo - 1.2 MB)
介绍(Introduction)
该代码是一个演示游戏,用(The code is a demo game, written with) SpriteLibrary
.本文试图解释如何使用(. This article is an attempt to explain how to design a game with) SpriteLibrary
,其中的代码显示了成品.该游戏易于修改,可让您绘制和填充自己的地图.(, with the code showing the finished product. The game is easy enough to modify, allowing you to draw and populate your own maps.)
背景(Background)
前阵子我做了(A while back I made the) SpriteLibrary
,但意识到人们可能需要更多示例来制作游戏.我希望发布其中的一些,希望对您有所帮助.背后的想法(, but realized that people will probably need a lot more in the way of examples for how to make a game. I hope to publish a few of these, which, I hope will help. The idea behind) SpriteLibrary
是为了简化简单游戏的图形部分.但是,(is to make the graphical portion of simple games a lot easier. But, the) SpriteLibrary
具有优点和缺点,本文将重点介绍其中的一些优点和缺点.(has strengths and weaknesses, some of which will be emphasized in this article.)
安装(Installation)
下载AdvDemo程序包和SpriteLibrary程序包后,您需要将它们解压缩并用C#进行编译.您将需要先构建SpriteLibrary,然后构建AdvDemo. AdvDemo可能需要您打开解决方案资源管理器,右键单击"资源",然后单击"添加资源".从那里您可以浏览到SpriteLibrary的构建位置.如果您只想下载预编译的游戏,则可以(After downloading the AdvDemo package and the SpriteLibrary package, you will need to unpack them and compile them in C#. You will need to build the SpriteLibrary first, and then the AdvDemo. AdvDemo may need you to open the Solution Explorer and right-click Resources and “Add a Resource.” From there you can browse to where SpriteLibrary was built. If you just want to download the pre-compiled game, you) 可以在这里找到(can find it here) . (免责声明:下载和安装随机人的程序是一件危险的事情.但是,嘿.我来自Internet.我必须是真实且友好的.如果可以的话,请使用源代码.这很好.养成习惯)(. (disclaimer: downloading and installing random people’s programs is a dangerous thing to do. But, hey. I am from the Internet. I must be truet-worthy and friendly. Use the source-code if you are able to. It is a good habit to form.))
使用SpriteLibrary设计RPG(Designing a RPG using SpriteLibrary)
此游戏有许多设计注意事项.我的出发点是我要使用(There were a number of design considerations for this game. My starting point was that I was going to use) SpriteLibrary
,我想做一些角色扮演游戏.我花了一些时间来决定是否要使其成为第一人称,第二人称或开销(我选择的).(, and I wanted to make some sort of Role Playing Game. I spent a little bit of time deciding if I wanted to make it first-person, second-person, or overhead (which I chose).)
第一人称/第三人称(First-Person / Third-person)
在这两种模式下,您到处跑动,然后才能看到游乐场的三维视图.(In these two modes, you run around and see a three-dimensional view of the playscape before you.) SpriteLibrary
,虽然可以执行某些操作,但裁剪效果最佳.如果您在其他子画面后面有子画面,则偶尔它们可以显示出来.如果您要寻找的宝藏一直在墙上可见,那确实是一个阻力.(, while it can do some of this OK, does not have the best clipping. If you have sprites behind other sprites, then occasionally they can show through. It is a real drag if the treasure you are trying to hunt for keeps being visible through the walls.)
第一人称比第三人称要容易一些.通常,我们前面只是挂着一把剑或武器,向我们展示了我们拥有的武器,而在第三人称视角中,您需要拥有所有冒险家的背面.(First person is a bit easier than third-person. We usually just have a sword or weapon hanging in front of us, showing us what weapon we have out, while in third-person you need to have the back-side of all your adventurers.)
我更像一个程序员,而不是一个图形设计师.最后,我花了很多时间在为该游戏绘制图形上,与在进行编程时一样.(I am more of a programmer than a graphics person. I ended up putting as much time into getting the graphics drawn for this game as I did into programming it.)
我之所以做出决定是因为(My decision was made because the) SpriteLibrary
非常容易在X/Y网格中移动精灵,并且对于3D而言还没有太多内置.我选择从上方看不起我们的冒险家.我还选择了没有光明/黑暗.它只是使编程变得简单得多.这应该是一个"简单"的演示,而不是一辈子的工作.(very easily moves sprites around in an X/Y grid, and does not have much built into it yet for 3D. I chose to look down on our adventurer from above. I also chose not to have light / darkness. It just makes things much simpler to program. This is supposed to be a “simple” demo, not a work of a lifetime.)
屏幕布局(The Screen Layout)
下一个主要的设计考虑因素是如何显示我们的聚会状态,敌人等.我选择在地图旁边放置一个窗格,该窗格显示我们的聚会,我们的健康状况等等.当我们面对敌人时,我们会在同一窗格中看到他们.而且,当我们去商店时,我们还会在该窗格中看到可以购买的商品.(The next main design consideration was how to show our party status, enemies, and the like. I chose to have a pane off to the side of the map, which shows our party, how much health we have, and the like. When we face enemies, we see them in the same pane. And, when we go to a store, we see the items we can purchase in that pane also.)
原因很简单.的(The reason for this is fairly simple. The) SpriteLibrary
对个人有效(works on individual) PictureBoxes
.对于每个(. For each) PictureBox
在游戏中,我们需要加载并初始化将在该窗格中使用的所有图形.我们可以这样做,以便在第一次需要该图像时单独加载它们.但这将比我现在想要的要多一些基础架构.因此,我拥有了所有敌人的特写镜头和所有财物(in the game, we need to load and initialize all the graphics which will be used on that pane. We could have done it such that we load them individually, when that image is first needed. But that would take a bit more infrastructure than I wanted to make at this time. So, I have it so all the close-ups of the enemies and all the possessions all show up on the one) PictureBox
.游戏加载后,它会弹出一个窗口,告诉您正在准备游戏.在这段时间内,它正在做的是准备好精灵.读取图像并进行处理. Sprite控制器的执行速度相当慢,但是一旦完成,它对图像的效率就很高.(. When the game loads, it does pop up a window telling you it is getting the game ready. What it is doing during that time is getting the sprites ready; reading in the images and processing them. The sprite controller is fairly slow in doing this, but once it is done, it is pretty efficient with the images.)
介面(The interface)
我用(I use the) SpriteController
(的一部分((part of the) SpriteLibrary
)观看按键.我从表单中获取鼠标移动,然后将其传递给() to watch for key presses. I get mouse-movement from the form, and I pass it on to the) SpriteController
当我在屏幕上拖动精灵时.这更多是因为我想展示如何进行精灵拖动,而不是因为这是最好的方式.(when I am dragging sprites around on the screen. This is more because I want to show how to do the sprite dragging than because it is the best way to do it.)
代码.(The code.)
派对设置(Party Setup)
我想在您的聚会中有一些不同的选择.一旦您有足够的钱可以雇用所有人.但是你只能从两个人开始.所以我做了一个(I wanted to have a few different choices in your party. You can hire everyone eventually, once you have enough money to do so. But you can only start with two people. So I made one) PictureBox
,并做了一个(, and made a) SpriteController
管理那个盒子里的精灵.我在框的中间有一条线,您可以将冒险者精灵拖到"选定"区域.当我们有两个冒险者准备玩时,您可以玩游戏.(to manage the sprites in that box. I have a line down the middle of the box, and you can drag adventurer sprites into the “selected” area. When we have two adventurers ready to play, you can play the game.)
由于角色扮演游戏会鼓励您更加贴近自己的数字自我,因此我也允许您更改玩家的姓名.因此,在玩游戏时,请确保在" Party-Setup"窗口和" Party-Setup"窗口之间来回传递党员.(Because Role-Playing-Games encourage you to grow closer to your digital selves, I also allow you to change the names of the players. Because of this, when we play the game, I make sure I pass the party members back and forth between the Party-Setup window and the) AdDemoForm
(玩游戏的地方).((where the game is played).)
AdvDemoForm(AdvDemoForm)
这是玩游戏核心的地方.一切都在进行(This is where the heart of the game is being played. Everything running on) SpriteLibrary
用"勾号"使事情发生.在SpriteLibrary页面上对此进行了更深入的说明,但是我还将在此处进行描述,主要是为了说明事情的工作原理.(uses a “tick” to make things happen. This is explained in some depth on the SpriteLibrary page, but I will describe some of it here too, mainly to explain how things work.)
DoTick功能(The DoTick function)
的(The) SpriteLibrary
有一个计时器"滴答",它很快就消失了.它每秒大约发生100次.每次发生此滴答声时,"(has a timer “tick” that goes off very rapidly. It happens about 100 times a second. Each time this tick happens, the “) DoTick
功能触发. (在程序中设置,位于AdvDemoForm.cs文件的151行附近).(” function fires off. (That is set in the program, around line 151 of the AdvDemoForm.cs file) We want the) DoTick
功能完成相对较快,因此它不应太复杂.我们使用CurrentMode枚举来跟踪游戏的期望值,因此我们知道如何处理事情.(function to complete relatively fast, so it should not be too complex. We use the CurrentMode enum to keep track of what the game is expecting, so we know how to handle things.)
如果您阅读(If you read the) DoTick
代码,您会发现我们应该立即退出该函数.例如,我们检查地图上是否有任何精灵从a点移到b点,然后退出函数.当我们告诉冒险者上下,左右移动时,我们告诉组成运动场的每个精灵在地图上四处移动(使用(code, you will see that we exit the function immediately if we should do so. For example, we check to see if any of the sprites on the map are in the process of moving from point a to point b and exit the function if that is the case. When we tell our adventurer to move up, down, left, or right, we tell each of the sprites that make up the playing-field to move around on the map (using the) Sprite.MoveTo
功能).在到达下一个位置之前,我们不希望接受新的说明,因此我们只需跳出(function). We do not want to accept new instructions until we have arrived at the next location, so we simply jump out of the) DoTick
如果我们在等待(if we are waiting on the) Sprites
.(.)
如果没有一个精灵在移动,但是代码知道我们刚刚在移动((If none of the sprites are moving, but the code knows we had just been moving () IsMoving
=true),我们才刚刚进入我们的新领域.我们设置一个布尔值((= true), we have just arrived into our new space. We set a Boolean value () isMoving
=false)表示我们不再移动,然后花一些时间来处理刚进入的空间.如果我们停了下来,而且空间上有一个坏人,那么我们就要战斗了.如果是一扇门,我们将移至该位置,如果是一家商店,则将对其进行处理.您会发现游戏中的大多数内容(生命,死亡,战斗,购物)都发生在(=false) to say that we are no longer moving, and then we spend some time processing the space we just landed on. If we stopped, and the space has a bad-guy on it, we set up to fight. If it is a door, we move to that location, and if it is a store, we process that. You will find that most everything in the game (life, death, fighting, shopping) all happens from the) DoTick
功能.滴答是生命的命脉(function. The Tick is the life-blood of the) SpriteLibrary
,并且使用Tick是使用它对程序进行编程的最佳方法.您可以使用表单事件(单击表单按钮)进行一些编程,但是许多您希望发生的事情并没有按照您希望的方式发生.(, and using a Tick is the best way to program things using it. You can do some programming using form events (form button-clicks), but a lot of things you would expect to happen do not happen the way you would like.)
例如:如果您单击按钮并告诉(For example: If you click on a button and tell a) Sprite
要移动,精灵要等到(to move, the sprite does not move until after the) Click
功能已完成.所有功能都使用相同的"线程",并且在Sprite事件发生之前需要完成form事件.有人尝试告诉精灵先做某事然后再做一个(function has completed. All the functions use the same “thread”, and the form events need to complete before the Sprite events can happen. It is very common for someone to try to tell a sprite to do something and then do a) Thread.Pause
等待精灵来做.但是Pause暂停了Sprite代码的运行,因为它暂停了整个线程(Sprite和所有线程).如果您使用Tick和short函数,则该函数会触发很多次,并在其中之间留出大量时间供Sprite执行其操作.(to wait for the sprite to do it. But the Pause keeps the sprite code from running, as it pauses the entire thread (Sprite and all). If you use the Tick, and a short function, then the function fires off lots of times, and leaves a lot of time in-between for the Sprites to do their thing.)
CheckKeypress(CheckKeypress)
在里面(In the) CheckKeypress
功能,我们处理大多数用户输入.那是我们寻找上,下,左,右移动的地方.您可以在任何给定时间按下许多键.所以(function, we process most of the user input. That is where we look for moving up, down, left, and right. You can have many keys pressed at any given time. So the) SpriteController
通常,通过询问是否按下了特定的键,它最容易使用.该函数询问是否按下向上键或W键,如果按下,则设置一个布尔值,表示我们要向上移动.稍后,我们检查以确保不会同时上下波动.如果我们朝着两个相互矛盾的方向前进,那么我们什么也不会走.(is usually easiest to use by asking it if a particular key is pressed. The function asks if either the Up, or the W keys are pressed, and if so, it sets a Boolean saying that we are to go Up. Later on, we check to make sure we are not set to go both up and down. If we are going in two conflicting directions, we do not go anywhere.)
其余功能处理按键.如果我们在商店中,我们可以做些事情.如果遇到,我们就无法朝自己的方向前进,我们可以战斗,奔跑或进行治疗.因此,该函数中包含一些逻辑.(The rest of the function processes the keypress. If we are in a store, there are things we can do. If we are in an encounter, we cannot move any direction we please, we can either fight, run, or do a healing-potion. So there is a little bit of logic in the function.)
空战(DoFight)
DoFight
是进行战斗的功能.滚动游戏最终要依靠一些关键要素(主要是战斗)来使其发挥作用.这有一个非常简单的战斗算法.可能比任何有头脑的人制作RPG都要简单得多.基本上,双方都想出可以造成多少伤害,然后对所选目标进行伤害.如果该目标死亡,则伤害会作用于排队的下一个生物.因此,两支球队先造成伤害,然后受到伤害.这样就有可能让两支球队互相残杀.我们真的不在乎坏人是死还是活.如果玩家的队伍已经死亡,那么他们已经死亡并且比赛结束了.(is the function that does a battle. The Roll-Playing Games end up relying on a few key pieces, mostly fighting, to make it work. This has a very simple fighting algorithm; probably much simpler than anyone in their right mind who is making an RPG would make it. Basically, both sides figure out how much damage they can do, and then they do it to the chosen target. If that target dies, the damage gets applied to the next creature in line. So both teams do damage first, then take damage. It is possible, then, to have both teams kill each-other. We do not really care if the bad guys are dead or alive. If the player’s team is dead, they are dead and the game is over.)
我们使用随机数生成器.的(We use a Random Number Generator. The) SpriteController
有一个实例化时创建的.您可以创建自己的随机数生成器,但是如果您在整个游戏中不使用相同的字样,那么随机数就不会太随机.每个玩家都对自己的敏捷性"滚动"以查看是否击中,如果击中,则他们针对自己的武器损害进行滚动以查看其造成的损害.产生的损坏将添加到潜在损坏列表中.导弹武器每回合两次命中,这确实使它们成为了强大的武器.但是,弓箭手型玩家并不像混战型玩家那样强悍.近战玩家受到的伤害减少,仅是因为他们更强悍.(has one that it creates when it is instantiated. You can create your own Random Number Generator, but if you do not use the same oen throughout the game, the random numbers turn out not to be too random. Each player “rolls” against their dexterity to see if they hit, and if they do, then they roll against the damage of their weapon to see how much damage they do. The resulting damage is added to the list of potential damage. Missile weapons get to hit twice a turn, which makes them formidable weapons indeed. But, the archer-type players are not as tough as the melee players. Melee players take a reduced amount of damage, simply because they are tougher.)
护甲每回合吸收一定数量的伤害.如果您有板甲,那么它每回合吸收20次击中.如果对方的力量转身造成25点累积伤害,则玩家受到5点伤害.(Armor absorbs an amount of damage a turn. If you have plate armor, then it absorbs 20 hits a turn. If the opposing force does 25 cumulative damage that turn, then the player takes 5 damage.)
精灵(Sprites)
在制作这款游戏时,我最终制作了很多精灵.我们每个要战斗的坏人都有一个.我有很多简单的精灵,有些则更复杂.我以为我会在这里简要讨论如何制作这些精灵.(In making this game, I ended up making a lot of sprites. I have one for each bad guy we end up fighting. I have a number of simple sprites, and some that are more complex. I thought I would briefly discuss how I made those sprites here.)
做一个战士(Making A Warrior)
我不是艺术家,所以我从很久以前制作的另一款游戏中偷了大部分图像.所有这些图像的尺寸均为200x200,并且是单帧图像,而不是动画.因此,我需要做的是使它们稍微移动一些,以使它们比起静止帧图像更像动画.(I am not an artist, so I stole most of my images from another game I had made a long time ago. All of those images were 200x200 in size, and were single frame images, not animations. So, what I needed to do was make them move around a little bit to make them feel a bit more like animations than still-frame images.)
我用(I use the)GIMP(GIMP),这是一种完美的免费开源软件包.第一步是制作一个网格,所以我知道将图像放置在哪里.的(, a free and open-source package that is perfect for this sort of thing. The first step was to make a grid, so I knew where to put my images. The) SpriteController
,当它使(, when it makes a) Sprite
,读入(, reads in the)
网格的内容,一个图像在另一个图像上.最好具有透明的背景,以便您可以查看其背后的内容.对于本游戏而言,没有太大关系,因为我们只有灰色背景.但是,对于其他游戏,这很重要.(contents of a grid, one image after the other. It is best to have a transparent background, so that you can see whatever is behind it. For this game, it does not matter too much, since we only have a grey background. But, for other games, it will matter.)
然后我粘贴一张图片并调整其大小.对于这个游戏,我将它们设为100x100.那是很小的,但是无论如何他们很少变得那么大.大多数情况下,它们在屏幕上保持很小.如果将它们设置得太大,则SpriteController会停顿下来尝试打印它们.如果太小(Then I paste in the one picture and resize it. For this game, I made them 100x100. That is fairly small, but they rarely get that big anyway. Most of the time they are kept pretty small on the screen. If you make them too big, the SpriteController will bog down trying to print them. If you make them too small,)
他们看上去都很粒状,质量很差.您需要为您的游戏找出最佳分辨率.(they look all grainy and poor quality. You need to figure out for your game what the best resolution is to work with.)
我复制了我的图像,所以我有想要的帧数.对于这个,我只有几个.然后,我想出了我想要的运动.我主要只是使她的头和剑移动.的(I duplicated my image so I had as many frames as I wanted. For this one, I had just a few of them. Then, I figured out what movement I wanted from it. I mainly just made her head and sword move. The)GIMP(GIMP)为此有三个出色的工具.选择工具,旋转工具和移动工具.我们使用选择工具圈出要移动的区域.然后,我们按ctrl-x和ctrl-y.复制并粘贴.然后,在粘贴但未"锚定"(放回图像)的同时,我们可以对其进行一些处理.我们可以使用移动工具将其稍微移动一点,但是我通常喜欢先旋转它,然后再将其移动到所需位置.(has three great tools for this. The selection tool, the rotation tool, and the movement tool. We circle the area we want to move with the selection tool. Then, we press ctrl-x and ctrl-y. That copies it and pastes it. Then, while it is pasted but not “anchored” (put back on the image), we can process it a bit. We can move it a little with the movement tool, but I usually like to rotate it first, then move it to line up where I want it.)
最后,将其"锚定"回原处,将其粘贴到您打开的任何当前层中.完成后,我需要做一点着色来填充剪切和粘贴的地方,但是并不需要太多的动作.(Finally, you “anchor” it back in place, which pasts it into whatever current layer you have open. When it is done, I need to do a little coloring to fill in where things were cut and pasted, but it does not take too much to get a little bit of movement.)
关于旋转工具,要了解的一件好事是,它允许您更改要旋转的项目的中心.如果我剪断了一条手臂,则使中心成为手臂旋转的位置,无论是肩膀还是肘部.通常,这意味着当我将其放回原位时,不需要使用过多的移动工具,而且它可以让我更好地预览完成后的外观.(One nice thing to know about the rotation tool, is that it allows you to change the center of the item you are going to rotate. If I have cut an arm out, I make the center be the place where the arm would rotate from, either the shoulder or the elbow. That usually means I do not need to use the movement tool as much when I am putting it back in position, as well as it gives me a better preview of what it looks like when I am done.)
精灵运动的目的是您需要了解精灵要执行的操作,无论是走路,抽动还是其他.然后您想要有几帧可以执行此操作.您可以使Sprite快或慢地进行动画处理,具体取决于Sprite应该执行的操作以及必须执行多少帧操作.您可以使它相当平稳地移动,但是绘制每一帧都需要花费大量时间,并且需要更多处理能力.(The object of the sprite movement is that you need to have an idea of what you want the sprite to be doing, whether walking, twitching, or whatnot. And then you want to have a few frames to do that in. You can make your sprites animate fast, or slow, depending on what the sprite should be doing and how many frames you have to do it in. With a lot of frames, you can get it to move fairly smoothly, but it takes a lot of time to draw every frame, as well as it takes more processing power.)
做龙(Making A Dragon)
现在,我们已经制作了一个简单的三帧动画,让我们看一个更复杂的动画.龙.当我设计这个RPG时,我想到的第一个想法是:“酷!我要制造一条喷火龙!“龙真棒.我希望它看起来很棒.因此,我希望它是一个比其他精灵更加复杂的精灵.(Now that we have made a simple animation of three frames, let’s look at a more complex one; the dragon. When I designed this RPG, the first though that went through my mind was, “Cool! I get to make a fire-breathing dragon!” Dragons are awesome. I wanted it to look awesome. And as such, I wanted it to be a much more complex sprite than my other ones.)
我所有其他生物都有一个动画.他们摇摇头,踩着剑,挥动斧头.但这就是他们一遍又一遍的事情.我希望我的龙与众不同.所以我给了他们每个人两个动画.他们大部分时间都会进行正常运动,但是每隔一段时间,他们就会分支到第二个动画中.而且,每隔一段时间,他们还会呼吸.(All my other critters have one animation. They waggle their head, they stomp their sword, they swing their axe. But that is all they do, over and over. I wanted my dragon to be different. So I gave every one of them two animations. They will do their normal movement most of the time, but every so often they will branch out into their second animation. And, every so often, they also breathe fire.)
我制作动画的方式与处理其他生物的方式相同.我从一个图像开始(这条龙作为彩图图像开始生活),我切开一条腿并旋转,我割下他的头并旋转,或者我切掉他的脖子并旋转整个头.对于其中一个,我将龙的前半部分切除并旋转了一下,使它看起来像是他的前脚从地面上lung了下来…不太复杂,但有效.(I make the animation the same way as I did with my other critters. I start with an image (this dragon started life as a coloring-book image), and I cut out a leg and rotate it, I cut off his head and rotate it, or I cut off his neck and rotate the whole head. For one of them, I cut the front-part of the dragon away and rotated it, making it look like he is lunging his front feet off the ground… Not too complex, but effective.)
但是幕后发生的事情是,我告诉每个雪碧动画一次.然后,动画制作完成后,我有一个事件((But what is happening behind the scenes, is that I am telling each Sprite to animate once. Then, when the animation is complete, I have an event () PartyClass.SpriteAnimationEnd
)触发.此函数检查小精灵有多少动画.如果只有一个,它将立即告诉精灵再次执行该动画.但是,如果它具有多个动画,它将随机选择要使用的动画,从而偏爱第一个动画.() that fires off. This function checks to see how many animations the sprite has. If it has just one, it immediately tells the sprite to do that animation again. But, if it has more than one animation, it randomly chooses which animation to use, favoring the first animation.)
而且,同一事件((And, that same event () PartyClass.SpriteAnimationEnd
)检查我们是否是一条龙.如果是这样,我们还选择一个随机数,然后选择是否进行灭火.火(再次,您可以告诉我我不是艺术家)是暂时添加的第二个精灵.当龙在呼吸中死亡时,您会看到一点点.当火球继续射出时,他变成了墓碑.那是我可以很容易地从那里编程的一个小细节,但是我主要是强调火是第二个精灵.我可以很容易地将木乃伊(那是易燃的东西)变成可呼吸的野兽.既然我有了呼吸呼吸的精灵,我所要做的就是决定应该呼吸的东西并使精灵动画.() checks to see if we are a dragon. If so, we also choose a random number and choose whether or not to breathe fire. The fire (and again, you can tell I am not an artist) is a second sprite that gets added temporarily. You can see this a little bit when the dragon dies mid-breath. He turns into a tombstone while the ball of fire continues to shoot out. That was a small detail that I could have easily programmed out of there, but I left it mainly to emphasize that the fire is a second sprite. I could easily turn a mummy (flammable thing that it is) into a fire-breathing beast. Now that I have my fire-breathing sprite, all I need to do is decide what should breathe fire and make the sprite animate.)
为了使火灾顺利进行,还需要做一些额外的工作.火需要从他的嘴里出来,而不是从他的眼睛,耳朵或肚脐上出来.我有几种不同的龙,它们的头在不同的位置.因此,我需要检查我拥有的那条龙,并为每条龙选择不同的射击起始位置.所有这些代码都可以在(There was a little bit of extra work that needed to be done to make the fire work nicely. The fire needs to come out of his mouth, not his eyes, ears, or belly-button. I have a few different dragons, and their heads are in different locations. So I needed to check which dragon I had, and choose a different fire starting position for each one. All that code can be seen in the) PartyClass.SpriteAnimationEnd
功能.(function.)
您将看到的最后一件事是,当火焰完成动画时,精灵将被销毁.我们没有一遍又一遍地重复火焰,它只发生一次,然后我们等待他再次呼吸,直到火焰熄灭.因此,我们可以按需制作火精灵.(The final thing you will see is that, when the flame finishes its animation, that the sprite gets destroyed. We do not have the flame repeating over and over, it happens once, and then we wait for him to breathe again before it comes out. So we make the fire sprite on demand.)
我想说的最后一件事是,您可以单击一个敌人来瞄准他.敌人扩大了,他们是您团队的目标敌人.当您想先杀死一个更危险的敌人时,这很方便.但是,对于龙来说有点奇怪.当您单击龙中呼吸时,我需要找到相应的火精灵,并将其放大(以及将其移动到嘴巴的位置,因为当整个图像放大时嘴巴会改变位置.)(I guess one last thing to mention, is that you can click on an enemy to target him. The enemy is enlarged, and they are the enemy your team targets. This is handy when you want to kill a more dangerous enemy first. But, it is a little odd for dragons. When you click on a dragon mid-breath, I needed to find the corresponding fire-sprite, and enlarge that (as well as moving it to where the mouth is, since the mouth changes location when the whole image is enlarged.))
修改游戏(Modifying the game)
CodeProject的好处是您可以获取代码并重新使用它.该游戏是功能齐全的游戏,但时间不长.我有关于世界上最糟糕的故事情节.你一直战斗直到杀死主要的龙.如果有人愿意,他们可以从中制作更长,更有趣的游戏.您可能需要在某些方面进行操作.(The nice thing about CodeProject is that you can take code and re-use it. This game is a fully functional game, but it is not very long. I have about the world’s wimpiest storyline. You go until you fight and kill the main dragon. If someone wants to, they can make a much longer and more interesting game from this. There are a few areas you may want to work on to do so.)
变更地图(Changing the map)
映射文件位于资源目录中,(The map file is in the resources directory, the) AdvDemoMap.advx
文件.在该文件中,有很好的说明来扩展或创建自己的地图.映射文件为XML,但使用起来并不复杂.如果您发现错误,游戏将为您提供相当完整的错误消息.您可以将该地图复制到桌面或其他位置,然后从中创建自己的地图.如果其他人的计算机上安装了AdvDemo,则他们可以打开您的地图文件并进行冒险.(file. Inside that file are fairly good instructions for expanding, or creating your own map. The map file is in XML, but is not too complex to work with. If you get something wrong, the game will give you a fairly complete error message. You can copy that map to your desktop or somewhere else and create your own from it. If someone else has AdvDemo installed on their computer, they can open your map-file and play your adventure.)
主地图是通过 标记构建的.它们看起来像:(The main map is built through the tags. They look something like:)
<Name>Town of Nod</Name>
<Line>wwwwww?wwwwwww</Line>
<Line>w h t t htw</Line>
<Line>w tt h w</Line>
<Line>wPh?t S w</Line>
<Line>w t h w</Line>
<Line>w h h h w</Line>
<Line>wwwwwwwwwwwwww</Line>
每个W是墙,H是房屋,S是商店. ?是一个标记,它提醒我们稍后在该空间上做一些事情(我们需要手动将事物放在?之上;?会被忽略.)(Where every W is a wall, the H are houses, and the S is a store. The ? is a marker that reminds us to make something on that space later on (we need to manually put things on top of the ?; the ? is simply ignored.))
更换武器(Changing the weapons)
您可以在其中更改武器的价值或损坏(You can change the value of, or damage of weapons in the) ItemClass.cs
文件.(file.)
添加武器有点棘手.您不仅需要为该物品创建一个精灵,而且还需要在一些地方对新武器进行硬编码.(Adding weapons is a bit trickier. Not only do you need to create a sprite for the item, but you need to hard-code the new weapon in a few places.)
对于每个精灵,您都需要将其加载到(For every sprite, you need to load it into the) AdvDemoForm.cs
文件在(file in the) LoadMultipurposeSprites
功能.的(function. The) LoadPlayingFieldSprites
该功能适用于地形(树木,商店等).(function is for terrain (trees, stores, etc).)
您需要在(You need to create an entry in the) PossessionName
枚举(enum in the) AdvDemoForm.cs
文件.(file.)
public enum PossessionName { potion_small, potion_large, armor_leather, armor_chain, armor_plate,
spear, club, scimitar, sword, dagger, battleaxe, crossbow, longbow, throwingstar,
sling, newWeaponName
}
您还需要在同一文件的SpriteName枚举中为该精灵创建一个条目.(You also need to make an entry for the sprite, in the SpriteName enum in the same file.)
public enum SpriteName { wall, walldoordown, walldoorleft, tree_1, tree_2, tree_3, tree_4,
cavewall, cavedoordown, cavedoorleft, NewWeaponSpriteName
然后,在项目类中,您需要输入一个新条目:(Then, in the item class, you need to make a new entry:)
case PossessionName.newWeaponName:
Name = "Lightsaber";
WeaponDamage = 50;
Description = "A glowing saber of death";
Value = 7500;
WhatType = PossessionType.melee_weapon;
break;
该武器将自动出现在商店中.目前,获得武器或装甲的唯一方法是购买武器或装甲. (或者在游戏开始时装备它们.您可以通过更改(The weapon will automatically appear in the store. At the moment, the only way to get weapons or armor, is by buying them. (or, equipping them at the start of the game. You can do this by changing the) CreatureClass
的实例化(instantiation of the) player_knight1
或其他(or other) player_*
生物.)(creatures.))
添加生物(Adding creatures)
您可以使用预先存在的精灵添加生物,也可以添加更多精灵.(You can use pre-existing sprites to add creatures, or you can add more sprites.)
首先,将其添加到(First, add it to the) SpriteNames
枚举(enum on the) AdvDemoForm.cs
文件.创建Sprite图片并将其添加到资源中之后,请确保还使用(file. After creating a sprite image and adding it to the resources, make sure you also load it with the) LoadMultipurposeSprites
功能.现在,您需要在列表中创建一个生物枚举(function. Now, you need to make a creature enum, also in the) AdvDemoForm.cs
文件,最后,向其中添加一点(file, and finally, add a small bit to the) CreatureClass
实例化功能:(instantiation function:)
case CreatureName.NewCreature:
SpriteImage = SpriteName.NewSpriteName;
size = .5; //Size in feet. 6.1 is just over 6 feet tall
strength = 1; //How tough this creature is
dexterity = 3; //How well it hits (out of 10)
intelligence = 1; //How smart it is. Smarter creatures are harder to run away from.
CreatureWepDamage = 5; //How much damage it is capable of doing
Name = "A ghastly tree elf.";
break;
结论(Conclusion)
我希望您能找到(I do hope that you find the) SpriteLibrary
有助于制作有趣的游戏.再次,(helpful for making fun games. Again,) SpriteLibrary
将使简单的游戏变得简单.但是,如果您真的想制作硬核游戏,则需要使用其他一些图形系统.(will make simple games simple. But, if you want to really get into making hard-core games, you will need to use some of the other graphical systems.)
历史(History)
- 2016年8月4日-修复了一些小错误,并增加了播放自己制作的游戏文件(.rpgx)或有人通过电子邮件向您发送文件的功能.(Aug 4 2016 - Minor bug fixes, and added the ability to play a game file (.rpgx) file that you are making yourself, or that someone has emailed you.)
- 2016年7月4日-创建第一个版本(July 4 2016 - Created first version)
许可
本文以及所有相关的源代码和文件均已获得The Code Project Open License (CPOL)的许可。
C# .NET VS2013 sprites 新闻 翻译