Предотвратить наложение видеоклипа
Я довольно новичок в Action Script, так со мной. Я создаю заставку, которая требует, чтобы видеоклип загружался на сцену в произвольной позиции в зависимости от размера экрана, а затем исчезал (у меня есть вся анимация в видеоклипе в качестве анимации).
Я столкнулся с препятствием и не могу понять, как предотвратить наложение видеоклипов друг на друга. Во всяком случае, я бы хотел, чтобы они появились в другом случайном месте, которое не вызывает перекрытия.
Вот весь код моего проекта:
stop();
import flash.display.MovieClip;
import flash.utils.Timer;
import flash.events.TimerEvent;
import flash.events.Event;
import flash.display.Stage;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.Event;
var greystoneLogos:Array = new Array ;
var countTimeArray:Array = new Array ;
var previousLogos:Array = new Array ;
var xpoint:int;
var ypoint:int;
function getNewSymbols()
{
previousLogos = new Array ;
greystoneLogos = new Array ;
var i:int;
for (i=0; i < 3; i++)
{
greystoneLogos[i] = new GreystoneLogo1();
greystoneLogos[i].width = 100;
greystoneLogos[i].height = 60;
addSymbolToStage(greystoneLogos[i],i*2000);
}
}
getNewSymbols();
function addSymbolToStage(currentLogo:MovieClip,waitTime:int)
{
var i3:int;
var i4:int;
var logoBoundaries:Array = new Array()
var XandY:Array = new Array()
for (i3=0; i3 < greystoneLogos.length; i3++)
{
if (greystoneLogos[i3] !== currentLogo)
{
xpoint = randomRange(this.stage.stageWidth - (currentLogo.width * 4.8));
ypoint = randomRange(this.stage.stageHeight - (currentLogo.height * 6.9));
logoBoundaries = getOffDimensions(currentLogo)
for (i4=0; i4 < logoBoundaries.length; i4++)
{
XandY = logoBoundaries[i4].split(":")
while ((xpoint <= (Number(XandY[0]) + Number(currentLogo.width * 4.8)) && xpoint >= (Number(XandY[0]) - Number(currentLogo.width * 4.8))) && (ypoint <= (Number(XandY[1]) + Number(currentLogo.height * 6.9)) && ypoint >= (Number(XandY[1]) - Number(currentLogo.height * 6.9)))){
xpoint = randomRange(this.stage.stageWidth - (currentLogo.width * 4.8));
trace(XandY[0] + " And " + (Number(currentLogo.width * 4.8)))
trace(xpoint + " And " + (Number(XandY[0]) + Number(currentLogo.width * 4.8)))
ypoint = randomRange(this.stage.stageHeight - (currentLogo.height * 6.9));
}
}
}
else
{
continue;
}
}
previousLogos.push(currentLogo);
currentLogo.x = xpoint;
currentLogo.y = ypoint;
stage.addChild(currentLogo);
currentLogo.gotoAndStop(1);
var countTime:Timer = new Timer(waitTime,1);
countTime.addEventListener(TimerEvent.TIMER, function(){
currentLogo.gotoAndPlay(1);
currentLogo.addFrameScript ( currentLogo.totalFrames - 1 , function(){
currentLogo.stop()
stage.removeChild(currentLogo)
if(stage.numChildren <= 1){
getNewSymbols();
}
}) ;
});
countTime.start();
}
function getOffDimensions(currentLogo:MovieClip){
var i3:int;
var tempArr:Array = new Array()
for (i3=0; i3 < greystoneLogos.length; i3++)
{
if (greystoneLogos[i3] !== currentLogo){
tempArr[i3]=greystoneLogos[i3].x +":"+ greystoneLogos[i3].y
}
}
return tempArr
}
function randomRange(max:Number, min:Number = 0):Number
{
return Math.random() * (max - min) + min;
}
Голая со мной в коде.. это была довольно быстрая и грязная работа.
Также может быть несколько неиспользованных переменных из нескольких вещей, которые я пробовал.
Код, который я разместил, заставит фрагмент ролика появляться в произвольном месте на основе последнего фрагмента ролика, который появился. Допустим, у нас есть 3 видеоклипа (пользователь сможет изменить количество отображаемых клипов): 1 отображается с 0,0, другой с 400 400, а последний - с 10,10, потому что у меня нет способа сохранить предыдущие значения для сравнения в цикле while.
Я надеюсь, что это проясняет это немного больше
РЕДАКТИРОВАТЬ:
Основываясь на функции, показанной ниже, я добавил это:
for (i3=0; i3 < greystoneLogos.length; i3++)
{
if (greystoneLogos[i3] !== currentLogo && greystoneLogos[i3] != null)
{
while(currentLogo.hitTestObject(greystoneLogos[i3]) == true){
xpoint = randomRange(this.stage.stageWidth - (currentLogo.width));
ypoint = randomRange(this.stage.stageHeight - (currentLogo.height));
i3 = 0
}
}else{
continue;
}
}
Что приводит к довольно плохой петле, а также к тому, что логотип все еще накладывается друг на друга
2 ответа
Самый быстрый способ, который я могу решить для решения этой проблемы, - это провести тест на попадание ( http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/display/DisplayObject.html) в новый MovieClip и, если он возвращает true, снова запустите код размещения
Хорошо, вот реализация этого самого быстрого способа. Вы можете отслеживать свой текущий displayObject с помощью свойства.numChildren. Вам даже не нужен массив ваших логотипов или вещей. Допустим, у вас есть функция, которая добавляет новый мувиклип на ваш экран. Он знает, сколько клипов вы можете иметь (MovieClipDummy - это просто мой тестовый класс - он рисует круг с указанным радиусом. Он должен быть заменен вашими объектами).
private function addAnotherMovieClip(): void {
if (_currentDummmiesCount < _dummmiesCount) {
var newDummy: MovieClipDummy = new MovieClipDummy(90);
addChild(newDummy);
//If we get a stackru error (see below)
//we just remove our object from the screen as it will most likely just won't fit
if (checkForEmptySpace(newDummy) != "") {
removeChild(newDummy);
return;
}
} else {
//Do nothing or do something
}
}
Он вызывает другую функцию, checkForEmptySpace, которая пытается разместить ваш мувиклип так, чтобы он не перекрывался с другими объектами. Вот:
private function checkForEmptySpace(newClip: Sprite): String {
//you should store your screen width somewhere.
//you can also call stage.stageWidth instead, but first make sure that you
//always have a link to the stage or it will throw an error
newClip.x = Math.random() * _screenWidth;
newClip.y = Math.random() * _screenHeight;
//===========================
//Important part - we try to check all the present children of our container
//numChildren is a property of the DisplayObjectContainer
for (var i: int; i < numChildren; i++) {
//We need a try here because we will get a Stackru error if there's no empty space left
try {
//We need to check if our current display object, received with getChildAt()
//is not the same as the one we've just added to the screen
//And if our new object intersects with ANY other object on the stage - we
//call THIS function once again.
//We do recursion because we can easily catch an error and remove this object from
//the screen
if (newClip != getChildAt(i) && newClip.hitTestObject(getChildAt(i))) {
//If our recursive function returns an error - we should pass it further
if (checkForEmptySpace(newClip) != "") {
return "error";
}
}
//The only error that can go here is stackru error. So when we get one
//we return this error string
} catch (error: Error) {
trace(error);
return "error";
}
}
//We only return this empty string if we don't have stackru error
//so there's possibly no space left for another movieclip
return "";
}
Вы можете сделать это без рекурсии, но вам придется проверять наличие свободного места с другой логикой.
И вы можете сделать это более "профессионально" с помощью дополнения Минковского. Вам следует подумать о сохранении массива "граничных" точек ваших мувиклипов (скажем, каждый мувиклип представляет собой прямоугольник), и когда вы добавляете новый объект на экран, вы вычисляете это дополнение Минковского. Он будет иметь несколько "свободных" мест на вашем экране, которые представляют любые возможные координаты вашего нового мувиклипа. Довольно интересно реализовать что-то подобное, потому что точность будет феноменальной. Но если у вас нет времени - просто используйте эту рекурсивную функцию размещения