我想为 Box2D 中的动态对象添加颜色。似乎必须在场景的渲染中分配动态对象的某些属性。我玩过 Box2D 演示,但不知道如何添加颜色(和位图)等属性?
1 回答
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;
例如:
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;
要为各种对象绘制精灵,您应该使用一个TW3SpriteSheets
类来处理它。
将sprite sheet图片作为资源文件添加到工程中,编译时会解压到res文件夹中。
像这样加载图像:
FSpriteSheet := TW3SpriteSheet.Create;
FSpriteSheet.LoadImage('res/MySpriteSheet.png');
并像这样使用图像:
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;
编辑:
在精灵表中,您拥有对象所需的所有旋转。
(图片来自: 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);
角度可以超过360度,你只想知道0到360之间的值。因此使用MOD:
SpriteAngle := Round(RadToDeg(Body.Angle)) MOD 360;
此外,角度可以是负数,因此您需要-1
变成359
:
if SpriteAngle < 0 then
SpriteAngle := SpriteAngle + 360;
最后。由于 360 度与 0 度相同,因此您想使用 0:
if SpriteAngle = 360 then
SpriteAngle := 0;
现在我们有一个从 0 到 359 度的角度,我们想根据这个角度选择正确的精灵。如果您的精灵表中有 32 个精灵,那么360/32 = 11.25
每个扇区都有度数。因此,对于第一个扇区(0 到 11.25),我们想使用 sprite 0,对于下一个扇区(11.25 到 22.5),我们将使用第二个 sprite,依此类推。通过使用Trunc
,我们将获得我们正在寻找的 sprite 编号。359/11.25 => 31.911 => 31
FSpriteSheet.Draw(Canvas, X, Y, Trunc(SpriteAngle/11.25));
在此屏幕截图中,我使用了本文中的精灵表 ( http://www.codeproject.com/Articles/9012/Rotating-Sprite-Objects-on-DirectDraw-Wrapper-for )。它有 101 个精灵,而且非常平滑。
(Debugdata: i, Body.Position.Y, Body.Angle, RadToDeg(Body.Angle), Final 0-359 angle, SpriteID)
编辑2:
关于 X、Y 和使用精灵表后半部分的一些注意事项......
为了避免混乱,我在前面的代码行中省略了 X 和 Y。
设置 X 和 Y 基本上是:
X := Body.Position.X * CScale;
Y := Body.Position.Y * CScale;
然而!如果你用 debugdraw 运行它,你会注意到Body.Position.X
andBody.Position.Y
指的是 Box2d 对象的中心,而FSpriteSheet.Draw(Canvas, X, Y, ...
指的是左上角。因此,您需要进行细微调整:
X := Round(Body.Position.X * CScale) - FSheet.SpriteHalfWidth;
Y := Round(Body.Position.Y * CScale) - FSheet.SpriteHalfHeight;
如何从精灵表的后半部分选择精灵?
好吧,这很容易;-)
如果要使用后半部分的图像,则需要从第二组中的第一个精灵开始以 0 为索引计数。每组有 112 张图像。第一组 = 0..111,第二组 = 112..223。因此,当您想达到第一组时,请使用0 + SpriteId
. 当您想从第二组中挑选精灵时,请使用112 + SpriteId
. 如果你有更多的集合,依此类推。
在我的示例中,我对每个第二个对象使用第二组。通过使用i MOD 2
,每个奇数都为 1,每个偶数都为 0。
因此,此代码将导致每个偶数为 0,每个奇数为 112:
SpriteSetStart := (i MOD 2) * 112;
然后我们添加对精灵 id 的引用。在我的示例中,有 101 个精灵(和 11 个空白精灵),每个精灵将覆盖 3.564 度的扇区。360/101 => 3.564。
SpriteId := Trunc(SpriteAngle/3.564);
最后:
FSpriteSheet.Draw(Canvas, X, Y, SpriteSetStart + SpriteId);