您的位置:首页 > 编程语言

《XNA高级编程:Xbox 360和Windows》2-3(2)

2010-05-11 21:11 267 查看
2.3开始编写Pong

处理用户输入



正如您在第一章所看到的,在XNA中捕捉用户的键盘和Gamepad输入是非常简单的,单单为它写一个单元测试有点夸张了。您已经知道它是如何工作的,而且也只是想测试一下控制球拍的运动,所以没有必要写一个新的单元测试,完全可以使用前面的TestGameSprites,或许可以把它重新命名为TestSingleplayerGame。单元测试的内容还是一样的,您只需在PongGame的Update方法中修改对输入的处理并更新球拍的位置:

// Get current gamepad and keyboard states

gamePad = GamePad.GetState(PlayerIndex.One);

gamePad2 = GamePad.GetState(PlayerIndex.Two);

keyboard = Keyboard.GetState();

gamePadUp = gamePad.DPad.Up == ButtonState.Pressed ||

gamePad.ThumbSticks.Left.Y > 0.5f;

gamePadDown = gamePad.DPad.Down == ButtonState.Pressed ||

gamePad.ThumbSticks.Left.Y < -0.5f;

gamePad2Up = gamePad2.DPad.Up == ButtonState.Pressed ||

gamePad2.ThumbSticks.Left.Y > 0.5f;

gamePad2Down = gamePad2.DPad.Down == ButtonState.Pressed ||

gamePad2.ThumbSticks.Left.Y < -0.5f;

// Move half way across the screen each second

float moveFactorPerSecond = 0.5f *

(float)gameTime.ElapsedRealTime.TotalMilliseconds / 1000.0f;

// Move up and down if we press the cursor or gamepad keys.

if (gamePadUp || keyboard.IsKeyDown(Keys.Up))

rightPaddlePosition -= moveFactorPerSecond;

if (gamePadDown || keyboard.IsKeyDown(Keys.Down))

rightPaddlePosition += moveFactorPerSecond;

// Second player is either controlled by player 2 or by the computer

if (multiplayer)

else

// Make sure paddles stay between 0 and 1

if (leftPaddlePosition < 0)

leftPaddlePosition = 0;

if (leftPaddlePosition > 1)

leftPaddlePosition = 1;

if (rightPaddlePosition < 0)

rightPaddlePosition = 0;

if (rightPaddlePosition > 1)

rightPaddlePosition = 1;

您可能注意到这里又有些新的变量(multiplayer、gamePad、 gamePad2、keyboard和 ComputerPaddleSpeed),但目前要关心的是改变球拍位置的代码。变量moveFactorPerSecond用来确保球和球拍总是以相同的速度运动,而不管帧的渲染速度是多少,如果是1fps(frame per second),那么moveFactorPerSecond就等于1,如果是10fps,那么它就等于0.1,如果是100fps,那么它就是0.01,以此类推。

接下来,当“Up”和“Down”键或按钮被按下的时候您要改变右边球拍的位置,而左边的球拍由另一个玩家控制,无论是使用Gampad还是“W”和“S”键。如果是单人游戏模式,那么左边的球拍就由计算机控制,并以ComputerPaddleSpeed=0.5f的速度跟着球运动。开始的时候,球运动比较慢,但每次碰撞都会提升一点速度,您也可以使用球拍的边缘撞击球来加速,这样计算机就接不到球您就赢了。

要让新的Update方法能正常工作,需要添加如下的变量和常量:

const float BallSpeedMultiplicator = 0.5f;

const float ComputerPaddleSpeed = 0.5f;//25f;

enum GameMode

GamePadState gamePad, gamePad2;

KeyboardState keyboard;

bool gamePadUp = false,

gamePadDown = false,

gamePad2Up = false,

gamePad2Down = false;

bool multiplayer = false;

GameMode gameMode = GameMode.Menu;

int currentMenuItem = 0;

对于当前的测试您只需要使用我前面提到几个变量,但还是要看一下游戏需要的其他变量。变量BallSpeedMultiplicator决定了球的速度,同时也决定了游戏的整体速度。游戏模式枚举GameMode用来处理当前您可能在的所有三种游戏模式,您可能是刚打开游戏处于菜单界面,或者正在游戏中。当您处在游戏中时,如果一个玩家输了,那么模式将被修改成游戏结束(GameOver)状态,并显示获胜的玩家。

下面是处理菜单输入的代码,虽然您现在还不需要,但它是您要处理的最后一部分输入操作:

// Show screen depending on our current screen mode

if (gameMode == GameMode.Menu)

public void StartNewBall()

// Update ball position and bounce off the borders

ballPosition += ballSpeedVector *

moveFactorPerSecond * BallSpeedMultiplicator;

如果现在使用这个测试运行游戏,球将运动到屏幕的外边,这就是为什么您需要碰撞检测。看一下图2-7所示的构思图,然后添加一些碰撞代码。有时候回过头去看之前设计的构思图,并基于新的想法和知识进行改进是很有必要的,比如这次就是这样。这里有三种碰撞可能会发生:

碰撞屏幕边界——屏幕顶部和底部

碰撞球拍——把球弹回给对手

碰撞球拍后面的屏幕边界——这时玩家会失去一条命,并用StartNewBall方法重新设置球

public static void TestBallCollisions()

// Check top and bottom screen border

if (ballPosition.Y < 0 || ballPosition.Y > 1)

// Check for collisions with the paddles

// Construct bounding boxes to use the intersection helper method.

Vector2 ballSize = new Vector2(

GameBallRect.Width / 1024.0f, GameBallRect.Height / 768.0f);

BoundingBox ballBox = new BoundingBox(

new Vector3(ballPosition.X-ballSize.X/2,

ballPosition.Y-ballSize.Y/2, 0),

new Vector3(ballPosition.X+ballSize.X/2,

ballPosition.Y+ballSize.Y/2, 0));

Vector2 paddleSize = new Vector2(

GameRedPaddleRect.Width / 1024.0f, GameRedPaddleRect.Height / 768.0f);

BoundingBox leftPaddleBox = new BoundingBox(

new Vector3(-paddleSize.X/2, leftPaddlePosition-paddleSize.Y/2, 0),

new Vector3(+paddleSize.X/2, leftPaddlePosition+paddleSize.Y/2, 0));

BoundingBox rightPaddleBox = new BoundingBox(

new Vector3(1-paddleSize.X/2, rightPaddlePosition-paddleSize.Y/2, 0),

new Vector3(1+paddleSize.X/2, rightPaddlePosition+paddleSize.Y/2, 0));

// Ball hit left paddle?

if (ballBox.Intersects(leftPaddleBox))

// Ball lost?

if (ballPosition.X < -0.065f)

else if (ballPosition.X > 1.065f)

// If either player has no more lives, the other one has won!

if (gameMode == GameMode.Game &&

(leftPlayerLives == 0 || rightPlayerLives == 0))

public static void TestSounds()

// Ball lost?

if (ballPosition.X < -0.065f)

else if (ballPosition.X > 1.065f)

{

// Play sound

soundBank.PlayCue("PongBallLost");

// Reduce number of lives

rightPlayerLives--;

// Start new ball

StartNewBall();

} // if

添加这些代码之后,您可以重新启用单元测试TestSingleplayerGame来检查一下声音能否被正确地播放。对于复杂的游戏需要有一个好的系统在播放声音的时候进行检测,而对于大多数的简单游戏,直接使用PlayCue方法就可以了,它可以在需要的时候直接用来播放声音并保存Cue。您也可以自己创建并管理Sound Cue,这样的好处是您可以停止播放或者重新开始等等。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: