跟我一起学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

原文地址:https://www.cnblogs.com/fish124423/p/2739291.html