Skip to content
This repository was archived by the owner on Feb 7, 2024. It is now read-only.

Commit a030c3c

Browse files
committed
stage scrolling
1 parent 95e6c12 commit a030c3c

File tree

15 files changed

+245
-107
lines changed

15 files changed

+245
-107
lines changed

TODO.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
- Make character bigger
2+
- Camera moving
3+
- store layer
4+
- Make slide primitives
5+
- Game controller controls

demo/character.js

Lines changed: 55 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
import React, { Component, PropTypes } from 'react';
2-
32
import { observer } from 'mobx-react';
3+
import Gamepad from 'html5-gamepad';
4+
import Matter from 'matter-js';
45

56
import {
67
Body,
78
Sprite,
89
} from '../src';
910

10-
import Matter from 'matter-js';
11+
const gamepad = new Gamepad();
1112

1213
@observer
1314
export default class Character extends Component {
@@ -18,58 +19,89 @@ export default class Character extends Component {
1819
};
1920

2021
static contextTypes = {
21-
loop: PropTypes.object,
22+
engine: PropTypes.object,
2223
scale: PropTypes.number,
2324
};
2425

25-
loop = () => {
26-
const { keys } = this.props;
26+
move = (body, x) => {
27+
Matter.Body.setVelocity(body, { x, y: 0 });
28+
};
29+
30+
jump = (body) => {
31+
this.isJumping = true;
32+
Matter.Body.applyForce(
33+
body,
34+
{ x: 0, y: 0 },
35+
{ x: 0, y: -0.15 },
36+
);
37+
Matter.Body.set(body, 'friction', 0);
38+
}
39+
40+
update = () => {
41+
const { keys, store } = this.props;
42+
const { body } = this.body;
2743

28-
if (keys) {
44+
const shouldMoveStageLeft = body.position.x < 448 && store.stageX < 0;
45+
const shouldMoveStageRight = body.position.x > 448 && store.stageX > -1024;
46+
47+
if (body.velocity.y === 0) {
48+
this.isJumping = false;
49+
Matter.Body.set(body, 'friction', 1);
50+
}
51+
52+
if (keys && !this.isJumping) {
2953

3054
let characterState = 2;
3155

32-
if (keys.isDown(keys.LEFT)) {
33-
this.body.body.position.x -= 1;
34-
characterState = 1;
35-
} else if (keys.isDown(keys.RIGHT)) {
36-
this.body.body.position.x += 1;
37-
characterState = 0;
56+
gamepad.update();
57+
58+
if (keys.isDown(keys.SPACE) || gamepad.button(0, 'a')) {
59+
this.jump(body);
3860
}
3961

40-
if (keys.isDown(keys.UP)) {
41-
Matter.Body.applyForce(
42-
this.body.body,
43-
{ x: 0, y: 0 },
44-
{ x: 0, y: -0.025 },
45-
);
62+
if (keys.isDown(keys.LEFT) || gamepad.button(0, 'button 14')) {
63+
if (shouldMoveStageLeft) {
64+
store.setStageX(store.stageX + 5);
65+
} else {
66+
this.move(body, -5);
67+
}
68+
69+
characterState = 1;
70+
} else if (keys.isDown(keys.RIGHT) || gamepad.button(0, 'button 15')) {
71+
if (shouldMoveStageRight) {
72+
store.setStageX(store.stageX - 5);
73+
} else {
74+
this.move(body, 5);
75+
}
76+
77+
characterState = 0;
4678
}
4779

48-
this.props.store.setCharacterPosition(this.body.body.position);
80+
store.setCharacterPosition(body.position);
4981

5082
this.setState({
5183
characterState,
5284
});
5385
}
54-
5586
};
5687

5788
constructor(props) {
5889
super(props);
5990

6091
this.loopID = null;
92+
this.isJumping = false;
6193

6294
this.state = {
6395
characterState: 2,
6496
};
6597
}
6698

6799
componentDidMount() {
68-
this.loopID = this.context.loop.subscribe(this.loop);
100+
Matter.Events.on(this.context.engine, 'afterUpdate', this.update);
69101
}
70102

71103
componentWillUnmount() {
72-
this.context.loop.unsubscribe(this.loopID);
104+
Matter.Events.off(this.context.engine, 'afterUpdate', this.update);
73105
}
74106

75107
getWrapperStyles() {
@@ -88,7 +120,7 @@ export default class Character extends Component {
88120
return (
89121
<div style={this.getWrapperStyles()}>
90122
<Body args={[
91-
0, 400, 64, 64, { inertia: Infinity }]
123+
0, 384, 64, 64, { inertia: Infinity, restitution: 0, friction: 1, frictionStatic: 0 }]
92124
}
93125
ref={(b) => { this.body = b; }}
94126
>

demo/demo.js

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import React, { Component } from 'react';
22

33
import {
44
Loop,
5-
Camera,
5+
Stage,
66
KeyListener,
77
World,
88
} from '../src';
@@ -13,7 +13,39 @@ import GameStore from './stores/game-store';
1313

1414
import './index.css';
1515

16+
import Matter from 'matter-js';
17+
1618
export default class Demo extends Component {
19+
20+
physicsInit = (engine) => {
21+
const ground = Matter.Bodies.rectangle(
22+
448 * 2, 448,
23+
1024 * 2, 64,
24+
{
25+
isStatic: true,
26+
},
27+
);
28+
29+
const leftWall = Matter.Bodies.rectangle(
30+
-96, 288,
31+
64, 576,
32+
{
33+
isStatic: true,
34+
},
35+
);
36+
37+
const rightWall = Matter.Bodies.rectangle(
38+
992, 288,
39+
64, 576,
40+
{
41+
isStatic: true,
42+
},
43+
);
44+
45+
Matter.World.addBody(engine.world, ground);
46+
Matter.World.addBody(engine.world, leftWall);
47+
Matter.World.addBody(engine.world, rightWall);
48+
}
1749
constructor(props) {
1850
super(props);
1951

@@ -23,7 +55,7 @@ export default class Demo extends Component {
2355
this.keyListener.subscribe([
2456
this.keyListener.LEFT,
2557
this.keyListener.RIGHT,
26-
this.keyListener.UP,
58+
this.keyListener.SPACE,
2759
]);
2860
}
2961
componentWillUnmount() {
@@ -32,15 +64,19 @@ export default class Demo extends Component {
3264
render() {
3365
return (
3466
<Loop>
35-
<Camera>
36-
<World>
37-
<Level />
67+
<Stage>
68+
<World
69+
onInit={this.physicsInit}
70+
>
71+
<Level
72+
store={GameStore}
73+
/>
3874
<Character
3975
store={GameStore}
4076
keys={this.keyListener}
4177
/>
4278
</World>
43-
</Camera>
79+
</Stage>
4480
</Loop>
4581
);
4682
}

demo/level.js

Lines changed: 69 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,63 +1,80 @@
1-
import React, { Component } from 'react';
1+
import React, { Component, PropTypes } from 'react';
2+
import { autorun } from 'mobx';
23

34
import {
4-
Body,
55
TileMap,
66
} from '../src';
77

8+
import GameStore from './stores/game-store';
9+
810
export default class Level extends Component {
11+
12+
static contextTypes = {
13+
scale: PropTypes.number,
14+
};
15+
16+
constructor(props) {
17+
super(props);
18+
19+
this.state = {
20+
stageX: 0,
21+
};
22+
}
23+
24+
componentDidMount() {
25+
this.cameraWatcher = autorun(() => {
26+
const targetX = Math.round(GameStore.stageX * this.context.scale);
27+
this.setState({
28+
stageX: targetX,
29+
});
30+
});
31+
}
32+
33+
componentWillUnmount() {
34+
this.cameraWatcher();
35+
}
36+
37+
getWrapperStyles() {
38+
return {
39+
position: 'absolute',
40+
transform: `translate(${this.state.stageX}px, 0px)`,
41+
transformOrigin: 'top left',
42+
};
43+
}
44+
945
render() {
1046
return (
11-
<TileMap
12-
{...this.props}
13-
src="assets/background.png"
14-
renderTile={(tile, src, styles) => {
15-
if (tile.index === 5) {
16-
return (
17-
<Body args={[
18-
tile.left, tile.top, tile.size, tile.size,
19-
{ isStatic: true },
20-
]}>
21-
<img
22-
style={styles}
23-
src={src}
24-
/>
25-
</Body>
26-
);
27-
} else {
28-
return (
29-
<img
30-
style={styles}
31-
src={src}
32-
/>
33-
);
34-
}
35-
}}
36-
layers={[
37-
[
38-
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
39-
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
40-
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
41-
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
42-
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
43-
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
44-
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
45-
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
46-
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
47-
],
48-
[
49-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
50-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
51-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
52-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
53-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
54-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
55-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
56-
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
57-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
58-
],
59-
]}
60-
/>
47+
<div style={this.getWrapperStyles()}>
48+
<TileMap
49+
{...this.props}
50+
src="assets/background.png"
51+
columns={32}
52+
layers={[
53+
[
54+
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
55+
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
56+
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
57+
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
58+
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
59+
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
60+
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
61+
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
62+
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
63+
],
64+
[
65+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
66+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
67+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
68+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
69+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
70+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
71+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
72+
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
73+
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
74+
],
75+
]}
76+
/>
77+
</div>
6178
);
6279
}
6380
}

demo/stores/game-store.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,16 @@ import { observable } from 'mobx';
22

33
class GameStore {
44
@observable characterPosition = { x: 0, y: 0 };
5+
6+
@observable stageX = 0;
7+
58
setCharacterPosition(position) {
69
this.characterPosition = position;
710
}
11+
12+
setStageX(x) {
13+
this.stageX = x;
14+
}
815
}
916

1017
export default new GameStore();

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
"license": "MIT",
2323
"repository": "https://github.com/FormidableLabs/react-music",
2424
"dependencies": {
25+
"html5-gamepad": "^0.1.4",
2526
"matter-js": "^0.10.0"
2627
},
2728
"peerDependencies": {

public/assets/background.png

-348 Bytes
Loading

0 commit comments

Comments
 (0)