Chapter 2(1): Creating Your First Game-Pong

来源:互联网 发布:matlab2014a软件激活 编辑:程序博客网 时间:2024/05/16 01:59
 
Chapter 2: Creating Your First Game-Pong
Overview
This chapter talks about designing and creating a simple Pong game. Pong was the first video game ever and even before there were the first Pong versions in the sixties there was a version that could be played on an oscilloscope (Tennis for Two, 1958, by William A. Higinbotham). This shows how easy it is to implement a very basic version of Pong. A TV engineer named Ralph Baer claims that he had the idea of implementing Pong even before that in 1951, but not until 1966 was he able to produce the first prototypes. Atari licensed Pong in the eighties and even fought a court case with another company claiming they were the first to invent Pong. If you think about it today it sounds really crazy for such a simple game. You can read the whole Pong story at www.pong-story.com.
这一章我们将来讨论设计和创建一个简单的游戏——PongPong是第一个视频游戏,Pong的早起版本出现于六十年代,当时可以在示波器上玩(双人网球,1958年,由William A. Higinbotham制作)。基本版的Pong运行起来是如此的容易。一个叫Ralph Baer的电视工程师称他早在1951年前就有了运行Pong的想法,但是直到1966年他才生产出第一个原型机。Atari在八十年代【许可】了Pong并和另一家声称第一个发明了Pong的公司打了官司。
Implementing a very simple Pong clone doesn’t take much time, but you will also learn about the sprite classes of XNA in this chapter. You start by writing the concept of your game and go through the full design phase of game projects. In future projects you can make the same choices, and after a while you won’t have to think about the process of writing concepts first anymore because you will do it naturally to get the ideas for the first unit tests. Then you learn about an effective way to organize and use textures for your games. Additionally you will fine-tune the game, make it more fun, add 2-player support, and even test it on the Xbox 360 console.
要执行一个简单的Pong并不需要花费多少时间,但是你将在本章中学到XNAsprite类。你将由写出游戏的概念开始,然后发展成为一个完整的游戏项目的设计。【将来你可以同样的选择来进行项目,过一会儿你可以不必在意一开始就写出概念,因为你将很自然的得到第一个单元测试的方法。】接着如何有效的组织和为你的游戏使用纹理。再有一点,你会细心调整这个游戏,让他更有趣,支持双人模式,设置在Xbox360上进行测试。
Though this chapter focuses on the Pong game, it is not the only thing you are going to learn. The Pong game is used to learn more about the Agile Methodology I will mention later in this chapter. You will learn why it is important to write unit tests first and design the game up front in a very quick process and then improve it as you go along. In the next chapters you will use unit tests for additional classes too. For this game you just have one simple class and a couple of unit tests added at the end of it to test out the graphics, the collision testing, and to position everything correctly.
即使本章的重点在于Pong,但这并不是说这是你为你能学到的东西。Pong还经常被用于学习关于我要在本章后面提到的【敏捷开发Agile Methodology】。你将了解到为什么进行单元测试是这么重要,还有为什么可以非常快速的设计出一个游戏但是完善它却要花如此之久。在下一章里,你将会为一个附加类使用单元测试。在这个游戏里,你只有一个简单的类,在最后还会加入几个单元测试来测试图像、碰撞还有将所有的东西放对地方。
The kinds of unit tests used in this chapter are referred to as static unit tests as opposed to the dynamic unit tests you learn about in the next chapter. The difference is that you have to start static unit tests by hand and check the results yourself by watching the result on the screen. Dynamic unit tests, on the other hand, are executed automatically with help of a Unit Testing Framework like NUnit. For more details about the Unit Testing Framework, read Chapter 3.
本章使用的是静态的单元测试,不同于下一章使用的动态单元测试。不同点是你必须手动开始静态单元测试,自己检测屏幕上显示的结果。另一方面,动态单元测试将由像NUnit这样的单元测试框架来自动执行。更多的关于单元测试框架的知识详见第三章。
 
