Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 30 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
30
Dung lượng
1,06 MB
Nội dung
CHAPTER 3 ■ PLANNING YOUR GAME 47 We have some very rough mockups of a hero and some combat. Let’s round this out with a level mockup. We inadvertently created a protagonist who looks just made for a zombie-smashing epic. This means that zombies are bound to be the antagonists, and high-octane wrench-and-revolver smashing will become the game play. The setting, keeping in line with a game that is just making itself at this point, will have to be a cemetery, as shown in Figure 3-6. Figure 3-6. Concept art: maps There we have it! We think we’ve pretty much nailed the look and feel of this game with minimal effort. We haven’t gotten into power-ups, enemy design, specific maps, health, death and dying, or any of that fun stuff, but we’ve made tremendous headway. The details will fall into place eventually. Tool Planning So far, we’ve made some basic decisions about how the game will look and feel, but in order to get one step closer to actually building the game, we need to broach the concept of tools. Tools will help us be more efficient at developing new level and character designs, and implanting them into the game without the need to change source code. Creating tools can be essential in the later stages of a game’s development cycle, since they allow you to focus on what really matters: the drooling, brain-eating, out-to-get-you zombies! The next couple of chapters will be specifically on creating the tools we’ll be using, and even beyond that, we’ll be tweaking them as new needs arise. In the meantime, we’ll need to be pretty clear on the data formats for the two areas where we’ll be creating all of the content: characters and maps. 48 CHAPTER 3 ■ PLANNING YOUR GAME Map Editor Because we are building a tool, we can go back to a more event-based model, where the appli- cation waits for the user to do something before proceeding. Since we are designing a tool that can handle the generation of maps, it makes sense to model it after a jigsaw puzzle. Much like with a jigsaw puzzle, we’ll drag pieces from a bin area to the map area, fitting them in just where they need to be. In the mockup of the map editor, shown in Figure 3-7, you can see the map, minus the bounding boxes, as it should be rendered on the left side, and the map segment palette on the right side. The map is composed of map segments that are dragged and dropped, allowing us to give the map a more organic feel than if we used a 16-bit-era grid. Figure 3-7. Concept art: map editor Character Editor The character tool format will use a concept similar to the map editor. We’ll divide the characters into parts, like arms, torsos, legs, and so on, and then create frames of animation by combining parts. Figure 3-8 shows the character editor mockup. We’ll allow ourselves to rotate parts and move them around. This technique allows for some pretty flexible animation and is what was used in The Dishwasher: Dead Samurai game. Animations will be made up of frames, and we’ll throw in a scripting system for combos and animation control. We’ll dwell much more on this in Chapter 5, where we build the character editor, but this should suffice for planning purposes. CHAPTER 3 ■ PLANNING YOUR GAME 49 Figure 3-8. Concept art: character editor Naming the Game Game naming is an aspect of planning that barely deserves its own section. For one thing, you don’t even have to give your game a name yet. ■Note When James created the solution for The Dishwasher: Dead Samurai, it was simply named ProjectDish1. Prior to The Dishwasher, there was ZSX3: Ninjastarmageddon (later renamed Manic Space), which was originally called ProjectNova. Long story short: it doesn’t matter what you call your game, but giving it a ProjectX code name is always fun. Regardless, let’ go ahead and christen this project Zombie Smashers XNA. A Game Plan It’s probably a good idea to formulate some approximate plan of attack before you blindly jump into any development. Doing so will help organize your thoughts and prevent you from feeling overwhelmed. Here’s a rough rundown of the game plan for our Zombie Smashers XNA project: • Create a map editor. • Create a character editor. • Create some map and character art. • Create some maps and characters. 50 CHAPTER 3 ■ PLANNING YOUR GAME • Create the game. • Bring the map and character functionality into the game. • Add character movement and collision functionality. • Add combat functionality. • And take it from there! Now we have some structure. It is a little disheartening that we don’t get to the actual game development until halfway down the list. The fact is that the game is made up of the content; without anything to create the content, there will be no game. The more time we spend on the editors and content, the easier it will be to whip together a demo. Conclusion We’ve taken a look at planning concepts, or lack thereof, through a case study of James’s own The Dishwasher: Dead Samurai and our newly christened Zombie Smashers XNA. We’ve examined some common pitfalls of overambitious indie development along with the unfortunate Teenage Game Tycoon (TGT) moniker, and settled on a just-ambitious-enough 2D side-scrolling action platformer. We sketched out some character, map, and game-play concept art, and made some initial tool plans. Everything may seem a bit vague at this point, but all will be revealed through implementation! 51 ■ ■ ■ CHAPTER 4 The Map Editor Making a World Maker Depending on your exposure with the games industry, it may come as a surprise to learn that that vast majority of game development time is spent on level design, which leads to this ques- tion: would you rather spend the vast majority of game development time happy or miserable? Of course, if you have someone else doing level design, it now becomes a matter of keeping that person happy, which is probably important as well. Since so much time in designing the game will be spent in the map editor, it’s pretty crit- ical to have a map editor that is robust and intuitive. Unfortunately, the map editor in our case study game, The Dishwasher: Dead Samurai (introduced in the previous chapter) was none of those things. This starts the chapter off in an awkward light and perhaps sets the tone for the book. A tech book should always reveal the best, cleanest practices. However, this tech book is setting out to reveal some rather ugly and hacky practices in the name of quick prototyping. We’ll be using The Dishwasher game as a model for our map editor. A few things will be cleaner in our version; a few things won’t be. Consider yourself warned. A map editor that isn’t clean or polished is OK though, because it just needs to serve its purpose for the level designer. When creating a tool like a map editor, it is important to realize that the consumer—the person using this product—will be either yourself or a level designer; in other words, someone who is used to these products. In that light, you do not need to create the slickest interface or include the best features. The map editor, above all else, just needs to work by being able to create levels consistently. Creating a New Project: Zombie Smashers The first item on the to-do list is to set up our development environment. Before we can get to creating the actual map editor, we need to create a solution for the game we’re building in this book, Zombie Smashers XNA. Begin by opening Visual Studio (as we mentioned in Chapter 2, for the examples in this book, we are using Visual C# 2005 Express Edition). In Visual Studio, select File ➤ New Project, select the Windows Game (2.0) template, and type in the project name ZombieSmashers, as shown in Figure 4-1. Be sure the “Create directory for solution” check box is selected, and then click OK. 52 CHAPTER 4 ■ THE MAP EDITOR Figure 4-1. Creating the ZombieSmashers project The next step is to add a MapEditor project, and make sure it is the project that runs when you start up. In Solution Explorer, right-click ZombieSmashers and select Add ➤ New Project. After making sure the Windows Game (2.0) template is selected again, enter the name MapEditor, as shown in Figure 4-2, and click OK. Figure 4-2. Adding the MapEditor project CHAPTER 4 ■ THE MAP EDITOR 53 Now, right-click the MapEditor project item in Solution Explorer and select Set As StartUp Project. This ensures the MapEditor project will run, and not the ZombieSmashers project. Solution Explorer now includes the MapEditor project, as shown in Figure 4-3. Figure 4-3. The MapEditor project added to ZombieSmashers Before we can get to the map bits, we’ll need some basic interface functionality—text rendering and interaction, mouse cursor rendering and input, scroll arrows, buttons, and that sort of thing. Drawing Text Text rendering is something that the XNA Framework didn’t implement out of the box origi- nally, so the early adopters had to create their own tools and techniques for implementing bitmap-based text drawing. Fortunately, we are now living in the 2.0 era, so we have a very handy tool called Sprite Font. We can add a Sprite Font to our Content project, and the Content Pipeline will automatically create a bitmap image from it. Then we can load the bitmap and draw it using our SpriteBatch. First, add Sprite Font to your project. Add a Fonts folder to your Content project, and then right-click that folder and select Add ➤ New Item. Select Sprite Font and name the item Arial.spriteFont, as shown in Figure 4-4. Then click Add. 54 CHAPTER 4 ■ THE MAP EDITOR Figure 4-4. Adding a new Sprite Font Now we’ll make a Text class to encapsulate some functionality, like state-based color and size and “cheap” buttons. Select Project ➤ Add Class, name the class Text, as shown in Figure 4-5, and then click Add. Figure 4-5. Adding a Text class Time to start coding! We want the Text class to hold references to a SpriteBatch and Arial SpriteFont, as well as class-level fields for size and color. We’ll declare this at the class level: CHAPTER 4 ■ THE MAP EDITOR 55 private float size = 1f; private Color color = Color.white; SpriteFont font; SpriteBatch sprite; Given these fields, and the fact that these fields should have something in them, the constructor is pretty straightforward: public Text(SpriteBatch _sprite, SpriteFont _font) { font = _font; sprite = _sprite; } We’ll create some properties to set the text color and size. This is the state-based approach. In our program, we’ll be able to set the text color and size once, and then do all of the drawing. public Color Color { get { return color; } set { color = value; } } public float Size { get { return size; } set { size = value ; } } Moving on, the drawing method is fairly straightforward. We’ll send it integer coordinates and a string, and then the method will cast the coordinates into a Vector2 and draw the string. public void DrawText(int x, int y, String s) { sprite.Begin(SpriteBlendMode.AlphaBlend); sprite.DrawString(font, s, new Vector2( (float)x, (float)y), color, 0f, new Vector2(), size, SpriteEffects.None, 1f); sprite.End(); } As for the “cheap” buttons we talked about earlier, we’re going to create a function to draw “clickable” text. This way, we’ll be able to create buttons from our main project easily, as we’ll be drawing text. The function defaults the draw color to white. If the mouse location is within the measured text dimensions (hover), the color will be yellow. If the mouse is hovering and clicked, the function returns true. Of course, this won’t exactly mimic Windows button behavior, but it will be good enough. 56 CHAPTER 4 ■ THE MAP EDITOR public bool DrawClickText(int x, int y, String s, int mosX, int mosY, bool mouseClick) { color = Color.White; bool r = false; if (mosX > x && mosY > y && mosX < x + font.MeasureString(s).X * size && mosY < y + font.MeasureString(s).Y * size) { color = Color.Yellow; if (mouseClick) r = true; } DrawText(x, y, s); return r; } Let’s head back to Game1 to test this out! At the class level, we’ll throw in the following: Text text; SpriteFont font; In LoadContent(), we’ll need to instantiate text and load our bitmap: font = Content.Load<SpriteFont>(@"Fonts/Arial"); text = new Text(spriteBatch, font); Finally, in Draw(), let’s throw some test strings at it. text.Size = 3.0f; text.Color = new Color(0, 0, 0, 125); for (int i = 0; i < 3; i++) { if (i == 2) text.Color = Color.White; text.DrawText(25 - i * 2, 250 - i * 2, "Zombie Smashers XNA FTW!"); } base.Draw(gameTime); [...]... previous location and current location per frame midMouseDown = (mState.MiddleButton == ButtonState.Pressed); CHAPTER 4 ■ THE MAP EDITOR if (midMouseDown) { scroll.X -= (mosX - pMosX) * 2.0f; scroll.Y -= (mosY - pMosY) * 2.0f; } Lastly, we need to make sure we send scroll in our Game1.map.Draw() call: map.Draw(sprite, mapsTex, scroll); This should work fine, but if you try to add a new segment, you’ll... format has a simple hierarchy, with the top level representing everything, or the world The world is composed of interlinking maps Each map is composed of map segments, a script, and a collision map The building block of the map is the map segment, so let’s start there 57 58 CHAPTER 4 ■ THE MAP EDITOR Figure 4-7 Game world format hierarchy Map Segments A map segment is a nongridded sprite that you can... the metadata itself, let’s take a peek at the actual sprite sheet we’ll be working with Our sprite sheet is shown in Figure 4-8 ■Note The zdx extension means something along the lines of “Zombie Data XNA. ” If you’re just using text files, you can give them whatever extension you like Figure 4-8 Maps1 sprite sheet 59 60 CHAPTER 4 ■ THE MAP EDITOR You can see that we have segments of grass, some stones,... it You’ll get a nice drop-shadow effect, as shown in Figure 4-6 Figure 4-6 Text success! FTW, for the uninitiated, means “For The Win,” which is exactly how we should be feeling about Zombie Smashers XNA at this point Text is ready to go, so it’s time to design our map editor now Creating the Map Editor Our map editor should allow us to manage everything contained in the game’s world and maps To begin . text.Size = 0. 8f; spriteBatch.Begin(SpriteBlendMode.AlphaBlend); spriteBatch.Draw(nullTex, new Rectangle( 500 , 20 , 28 0, 5 50) , new Color (0, 0, 0, 100 )); spriteBatch.End(); for (int i = 0; i <. it. text.Size = 3.0f; text.Color = new Color (0, 0, 0, 125 ); for (int i = 0; i < 3; i++) { if (i == 2) text.Color = Color.White; text.DrawText (25 - i * 2, 25 0 - i * 2, "Zombie Smashers XNA FTW!"); } base.Draw(gameTime); CHAPTER. spriteBatch.Begin(SpriteBlendMode.AlphaBlend); spriteBatch.Draw(iconsTex, new Vector2(mosX, mosY), new Rectangle (0, 0, 32, 32) , Color.White, 0. 0f, new Vector2 (0, 0) , 1.0f, SpriteEffects.None, 0. 0f); spriteBatch.End(); } Put a call