XNA飞跃的方块--简单的实现
2010-12-23 17:50 WangQiang 阅读(1816) 评论(3) 编辑 收藏 举报最近在博客园开了博客,这也是第一次开IT类博客,之所有选择博客园是觉得比较稳定,而且有很多大牛也在此写博。
第一次写这类文章,写的不好请大家指出 。好了..不废话了。
------------
半年前接触XNA,但是学习一直比较紧,一直都在做与学习有关的东西,所以只是了解了解。最近学习上的项目都忙完了,突然觉得比较闲,开始做个小游戏了,游戏比较简单,代码写的也比较浅显,只是想给初学者一个小小教程,顺便加深一下自己的印象(文中提示是我自己觉得初学者容易忘记的,再就是可能写的比较详细)。
游戏素材:一个方块,若干跳板。
(block.png)AND
(board.png)
预计效果:可以跳跃的方块,随机生成跳板,方块可以站在跳板上。
接下来我们来实现吧(部分自动生成代码略过。此文代码在VS2010+XNA4.0下测试成功,其他版本环境需稍加修改。)
1.首先我们需要定义的内容:
1 //2D图形
2 Texture2D blockTexture;
3 Texture2D boardTexture;
4
5 //球
6 Vector2 blockPosition;//位置
7 const int blockSpeed = 10;//左右移动速度
9
9 //跳板
10 List<Vector2> boardsPositions = new List<Vector2>();//跳板集合
11 const float boardSpawnOdds = 0.01f;//跳板产生的几率
12 const int boardSpeed = 3;//跳板移动速度
(提示:const限定一个变量不允许被改变)
在上面定义的boardsPositions是用来存取随机生产出来的各个跳板的坐标的集合(额.有点绕口)。
2.再让我们在LoadContent()中把图片加载到blockTexture和boardTexture对象中去。
1 blockTexture = Content.Load<Texture2D>("ball");
2 boardTexture = Content.Load<Texture2D>("bat");
3
4 blockPosition = new Vector2((Window.ClientBounds.Width - blockTexture.Width) / 2,
5 Window.ClientBounds.Height - blockTexture.Height); //居中方块
(提示:Window.ClientBounds.Height/Width是游戏窗口的高度和宽度)
3.准备工作已经做好,现在我们把方块和跳板画到游戏去吧!在Draw()键入以下代码。
1 spriteBatch.Begin();//准备画画
2
3 spriteBatch.Draw(blockTexture, blockPosition, Color.White);//画方块
4 foreach (Vector2 blocksPosition in boardsPositions)
5 {
6 spriteBatch.Draw(boardTexture, blocksPosition, Color.White);
7 }//遍历boardsPositions集合,画出各个跳板
8
9 spriteBatch.End();//结束画画
好了!现在我们运行一下,
4.咦?大家是不是发现方块不能移动哦,这怎么行呢,恩...我们先来实现左右移动吧!在Update中我们写上按键判断,并且改变方块的位置。
1 KeyboardState keyBoard = Keyboard.GetState();
2 //这里定义的是电脑键盘状态,
3 //如果考虑到XBOX360需要GamePadState gamePad = GamePad.GetState(PlayerIndex.One);
4
5 if (keyBoard.IsKeyDown(Keys.Left))//按左
6 {
7 blockPosition.X -= blockSpeed;
8 }
9 if (keyBoard.IsKeyDown(Keys.Right))//按右
10 {
11 blockPosition.X += blockSpeed;
12 }
13
14 blockPosition.X = MathHelper.Clamp(blockPosition.X,
15 0, Window.ClientBounds.Width - blockTexture.Width);
16 //这里的意思是,把方块的X轴坐标限制在游戏屏幕之内
blockSpeed是我们之前已经定义好了的速度,你可以根据需要修改,因为Update()方法是不断重复执行,所以只需累加即可。
5.好了,我们的方块可以随意移动了!真是激动人心,但是我们的主题可不是只有左右移动那么简单,我们还要跳呢!
在跳跃中,我们要想到如何使方块上下移动,并且能最好实现重力加速度。现在我们分析一下重力加速度,在方块跳跃的过程中,起跳时速度是由快到慢,落下时是由慢到快(还有其他许多情况未考虑,此文只实现简单效果)。自认为数学学的还是很差的,我想大家数学应该比我好的,各位可能已经想到了很多方法来实现了,这里我举出一个简单的算法。
我们先定义三个全局变量:
1 bool jumpState = false;//此变量用来表示方块跳跃的状态
2 int blockJumpSpeed = 20;//跳跃时加速度
3 int downSpeed = 0;//不在跳跃时下降加速度,在此不做具体解释,后文中将会讲到。
接下来在Update()中键入如下内容:
1 if (keyBoard.IsKeyDown(Keys.Up))//按上
2 {
3 jumpState = true;
4 }
5
6 if (jumpState)//跳跃状态为true时
7 {
8 blockJumpSpeed = blockJumpSpeed - 1;
9 blockPosition.Y -= blockJumpSpeed;
10 }
11
12 if (blockPosition.Y > Window.ClientBounds.Height - blockTexture.Height)
13 {
14 blockPosition.Y = Window.ClientBounds.Height - blockTexture.Height;
15 blockJumpSpeed = 20;
16 jumpState = false;
17 downSpeed = 0;
18 }//当方块坠落到最下方时则停住,并且初始化跳跃加速度和非跳跃下降加速度
(提示:只有JumpState为true时,跳跃整个动作才会执行。同样因为Update()不断执行的原因,只有掉落到最下方才会停止)
看见了吗?我们重点关注第二个if中的内容,blockJumpSpeed是在不断变化的,我们可以知道blockJumpSpeed>0时方块是上升的,由于blockJumpSpeed数值越来越小,所有上升速也越来越慢,当blockJumpSpeed<0方块则会下降,而且速度是越来越快的,所以一个简单的重力加速度就完成了。
现在你可以执行了,方块可以完成完整的动作了,操作方块快乐的跳跃!
6.好了好了,我们别沉浸在欢乐中了,我们的目标还没完成,我们的跳板呢,光是方块跳来跳去,实在有些无趣。
跳板是需要随机生成的,所以我们实例化一个Random对象:
1 Random random = new Random();
然后在Update()中添加:
1 if (random.NextDouble() < boardSpawnOdds)
2 {
3 float y = (float)random.NextDouble() * (Window.ClientBounds.Height - boardTexture.Height);
4 boardsPositions.Add(new Vector2(-boardTexture.Width, y));
5 }//随机一个数如果符合则向boardsPositions中添加一个随机位置的方块
6
7 for (int i = 0; i < boardsPositions.Count; i++)
8 {
9 boardsPositions[i] = new Vector2(boardsPositions[i].X + boardSpeed, boardsPositions[i].Y);
10 if (boardsPositions[i].X > Window.ClientBounds.Width)
11 {
12 boardsPositions.RemoveAt(i);
13 i--;
14 }//当跳板从屏幕移除时清除
15 }//移动boardsPositions集合中每个方块的位置
(提示:当跳板移除屏幕并且不再显示时一定要从集合中清楚,否则会造成占用大量资源)
这样,跳板就生成出来了,大家也可以适当的做一些修改,来改变跳板的方向和速度。
7.我们现在就只剩下最后一个问题了,也是整个游戏中最费脑细胞的问题,那就是如何让我们的方块站到跳板上。此处涉及到碰撞检测,在游戏中方块和每个跳板都是一个矩形图片,我们可以把每一个都转换为矩形来进行碰撞检测。
我们先定义一个对象和全局变量:
Vector2 boardIntersects = Vector2.Zero;//与方块发生碰撞的跳板
bool hit = false;//是否发生碰撞
在Update()中添加定义一个方块的矩形:
1 Rectangle blockRectangle = new Rectangle((int)blockPosition.X,
2 (int)blockPosition.Y, blockTexture.Width, blockTexture.Height);
接下来修改前一步骤中的:
修改前的代码(忽略):
1 if (random.NextDouble() < boardSpawnOdds)
2 {
3 float y = (float)random.NextDouble() * (Window.ClientBounds.Height - boardTexture.Height);
4 boardsPositions.Add(new Vector2(-boardTexture.Width, y));
5 }//随机一个数如果符合则向boardsPositions中添加一个随机位置的方块
6
7 for (int i = 0; i < boardsPositions.Count; i++)
8 {
9 boardsPositions[i] = new Vector2(boardsPositions[i].X + boardSpeed, boardsPositions[i].Y);
10 if (boardsPositions[i].X > Window.ClientBounds.Width)
11 {
12 boardsPositions.RemoveAt(i);
13 i--;
14 }//当跳板从屏幕移除时清除
15 }//移动boardsPositions集合中每个方块的位置
修改后(黑体部分是新添加的):
1 hit = false; //初始化碰撞,重新判断是否碰撞
2 for (int i = 0; i < boardsPositions.Count; i++)
3 {
4 boardsPositions[i] = new Vector2(boardsPositions[i].X + boardSpeed, boardsPositions[i].Y);
5 //移动boardsPositions集合中每个跳板的位置
6
7 Rectangle boardRectangle = new Rectangle((int)boardsPositions[i].X,
8 (int)boardsPositions[i].Y, boardTexture.Width, boardTexture.Height);
9 //实例化一个当前遍历到的跳板的矩形
10
11 if (boardsPositions[i].X > Window.ClientBounds.Width)
12 {
13 boardsPositions.RemoveAt(i);
14 i--;
15 }//当矩形超出屏幕范围则从集合中清除
16
17 if (blockRectangle.Intersects(boardRectangle))
18 {
19 boardIntersects = boardsPositions[i];
20 hit = true;
21 }//当前遍历到的跳板与方块发生碰撞时取出跳板到boardsIntersects对象
22 }
注意黑体中的blockRectangle.Intersects(boardRectangle)方法,当blockRectangle与boardRectangle两个矩形发生碰撞时,此方法返回true,反之则返回false。
现在我们没有对发生碰撞后做出任何反映,还需做进一步判断,现在在第6个步骤的代码的前面(就是随机生成跳板的代码前面)添加如下代码:
1 if (hit)//如果发生碰撞
2 {
3 if (keyBoard.IsKeyDown(Keys.Up) &&
4 blockPosition.Y == boardIntersects.Y - blockTexture.Height + 1)
5 {//只有方块落在跳板上之后按方向键“上”才会跳
6 blockJumpSpeed = 20;
7 jumpState = true;
8 }
9 else if (blockJumpSpeed < 0 || blockJumpSpeed == 20)
10 {//当向下落的时候才会掉到跳板上,防止向上跳时碰撞到即到了跳板上
11 blockPosition.Y = boardIntersects.Y - blockTexture.Height + 1;
12 blockPosition.X += boardSpeed;
13 blockJumpSpeed = 20;
14 jumpState = false;
15 }
16 }
17 else//未碰撞时
18 {
19 if (!jumpState)//未跳跃时
20 {
21 if (blockPosition.Y < Window.ClientBounds.Height - blockTexture.Height)
22 {//当方块位置高于地面时,向下加速度掉落
23 downSpeed = downSpeed - 1;
24 blockPosition.Y -= downSpeed;
25 }
26 }
27 }
你是否还记得downSpeed变量,用来模拟非人为操作重力加速度的,比如当跳板移出屏幕时,方块在上面会自然下来。
到此简单的一个方块跳跃游戏已经做好了(或许还不能算作游戏 = -),至于关卡之类的需要读者发挥自己的想象力了。最后,可能到此代码还有许多不理想的地方,希望各位大牛指出或加以修改,我会感激不尽。对了,如果你做出了更加好玩的游戏,别忘了发上来和大家分享哦!恩....第一篇,希望大家多多支持哦!
转载别忘了注明出处:http://www.cnblogs.com/WangQ/archive/2010/12/23/xnajumpblock.html 请输入标题