11
votes

TIMERS AS3 VS. Enter_Frame Performance

Je construis un jeu qui a obtenu des choses déplaçant tout le temps, alors j'utilise beaucoup d'instances de minuterie pour contrôler la répétition et le mouvement de déclenchement.

La chose est que je commençais à remarquer certaines performances "lags". Est-ce dû aux minuteries? Et suggérez-vous d'utiliser l'événement Enter_frame à la place?

liée: suggérez-vous une autre bibliothèque / méthode de tels jeux pouvant améliorer les performances? Simple Tween Bibliothèques ne suffisent pas en soi.


0 commentaires

4 Réponses :


1
votes

Si vous n'utilisez pas une bibliothèque Tween, je regarderais Tweenlite ou Tweenmax. Il inclut une minuterie appelée retardée ainsi que le regroupement de tweens ensemble. Il a de grandes performances et est simple à utiliser.

Regardez ici aux tests de performance

http://blog.greensock.com/tweening-speed-test/

josh


0 commentaires

8
votes

Peut-être que cela aurait plus de sens, d'avoir une seule minuterie en cours d'exécution forte> pour cette affaire ... Autant que je sache, une minuterie de course a besoin d'un fil entier ... Pour le mettre en pseudo-code, le code principal du fil de la minuterie est quelque chose comme ça ...

package {
    //{ region imports
        import flash.display.*;
        import flash.events.*;
        import flash.sampler.getSize;
        import flash.system.System;
        import flash.text.*;
        import flash.utils.*;   
    //} endregion
    public class Main extends MovieClip {
        //{ region configuration
            private const timers:Boolean = false;//true for Timer, false for Ticker
            private const delay:Number = 500;
            private const baseCount:uint = 10000;//base count of functions to be called
            private const factor:Number = 20;//factor for Ticker, which is a little more performant     
        //} endregion
        //{ region vars/consts
            private const count:uint = baseCount * (timers ? 1 : factor);
            private const nullMem:uint = System.totalMemory;//this is the footprint of the VM ... we'll subtract it ... ok, the textfield is not taken into account, but that should be alright ... i guess ...
            private var monitor:TextField;
            private var frameCount:uint = 0;
            private var secCount:uint = 0;      
        //} endregion
        public function Main():void {   
            var t:Ticker = new Ticker(delay);
            var genHandler:Function = function ():Function {
                return function (e:TimerEvent):void { };
            }
            var genCallback:Function = function ():Function {
                return function (tick:uint):void { };
            }
            for (var i:uint = 0; i < count; i++) {
                if (timers) {
                    var timer:Timer = new Timer(delay, 0);
                    timer.addEventListener(TimerEvent.TIMER, genHandler());
                    timer.start();                  
                }
                else {
                    t.addCallback(genCallback());
                }
            }
            this.addChild(this.monitor = new TextField());
            this.monitor.autoSize = TextFieldAutoSize.LEFT;
            this.monitor.defaultTextFormat = new TextFormat("_typewriter");
            this.addEventListener(Event.ENTER_FRAME, function (e:Event):void { frameCount++ });
            setInterval(function ():void { 
                    monitor.text = "Memory usage: " 
                        + groupDidgits(System.totalMemory - nullMem) 
                        + " B\navg. FPS: " + (frameCount /++secCount).toPrecision(3) 
                        + "\nuptime: " + secCount + "\nwith " + count + " functions"; 
                }, 1000);
        }
        private function groupDidgits(n:int,sep:String = " "):String {
            return n.toString().split("").reverse().map(function (c:String, i:int, ...rest):String { return c + ((i % 3 == 0 && i > 0) ? sep : ""); } ).reverse().join("");
        }
    }
}


9 commentaires

Qu'y a-t-il avec la «région»?


Oh. Et pourquoi faites-vous des variables de membres privées au lieu de protéger?


Merci pour les informations inestimables concernant les minuteries. Je dois essayer votre code; Le ticker semble prometteur!


@Luke À propos des régions: J'utilise FlashDéveloppe pour le développement ActionScript ... Les régions permettent de plier sur mesure, de sorte que je puisse replier différentes parties de la classe ... plus il donne au code une structure supplémentaire ... juste une convention codante de la mine, pour ainsi dire ...


@ back2dos. Merci pour ça. Toutefois. Je ne suis pas d'accord avec à peu près tout ce que vous dites dans votre mise à jour. Il semble que vous pensiez que tout est hostile et vous devez vous protéger et autres programmeurs de vos implémentations de classe. Ma philosophie est exactement le contraire. Chaque membre de la classe devrait être disponible pour la sous-classement, sauf indication contraire de la rendre privée. Votre approche semble un peu bureaucratique pour moi. Et bien. Heureux de ne pas avoir à travailler sur des projets ensemble. :)


Il s'agit de l'encapsulation et de l'écriture de code de recherche, qui fonctionnera toujours comme prévu ou lancez des erreurs d'exécution, si oui. fait des choses stupides avec elle. Pour moi, une bonne API est puissante, petite et axée sur les problèmes. Ne vous souciez pas de la façon dont, tant que c'est ce qui est fiable. C'est ce que j'attends, et c'est pourquoi je le fais moi-même. BTW, le point de sous-classement ne vibre pas avec des propriétés de Superclass, mais pour une mise en œuvre concrète du comportement abstraite et constitue un très bon outil pour établir le CIO. Vous pouvez poser une question sur tout cela, si vous voulez vraiment discuter de cette question au sérieux.