Game Ideas游戏创意
Talking about the game concept for a game like Pong seems to be a little ridiculous, but I will try to keep things as general as possible. The important thing is that you think about what the game should look and feel like before you start coding. The bigger the game project is, the more important the design phase is. I’m not saying that you can’t write games or applications without any concept at all. In fact, most beginners will just start writing something and then improve it again and again until it looks good. The problem with this approach is that it is highly unlikely to find the best solution on the first try.
也许考虑像Pong这样的小游戏的概念看起来似乎很滑稽,但是我会尽力保持将事物一般化看待。真正重要的是在你开始编码之前想想你的游戏应该是怎么样的感觉。越大型的游戏,设计阶段就越重要。我不是说没有任何概念就写不了游戏或程序,事实上,大多数初学者都回一开始就写代码,接着一遍又一遍的改进完善知道游戏看起来像个样。这种方法的问题就是不大可能从一开始就找到最佳的解决方案。
The game logic is very simple and it does not require much text or graphics (see Figure 2-1). This makes both the game code and your concept very simple to write. Just think about all the components required for this game (ball, paddles, and the screen borders) and write down your initial ideas.
这个游戏的逻辑非常简单,不需要很多的文字和图像。这使你的游戏代码和概念都非常易写。只用考虑这个游戏所需的组成部分(球、挡板、屏幕边界),然后写下你最先的想法。

Figure 2-1
Write Down Your Ideas!写下你的想法
Writing a concept does not necessarily mean you have to write down all your ideas, draw UML diagrams like crazy, and only start working when everything is fully planned. I’m completely against that approach because you can’t know how everything will work out. Additionally, beginners probably have no idea what the best way is to design a full game up front. Instead you can have a very clear picture of the game in your mind and after you think you have spent enough time on the design in your mind, you can start working.
写出概念并不是需要你写下你所有的想法,画出UML图看似有点疯狂了,当所有都计划好了才开始工作。我反对那种方法因为你不可能知道每一件事将会如何进行。还有,初学者可能不知道怎样在一开始就设计一个完整游戏的最好方法。但是你却可能在头脑中有一个关于游戏的清晰的画面,接着当你认为你已经花了足够的时间在脑中构思设计你的游戏,那么你可以开始工作了。
If you have other people working on your game project too, it becomes harder to explain ideas and keep everyone in sync. Just for this reason alone you should make it a habit to write down your game idea on just one single page. You can not only show this to other people and get more input, but you will also think about things while writing down some parts of your game idea - and when you see it on paper it might seem more complex than in your mind and you have to think about additional dependencies.
如果还有其他人参与到你的游戏项目中,解释清楚想法并保持每个人的思想相统一是件更困难的事。就因为这个原因,你应该养成只在一张纸上写下你游戏想法的习惯。你不能只把这个给别人看就能获得反馈,但是当你写下部分你游戏的构思时你会考虑很多,当你看着那张纸时它可能会比你想的更复杂,你还不得不考虑其他附加的部分。
For example, for your Pong game you know that you need two paddles and a ball, which moves between the paddles. But maybe only after you write down the initial ideas and think about the sprite textures might you think about the more detailed game play - how many lives does each player have, how do you find out if the ball hits the paddle edges, and how do you handle that? Does the speed of the paddle influence the ball speed and direction? What about increasing the ball speed after a while to speed up the game if both players are bored? Sure, many of these things can be improved after you finish the first version of your game. But it is a lot easier to take all these things into consideration before you write complicated code and then later see that you don’t even need that.
举个例子,你知道在你的Pong游戏中需要两个挡板和一个在挡板间移动的球。但是可能就在你写下最初的构想后,你会考虑更详细的游戏玩法——每一个玩家有几条命,你如何知道球碰到了挡板边沿,然后如何处理。挡板的速度会影响球的速度和方向吗?如果两位玩家感到厌倦了,过一段时间提升一下游戏速度怎么样呢?当然,很多这些东西可以在你完成游戏的第一个版本后进行改进。但是在你编写复杂的代码前考虑这些事会容易得多,然后看看你不需要什么。
As an example, I will write down the design concept for the Pong game you will develop in this chapter. You might want to take 5–10 pages for more complex games, but don’t write 100 pages of concept text without coding anything. It will take too much time and it will get very hard to manage the concept. For the Agile Methodology you will often update the concept and change details. I usually don’t start with UML diagrams until at least 50% of the code is done, and the overview diagrams and the documentation gets updated later when the project goes final.
作为一个例子,我会写下你在本章中要开发的Pong游戏的设计概念。则会花费很多时间,而且管理概念也会很困难。使用敏捷方法你会经常要更新你的概念和改变细节。我一般在至少50%的代码完成之前不会使用UML图的,概观图和文档在项目进入最后阶段才会更新。
Game Idea: Pong
The game is a simple Pong clone for one or two players. In the singleplayer mode the computer will control the other paddle. In the multiplayer mode, two players can either control their paddles with two gamepads, with different keys on the keyboard on the same PC, or on the Xbox 360 console.
这个简单的Pong克隆版游戏可以一到两个人来玩。在单人模式里,电脑将控制另一个挡板。在多人模式里,两个玩家可以在同一台PC或Xbox360上使用两个手柄或者键盘上的不同按键来控制挡板移动。
The game features a few 2D graphics for the ball and the paddles and a few sound files for the ball hitting one of the paddles or for losing a life. There is a very simple menu allowing you to select the following:
§ Singleplayer
§ Multiplayer
§ Exit
游戏使用了一些球和挡板的2D图像,还有一些用在球撞击挡板或失去一条命时使用的声音文件。
下面是一个简要的游戏菜单:
§ 单人模式
§ 双人模式
§ 退出游戏
 
