在Smart Mobile Studio中为Box2D对象添加颜色

Fle*_*ing 5 javascript delphi html5 box2d smart-mobile-studio

我想为Box2D中的动态对象添加颜色。似乎必须在场景渲染中分配动态对象的某些属性。我玩过Box2D演示,但无法弄清楚如何添加颜色(和位图)之类的属性?

Jør*_*eit 4

SmartMS 附带的 Box2d 演示使用 Box2d 的“DebugDraw”功能。此功能只是使用“静态对象”、“移动对象”和“静止对象”的一些内部颜色绘制对象的表示。我实际上不确定是否可以覆盖这些......

您需要做的是将FWorld.DrawDebugData(在PaintView方法中)替换为您想要使用的自定义绘画。

您可以像这样遍历所有对象:

  Body := FWorld.GetBodyList;  //Will give you first object in list

  while Assigned(Body) do
  begin
    //Do something with "Body" here...

    Body := Body.GetNext;  //Will give you next object in list
  end;
Run Code Online (Sandbox Code Playgroud)

例如:

  i := 0;
  Canvas.Font := '10pt verdana';
  Canvas.FillStyle := 'rgb(255,255,255)';
  Canvas.FillTextF('Count:' + IntToStr(FWorld.GetBodyCount), 30, 40, MAX_INT);

  Body := FWorld.GetBodyList;
  while Assigned(Body) do
  begin
    Canvas.FillTextF('i:' + IntToStr(i),                    30, 60+(i*12), MAX_INT);
    Canvas.FillTextF('Y:' + FloatToStr(Body.Position.Y, 2), 70, 60+(i*12), MAX_INT);

    Body := Body.GetNext;
    Inc(i);
  end;
Run Code Online (Sandbox Code Playgroud)

要为各种对象绘制精灵,您应该使用一个TW3SpriteSheets类来处理它。

将spritesheet图片作为资源文件添加到工程中,编译时会解压到res文件夹中。

像这样加载图像:

  FSpriteSheet := TW3SpriteSheet.Create;
  FSpriteSheet.LoadImage('res/MySpriteSheet.png');
Run Code Online (Sandbox Code Playgroud)

并使用这样的图像:

  if FSpriteSheet.Ready then
  begin
    FSpriteSheet.Draw(Canvas, 100, 100, 1); // draw tile #1
    FSpriteSheet.Draw(Canvas, 133, 100, 2); // draw tile #2
    FSpriteSheet.Draw(Canvas, 166, 100, 3); // draw tile #3
  end;
Run Code Online (Sandbox Code Playgroud)

编辑:

在精灵表中,您拥有对象所需的所有旋转。

在此输入图像描述
(图片来自:http://gameonaut.com/wordpress/2011/11/flixel-demo-creating-animated-and-rotated-sprites-from-an-un-rotated-animated-images/

在此输入图像描述
(图片来自:http://windowsphone7developerguide.blograby.com/more-sprite-transforms-rotation-and-scaling/

Angle您从 Box2d 获得的值以弧度为单位。使用 build int 函数RadToDeg获取 0-360 度的角度。

Canvas.FillTextF('A:' + FloatToStr(Body.Angle, 2),               140, 60+(i*12), MAX_INT);
Canvas.FillTextF('A:' + FloatToStr(RadToDeg(Body.Angle), 0),     220, 60+(i*12), MAX_INT);
Run Code Online (Sandbox Code Playgroud)

角度可以超过 360 度,而您只想知道 0 到 360 之间的值。因此使用 MOD:

 SpriteAngle := Round(RadToDeg(Body.Angle)) MOD 360;
Run Code Online (Sandbox Code Playgroud)

此外,角度可以是负数,所以你需要-1变成359

 if SpriteAngle < 0 then
    SpriteAngle := SpriteAngle + 360;
Run Code Online (Sandbox Code Playgroud)

最后。由于 360 度与 0 度相同,因此您需要使用 0:

 if SpriteAngle = 360 then
    SpriteAngle := 0;
Run Code Online (Sandbox Code Playgroud)

现在我们有一个从 0 到 359 度的角度,我们想根据角度选择正确的精灵。如果你的精灵表中有 32 个精灵,那么每个扇区都会有360/32 = 11.25度数。因此,对于第一个扇区(0 到 11.25),我们希望使用精灵 0,对于下一个扇区(11.25 到 22.5),我们将使用第二个精灵,依此类推。通过使用,Trunc我们将获得我们正在寻找的精灵编号。359/11.25 => 31.911 => 31

  FSpriteSheet.Draw(Canvas, X, Y, Trunc(SpriteAngle/11.25)); 
Run Code Online (Sandbox Code Playgroud)

在此屏幕截图中,我使用了本文中的精灵表 ( http://www.codeproject.com/Articles/9012/Rotating-Sprite-Objects-on-DirectDraw-Wrapper-for )。它有101个精灵,而且非常流畅。
(调试数据:i、Body.Position.Y、Body.Angle、RadToDeg(Body.Angle)、最终 0-359 角度、SpriteID)

在此输入图像描述
(点击播放截屏)


编辑2:

关于 X、Y 和使用精灵表后半部分的一些注释...

为了避免混乱,我省略了上一个代码行中的 X 和 Y。

设置 X 和 Y 基本上是:

X := Body.Position.X * CScale;
Y := Body.Position.Y * CScale;
Run Code Online (Sandbox Code Playgroud)

然而!如果您使用 debugdraw 运行此命令,您会注意到Body.Position.XandBody.Position.Y指的是 Box2d 对象的中心,而 whileFSpriteSheet.Draw(Canvas, X, Y, ...指的是左上角。因此,您需要进行细微调整:

X := Round(Body.Position.X * CScale) - FSheet.SpriteHalfWidth;
Y := Round(Body.Position.Y * CScale) - FSheet.SpriteHalfHeight;
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述 在此输入图像描述


如何从精灵表的后半部分中挑选精灵?

嗯,这很简单;-)

如果要使用后半部分的图像,则需要从第二组中的第一个精灵开始从 0 索引计数。每组有 112 张图像。第一组 = 0..111,第二组 = 112..223。因此,当您想达到第一组时,请使用0 + SpriteId. 当您想从第二组中选取精灵时,请使用112 + SpriteId。如果您有更多套,依此类推。

我的示例中,我为每隔一个对象使用第二组。通过使用i MOD 2,每个奇数都将是 1,每个偶数都将是 0。

因此,此代码将导致每个偶数为 0,每个奇数为 112:

SpriteSetStart := (i MOD 2) * 112;
Run Code Online (Sandbox Code Playgroud)

然后我们添加对 sprite id 的引用。在我的示例中,有 101 个精灵(以及 11 个空白精灵),每个精灵将覆盖 3.564 度的扇区。360/101 => 3.564。

SpriteId := Trunc(SpriteAngle/3.564);
Run Code Online (Sandbox Code Playgroud)

最后:

FSpriteSheet.Draw(Canvas, X, Y, SpriteSetStart + SpriteId); 
Run Code Online (Sandbox Code Playgroud)