PDA

Просмотр полной версии : Опять затык с хитТест


sinya
04.04.2008, 13:52
Всем привет.

Объясните, пожалуйста, что не так в моем случае. У меня есть мувик bgr, в нем мувик bgrr и aaa. Для aaa написана onEnterFrame ф-ция, которая опускает aaa вниз, пока он не коснется своим центром bgrr. Проблема в том, что при перемещении основного мувика bgr aaa смещается относительно bgrr. Точнее, когда центр aaa уже находится на bgrr, то при перемещении bgr хитТест центра aaa и bgrr иногда выдает false, из-за чего aaa перемещается еще на шаг ниже.
Короче, лучше глянуть: http://flashart.com.ua/1
потрясите мышкой красный круг.

function standBy() {
this.hit = false;
if (bgr.bgrr.hitTest(this._x + bgr._x, this._y + bgr._y, true)==false)
this._y+=6;
trace (this._x);
}
bgr.aaa.onEnterFrame = standBy;
bgr.onMouseDown = function () {this.startDrag();}


исходник тут: http://flashart.com.ua/1/eq.fla

Как мне добиться, чтобы aaa, раз уткнувшись в bgrr, больше не смещалось относительно него при перемещении bgr?

silin
04.04.2008, 14:43
>>чтобы aaa, раз уткнувшись в bgrr, больше не смещалось относительно него при перемещении bgr

не проверять больше ничего:
if (bgr.bgrr.hitTest(this._x + bgr._x, this._y + bgr._y, true)==false) {
this._y+=6;
}else{
delete this.onEnterFrame;
}

sinya
04.04.2008, 14:55
Так нельзя, мне нужно проверять, т.к. bgrr может опуститься ниже, а aaa должно всегда находиться на поверхности bgrr.

olexandr
04.04.2008, 15:07
не было особого желания вникать, но мне показалось, что не до конца продумана логика поведения - ошибка в ней...
но мне кажется, проще всего - убить onEnterFrame после соприкосновения, а после движения bgrr, можно опять же запустить onEnterFrame

sinya
04.04.2008, 16:38
Ааа, ошибка в логике поведения... Понятно...

silin
04.04.2008, 17:28
Так нельзя, мне нужно проверять, т.к. bgrr может опуститься ниже, а aaa должно всегда находиться на поверхности bgrr.
все равно проверять-то уже ничего не надо: засеки где он находится относительно bgrr и двигай вместе с ним
if (bgr.bgrr.hitTest(this._x + bgr._x, this._y + bgr._y, true)==false) {
this._y+=6;
}else{
this.dx=this._x-bgr.bgrr._x;
this.dy=this._y-bgr.bgrr._y;
this.onEnterFrame=function(){
this._x=bgr.bgrr._x+this._dx;
this._y=bgr.bgrr._y+this._dy;
}
}

sinya
04.04.2008, 18:20
Хочу прояснить ситуацию: мне не нужны обходные пути, меня интересует, как сделать, чтоб aaa не смещалась относительно bgrr при перемещении bgr.
Описанная выше ситуация сложилась во время программирования игры. Допустим, aaa - это один персонаж, а bgrr - другой. Так вот персонаж aaa сидит на персонаже bgrr. Если bgrr отойдет в сторону, мне не нужно, чтобы aaa ехал на нем. Мне нужно, чтобы он плавно опустился на освободившееся место.

И вообще, как объяснить то, что я описал выше? Очередная недоработка флэш?

crazyone
04.04.2008, 19:53
Впринципе - вы неправильно понимаете, как работает startDrag(). Хотя это не ваша вина, наверное.
Попробуйте так:
function standBy() {
this.hit = false;
if (bgr.bgrr.hitTest(this._x + bgr._x, this._y + bgr._y, true)==false)
this._y+=6;
}
bgr.aaa.onEnterFrame = standBy;
bgr.onMouseDown = function () {this.drag=true;}
bgr.onMouseMove=function(){if(this.drag){this._x=_xmouse,this._y=_ymouse; updateAfterEvent()}}

Если хотите понять - почему так, обратите внимание на updateAfterEvent.

