繁体   English   中英

使用一个带有四个方向的子画面图纸的子画面二维运动动画

2D movement animation for sprites using one sprite sheet with four directions

提示:本站收集StackOverFlow近2千万问答,支持中英文搜索,鼠标放在语句上弹窗显示对应的参考中文或英文, 本站还提供   中文繁体   英文版本   中英对照 版本,有任何建议请联系yoyou2525@163.com。

我出于学习目的而制作2D塔防游戏,并且在移动时无法使敌人(精灵)面对正确的方向。

以下是地图的构建方式,以进行澄清:

http://i.imgur.com/ivO8kWe.png

这是我用来测试的Sprite工作表:

http://i.imgur.com/2h4fSL3.png

左上方的第一个子画面是第0帧,右侧的下一个子画面是第1帧,依此类推。 如您所见,精灵已经朝错误的方向前进。 该地图具有起点(顶部的第一个棕色瓷砖)和终点(终点的最后一个棕色瓷砖),并且只有棕色瓷砖是可步行的,因此有了起点和终点,它将计算出精灵走到终点的最短有效路径。

就是说,每一个生成的精灵都会有一个预定的行走路径,从中我尝试通过检查最后的X或Y位置以及X或Y当前位置来找到精灵所面对的方向,并选择哪条线我将用于行走动画的Sprite表的。 例如,假设小精灵正在向南移动,它应该使用小精灵表格底部(第15到19帧)的小精灵,但它不起作用。

这是我用于敌人的动画课:

 public class AnimatedSprite : Sprite
    {
        public int Lines { get; set; }
        public int Columns { get; set; }
        protected int currentFrame;
        protected int totalFrames;
        protected int timeSinceLastFrame = 0;
        protected int milisecondsPerFrame = 50;


        public AnimatedSprite(Texture2D texture, int lines, int columns, Vector2 position)
            : base ( texture, position)
        {
            this.texture = texture;
            this.position = position;
            Lines = lines;
            Columns = columns;
            totalFrames = Lines * Columns;
        }

        public override void Update(GameTime gameTime)
        {
            base.Update(gameTime);

           //Here i check if the sprite sheet have more than 1 line because if it have, 
           //it must use a different update method.
            if (Lines > 1)
            {
                // Down
                if (lastPostion.Y < position.Y)
                {
                    AnimateDown(gameTime);
                }
                // Up
                if (position.Y < lastPosition.Y)
                {
                    AnimateUp(gameTime);
                }

                // Right
                if (position.X > lastPosition.X)
                {
                    AnimateRight(gameTime);
                }

                // Left
                if (position.X < lastPosition.X)
                {
                    AnimateLeft(gameTime);
                }
            }

            if (Lines == 1) {
            timeSinceLastFrame += gameTime.ElapsedGameTime.Milliseconds;
            if (timeSinceLastFrame > milisecondsPerFrame)
            {
                timeSinceLastFrame -= milisecondsPerFrame;
                currentFrame++;
                if (currentFrame == totalFrames)
                {
                    currentFrame = 0;
                }
            }
        }                        
           center = new Vector2(position.X + texture.Width / Columns, position.Y + texture.Height / Lines);
        }

        public void AnimateUp(GameTime gameTime)
        {
            timeSinceLastFrame += gameTime.ElapsedGameTime.Milliseconds;
            if (timeSinceLastFrame > milisecondsPerFrame)
            {
                timeSinceLastFrame -= milisecondsPerFrame;
                currentFrame++;
                if (currentFrame > 14)
                    currentFrame = 10;
            }
        }

        public void AnimateDown(GameTime gameTime)
        {
            timeSinceLastFrame += gameTime.ElapsedGameTime.Milliseconds;
            if (timeSinceLastFrame > milisecondsPerFrame)
            {
                timeSinceLastFrame -= milisecondsPerFrame;
                currentFrame++;
                if (currentFrame > 19)
                    currentFrame = 15;
            }
        }           

        public void AnimateLeft(GameTime gameTime)
        {
            timeSinceLastFrame += gameTime.ElapsedGameTime.Milliseconds;
                if (timeSinceLastFrame > milisecondsPerFrame)
            {
                timeSinceLastFrame -= milisecondsPerFrame;
                currentFrame++;
                if (currentFrame > 4)
                    currentFrame = 0;
            }
        }

     public void AnimateRight(GameTime gameTime)
        {
            timeSinceLastFrame += gameTime.ElapsedGameTime.Milliseconds;
                if (timeSinceLastFrame > milisecondsPerFrame)
            {
                timeSinceLastFrame -= milisecondsPerFrame;
                currentFrame++;
                if (currentFrame > 9)
                    currentFrame = 5;
            }
        }


        public override void Draw(SpriteBatch spriteBatch)
        {
            int width = texture.Width / Columns;
            int height = texture.Height / Lines;
            int line = (int)((float)currentFrame / (float)Columns);
            int column = currentFrame % Columns;

            Rectangle originRectangle = new Rectangle(width * column, height * line, width, height);
            Rectangle destinationRectangle = new Rectangle((int)position.X, (int)position.Y, width, height);          

            spriteBatch.Draw(texture, destinationRectangle, originRectangle, Color.White);
        }
    }
}

编辑:我在一条直线水平上进行了测试(起点在左侧),它开始朝左(第0帧),但是当它到达第三个棕色瓷砖时,它固定并面向正确的方向:

i.imgur.com/3FsGhuY.png

