Добавляйте цвета к объектам Box2D в Smart Mobile Studio

Я хочу добавить цвета к динамическим объектам в Box2D. Кажется, что некоторые свойства динамических объектов должны быть назначены при рендеринге сцены. Я играл с демо Box2D, но не могу понять, как добавить свойства, такие как цвета (и растровые изображения)?

1 ответ

Решение

Демонстрация Box2d, поставляемая с SmartMS, использует функцию "DebugDraw" Box2d. Эта функция просто рисует представление объекта с некоторыми внутренними цветами для "статического объекта", "движущегося объекта" и "неподвижного объекта". Я на самом деле не уверен, если это можно переопределить...

Что вам нужно сделать, это заменить FWorld.DrawDebugDataPaintView метод) с пользовательской картиной, которую вы хотели бы использовать.

Вы можете пройти весь объект следующим образом:

  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 класс, чтобы справиться с этим.

Добавьте изображение спрайт-листа в файл ресурсов в проект, и оно будет извлечено в папку 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) мы хотели бы использовать спрайт 0, для следующего сектора (от 11,25 до 22,5) мы бы использовали второй спрайт и т. Д. Используя Trunc мы получим номер спрайта, который мы ищем. 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 спрайт, и это очень гладко.
(Отладочные данные: 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;

Тем не мение! Если вы запустите это с помощью debugdraw, вы заметите, что Body.Position.X а также Body.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;

Затем мы добавляем ссылку на идентификатор спрайта. В моем примере с 101 спрайтом (и 11 пустыми спайтами) каждый спрайт будет покрывать сектор 3,564 градуса. 360/101 => 3,564.

SpriteId := Trunc(SpriteAngle/3.564);

В заключение:

FSpriteSheet.Draw(Canvas, X, Y, SpriteSetStart + SpriteId); 
Другие вопросы по тегам