You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
For this tutorial, create a new project using the launcher,
25
+
For this tutorial, create a new project using the launcher,
26
26
and when choosing an outline, **select the tutorial project outline**.
27
27
This project is pre-configured so we can dive right in.
28
28
@@ -33,7 +33,7 @@ This project is pre-configured so we can dive right in.
33
33
In order to run our project, we first need to install a module. If you don't, you'll get errors!
34
34
35
35
You can use the launcher to install modules. Head over to the module page, and search for the arcade module.
36
-
Once you find it, you can click through, and click the download arrow.
36
+
Once you find it, you can click through, and click the download arrow.
37
37
38
38
The project is configured to use version `0.0.23`, install that version.
39
39
@@ -45,7 +45,7 @@ The project is configured to use version `0.0.23`, install that version.
45
45
46
46
## Using the module in a project
47
47
48
-
If you look inside of the `luxe.project/modules.lx` file you'll find the `luxe` and `arcade` modules referenced by version.
48
+
If you look inside of the `luxe.project/modules.lx` file you'll find the `luxe` and `arcade` modules referenced by version.
49
49
You can use the launcher to add a module to the project using the `+` icon, or you can manually add it to this file.
50
50
51
51
In this case, it's already there from the outline, so let's move on!
@@ -61,13 +61,13 @@ An Entity in the world can also have modifiers attached that perform logic, and
61
61
62
62
To create an entity, we do `Entity.create(world)` - this gives us a blank entity, and is ready to be modified to give it meaning.
63
63
64
-
The first thing we'll do, is attach a `Transform` modifier. Modifiers use the same `create` pattern,
64
+
The first thing we'll do, is attach a `Transform` modifier. Modifiers use the same `create` pattern,
65
65
and some modifiers add `create` methods with convenience arguments, like we'll see below from `Sprite.create`.
66
66
67
67
Let's create a new `player` variable in our game, and then inside ready we'll create an entity, attach a transform and a sprite to it.
68
68
69
69
??? note "`world_width/world_height` ?"
70
-
Since our tutorial outline is based on the pixel outline, we have a fixed world size that will auto scale. This size is set in `outline/settings.settings.lx` and the size of the world is available in `world_width` and `world_height`. This is different from `width`/`height`, which is the window size.
70
+
Since our tutorial outline is based on the pixel outline, we have a fixed world size that will auto scale. This size is set in `outline/settings.settings.lx` and the size of the world is available in `world_width` and `world_height`. This is different from `width`/`height`, which is the window size.
71
71
72
72
!!! tip "add the highlighted code to `ready`"
73
73
@@ -98,11 +98,11 @@ And just like that, we have our player in the middle of the screen.
98
98
99
99
## Arcade physics
100
100
101
-
The `arcade` module provides collision + physics for a wide range of games, and comes with a bunch of ready to use tools.
101
+
The `arcade` module provides collision + physics for a wide range of games, and comes with a bunch of ready to use tools.
102
102
103
-
The first important one is the Arcade modifier, which gives an entity a collider shape, and allows you to choose flags like whether it's solid or a trigger, what shape it is, change the velocity and more. It also gives us a callback for when we collide with something, so we can implement a response to overlapping or colliding with something.
103
+
The first important one is the Arcade modifier, which gives an entity a collider shape, and allows you to choose flags like whether it's solid or a trigger, what shape it is, change the velocity and more. It also gives us a callback for when we collide with something, so we can implement a response to overlapping or colliding with something.
104
104
105
-
### Arcade import
105
+
### Arcade import
106
106
107
107
We're gonna use the `Arcade` modifier from the `arcade` module to make our bee interact with the world. We'll import that module into the top of our `game.wren` code like this:
108
108
@@ -139,12 +139,12 @@ create_player() {
139
139
Arcade.create(player)
140
140
Arcade.set_shape_type(player, ShapeType.circle)
141
141
Arcade.set_radius(player, 32)
142
-
142
+
143
143
}
144
144
```
145
145
146
-
If we run this, it will look identical to before! That's because there's no gravity or anything on our entity.
147
-
So how do we know it's working? How do we know the radius matches? We can ask `Arcade` to debug draw the physics state.
146
+
If we run this, it will look identical to before! That's because there's no gravity or anything on our entity.
147
+
So how do we know it's working? How do we know the radius matches? We can ask `Arcade` to debug draw the physics state.
148
148
149
149
!!! tip "add the highlighted line to `create_player`"
Our outline includes a scene that has been created for us. This scene includes some background details, and a floor collider which will keep our bee on screen.
181
181
182
-
A scene is a kind of data based asset, a container for pre-configured entities with their modifiers already attached.
182
+
A scene is a kind of data based asset, a container for pre-configured entities with their modifiers already attached.
183
183
184
184
A particular scene can only be loaded once into the same world, but you can load multiple scenes into the same world.
185
185
This makes them useful as a tool to layer or keep things loaded in the world, and much more. Scenes are typically what you would use for stuff like a Menu, or Level based games.
@@ -215,17 +215,17 @@ construct ready() {
215
215
216
216
With that, we'll see the clouds, some buildings, a gradient and we'll see the floor collider. The bee will bounce off the floor, and we're ready for the next step.
The bee jump is a little easy to go off screen, so we'll make a minor change to `create_player()` to give them a max speed, and we'll also enforce that the bee is always in the same position on screen, about a quarter of the way in.
289
289
290
-
```js hl_lines="4"
290
+
```js hl_lines="6"
291
291
create_player() {
292
292
293
293
...
@@ -312,16 +312,16 @@ tick(delta: Num) {
312
312
313
313
Now when we play, we have a couple jumps before we leave the screen, and our bee is in a nice place for the game.
Prototypes are similar to a `Scene`, they are pre-configured entities with their modifiers ready to create.
321
+
Prototypes are similar to a `Scene`, they are pre-configured entities with their modifiers ready to create.
322
322
323
323
!!! info "Prototype vs Scene"
324
-
Prototypes are not limited to one per world like scenes. You can create an **instance** as many times as you need.
324
+
Prototypes are not limited to one per world like scenes. You can create an **instance** as many times as you need.
325
325
326
326
They can be created dynamically like we will below, and they can be placed inside a scene, and inside of other prototypes. Each instance can have the values from the prototype overridden when placed that way.
327
327
@@ -356,7 +356,7 @@ The next step is to move the pillars across the screen, so the player will have
356
356
357
357
!!! note "There's a more detailed guide on [custom modifiers](../../learn/modifiers/custom-modifiers.md) here"
358
358
359
-
To do that, we want to make a modifier that will move any pillar that it is attached to, and when the pillar moves off the left of the screen, clean itself up.
359
+
To do that, we want to make a modifier that will move any pillar that it is attached to, and when the pillar moves off the left of the screen, clean itself up.
360
360
361
361
!!! tip "Create a folder called system/ in the project"
We probably want more than one pillar to come across the level, so we'll use a tool called `World.schedule(world, time, fn)`. This calls a function every `time` seconds, but the important part is that it is affected by the world rate.
483
+
We probably want more than one pillar to come across the level, so we'll use a tool called `World.schedule(world, time, fn)`. This calls a function every `time` seconds, but the important part is that it is affected by the world rate.
484
484
485
485
!!! note "If we used `Frame.schedule(time, fn)` it would be global, and not world specific. With `World.schedule` we can pause by setting the world rate to 0."
486
486
@@ -489,7 +489,7 @@ We probably want more than one pillar to come across the level, so we'll use a t
489
489
...
490
490
491
491
create_player()
492
-
492
+
493
493
create_pillar()
494
494
World.schedule(world, 6, 9999) {
495
495
create_pillar()
@@ -504,11 +504,11 @@ And with that change, we now get a constant stream of pillars to jump over! We h
504
504
505
505
## Handling collision
506
506
507
-
Our last step for this game is handling what happens when you hit something.
507
+
Our last step for this game is handling what happens when you hit something.
508
508
509
509
If you saw the moving pillar video above, the player goes through the walls and keeps jumping forward because of our code to keep it in the same spot.
510
510
511
-
Instead what we'll do is check the direction of the hit, and if you hit a wall (sideways), pause the game world.
511
+
Instead what we'll do is check the direction of the hit, and if you hit a wall (sideways), pause the game world.
512
512
513
513
```js hl_lines="3 7"
514
514
...
@@ -518,7 +518,7 @@ Instead what we'll do is check the direction of the hit, and if you hit a wall (
The check is a little abrupt, and isn't very fun because it's super precise and you can fail easily.
544
+
The check is a little abrupt, and isn't very fun because it's super precise and you can fail easily.
545
545
546
546
To make the game a bit more fun, we'll add some squishy behaviour. When we hit a collider, we get the height and check the distance. If the distance is less than 32 (half the radius of our bee), we've just hit the edge of the collider with the bottom of the bee and we can ignore it.
547
547
548
548
Another tweak, we'll **play a bounce animation** when we hit a flower. This also uses the `Tags` modifier, which allows us to tag entities with specific tags and check for them. In this case, our flower entity inside the pillar prototype already has a tag.
One final task is to make it so you can reset the state so you can try again.
583
583
584
-
We'll add a `reset()` method, first we reset the player position, and unpause the world.
584
+
We'll add a `reset()` method, first we reset the player position, and unpause the world.
585
585
This is called from tick using a simple key check.
586
586
587
587
```js hl_lines="1 2 3 4 8 9 10"
@@ -600,18 +600,18 @@ tick(delta: Num) {
600
600
```
601
601
602
602
Now, our pillars will still be there, so we'll need to clear them up.
603
-
We could keep an array of pillars we create, and then clean them up like we did in the draw tutorial?
603
+
We could keep an array of pillars we create, and then clean them up like we did in the draw tutorial?
604
604
The modifer system we created already knows about all of our pillars though!
605
605
606
-
We can add a public API to our pillar modifier, e.g `Pillar.reset(world)`.
606
+
We can add a public API to our pillar modifier, e.g `Pillar.reset(world)`.
607
607
To do this, we'll add a method to the `API` class in our modifier. This method has access to a method called `system_in`, which gives us our system to call into.
608
608
609
609
```js hl_lines="3 4 5 6"
610
610
classPillar is API {
611
611
612
612
staticreset(world:World) {
613
613
var system: System =system_in(world)
614
-
system.reset()
614
+
system.reset()
615
615
}
616
616
617
617
}
@@ -623,7 +623,7 @@ Now inside of our system, we can add the reset method. This method will simply l
623
623
classSystem is Modifier {
624
624
625
625
...
626
-
626
+
627
627
reset() {
628
628
each {|entity: Entity, pillar: Data|
629
629
Frame.end { Entity.destroy(entity) }
@@ -650,14 +650,14 @@ One more tweak, now that we know it is working: turn off the debug drawer!
0 commit comments