Les sprites comme acteurs

12

Je n'ai pas d'expérience dans les questions de développement de jeux, mais en tant que programmeur. Dans la langue Scala, vous pouvez avoir des multi-tâches évolutives avec des acteurs, très stables, d'après ce que j'entends. Vous pouvez même en exécuter des centaines de milliers sans problème.

J'ai donc pensé que vous pourriez peut-être les utiliser comme classe de base pour les sprites 2D, pour sortir de la boucle de jeu qui nécessite de parcourir tous les sprites et de les déplacer. Ils se déplaceraient essentiellement, en fonction des événements.

Est-ce que cela aurait du sens pour un jeu? L'avoir multitâche comme ça? Après tout, il fonctionnera sur la JVM, bien que cela ne devrait plus être un problème de nos jours.

ÉDITER:

Après avoir barboté pendant un certain temps, j'ai remarqué qu'il n'y a qu'un seul avantage réel à cette idée: le support multicœur. Une boucle de jeu simple ne fonctionnera que sur un seul cœur et fonctionnera de manière séquentielle.

Étant donné que les ordinateurs modernes, même à la maison, ont de nos jours deux cœurs ou plus intégrés, je pense que c'est une bonne idée de permettre aux programmeurs de jeux d'utiliser efficacement les autres cœurs. Après tout, je pense que le joueur n'aura généralement que le jeu sur sa machine à huit cœurs, alors pourquoi pas.

L'autre avantage que je vois est que dans Scala, vous pouvez avoir RemoteActors, qui peut être traité de la même manière mais exécuté sur un autre ordinateur. Alors peut-être que cela peut également simplifier les jeux en réseau.

J'ai l'intention d'intégrer cela dans mon moteur Scala 2D dès que possible.

Lanbo
la source
Je serais très intéressé de savoir comment cela se passe. J'ai regardé Scala plusieurs fois mais je n'y ai jamais plongé auparavant.
Davy8
Beaucoup diront que pour une prise en charge multicœur explicite, il vaut mieux utiliser des threads plutôt que des processus (et des processus de modèle d'acteurs Scala). En effet, vous pouvez tirer parti de la mémoire partagée entre les threads. Bien sûr, cela est sujet aux erreurs, contrairement au modèle Actor.
Kylotan
Les acteurs Scala sont multiplexés au-dessus d'un pool de threads, de sorte qu'ils pourraient être plus légers que les threads. Cela signifie qu'ils peuvent manipuler la mémoire partagée pour communiquer, à condition qu'elle soit correctement synchronisée. Si vous utilisez des acteurs distants, ils peuvent être sur des processus différents et la seule façon de communiquer est d'envoyer des messages.
axel22

Réponses:

7

Je n'ai pas essayé, mais je suis programmeur Scala, et je dirais que ce n'est pas la meilleure approche. Les sprites doivent être animés de manière synchrone. Les acteurs n'ont aucune garantie qu'ils seront exécutés équitablement - certains sprites peuvent donc être plus rapides que d'autres, ce qui n'est pas ce que vous voulez. Vous voudrez peut-être utiliser une barrière pour les synchroniser, mais alors - pourquoi utiliser des acteurs. Si vous ne comptez que sur la transmission des messages, l'implémentation de ce type de synchronisation (implémentation d'une barrière pour plus de 1000 acteurs) est une exagération.

Un autre problème est - pourquoi utiliseriez-vous la transmission de messages? Avez-vous besoin de vos sprites pour communiquer? Vous pouvez envoyer un message par le maître acteur, en disant à chaque sprite de passer à l'image suivante, mais en termes de performances, ce sont des magnitudes et des magnitudes plus que d'invoquer directement des méthodes et d'itérer à travers un ensemble de sprites.

Il me semble que ce dont vous avez besoin ici est une sorte de multitâche très léger, et aucun message ne passe du tout. Rouler dans votre propre implémentation de type acteur qui garantit l'équité est probablement la meilleure façon de procéder si vous voulez vous en assurer, mais c'est trop de travail pour trop peu de gain. Une autre chose à regarder est la programmation réactive fonctionnelle et scala.react, je crois que c'est une meilleure correspondance pour ce cas d'utilisation.

J'ai implémenté un moteur de jeu isométrique 2D dans Scala. Je n'ai utilisé qu'un seul acteur mondial pour mettre à jour les sprites visibles qui étaient animés.

Vous souhaiterez peut-être implémenter votre logique de jeu à l'aide d'acteurs - par exemple, pour distribuer des calculs sur différentes parties de votre carte de jeu à différents acteurs, afin qu'ils mettent à jour l'état du jeu en parallèle - et gagner en gain de performances. Je n'utiliserais pas un seul acteur par objet de jeu, plutôt un acteur par région. Si vous optez pour un grain trop fin, les performances en souffrent.

Pourtant, si j'étais vous, j'essaierais, juste pour voir ce qui se passe.

axel22
la source
1

J'ai donc pensé que vous pourriez peut-être les utiliser comme classe de base pour les sprites 2D, pour sortir de la boucle de jeu qui nécessite de parcourir tous les sprites et de les déplacer. Ils se déplaceraient essentiellement, en fonction des événements.

Quel serait l'événement qui les émeut?

Serait-ce un événement que vous émettez une fois par image?

Et si oui, comment cela a-t-il changé le système d'une manière pratique?

Lors de l'étude initiale de l'orientation objet dans le contexte du C ++, j'ai appris que certaines personnes aimaient penser à une déclaration telle xyz.doThis(x)que signifier `` envoyer le message doThis à xyz (avec une charge utile de x) et attendre une réponse immédiate ''. Vu à ce niveau, il n'y a pas de différence intrinsèque entre un système basé sur un événement ou un message et un système procédural normal.

