我通过创建一个小型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并不是一个好的解决方案?
答案 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并进行相应的更新,更新逻辑也会更改。