Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
373 views
in Technique[技术] by (71.8m points)

reactjs - 许多组件具有相同的异径管但初始状态不同(Many components with the same reducer but different initial state)

I tested Redux with creating a little RPG game.

(我通过创建一个小的RPG游戏测试了Redux。)

I have a component called Monster who move on the map.

(我有一个叫做Monster的组件,它在地图上移动。)

The position, the direction and the spriteLocation are controlled by the store.

(位置,方向和spriteLocation由商店控制。)

The monster Reducer look like this:

(怪物Reducer看起来像这样:)

const intialState = {
   position: [0,360],
   spriteLocation: '0px 80px',
   direction: 'EAST',
   walkIndex : 0
}

const monsterReducer = (state = intialState, action) => {
   switch(action.type){
       case 'MOVE_MONSTER':
           return {
               ...action.payload
           }
       default:
           return state
   }
}

export default monsterReducer

The moves are dispatched like that:

(动作的调度是这样的:)

import store from '../../config/store'
import {SPRITE_SIZE, MAP_WIDTH, MAP_HEIGHT} from '../../config/constants'

export default function handleMovement(monster){

    //APPEL AU DEPLACEMENT TOUTES LES X secondes
    // setInterval(handleMove(store.getState().monster.direction), 500);
    setInterval(() => {
        handleMove(store.getState().monster.direction)
      }, 300);

    function handleMove(direction){
        switch(direction){
            case 'WEST':
                return attemptMove('WEST')
            case 'EAST':
                return attemptMove('EAST')
            case 'NORTH':
                return attemptMove('NORTH')
            case 'SOUTH':
                return attemptMove('SOUTH')
            default:
        }
    }

    function attemptMove(direction){
        const oldPos = store.getState().monster.position
        const newPos = getNewPosition(oldPos,direction)
        if(observeBoundaries(newPos) && observeImpassable(newPos)){
            dispatchMove(direction, newPos)
        }else{
            switch(direction){
                case 'WEST':
                    return attemptMove('EAST')
                case 'EAST':
                    return attemptMove('WEST')
                case 'NORTH':
                    return attemptMove('SOUTH')
                case 'SOUTH':
                    return attemptMove('NORTH')
                default:
            }
        }
    }

    //UPDATE DE LA POSITION
    function getNewPosition(oldPos, direction){
        switch(direction){
            case 'WEST':
                return [oldPos[0]-SPRITE_SIZE, oldPos[1]]
            case 'EAST':
                return [oldPos[0]+SPRITE_SIZE, oldPos[1]]
            case 'NORTH':
                return [oldPos[0], oldPos[1]-SPRITE_SIZE]
            case 'SOUTH':
                return [oldPos[0], oldPos[1]+SPRITE_SIZE]
            default:
        }        
    }

    function observeBoundaries(newPos){
        //SI ON EST DANS LA MAP ON RETOURNE TRUE SINON FALSE
        return (newPos[0] >= 0 && newPos[0] <= MAP_WIDTH-SPRITE_SIZE) &&
                (newPos[1] >= 0 && newPos[1] <= MAP_HEIGHT-SPRITE_SIZE)
    }

    function observeImpassable(newPos){
        //TEST DES OBSTACLES
        const tiles = store.getState().map.tiles
        const y = newPos[1] / SPRITE_SIZE
        const x = newPos[0] / SPRITE_SIZE
        const nextTile = tiles[y][x]
        return  nextTile < 5
    }

    function getWalkIndex(){
        const walkIndex = store.getState().monster.walkIndex
        return walkIndex >= 4 ? 0 : walkIndex+1
    }

    function getSpriteLocation(direction, walkIndex){
        switch (direction){
            case 'EAST' :
                return `${SPRITE_SIZE*walkIndex}px ${SPRITE_SIZE*2}px`
            case 'SOUTH' :
                return `${SPRITE_SIZE*walkIndex}px ${SPRITE_SIZE*0}px`
            case 'WEST' :
                return `${SPRITE_SIZE*walkIndex}px ${SPRITE_SIZE*3}px`
            case 'NORTH' :
                return `${SPRITE_SIZE*walkIndex}px ${SPRITE_SIZE*1}px`
            default:

        }
    }

    //DISPATCH DE LA NOUVELLE POSITION ET DIRECTION POUR ANIMATION DU PERSO AU STORE
    function dispatchMove(direction, newPos){
        const walkIndex = getWalkIndex()
        store.dispatch({
            type: 'MOVE_MONSTER',
            payload: {
                position: newPos,
                direction,
                walkIndex,
                spriteLocation : getSpriteLocation(direction, walkIndex)
            }
        })
    }

    return  monster
}

I would like to create another Monster component but with different initial state but who works with the same reducer.

(我想创建另一个Monster组件,但是初始状态不同,但是谁使用相同的reducer。)

Maybe it's not the good solution to use reducer for that?

(也许使用reducer并不是一个好的解决方案?)

  ask by Yann SAINTY translate from so

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Redux is used to share state within the component not to hold a single component state.

(Redux用于在组件内共享状态,而不保存单个组件状态。)

So in this case monster component can have own state or if still, you want reducer there you have to change the structure of reducer.

(因此,在这种情况下,怪物组件可以具有自己的状态,或者如果仍然存在,则需要在其中更改减速器的结构。)

const intialState = {
   monsters: {
   }
}

const monsterReducer = (state = intialState, action) => {
   switch(action.type){
       case 'MOVE_MONSTER':
           return {
               ...action.payload
           }
       default:
           return state
   }
}

export default monsterReducer

So whenever a monster is registered you can initilize monster in same reducer.

(因此,每当注册一个怪物时,您都可以在相同的reducer中将其初始化。)

ie

(即)

registerMonster(id) - when new monster action

(registerMonster(id) -新怪物动作时)

reducer

(减速器)

case "REGISETER_MONSTER":
    return {
       ...state,
       [action.payload.id]: {
           position: [0,360],
           spriteLocation: '0px 80px',
           direction: 'EAST',
           walkIndex : 0
       }
    }

the id should be unique for each monster and then updation logic will also change there you have to pass the id of monster and update accordingly.

(每个怪物的ID都应该是唯一的,然后更新逻辑也会更改,您必须传递怪物的ID并进行相应的更新。)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...