Closed michaelcuneo closed 4 years ago
I've managed to fix this by checking to see if input exists before it creates the payload...
let payload;
if (input) {
payload = input.find(x => x.name === 'onMouseDown');
}
Hi @michaelcuneo,
Thanks for finding and debugging this. I'm a bit stumped, because input
should always be truthy (an array, an empty array) - never undefined
or null
..
I am implementing into Max Stoibers react-boilerplate. I just deleted the HomePage, made a new index.js and threw it all inside there...
Logging the GameEngine shows that it's actually all configured and running.
On further investigation, the input is now undefined from scratch, before and after clicking.
index.js
import React from 'react';
import { Helmet } from 'react-helmet';
import { GameEngine } from 'react-game-engine';
import { Finger } from './Renderers';
import { MoveFinger } from './Systems';
class HomePage extends React.PureComponent {
constructor() {
super();
this.GameEngineRef = React.createRef();
}
componentDidMount() {
this.GameEngineRef.current.start();
}
componentWillUnmount() {
this.GameEngineRef.current.stop();
}
render() {
return [
<Helmet key="Helmet">
<title>Home Page</title>
<meta
name="description"
content="A React.js Boilerplate application homepage"
/>
</Helmet>,
<GameEngine
key="GameEngine"
ref={this.GameEngineRef}
systems={[MoveFinger]}
entities={{
finger1: { position: [20, 200], renderer: <Finger /> },
/* finger2: { position: [40, 200], renderer: <Finger /> }, */
/* finger3: { position: [60, 200], renderer: <Finger /> }, */
}}
running
/>,
];
}
}
export default HomePage;
Renderers.js
import React from 'react';
import PropTypes from 'prop-types';
class Finger extends React.PureComponent {
render() {
console.log(this.props.position[0], this.props.position[1]);
const x = this.props.position[0] + window.innerWidth / 2;
const y = this.props.position[1] + window.innerHeight / 2;
console.log(x, y);
return (
<div
style={{
position: 'absolute',
width: 50,
height: 50,
backgroundColor: 'red',
left: x,
top: y,
transformOrigin: '50% 50%',
}}
/>
);
}
}
Finger.propTypes = {
position: PropTypes.array,
};
export { Finger };
Systems.js
const MoveFinger = (entities, { input }) => {
// -- I'm choosing to update the game state (entities) directly for the sake of brevity and simplicity.
// -- There's nothing stopping you from treating the game state as immutable and returning a copy..
// -- Example: return { ...entities, t.id: { UPDATED COMPONENTS }};
// -- That said, it's probably worth considering performance implications in either case.
let payload;
if (input) {
payload = input.find(x => x.name === 'onMouseDown');
}
if (payload) {
const finger = entities.finger1;
finger.position[0] = payload.pageX;
finger.position[1] = payload.pageY;
}
return entities;
};
export { MoveFinger };
Actually I have modified the example a little, because I was unsure of what RADIUS was, because it's undefined in the example... I used the width and height of the screen halved instead... what's RADIUS meant to be?
RADIUS
is a typo left over from the React Native examples. I still can't see why input
would be undefined.
Can you try and remove the following and see if input
is still undefined?
constructor() {
super();
this.GameEngineRef = React.createRef();
}
componentDidMount() {
this.GameEngineRef.current.start();
}
componentWillUnmount() {
this.GameEngineRef.current.stop();
}
I think I've somehow fixed it while troubleshooting, but didn't see that it had actually been fixed until I now log in System, and see that input is giving me data.
It appears to be working fine, but the objects don't move...
I believe I know what may have occurred, the original index.js was a stateless function() {} instead of a class extending React.PureComponent. I think the switch there may have fixed it partially.
Now to get the object moving. :) The data appears to be getting to the System, entities are returned,
As soon as I click anywhere, the Finger1 position becomes (undefined, undefined)
Found the issue... not 100% sure why, but payload has a tree inside called payload before getting to pageX... so I had to change the following two lines
finger.position[0] = payload.payload.pageX;
finger.position[1] = payload.payload.pageY;
I now get data back from entities, with coordinates for Finger1.
But still no movement of the actual entity.
O.k. turns out, finger is not allowed to be a PureComponent. Changing to Component got it working fine.
Here are my final solutions for making it work.
index.js
import React from 'react';
import { Helmet } from 'react-helmet';
import { GameEngine } from 'react-game-engine';
import Finger from './Renderers';
import { MoveFinger } from './Systems';
class HomePage extends React.PureComponent {
render() {
return [
<Helmet key="Helmet">
<title>Home Page</title>
<meta
name="description"
content="A React.js Boilerplate application homepage"
/>
</Helmet>,
<GameEngine
key="GameEngine"
systems={[MoveFinger]}
entities={{
finger1: { position: [20, 200], renderer: <Finger /> },
finger2: { position: [40, 200], renderer: <Finger /> },
finger3: { position: [60, 200], renderer: <Finger /> },
}}
/>,
];
}
}
export default HomePage;
Renderers.js
import React from 'react';
import PropTypes from 'prop-types';
class Finger extends React.Component {
render() {
const x = this.props.position[0];
const y = this.props.position[1];
console.log(x, y);
return (
<div
style={{
position: 'absolute',
width: 50,
height: 50,
backgroundColor: 'red',
left: x,
top: y,
}}
/>
);
}
}
Finger.propTypes = {
position: PropTypes.array,
};
export default Finger;
Systems.js
const MoveFinger = (entities, { input }) => {
// -- I'm choosing to update the game state (entities) directly for the sake of brevity and simplicity.
// -- There's nothing stopping you from treating the game state as immutable and returning a copy..
// -- Example: return { ...entities, t.id: { UPDATED COMPONENTS }};
// -- That said, it's probably worth considering performance implications in either case.
const payload = input.find(x => x.name === 'onMouseDown');
if (payload) {
const finger = entities.finger1;
finger.position[0] = payload.payload.pageX;
finger.position[1] = payload.payload.pageY;
}
return entities;
};
export { MoveFinger };
Thanks for the help, can't wait to see what I can build with this.
Thanks for providing your updated code @michaelcuneo!
I'll see if I can update the docs ASAP - but I'll focus on your other issue first, that seems like a show stopper. Cheers.
If I throw the example quickstart into a blank boilerplate, and run, I get
Systems.js?86e8:7 Uncaught TypeError: Cannot read property 'payload' of undefined at MoveFinger (Systems.js?86e8:7)