The menu is implemented with a simple texture, the background is just a dark space, and most graphics are bright. You will try to make the game as much fun as possible.
这个菜单使用一个简单的纹理来实现,背景只是一个黑暗的宇宙空间,其他大多数图像是亮色的。你可以试着让游戏尽可能有趣。
Features and Game Play特性和玩法
The game has two screen modes: Menu and Game. The menu just contains the menu items that were mentioned in the preceding section, and the game consists basically of the ball and the two paddles and a simple scoring system. Take a look at a simple drawing for what you are trying to accomplish (see Figure 2-2).
游戏有两种屏幕模式:菜单和游戏。菜单包含我们之前提到的选项,游戏部分包括了球、挡板和简单的记分系统。看看你要完成的游戏的一个草图。

Figure 2-2
Technology技术
Obviously you are going to use XNA Game Studio Express; there are no additional libraries you are going to use and because you will just render some simple sprites, there are no 3D models or shaders involved here. The game should run on both the Windows platform and the Xbox 360 console.
很明显,你将要使用XNA GSE;你只要渲染啊几个简单的sprite,而不需要添加其他的库,这里既不需要3D模型也不需要着色器。游戏可以在Windows和Xbox360平台上运行。
As you can see I managed to fit everything on a single page, which is one of my rules I use when I write game concepts: First fit everything on one single page, then get a little bit into coding and if required by your team or an external partner (for example, if you want to show the concept to a game publisher), write a whitepaper with 5–10 pages from the initial idea and add some early sketches.
就像你看到的那样,我试图将每一样东西都写在单独的一页里,这是我写游戏概念时使用的一个规则:最先将每一样东西写在单独一页,然后将一些转换成代码,如果你的团队或其它合作者(例如你想将游戏概念展现给你的游戏出版商)需要的话,可以将最初的想法写成一份5~10页的白皮书并附上早期的草稿。
I never talked about the programming itself in the concept; I just made sure that you know which technology to use. Now it is time to think about the implementation. Don’t think about your abilities when writing the game concept, it will just limit you too much. Keep it in the back of your mind.
我从来不在概念里论及程序本身;我仅仅是确定你想使用什么技术。现在是时候考虑执行的问题了。当你写游戏概念是别考虑你的能力,否则则会对你造成许多局限。在你的脑子里要牢记这一条。
A more complete example of a game concept is the Rocket Commander concept (see Figure 2-3). You can check it out from the PDF file in the directory for this chapter. It contains four pages and a cover and it features all the ideas for the Rocket Commander game. As you can see from the cover, the game looks very different from the concept, but the general game ideas are there.
一个完整游戏概念的例子是Rocket Commander(火箭指挥官)。你可以在本章的文件目录里查看他的PDF文件。里面有1个封面和4页文档,描写了Rocket Commander游戏的构思。就像你看到的封面那样,游戏看起来和概念很不一样,但是这都是很普通的游戏构思。

