|
|
|||||
Регистрация: Aug 2013
Адрес: Москва
Сообщений: 59
|
Параллакс в двух направлениях
Доброго времени суток! Вот уже много времени бьюсь над решением задачи - всё никак не получается + в интернете подходящей информации найти не могу. Суть такова: нужно сделать эффект параллакса, но не только при изменении x и y координат, а ещё и при приближении. Это всё на примере звёздного неба. Когда по x и y таскать надо, всё получается, а вот с глубиной проблемы. Может, кто сталкивался с подобным. Буду очень признателен за совет. Спасибо
|
|
|||||
Регистрация: Aug 2010
Сообщений: 22
|
Зависит от того, как сейчас у вас реализованы параллакс слои. Это спрайты с разной координатой z, или это спрайты, которые лежат на одном уровне, но перемещение спрайта, который должен быть дальше, просто делается медленнее? Если первое, то просто гоняете z, если второе, то создать эффект приближения можно, масштабируя спрайты, которые должны быть ближе к зрителю быстрее, чем те которые должны казаться дальше. Что-то типа:
Это все предположения, но, полагаю, что таким образом вполне можно реализовать то, что нужно. |
|
|||||
Цитата:
|
|
|||||
на вскидку такой вариант:
Дальняя картинка по размеру меньше ближней, соответственно, для дальней картинки масштабирование умножаем на ширинуДальней / ширинуБлижней то есть, допустим ширина передней картинки 2000, а дальней 1000. Что-то типа того. Не проверял, но это первое, что пришло в голову |
|
|||||
Регистрация: Aug 2013
Адрес: Москва
Сообщений: 59
|
Не выходит, к сожалению. Появляется какой-то сдвиг после масштабирования, и как только переходим к перетаскиванию, картинка как бы делает скачок
|
|
|||||
Banned
[+4 24.02.14]
[+4 07.11.13] [+ 13.03.14] Регистрация: Mar 2013
Сообщений: 1,864
|
Создайте столько контейнеров, сколько предполагаете глубин. Наполните их обьектами и положите все в один контейнер, который таскаете мышкой. При клике или при прокрутке мышкой, масштабируйте каждый с разными значениями в EnterFrame. И масштаб должен быть для всех контейнеров, от заданной точки, что то вроде -
public static function scalePoint(target:DisplayObject, scaleX:Number, scaleY:Number, point:Point):void { var dXS:Number = (target.x - point.x) / target.scaleX; var dYS:Number = (target.y - point.y) / target.scaleY; target.scaleX = scaleX; target.scaleY = scaleY; target.x = point.x + dXS * target.scaleX; target.y = point.y + dYS * target.scaleY; } |
|
|||||
Регистрация: Aug 2013
Адрес: Москва
Сообщений: 59
|
А что тогда за точку брать для каждого конкретного слоя?
|
|
|||||
Banned
[+4 24.02.14]
[+4 07.11.13] [+ 13.03.14] Регистрация: Mar 2013
Сообщений: 1,864
|
Цитата:
|
|
|||||
Регистрация: Aug 2013
Адрес: Москва
Сообщений: 59
|
Может, я что-то не так делаю, но всё равно не то. Вот код основного класса Main:
package { import flash.display.Sprite; import flash.geom.Point; public class Main extends Sprite { public var s:Space; public var stars:Vector.<Sprite> = new Vector.<Sprite>; private var s0: Star; private var pre_x:Number=0; private var pre_y:Number=0; public function Main() { fillSky(1000, 800); s = new Space(500 - 700, 400 - 500); //Располагаем посередине. 700x500 - размер swf pre_x = s.x; pre_y = s.y; addChild(s); } private function fillSky(W:int, H:int) { //i - слой, j - звезда в слое //i=0 - слой, самый ближний к наблюдателю //j - звезда, размер выбирается рандомно в пределах слоя (внутри есть свойство dist = дальность {0..100}) var sloy:Sprite; for (var i:int = 0; i < 10; i++) { sloy = new Sprite(); for (var j:int = 0; j < 25; j++) { s0 = new Star(Math.random() * W, Math.random() * H, Math.random() * 10+i*10); sloy.addChild(s0); } stars.push(sloy); addChildAt(sloy,0); } } public function moveSky():void { //рассчитываем насколько сдвинулся Space var dx:Number = s.x-pre_x; var dy:Number = s.y - pre_y; //запоминаем положение Space для вычисления разницы pre_x = s.x; pre_y = s.y; //сдвигаем каждый слой соответственно его глубине for (var i:int = 0; i < stars.length; i++) { stars[i].x += dx / (10 - i +2); //по идее надо делать 10-i, но тогда при i=9 ,будет dx/1, что соответствует слою Space. А нужно сделать всё-таки чуть сзади stars[i].y += dy / (10 - i +2); } } public function scalePoint(target:Sprite, scaleX:Number, scaleY:Number, point:Point):void{ var dXS:Number = (target.x - point.x) / target.scaleX; var dYS:Number = (target.y - point.y) / target.scaleY; target.scaleX = scaleX; target.scaleY = scaleY; target.x = point.x + dXS * target.scaleX; target.y = point.y + dYS * target.scaleY; } public function scaleSky(bigger:Boolean):void { var p:Point; for (var i:int = 0; i < stars.length; i++) { p = new Point(stage.stageWidth/2, stage.stageHeight/2); p = globalToLocal(p); scalePoint(stars[i], s.scaleX * (1 - 1 / (10 - i +2)), s.scaleY * (1 - 1 / (10 - i +2)), p); } } } } package { import flash.display.Sprite; import flash.events.Event; import flash.events.MouseEvent; import flash.geom.Point; import flash.geom.Rectangle; public class Space extends Sprite { public const GEN_W:int = 700; //horizontal size of swf file public const GEN_H:int = 500; //vertical size of swf file public var WW:Number = 1000; //данные о начальной высоте спейса public var HH:Number = 800; //данные о начальной ширине спейса public var scale_f:Number = 1; private var droped:Boolean = false; public function Space(XX:int, YY:int) { x = XX; y = YY; graphics.beginFill(0x000000,0.5); graphics.drawRect(0, 0, 1000, 800); graphics.endFill(); graphics.beginFill(0x00FF00); graphics.drawCircle(400, 300, 100); graphics.endFill(); graphics.beginFill(0x00FF00); graphics.drawCircle(200, 700, 50); graphics.endFill(); addEventListener(MouseEvent.MOUSE_DOWN, onMDown); addEventListener(MouseEvent.MOUSE_UP, onMUp); addEventListener(MouseEvent.MOUSE_WHEEL, sScale); addEventListener(Event.ENTER_FRAME, EF); } private function onMDown(e:MouseEvent) { var dx:Number = WW-stage.stageWidth; var dy:Number = HH-stage.stageHeight; var dragRect:Rectangle = new Rectangle(-dx,-dy, dx,dy); startDrag(false, dragRect); droped = true; } private function onMUp(e:MouseEvent) { stopDrag(); droped = false; } //изменение масштаба карты private function sScale(e:MouseEvent):void { var sc:Number = 0.95; var p = new Point(GEN_W/2, GEN_H/2); p = globalToLocal(p); if ((e.delta < 0) && (WW*sc>=GEN_W) && (HH*sc>=GEN_H)) { width *= sc; height *= sc; WW *= sc; HH *= sc; scale_f *= sc; (parent as Main).scaleSky(false); } else if ((e.delta > 0) && (scale_f<5)) { width /= sc; height /= sc; WW /= sc; HH /= sc; scale_f /= sc; (parent as Main).scaleSky(true); } p = localToGlobal(p); x += GEN_W/2 - p.x; y += GEN_H / 2 -p.y; if (x > 0) x = 0; if (y > 0) y = 0; if (x + WW < GEN_W) x = GEN_W - WW; if (y + HH < GEN_H) y = GEN_H - HH; } private function EF(e:Event) { if (droped) (parent as Main).moveSky(); } } } package { import flash.display.Shape; public class Star extends Shape { public var dist:Number = 0; //0..100 public var x0:int = 0; public var y0:int = 0; public function Star(X:Number, Y:Number, D: Number = 0) { dist = D; x0 = X; y0 = Y; x = X; y = Y; graphics.beginFill(0xFFFFFF); graphics.drawCircle(0, 0,D/100+0.01); graphics.endFill(); } } } |
|
|||||
Banned
[+4 24.02.14]
[+4 07.11.13] [+ 13.03.14] Регистрация: Mar 2013
Сообщений: 1,864
|
Цитата:
И помочь, если честно, я тоже не могу, мне так же, как и Вам придётся долго думать. |
Часовой пояс GMT +4, время: 18:04. |
|
« Предыдущая тема | Следующая тема » |
|
|