PDA

Просмотр полной версии : Двойная буферизация, возможно ли?


neonoviiwolf
26.06.2016, 16:27
Доброго!
В игре есть раздражающий момент, у меня большой задний фон и он состоит из нескольких кадров(7 кадров). Во время старта игры происходит загрузка каждого кадра в память (как я понимаю) и я получаю 7 рывков (у меня кадр мувика сменяется через каждые 10 кадров флеша), дальше всё идёт гладко. Но потом, переодически снова эти 7 рывков, после начала игры заново (когда как, чаще всго после того, как сделал перерыв в несколько секунд), ссылку на фон не удаляю, так что GC не должен убивать, да и фон не меняется, просто игрок оказывается в другом месте на этом же фоне. Думал как решить проблему, теперь при старте, до начало игры сделал окно загрузки, в это время как раз полностью проигрывается мувик заднего фона и тормоза при первом старте пропали, но что делать, когда периодически при рестарте игры тормоза снова

caseyryan
26.06.2016, 17:39
Что ты имеешь в виду под двойной буферизацией здесь?
Твой фон, очевидно, глючит из-за ошибки в коде. Рестарт у тебя не правильно делается, вот и все.

neonoviiwolf
26.06.2016, 18:39
Что ты имеешь в виду под двойной буферизацией здесь?
Твой фон, очевидно, глючит из-за ошибки в коде. Рестарт у тебя не правильно делается, вот и все.

буферизация - это вроде, когда картинка заранее готовится в памяти, но могу ошибаться

Не думаю, что ошибка в коде, у мувика размеры 4к на 2.7к пикселей, состоит из 7 картинок. Тормоза появляются при начале проигрывание этого мувика, пока не пройдут все кадры по очереди, потом всё отлично. Но стоит перестать играть на 20-30 сек и начать сначала, то снова будет ровно столько же тормозов, пока кадры не сменят друг друга. Если сменить мувик на меньший размер или вставить пустой, то проблем нету

Bletraut
26.06.2016, 20:44
Никогда не встречал подобного. У меня анимация из 40 кадров, каждый кадр размером 1024х1024, размер картинки огромный, режу её на кадры и просто меняю bitmapdata у bitmap никаких рывков никогда нет. Аналогичные результаты и с любыми другими размерами, никакая буферизация здесь не нужна.

neonoviiwolf
26.06.2016, 23:22
Никогда не встречал подобного. У меня анимация из 40 кадров, каждый кадр размером 1024х1024, размер картинки огромный, режу её на кадры и просто меняю bitmapdata у bitmap никаких рывков никогда нет. Аналогичные результаты и с любыми другими размерами, никакая буферизация здесь не нужна.

при разрешении 1024х1024 проблем нема, если более подробно, то использую несколько таких текструр 4000х2700(есть копии и есть нет), скаут показывает, что тормоза из-за рендера изображения, да я и сам вижу, все скачки точно совпадают, когда должен сменить кадр и ровно один раз, следующие тормоза возникают, после того, как игрок временно перестанет играть или постаивть игру на паузу. Мне кажется, что GC удаляет из памяти все кадры мувика, кроме текущего, а когда снова запускается игра, по новой рендериться. Думаю можно попробовать сделать 7 спрайтов и потом просто менять их глубину отображения(хз как называется), создавая аналог мувика

Bletraut
27.06.2016, 17:28
Какая еще глубина отображения? Просто менять битмапдату у битмап. Баг явно в коде, либо корявой реализации. Никаких рывков не должно быть.

neonoviiwolf
27.06.2016, 22:48
Какая еще глубина отображения? Просто менять битмапдату у битмап. Баг явно в коде, либо корявой реализации. Никаких рывков не должно быть.

да как может быть реализация кривая, если я просто добавляю мувик на сцену и он просто играет

Добавлено через 3 минуты
package classesGame.addActionUnits.addAction
{
import classesGame.options.OptionsUnits;
import classesGame.userEvent.UserEvent;
import flash.events.Event;
import nape.phys.Body;
import singleton.sFloor.SFloor;

public class AddActionCover extends IParentCommon
{

public function AddActionCover()
{
}

private var cover1:cover_mc = new cover_mc();
private var cover2:cover_mc = new cover_mc();

override public function init(e:Event):void
{
super.init(e);

stage.addEventListener(UserEvent.START_FLAG_1, userEvent);
stage.addEventListener(UserEvent.START_FLAG_3, userEvent);
stage.addEventListener(UserEvent.PAUSE, userEvent);
stage.addEventListener(UserEvent.PLAY, userEvent);
stage.addEventListener(UserEvent.EMERGING_WALL, userEvent);
stage.addEventListener(UserEvent.SHOT_WALL, userEvent);

this.addChild(cover1);
this.addChild(cover2);
this.addEventListener(Event.ENTER_FRAME, driveAway);
}

private function driveAway(e:Event):void
{
if (cover1.totalFrames > cover1.currentFrame)
stage.dispatchEvent(new UserEvent(UserEvent.CREATE_SEGMENT, true, false));
else
{
stage.dispatchEvent(new UserEvent(UserEvent.CREATE_ALL, true, false));
this.removeEventListener(Event.ENTER_FRAME, driveAway);
cover1.visible = cover2.visible = false;
}
}

private function userEvent(e:UserEvent):void
{
switch (e.type)
{
case "startFlag1":
case "emergingWall":
this.removeEventListener(Event.ENTER_FRAME, updateCover);
startFlag1();
break;
case "shotWall":
case "startFlag3":
this.addEventListener(Event.ENTER_FRAME, updateCover);
break;
case "pause":
this.removeEventListener(Event.ENTER_FRAME, updateCover);
break;
case "play":
this.addEventListener(Event.ENTER_FRAME, updateCover);
break;
}
}

private function updateCoverOffset(e:Event):void
{
cover1.y = cover2.y = bodyFloor.position.y - 2651.4;
}

private function startFlag1():void
{
cover1.visible = cover2.visible = true;
cover1.gotoAndStop(1);
cover2.gotoAndStop(1);
//!!!
OptionsUnits.positionWall_1 = cover1.width * 2;
//
cover1.y = cover2.y = -cover1.height + stage.stageHeight;
cover1.x = 0;
cover2.x = cover1.x + cover1.width;
this.addEventListener(Event.ENTER_FRAME, updateCoverOffset);
}

private var bodyFloor:Body = SFloor.getSFloor.getFloor.getBody;
private var step:uint = 0;

private function updateCover(e:Event):void
{
cover1.x -= OptionsUnits.tempGameSpeed ;
cover2.x -= OptionsUnits.tempGameSpeed;

if (cover1.x < -cover1.width)
cover1.x = cover2.x + cover2.width;
if (cover2.x < -cover2.width)
cover2.x = cover1.x + cover1.width;

if (step < 51)
{
++step;
cover1.gotoAndStop(uint(step / 10 + 1));
cover2.gotoAndStop(uint(step / 10 + 1));
}
else step = 0;
}
}
}

