Vous êtes sur la page 1sur 8

6/25/13

2D Game Primer (Visual C#) | Coding4Fun Articles | Channel 9

2D Game Primer (Visual C #)


This article is the first part of the Upgrade Your Game series of tutorials. It walks you through the basics of how 2D games work using Visual C# Andy Dunn - The Z-Man The Z-Buffer [1] Difficulty: Easy Time Required: 1-3 hours Cost: Free Software: Visual Basic or Visual C# Express Editions [2], Visual C# Upgrade Your Game Series

Introduction
Welcome to the Upgrade Your Game series of tutorials. There are four tutorials, each covering how to write a simple computer game using Visual Studio Express products. Though the games are simple, each one teaches some game development techniques and builds on the last to improve your skills. The skills can be applied to more complex games including 3D games using Microsoft DirectX [3]. When you program games, you have to use math whether you want to or not. The simpler the game, the less math there is to learn, and 2D games use simpler math but you cannot avoid it altogether. Today's top-selling 3D games are full of 3D vector math and complex simulations of physics. Fortunately, you do not need to know all of that for the simple games presented in this series. This 2D primer covers some of the fundamentals of simple math needed for the
channel9.msdn.com/coding4fun/articles/2D-Game-Primer-Visual-C 1/8

6/25/13

2D Game Primer (Visual C#) | Coding4Fun Articles | Channel 9

games in this series. Note: This documentation assumes that you have a basic knowledge of programming concepts and the Visual C# environment. You can learn more about these topics in the product documentation by clicking Help on the menu bar, and then clicking Contents, Index, or Search. You can also access Help by positioning the mouse cursor on language keywords or user interface elements such as windows or dialog boxes, and pressing F1.

2D Game Development Concepts


The Game Loop Window Forms and ASP applications are often called "event-driven" applications they sit doing nothing for most of the time waiting for an external stimulus, such as a button press from an end user or a Web service request from another application. This works really well for that kind of application. Games, on the other hand, are generally not sitting doing nothing all the time. Even if the end user is not pressing a key or a button on the gamepad, the game must animate characters, perform AI functions, and play sounds and many other things depending on the game. You've probably done some of these background type tasks in Windows Forms applications using timer controls or background threads. But in general these don't scale to the computer game scenario, where there are multiple animations and multiple background tasks all happening at very different intervals. The solution that most games use (and by "most games" I mean everything right up to the top-selling Xbox 360 titles) is usually called the "game loop." In pseudo code it looks something like this: W h i l e( g a m ei sr u n n i n g ) C h e c kf o ri n p u t U p d a t ea l lo b j e c t si nt h eg a m e D r a wa l lo b j e c t si nt h eg a m e This might explain one reason why games almost always use 100% of your CPU even if they don't appear to be doing much. The faster your computer is, the faster this loop will run and the smoother the animation and the
channel9.msdn.com/coding4fun/articles/2D-Game-Primer-Visual-C 2/8

6/25/13

2D Game Primer (Visual C#) | Coding4Fun Articles | Channel 9

synchronization will be. There is one slight problem with running a tight loop like that, at least in Windows. If you don't allow Windows to check for and process Windows messages and events, your application will be marked as "Not responding" by the operating system. You might have seen this in your applications if you have a loop that runs for a long time. You might also have solved it by putting a call to DoEvents into the loop, which allows Windows to process the events. This can work reasonably well if you know the loop will end eventually, but in this case the loop is the entire game and you need a better way. The method I have chosen to use for these games is NOT the most efficient (for a full discussion on this under Managed DirectX see the MDX Game Loop FAQ
[4]), but it is the simplest, and none of the games covered here needs the more

complex method.
p r i v a t ev o i dT i n y T e n n i s _ P a i n t ( o b j e c ts e n d e r ,P a i n t E v e n t A r g se ) { / / W o r ko u th o wl o n gs i n c ew ew e r el a s th e r e i ns e c o n d s d o u b l eg a m e T i m e=_ t i m e r . E l a p s e d M i l l i s e c o n d s/1 0 0 0 . 0 ; d o u b l ee l a p s e d T i m e=g a m e T i m e-_ l a s t T i m e ; _ l a s t T i m e=g a m e T i m e ; _ f r a m e C o u n t e r + + ; / / P e r f o r ma n ya n i m a t i o n / / D r a wt h eg a m eo b j e c t s / / F o r c et h en e x tP a i n t ( ) t h i s . I n v a l i d a t e ( ) ; }

Sprites Sprites [5] are two-dimensional images that appear in a video game. Sometimes they are static images, but in general they are the building blocks for animation. They either move around the screen or change the image at regular intervals, giving a "flip book" kind of animation; or they do both, giving you characters like Mario and Donkey Kong that can move around the screen running and jumping. Positioning a Sprite Just like Windows Forms controls, sprites are placed at an x,y position on the form. 0,0 is the top left and ClientSize.Width, ClientSize.Height is the bottom
channel9.msdn.com/coding4fun/articles/2D-Game-Primer-Visual-C 3/8

6/25/13

2D Game Primer (Visual C#) | Coding4Fun Articles | Channel 9

right. Just like Windows Forms controls, sprites have a height and width too. However, unlike Windows Forms controls, sprites are primarily designed to move and animate, often hundreds of times per second, to get the smoothest animation possible. So while a sprite can only be drawn at an integer x,y position, its ACTUAL position at a subsecond point in time could be 1.45, 12.67. It's important to remember this position so that the animation doesn't get choppy. A sprite position is stored using a floating-point Point structure PointF rather than the integer-based Point structure like Windows Forms controls. This means you can store the subpixel accuracy and then just convert to integer screen positions when you draw them. Vectors The more game programming you do, the more you will come across the term "vector." Though I've avoided the term in this series for the sake of simplicity, it's worth noting that the concepts are used when the positions of the sprites are updated for animation. Simply put, a vector is just an offset. So a vector of (4,2) means that from some start point you move 4 units in the x-axis and 2 in the y-axis. You will see positions referred to as vectors. In this case, a position of (4,2) means an offset of (4,2) from the origin.

Vectors can be added together, so (4,2) + (2,4) gives you a total offset of (6,6). Vectors can have negative components, so (-2,1) means move 2 units to the left
channel9.msdn.com/coding4fun/articles/2D-Game-Primer-Visual-C 4/8

6/25/13

2D Game Primer (Visual C#) | Coding4Fun Articles | Channel 9

on the x-axis and 1 unit down on the y-axis.

All of these concepts are used when moving a sprite around the screen. Moving a Sprite Sprites move with a certain velocity. Velocity is different from speed because velocity also contains information about the direction. For example, you could tell me you are driving at 60 mph, and I would guess that in one hour you would be 60 miles from the start point. But if you were driving round in a circle, that would not be the case. If I told you my velocity was 60 mph due east, then I would know for sure where you would end up. Since your position is an x, y value you can store your velocity as another twocomponent vector (s, t): s is how fast you want to move on the x-axis, and t is how fast you want to move on the y-axis. If you add them together: (x,y) + (s,t) = (x+s, y+t), you get the new position of the sprite. Example: Sprite is at (4,10) and has a speed of (1,0). (1,0) means the sprite will move right in the x direction only. (4,10) + (1,0) = (5,10). If you repeat this addition every second, then the sprite will move 1 pixel per second across the screen. You can see that any direction and speed can be represented just by changing the s, t values in that vector.

channel9.msdn.com/coding4fun/articles/2D-Game-Primer-Visual-C

5/8

6/25/13

2D Game Primer (Visual C#) | Coding4Fun Articles | Channel 9

Time-Based Animation Imagine a sprite that starts at x=0 and is moving to the right with a velocity of +10. If you walk through the game loop above, the sprite would have +10 added to its position each time the sprite was updated and would move from x=0 to x= {some bigger number} where {some bigger number} is 10 times the number of times the loop has been run. But the question is, exactly how fast would it move? Well, it depends on how fast the loop runs, which depends on how fast your computer is running. This would mean that on your top-of-the-line gaming rig the sprite could cross the screen in half a second, but on your parents' four-year-old "we only use it for e-mail" computer it could take two seconds. Obviously this isn't something that is desirable in a computer game. To fix this you need to think about what velocity really is. What does that +10 mean? Velocity is a measure of distance over a period of time, so you cannot think of the +1 as just a distance; it's really +1 pixel in some time that you need to define. So each time round the loop, you just need to know how long it's been since the last update and scale the movement by that time. A sprite that has a velocity of +10 actually means you move +10 pixels per second. So if it's been half a second since the last frame, multiply that by the velocity and move 5 pixels. In reality the time between frames is fractions of a second. So on your fast gaming rig, where the loop runs very fast, the sprite will move with subpixel accuracy for some very smooth animation. On your parents' computer, where the loop only runs 5 times per second, the sprite will move 2 pixels each frame, but after 10 seconds the sprite will be in exactly the same place as it is on your computer. The code will look something like this (notice that for accuracy elapsedTime is a double and therefore needs to be cast down to a float to match the PointF structure):
/ / M o v et h es p r i t eb a s e do nt h ev e l o c i t y L o c a t i o n . X+ =V e l o c i t y . X*( f l o a t ) e l a p s e d T i m e ; L o c a t i o n . Y+ =V e l o c i t y . Y*( f l o a t ) e l a p s e d T i m e ;

The loop timings I mentioned here are very exaggerated on most computers the loop will be running hundreds or thousands of times per second, meaning that your animations will be very smooth and accurate. Sprite bounds
channel9.msdn.com/coding4fun/articles/2D-Game-Primer-Visual-C 6/8

6/25/13

2D Game Primer (Visual C#) | Coding4Fun Articles | Channel 9

There are two ways to represent the rectangle containing the sprite: 1. X, Y, Height, Width 2. X, Y of top left corner and X, Y of bottom right corner Whilst both of these are valid, you must usually find the first one in use. It's easier to update just one corner as the sprite moves around and calculate the other corner when it's needed. For tasks like collisions- and bounds-checking you need to calculate the bottom-right corner, so you will see X+Width and Y+Height as a very commonly used formula in games. Simple Collision Detection Collisions are a vital part of almost any game they restrict where an object can move, whether an object has taken damage, and so forth. Simple collisions can be described in terms of the positions and size of the sprites and the regions they need to collide with. Since everything is rectangular in this case, there is no need for any more complex collisions that need to be determined at the pixel level. All the collisions can be checked for by looking to see if the rectangles overlap or if the coordinates are outside of a certain range. Checking for rectangle overlap is quite simple [6].
p r i v a t eb o o lc o l l i d e ( ) { r e t u r n!(s p r i t e 1 . L o c a t i o n . X>s p r i t e 2 . L o c a t i o n . X+s p r i t e 2 . S i z e . W i d t h | |s p r i t e 1 . L o c a t i o n . X+s p r i t e 1 . S i z e . W i d t h <s p r i t e 2 . L o c a t i o n . X | |s p r i t e 1 . L o c a t i o n . Y>s p r i t e 2 . L o c a t i o n . Y+s p r i t e 2 . S i z e . H e i g h t | |s p r i t e 1 . L o c a t i o n . Y+s p r i t e 1 . S i z e . H e i g h t<s p r i t e 2 . L o c a t i o n . Y ) ; }

1. http://www.thezbuffer.com/ 2. http://msdn.com/express/ 3. http://msdnprod/directx/ 4. http://www.thezbuffer.com/articles/185.aspx 5. http://en.wikipedia.org/wiki/Sprite_%28computer_graphics%29 6. http://www.tekpool.com/?p=23

channel9.msdn.com/coding4fun/articles/2D-Game-Primer-Visual-C

7/8

6/25/13

2D Game Primer (Visual C#) | Coding4Fun Articles | Channel 9

channel9.msdn.com/coding4fun/articles/2D-Game-Primer-Visual-C

8/8

Vous aimerez peut-être aussi