Edit2:我在所有四个方向(上下移动,向右移动和向左移动,反之亦然)上使用直线水平进行了测试,并且在所有这些方向上,它都从第0帧开始,并在到达第三个图块时开始修复并面对正确的方向。

1 个回复

您无需检查当前帧是否低于所需动画循环的最小值; 您只需要对照最大值进行检查即可。 另外,您的代码中有一些重复可能应该被考虑在内,以使其更易于阅读和使用。

我将用单个方法替换所有AnimateXXXX方法:

public void AnimateLoop(GameTime gameTime, int loopFirstFrame, int loopLastFrame)
{
    timeSinceLastFrame += gameTime.ElapsedGameTime.Milliseconds;
    if (timeSinceLastFrame > milisecondsPerFrame)
    {
        timeSinceLastFrame -= milisecondsPerFrame;
        currentFrame++;
    }
    if (currentFrame > loopLastFrame || currentFrame < loopFirstFrame)
        currentFrame = loopFirstFrame;
}

然后像这样称呼他们:

// Down
if (lastPostion.Y < position.Y)
    AnimateLoop(gameTime, 15, 19);
// Up
if (position.Y < lastPosition.Y)
    AnimateLoop(gameTime, 10, 14);
// Right
if (lastPosition.X < position.X)
    AnimateLoop(gameTime, 5, 9);
// Left
if (position.X < lastPosition.X)
    AnimateLoop(gameTime, 0, 4);
1 Libgdx:为什么我的子画面没有动画?

我正在使用libGDX构建一个小型游戏,目前正在尝试在屏幕上制作动画。 当前,它仅显示动画的第一帧。 我正在使用线程来更新和渲染(这是我怀疑问题所在的地方) 这是要动画的对象的类 我知道我可能在这里错过了一些非常大而明显的东西。 ...

2 我如何为子画面动画,但要像人一样运动?

我正在用html5和javascript制作游戏,此图片会移动。 我可以轻松地移动它,这就是我想要它以人文特征移动的任何简单的恐惧。 就像我按向右一样,它的腿开始来回移动并走路,而不仅仅是整个图像在移动。 指向精灵的链接是: http : //i1057.photobucket.com/a ...

3 如何使四个子画面循环播放,使其表现得像GIF一样充当一个子画面?

因此,我有四个在绘画中编辑过的精灵,因此在遍历它们时看起来像是GIF。 如何使这4个精灵不断循环,使它们看起来像GIF,就像一个精灵? 如何在按向左和向右时将所有四个精灵作为一个精灵左右移动? 这是“ GIF”的代码: 如何使这些循环的精灵在向左按下时向左移动,向右按下时向 ...

4 从子画面加载一个简单的子画面

我知道当您使用以下命令加载精灵帧时: 它通常从缓存中的最后一个sprite-sheet中获取sprite。 我想从特定的精灵表加载特定的精灵: 负载sprite1.png从spritesheet1.png 。 我该怎么办? 谢谢 。 ...

5 如何从多个组件子画面表生成动画子画面

我发现这些很棒的幻想精灵图纸在CC许可下可用,并且想将它们用于Unity( as3gamegears )中的2D游戏。 谁能帮助我了解如何将所有组件子画面表放在一起以构成完整的子画面。 武器和衣服都放在不同的床单中,我想我将不得不使用诸如GIMP之类的东西将它们放在一起,但我不知道如何。 ...

6 矩阵变换和子画面方向的问题

我有一个名为Tool的精灵,它以表示为float的速度和表示为Vector2的方向移动。 当我在屏幕上单击鼠标时,精灵会更改其方向,并开始朝着mouseclick移动。 除此之外,我还要旋转精灵,使其面向前进的方向。 但是,当我添加一个假定要跟随该精灵的摄像机以使该精灵始终位于屏幕中央时, ...

7 来自多个子画面的动画子画面

我是Android开发人员的新手,在处理覆盖超过1个Sprite工作表的大型动画时,刚遇到了一个问题。 基本上,我有一个很大的精灵,其动画跨2个精灵表运行。 我试图找到一种方法来成功加载它们。 我将向您展示我正在尝试的内容,希望有人可以向我展示正确的方法或帮助我以自己的方式完成它。 ...

8 动画数组不动画子画面

我正在用SpriteKit在Swift中制作一个简单的RPG。 我编写了一个角色类来帮助我处理所有动画,但动画遇到了一些麻烦。 人物类: 尚未为Walk West绘制框架 游戏场景类: 它的设置方式使我要做的就是调用动画的函数。 当我称呼它们时,我得到的只是一个静 ...

9 与C#结合使用:根据子画面表更改子画面

我的用户界面: 我已经在顶部设置了健康栏。 这是带有3个索引的Sprite表。 每个都有不同数量的心(3,2,1)。 我将上面显示的运行状况图像连接到LoseCollider(C#脚本)。 目标: 当球掉到屏幕底部的对撞机上而不是进入输球屏幕时,球将重置为附着在 ...

10 使用Phaser在父子画面后面显示子子画面

使用Phaser是否可以在父子画面后面显示子子画面? 我想通过渲染一个填充的绿色圆圈并将其粘贴在父精灵后面来在我的精灵周围绘制一个圆环。 我知道我可以为此使用一个组,但是我希望父级精灵受物理影响,并且不知道如何将该组与组用法协调。 这是我的问题的jsfiddle: http : //j ...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2022 STACKOOM.COM