dimarik
28.06.2016, 19:49
Тормоза из-за растеризации могут быть. Попробуйте cacheAsBitmap, если не предполагается менять мувику цветовую и геометрическую трансформацию.

Bletraut
28.06.2016, 19:58
да как может быть реализация кривая, если я просто добавляю мувик на сцену и он просто играет

Добавлено через 3 минуты
package classesGame.addActionUnits.addAction
{
import classesGame.options.OptionsUnits;
import classesGame.userEvent.UserEvent;
import flash.events.Event;
import nape.phys.Body;
import singleton.sFloor.SFloor;

public class AddActionCover extends IParentCommon
{

public function AddActionCover()
{
}

private var cover1:cover_mc = new cover_mc();
private var cover2:cover_mc = new cover_mc();

override public function init(e:Event):void
{
super.init(e);

stage.addEventListener(UserEvent.START_FLAG_1, userEvent);
stage.addEventListener(UserEvent.START_FLAG_3, userEvent);
stage.addEventListener(UserEvent.PAUSE, userEvent);
stage.addEventListener(UserEvent.PLAY, userEvent);
stage.addEventListener(UserEvent.EMERGING_WALL, userEvent);
stage.addEventListener(UserEvent.SHOT_WALL, userEvent);

this.addChild(cover1);
this.addChild(cover2);
this.addEventListener(Event.ENTER_FRAME, driveAway);
}

private function driveAway(e:Event):void
{
if (cover1.totalFrames > cover1.currentFrame)
stage.dispatchEvent(new UserEvent(UserEvent.CREATE_SEGMENT, true, false));
else
{
stage.dispatchEvent(new UserEvent(UserEvent.CREATE_ALL, true, false));
this.removeEventListener(Event.ENTER_FRAME, driveAway);
cover1.visible = cover2.visible = false;
}
}

private function userEvent(e:UserEvent):void
{
switch (e.type)
{
case "startFlag1":
case "emergingWall":
this.removeEventListener(Event.ENTER_FRAME, updateCover);
startFlag1();
break;
case "shotWall":
case "startFlag3":
this.addEventListener(Event.ENTER_FRAME, updateCover);
break;
case "pause":
this.removeEventListener(Event.ENTER_FRAME, updateCover);
break;
case "play":
this.addEventListener(Event.ENTER_FRAME, updateCover);
break;
}
}

private function updateCoverOffset(e:Event):void
{
cover1.y = cover2.y = bodyFloor.position.y - 2651.4;
}

private function startFlag1():void
{
cover1.visible = cover2.visible = true;
cover1.gotoAndStop(1);
cover2.gotoAndStop(1);
//!!!
OptionsUnits.positionWall_1 = cover1.width * 2;
//
cover1.y = cover2.y = -cover1.height + stage.stageHeight;
cover1.x = 0;
cover2.x = cover1.x + cover1.width;
this.addEventListener(Event.ENTER_FRAME, updateCoverOffset);
}

private var bodyFloor:Body = SFloor.getSFloor.getFloor.getBody;
private var step:uint = 0;

private function updateCover(e:Event):void
{
cover1.x -= OptionsUnits.tempGameSpeed ;
cover2.x -= OptionsUnits.tempGameSpeed;

if (cover1.x < -cover1.width)
cover1.x = cover2.x + cover2.width;
if (cover2.x < -cover2.width)
cover2.x = cover1.x + cover1.width;

if (step < 51)
{
++step;
cover1.gotoAndStop(uint(step / 10 + 1));
cover2.gotoAndStop(uint(step / 10 + 1));
}
else step = 0;
}
}
}

Нужно не мувиклип отображать, а bitmap и менять у неё bitmapdata.

neonoviiwolf
28.06.2016, 20:44
Bletraut покажите как, ни разу не задумывался

undefined
28.06.2016, 20:54
возможно GC действительно выгружает невидимые кадры т.к. никаких ссылок на контент не остается при переходе на другой кадр.Решение - сделать свой MovieClip с кешированием.

Bletraut
29.06.2016, 00:06
Вместо того, чтобы размещать растровое изображение на кадрах, нужно создать bitmap, а из растровых изображений сделать массив с bitmapdata. И сделать свой собственный класс для анимации, где просто подменять bitmapdata у текущей bitmap на эти вот bitmapdat'ы из массива.

Пример. (http://stackoverflow.com/questions/24417189/convert-each-frame-from-a-movieclip-to-cached-bitmapdata-to-another-mc-while-run)