学习笔记31(手把手教用XNA开发WINPHONE7游戏5--完结篇)

Alien Game逻辑

在这最有一个部分你将创建game-specific logichelper方法和类。胜利就在眼前,你的第一个winphone7程序就要出现了,加油加油!!(感谢http://winphone.us/)。另外最近imagecup要开始了,帮小美女推一下,学生们有时间都去参加。为了帮大家了解imagecup和winphone7的开发,我可能会针对学生讲一些入门级webcast,有详细计划再通知大家。刚刚翻译了imagecup的winphone7的评判标准,觉得有一条很好玩,就是要让使用了你的程序的人想去买一部winphone,呵呵这个占20%,大家加油了。另外有人要源代码,我把最后成品的源代码放到下一篇“番外篇”了,大家感兴趣可以去下载。

1.GameplayScreen.cs文件里,创建一个新的helper(GameplayScreen类之外)根据下面的代码:

(Code Snippet –Game Development with XNA– Gameplay Screen – Bullet class)

C#

/// <summary>

///Represents either an alien or player bullet

/// </summary>

publicclassBullet

{

publicVector2Position;

publicVector2Velocity;

publicboolIsAlive;

}

2.Bullet类后面添加两个helper:

(Code Snippet –Game Development with XNA– Gameplay Screen – Player and Alien classes)

C#

/// <summary>

///The player's state

/// </summary>

publicclassPlayer

{

publicVector2Position;

publicVector2Velocity;

publicfloatWidth;

publicfloatHeight;

publicboolIsAlive;

publicfloatFireTimer;

publicfloatRespawnTimer;

publicstringName;

publicTexture2DPicture;

publicintScore;

publicintLives;

}

/// <summary>

///Data for an alien.The only difference between the ships

///and the badguys are the texture used.

/// </summary>

publicclassAlien

{

publicVector2Position;

publicTexture2DTexture;

publicVector2Velocity;

publicfloatWidth;

publicfloatHeight;

publicintScore;

publicboolIsAlive;

publicfloatFireTimer;

publicfloatAccuracy;

publicintFireCount;

}

3.添加如下GameplayScreen类的变量:

(Code Snippet –Game Development with XNA – Gameplay Screen – even more variables)

C#

Playerplayer;

List<Alien> aliens;

List<Bullet> alienBullets;

List<Bullet> playerBullets;

4.在构造函数中初始化这些变量,如下所示:

(Code Snippet –Game Development with XNA – Gameplay Screen – Player and Alien Initialization)

C#

publicGameplayScreen()

{

...

player =newPlayer();

playerBullets =newList<Bullet>();

aliens =newList<Alien>();

alienBullets =newList<Bullet>();

Accelerometer =newAccelerometer();

if(AccelerometerSensor.Default.State ==SensorState.Ready)

{

...

}

...

}

5.初始化player变量WidthHeightLoadContent方法中(初始化ParticleSystem之后):

(Code Snippet –Game Development with XNA – Gameplay Screen – Player Initialization in LoadContent method)

C#

publicoverridevoidLoadContent()

{

...

particles =newParticleSystem(ScreenManager.Game.Content, ScreenManager.SpriteBatch);

player.Width = tankTexture.Width;

player.Height = tankTexture.Height;

base.LoadContent();

}

6.下面的一小段代码将添加游戏的逻辑。他们将根据用户的输入来改变“player1”的移动。导航到HandleInput的方法,并找到以下行:

C#

//TODO: Update player Velocity over X axis #1

在它的后面添加如下代码段:

(Code Snippet –Game Development with XNA – Gameplay Screen – Player Movements 1 in HandleInput method)

C#

player.Velocity.X = movement;

7.找到以下行(HandleInput方法中):

C#

//TODO: Update player velocity over X axis #2

在其后添加如下代码:

(Code Snippet –Game Development with XNA – Gameplay Screen – Player Movements 2 in HandleInput method)

C#

player.Velocity.X = -1.0f;

8.找到以下行(HandleInput方法中):

C#

//TODO: Update player velocity over X axis #3

在其后添加如下代码:

(Code Snippet –Game Development with XNA – Gameplay Screen – Player Movements 3 in HandleInput method)

C#

player.Velocity.X = 1.0f;

9.找到以下行(HandleInput方法中):

C#

//TODO: Update player velocity over X axis #4

在其后添加如下代码:

(Code Snippet –Game Development with XNA – Gameplay Screen – Player Movements 4 in HandleInput method)

C#

player.Velocity.X =MathHelper.Min(input.CurrentGamePadStates[0].ThumbSticks.Left.X * 2.0f, 1.0f);

10.找到以下行:

C#

//TODO: Fire the bullet

更改"if"语句根据下面的代码片断::

(Code Snippet –Game Development with XNA– Gameplay Screen – HandleInput firing the bullet code)

C#

if(player.FireTimer <= 0.0f && player.IsAlive && !gameOver)

{

Bulletbullet = CreatePlayerBullet();

bullet.Position =newVector2((int)(player.Position.X + player.Width / 2) - bulletTexture.Width / 2, player.Position.Y - 4);

bullet.Velocity =newVector2(0, -256.0f);

player.FireTimer = 1.0f;

particles.CreatePlayerFireSmoke(player);

playerFired.Play();

}

elseif (gameOver)

finishCurrentGame();

11.创建GameplayScreen类中的以下方法:

此方法将创建Bullet类的一个实例。此实例使用在前面的代码段。

(Code Snippet –Game Development with XNA– Gameplay Screen – CreatePlayerBullet method)

C#

/// <summary>

///Returns an instance of a usable player bullet.Prefers reusing an /// existing (dead)

///bullet over creating a new instance.

/// </summary>

/// <returns>A bullet ready to place into the world.</returns>

BulletCreatePlayerBullet()

{

Bulletb =null;

for(inti = 0; i < playerBullets.Count; ++i)

{

if(playerBullets[i].IsAlive ==false)

{

b = playerBullets[i];

break;

}

}

if(b ==null)

{

b =newBullet();

playerBullets.Add(b);

}

b.IsAlive =true;

returnb;

}

12.更改Update方法。在"base.Update()"方法调用之前,添加下面的蓝色突出显示的代码段:

此块的代码实际上提供了游戏的逻辑它移动玩家和调用该方法来更新异型和重新计算子弹的位置。

(Code Snippet –Game Development with XNA– Gameplay Screen – Update method)

C#

publicoverridevoidUpdate(GameTimegameTime,

boolotherScreenHasFocus,boolcoveredByOtherScreen)

{

floatelapsed = (float)gameTime.ElapsedGameTime.TotalSeconds;

if(IsActive)

{

// Move the player

if(player.IsAlive ==true)

{

player.Position += player.Velocity * 128.0f * elapsed;

player.FireTimer -= elapsed;

if(player.Position.X <= 0.0f)

player.Position =newVector2(0.0f, player.Position.Y);

if(player.Position.X + player.Width >= worldBounds.Right)

player.Position =newVector2(worldBounds.Right - player.Width, player.Position.Y);

}

Respawn(elapsed);

UpdateAliens(elapsed);

UpdateBullets(elapsed);

CheckHits();

if(player.IsAlive && player.Velocity.LengthSquared() > 0.0f)

particles.CreatePlayerDust(player);

particles.Update(elapsed);

}

base.Update(gameTime, otherScreenHasFocus, coveredByOtherScreen);

}

13.GameplayScreen类中添加helper方法:

Note:下面的代码段中添加大量的帮助器方法。方法用途如下:

重生:检查是否,玩家已经"死亡"但这场游戏还没有结束,如果这,它完成等待respawnTimer结束后创建一个新的玩家实例屏幕的中间。

UpdateBullets检查和更新屏幕上的玩家和异形子弹的位置。

UpdateAliens移动异形,并计算是否发射子弹和朝哪个方向。

CheckHits检查所有的子弹和玩家/异形的碰撞。它还将处理游戏逻辑,当命中发生时,进行让死亡,加分或者结束游戏等。

(Code Snippet –Game Development with XNA– Gameplay Screen – Helper update methods)

C#

/// <summary>

///Handles respawning the player if we are playing a game and the player is dead.

/// </summary>

/// <param name="elapsed">Time elapsed since Respawn was called last.</param>

voidRespawn(float elapsed)

{

if(gameOver)

return;

if(!player.IsAlive)

{

player.RespawnTimer -= elapsed;

if(player.RespawnTimer <= 0.0f)

{

// See if there are any bullets close...

intleft = worldBounds.Width / 2 - tankTexture.Width / 2 - 8;

intright = worldBounds.Width / 2 + tankTexture.Width / 2 + 8;

for(inti = 0; i < alienBullets.Count; ++i)

{

if(alienBullets[i].IsAlive ==false)

continue;

if(alienBullets[i].Position.X >= left || alienBullets[i].Position.X <= right)

return;

}

player.IsAlive =true;

player.Position =newVector2(worldBounds.Width / 2 - player.Width / 2, worldBounds.Bottom - groundTexture.Height + 2 - player.Height);

player.Velocity =Vector2.Zero;

player.Lives--;

}

}

}

/// <summary>

///Moves all of the bullets (player and alien) and prunes "dead" bullets.

/// </summary>

/// <param name="elapsed"></param>

voidUpdateBullets(float elapsed)

{

for(inti = 0; i < playerBullets.Count; ++i)

{

if(playerBullets[i].IsAlive ==false)

continue;

playerBullets[i].Position += playerBullets[i].Velocity * elapsed;

if(playerBullets[i].Position.Y < -32)

{

playerBullets[i].IsAlive =false;

hitStreak = 0;

}

}

for(inti = 0; i < alienBullets.Count; ++i)

{

if(alienBullets[i].IsAlive ==false)

continue;

alienBullets[i].Position += alienBullets[i].Velocity * elapsed;

if(alienBullets[i].Position.Y > worldBounds.Height - groundTexture.Height - laserTexture.Height)

alienBullets[i].IsAlive =false;

}

}

/// <summary>

///Moves the aliens and performs their "thinking" by determining if they

///should shoot and where.

/// </summary>

/// <param name="elapsed">The elapsed time since UpdateAliens was called last.</param>

privatevoid UpdateAliens(floatelapsed)

{

// See if it's time to spawn an alien;

alienSpawnTimer -= elapsed;

if(alienSpawnTimer <= 0.0f)

{

SpawnAlien();

alienSpawnTimer += alienSpawnRate;

}

for(inti = 0; i < aliens.Count; ++i)

{

if(aliens[i].IsAlive ==false)

continue;

aliens[i].Position += aliens[i].Velocity * elapsed;

if((aliens[i].Position.X < -aliens[i].Width - 64 && aliens[i].Velocity.X < 0.0f) ||

(aliens[i].Position.X > worldBounds.Width + 64 && aliens[i].Velocity.X > 0.0f))

{

aliens[i].IsAlive =false;

continue;

}

aliens[i].FireTimer -= elapsed;

if(aliens[i].FireTimer <= 0.0f && aliens[i].FireCount > 0)

{

if(player.IsAlive)

{

Bulletbullet = CreateAlienBullet();

bullet.Position.X = aliens[i].Position.X + aliens[i].Width / 2 - laserTexture.Width / 2;

bullet.Position.Y = aliens[i].Position.Y + aliens[i].Height;

if((float)random.NextDouble() <= aliens[i].Accuracy)

{

bullet.Velocity =Vector2.Normalize(player.Position - aliens[i].Position) * 64.0f;

}

else

{

bullet.Velocity =newVector2(-8.0f + 16.0f * (float)random.NextDouble(), 64.0f);

}

alienFired.Play();

}

aliens[i].FireCount--;

}

}

}

/// <summary>

///Performs all bullet and player/alien collision detection.Also handles game logic

///when a hit occurs, such as killing something, adding score, ending the game, etc.

/// </summary>

voidCheckHits()

{

if(gameOver)

return;

for(inti = 0; i < playerBullets.Count; ++i)

{

if(playerBullets[i].IsAlive ==false)

continue;

for(inta = 0; a < aliens.Count; ++a)

{

if(aliens[a].IsAlive ==false)

continue;

if((playerBullets[i].Position.X >= aliens[a].Position.X && playerBullets[i].Position.X <= aliens[a].Position.X + aliens[a].Width) && (playerBullets[i].Position.Y >= aliens[a].Position.Y && playerBullets[i].Position.Y <= aliens[a].Position.Y + aliens[a].Height))

{

playerBullets[i].IsAlive =false;

aliens[a].IsAlive =false;

hitStreak++;

player.Score += aliens[a].Score * (hitStreak / 5 + 1);

if(player.Score > highScore)

highScore = player.Score;

if(player.Score > nextLife)

{

player.Lives++;

nextLife += nextLife;

}

levelKillCount--;

if(levelKillCount <= 0)

AdvanceLevel();

particles.CreateAlienExplosion(newVector2(aliens[a].Position.X + aliens[a].Width / 2, aliens[a].Position.Y + aliens[a].Height / 2));

alienDied.Play();

}

}

}

if(player.IsAlive ==false)

return;

for(inti = 0; i < alienBullets.Count; ++i)

{

if(alienBullets[i].IsAlive ==false)

continue;

if((alienBullets[i].Position.X >= player.Position.X + 2 && alienBullets[i].Position.X <= player.Position.X + player.Width - 2) && (alienBullets[i].Position.Y >= player.Position.Y + 2 && alienBullets[i].Position.Y <= player.Position.Y + player.Height))

{

alienBullets[i].IsAlive =false;

player.IsAlive =false;

hitStreak = 0;

player.RespawnTimer = 3.0f;

particles.CreatePlayerExplosion(newVector2(player.Position.X + player.Width / 2, player.Position.Y + player.Height / 2));

playerDied.Play();

if(player.Lives <= 0)

{

gameOver =true;

}

}

}

}

///<summary>

///Advances the difficulty of the game one level.

///</summary>

voidAdvanceLevel()

{

baseLevelKillCount += 5;

levelKillCount = baseLevelKillCount;

alienScore += 25;

alienSpawnRate -= 0.3f;

alienMaxAccuracy += 0.1f;

if(alienMaxAccuracy > 0.75f)

alienMaxAccuracy = 0.75f;

alienSpeedMin *= 1.35f;

alienSpeedMax *= 1.35f;

if(alienSpawnRate < 0.33f)

alienSpawnRate = 0.33f;

if(transitionFactor == 1.0f)

{

transitionRate = -0.5f;

}

else

{

transitionRate = 0.5f;

}

}

14.GameplayScreen类中添加如下代码:

Note:下面的代码片断还增加了大量的帮助器方法。他们的目的是,如下所示:CreateAlienBullet创建的异形的子弹,将用于异形向玩家开火

SpawnAlien初始化一个新的异形实例,设置了的初始位置、速度,选择颜色纹理等。

CreateAlien创建新异形的实例,并将其添加到异形集合

(Code Snippet –Game Development with XNA– Gameplay Screen – Helper aliens methods)

C#

/// <summary>

///Returns an instance of a usable alien bullet.Prefers reusing an existing (dead)

///bullet over creating a new instance.

/// </summary>

/// <returns>A bullet ready to place into the world.</returns>

BulletCreateAlienBullet()

{

Bulletb =null;

for(inti = 0; i < alienBullets.Count; ++i)

{

if(alienBullets[i].IsAlive ==false)

{

b = alienBullets[i];

break;

}

}

if(b ==null)

{

b =newBullet();

alienBullets.Add(b);

}

b.IsAlive =true;

returnb;

}

/// <summary>

///Creates an instance of an alien, sets the initial state, and places it into the world.

/// </summary>

privatevoid SpawnAlien()

{

AliennewAlien = CreateAlien();

if(random.Next(2) == 1)

{

newAlien.Position.X = -64.0f;

newAlien.Velocity.X = random.Next((int)alienSpeedMin, (int)alienSpeedMax);

}

else

{

newAlien.Position.X = worldBounds.Width + 32;

newAlien.Velocity.X = -random.Next((int)alienSpeedMin, (int)alienSpeedMax);

}

newAlien.Position.Y = 24.0f + 80.0f * (float)random.NextDouble();

// Aliens

if(transitionFactor > 0.0f)

{

switch(random.Next(4))

{

case0:

newAlien.Texture = badguy_blue;

break;

case1:

newAlien.Texture = badguy_red;

break;

case2:

newAlien.Texture = badguy_green;

break;

case3:

newAlien.Texture = badguy_orange;

break;

}

}

else

{

newAlien.Texture = alienTexture;

}

newAlien.Width = newAlien.Texture.Width;

newAlien.Height = newAlien.Texture.Height;

newAlien.IsAlive =true;

newAlien.Score = alienScore;

floatduration = screenHeight / newAlien.Velocity.Length();

newAlien.FireTimer = duration * (float)random.NextDouble();

newAlien.FireCount = 1;

newAlien.Accuracy = alienMaxAccuracy;

}

/// <summary>

///Returns an instance of a usable alien instance. Prefers reusing an existing (dead)

///alien over creating a new instance.

/// </summary>

/// <returns>An alien ready to place into the world.</returns>

AlienCreateAlien()

{

Alienb =null;

for(inti = 0; i < aliens.Count; ++i)

{

if(aliens[i].IsAlive ==false)

{

b = aliens[i];

break;

}

}

if(b ==null)

{

b =newAlien();

aliens.Add(b);

}

b.IsAlive =true;

returnb;

}

15..导航到Draw方法并添加下面的蓝色突出显示的代码段,Screen.SpriteBatch.Begin()Screen.SpriteBatch.End()之间:

这样更改方法方法将呼调用helper方法以在屏幕上绘制变化后的内容。

(Code Snippet –Game Development with XNA–Gameplay Screen – Draw method update)

C#

publicoverridevoidDraw(GameTimegameTime)

{

floatelapsedTime = (float)gameTime.ElapsedGameTime.TotalSeconds;

ScreenManager.SpriteBatch.Begin();

DrawBackground(elapsedTime);

DrawAliens();

DrawPlayer();

DrawBullets();

particles.Draw();

DrawForeground(elapsedTime);

DrawHud();

ScreenManager.SpriteBatch.End();

}

16.Draw方法后面添加如下方法:

Note:下面的代码段中添加大量的绘图相关的Helper方法。方法用途如下:DrawPlayer绘制玩家的坦克。

DrawAliens绘制所有异形

DrawBullets绘制所有的子弹(玩家的和异形的)。

DrawForeground作为前台绘制云,并将其移动。

DrawBackground绘制草、丘陵、山地和太阳/月亮。此外处理白天和黑夜之间转换。

DrawHud绘制分数、剩余的生命值和"GAME OVER"需要的时候。

drawString绘制隐藏的文本的通用方法。

(Code Snippet –Game Development with XNA– Gameplay Screen – Draw methods)

C#

/// <summary>

///Draws the player's tank

/// </summary>

voidDrawPlayer()

{

if(!gameOver && player.IsAlive)

{

ScreenManager.SpriteBatch.Draw(tankTexture, player.Position,Color.White);

}

}

/// <summary>

///Draws all of the aliens.

/// </summary>

voidDrawAliens()

{

for(inti = 0; i < aliens.Count; ++i)

{

if(aliens[i].IsAlive) ScreenManager.SpriteBatch.Draw(aliens[i].Texture, newRectangle((int)aliens[i].Position.X, (int)aliens[i].Position.Y, (int)aliens[i].Width, (int)aliens[i].Height), Color.White);

}

}

/// <summary>

///Draw both the player and alien bullets.

/// </summary>

privatevoid DrawBullets()

{

for(inti = 0; i < playerBullets.Count; ++i)

{

if(playerBullets[i].IsAlive)

ScreenManager.SpriteBatch.Draw(bulletTexture, playerBullets[i].Position,Color.White);

}

for(inti = 0; i < alienBullets.Count; ++i)

{

if(alienBullets[i].IsAlive)

ScreenManager.SpriteBatch.Draw(laserTexture, alienBullets[i].Position,Color.White);

}

}

/// <summary>

///Draw the foreground, which is basically the clouds. I think I had planned on one point

///having foreground grass that was drawn in front of the tank.

/// </summary>

/// <param name="elapsedTime">The elapsed time since last Draw</param>

privatevoid DrawForeground(floatelapsedTime)

{

// Move the clouds.Movement seems like an Update thing to do, but this animations

// have no impact over gameplay.

cloud1Position +=newVector2(24.0f, 0.0f) * elapsedTime;

if(cloud1Position.X > screenWidth)

cloud1Position.X = -cloud1Texture.Width * 2.0f;

cloud2Position +=newVector2(16.0f, 0.0f) * elapsedTime;

if(cloud2Position.X > screenWidth)

cloud2Position.X = -cloud1Texture.Width * 2.0f;

ScreenManager.SpriteBatch.Draw(cloud1Texture, cloud1Position,Color.White);

ScreenManager.SpriteBatch.Draw(cloud2Texture, cloud2Position,Color.White);

}

/// <summary>

///Draw the grass, hills, mountains, and sun/moon. Handle transitioning

///between day and night as well.

/// </summary>

/// <param name="elapsedTime">The elapsed time since last Draw</param>

privatevoid DrawBackground(floatelapsedTime)

{

transitionFactor += transitionRate * elapsedTime;

if(transitionFactor < 0.0f)

{

transitionFactor = 0.0f;

transitionRate = 0.0f;

}

if(transitionFactor > 1.0f)

{

transitionFactor = 1.0f;

transitionRate = 0.0f;

}

Vector3day =Color.White.ToVector3();

Vector3night =newColor(80, 80, 180).ToVector3();

Vector3dayClear =Color.CornflowerBlue.ToVector3();

Vector3nightClear = night;

Colorclear =newColor(Vector3.Lerp(dayClear, nightClear, transitionFactor));

Colortint =newColor(Vector3.Lerp(day, night, transitionFactor));

// Clear the background, using the day/night color

ScreenManager.Game.GraphicsDevice.Clear(clear);

// Draw the mountains

ScreenManager.SpriteBatch.Draw(mountainsTexture,newVector2(0, screenHeight - mountainsTexture.Height), tint);

// Draw the hills

ScreenManager.SpriteBatch.Draw(hillsTexture,newVector2(0, screenHeight - hillsTexture.Height), tint);

// Draw the ground

ScreenManager.SpriteBatch.Draw(groundTexture,newVector2(0, screenHeight - groundTexture.Height), tint);

// Draw the sun or moon (based on time)

ScreenManager.SpriteBatch.Draw(sunTexture, sunPosition, newColor(255, 255, 255, (byte)(255.0f * (1.0f - transitionFactor))));

ScreenManager.SpriteBatch.Draw(moonTexture, sunPosition, newColor(255, 255, 255, (byte)(255.0f * transitionFactor)));

}

/// <summary>

///Draw the hud, which consists of the score elements and the GAME OVER tag.

/// </summary>

voidDrawHud()

{

floatscale = 2.0f;

if(gameOver)

{

Vector2size = menuFont.MeasureString("GAME OVER");

DrawString(menuFont,"GAME OVER",newVector2(ScreenManager.Game.GraphicsDevice.Viewport.Width / 2 - size.X, ScreenManager.Game.GraphicsDevice.Viewport.Height / 2 - size.Y / 2),newColor(255, 64, 64), scale);

}

else

{

intbonus = 100 * (hitStreak / 5);

stringbonusString = (bonus > 0 ?" ("+ bonus.ToString(System.Globalization.CultureInfo.CurrentCulture) +"%)":"");

// Score

DrawString(scoreFont,"SCORE: "+ player.Score.ToString(System.Globalization.CultureInfo.CurrentCulture) + bonusString,newVector2(leftOffset, topOffset),Color.Yellow, scale);

stringtext ="LIVES: "+ player.Lives.ToString(System.Globalization.CultureInfo.CurrentCulture);

Vector2size = scoreFont.MeasureString(text);

size *= scale;

// Lives

DrawString(scoreFont, text,newVector2(screenWidth - leftOffset - (int)size.X, topOffset), Color.Yellow, scale);

DrawString(scoreFont,"LEVEL: "+ (((baseLevelKillCount - 5) / 5) + 1).ToString(System.Globalization.CultureInfo.CurrentCulture),newVector2(leftOffset, screenHeight - bottomOffset),Color.Yellow, scale);

text ="HIGH SCORE: "+ highScore.ToString(System.Globalization.CultureInfo

.CurrentCulture);

size = scoreFont.MeasureString(text);

DrawString(scoreFont, text,newVector2(screenWidth - leftOffset - (int)size.X * 2, screenHeight - bottomOffset),Color.Yellow, scale);

}

}

/// <summary>

///A simple helper to draw shadowed text.

/// </summary>

voidDrawString(SpriteFont font,stringtext,

Vector2position,Color color)

{

ScreenManager.SpriteBatch.DrawString(font, text,newVector2(position.X + 1, position.Y + 1),Color.Black);

ScreenManager.SpriteBatch.DrawString(font, text, position, color);

}

/// <summary>

///A simple helper to draw shadowed text.

/// </summary>

voidDrawString(SpriteFont font,stringtext,

Vector2position,Color color,floatfontScale)

{

ScreenManager.SpriteBatch.DrawString(font, text,newVector2(position.X + 1, position.Y + 1),Color.Black, 0,newVector2(0, font.LineSpacing / 2), fontScale, SpriteEffects.None, 0);

ScreenManager.SpriteBatch.DrawString(font, text, position, color, 0,newVector2(0, font.LineSpacing / 2), fontScale,SpriteEffects.None, 0);

}

17.找到LoadContent方法,在base.LoadContent()调用后面体检如下代码:

C#

publicoverridevoidLoadContent()

{

...

player.Width = tankTexture.Width;

player.Height = tankTexture.Height;

base.LoadContent();

LoadHighscore();

Start();

}

18.找到UnloadContent方法并particles = null;之前的位置添加下面的代码:

C#

publicoverridevoidUnloadContent()

{

SaveHighscore();

particles =null;

base.UnloadContent();

}

19.创建一个区域loading/unloading high scores logic。我们需要通过Isolated Storage来读取Windows Phone文件系统中的数据。用如下代码在GameplayScreen类中创建logic:

(Code Snippet –Game Development with XNA – Gameplay Screen – Highscore storage methods)

C#

#regionHighscore loading/saving logic

///<summary>

///Saves the current highscore to a text file. The StorageDevice was selected during screen loading.

///</summary>

privatevoid SaveHighscore()

{

using(IsolatedStorageFileisf =IsolatedStorageFile.GetUserStoreForApplication())

{

using(IsolatedStorageFileStreamisfs =newIsolatedStorageFileStream("highscores.txt",FileMode.Create, isf))

{

using(StreamWriterwriter =newStreamWriter(isfs))

{

writer.Write(highScore.ToString(System.Globalization.CultureInfo.InvariantCulture));

writer.Flush();

writer.Close();

}

}

}

}

///<summary>

///Loads the high score from a text file.The StorageDevice was selected during the loading screen.

///</summary>

privatevoid LoadHighscore()

{

using(IsolatedStorageFileisf =IsolatedStorageFile.GetUserStoreForApplication())

{

if(isf.FileExists("highscores.txt"))

{

using(IsolatedStorageFileStreamisfs =newIsolatedStorageFileStream("highscores.txt",FileMode.Open, isf))

{

using(StreamReaderreader =newStreamReader(isfs))

{

try

{

highScore =Int32.Parse(reader.ReadToEnd(), System.Globalization.CultureInfo.InvariantCulture);

}

catch(FormatException)

{

highScore = 10000;

}

finally

{

if(reader !=null)

reader.Close();

}

}

}

}

}

}

#endregion

20.GameplayScreen类中创建Start方法来开始一个新游戏:

(Code Snippet –Game Development with XNA– Gameplay Screen – Start method)

C#

///<summary>

///Starts a new game session, setting all game states to initial values.

///</summary>

voidStart()

{

if(gameOver)

{

player.Score = 0;

player.Lives = 3;

player.RespawnTimer = 0.0f;

gameOver =false;

aliens.Clear();

alienBullets.Clear();

playerBullets.Clear();

Respawn(0.0f);

}

transitionRate = 0.0f;

transitionFactor = 0.0f;

levelKillCount = 5;

baseLevelKillCount = 5;

alienScore = 25;

alienSpawnRate = 1.0f;

alienMaxAccuracy = 0.25f;

alienSpeedMin = 24.0f;

alienSpeedMax = 32.0f;

alienSpawnRate = 2.0f;

alienSpawnTimer = alienSpawnRate;

nextLife = 5000;

}

21.打开ParticleSystem.cs文件

22.添加如下命名申明:

(Code Snippet –Game Development with XNA– ParticleSystem – using statement)

C#

usingAlienGame;

23.在这个步骤,你将添加两个方法。一个用来创建玩家控制坦克时泥土/灰尘的效果。一个用来创建玩家发射子弹时,火焰的效果。添加如下方法到ParticleSystem类中:

(Code Snippet –Game Development with XNA– ParticleSystem – Helper player effects methods)

C#

///<summary>

///Creates the mud/dust effect when the player moves.

///</summary>

///<param name="position">Where on the screen to create the effect.</param>

publicvoidCreatePlayerDust(Playerplayer)

{

for(inti = 0; i < 2; ++i)

{

Particlep = CreateParticle();

p.Texture = smoke;

p.Color =newColor(125, 108, 43);

p.Position.X = player.Position.X + player.Width * (float)random.NextDouble();

p.Position.Y = player.Position.Y + player.Height - 3.0f * (float)random.NextDouble();

p.Alpha = 1.0f;

p.AlphaRate = -2.0f;

p.Life = 0.5f;

p.Rotation = 0.0f;

p.RotationRate = -2.0f + 4.0f * (float)random.NextDouble();

p.Scale = 0.25f;

p.ScaleRate = 0.5f;

p.Velocity.X = -4 + 8.0f * (float)random.NextDouble();

p.Velocity.Y = -8 + 4.0f * (float)random.NextDouble();

}

}

///<summary>

///Creates the effect for when the player fires a bullet.

///</summary>

///<param name="position">Where on the screen to create the effect.</param>

publicvoidCreatePlayerFireSmoke(Playerplayer)

{

for(inti = 0; i < 8; ++i)

{

Particlep = CreateParticle();

p.Texture = smoke;

p.Color =Color.White;

p.Position.X = player.Position.X + player.Width / 2;

p.Position.Y = player.Position.Y;

p.Alpha = 1.0f;

p.AlphaRate = -1.0f;

p.Life = 1.0f;

p.Rotation = 0.0f;

p.RotationRate = -2.0f + 4.0f * (float)random.NextDouble();

p.Scale = 0.25f;

p.ScaleRate = 0.25f;

p.Velocity.X = -4 + 8.0f * (float)random.NextDouble();

p.Velocity.Y = -16.0f + -32.0f * (float)random.NextDouble();

}

}

24.编译并运行该应用程序。选择"开始游戏"菜单项,并享受你自己编写的游戏吧。

Note:在模拟器中我们使用桌面的键盘移动车辆,您需要首先按PAUSE/BREAK键。这将开启或者关闭仿真程序软件输入面板(SIP)或者桌面的键盘。因为键盘不能同时作为仿真程序软件输入面板(SIP)和桌面的键盘,这个问题将在后面的版本里解决。

学习笔记31(手把手教用XNA开发WINPHONE7游戏5--完结篇)

1

完工的游戏

恭喜你,你终于完成了一个属于你自己的winphone7手机程序。

在今天的部分的过程中,您创建包括玩家和异形的移动计算、 命中的检测、 屏幕绘制,和其他一些的 AlienGame 逻辑。

你可能感兴趣的:(学习笔记)