📜 ⬆️ ⬇️

Learning to program XNA games for Windows Phone 7 "Mango" - the beginning

In light of the recent announcement by HTC about the imminent appearance of phones on Windows Phone 7 “Mango” in the Russian market, the development of applications for Windows Phone is becoming particularly relevant - now it is possible to saturate the Windows Phone Marketplace with applications close to our Russian heart. This is one of the reasons why we ( WindoWs Phone 7 Camp ) are today (September 5), and urge you to come, watch the online broadcast and take on Visual Studio right now.



At this event, I just talked about programming games on XNA for a phone, and in this connection I would like to devote a few articles to this on a habr. In today's article, I will show you how to write a simple “sea battle” game - and in the next articles we will add sound, XNA integration with Silverlight, the use of sensors (accelerometer), etc. to it. For lovers of watching videos, the process of writing a game is also described in this screencast .
')

Sea battle, which we will write - this is not the game that many played in childhood on paper in the box. This is a game that was available in slot machines, where you had to get into a floating ship with a few shots. In our game there will also be a ship floating at the top of the screen, and projectiles that can be released from the bottom of the screen by touching it.

First, a few words about XNA. XNA is a collection of libraries that runs on top of Microsoft .NET, both on the phone and on other devices: a full-fledged personal computer, XBox 360 and Zune. Moreover, the game code for all these devices may differ very slightly - given the difference in ways to control the game and different screen resolutions. The remaining aspects are graphics, sound output, game saving, etc. - as much as possible unified for all devices. In addition, XNA runs on top of an available .NET platform (this is a full-featured .NET 4.0 on a computer, and the .NET Compact Framework on other devices), so you can use other platform features (for example, networking tools). Theoretically, XNA can be used not only to create games, but also for a wider range of dynamic rich graphics applications — for example, for scientific visualization.

The architecture of the XNA application is quite different from the classic Windows or Web application. It does not use the event model, since it is not very suitable for solving real-time tasks - and yet we want the game to unfold before our eyes in real time, at a speed of at least 25 frames per second! Therefore, the game has a very simple software model - the game cycle . At the beginning of the game (or game level), the special LoadContent function is called to load the main resources (graphic and sound elements), then the Update methods (to update the game state depending on the user’s action with input devices) and Draw (to draw the state games on the screen). Thus, to write a game you need to perform several basic actions:
  1. Create graphic and sound design elements of the game and put them into the project. Microsoft Expression tools are well suited for creating graphic elements. Graphic elements can be both two-dimensional sprites, and three-dimensional models.
  2. Describe the variables to store all the necessary elements and override the LoadContent method to load them into memory.
  3. Understand how the state of the game will look like - i. a set of variables and data structures that will describe the game at each point in time. The state can be quite simple (as in our example, the coordinates of the ship and the projectile), or consist of many independent interacting objects or agents with their own intelligence and logic.
  4. Process user actions with input devices and program the logic of the game state change in the Update method.
  5. Program state display on the screen in the Draw method. Here again 2D or 3D graphics can be used, depending on the style of the game.
  6. If the game is more difficult, it contains several levels, etc. - it may be useful to improve the object model to separate each level into a separate class - then for each level you will have to partially repeat the steps described above
  7. Play, enjoy, share the game with others (steps include creating an installer, distributing the game through the Windows Mobile Marketplace, XBox Indie Games, etc.).


Vistual Studio Shot
For our development, we will need Visual Studio 2010 (I remind you that students can get it through the DreamSpark program for free) and the XNA Game Studio , which is part of the Windows Phone Developer Tools . Having installed all this, you should be able to create a new project such as the Windows Phone Game (4.0) , which will be a game framework containing the methods described above, and issuing a game with an empty purple screen when launched. To fill the game with content, let's go through the steps described above (1-5, since steps 6 and 7 do not make sense for a simple game). When Visual Studio asks which version of the phone you want - 7.0 or 7.1 Mango - you should develop the game, feel free to choose 7.1 - this way you will have access to new features, such as additional sensors, fast application switching, etc.

Let's start with the fact that we will do one important action to correctly orient the phone. By default, the game screen can be rotated vertically or horizontally. If we need some specific orientation, then in the constructor of the Game1 class, we can set the desired screen resolution as follows:

graphics.PreferredBackBufferWidth = 480;
graphics.PreferredBackBufferHeight = 800;

* This source code was highlighted with Source Code Highlighter .


Pay attention - in the created solution there are two projects: the game itself, and the game resources (Content) - images, sounds, etc. There are two classes in the game itself - Program.cs is needed to start the game, and Game1.cs contains the main logic of the game (LoadContent / Update / Draw functions), and we will modify it.

In our case, the graphic content will consist of three elements - images of the ship and the explosion, which we will take from the Microsoft Office clipart collection, and the image of the projectile - a red dash that can be drawn in Paint. We will add the resulting graphic files to the Content-project of our game (we use the Add Existing Item menu) - the result can be seen in the figure above.

Next, we describe the variables responsible for the state of the game. We will need to store graphic images of the ship, the rocket and the explosion - they will be Texture2D, the coordinates and speed of the ship (speed is needed to set the direction), as well as the coordinates of the rocket - these will be objects of type Vector2. Additionally, the explode variable will be needed to draw the explosion - it will count down the number of frames during which an explosion is shown instead of a ship.

Texture2D ship, rocket, explosion;
Vector2 ship_pos = new Vector2(100, 100);
Vector2 ship_dir = new Vector2(3, 0);
Vector2 rock_pos = Vector2.Zero;

int explode = 0;