silin
04.04.2008, 20:11
объяснить внятно трудно, скорее всего дело в том, что пересчет при драге не синхронизирован с enterFrame, поэтому мувик проскакивает в зону с хитТестом, а эта ситуация у тебя никак не обрабатывается..
учесть этот нюанс можно так, например:
function standBy() {
if(!bgr.bgrr.hitTest(this._x + bgr._x, this._y + bgr._y, true)){
this._y+=6;
}else{
while(bgr.bgrr.hitTest(this._x + bgr._x, this._y + bgr._y, true))this._y-=6;
this._y+=6;
}
}
bgr.aaa.onEnterFrame = standBy;
bgr.bgrr.onPress=startDrag;
bgr.bgrr.onRelease=stopDrag;

sinya
04.04.2008, 20:13
2crazyone: да startDrag тут не при чем, так происходит при любом перемещении bgr вверх-вниз.

sinya
08.04.2008, 20:41
Рискну еще раз поднять эту тему, т.к. выход пока не нашел.

2silin: я потестил при маленьком fps. Версия "Пересчет при драге не синхронизирован" не подтверждается ИМХО, т.к. и в прошлом, и в позапрошлом кадре Центр квадратика aaa находился в пределах круга bgrr.
Повторюсь и уточню: смещение aaa вниз происходит не только при драге, но при любом движении всей системы bgr вверх.

silin
08.04.2008, 21:07
а фпс не причем, просто пересчет координат при драге происходит раньше (или позже), чем манипуляции в ентерФрэйм, отсюда и возможность 'проскока' мувика внутрь, отставание и т.п.
если расчет всех перемещений положить в один обработчик, то все работает строго как напишем:
import flash.geom.Point;

var dragPoint:Point;

bgr.onPress = function() {
dragPoint = new Point(_xmouse, _ymouse);
}

bgr.onRelease = function() {
dragPoint = null;
}

function onEnterFrame() {
//падаем мувик
if (!bgr.bgrr.hitTest(bgr.aaa._x + bgr._x, bgr.aaa._y + bgr._y, true)) {
bgr.aaa._y+=6;
}
//аналог драга
if (dragPoint) {
bgr._x += _xmouse - dragPoint.x;
bgr._y += _ymouse - dragPoint.y;
dragPoint.x = _xmouse;
dragPoint.y = _ymouse;
}
}

sinya
08.04.2008, 23:10
Так "проскок" мувика внутрь не вызовет смещения вниз, смещение вызывается "выскакиванием из". А такого произойти не может, поскольку движение идет вверх. Да, все в одном обработчике - помогает, но для моего случая недопустимо.

silin
09.04.2008, 00:47
больше помочь нечем, заклинания типа "такого произойти не может" не помогут - раз происходит, значит это надо просто учитывать..
зы
"недопустимо" это слишком категорично: варианты всегда есть.., к тому же вовсе необязательно чтобы все было именно в одном обработчике, можно и в разных, но вызываемых по ентерФрэйм..

sinya
09.04.2008, 14:33
Самое смешное, что если мы напишем общий onEnterFrame для всего ролика и в нем будем двигать bgr вверх-вниз, то проскакиваний не будет. А если написать onEnterFrame для какого-нибудь левого мувика и из него двигать bgr, то будет проскакивать. :wacko:

crazyone
10.04.2008, 16:46
Юз updateAfterEvent() после изменения координат.
хиттест, насколько я знаю, работает по отрисованным объектам. Т.е. - вы сместили клип, его координаты поменялись, а хиттест выдает по старым данным.
А вот это ваше "Самое смешное" объясняется тем, в какой очередности обрабатываются события. Флэш-то все обрабатывает по очереди. И перерисовывать все после каждого события - нет смысла.
Событийная модель - она всего лишь модель, вычисления остаются линейными, ага.

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

sinya
10.04.2008, 17:46
Не знаю, почему вы не решили проблемму, если приведенный мной код вполне ее решает, в нем даже менять ничего не надо.

Да потому что в реальной задаче, где мне это нужно, драга нет. bgr перемещается из onEnterFrame другого клипа. А updateAfterEvent(), как я понял, с ним не работает:

This function works only with certain Mouse and MovieClip handlers: the mouseDown, mouseUp, mouseMove, keyDown and keyUp handlers for the Mouse class; the onMouseMove, onMouseDown, onMouseUp, onKeyDown, and onKeyUp handlers for the MovieClip class.

В любом случае, проблему решил, всем спасибо.