跟我一起学XNA(2)让物体动起来②(附源码)
加载一个静态图片,左右移动,真没啥意思,鼠标单击上去都没反应,这也太山寨了吧。
来点稍微给力的,\(^o^)/
新建项目,加载图片,和第一章是一样的
Texture2D people; protected override void LoadContent() { // Create a new SpriteBatch, which can be used to draw textures. spriteBatch = new SpriteBatch(GraphicsDevice); people = Content.Load<Texture2D>(@"Image/PlayerMagic"); // TODO: use this.Content to load your game content here }
这里有一个地方,就是当你加载Body0这个gif的时候,最好转换成png或者jpg之类的,而且最好不要太大,因为它加载图片大会出现一个这样的异常
意思都能看懂,就是图片太大,Textrue2D容积小,当然有解决办法,我还没想到,以后知道了补上,如果是程序无法识别的图片格式,他会报格式不识别这个错误
//这里是图片中每一帧图片的大小 Point pictureSize = new Point(150, 150); Point currentFrame = new Point(0, 0); //这里是你的图片有几帧,10是行,1是列,因为图片只有一行,所以列没啥用,那个Body0可以用得着 Point pictureNum = new Point(10, 1); public Game1() { graphics = new GraphicsDeviceManager(this); Content.RootDirectory = "Content"; //因为程序1秒刷新60次,你可以自定义刷新的时间,这里是每0.12秒刷新 TargetElapsedTime = new TimeSpan(0, 0, 0, 0, 120); //鼠标可见 IsMouseVisible = true; }
因为是从一张图片动态取帧,所以才有Point pictureNum = new Point(10, 1);这样的变量10列1行,其实用两个变量记录也行,一个记录行,一个记录列
protected override void Draw(GameTime gameTime) { GraphicsDevice.Clear(Color.CornflowerBlue); // TODO: Add your drawing code here spriteBatch.Begin(SpriteSortMode.FrontToBack, BlendState.AlphaBlend); spriteBatch.Draw(people, Vector2.Zero, new Rectangle(currentFrame.X * pictureSize.X, currentFrame.Y * pictureSize.Y, pictureSize.X, pictureSize.Y), Color.White, 0, Vector2.Zero, 1, SpriteEffects.None, 0); spriteBatch.End(); base.Draw(gameTime); }
Draw这里,要使用重载函数来动态的用new Rectangle来获取显示的位置了
protected override void Update(GameTime gameTime) { // Allows the game to exit if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed) this.Exit(); // TODO: Add your update logic here ++currentFrame.X; if (currentFrame.X >= pictureNum.X) { currentFrame.X = 0; } base.Update(gameTime); }
Update这里加入一个判断,当Rectangle超过图片大小时候,清零重来
运行,左上角会有一个gif图片,当然,还有另外一种方法
我这里面加了8张图片,可以再Draw中这么处理
protected override void Draw(GameTime gameTime) { GraphicsDevice.Clear(Color.CornflowerBlue); // TODO: Add your drawing code here spriteBatch.Begin(SpriteSortMode.FrontToBack, BlendState.AlphaBlend); //spriteBatch.Draw(people, Vector2.Zero, //new Rectangle(currentFrame.X * pictureSize.X, //currentFrame.Y * pictureSize.Y, //pictureSize.X, //pictureSize.Y), //Color.White, 0, Vector2.Zero, //1, SpriteEffects.None, 0); spriteBatch.Draw(list[currentFrame.X], Vector2.Zero, null, Color.White); ++currentFrame.X; if (currentFrame.X >=8) { currentFrame.X = 0; } spriteBatch.End(); base.Draw(gameTime); }
之前我有这样的操作,也能达到相同效果
List<Texture2D> list = new List<Texture2D>(); protected override void LoadContent() { // Create a new SpriteBatch, which can be used to draw textures. spriteBatch = new SpriteBatch(GraphicsDevice); people = Content.Load<Texture2D>(@"Image/PlayerMagic"); for (int i = 0; i < 8; i++) { list.Add(Content.Load<Texture2D>(string.Format(@"Image/{0}",i))); } // TODO: use this.Content to load your game content here }
两个方法一样的,注意的是如果用第二种方法,你要把Update中的方法先注释掉
进入下一个问题
图片随鼠标移动
//记录前一个鼠标的位置 MouseState preMouseState; //图片的位置 Vector2 ringsPosition = Vector2.Zero; //移动的速度 const float ringsSpeed = 4;
我们新加几个变量
protected override void Update(GameTime gameTime) { // Allows the game to exit if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed) this.Exit(); // TODO: Add your update logic here ++currentFrame.X; if (currentFrame.X >= pictureNum.X) { currentFrame.X = 0; } MouseState mouseState = Mouse.GetState(); if (mouseState.X != preMouseState.X || mouseState.Y != preMouseState.Y) ringsPosition = new Vector2(mouseState.X-75, mouseState.Y-75); preMouseState = mouseState; base.Update(gameTime); }
Update的时候记录一下鼠标的位置,说白了就是把图片移动到当前鼠标位置呗,这里也要改一下
protected override void Draw(GameTime gameTime) { GraphicsDevice.Clear(Color.CornflowerBlue); // TODO: Add your drawing code here spriteBatch.Begin(SpriteSortMode.FrontToBack, BlendState.AlphaBlend); spriteBatch.Draw(people, ringsPosition, new Rectangle(currentFrame.X * pictureSize.X, currentFrame.Y * pictureSize.Y, pictureSize.X, pictureSize.Y), Color.White, 0, Vector2.Zero, 1, SpriteEffects.None, 0); //spriteBatch.Draw(list[currentFrame.X], ringsPosition, null, Color.White); //++currentFrame.X; //if (currentFrame.X >= 8) //{ // currentFrame.X = 0; //} spriteBatch.End(); base.Draw(gameTime); }
红色也要改一下
spriteBatch.Draw(list[currentFrame.X], Vector2.Zero, null, Color.White); ++currentFrame.X; if (currentFrame.X >=8) { currentFrame.X = 0; }
还有这个东西也要改一下,红色的那个,我程序已经改过了,如果注释错了可能会报错
声明一下(图片是从别的地方拿过来的,当时玩wpf的时候看过深蓝的教程,顺手把图片牵过来了)
源代码:files.cnblogs.com/fish124423/XNA.rar