Своя гравитация для каждого тела в Box2d

Добрый вечер.
Это довольно короткий пост, потому я сначала поместил его в «Персональные».

Я только что добавил себе возможность применять к каждому телу свою статическую (только направление, нет притяжения к конкретной точке) гравитацию. Это занимает около минуты.
Решил выложить на случай, если кому-нибудь понадобится.

Итак, мы отредактируем 2 класса бокса, а именно:
Box2D\Dynamics\b2Island.as
Box2D\Dynamics\b2Body.as

В тело мы добавляем 2 переменные, одна из которых будет хранить саму гравитацию, а другая будет флагом, говорящим движку изменена-ли гравитация.
Следующее можно добавить в любое место b2Body.as
b2internal var m_useCustomGravity:Boolean = false;
	b2internal var m_customGravity:b2Vec2 = null;
	
	/**
	* Set custom Gravity. Use this to change the object's gravity.
	*/
	public function setCustomGravity(newGravity:b2Vec2):void 
	{
		if (newGravity.IsValid())
		{
			//trace("valid");
			m_useCustomGravity = true;
			m_customGravity = newGravity;
		}
		
	}
	
	/**
	* Get custom Gravity. Returns null is nocustom gravity attached.
	*/
	public function getCustomGravity():b2Vec2 
	{
		return m_customGravity;
	}
	
	/**
	* Sets the object to be moved by default gravity.
	*/
	public function clearCustomGravity():void 
	{
		m_useCustomGravity = false;
		m_customGravity = null;
	}


Замечание: Проверка newGravity.IsValid() обязательна, в противном случае можно получить 100% загрузку процессора и неработоспособность физики из-за того, что движок будет пытаться использовать нечисловые значения для рассчёта скорости.

Далее надо вставить всего 2 строки в b2ISland.
if (b.m_useCustomGravity)
gravity = b.m_customGravity;


Вот кусок класса со вставленной проверкой:
public function Solve(step:b2TimeStep, gravity:b2Vec2, allowSleep:Boolean) : void
	{
		var i:int;
		var j:int;
		var b:b2Body;
		var joint:b2Joint;
		
		// Integrate velocities and apply damping.
		for (i = 0; i < m_bodyCount; ++i)
		{
			b = m_bodies[i];
			
			if (b.GetType() != b2Body.b2_dynamicBody)
				continue;
				
			//Modified by Midnight to use custom gravity for each body.
			if (b.m_useCustomGravity)
				gravity = b.m_customGravity;
				
				
			// Integrate velocities.
			//b.m_linearVelocity += step.dt * (gravity + b.m_invMass * b.m_force);
			b.m_linearVelocity.x += step.dt * (gravity.x + b.m_invMass * b.m_force.x);
			b.m_linearVelocity.y += step.dt * (gravity.y + b.m_invMass * b.m_force.y);
			b.m_angularVelocity += step.dt * b.m_invI * b.m_torque;
...Обрыв файла


Да, да, вы правильно заметили, это одна из самых важных частей box2d, будьте осторожны с её редактированием.

На всякий случай использование с объяснением:
//var body:b2Body;
body.setCustomGravity(tempVec);   //Изменяет гравитацию тела
body.clearCustomGravity(tempVec); //Возвращает телу стандартную гравитацию.
body.getCustomGravity(tempVec);   //возвращает B2Vec2 с заданной гравитацией, нулевой указатель, если она не задана.


Это и всё, спасибо за внимание.
Отзывы приветствуются.

PS: Метод является доработанной и более удобной версией этого:
www.emanueleferonato.com/2009/07/17/managing-multiple-gravities-with-box2d/

Комментарии (9)

+2
Я бы просто поставил нулевую гравиацию и в цикле по телам ходил и силу применял. Это проще и вряд ли на производительности скажется. Портов бокса сейчас много, портабельность не помешает. И, кстати, мне казалось, что поддерживается сейчас только тот что на алхимии, а порт на as брошен.
0
Он не только поддерживается, там ещё и производительность больше.
Я всё никак на него перейти не могу…
0
Мне кажется даже существующий проект можно перетянуть, это ж в общем-то тот же движок. Вот стоит ли оно того… я лично был несколько разочарован, когда пробовал, т.е. скорость конечно больше, но как-то не сильно. Я тогда делал веревки длинные и как задуманное не получалось, так и не получалось, а в nape, еще старом, тянуло по производительности. (впрочем тот проект так и не пошел все равно)
0
Если надо будет менять гравитацию, будет уже геморно. А портабельность что, разве проблема в другом порте пару строчек дописать? Китайцев то такие изменения в движке не остановят же)
0
Почему геморно? Заводишь в каждом теле в userData добавляешь поле gravity или иначе как определяешь для каждого тела какая должна быть гравитация (по filter например) и в цикле ко всем силу применяешь. Это с десяток строк кода, и отсутствие необходимости лезть во внутренности движка (а значит отсутствие проблем с обновлением например, хотя вроде бы для бокс2д сейчас не очень актуально это.)

В алхимическом порте что-то в движке поправить — чуть-чуть проблема. Нужно алхимию ставить и научаться его компилировать.
0
Там все просто на самом деле :) Я в своем движке юзаю — полет нормальный.
0
//это я о компиляции под алхимию
0
ну так я пишу — чуть-чуть
0
только что опробовал, спасибо!
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.