Kylotan
la source
Les acteurs sont une solution multi-thread. Les communications ne sont pas synchrones. Les acteurs Scala (concept d'Erlang) permettent une programmation multi-cœurs facile.
Ellis
Vous avez un point là-dessus, mais la différence ici serait que le sprite basé sur l'acteur ne bloque pas la boucle de jeu pendant l'exécution de l'action, tandis que l'approche par méthode attend que xyz.doThis(x)soit terminée. Je pense que cela pourrait même aider à accélérer la logique du jeu, en particulier sur les systèmes multicœurs.
Lanbo
Cela facilite la distribution de la gestion des entités sur plusieurs cœurs, c'est vrai. Mais le coût de cela est que vous ne pouvez pas facilement vous référer d'un acteur à un autre sans que des messages supplémentaires ou des données supplémentaires soient envoyés dans les messages. Vous vous rendez donc rapidement compte que l'approche naïve ici ne vous aide pas - pouvez-vous formuler une manière basée sur l'acteur d'effectuer les mises à jour?
Kylotan
Actuellement, j'expérimente une sorte de mise à jour distribuée: Mes acteurs sont comme des nœuds dans une arborescence, et la mise à jour de la racine met à jour les enfants, par distribution de messages. En outre, le véritable avantage sera la mise en réseau: dans Scala, un acteur et un RemoteActor (acteur sur un autre système) peuvent être adressés de la même manière, par les mêmes messages.
Lanbo
Oui, mais le problème n'est pas le déclenchement de la mise à jour en tant que tel, c'est de s'assurer que le destinataire du message dispose de toutes les informations nécessaires pour agir en conséquence.
Kylotan
0

C'est une bonne approche pour penser à mettre à jour vos objets de jeu. Je ne connais pas Scala, mais je dis: essayez-le et voyez comment ça se passe, et encore mieux postez vos résultats!

Les principales questions qui me viennent à l'esprit sont: comment gérez-vous la fréquence de mise à jour de certains objets de jeu par rapport à d'autres? Aurez-vous besoin de vous inquiéter du fait que les acteurs des sprites prennent trop de cycles de sorte que le système de rendu n’ait pas le temps de dessiner une image tous les 1 / 60e | 30e | 24e de seconde?

Une autre chose à considérer est de savoir comment cela affectera la résolution des interactions joueur contre IA qui dépendent de l'ordre d'une séquence d'événements très rapides. En fonction du type de jeu, ce ne sera probablement pas beaucoup d' importance.

michael.bartnett
la source
La grande chose au sujet des acteurs Scala est qu'ils sont axés sur les messages. Chacun d'eux a sa propre file d'attente de messages / d'événements. Je ne sais pas si "Draw" devrait être un message ou une méthode d'appel. Je pense que ce sera le dernier, afin qu'un Sprite puisse être dessiné à tout moment, quel que soit l'état de leur file d'attente d'événements. Et ils peuvent s’envoyer des messages pour s’assurer que les choses se font dans un certain ordre.
Lanbo
Soyez prudent là-bas, je ne pense pas que chaque sprite ait une méthode ou un événement Draw serait utile, sauf peut-être comme indicateur pour basculer la visibilité. Dans la phase de rendu d'une boucle de jeu, l'ordre dans lequel les sprites sont rendus à l'écran a un grand effet sur le résultat. Si vous avez un sprite qui se trouve devant l'autre (la dimension étant vers le moniteur), vous voulez que celui-ci soit dessiné en second. Je vois les acteurs de Scala utiles pour la partie mise à jour / logique de la boucle de jeu.
michael.bartnett
Habituellement, vous ne disposez que d'une méthode de dessin, donc en l'implémentant de cette façon, il ne devrait pas y avoir beaucoup de différence avec la façon normale de traiter les sprites.
Lanbo
Ah d'accord, j'ai mal compris ce que vous décriviez. J'imaginais en quelque sorte des sprites qui se rendaient quand et comme bon leur semble. Faites-nous savoir comment cela se passe!
michael.bartnett
0

Eh bien, je ne suis pas vraiment un programmeur non plus, mais je ne vois aucun problème sur votre proposition. Je n'ai même pas pensé à une telle façon de développer des acteurs.

Cela peut être tout un défi, car l'IA doit être très précise, pour éviter un comportement inattendu, mais en plus de cela, je vois que c'est une assez bonne proposition

Carlos Valenzuela
la source
0

Si par sprite vous voulez dire entité de jeu, alors bien sûr.

Les entités de jeu ne devraient jamais se dessiner. Ils doivent mettre à jour une poignée graphique qui décrit où et comment ils doivent être dessinés. Le système de rendu ou le graphique de scène ou tout ce qui fait le dessin réel. Il y a une carte graphique, de plus, la carte graphique doit être synchronisée toutes les 16 ms. Une telle configuration ne fonctionne tout simplement pas bien pour le traitement asynchrone distribué.

Le système de rendu doit être un acteur (ou éventuellement un couple si vous êtes difficile). Lorsque les entités de jeu mettent à jour la poignée graphique, elles envoient des messages au système de rendu. Le système de rendu peut-il prendre toutes sortes de décisions et / ou d'optimisations, par exemple le rendu par lots, l'occlusion, le lissage de la gigue physique, etc.

Je ne suis pas développeur Scala, mais j'en ai fait pas mal avec Erlang. Donc, si une partie de ma terminologie Scala est incorrecte, veuillez me pardonner.

deft_code
la source