L'explication sur les minuteries et les threads est totalement inexacte. Tous ActionScript dans le Player Flash s'exécutent dans un seul fil, quelles que soient les minuteries, etc. Il est important de se souvenir de cela et de ne pas résumé cela comme "thread-like" si vous voulez comprendre ce qui se passe vraiment.


Si vous lisez mon message, vous auriez réalisé, j'ai déclaré que ABC est exécuté par un seul fil. Flash Player comme tel n'est pas. Pixel Bender est le meilleur exemple, où vous pouvez même exécuter du code parallèle.


@Luke: "Les membres ont déclaré protégé plus ouvert aux abus que les membres déclarés privés. En particulier, la déclaration de données de données protégées est généralement une erreur de conception. Placer des quantités importantes de données dans une classe commune pour toutes les classes dérivées pour utiliser des feuilles que les données ouvertes à La corruption. Les données pires, protégées, telles que les données publiques, ne peuvent pas être facilement restructurées car il n'y a pas de bon moyen de trouver toutes les utilisations. Ainsi, les données protégées deviennent un problème de maintenance logicielle. " - Bjarne Stroustrup. Voir aussi CPPTIFS.COM/PROT_DATA .



6
votes

Je recommanderais d'utiliser Enter_frame en tant que maître "TICK" pour votre moteur de jeu. Enter_frame Lignes Up Exactement avec le framerate de Flash Player, qui est le vrai framerate maximum de votre code s'exécutera à. Les minuteries, etc., ne sont que des approximations et ne peuvent pas exécuter plus rapidement que Enter_frame.

En fait, alors que j'utilise à l'origine des minuteries pour toutes mes affaires, je m'éloigne lentement à cause de problèmes d'aliasing. Si vous définissez votre minuterie pour 30FPS, mais le lecteur Flash finit par fonctionner à 15fps, la minuterie se retrouvera à l'envoi de la minuterie de la minuterie deux fois entre Enter_Frame Events. Si ces événements de minuterie conduisent à un code coûteux (ce qu'ils voudraient s'il s'agit de la coche de votre moteur de jeu), il a le potentiel de pousser le lecteur réel framerate inférieur (parce que maintenant vous cochez deux fois par Enter_frame) .

Donc, la minuterie est bonne si vous avez quelque chose que vous souhaitez courir périodiquement, mais que vous courez n'importe quoi près de votre framerate réel de votre SWF, je recommanderais d'utiliser le framate et le réglage de votre logique SWF.

Une approche consiste à calculer le temps Deltas sur chaque Enter_frame. Si vous avez une logique temps basée sur le temps, c'est la meilleure approche. Une autre approche, si votre SWF suppose un taux de mise à jour fixe (comme le code basé sur la minuterie), consiste à appeler la méthode de votre jeu de votre jeu si vous avez dépassé le Delta Time Delta sur un Entre_frame.

Je voudrais pas recommandez de faire deux tiques par Enter_frame si vous tombez derrière (ou vous vous retrouverez avec la même situation que les minuteries). À un moment donné, votre jeu doit ralentir ou devient injouable (parce que les Deltas deviennent trop gros). Faire plus d'une tique par Enter_frame Lorsque vous êtes déjà ralentissé, vous ne vous rallierez que plus loin. Les utilisateurs peuvent mieux gérer ralentissez gameplay qu'elles ne peuvent sauter gameplay.


1 commentaires

Merci pour les précieuses informations! La chose est que j'utilise une combinaison des deux. Enter_frame pour mon personnage déplacé de la souris et la minuterie pour le déplacement de voitures ... La bonne chose, c'est que le "décalage" que j'ai mentionné dans ma question ci-dessus n'a été expérimenté que dans l'outil de création de flash. Lorsque j'ai ouvert le SWF seul (en cours d'exécution dans un lecteur flash autonome), la vitesse était parfaite 30 fps.



0
votes

Le problème vient probablement du fait que les minuteries ne sont pas vraiment fiables en ce sens qu'ils ne sont pas aussi fps indépendants que nous pensons qu'ils sont. Lorsque le framate tombe, pour une raison quelconque, les minuteries seront également appelées aussi souvent. Ceci est assez différent que le comportement en C, C ++ ou d'autres langages de l'OOP et de nombreuses personnes tombent donc pour ce piège.

Pour éviter cela, essayez d'utiliser l'événement Enter_frame en tant que boucle de jeu principale et à l'intérieur de cette boucle, évaluez le moment de savoir si vous devez effectuer une ou plusieurs mises à jour de votre logique de jeu. Cela rendra votre code totalement fps indépendant. Vous pouvez utiliser l'appel Flash.Utils.getimer pour obtenir le temps depuis le lancement.

J'ai écrit un message à ce sujet sur mon site Web: http://fabricebacquart.info/wordpress/?p=9


0 commentaires