Просмотр полной версии : Тормоза таймера при высоких частотах повторений
Universe
13.09.2013, 16:00
Для представления проблемы приведу следующий пример:
import flash.events.TimerEvent;
var mySeconds:int = 0;
var firstTime:Number = 0;
var myDate:Date = new Date();
var myTimer:Timer = new Timer(10, 200);
myTimer.addEventListener(TimerEvent.TIMER, onTimer);
myTimer.addEventListener(TimerEvent.TIMER_COMPLETE, onTimerComplete);
myTimer.start();
trace("Timer Start", myDate.getSeconds());
function onTimer(e:TimerEvent):void
{
myDate = new Date();
mySeconds += 10;
trace(mySeconds);
}
function onTimerComplete(e:TimerEvent):void
{
var curTime:Number = myDate.getSeconds() - firstTime;
trace("Timer Complete", curTime);
}
Пример выше выполняет обычный трейс за отведённое время, т.е. раз в 10 милисекунд, 200 раз. Если посчитать, в секундах, выполнение таймера должно завершиться через 2 сек. Однако это время растягивается до 4 сек, я уже не говорю какая разница во времени будет, если поставить например 2000 раз, раз в милисекунду. Вопрос знатокам: изза чего происходит такой разбег по времени?
AlexCooper
13.09.2013, 16:08
Universe, да есть такая трабла, так же как и c setInterval. Потому лучше использовать свой обработчик к примеру на ENTER_FRAME проверяющий время.
Возможно попробуйте setTimeout
Проверил setTimeout, тот же результат.
Добавлено через 23 минуты
setTimeout
import flash.utils.setTimeout;
var time:Number = -10;
var startTime:Number = new Date().time;
var timeLast:Number = 0;
timeEvent();
function timeEvent():void {
time += 10;
var colaps:Number = new Date().time-startTime;
var realTime:Number = Math.floor(colaps/100)/10;
if (Math.floor(realTime)!=timeLast) {
timeLast = Math.floor(realTime);
trace('setTimeout: '+Math.floor(time/100)/10+' RealTime: '+realTime);
}
setTimeout( timeOut, 10 );
}
setTimeout: 0.4 RealTime: 1
setTimeout: 0.9 RealTime: 2
setTimeout: 1.4 RealTime: 3
setTimeout: 1.8 RealTime: 4
setTimeout: 2.3 RealTime: 5
setTimeout: 2.8 RealTime: 6
setTimeout: 3.3 RealTime: 7
setTimeout: 3.8 RealTime: 8
setTimeout: 4.2 RealTime: 9
setTimeout: 4.7 RealTime: 10
setInterval
import flash.utils.setInterval;
var time:Number = -10;
var startTime:Number = new Date().time;
var timeLast:Number = 0;
setInterval( timeEvent, 10 );
timeEvent();
function timeEvent(event:*=null):void {
time += 10;
var colaps:Number = new Date().time-startTime;
var realTime:Number = Math.floor(colaps/100)/10;
if (Math.floor(realTime)!=timeLast) {
timeLast = Math.floor(realTime);
trace('setInterval: '+Math.floor(time/100)/10+' RealTime: '+realTime);
}
}
setInterval: 0.4 RealTime: 1
setInterval: 0.9 RealTime: 2
setInterval: 1.4 RealTime: 3
setInterval: 1.8 RealTime: 4
setInterval: 2.3 RealTime: 5
setInterval: 2.8 RealTime: 6
setInterval: 3.3 RealTime: 7
setInterval: 3.8 RealTime: 8
setInterval: 4.2 RealTime: 9
setInterval: 4.7 RealTime: 10
Universe
13.09.2013, 16:34
а чем это вызвано?
AlexCooper
13.09.2013, 16:47
а чем это вызвано?
Честно говоря Я не знаю, особенно проявляется на малых интервалах. Стыкался когда-то с подобным, делал таймер обратного отсчёта на Timer'e, а в результате получил вообще интересную штуку. Таймер сначало быстро отсчитывал, а со временем замедлялся и приближался к реальному времени. Для глаз это выглядело как будто время с фейдином шло, потому переписал привязавши к new Date().time
Цитата из справочника по ActionScript 3.0
delay
...
Примечание. Не рекомендуется задавать свойству delay значение меньше 20 миллисекунд. Частота объекта Timer ограничена 60 кадрами в секунду, то есть задержка меньше 16,6 миллисекунд вызывает проблемы во время выполнения.
AlexCooper
13.09.2013, 16:55
Цитата из справочника по ActionScript 3.0
Интересно что в справочнике только для Timer написали поправку.
В справке про таймер написано о возможных расхождениях во времени. То-есть таймер не гарантирует строго указанную ему точность выполнения. Он стремится к ней, но в реале сказываются факторы производительности и сложности вычислений.
Там-же чуть ниже написано:
delay:Number — Задержка в миллисекундах между событиями таймера. Не рекомендуется задавать свойству delay значение меньше 20 миллисекунд. Частота объекта Timer ограничена 60 кадрами в секунду, то есть задержка меньше 16,6 миллисекунд вызывает проблемы во время выполнения.
Если нужна безукоризненная точность, используйте метод getTimer() для получения прошедшего времени. Рассчитывайте состояние программы или шага анимации на основе прошедшего времени.
AlexCooper
13.09.2013, 17:26
Причем при использовании даже 100мс дает погрешность
import flash.events.TimerEvent;
var mySeconds:int = 0;
var firstTime:Number = new Date().time;
var myDate:Date = new Date();
var myTimer:Timer = new Timer(100,100);
myTimer.addEventListener(TimerEvent.TIMER, onTimer);
myTimer.addEventListener(TimerEvent.TIMER_COMPLETE, onTimerComplete);
myTimer.start();
var time:Number = 0;
function onTimer(e:TimerEvent):void
{
time+=100;
trace(time+" <> "+(new Date().time-firstTime));
}
// TimerTime <> RealTime
100 <> 110
200 <> 235
300 <> 360
400 <> 485
500 <> 610
600 <> 735
700 <> 860
800 <> 985
900 <> 1204
1000 <> 1329
1100 <> 1438
1200 <> 1579
1300 <> 1688
1400 <> 1829
1500 <> 1938
1600 <> 2079
1700 <> 2188
1800 <> 2329
1900 <> 2438
2000 <> 2579
2100 <> 2688
2200 <> 2829
2300 <> 2938
2400 <> 3079
2500 <> 3188
2600 <> 3329
2700 <> 3438
2800 <> 3579
2900 <> 3688
3000 <> 3829
3100 <> 3938
3200 <> 4079
3300 <> 4188
3400 <> 4329
3500 <> 4438
3600 <> 4579
3700 <> 4688
3800 <> 4829
3900 <> 4938
4000 <> 5079
4100 <> 5188
4200 <> 5329
4300 <> 5438
4400 <> 5579
4500 <> 5688
4600 <> 5829
4700 <> 5938
4800 <> 6079
4900 <> 6188
5000 <> 6329
5100 <> 6438
5200 <> 6579
5300 <> 6688
5400 <> 6829
5500 <> 6938
5600 <> 7079
5700 <> 7188
5800 <> 7329
5900 <> 7438
6000 <> 7579
6100 <> 7688
6200 <> 7829
6300 <> 7938
6400 <> 8079
6500 <> 8188
6600 <> 8329
6700 <> 8438
6800 <> 8579
6900 <> 8688
7000 <> 8829
7100 <> 8938
7200 <> 9079
7300 <> 9188
7400 <> 9329
7500 <> 9438
7600 <> 9579
7700 <> 9688
7800 <> 9829
7900 <> 9938
8000 <> 10079
8100 <> 10188
8200 <> 10329
8300 <> 10438
8400 <> 10579
8500 <> 10688
8600 <> 10829
8700 <> 10938
8800 <> 11079
8900 <> 11188
9000 <> 11329
9100 <> 11438
9200 <> 11579
9300 <> 11688
9400 <> 11829
9500 <> 11938
9600 <> 12079
9700 <> 12188
9800 <> 12329
9900 <> 12438
10000 <> 12579
Добавлено через 4 минуты
и 300мс
30000 <> 33281
только 500мс таймер дает верные значения
500 <> 500
1000 <> 1000
1500 <> 1500
2000 <> 2000
2500 <> 2500
3000 <> 3000
3500 <> 3500
4000 <> 4000
4500 <> 4500
5000 <> 5000
5500 <> 5500
6000 <> 6000
6500 <> 6500
7000 <> 7000
7500 <> 7500
8000 <> 8000
8500 <> 8500
9000 <> 9000
9500 <> 9500
10000 <> 10000 и то как писал Tails всё это еще нужно налаживать на аппаратную часть
AlexCooper,
Вы 10 раз в секунду создаёте новый экземпляр Date и вызываете его геттер.
Для получения прошедшего времени просто дёргайте функцию getTimer() из пакета: flash.utils
AlexCooper
13.09.2013, 17:32
AlexCooper,
Вы 10 раз в секунду создаёте новый экземпляр Date и вызываете его геттер.
Для получения прошедшего времени просто дёргайте функцию getTimer() из пакета: flash.utils
согласен что getTimer() будет работать быстрее.
p.s. Но это уже другая история)
Потому что Elastic Racetrack
любое выполнение кода тоже время
1. выполнить код 200 раз с интервалом 10 ms не то же самое что подождать 2000 ms, в любом случае будет тратиться время на повторный запуск таймера - это и будет погрешность.
2. цикл кадра в виртуальной машине тоже не постоянный http://www.craftymind.com/2008/04/18/updated-elastic-racetrack-for-flash-9-and-avm2/ он состоит из последовательных этапов (выполнение кода, апдейт таймеров, вход в кадр, рендеринг, выход из кадра, включение сборки мусора если нужно, обработка лоадеров и тд и тп), поэтому момент повторного запуска таймера зависит не от константного времени работы, а от удачного попадания в этап апдейта таймеров и времени работы предыдущих этапов (на разных машинах время будет разное). этот цикл запускается не раз в 1ms а раз в 1 кадр. тоесть если у тебя будет 60 fps то время обработки повторного таймера будет меняться +/- 16 ms.
3. Выполнение цикла кадра AVM можно приостановить извне (попытаться закрыть окно, свернуть вкладку/окно, вызвать контекстное меню и тд) если приостановить выполнение то соответсвенно у тебя так же сдвинется отсечка таймера
Поэтому не нужно завязываться на правильность работы таймера, лучше слушать событие входа в кадр и определять поведение основываясь на времени с момента запуска AVM getTimer()
Akopalipsis
13.09.2013, 19:19
Рассчитывайте состояние программы или шага анимации на основе прошедшего времени.
А можно немного теории на простом примере?
Предположим рисуются линии на экране, расстояние от координаты ноль\ноль которых рассчитано при помощи интервалов таймера.
И чем больше задержка, тем больше расстояние. Но как рассчитать по прошедшему времени?
Вот в первый раз расхождение ноль, второй +0.5, третий +1.0.... Как это можно при помощи getTimer устранить? ( о работе getTimer я знаю только, что он замеряет отрезок времени, за которое что то выполнилось ).
AlexCooper
13.09.2013, 19:32
Akopalipsis getTimer возвращает время в миллисекундах от старта запуска виртуальной машины AVM1/2 , грубо говоря время в мс от начала работы программы. Если к примеру дату еще можно изменить то getTimer это только геттер и изменить обнулить его можно только перезапустив приложение. Соответсвено привязав движение ( или что вам нужно ) к этому счётчику асинхронизировать что-либо будет очень сложно.
Akopalipsis,
Всё очень просто, смотри.
Для начала создаёшь обычный таймер с интервалом 60fps (или какую тебе нужно частоту обновления) и обычную переменную на уровне класса с типом Number, для расчётов:
private var lastTime:Number = 0;
private var timer:Timer = new Timer(1000 / 60);
Соответственно, подписываешь функцию слушатель, которую таймер будет дёргать 60 раз в секунду.
Далее, на каждой итерций, в функций листенере расчитываеш реально прошедшее время таким вот не замысловатым образом:
private function onTimerTick(e:TimerEvent):void{
var currentTime:Number = getTimer(); // Текущее время
var elapsedTime:Number = (currentTime - lastTime) / 1000; // Реально прошедшее время с последней иттераций
lastTime = currentTime; // Запоминаем текущее время для следующего вызова.
}
Так ты получаешь в переменной elapsedTime - реально прошедшее время. Для удобства, его лучше перевести в секунды (разделить на 1000).
Далее всё становится ещё проще.
Тебе нужно рисовать некоторую линию от 0:0. Всё что для этого нужно - это запомнить текущее положение линий (до куда её нарисовали от 0:0) и указать расстояние, на которое она рисуется за 1 секунду реального времени. Выглядеть это может примерно так:
/// Скорость рисования линий за 1 секунду.
private static const DRAW_SPEED:Number = 15;
private var linePoint:Point = new Point(0, 0);
// На каждой иттераций таймера, ты имеешь прошедшее время с момента последнего вызова,
// которое можеш передавать функций рисовалке линий:
private function lineAnimation(time:Number):void{
// Эта функция знает лишь то, что с последнего вызова прошло time секунд.
// Так как мы имеем скорость рисования линий за 1 секунду, мы можем найти расстояние
// на которое она нарисуется за текущее прошедшее время.
// Новая позиция для линий:
linePoint.x += time * DRAW_SPEED;
// Код, рисующий линию к новой координате
// ...
}
Вот и всё. Ничего сложного если совсем немного вникнуть. Все ваши анимаций, скорости перемещения персонажа и другие параметры изменения, должны указываться как - изменение за 1 секунду времени.
По такому принципу, например, работает анимация в Starling. На основе прошедшего времени работают физические движки. По этому-же принципу можно делать и "не лагающие игры". То-есть, лагать они конечно-же могут, будет уменьшаться частота обновления мира (fps), но эффекты при этом будут проигрываться с нормальной скоростью, а не замедленной. Уменьшится fps но действие в игре будет идти с той-же скоростью.
Akopalipsis
13.09.2013, 23:03
Tails Спасибо большое за обьяснение! Несколько дней у меня наверное ещё займет геометрия, но как только закончу, первым делом в эту тему и пробовать. А то постоянно читаю о разнице во времени ентерфрайма и таймера. Лучше сразу научиться делать с getTimer(), чем в будущем пожалеть, что не отвел одного дня для разбора темы.
Комменты не читал, смотрите сюда (http://www.craftymind.com/2008/04/18/updated-elastic-racetrack-for-flash-9-and-avm2/).
Akopalipsis
28.10.2013, 00:53
На несколько минут руки застыли над клавиатурой и...( не знаю как задать этот вопрос )
Может кто нибудь рассказать принцип по которому только один класс в приложении является
EnterFrame-ом.
Создаю я класс синглетон для всего приложения. А дальше что? Если делать события, то они сразу сведут на нет все getTimer-ы. Если сделать метод и передавать туда ссылку на метод, который по таймеру будет получать в параметры прошедшее время, то ведь это тоже ведь сведёт на нет все труды?
Обьясните на словах, как это делается?
Ну, например инвалидация. Модель посылает событие об изменении, но Вид не пытается сделать перерисовку сразу же. В обработчике события от Модели Вид только устанавливает флаг isChanged = true;
Второй механизм проверяет флаги по событию таймера, или рендера, или ентерфрейму, и увидев флаг true делает соответствующее обновление, после чего снова устанавливает флаг в false.
Dukobpa3
28.10.2013, 01:49
Таймер физически не может выдавать значения чаще чем раз в кадр.
Соответственно погрешность зависит от фпс в первую очередь.
К тому же если вы взяли к примеру 100 мс - то это 10 повторений в секунду. А фпс допустим 24. 1000/24 = 41.6666.
т.е. 100 мс это 2.4 кадра на один тик.
Хотите точный таймер - используйте периоды кратные длине кадра. Но даже в таком случае точность [почти] гарантируется только без нагрузок. При любых нагрузках - длина кадра начинает скакать. Там дольше считали, там быстрее получилось и в таком духе. Плюс от системы тоже зависит.
Короче таймер во флеше нифига не таймер с такой реализацией.
Единственный гарантированный метод выше упоминали - подписка на ентерфрейм + замер кол-ва милисекунд от предыдущего кадра.
Akopalipsis
28.10.2013, 02:59
Спасибо Вам! Пока хотел написать уточнения к вопросу, из сказанных Вами слов получилось вообразить процесс в голове и я начал делать, чтобы показать про что именно я говорю. Но как всегда ( у меня )
возникли мелкие заминки.. И я сегодня уже не потяну, перенесу на завтра)
Dukobpa3, совершенно верно про кратность интервала таймера и частоту кадров. Но, есть несколько способов добиться более или менее точных таймингов. Первый описан в цикле из трех статей здесь: http://www.computus.org/journal/?p=22 Там же разжевано и то, почему все это происходит.
Второй способ - подгружать mp3 со строго отмеренной длиной, равной вашему интервалу, и использовать событие SOUND_COMPLETE.
Второй способ - подгружать mp3 со строго отмеренной длиной, равной вашему интервалу, и использовать событие SOUND_COMPLETE.
Которое придет в том же потоке событий, что и события таймера... И никакой разницы, кроме загрузки и декодирования мусора, не будет.
Добавлено через 9 минут
Интересно что в справочнике только для Timer написали поправку.
По двум причинам. setInterval и setTimeout были добавлены для совместимости (по-крайней мере так позиционировалось когда только появилась AVM2) и на их документацию забили сразу же, с припиской "рекомендуется создавать объект Timer". И вторая, обе эти функции все равно создают таймер, со всеми вытекающими.
Akopalipsis
28.10.2013, 16:26
Сделал пока вот как, если у такого подхода есть какие то недостатки по сравнению с другим ( который я не знаю ), то то поделитесь пожалуйста им.
package
{
import flash.display.DisplayObject;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
public class Main extends Sprite
{
private var _timerFrame:TimerFrame;
private var _animator:Animator;
private var _boll:Boll;
private var _convas:Convas;
public function Main()
{
init();
}
private function init(event:Event=null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
stage.addEventListener(MouseEvent.MOUSE_DOWN, stage_mouseDownHandler);
stage.addEventListener(MouseEvent.MOUSE_UP, stage_mouseUpHandler);
_timerFrame = new TimerFrame();
_boll = new Boll();
_animator = new Animator(_boll);
_animator.startX = 50;
_animator.startY = 200;
_convas = new Convas();
super.addChild(_convas);
_animator.doc = _convas;
}
private function stage_mouseUpHandler(event:MouseEvent):void
{
_timerFrame.removeAnimator(_animator);
}
private function stage_mouseDownHandler(event:MouseEvent):void
{
_timerFrame.addAnimators(_animator);
}
}
}
package
{
import flash.display.Sprite;
import flash.events.Event;
public class Boll extends Sprite
{
public function Boll()
{
super.addEventListener(Event.ADDED_TO_STAGE, super_addedToStageHandler);
}
private function super_addedToStageHandler(event:Event):void
{
super.removeEventListener(Event.ADDED_TO_STAGE, super_addedToStageHandler);
super.graphics.beginFill(0x2B81AE);
super.graphics.drawCircle(0, 0, 40);
super.graphics.endFill();
}
override public function get x():Number {return super.x ;}
override public function set x(value:Number):void { super.x = value; }
override public function get y():Number {return super.y;}
override public function set y(value:Number):void {super.y = value;}
}
}
package
{
import flash.display.DisplayObject;
import flash.display.DisplayObjectContainer;
import flash.display.Sprite;
import flash.errors.IllegalOperationError;
public class Animator extends Object implements IAnimator
{
private var _boll:DisplayObject;
private var _doc:DisplayObjectContainer;
private var _startX:int;
private var _startY:int;
private var _finishX:int;
private var _finishY:int;
private var _elapsedTime:Number;
public function Animator(boll:DisplayObject)
{
_boll = boll as DisplayObject;
}
private function addCanvas():void
{
_boll.x = _startX;
_boll.y = _startY;
_doc.addChild(_boll as DisplayObject);
}
public function animation(time:Number):void
{
trace('animator');
}
public function set startX(value:int):void {_startX = value;}
public function set startY(value:int):void {_startY = value;}
public function set finishX(value:int):void {_finishX = value;}
public function set finishY(value:int):void {_finishY = value;}
public function set doc(value:DisplayObjectContainer):void
{
if (!value) throw new IllegalOperationError("");
_doc = value;
this.addCanvas();
}
public function set elapsedTime(value:Number):void
{
_elapsedTime = value;
}
}
}
package
{
import flash.display.Sprite;
import flash.events.Event;
public class Convas extends Sprite
{
public function Convas()
{
super.addEventListener(Event.ADDED_TO_STAGE, super_addedToStageHandler);
}
private function super_addedToStageHandler(event:Event):void
{
super.removeEventListener(Event.ADDED_TO_STAGE, super_addedToStageHandler);
}
}
}
package
{
public interface IAnimator
{
function animation(time:Number):void;
}
}
package
{
import flash.display.Sprite;
import flash.events.DataEvent;
import flash.events.Event;
import flash.events.EventDispatcher;
public class TimerFrame extends Sprite
{
private var _elapsedTime:Number;
private var _animators:Vector.<IAnimator>;
public function TimerFrame()
{
_animators = new Vector.<IAnimator>([]);
addEventListener(Event.ENTER_FRAME, super_enterFrameHandler);
}
private function super_enterFrameHandler(event:Event):void
{
var num:Number = 5;
var length:int = _animators.length;
for (var i:int = 0; i < length; i++)
{
_animators[i].animation(num);
}
}
public function addAnimators(animator:IAnimator):void
{
_animators.push(animator);
}
public function removeAnimator(animator:IAnimator):void
{
var length:int = _animators.length;
for (var i:int = 0; i < length; i++)
{
if (_animators[i] == animator)
{
_animators.splice(i, 1);
break;
}
}
}
}
}
И прежде чем я начну делать класс дляентерФрайм + гетТаймер, хочу вот что уточнить.
Какую связку нужно или лучше делать - ентерФрайм + гетТаймер или таймер + гетТаймер?
Dukobpa3
28.10.2013, 16:46
И прежде чем я начну делать класс
Прежде чем наворачивать вот это на свой проект - сделай то, что заставит тебя этим заниматься.
Другими словами - решай проблемы по мере поступления.
У тебя есть в проекте косяки которые влечет за собой косой таймер? Или ты решил сделать всё "сразу правильно"?
Я по опыту могу сказать что ентерпрайз-подход нужен в ентерпрайзе. Если ты пишешь какой-то микропроект для себя - то там это всё только усложняет понимание. Не заморачивайся с таймера, насколько я понимаю - ты еще и с ентерфреймом то до конца не разобрался.
public function addAnimator(animator:IAnimator):void {
if (_animators.indexOf(animator) == -1)
_animators.push(animator)
}
public function removeAnimator(animator:IAnimator):void {
_animators.splice( _animators.indexOf(animator), 1 );
}
Canvas.
Akopalipsis
28.10.2013, 17:16
dimarik Спасибо! А как с enterFrame быть?
У тебя есть в проекте косяки которые влечет за собой косой таймер? Или ты решил сделать всё "сразу правильно"?
Вот пройдёт время и мне может это срочно понадобится и вместо "а! я это уже делал", будет тема на форуме - "EnterFrame + getTimer срочно! бросили все дела и начали мне помогать!!!!!".
Вот представьте чтобы было, если бы Вы попали к любому специалисту, который не чего не умеет,
только по тому, что его наставник говорил, что пока тебе это не надо.
ты еще и с ентерфреймом то до конца не разобрался.
Вот сейчас я и разбираюсь. И если Вам не тяжело, то в чем мои не понимания EnterFrame?
Да, я не знаю как сделать, чтобы один класс был на все приложение. Можете на словах обьяснить?
Добавлено через 5 минут
Я по опыту могу сказать что ентерпрайз-подход нужен в ентерпрайзе.
Ентерпрайз - это enterFrame+getTimer?
Dukobpa3
28.10.2013, 17:28
Ентерпрайз - это
Энтерпрайз - это перестраховка там где вероятность косяка слишком мала, для того чтобы тратить время и писать + 200-2000 строк кода. Но их все-равно пишут. Потому что ентерпрайз.
Добавлено через 3 минуты
KISS (http://en.wikipedia.org/wiki/KISS_principle)
по тому, что его наставник говорил, что пока тебе это не надо.
Я бы не хотел попасть к специалисту который знает всё, но так и не смог ничего закончить.
Потому что он не специалист, а академик.
И с академиками я работать не хочу и не буду. А специалист тем и отличается от академика что знает он, возможно, меньше. Но всем, что он знает - умеет пользоваться.
Перегруз информацией еще никому в прок не стал.
Добавлено через 13 минут
Вообще у меня по этому поводу слегка предвзятое отношение.
Насмотрелся уже велосипедов разных.
И очень важно понимать, где стоит воротить такую схему, потому что это действительно удобнее. А где лучше просто сделать то что надо.
Очень уж часто такие схемы только оттягивают момент "релиза"(даже если это чисто понятие для себя).
При любых раскладах важнее закончить начатое, чем позаниматься любовью и в итоге запутаться и вообще ничего не сделать.
30130
Akopalipsis
28.10.2013, 17:52
Вообще у меня по этому поводу слегка предвзятое отношение.
я не стремлюсь создать простое приложение перегруженное всякими подстраховками.
я учусь и буду учится, потому что сейчас на это есть время и это не кого кроме меня не затрагивает.
Ещё раз скажу, что я буду учится, пока учусь, а не когда от моей тупости, кто то будет страдать.
С "излишествами" про которые говорится по Вашей ссылке я согласен, но я не согласен, что она мне помогла решить мои вопросы. я искренне не понимаю советов, которые предлагают оставить всё на потом.
Так же я не понимаю для кого Вы старались написав два последних поста. я не чего не подчерпнул, кроме как - я это умею, знайте об этом все, а ты не учись, иди курьером работай, потому что я умею, а ты ещё нет. И я буду об этом каждое твоё сообщение говорить, потому что мне забавно от того, что я кого то называю глупым, а вообще программисты нынче не те... ох не те.
я прошу прощения за такое резкое мнение, но оно вот так со стороны выглядит.
Dukobpa3
28.10.2013, 17:55
Я умею именно потому что сознательно не усложнял себе жизнь когда этого не требовалось. Я выполнял реальные задачи. И со временем дорос и до таких задач.
В этом и был главный посыл моего сообщения.
И это совершенно не значит "не учись". Просто учеба ради учебы - это бред.
Учеба должна помогать тебе с чем-то справиться. С какой-то задачей.
Добавлено через 2 минуты
И мне сейчас по долгу службы приходится очень много усилий тратить на джуниоров которые нахватались поверхам всякого рода паттернов и подходов к программированию, но совершенно не понимают к чему это вообще надо.
И начинаются фабрики для трех кнопок, потому что где-то прочли что хардкод это плохо - а для трех кнопок - хардкод - правильный выбор.
Или какой-то вырвиглазый обсервер или еще какое-то г-но.
Он не может составить простейший алгоритм обхода двумерного массива по заданному пути - зато уже пытается оперировать всякими терминами умными. Потому что в книжках пишут.
Добавлено через 4 минуты
И при приеме в свою команду миддла-жуниора я предпочту того который не знает как называется паттерн, или не знаком с каким-то подходом - но у него в портфолио есть хоть один законченный проект.
Бог-весть как написан, но работает.
Потому что я пойму - человек сможет закончить начатое.
А научить делать его это правильно - я смогу.
Вот и Дизель согласен
30131
Все должно быть в гармонии. "Спортсмен", прекрасно разбирающийся в тонкостях метаболизма, расщепления молочной кислоты и синтеза белков, неспособный поднять гирю — не спортсмен.
Akopalipsis
28.10.2013, 18:19
Он не может составить простейший алгоритм обхода двумерного массива по заданному пути - зато уже пытается оперироваться всякими терминами умными. Потому что в книжках пишут.
Пока есть немного времени то же выскажусь)
Тут может быть несколько причин - кто то этому джуниору на этапе обучения ( как я сейчас ) сказал -
зачем тебе велосипеды, есть RL2, есть nape, starling... Вы кому нибудь давали советы не строит велосипеды?
Второе - просто у него не математический склад ума.
Третье - у него не хватило фантазии посмотреть готовые алгоритмы, чтобы хотя бы их выучить, как я пытаюсь сделать с кадрами. Но тут в голове советы всплывают - зачем велосипеды, зачем усложнять.
Хорошо что я не слушаю такие советы.я слушаю только когда говорят - почитай.
Но сколько бы я проектов не сделал, хоть сотню, мне все равно придётся когда учить то, что можно сейчас. А вообще программист - математик, это больше наверное исключение. И есть чувство,
что Вы сами учились по чужим кодам. И повторюсь, Ваш стаж не соответствует с датой регистрации на форуме. Есть сомнение, что ещё пару лет назад, под другим аккам, Вы спрашивали всякую ерунду.)
Dukobpa3
28.10.2013, 18:26
Но сколько бы я проектов не сделал, хоть сотню
Говорить про сотню, не закончив ни одного - как минимум глупо.
У меня вот тоже штук шесть всего(достойных). До сотни еще огого. И ниче, рабошим.
Добавлено через 42 секунды
А про спортсмена хорошо:)
Я запомню.
Akopalipsis
28.10.2013, 18:28
И как только я закончу EnterFrame перейду к поиску путей. И всё это благодаря Вам и Вашему примеру, которому я рад только потому, что он и показывает, как всё просто! Хотя я сделал немного по другому.
я как смог реализовал что то наподобие класса Context из RL. И вот когда я сделаю эту игру, то сяду и подумаю и скорее всего склонюсь к использованию RL так как я его уже почти на изусть выучил.
Добавлено через 2 минуты
Если спортсмен способный поднять слона не будет знать как на его организм действует молочная кислота и когда и для чего она вырабатывается, то есть предположение, что долго он не протянет.
Добавлено через 5 минут
И уже много раз бы обьяснили как надо)
Тут может быть несколько причин - кто то этому джуниору на этапе обучения ( как я сейчас ) сказал - зачем тебе велосипеды, есть RL2, есть nape, starling... Вы кому нибудь давали советы не строит велосипеды?
Я давал, и не собираюсь прекращать это занятие. Прежде чем лепить свои велосипеды, необходимо разобраться как подобные проблемы решали другие. Тем более, что все перечисленные вами проекты с открытым кодом.
Одним словом, прежде чем решать проблему, ее надо понять, возможно проблема совсем в другом месте.
Добавлено через 3 минуты
И вот когда я сделаю эту игру, то сяду и подумаю и скорее всего склонюсь к использованию RL так как я его уже почти на изусть выучил.
Только сначала подумайте, а нужен ли он вам и в каких местах таки нужен.
Akopalipsis
28.10.2013, 20:31
Только сначала подумайте, а нужен ли он вам и в каких местах таки нужен.
Спасибо! Как доучусь до этапа завершения, то покажу и уже на основании общественного вердикта, подумаю.
Прежде чем лепить свои велосипеды, необходимо разобраться как подобные проблемы решали другие.
Вот только это я и ожидаю задавая вопрос на форуме. Но и в этот раз я немного сглупил, так как ускользнули слова из ранее данного ответа.
Psycho Tiger
29.10.2013, 00:59
Всегда есть уровень ниже. Флеш компилируется в байткод. Чтобы писать на флеше не нужно понимать байткод. А байткод интерпретируется виртуальной машиной. О ее устройстве тоже, в общем то, знать не нужно. Дальше машинный код. Паяльник. Квантовая физика. Выходит, без квантовой физики игру не написать?) совершенно очевидно, что знание квантовой физики ну никак не влияет на способности к программированию.
Сейчас такое время, что гораздо важнее уметь склеивать куски готового, чем писать что-то с нуля. Это дешевле, быстрее и качество как правило лучше.
А знания... Создавая что-то они придут. И это будут не "знания в вакууме" - ну серьезно, какой паттерн тебе жизнь спас? Половина из них занимается только тем что выглядят круто, а на деле в чем профит - непонятно.
Программисты занимаются тем, что решают задачу. Побеждает тот, кто ее решил.
Но, если честно, твой энтузиазм действительно подкупает. Ты как Брюс Уиллис на линии огня.
Akopalipsis
29.10.2013, 01:12
Но, если честно, твой энтузиазм действительно подкупает. Ты как Брюс Уиллис на линии огня.
Это не энтузиазм, а стремление к словам, которые Вы написали выше.
Разве можно назвать анимацию на Timer+getTimer лишним и тем более делом на потом.
Вот начну я что то делать, сразу скажут, что лучше всего начать со starling - просто, сильно и быстро.
Вот старлинг я придумывать не хочу. Но хочу уже сегодня разобрать до винтика работу его метода
function advanceTime(time:Number):void
а лучше варианта чем воспроизвести с самого нуля - нет! То есть это естественное стремление к простоте и быстроте. И не могу упустить случая и не пожелать Вам - много свободного времени и хорошего настроения!)
Разве можно назвать анимацию на Timer+getTimer лишним и тем более делом на потом.
Можно.
Dukobpa3
29.10.2013, 02:01
Разве можно назвать анимацию на Timer+getTimer лишним и тем более делом на потом.
Лол. Да мне это всего в одном проекте понадобилось)
В мультиплеерном риалтайме:) И то, в итоге все-равно иначе сделал)))
Всё.
Akopalipsis
29.10.2013, 02:31
Dukobpa3 я сделал и успокоился уже давно. Но у меня вопрос о одном классе с enterFrame остался открытым :) Так как сделал я видимо неправильно и меня немного скорректировали. И тут вот какое дело, с классом аниматор я наверное погорячился. Просто моей целью было сделать, чтобы класс - обьект не содержал анимацию. Хотя я сейчас пока пишу, думаю что не так то и погорячился, потому что, будь сто обьектов с одинаковой анимацией, то вот такая обвертка содержащая только анимацию была бы самое то. Но это другая история и я вернусь к enterFrame. Как его лучше сделать, подскажите на словах?)
Dukobpa3
29.10.2013, 02:35
Как его лучше сделать
Видимо использовать какой-то твинер?
Akopalipsis
29.10.2013, 03:03
Видимо использовать какой-то твинер?
Использовать твинер? Твинер для enterFrame? Или Вы о плавном движении?)
я немного о другом, твинер для плавной анимации я сам в соседней теме советовал,
так как посмотрел в блоге, ссылки на который часто на форуме показываю.
Но возвращаясь к вопросу - как реализовать класс в плане архитектуры приложения?
Вот один вариант, это сделать передачу значений фрайма при добавлении в ДОК, если есть интерфейс IAnimator, то передаём тики ENTER_FRAME. Но тогда, если обьект нужно анимировать не сразу по добавлению в ДОК, то нужно делать каждый тик проверку на true, а это затратно.
Dukobpa3
29.10.2013, 03:21
Сам то понял что сказал?:)
Я - нет:)
Добавлено через 19 минут
GlobalTimer (https://github.com/eggs-gd/eggs-framework-as3/blob/master/src/main/as3/gd/eggs/util/GlobalTimer.as)
AnimationManager (https://github.com/eggs-gd/eggs-framework-as3/blob/master/src/main/as3/gd/eggs/customanim/AnimationManager.as)
Вот здесь поковыряйся.
Это мой код, но:
1. я в упор не понимаю почему коллбек таймера выдает Date, а ентерфрейм - unixtime:int, хотя вроде логичнее и там и там юникстайм слать, видимо у меня была какая-то мотивация.
2. Манагер анимаций штука крутая, но реализация сомнительная. Хоть проект я с ним и зарелизил.
Короче предстоит еще разобраться че там как.
Добавлено через 33 минуты
коллбек таймера выдает Date, а ентерфрейм - unixtime:int,
А. Понял.
Короче таймер время сервера выдает. Предполагается что вся система синхронизируется по серверному времени периодически и секундный таймер как раз для таких вот событий по времени.
А ентерФрейм выдает просто getTimer(), в коллбеке можно сравнить с каким-то предыдущим значением и что-то с этим сделать.
Работает на vBulletin ® версия 3.7.3. Copyright ©2000-2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Copyright © 1999-2008 Flasher.ru. All rights reserved.