【问题标题】:How to Create a sprite Image如何创建精灵图像
【发布时间】:2020-08-23 16:06:18
【问题描述】:

我正在尝试创建一个非常基本的精灵图像。

首先我有一个现有的图像(宽度=100px,高度=100px)。

我将在这张图片中循环 10 到 100 次,每次都将它放在上一张旁边的精灵上。

精灵被限制为 3000px 宽。

将图像彼此相邻放置很好,因为我可以用简单的方法将它们组合起来,但是,我需要将组合图像的宽度限制为 3000 像素,然后从新行开始。

【问题讨论】:

  • 听起来很简单;在总图像长度小于 3000px 时循环附加图像。
  • 我就是这样,但正如你所见,当精灵总共有 3000 像素宽时,我必须从“新行”开始。
  • 嗨@DustyRoberts,关于您的问题,我的思路是否正确?
  • 抱歉这个不清楚的问题,我指的不是游戏开发人员所知道的精灵,而是 web 开发人员和 html 人员所知道的图像精灵。 @Matt,你有一个完整的答案,所以赏金给了你,但是丹尼尔,我把你的答案标记为答案,因为你实际上得到了我的要求:)

标签: c# winforms image-processing


【解决方案1】:

在下面的 MSDN 文章中有很多关于 2D-sprite 的信息:Rendering 2D sprites

这些示例基于Microsoft's XNA,这是一个可在 Visual Studio 中用于为 Windows、Windows Phone 和 XBOX 360 开发游戏的平台。

例如,要绘制一个精灵,可以使用以下 C# 代码(示例取自 MSDN 文章,已删除 XBOX 360 特定代码):

private Texture2D SpriteTexture;
private Rectangle TitleSafe;

    protected override void LoadContent()
    {
        // Create a new SpriteBatch, which can be used to draw textures.
        spriteBatch = new SpriteBatch(GraphicsDevice);
        SpriteTexture = Content.Load<Texture2D>("ship");
        TitleSafe = GetTitleSafeArea(.8f);
    }

    protected Rectangle GetTitleSafeArea(float percent)
    {
        Rectangle retval = new Rectangle(
            graphics.GraphicsDevice.Viewport.X,
            graphics.GraphicsDevice.Viewport.Y,
            graphics.GraphicsDevice.Viewport.Width,
            graphics.GraphicsDevice.Viewport.Height);
        return retval;
    }

    protected override void Draw(GameTime gameTime)
    {
        graphics.GraphicsDevice.Clear(Color.CornflowerBlue);
        spriteBatch.Begin();
        Vector2 pos = new Vector2(TitleSafe.Left, TitleSafe.Top);
        spriteBatch.Draw(SpriteTexture, pos, Color.White);
        spriteBatch.End();
        base.Draw(gameTime);
    }

你需要调用LoadContent()来初始化它,然后你需要调用GetTitleSafeArea(100)来获得安全绘制区域(在这种情况下是100%),最后你可以使用Draw方法。它接受包含GameTime 类实例的参数,该实例是游戏计时状态的快照,以可变步长(实时)或固定步长(游戏时间)游戏可以使用的值表示。

如果对你有帮助,请告诉我。

【讨论】:

  • 嗨,Matt,StackOverflow 的答案通常会包含链接内容的摘要或专门回答问题的亮点。 SE 网站的目标是成为未来几年的知识和答案资源。对于仅链接的答案,操作员必须挖掘另一个资源以找到他/她可能不确定的答案。最重要的是,如果您的链接永远中断(通常微软的链接会随着时间的推移而中断),那么您的答案对于将来访问此页面的任何人都是无用的。考虑制作和编辑您的答案以添加更多详细信息。祝你好运!
  • 嗨杰里米,我同意,因此我添加了更多细节。问候,马特
【解决方案2】:

让我尝试一些伪代码:

Bitmap originalImage; //  that is your image of 100x100 pixels
Bitmap bigImage;      //  this is your 3000x3000 canvas
int xPut = 0;
int yPut = 0;
int maxHeight = 0;
while (someExitCondition) 
{
    Bitmap imagePiece = GetImagePieceAccordingToSomeParameters(originalImage);
    if (xPut + imagePiece.Width > 3000)
    {
        xPut = 0;
        yPut += maxHeight;
        maxHeight = 0;
    }
    DrawPieceToCanvas(bigImage, xPut, yPut, imagePiece);
    xPut += imagePiece.Width;
    if (imagePiece.Height > maxHeight) maxHeight = imagePiece.Height;
    //  iterate until done
}

【讨论】:

    【解决方案3】:

    在 3000 处声明一个变量,如果您放入宽度为 250 的图片,则将其从变量中取出,继续这样做,这也允许您通过查看来决定该行是否有足够的空间用于下一张图片如果左边的数字大于下一张图片的宽度。每次从新行开始时,将变量设置回 3k 并重新开始。解决了

    【讨论】:

      【解决方案4】:

      一种可行的方法是允许将精灵的帧放置在位图中的任何位置(这样可以使它们更紧凑),并为每个位图附上一个描述位置、大小和来源的 (n xml) 文件每帧 AND 都有所有动画的列表。像这样的:

      <SpriteSheet>
          <Frames>
              <Frame id="0" location="20,40" size="64,64" origin="32,32" />
              <Frame id="1" location="100,40" size="64,64" origin="32,32" />
              <Frame id="2" location="164,40" size="64,64" origin="0,0" />
              <Frame id="3" location="20,120" size="64,64" origin="32,32" />
          </Frames>
          <Animations>
              <Animation name="walk left" >
                  <Keyframes>
                      <Keyframe frameId="0" duration="0:0:0.5" offset="-5,0" />
                      <Keyframe frameId="1" duration="0:0:0.5" offset="-5,0" />
                      <Keyframe frameId="2" duration="0:0:0.4" offset="-2,0" />
                      <Keyframe frameId="1" duration="0:0:0.5" offset="-5,0" />
                  </Keyframes>
              </Animation>
              <Animation name="walk right" >
                  <Keyframes>
                      <Keyframe frameId="5" duration="0:0:0.5" offset="5,0" />
                      <Keyframe frameId="6" duration="0:0:0.5" offset="5,0" />
                      <Keyframe frameId="2" duration="0:0:0.4" offset="2,0" />
                      <Keyframe frameId="6" duration="0:0:0.5" offset="5,0" />
                  </Keyframes>
              </Animation>
          </Animations>
      </SpriteSheet>
      

      通过这种方式,您可以在动画中重复使用帧(从而进一步优化位图大小)并通过简单地编辑 XML 文件来自定义动画。

      您所要做的就是读取 XML 文件、读取位图并在开始动画时:启动一个定期计时的计时器。当它滴答作响时,您可以通过将关键帧的持续时间一一添加并在总和超过滴答时间时停止来计算动画中的正确关键帧;应该使用当前的关键帧。

      在上面的 XML 文件中,我添加了诸如偏移之类的东西,它允许您在动画期间修改精灵的位置(您甚至可以对其进行插值以使其平滑移动)

      剩下的就是从位图中抓取正确的帧。作为一种优化,您可以在加载 XML 文件时通过抓取帧来预处理位图,将它们保留为小位图,并丢弃大位图。当位图很大并且没有完全覆盖在帧中时,这可能会优化内存。

      在其他情况下,您无需进行预处理,只需 blit 帧即可。

      对于较大的应用程序(更多位图/动画/帧),我建议创建一个应用程序来创建和编辑 XML 文件。另一种选择可能是为您最喜欢的绘画程序创建一个插件(如果可能的话)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-10-09
        • 1970-01-01
        • 1970-01-01
        • 2021-01-21
        • 2017-01-07
        • 2019-09-26
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多