Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   [Алгоритмы] Коллизии и оптимизация кода (http://www.flasher.ru/forum/showthread.php?t=205733)

fd96 18.12.2013 21:22

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

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

Сам Код...
Код AS3:

<?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

Если все хотите сами сделать, то вот отличный источник.


Часовой пояс GMT +4, время: 21:48.

Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2024, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.