I am learning ReactJS by trying to coding a game.
In this game i want that at a specify period of time/frequency a random number between one and four, of enemy (represented by images) appear at the top of the screen and fall toward the bottom of the screen. When they arrived at the bottom of the screen the relevant row disapear.
Until now i ve succeeded to get that at each load of a page a random number of ennemies appears at a random offset at the top of the screen and they fall to the bottom of the screen.
The problem is that there is only a unique row that is generated and it does it only one time.
Here my actual code (that works):
class EnemyManager extends React.Component{
constructor(props) {
super(props);
this.state={
enemyNbr: Math.floor(Math.random() * 5) + 1
}
}
generate_enemy_fct(){
console.log("enemyNbr:" + this.state.enemyNbr); // Test--------------------------------------------------------
let enemyArr = new Array(4);
if (1 <= this.state.enemyNbr && this.props.loopEnemyBool === true){
enemyArr[0] = <Enemy enemySrcImg="./gameData/nig01.webp"/>;
}
if(2 <= this.state.enemyNbr && this.props.loopEnemyBool === true){
enemyArr[1] = <Enemy enemySrcImg="./gameData/nig02.webp"/>;
}
if(3 <= this.state.enemyNbr && this.props.loopEnemyBool === true){
enemyArr[2] = <Enemy enemySrcImg="./gameData/nig03.webp"/>;
}
if(4 <= this.state.enemyNbr && this.props.loopEnemyBool === true){
enemyArr[3] = <Enemy enemySrcImg="./gameData/nig04.webp"/>;
}
return enemyArr;
}
render(){
let enemyArrTmp = this.generate_enemy_fct(true);
return(
<div className="EnemyManager">
{enemyArrTmp[0]}
{enemyArrTmp[1]}
{enemyArrTmp[2]}
{enemyArrTmp[3]}
</div>
)
}
}
And i would like that it would behave like this:
class EnemyManager extends React.Component{
constructor(props) {
super(props);
this.state={
enemyNbr: Math.floor(Math.random() * 5) + 1
}
}
generate_enemy_fct(){
console.log("enemyNbr:" + this.state.enemyNbr); // Test--------------------------------------------------------
let enemyArr = new Array(4);
if (1 <= this.state.enemyNbr && this.props.loopEnemyBool === true){
enemyArr[0] = <Enemy enemySrcImg="./gameData/nig01.webp"/>;
}
if(2 <= this.state.enemyNbr && this.props.loopEnemyBool === true){
enemyArr[1] = <Enemy enemySrcImg="./gameData/nig02.webp"/>;
}
if(3 <= this.state.enemyNbr && this.props.loopEnemyBool === true){
enemyArr[2] = <Enemy enemySrcImg="./gameData/nig03.webp"/>;
}
if(4 <= this.state.enemyNbr && this.props.loopEnemyBool === true){
enemyArr[3] = <Enemy enemySrcImg="./gameData/nig04.webp"/>;
}
return enemyArr;
}
render(){
let enemyArrTmp = this.generate_enemy_fct(true);
return(
<div className="EnemyManager">
for(let i=0; i<10**6; i++){
if(i%1000===0){ // For exemple generate a new row of enemies at each 1000th iteration
let enemyArrTmp = this.generate_enemy_fct(true);
}
{enemyArrTmp[0]}
{enemyArrTmp[1]}
{enemyArrTmp[2]}
{enemyArrTmp[3]}
}
</div>
)
}}
I am really stuck on this problem thank for your help.
EDIT: As it had been asked me here the code of the <Enemy/>
component.
class Enemy extends React.Component{
constructor(props) {
super(props);
this.enemyImg = this.props.enemySrcImg;
this.state={
posYenemy:0,
posXenemy:0,
}
this.refDivEnemy=React.createRef();
}
componentDidMount () {
this.setState({posXenemy: Math.floor(Math.random() * (window.innerWidth- this.refDivEnemy.current.offsetWidth*1.15))});
this.timerID = setInterval(() => {
if(this.state.posYenemy+this.refDivEnemy.current.offsetHeight*1.15<window.innerHeight){
console.log("posYenemy:" + this.state.posYenemy +"- windowHeight:" + window.innerHeight + "- enemyImgHeight:" + this.refDivEnemy.current.offsetHeight); // Test--------------------------------------------------------
this.setState((prevState) => ({
posYenemy: Math.floor(prevState.posYenemy + window.innerHeight * 0.05)
}))
}
}, 500);
}
componentWillUnmount(){
clearInterval(this.timerID);
}
render(){
return(
<div className="enemyDiv"
ref={this.refDivEnemy}
style={{
position: "absolute",
top: `${100*this.state.posYenemy/window.innerHeight}vh`,
left: `${100*this.state.posXenemy/window.innerWidth}vw`
}}>
<img className="enemyImg"
alt="enemy_img"
src={require(`${this.enemyImg}`)}
style={{
height: "10vh"
}}
/>
</div>
)
}
}
The problem is, your Enemy Manager class isn't doing enough managing. As of now, it does not know where its children (Enemy) are on the screen, so it can't make a decision on whether or not to render them. In addition to creating new enemies, your Enemy Manager class needs to decide where each Enemy is on the screen, and determine if it should continue to exist.
Here's what you can do to fix this:
{image: 'foo.webp', xPos: 0, yPos: 0}
generate_enemy
function, which you will modify to create EnemyProps objects instead of <Enemy>
components. The function will assign an image and a random X position to each object it creates, then push it onto the cloned array. state.enemies.map(enemy => <Enemy props={enemy} />
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.