Figure 2-3
Agile Methodology敏捷开发方法
The Agile Methodology is a conceptual framework for software development. The basic idea is to avoid big planning phases, which can often lead to risky and unrealistic project schedules that are hard to keep. For smaller projects you will use short time iterations anyway, but as projects grow bigger you might see yourself standing in front of problems that require months or even years to finish, and that is very hard to plan.
敏捷开发方法是软件开发中一个概念性的框架。它的基本思想是避免大型的规划阶段,否则会导致冒险的、不可实现的且难以保持的项目计划。对于小型一些的项目,你将使用较短的时间来进行反复,但是随着项目的变大,你会发现你遇到的是需要几个月甚者几年才能完成的问题,这是难以计划的。
Instead of planning everything down to the most detailed level, only a very rough concept is done. Each part of the concept is then iterated through the agile process of planning this feature in greater detail, designing the code with help of unit tests, then doing the actual code implementation, and finally testing and documenting this part. This iteration should not take longer than a few weeks and is repeated for all parts of the big project.
先做出一个简陋的概念就好,而不用把每一个细节都计划好。【概念的每一个部分接着通过敏捷过程的反复来变得更详细】,使用单元测试来设计代码,然后实际执行代码,并进行最终测试和为这一部分编制文档。这个反复的过程不要超过几个星期,并且大型项目中的所有部分都要如此重复。
Agile methods also include some other ideas about working better together, teaming up developers with the customers, testers, managers and designers, and so on. There are several rules that can be used to bring some structure into this agile framework to avoid having total chaos. Because of the shortened planning phase it looks like there is no detailed plan for the project, similar to a chaotic brute force coding approach. But in reality the planning process continues throughout the whole project and is much more useful than planning everything just at the beginning and having to live with all the mistakes made in that stage for the whole project.
敏捷方法同样包括一些其他能让工作更好进行的思想,将开发者同客户、测试者、经理和设计者等结合起来。有一些规则用于构建敏捷框架来避免混乱。因为缩短计划阶段让项目看起来没有一个详细的计划,就像使用蛮力进行编程。但是事实上这个计划过程始终贯穿真各个项目,这比在一开始就计划好一切有用得多。
I will not talk much about the Agile Methodologies in this book, but I will use unit testing and the short concept first, unit test design, then code iteration throughout all projects in this book. If you want to read more about unit testing I recommend reading the website of Martin Fowler at http://martinfowler.com.
我不会在书中讲述很多敏捷开发方法,但是我会使用单元测试和简短的概念,单元测试设计,然后反复编写代码在书中将贯穿整个项目。如果你想了解更多关于单元测试的内容,我推荐你阅读这个网站。
Martin has also written several books and I can recommend his Refactoring: Improving the Design of Existing Code book, which you can also find on the website. You can find many more links and information about the agile software development process on his site too.
Solving Initial Difficulties解决最初的困难
Ok, now you have an idea about your game, but you have not spent much time about where you get the graphics from, what you do about the sound files, and how to implement them. What about the problem with the ball hitting the sides of the paddle? Do you even need a simple physics engine for the ball?
OK,现在你有了游戏的构想,但是你却没有花足够的时间在从何处获得图像,声音文件怎么办,如何运行它们。当球碰撞挡板的边时会发生什么问题?你是否需要一个简单的物理引擎?
All these questions usually arise after the design phase and for more complex projects it can take weeks, if not months to just figure out some of the basic problems. For example, the first .NET 2.0 game I did was Rocket Commander and I had a nice idea to have thousands of asteroids on the screen, and millions in the level as a whole. I had some cool ideas about letting them collide and bounce off each other; it was not really clear how to implement it in an optimized manner. After some initial tests I found out that I couldn’t even render 100 asteroids without a significant performance drop. Instead of rewriting the game concept and making a really boring game without many asteroids at all (which is the game principle of Rocket Commander - without the many asteroids you don’t really have a game at all), I tried to solve this problem by rendering a lot of asteroids sorted by shaders and material settings, doing very early skipping of asteroids if they were not visible, and having the physics only apply to the nearby asteroids.
所有的问题都在设计后出现,对于一个更复杂的项目来说则会花费几个星期的时间,否则的话将会花费几个月的时间来解决基本问题。例如,我做的第一个.NET2.0的游戏是Rocket Commander,我有一个好主意让屏幕生出现上千个小行星。我有一些很酷的想法让它们相互碰撞并试探;没有真正清晰的方法能让他们以一个好的方法来执行。经过一些最初的测试后,我发现没有【significant performance drop】我甚至不能渲染100个小行星。我试着靠通过对着色和【材质】设置排序来渲染大量的小行星以解决问题,而不是重写我的游戏概念而使之成为没有任何小行星的无聊游戏(这是这个游戏的基础,没了小行星你根本就感觉不到这是一个游戏)。及早的跳过那些不可见的小行星不去处理,而且尽对附近的小行星应用物理效应。
Even after working and optimizing the asteroids for a week until they rendered at a great performance, the physics were still way too slow. Just updating 5 to 10 thousand asteroids in viewable range every single frame to see if any of them hit any other asteroid was just way too much, even with the best optimizations applied. I still wanted the asteroids to collide and behave correctly after collisions. If I did just check a certain amount of asteroids each frame, the algorithm often missed collisions and only caught up when both asteroids had already penetrated each other, causing even more troubles than removing the physics altogether. I was close to giving up because I had already spent 50% of the total project time just solving this single problem, but then I got the idea to separate the space into sectors. Each sector had a certain amount of asteroids and every time an asteroid left a sector it was removed and added to the new sector. For collision checks asteroids had only to check their own and all neighboring sectors, which still sounds like a lot of collision checks, but the sector logic did improve the physics performance by a factor of 100 and even more after more optimizations.
用了一个星期的时间来优化小行星的,并获得了不错的渲染效果,物理过程的运行依然缓慢。如果每一帧我都检验某个量的小行星,那么算法就会经常丢失碰撞或者会发生一个小行星进入到另一个小行星里,引起的麻烦比移除整个物理过程还多。当时我已经花了整个项目时间的一半就为了解决这一个问题,我快要放弃了,但是后来我有了一个想法,将空间分割成不同的扇形区域。每个区域都有一定量的小行星,每一次一个小行星从一个区域移除并添加到另一个新的区域。这样碰撞检验仅仅只需要检查它们自己的和邻近的区域,这听起来似乎还是要检查所有的碰撞,【但是经过优化后的区域逻辑大大改善了物理过程的表现。】
In most game projects I do nowadays I spend more than half of the time solving the initial problems and then dividing them up into smaller problems, which again have to be solved. The game itself is then later assembled by just putting these pieces together, and almost like magic the whole game is done in a matter of days. Though this is the best approach to finish a game as quickly as possible, it can be frustrating to see no results for a very long time, and in the past I always iterated the game until I was pleased with the results. This did take a very long time. Thanks to the agile development process, I’m now able to work on the problems and not iterate an almost endless loop of improvements.
到现在为止我所做的大多数游戏中,我都花了超过一半的时间来解决最初的问题,然后将它们分割成需要解决的更小的问题。接着将这些小问题集合起来,就像是魔术一样几天后整个游戏就做成了。这是尽快完成游戏的最佳方法,在过去我总是不断地反复游戏直到我对结果感到满意为止。这样做会花很长时间。由于使用了敏捷开发过程,我现在可以解决问题而不用再无休止的反复了。
What does this mean for your Pong game? Well, the game is very simple and you won’t spend a lot of time improving it 100 times. But say you just implement a basic version of Pong with a hard-coded paddle for the computer on the left side moving up and down depending on the ball position and controlling the right paddle. Then later after improving and testing the single-player game you might want to add 2-player support and it gets hard because you hard-coded the computer code. You might comment the computer code out or even remove it and restructure the game play code. Then a little bit later after testing the 2-player mode you might want to add the menu and again you have put the code at a different location, re-implement the computer game code, and so on.
这对Pong的开发意味着什么?这个游戏非常简单,你不需要花费大量的时间来改进。但比方说你只是运行一个基本版本的Pong,使用【硬编码/写死hard-code】的方法为左边的挡板编写代码,让其根据球的位置和右边挡板的控制情况来移动。接着当你改善和测试单人模式后你想加入双人的支持,这就会因你为电脑编写的是硬编码而变得困难。你可能想为电脑控制的代码写注释,或者移除它,接着重构游戏代码。当你测试双人模式后又想添加目录,然后你又将代码放到不同的位置,重运行电脑控制的那段代码,如此等等。
Though this is all good practice and forces you to refactor (refactoring means changing the layout of your code without changing the functionality to improve maintenance; see Martin Fowler’s book, Refactoring) it is a lot easier to just focus on one part of the game at a time and have several game versions and tests running side by side. You will do exactly that in the next part of this chapter, and hopefully you can grasp what I mean. Refactoring will occur more naturally and makes your code more usable and lets you see the result much quicker thanks to unit testing.
即使这是好的练习方式,并促使你重构,一个时间只关注一个部分是很容易的,并编写多个游戏版本,独立的测试。你将在本章的下一个部分恰到好处的做到这些,希望你能理解我的意思。重构的使用会变得更自然,让你的代码更可用,使用单元测试你能更快地看到结果。
One of the problems you will solve in the next part is how to handle the ball physics and how to detect which part of the paddle you hit.
你在下一章里要解决的一个内容是如何处理球的物理效果和如何侦测你碰到的是挡板的哪一部分。
Creating Some Textures创建纹理
Before you start coding you need some textures to display stuff on the screen. Even if you use dummy bitmaps here or get some graphics from somewhere else, it is still important to think about the final graphics, which dimensions the ball and paddles should have, and things like that.
在你开始编码之前你需要一些纹理来在屏幕上显示材质。即使你使用一张假的bmp图或从其他地方搞来的图像,考虑最终的图像仍然是重要的,标出球和挡板应有的尺寸还有诸如此类的事。
Again for your Pong game it is pretty simple, but more complex games might require an art concept, a lot of sketches and someone who has a good idea how to manage all this artwork and how to get them all done in time for the game programmer to implement them. Back in the early days of computer games almost all games were created by one individual, and though this is the easiest way, today no serious game is developed by just one person. Most good artists are not programmers and most programmers are not good artists. If you do a simple game it does not matter so much, but the bigger your project gets, the more time you will spend with finding teammates, skilled artists, and modelers and putting everything together.
你的Pong游戏是非常简单的,但是更复杂的游戏需要一个艺术性的概念、大量的草稿还有一个懂得如何管理这些东西并能为程序员及时地提供这些资源。几乎所有的早期电脑游戏都是有一个人来开发,即使这是最简单的方法,然而在当今没有哪个大型的游戏是由个人来开发的。大多数好的艺术家不是程序员,大多数程序员也不是艺术家。如果你只是做一个简单的游戏,就不需要考虑这么多,但是当你想做更大的项目的时候,你需要花更多的时间来寻找你的伙伴,有能力的人,做模型的人,将他们结合起来。
Take a look at the graphics for your game (see Figure 2-4). You will use three textures: (1) PongBackground.dds for the background, (2) PongMenu.png, which contains the logo, menu items, and all other texts for your game, and finally, (3) PongGame.png for the paddles and the ball.
看看你游戏需要的图像,有三个纹理文件(1)作为背景的PongBackground.dds(2)包含logo、菜单选项和其他游戏中需要的文字的PongMenu.png(3)用于表示挡板和球的PongGame.png

Figure 2-4
Additionally you will import two sound files (PongBallHit.wav and PongBallLost.wav) into your project and add a simple XACT project to play the sounds. To learn more about sounds and XACT, please read Chapter 9.
你还要导入两个声音文件(PongBallHit.wavPongBallLost.wav)到你的项目中,并添加一个简单的XACT项目来播放声音。想了解更多关于声音和XACT的只是请参见第九章。