@@ -6,17 +6,20 @@ url: custom_components
6
6
7
7
# Custom Components
8
8
9
- KAPLAY uses a flexible component system that helps you compose game logic.
9
+ KAPLAY uses a flexible component system that helps you compose game objects
10
+ logic.
10
11
11
- Let's take a look at how the default component ` lifespan() ` is implemented.
12
+ Let's take a look at how the default component ` lifespan() ` is implemented:
12
13
13
14
``` js
14
15
function lifespan (time ) {
15
16
let timer = 0 ;
17
+
16
18
return {
17
19
id: " lifespan" ,
18
20
update () {
19
21
timer -= dt ();
22
+
20
23
if (timer <= 0 ) {
21
24
destroy (this );
22
25
}
@@ -25,50 +28,119 @@ function lifespan(time) {
25
28
}
26
29
```
27
30
28
- Components are just plain functions that returns an object. The return object
29
- will contain all the exposed states, methods, and event hooks of the component.
30
- In this case, the ` lifespan() ` component returns an ` id ` , which is a string
31
- which serves as an unique identification of the comp. There's also an
32
- ` update() ` , which is an event hook that'll run every frame. All ` this ` inside
33
- the component functions refer to the game obj it's attached to.
31
+ Components are just functions that returns an object. The return object will
32
+ contain all the exposed states, methods, and event hooks of the component.
33
+
34
+ In this case, the ` lifespan() ` component returns:
35
+
36
+ - ` id ` : unique identification of the comp, used in require, ` .unuse() ` , etc.
37
+ - ` update() ` : an event hook that'll run every frame and only exists while the
38
+ component is attached to a Game Object.
39
+
40
+ Also, all ` this ` inside the component functions refer to the ** Game Object**
41
+ it's attached to.
34
42
35
- All special fields:
43
+ Here's a list of all special fields you can use in your component :
36
44
37
45
``` js
38
- function mycomp () {
39
- // use closed local variable for internal data
46
+ function myComp () {
47
+ // Use closed local variable for internal data
40
48
let data = 123 ;
49
+
41
50
return {
42
51
id: " mycomp" ,
43
- // if this comp requires other comps to work
52
+ // If this comp requires other comps to work, we use comp ids
44
53
require: [" area" , " pos" ],
45
- // runs when the obj is added to scene
54
+ // Runs when the obj is added to scene
46
55
add () {
47
56
debug .log (" Hi! This should only be fire once." );
48
57
},
49
- // runs every frame
58
+ // Runs every frame
50
59
update () {
51
- // we 're using a method from "pos" comp here, so we declare require "pos" above
60
+ // We 're using a method from "pos" comp here, so we declare require "pos" above
52
61
this .move (200 , 0 );
53
62
},
54
- // runs every frame, after update
63
+ // Runs every frame, after update
55
64
draw () {
56
65
drawLine (this .pos , mousePos ());
57
66
},
58
- // runs when obj is destroyed
67
+ // Runs when obj is destroyed
59
68
destroy () {
60
- debug .log (" Oh bye" );
69
+ debug .log (" Oh bye :< " );
61
70
},
62
- // what to display in inspect mode
71
+ // What to display in debug inspect mode
63
72
inspect () {
64
73
return " some state that deserves to be shown in inspect mode" ;
65
74
},
66
75
};
67
76
}
68
77
```
69
78
70
- Most KAPLAY built-in components are built using public interfaces, feel free to
71
- check them out. Also check out the "drag", "platformer", "doublejump" demos with
72
- their own custom components.
79
+ All KAPLAY built-in components are implemented this way. You can check the
80
+ source code
81
+ [ here ] ( https://github.com/kaplayjs/kaplay/tree/master/src/ecs/components )
73
82
74
83
Check out the [ component demo] ( https://play.kaplayjs.com/?example=component ) .
84
+
85
+ ## TypeScript
86
+
87
+ If you're using TypeScript, we recommend creating an specific type for your
88
+ component:
89
+
90
+ ``` ts
91
+ // You can import types from kaplay package
92
+ import type { Comp } from " kaplay" ;
93
+
94
+ interface MyCustomComp extends Comp {
95
+ // you just need to declare new stuff here
96
+ myCustomProp: number ;
97
+ myCustomMethod: (arg : string ) => void ;
98
+ }
99
+
100
+ function myCustomComp(): MyCustomComp {
101
+ return {
102
+ id: " myCustomComp" ,
103
+ myCustomProp: 123 ,
104
+ myCustomMethod(arg ) {
105
+ console .log (arg );
106
+ },
107
+ };
108
+ }
109
+ ```
110
+
111
+ When you want to use ` this ` inside any component method, but TypeScript doesn't
112
+ know what type it is, you can type ` this ` to ` GameObj<MyCustomComp> ` :
113
+
114
+ ``` ts
115
+ function myCustomComp(): MyCustomComp {
116
+ return {
117
+ id: " myCustomComp" ,
118
+ myCustomMethod(this : GameObj <MyCustomComp > arg ) {
119
+ this .myCustomProp ; // typed from MyCustomComp
120
+ this .tags // typed from GameObjRaw
121
+ },
122
+ };
123
+ }
124
+ ```
125
+
126
+ Even better if you got a component that requires other components, you can use
127
+ ` GameObj<YourComp | OtherComp> ` to type ` this ` .
128
+
129
+ ``` ts
130
+ function specie(specie : string ): SpecieComp {
131
+ return {
132
+ id: " specie" ,
133
+ require: [" color" ],
134
+
135
+ specie: specie ,
136
+ evolve(this : GameObj <SpecieComp >, specie : string ) {
137
+ this .specie = specie ;
138
+ this .tag (specie );
139
+ },
140
+ evil(this : GameObj <SpecieComp | ColorComp >) {
141
+ // this.color is typed
142
+ this .color = Color .RED ;
143
+ },
144
+ };
145
+ }
146
+ ```
0 commit comments