摘要:
在很多游戏开发中角色的运动都是相对游戏背景而言的,也就是说我们通过移动游戏场景来给游戏角色带来一种运动效果,毕竟我们的游戏视窗是有限的,如果无止境的让角色运动肯定是不可行的,下面我们就一块看一下在XNA中如何制作滚动的背景。
内容:
在多数游戏开发的时候,特别是对于角色游戏,除了游戏角色本身的运动之外,更多的时候游戏给人的行动感觉是由游戏背景的移动造成的(我们平时看的动画片也是如此),毕竟游戏视窗是有限的,角色不可能超出游戏视窗而运动,它的运动范围也仅仅在整个游戏视窗内。这样一来我们就必须准备好整个游戏的背景,在游戏中动态改变它的位置。可是对于稍微复杂的游戏,其背景长度也是不可估量的(例如超级玛丽),此时我们就不可能一次加载所有的背景,此时我们怎么办呢?事实上对于这个问题我们通常是将整个背景做成可循环的,这有一点类似于我们地板设计,每个地板和另一地板的连接处花纹都是连续的;其次就是我们可以将游戏背景中的物体拆分开来,然后在游戏运行过程中进行动态组合。对于第二种情况我们暂且不管,我们今天主要讨论一下第一种情况。针对第一种情况假设我们有下面一副背景,在X方向它是可以无限循环显示的:
那么下面我们是不是就可以直接让整个图片循环显示就可了呢?答案是否定的。对于重复显示的背景我们直接整张图片加载起来是不切实际的,因为它的体积太大了。我们常用的做法是根据屏幕大小将图片分割成多张。例如上面的背景我们就可以切分成两张图片:
为了清楚的看到整个背景滚动形成的动画效果,我们给游戏添加一个角色:
下面是我们的完整代码:
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using Microsoft.Xna.Framework;
5 using Microsoft.Xna.Framework.Audio;
6 using Microsoft.Xna.Framework.Content;
7 using Microsoft.Xna.Framework.GamerServices;
8 using Microsoft.Xna.Framework.Graphics;
9 using Microsoft.Xna.Framework.Input;
10 using Microsoft.Xna.Framework.Input.Touch;
11 using Microsoft.Xna.Framework.Media;
12 namespace ScrollBackground
13 {
14 public class MyGame : Microsoft.Xna.Framework.Game
15 {
16 GraphicsDeviceManager graphics;
17 SpriteBatch spriteBatch;
18 private Texture2D background1;//第一个背景
19 private Texture2D background2;//第二个背景
20 private Vector2 bg1Position1;//第一个背景位置
21 private Vector2 bg2Position2;//第二个背景位置
22 private float speed;//滚动速度
23 private Texture2D bird;//小鸟
24 private Vector2 birdPosition;//小鸟所在位置
25 public MyGame()
26 {
27 graphics = new GraphicsDeviceManager(this);
28 Content.RootDirectory = "Content";
29 graphics.PreferredBackBufferWidth = 800;//游戏视窗的高度和宽度决定了游戏在模拟器中是横向显示还是纵向显示
30 graphics.PreferredBackBufferHeight = 480;
31 TargetElapsedTime = TimeSpan.FromTicks(333333);
32 }
33 protected override void Initialize()
34 {
35 bg1Position1 = new Vector2(0, 0);
36 bg2Position2 = new Vector2(graphics.PreferredBackBufferWidth, 0);
37 speed = 2;
38 birdPosition = new Vector2(200, 50);
39 base.Initialize();
40 }
41 protected override void LoadContent()
42 {
43 spriteBatch = new SpriteBatch(GraphicsDevice);
44 background1 = Content.Load<Texture2D>("bg1");
45 background2 = Content.Load<Texture2D>("bg2");
46 bird = Content.Load<Texture2D>("bird");
47 }
48 protected override void UnloadContent()
49 {
50 }
51 protected override void Update(GameTime gameTime)
52 {
53 if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
54 this.Exit();
55 if (bg1Position1.X < -background1.Width)
56 {
57 bg1Position1.X=bg2Position2.X+graphics.PreferredBackBufferWidth;
58 }
59 if (bg2Position2.X < -background2.Width)
60 {
61 bg2Position2.X = bg1Position1.X + graphics.PreferredBackBufferWidth;
62 }
63 bg1Position1.X -= speed;
64 bg2Position2.X -= speed;
65 base.Update(gameTime);
66 }
67 protected override void Draw(GameTime gameTime)
68 {
69 GraphicsDevice.Clear(Color.CornflowerBlue);
70 spriteBatch.Begin();
71 spriteBatch.Draw(background1, bg1Position1, Color.White);
72 spriteBatch.Draw(background2, bg2Position2, Color.White);
73 spriteBatch.Draw(bird, birdPosition, Color.White);
74 spriteBatch.End();
75 base.Draw(gameTime);
76 }
77 }
78 }
2 using System.Collections.Generic;
3 using System.Linq;
4 using Microsoft.Xna.Framework;
5 using Microsoft.Xna.Framework.Audio;
6 using Microsoft.Xna.Framework.Content;
7 using Microsoft.Xna.Framework.GamerServices;
8 using Microsoft.Xna.Framework.Graphics;
9 using Microsoft.Xna.Framework.Input;
10 using Microsoft.Xna.Framework.Input.Touch;
11 using Microsoft.Xna.Framework.Media;
12 namespace ScrollBackground
13 {
14 public class MyGame : Microsoft.Xna.Framework.Game
15 {
16 GraphicsDeviceManager graphics;
17 SpriteBatch spriteBatch;
18 private Texture2D background1;//第一个背景
19 private Texture2D background2;//第二个背景
20 private Vector2 bg1Position1;//第一个背景位置
21 private Vector2 bg2Position2;//第二个背景位置
22 private float speed;//滚动速度
23 private Texture2D bird;//小鸟
24 private Vector2 birdPosition;//小鸟所在位置
25 public MyGame()
26 {
27 graphics = new GraphicsDeviceManager(this);
28 Content.RootDirectory = "Content";
29 graphics.PreferredBackBufferWidth = 800;//游戏视窗的高度和宽度决定了游戏在模拟器中是横向显示还是纵向显示
30 graphics.PreferredBackBufferHeight = 480;
31 TargetElapsedTime = TimeSpan.FromTicks(333333);
32 }
33 protected override void Initialize()
34 {
35 bg1Position1 = new Vector2(0, 0);
36 bg2Position2 = new Vector2(graphics.PreferredBackBufferWidth, 0);
37 speed = 2;
38 birdPosition = new Vector2(200, 50);
39 base.Initialize();
40 }
41 protected override void LoadContent()
42 {
43 spriteBatch = new SpriteBatch(GraphicsDevice);
44 background1 = Content.Load<Texture2D>("bg1");
45 background2 = Content.Load<Texture2D>("bg2");
46 bird = Content.Load<Texture2D>("bird");
47 }
48 protected override void UnloadContent()
49 {
50 }
51 protected override void Update(GameTime gameTime)
52 {
53 if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
54 this.Exit();
55 if (bg1Position1.X < -background1.Width)
56 {
57 bg1Position1.X=bg2Position2.X+graphics.PreferredBackBufferWidth;
58 }
59 if (bg2Position2.X < -background2.Width)
60 {
61 bg2Position2.X = bg1Position1.X + graphics.PreferredBackBufferWidth;
62 }
63 bg1Position1.X -= speed;
64 bg2Position2.X -= speed;
65 base.Update(gameTime);
66 }
67 protected override void Draw(GameTime gameTime)
68 {
69 GraphicsDevice.Clear(Color.CornflowerBlue);
70 spriteBatch.Begin();
71 spriteBatch.Draw(background1, bg1Position1, Color.White);
72 spriteBatch.Draw(background2, bg2Position2, Color.White);
73 spriteBatch.Draw(bird, birdPosition, Color.White);
74 spriteBatch.End();
75 base.Draw(gameTime);
76 }
77 }
78 }
其运行后的效果如下:
OK,代码比较简单,我也就不再过多解释,附上源程序: