PDA

Просмотр полной версии : Алгоритмы Коллизии и оптимизация кода


fd96
18.12.2013, 21:22
Господа, тема избита, вопросы обсуждались тысячи раз здесь и даже при моём участии, но вот , снова столкнулся, снова прошу помощи и это спустя почти 1.5 года, прошу подсказок и вменяемой критики, ибо знаю о своей криворукости.

Ближе к делу.
Есть готовый код, работает, но не так, как хотелось бы - вина всему - проверка коллизий, проверка в циклах с тремя вложенными. Код прилагаю, надеюсь на помощь, есть ориентир, что должно выйти в итоге. Не поленитесь, пожалуйста - прочитайте код и предложите выход. Кода 250 строк. Коллизию проверяю попиксельно ибо реакция на отклик важна до миллиметра. Мой ориентир - http://flukedude.com/theimpossiblegame/?lang=ru/ тут флешка с игрой , кубик скачет :D У меня впрочем - то всё хорошо , но отклик на прыжок слабоват очень...

Сам Код...
<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
width="800" height="600" frameRate="65" name="scroll" keyDown="keys(event)">
<fx:Style source="imp.css"/>
<fx:Declarations>
<!-- Разместить невизуальные элементы (например, службы или объекты значений) -->
</fx:Declarations>
<fx:Script>
<![CDATA[
import mx.controls.Alert;
import mx.events.FlexEvent;
public var _maxHeight:Number;
public var _returnValue:Boolean;
public var rec:Rectangle = new Rectangle;
public var i:int = 1;
public var level:Array;
public var jump:Boolean=false;
public var jump2:Boolean=false;
public var jumpcost:int=90;
public var jumped:int=0;
public var sx:int;
public var sy:int;
public var speed:int=6;
public var ani:int=0;
public var anim:Array = ["player1.png","player3.png","player5.png","player.png"];
public var col:Boolean = false;
public function keys(event:KeyboardEvent):void
{
if(event.keyCode == Keyboard.R)
{
if((jump==false)&&(jump2==false)&&(_returnValue==true))
{
jump=true;
}
}
if(event.keyCode == Keyboard.Q)
{
player.source="pole.png";
}
if(event.keyCode == Keyboard.W)
{
player.source="player.png";
}
}
public function onbutton(event:Event):void
{
base.addEventListener(Event.ENTER_FRAME, framed);
}
public function start(event:Event):void
{
rec.x=0;
rec.y=0;
rec.width=800;
rec.height=600;
level=base.getChildren();
base.focusEnabled=true;
this.setFocus();
sy=player.y;
sx=player.x;
player.load("player.png");
level=base.getChildren();


}

public function framed(event:Event):void
{
shader.x=player.x-107;
shader1.x=player.x-137;
based.scrollRect=rec;
var py:int;
i=level.length-1;
var l:int=0;
if((jump==true)||(jump2==true))
{

}
i=level.length-1;
if((jump==true)&&(jump2==false))
{
player.y=player.y-8;
jumped=jumped+8;
if(jumped>=jumpcost)
{
jump2=true;
jump=false;
jumped = 0;
}
}
py=player.y;
if(!jump)
{
player.y=player.y+5;
}
for(i;i>-1;i--)
{
complex(player,level[i])
if((_returnValue==false)&&(jumped>=jumpcost))
{
jump2=true;
break;
}
else if(_returnValue==true)
{
test.text="true";
player.y=py;
l=0;
for(l;l<5;l++)
{
complex(player,level[i])
if(_returnValue==false)
{
player.y++;
break;
}
else
{
if((player.x+60>=level[i].x)&&(level[i].name!="floor")&&(player.y>=level[i].y-58)&&(level[i].name!="ice"))
{
player.x=sx;
player.y=sy;
}
if((player.y>=level[i].y+level[i].height)||(level[i].name=="spike")||(level[i].name=="lava"))
{
player.x=sx;
player.y=sy;
}
if(level[i].name=="ice")
{
speed=8;
}
if(level[i].name!="ice")
{
speed=7;
}
break;
}
}
break;
}

}
player.x=player.x+speed;
rec.x=player.x-70;
}
public function complex(clip1:DisplayObjectContainer, clip2:DisplayObjectContainer):Boolean
{


var _onePoint:Point;
var _twoPoint:Point;
var _tp:Point;
var _fp:Point;

var _oneRectangle:Rectangle;
var _twoRectangle:Rectangle;

var _oneClipBmpData:BitmapData;
var _twoClipBmpData:BitmapData;

var _oneOffset:Matrix;
var _twoOffset:Matrix;
var _maxWidth:Number;


_oneRectangle = clip2.getBounds(clip2);
_twoRectangle = clip1.getBounds(clip1);
_oneOffset = clip1.transform.matrix;
_oneOffset.tx = clip1.x - clip2.x;
_oneOffset.ty = clip1.y - clip2.y;
_twoOffset = clip2.transform.matrix;
_twoOffset.tx = clip2.x - clip2.x;
_twoOffset.ty = clip2.y - clip2.y;
_maxWidth = Math.max(_oneRectangle.width, _twoRectangle.width);
_maxHeight = Math.max(_oneRectangle.height, _twoRectangle.height);

_twoClipBmpData = new BitmapData(_maxWidth, _maxHeight, true, 0);



_oneClipBmpData = new BitmapData(_maxWidth, _maxHeight, true, 0);

_twoClipBmpData.draw(clip1, _oneOffset);
_oneClipBmpData.draw(clip2, _twoOffset);

_onePoint = new Point(_oneRectangle.x, _oneRectangle.y);
_twoPoint = new Point(_twoRectangle.x, _twoRectangle.y);
_tp = new Point(_oneRectangle.x+_oneRectangle.width, _oneRectangle.y+_oneRectangle.height);
_fp = new Point(_twoRectangle.x+_twoRectangle.width, _twoRectangle.y+_twoRectangle.height);

if((_oneClipBmpData.hitTest(_onePoint, 255, _twoClipBmpData, _twoPoint, 255))||(_oneClipBmpData.hitTest(_tp, 255, _twoClipBmpData, _fp, 255)))
{
_returnValue = true;
jump=false;
jumped=0;
jump2=false;
}
else
{
_returnValue = false;
}

_twoClipBmpData.dispose();
_oneClipBmpData.dispose();

return _returnValue;
}

]]>
</fx:Script>
<s:BorderContainer x="0" y="0" width="1500" height="600" backgroundColor="#F5FB91"
contentBackgroundColor="#B4B4B4" addedToStage="start(event)" id="based">
<mx:Canvas id="base" x="0" y="0" width="8000" height="600" backgroundColor="#EAEAEA">

<mx:Canvas x="0" y="382" width="8000" height="127" backgroundColor="#878787" name="floor">
</mx:Canvas>
<s:Button x="71" y="9" label="Кнопка" buttonDown="onbutton(event)"/>
<s:Label x="167" y="18" id="test"/>
<s:Image x="1500" y="343" width="40" height="40" scaleMode="stretch" source="spike.png" smooth="true" smoothingQuality="high" name="spike" />
<s:Image x="2200" y="343" width="40" height="40" scaleMode="stretch" source="spike.png" smooth="true" smoothingQuality="high" name="spike" />
<s:Image x="2500" y="343" width="40" height="40" scaleMode="stretch" source="spike.png" smooth="true" smoothingQuality="high" name="spike" />
<s:Image x="3000" y="343" width="40" height="40" scaleMode="stretch" source="spike.png" smooth="true" smoothingQuality="high" name="spike" />
<s:Image x="3400" y="343" width="40" height="40" scaleMode="stretch" source="spike.png" smooth="true" smoothingQuality="high" name="spike" />
<s:Image x="3440" y="343" width="40" height="40" scaleMode="stretch" source="spike.png" smooth="true" smoothingQuality="high" name="spike" />
<s:Image x="3590" y="343" width="40" height="40" scaleMode="stretch" source="spike.png" smooth="true" smoothingQuality="high" name="spike" />
<s:Image x="3820" y="320" width="40" height="40" scaleMode="stretch" source="spike1.png" smooth="true" smoothingQuality="high" name="spike" />
<s:Image x="3860" y="320" width="40" height="40" scaleMode="stretch" source="spike1.png" smooth="true" smoothingQuality="high" name="spike" />
<s:Image x="3900" y="320" width="40" height="40" scaleMode="stretch" source="spike1.png" smooth="true" smoothingQuality="high" name="spike" />
<s:Image x="4100" y="343" width="40" height="40" scaleMode="stretch" source="spike.png" smooth="true" smoothingQuality="high" name="spike" />
<s:Image x="800" y="343" width="40" height="40" scaleMode="stretch" source="cube.png" smooth="true" smoothingQuality="high"/>
<s:Image x="840" y="368" width="160" height="15" scaleMode="stretch" source="lava.png" smooth="true" smoothingQuality="high" name="lava"/>
<s:Image x="2240" y="377" width="260" height="15" scaleMode="stretch" source="ice.png" smooth="true" smoothingQuality="high" name="ice"/>
<s:Image x="1000" y="343" width="40" height="40" scaleMode="stretch" source="cube.png" smooth="true" smoothingQuality="high"/>
<s:Image x="1200" y="343" width="40" height="40" scaleMode="stretch" source="cube.png" smooth="true" smoothingQuality="high"/>
<s:Image x="3820" y="263" width="40" height="40" scaleMode="stretch" source="cube.png" smooth="true" smoothingQuality="high"/>
<s:Image x="3900" y="263" width="40" height="40" scaleMode="stretch" source="cube.png" smooth="true" smoothingQuality="high"/>

</mx:Canvas>
<s:BorderContainer id="shader" x="0" y="0" width="111" height="601" backgroundAlpha="0.5"
backgroundColor="#EFEFEF" borderVisible="false" borderWeight="0">
</s:BorderContainer>
<s:BorderContainer id="shader1" x="0" y="0" width="111" height="601" backgroundAlpha="0.7"
backgroundColor="#EFEFEF" borderVisible="false" borderWeight="0">
</s:BorderContainer>
<mx:Image id="player" x="38" y="247" width="80" height="80" />
</s:BorderContainer>
</s:WindowedApplication>

MikroAcse
18.12.2013, 23:54
Удивительно, делать игру на флексе.
А так, мне кажется, что Вам больше подойдет какой-нибудь движок, например Nape.
Так как попиксельная проверка занимает много процессорного времени.

fd96
19.12.2013, 00:43
Да, флекс, да странно, но с другой стороны больше свободы - меньше твинов - хардкор...
Если вы смотрели пример - к чему я стремлюсь, то понимаете, что коллизии попиксельно просто самый подходящий выход для меня - ибо каждый пиксель важен.

Я прошу подсказать варианты проверки коллизий методами быстрее этого, желательно примеры.

На данный момент у меня только одна мысль - проверять коллизию только под маской прозрачной в зоне досягаемости куба. Создать маску прозрачную и через неё добавлять и удалять в массив проверки элементы дочерние спрайта base.

Намного ли это уменьшит время процессорного отклика?

EDIT:

Есть ещё идея - просчитывать от центра куба вектор до ближайшей цели и когда длинна вектора < пол куба то коллизия true.
но в таком случае, что делать с полом и насколько это рентабельно в плане ресурсоёмкости, подскажите же , гуру, я уже рыдаю.

MikroAcse
19.12.2013, 00:51
ибо каждый пиксель важен
Так физический движок использует формулы тригонометрические для быстрого вычисления столкновения фигур любого типа.
Работать будет в *очень много раз* быстрее, при этом качество будет таким же, даже лучше.

Есть ещё идея - просчитывать от центра куба вектор до ближайшей цели и когда длинна вектора < пол куба то коллизия true.
но в таком случае, что делать с полом и насколько это рентабельно в плане ресурсоёмкости, подскажите же , гуру, я уже рыдаю.
Вот примерно такой подход используется в Nape/Box2D, и это в *очень много раз* быстрее, чем попиксельная проверка.
Правда в Nape/Box2D это еще быстрее выходит.

fd96
19.12.2013, 01:17
Насчёт формул тригонометрии, подскажите, в каком направлении копать. пожалуйста?

А на счёт векторов да, можно, но как узнать в случае с пирамидой в каком месте я её касаюсь? Однако вопрос... Учитывая, что пирамида - PNG файл...

Подскажите алгоритм вычислений, если не трудно. И точно ли эти методы будут занимать меньше времени ибо кода будет значимо больше.

MikroAcse
19.12.2013, 01:36
Не выдумывайте велосипедов, используйте готовые движки, советую Nape.
А если лень разбираться - Citrus Engine.
Благо Google есть.

fd96
19.12.2013, 01:38
Весь интерес ведь в том, чтобы сделать самому, да и в движке я рыть буду дольше, чем в тригонометрии, не уж то никто не занимался коллизиями так плотно, все использовали движки?

EDIT:

И ещё кое что, движок привертеть к FLEX... Тот ещё изврат я так полагаю, оно того стоит? =)

Akopalipsis
19.12.2013, 01:53
И точно ли эти методы будут занимать меньше времени ибо кода будет значимо больше.
У меня схожая картина, мне всё хочется сделать самому, ну или попробовать, в плане банального саморазвития. И вот что скажу - нужно задумываться, стоит ли данная самодеятельность того, чего не одному не удавалось вернуть - ВРЕМЯ! я сейчас завис над ковырянием анимаций. Но как я рассуждал думая об этом - первым что я вынес, это то, что я плохо понимаю математику и это велосипедство пойдет мне на пользу. Так же я думал, что быстрее анимации не чего нет и этот опыт пойдет мне на пользу, его и в дальнейшем можно будет применять. И на деле так оно все и оказалось. Узнал много нового и даже то, о чем и не подозревал. Но если бы я знал математику и у меня был бы опыт, то вот честно скажу - оно не нужно. Ещё чуть - чуть и я закончу, но это будет, скорее всего, последнее что я велосипедничал. А то я чувствую, так и десять лет пройдет, а я так и буду только ковыряться.
И по теме - больше кода, чаще всего и ускорят работу.
И если Вы хотите лучшее - скачайте Nape, изучите его, пусть хоть несколько месяцев пройдет, а потом сядете и сделаете либо так же, либо так же. Но если Вы знаете математику, то зачем Вам это надо?

GBee
19.12.2013, 02:21
В одной игре проверку делал через getPixel. Там птичка летела по туннелю. И каждый момент времени проверялось несколько точек у птички. Если в хоть одной точке туннель не прозрачен, то столкновение.

ChuwY
19.12.2013, 02:53
Если все хотите сами сделать, то вот отличный источник (http://noregret.org/tutor/n/).

fd96
19.12.2013, 03:24
спасибо, отличный ресурс... Заинтересовал метод с пикселами, он проще чем пересчёт по векторам плоскости и можно работать не имея массивов вообще,хорошая идея, можно увидеть пример такой проверки, пожалуйста? =)

Добавлено через 4 минуты
Но если Вы знаете математику, то зачем Вам это надо?

Это нужно просто ради того, чтоб не забыть методы геометрического анализа и алгоритмирования,
из того, что у меня вышло я уже понимаю, что руки мои стали кривыми за год без AS3 и я обленился настолько, что не хочу писать даже 2 лишних строки кода, даже если это банальные формулы сложения векторов и определение длинны вектора, думаю это принесёт пользу, вернёт меня к жизни как минимум, а то совсем обленился...

GBee
19.12.2013, 16:17
Заинтересовал метод с пикселами, он проще чем пересчёт по векторам плоскости и можно работать не имея массивов вообще,хорошая идея, можно увидеть пример такой проверки, пожалуйста? =)
/*pt проверяемая точка птички*/
public function checkCollision(pt:Point):Boolean
{
var bd:BitmapData = new BitmapData(1, 1);
var m:Matrix = new Matrix();
m.tx = -pt.x + _fon.x; //тут у вас свои расчеты будут.
m.ty = -pt.y; //тут тоже
bd.draw(_fon, m);
var color:uint = bd.getPixel(0, 0);
bd.dispose();
return color == 16777215; //проверка на непрозрачность, тут надо поглядеть, какая точка считается "непрозрачной". Я мышкой водил искал.
}


if (_tunnel.checkCollision(fwd) || _tunnel.checkCollision(top) || _tunnel.checkCollision(bottom))
{
boom();
}

Есть общий контейнер, он содержит спрайты _tunnel и _bird. В _tunnel генерится лабиринт и анимация его движения, поэтому в матрице тх высчитывается через _fon - спрайт, который циклично двигается и прыгает, а-ля байда сверху в печатной машинке.
fwd, top, bottom это точки сенсоры на птичке.
Мы создаем битмапу 1 на 1 и отрисовываем соответствующую точку тоннеля в нее. Тут вполне можно тоже улучшить алгоритм, рисуя сразу массив точек и проверяя. Но мне хватило с лихвой.

Котяра
19.12.2013, 18:28
Коллизии желательно проверять в несколько проходов.
1.Если много объектов - проверяем по сетке (или по дереву квадрантов).
2. Если мало объектов - проверяем по баундсу (или по баундсу в пределах одной ячейки сетки)
3. Попиксельно.

вот библиотека работающая только с коллизиями
https://github.com/martinkallman/collision-as3
Хорошая статья для самых маленьких)
http://flashgameblogs.ru/blog/actionscript/381.html

fd96
20.12.2013, 00:52
QuadTree хорош, я знаю, хорош, но не для меня =( объекты должны двигаться с очень высокими скоростями...

По баундсу проверять тоже нельзя мне надо коллизию прямо по форме фигуры с точностью до микрона... плохо....

ПОПИКСЕЛЬНО, ДА , СПАСИБО ЗА СОВЕТ, в самом первом сообщении я ведь писал, что сделал попиксельно, но ОНА ОЧЕНЬ ТОРМОЗИТ, много процессорного времени жрёт...

GBee, У вас в примере Tunel это просто картинка,а могу ли я проверить пиксель только для детей определённого контейнера не учитывая нижние контейнеры?

MikroAcse
20.12.2013, 01:10
За это время вы бы уже изучили и использовали Nape.

fd96
20.12.2013, 01:21
Я уже изучил, но хочу сделать сам ибо сложно и интересно, меня интересует не столько результат, сколько процесс и его сложности, и по-моему Box2D интереснее как сам движок 2D игры. Но у Nape есть свои плюсы, просто я тот ещё консерватор =)

P.S. Всем спасибо за советы, действительно полезные.

GBee
20.12.2013, 02:58
GBee, У вас в примере Tunel это просто картинка,а могу ли я проверить пиксель только для детей определённого контейнера не учитывая нижние контейнеры?
Да что угодно, если это можно в битмап отрисовать, главное точное положение найти.

MikroAcse
20.12.2013, 11:18
Nape2D как раз прекрасный физический движок для игры.
Плюс он быстрее и проще, чем Box2D.

Hauts
20.12.2013, 12:14
MikroAcse, не надоело?

MikroAcse
20.12.2013, 12:19
MikroAcse, не надоело?
Неа :) Может, и добьюсь своего.

GBee
20.12.2013, 15:40
Неа Может, и добьюсь своего.
Третьего плюса? :о)

MikroAcse
20.12.2013, 15:54
Третьего плюса? :о)
А я и не развожу флейм.
Я просто говорю, что хватит писать костыли, лучше пользуйтесь движком.
И я советую Nape (можно +Citrus).

Котяра
20.12.2013, 16:27
По баундсу проверять тоже нельзя мне надо коллизию прямо по форме фигуры с точностью до микрона... плохо....
ПОПИКСЕЛЬНО, ДА , СПАСИБО ЗА СОВЕТ, в самом первом сообщении я ведь писал, что сделал попиксельно, но ОНА ОЧЕНЬ ТОРМОЗИТ, много процессорного времени жрёт...

1.Просто перед тем как проверять попиксельно - надо делать проверку по баундсам и уже если они пересекаются - проверять попиксельно.

2.Попиксельно можно проверять через наложения битмап.
30288
Берём пересечение баундсов - создаём битмапу такого размера копируем альфу 1 объекта в канал R, альфу другого в канал B, потом вызываем http://help.adobe.com/ru_RU/FlashPlatform/reference/actionscript/3/flash/display/BitmapData.html#getColorBoundsRect() для цвета 0xffff00. Если результирующий прямоугольник пустой, значит пересечения альф не было.
Альфа должна быть ff/0 без полупрозрачностей. Если есть полупрозрачности надо предварительно сделать theresold.

Котяра
20.12.2013, 16:30
А я и не развожу флейм.
Я просто говорю, что хватит писать костыли, лучше пользуйтесь движком.
И я советую Nape (можно +Citrus).

Если нужны только проверки на коллизии, зачем забивать гвозди микроскопом?
Да и приятно разобраться в сложном вопросе самостоятельно, тем более, что для конкретной задачи решение может быть на порядки оптимальнее, чем универсальное.

fd96
20.12.2013, 17:35
Если иметь в виду такие баундсы, то я уже делал, прыжок всё равно притормаживает на моменте получение битмапы и пересчёт всех возможных пересечений писелов. наверно я кривой. А на счёт движков и такой простой игры поддерживаю, как гвозди микроскопом забивать.

А можно в битмап дате получить пикселы только определённые, проверять не всю дату, а только четверть или как - то так, по координатам, но не getPixel и hitTest?

Котяра
20.12.2013, 18:05
ну я же написал как проверять без getPixel

MikroAcse
20.12.2013, 18:17
А на счёт движков и такой простой игры поддерживаю, как гвозди микроскопом забивать.
Я не поддерживаю. По-моему, как раз все будет нормально.
Движок не большой, в будущем пригодится.

Котяра
20.12.2013, 20:22
Набросал примерчик
collision.swf

package
{
import flash.display.Bitmap;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.filters.BitmapFilter;
import flash.filters.GlowFilter;

/**
* ...
* @author k0t0vich
*/
public class Main extends Sprite {
static public const GLOWFILTER:BitmapFilter = new GlowFilter(0xFF0000);
private var _hero:Bitmap;
private var _boxes:Array = [];

private var _bitmap:Bitmap;

public function Main():void {
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}

private function init(e:Event = null):void {
removeEventListener(Event.ADDED_TO_STAGE, init);
createElements();
stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
}

private function createElements():void {
for (var i:int = 0; i < 50; i++) {
var box:Bitmap = new Resources.Box();
box.x = int(Math.random()*stage.stageWidth);
box.y = int(Math.random()*stage.stageHeight);
_boxes.push(box);
addChild(box);
}

_hero = new Resources.Hero();
addChild(_hero);
}

private function mouseMoveHandler(e:Event):void {
render();
detectCollision();
}

private function render():void {
_hero.x = mouseX;
_hero.y = mouseY;

var len:uint = _boxes.length;
for (var i:int = 0; i < len; i++) {
var box:Bitmap = _boxes[i];
box.filters = [];
}

// для отображения в углу пересекающейся битмапы
/*if (_bitmap && _bitmap.bitmapData) {
_bitmap.bitmapData.dispose();
_bitmap = null;
}

if (Collision.tmp){
_bitmap = new Bitmap(Collision.tmp);
addChild(_bitmap);
}*/
}

private function detectCollision():void {
var intersects:Array = Collision.detectOneForMore(_hero, _boxes);
var len:uint = intersects.length;
for (var i:int = 0; i < len; i++) {
var box:Bitmap = intersects[i];
box.filters = [GLOWFILTER];
}
}

}

}

