Skip to content

Commit

Permalink
working on ui and physics docs
Browse files Browse the repository at this point in the history
  • Loading branch information
Marco Stagni committed Feb 22, 2022
1 parent 8c0f766 commit 895c320
Show file tree
Hide file tree
Showing 48 changed files with 4,767 additions and 27 deletions.
Binary file modified .DS_Store
Binary file not shown.
7 changes: 7 additions & 0 deletions docs/engine/_sidebar.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,12 @@
- [3. Orbit](/engine/advanced/controls/orbit.md)
- [4. Transform](/engine/advanced/controls/transform.md)
- [5. Fly](/engine/advanced/controls/fly.md)
- Scripting
- Builtin
- [1. BaseCar](/engine/advanced/scripting/builtin/basecar.md)
- [2. SmoothCarFollow](/engine/advanced/scripting/builtin/smoothcarfollow.md)
- [3. Trails](/engine/advanced/scripting/builtin/trails.md)
- [1. Scripts](/engine/advanced/scripting/scripts.md)
- Effects
- [1. PostProcessing](/engine/advanced/effects/postprocessing.md)
- [2. Particles](/engine/advanced/effects/particles.md)
Expand All @@ -67,6 +73,7 @@
- [2. Features](/engine/utilities/features.md)
- [3. Workers](/engine/utilities/workers.md)
- [Router](/engine/advanced/router.md)
- [GameRunner](/engine/advanced/gamerunner.md)
- [Animations](/engine/advanced/animations.md)
- [State Machines](/engine/advanced/state_machines.md)
- [Physics](/engine/advanced/physics.md)
Expand Down
1 change: 1 addition & 0 deletions docs/engine/advanced/gamerunner.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# GameRunner
File renamed without changes.
Binary file modified docs/engine/getting-started/.DS_Store
Binary file not shown.
118 changes: 117 additions & 1 deletion docs/engine/getting-started/driving_around.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,120 @@ const assets = {
Similarly to textures, the engine will preload the models and will make them available to use in your levels.


## Configuring the car
## Configuring the car

In order to create our car, we're going to do a few things:
- Import the chassis
- Import the wheels
- Use one of the engine builtin scripts, called `BaseCar`. This will handle everything that's needed for the car to work just fine (Input handling, initial setup) and it's fully customisable.

?> The engine has a number of builtin scripts, and `BaseCar` is just one of them. Please head over to the dedicated page [here](/engine/advanced/scripting/scripts.md).

Let's create a couple new functions for this in our level:

?> Why are we creating a bunch of functions in the same file? For simplicity's sake.

```js
import {
// previous imports
Models
} from 'mage-engine';

// inside our level once again
createWheel(wheelNo) {
return Models.getModel('wheel', { name: `wheel_${wheelNo}` });
}

createCar() {
const car = Models.getModel('car', { name: 'mycar' });
car.setPosition({ y: 14 });

const wheels = [
this.createWheel(1),
this.createWheel(2),
this.createWheel(3),
this.createWheel(4),
];

car.addScript(Scripts.BUILTIN.BASECAR, {
wheels,
mass: 100,
wheelsOptions: {
back: {
axisPosition: -1.25,
radius: .35,
halfTrack: 1,
axisHeight: 0
},
front: {
axisPosition: 1.2,
radius: .35,
halfTrack: 1,
axisHeight: 0
}
},
suspensions: {
stiffness: 20.0,
damping: 2.3,
compression: 4.4,
restLength: 0.6
}
});

return car;
}

onCreate() {
// what we had before
const car = this.createCar();

// moving camera a bit further
const camera = Scene.getCamera();
camera.setPosition({ x: -10, y: 15, z: -10 });
camera.lookAt({ x: 0, y: 0, z: 0 });
}
```

The creation process is pretty straightforward. Invoking `this.createCar` will import the chassis model into the scene, import 4 wheels, then assign the `BASECAR` builtin script to the car itself.

?> The `BASECAR` script is not very complicated, but it allows you to define a vehicle, its mass, suspensions and wheels in a very easy way. More information on that in its dedicated page [here](/engine/advanced/scripting/builtin/basecar.md).

?> For the purpose of this example, we moved the camera to be in `{ x: -10, y: 15, z: -10 }`, focused on the origin. This will allow us to watch the action a bit better. In the next guide the three lines setting the camera position will not be needed.

### How does this look like?

Run your application, and use `w`,`s`, `a`, and `d` to control the car. Hopefully, something like this:

<video controls height="480" width="640" style="display: block; margin: auto; ">
<source src="engine/getting-started/img/falling_car.mp4"
type="video/mp4">
Sorry, your browser doesn't support embedded videos.
</video>

!> Quick note: we are spawning cubes in random positions with random rotations. This means that they might spawn underneath the car, making it flip. Just reload the page until everything runs fine! This is just a demo, so edge cases like this one are not covered.

## Follow that car!

This is looking quite nice, right? it would be even nicer if the camera was able to follow the car around! Luckily, this is easily obtainable using another builtin script, called `SMOOTH_CAR_FOLLOW`. Remember the few lines of code we just wrote where we placed the camera at a fixed position? Let's remove those and replace them with the following:

```js
Scene.getCamera().addScript(Scripts.BUILTIN.SMOOTH_CAMERA_FOLLOW, { target: car });
```

The script options must include a target, which is the car we just created.

?> The `SMOOTH_CAR_FOLLOW` script is configurable, and its API is fully described [here](/engine/advanced/scripting/builtin/smooth_car_follow.md).

Let's have a look at how it is now!

<video controls height="480" width="640" style="display: block; margin: auto; ">
<source src="engine/getting-started/img/following_car.mp4"
type="video/mp4">
Sorry, your browser doesn't support embedded videos.
</video>

In case you're wondering, jumping off the platform is not needed.

### What happens now?

We covered a lot of information over the past guides. We now know how to handle lights, scripts, user input, cameras and textures, as well as loading up models into the scene. There is one thing left to do, show the player a nice [UI](/engine/getting-started/ui.md);
Binary file added docs/engine/getting-started/img/falling_car.mp4
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Binary file added docs/engine/getting-started/img/following_car.mp4
Binary file not shown.
4 changes: 2 additions & 2 deletions docs/engine/getting-started/installing-mage-engine.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ Installing the Engine is as simple as running the following npm command:
npm install --save mage-engine@latest
```

This will install mage-engine v3.16.1 . You should be able to see something like this in your `package.json` under the `dependencies` section:
This will install mage-engine v3.16.3 . You should be able to see something like this in your `package.json` under the `dependencies` section:

```json
"libraryA": "0.0.1",
"anotherLibrary": "1.11.1",
"inferno": "7.3.2",
"mage-engine": "3.16.1",
"mage-engine": "3.16.3",
```

This is everything you need to do in order to start. Check the next step on how to set up your project before creating your first scene.
Expand Down
76 changes: 72 additions & 4 deletions docs/engine/getting-started/physics.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,83 @@ createFloor() {
floor.enablePhysics({ mass: 0 });
}

onUpdate(dt) {
if (cameraTarget) {
Scene.getCamera().lookAt(this.cameraTarget.getPosition());
}
}

onCreate() {
// same code as before
cube.setPosition({y : 20 });
cube.enablePhysics({ mass: 1 });
cube.setPosition({ y : 50 });
cube.setRotation({ x: Math.random(), y: Math.random(), z: Math.random() });
cube.enablePhysics({ mass: 0.1 });

this.cameraTarget = cube;
}
```

- `floor.enablePhysics()` and `cube.enablePhysics()` are all that's needed to enable physics for these two elements. The method requires a set of options:
- `mass`: this is the most important value. When set to `0`, will make the element static. Any value above `0` will make the element dynamic.
- We increased the cube `y` position to `20`.
- We increased the cube `y` position to `50`.
- We set a random rotation for the cube using `cube.setRotation()`.

- `onUpdate` : this is a level lifecycle method. It will be invoked at every frame, and it will receive the elapsed delta time as parameter. In here, we're telling the camera to look at the camera target (the cube).

?> More information on the `onUpdate` and other lifecycle methods can be found [here](/engine/advanced/core/level.md).

If everything has gone right, this is what you should be able to see now:

<video controls height="480" width="640" style="display: block; margin: auto; ">
<source src="engine/getting-started/img/falling_purple_cube.mp4"
type="video/mp4">
Sorry, your browser doesn't support embedded videos.
</video>

### From one to many
Sure, one falling cube looks nice, but what about 50 small ones? We can have something like this:

```js
import {
// previous imports
math
} from 'mage-engine';

// inside our level
generateCubes() {
for (let i=0; i<50; i++) {
const cube = new Cube(1);
cube.setName(`${i}`);
cube.setTextureMap('purple');
cube.setPosition({
x: math.randomIntFromInterval(-10, 10),
y: Math.random() * 5 + 10,
z: math.randomIntFromInterval(-10, 10)
});
cube.setRotation({
x: Math.random(),
y: Math.random(),
z: Math.random()
});

cube.setMaterialFromName(constants.MATERIALS.STANDARD);

cube.enablePhysics({ mass: .1 });
}
}

onUpdate() {
// if (cameraTarget) {
// Scene.getCamera().lookAt(this.cameraTarget.getPosition());
// }
}

onCreate() {
// same as before
this.generateCubes();
}
```

## Let's go for a drive now

If everything has gone right, this is what you should be able to see now
We created a platform, we created 50 "obstacles". What's the best way to proceed? Drive through the obstacles and watch them flying! Let's start [driving around](/engine/getting-started/driving-around.md).
109 changes: 109 additions & 0 deletions docs/engine/getting-started/ui.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
# User Interface

This guide will give you a short introduction to UI. Mage engine uses `inferno` for its components and `redux` for state management.

!> This guide is assuming you have basic knowledge of how React-like UI frameworks work, so it's not going into details when it comes to the inner workings of the framework.

?> The topic is quite extensive, and it's fully covered in its dedicated page. For more information about state management, head over [here](/engine/advanced/state_management.md). If you need a deeper introduction to UI, please refer to [this page](/engine/advanced/ui.md).

For this guide, we're going to introduce two simple components, one called `SpeedIndicator` and another one called `ResetButton`.
First, let's create the `SpeedIndicator` component.

### SpeedIndicator.js

```js
const SpeedIndicator = ({ speed }) => {
return (
<span>
{ speed }
</span>
);
};

export default SpeedIndicator
```

Pretty self explanatory, this will render a component that contains a `span` displaying the current speed of the car.

### ResetButton.js

```js
const ResetButton = ({ onClick }) => {
return (
<button onClick={onClick}>
reset
</button>
);
};

export default ResetButton;
```

This one is quite easy as well. It will display a button on screen: its purpose is to reset the car to its initial position if you fall off the edge.

### Root.js

Let's now create a root component that will take care of both child components.

```js
import { Component, GameRunner } from 'inferno';

class Root extends Component {
constructor(props) {
super(props);

this.state = {
speed: 0
};
}

componentDidMount() {
const level = GameRunner.getCurrentLevel();
setInterval(() => {
if (level.car) {
const { speed } = level.car.getPhysicsState();
this.setState({ speed });
}
}, 250);
}

handleResetButtonClick = () => {
GameRunner.getCurrentLevel().resetCar();
}

render() {
const { speed } = this.state;

return (
<>
<SpeedIndicator speed={speed}>
<ResetButton onClick={this.handleResetButtonClick}>
</>
)
}
}
```

What is happening in `Root.js`:
- We set up a timer, every `250ms` we're going to get the current running level, get the car instance and extract its speed.
- `GameRunner.getCurrentLevel()`: belongs to the `GameRunner` module, which is responsible for running your levels. This method will return the instance of the level that is currently playing.
- `car.getPhysicsState()` will return the current physic state for the object.

?> More information on `GameRunner` is available on its dedicated page [here](/engine/advanced/gamerunner.md). The same applies for the `Element` [page](/engine/advanced/core/element.md), where `getPhysicsState` is explained.

## Enabling UI

Enabling UI is pretty straightforward. Just head over your configuration object, and add the following:

```js
import Root from './path/to/Root.js';

const config = {
// previous config
ui: {
root: Root
}
}
```

?> Again, configuration has its dedicated page [here](/engine/advanced/configuration.md).
11 changes: 10 additions & 1 deletion docs/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,22 @@
<link rel="icon" type="image/png" href="favicon.ico">
<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/docsify-sidebar-collapse/dist/sidebar.min.css" />
<link rel="stylesheet" href="./css/style.css">
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-434GQWY0J2"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());

gtag('config', 'G-434GQWY0J2');
</script>
</head>

<body>
<div id="app">Loading...</div>
<script>
window.$docsify = {
name: 'v3.16.1',
name: 'v3.16.3',
repo: 'https://github.com/MageStudio/Mage',
loadSidebar: true,
auto2top: true,
Expand Down
Binary file modified examples/.DS_Store
Binary file not shown.
3 changes: 3 additions & 0 deletions examples/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@
<li class='example' data-src='./cube-texture/index.html'>Textures</li>
<li class='example' data-src='./lights/index.html'>Lights and skybox</li>
<li class='example' data-src='./physics/index.html'>physics</li>
<li class='example' data-src='./physics_many/index.html'>physics many</li>
<li class='example' data-src='./physics_car/index.html'>physics car</li>
<li class='example' data-src='./physics_car_ui/index.html'>physics car UI</li>
</ul>
<iframe class='example-frame'></iframe>

Expand Down
Loading

0 comments on commit 895c320

Please sign in to comment.