* This source code was highlighted with Source Code Highlighter .


The LoadContent method for loading the contents of the game will look quite simple (the description of the function and the first line were generated automatically when creating the project, we only had to add three lines to load the resources we described):

protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
ship = Content.Load<Texture2D>( "Ship" );
rocket = Content.Load<Texture2D>( "Rocket" );
explosion = Content.Load<Texture2D>( "Explode" );

}

* This source code was highlighted with Source Code Highlighter .


The drawing method is also quite simple:

protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.White);
spriteBatch.Begin();
if (explode > 0) spriteBatch.Draw(explosion, ship_pos, Color.White);
else spriteBatch.Draw(ship, ship_pos,Color.White);
if (rock_pos != Vector2.Zero){ spriteBatch.Draw(rocket, rock_pos, Color.Red); }
spriteBatch.End();
base .Draw(gameTime);
}

* This source code was highlighted with Source Code Highlighter .


It should be noted one subtlety - when drawing sprites on the screen, we draw pictures in “portions” called SpriteBatch . Accordingly, we open such a “drawing transaction” with a call to spriteBatch.Begin (), and end with a call to spriteBatch.End (), between which there are calls to spriteBatch.Draw () or DrawString (..). In our case, we draw either a ship or an explosion image - depending on the explode variable, and also display a rocket if it is released and flies to the ship - this is determined by the non-zero value of the rock_pos coordinate vector.

We now turn to the consideration of the Update method. We will consider it in parts. The first part is responsible for drawing the explosion: when the explode flag is non-zero, the only task of our game is to draw the explosion. Therefore, we simply reduce the frame counter during which the explosion is shown, and when it reaches zero, we return the ship to its original position so that the game starts again:

protected override void Update(GameTime gameTime)
{
if (explode > 0)
{
explode--;
if (explode == 0)
{
ship_pos.X = 0;
ship_dir.X = 3;
}
base .Update(gameTime);
return ;
}
....
base .Update(gameTime);
}

* This source code was highlighted with Source Code Highlighter .


Notice that at the end of the Update method, the Base class's Update method is called.

The following code snippet is responsible for moving the ship left and right:

ship_pos += ship_dir;
if (ship_pos.X + ship.Width >= 480 || ship_pos.X <= 0)
{
ship_dir = -ship_dir;
}

* This source code was highlighted with Source Code Highlighter .


Here we explicitly use the screen resolution - in practice, of course, this is not worth doing, it is better to set constants at the beginning of the program, or use variables that are initialized during the game operation depending on the specific device.

Next, we will process the user's actions - in our case, touching the screen. TouchPanel.GetState () allows you to get the status of the telephone panel, which in turn can contain information about several simultaneous touches (MultiTouch support). We will process only one (first) touch, and if there is such a touch, we will launch a rocket from a point whose X-coordinate coincides with the touch, and the vertical coordinate is fixed somewhere at the bottom of the screen:

var tc = TouchPanel.GetState();
if (tc.Count>0)
{
rock_pos.X = tc[0].Position.X;
rock_pos.Y = 750;
}

* This source code was highlighted with Source Code Highlighter .


The following is the code responsible for the movement of the rocket and the testing of the collision of the rocket with the ship:

if (rock_pos != Vector2.Zero)
{
rock_pos += new Vector2(0, -7);
if (rock_pos.Y >= 0 && rock_pos.Y <= ship_pos.Y + ship.Height &&
rock_pos.X >= ship_pos.X && rock_pos.X <= ship_pos.X + ship.Width)
{
explode = 20;
ship_pos.X = rock_pos.X - explosion.Width / 2;
rock_pos = Vector2.Zero;
}
if (rock_pos.Y == 0) rock_pos = Vector2.Zero;
}

* This source code was highlighted with Source Code Highlighter .


For rocket movement, we simply add the velocity value in the form of a two-dimensional vector on each game cycle. Collision is defined “manually” by coordinates (for more complex shapes, it makes sense to use other XNA intercept recognition functions) - in case of defeat, the variable explode is set, which means that the next few frames will show an explosion instead of a ship. If the rocket reaches the upper border of the screen - its movement stops (zero coordinates are set).

To give the game a final believability, it makes sense to mirror the image of the ship in the case when it floats to the left (so that it does not float backwards). To do this, slightly modify the code to display the ship, adding the possibility of mirror reflection:

if (explode == 0)
{
spriteBatch.Draw(ship, ship_pos, null , Color.White,0f,
Vector2.Zero,1.0f,
ship_dir.X>0 ? SpriteEffects.FlipHorizontally : SpriteEffects.None,0f);
}
else spriteBatch.Draw(explosion, ship_pos, Color.White);


* This source code was highlighted with Source Code Highlighter .


That's all that is needed to write the simplest game. To make it more attractive, it is worthwhile to draw a beautiful graphic substrate over which the shooting will unfold - for this it is enough to draw the corresponding image at the beginning of the spriteBatch, so that all further objects are drawn over the image. You can also add a hit counter - while drawing a string, you will need to use the spriteBatch.DrawString method, and the font that will be used to display the string will need to be placed into project resources and loaded into the LoadContent method.

You can download the source code of the entire project to deal with it at your leisure, or use it as a starting point for creating your own games. Of course, this example was very simple, and does not constitute a good example of how to write games in reality. Many more realistic examples you can find:



In the next releases I will explain how to improve the game by adding sound and control of the ship using the accelerometer. I will be glad to hear your comments, suggestions and questions below, as well as on Twitter .

Source: https://habr.com/ru/post/127669/


All Articles