package
{
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.BitmapDataChannel;
import flash.geom.Point;
import flash.geom.Rectangle;
/**
* ...
* @author k0t0vich
*/
public class Collision {
static public const ZERO_POINT:Point = new Point();

// для отображения в углу пересекающейся битмапы
//static public var tmp:BitmapData;

static public function detectOneForMore(hero:Bitmap, enemies:Array):Array {
var result:Array = [];
var len:uint = enemies.length;
for (var i:int = 0; i < len; i++) {
var enemy:Bitmap = enemies[i];
if (hero.getBounds(hero.parent).intersects(enemy.getBounds(enemy.parent))) {
if (detectAlphaIntersection(hero, enemy)){
result.push(enemy);
}

}

}
return result;
}


static public function detectAlphaIntersection(hero:Bitmap, enemy:Bitmap):Boolean {

var r:Rectangle = hero.getBounds(hero.parent).intersection(enemy.getBounds(enemy.parent));
if (r.width > 0){
var hRect:Rectangle = new Rectangle(r.x - hero.x, r.y - hero.y, r.width, r.height);
var eRect:Rectangle = new Rectangle(r.x - enemy.x, r.y - enemy.y, r.width, r.height);
trace(hRect);
trace(eRect);

var bmpd:BitmapData = new BitmapData(r.width, r.height, false, 0x00000000);
bmpd.copyChannel(hero.bitmapData, hRect, ZERO_POINT, BitmapDataChannel.ALPHA, BitmapDataChannel.RED);
bmpd.copyChannel(enemy.bitmapData, eRect, ZERO_POINT, BitmapDataChannel.ALPHA, BitmapDataChannel.GREEN);

// для отображения в углу пересекающейся битмапы
//tmp = bmpd;

var alphaIntersectionRectangle:Rectangle = bmpd.getColorBoundsRect(0xFFFFFFFF, 0x00FFFF00, true);
bmpd.dispose();
return alphaIntersectionRectangle.width > 0;
}

return false;
}

}

}

package {
/**
* ...
* @author k0t0vich
*/
public class Resources {
[Embed(source = "../assets/box.png")]
public static const Box:Class;

[Embed(source="../assets/hero.png")]
public static const Hero:Class;

}

}
Тесты на быстродействие сами уж как-нибудь.

FD проект
30290

Hauts
20.12.2013, 20:35
Пример Котяры можно еще очень здорово оптимизировать, если закэшировать bounds у блоков, использовать свою реализацию intersects и использовать одну большую битмапдату для всех проверок (очищая ее, соответственно, перед проверкой).

fd96
20.12.2013, 20:47
Отлично! Именно так, одну большую битмапдату препятствий и к ним проверку через getColor препятствия красить чёрным - свободу - белым, проверять только 6 пикселов можно даже 4 по углам куба. Никаких циклов и массивов, ура ура, совместный разум победил! =)

Котяра
20.12.2013, 20:53
Вот в правом верхнем углу - показ пересечений.
А код - да оптимизировать можно и нужно.
collision.swf

Котяра
20.12.2013, 21:00
Пример Котяры можно еще очень здорово оптимизировать, если закэшировать bounds у блоков, использовать свою реализацию intersects и использовать одну большую битмапдату для всех проверок (очищая ее, соответственно, перед проверкой).Всё зависит от задачи. Я сделал наиболее общий случай.

Hauts
20.12.2013, 21:27
Котяра, да, конечно, я понимаю. Я для ТС написал, на будущее.

Котяра
21.12.2013, 03:42
Отлично! Именно так, одну большую битмапдату препятствий и к ним проверку через getColor препятствия красить чёрным - свободу - белым, проверять только 6 пикселов можно даже 4 по углам куба. Никаких циклов и массивов, ура ура, совместный разум победил! =)

бред какой-то.

samana
21.12.2013, 03:49
Ух ты! Классная вообще идея! Спасибо, Котяра!