许多组件具有相同的异径管但初始状态不同

时间:2019-12-01 10:29:48

标签: reactjs redux react-redux

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

我有一个叫做Monster的组件,它在地图上移动。位置,方向和spriteLocation由商店控制。怪物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

移动是这样进行的:

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
}

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

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

1 个答案:

答案 0 :(得分:0)

Redux用于在组件内共享状态,而不保存单个组件状态。因此,在这种情况下,怪物组件可以具有自己的状态,或者如果仍然存在,则需要在其中更改减速器。

const intialState = {
   monsters: {
   }
}

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

export default monsterReducer

因此,无论何时注册怪物,您都可以在同一减速器中将其初始化。 即

registerMonster(id)-新的怪物动作

减速器

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

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