user-components.rst 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. .. include:: ../_header.rst
  2. User Components
  3. ---------------
  4. .. toctree::
  5. :maxdepth: 1
  6. user-components-create-file
  7. user-components-editor
  8. user-components-compiler
  9. user-components-start-update-methods
  10. user-components-super-class
  11. user-components-awake-event
  12. user-components-instancing
  13. user-components-in-prefab-object
  14. A Component is a `design pattern <https://gameprogrammingpatterns.com/component.html>`_ that you can use to create reusable code and extend the behavior and data of a game object, using `composition over inheritance <https://en.wikipedia.org/wiki/Composition_over_inheritance>`_.
  15. For example, an **HorizontalMove** component can be added to any kind of enemy object that moves horizontally from one position to another. This component class can be written more or less like this (see the |UserComponentsCompiler|_ section for a real example):
  16. .. code::
  17. class HorizontalMove {
  18. constructor(gameObject) {
  19. // in the component, keep a reference to the entity
  20. this.gameObject = gameObject;
  21. // in the entity, keep a reference ('horizontalMove') to the component
  22. this.gameObject.horizontalMove = this;
  23. // init properties with default values
  24. this.minX = 0;
  25. this.maxX = 800;
  26. this.horizVelocity = 10;
  27. }
  28. start() {
  29. this.gameObject.body.velocity.x = this.horizVelocity;
  30. }
  31. update() {
  32. // the behavior of the component
  33. const velocity = this.gameObject.body.velocity;
  34. if (this.gameObject.x < this.minX) {
  35. velocity.x = Math.abs(this.horizVelocity);
  36. }
  37. if (this.gameObject.x > this.maxX) {
  38. velocity.x = -Math.abs(this.horizVelocity);
  39. }
  40. }
  41. }
  42. In the scene, you can create objects and add the **HorizontalMove** component to them. Then, update the components at every game loop step:
  43. .. code::
  44. class Level extends Phaser.Scene {
  45. create() {
  46. // create two objects, alien and spider, and add the HorizontalMove
  47. // component to both, but with different property values.
  48. this.alien = this.add.sprite(10, 10, "enemies", "alien");
  49. const alienMove = new HorizontalMove(this.alien);
  50. alienMove.minX = 10;
  51. alienMove.maxX = 100;
  52. alienMove.horizVelocity = 40;
  53. alienMove.start();
  54. this.spider = this.add.sprite(80, 100, "enemies", "spider");
  55. const spiderMove = new HorizontalMove(this.spider);
  56. spiderMove.minX = 50;
  57. spiderMove.maxX = 200;
  58. spiderMove.horizVelocity = -20;
  59. spiderMove.start();
  60. }
  61. update() {
  62. // update the HorizontalMove component of each object
  63. this.alien.horizontalMove.update();
  64. this.spider.horizontalMove.update();
  65. // in a real case, the component can register
  66. // a listener to the UPDATE event of the scene.
  67. }
  68. }
  69. In |PhaserEditor|_, we provide a way to create game object components (we name it **User Components**, to make a difference with the built-in Phaser components) and use them in the |SceneEditor|_. The prefabs_ system is another way to create reusable behaviors and data but has the limitation that it uses inheritance.
  70. Like the |SceneEditor|_, we provide a |UserComponentsEditor|_.
  71. The |UserComponentsEditor|_ allows you to create User Components configuration files. A User Components configuration file (``*.components``) contains a list of component configurations that are compiled into JavaScript (or TypeScript) code. It is pretty similar to the |SceneCompiler|_.