JS游戏开发:LocalStorage数据不持久及push函数报错求助
LocalStorage数据丢失及
objectForMonsterMarkers.push报错修复 问题1:页面刷新后LocalStorage数据无法保存显示
原因
- 初始化条件逻辑错误:原代码
if (playerCharachteristics || monsterCharachteritics === null)的判断逻辑完全错误——只要playerCharachteristics存在(非null),不管怪物数据是否缺失,都会重新生成玩家和怪物数据,直接覆盖本地存储的值。 - 无效的分支判断:后续的
else if与前面的if条件完全重复,永远不会触发,导致读取本地存储后无法调用generateMonster渲染怪物。 - 存储DOM元素到LocalStorage:代码中将
playerCharachteristics.pHealthBar、monsterCharachteritics.mHealthBar等DOM对象存入LocalStorage,这类对象无法被JSON正确序列化,直接导致存储和读取失败。
修复方案
- 修正初始化条件:改为任一数据不存在时才初始化,即
if (!playerCharachteristics || !monsterCharachteritics)。 - 删除重复的else if分支,在数据存在时直接调用
generateMonster渲染内容。 - 分离数据与DOM引用:只存储数值、布尔值等可序列化的数据,DOM元素在页面加载后重新获取,不存入LocalStorage。
问题2:objectForMonsterMarkers.push不是函数报错
原因
objectForMonsterMarkers初始化为数组,但在monsterHit函数中,将布尔值booleanGameMechanics存入了monsterBooleanImage对应的LocalStorage键中。下次页面加载时,objectForMonsterMarkers会被解析为布尔值而非数组,调用push方法自然报错。
修复方案
- 拆分存储键:用单独的键存储
objectForMonsterMarkers数组(比如monsterMarkers),怪物的布尔状态用另一个键(比如monsterActiveStatus)存储,避免类型混淆。 - 确保数组类型安全:读取
objectForMonsterMarkers时直接做兜底初始化,保证其始终为数组。
修改后的完整代码
// 初始化本地存储数据 let playerCharachteristics = JSON.parse(localStorage.getItem('playerCharachteristics')); let monsterCharachteritics = JSON.parse(localStorage.getItem('monsterCharachteritics')); let objectForMonsterMarkers = JSON.parse(localStorage.getItem('monsterMarkers')) || []; let monsterActiveStatus = JSON.parse(localStorage.getItem('monsterActiveStatus')); // 初始化玩家和怪物数据(任一不存在时) if (!playerCharachteristics || !monsterCharachteritics) { playerCharachteristics = { pStrength: parseInt(Math.random() * 80), // 攻击点数,在monsterHit中会增加 pStrengthBar: parseInt(Math.random() * 80), pDefence: parseInt(Math.random() * 70), pDefenceBar: parseInt(Math.random() * 80), pHealth: parseInt(Math.random() * 100), pHealthBarWidth: 100 // 存储宽度数值,而非DOM元素 }; monsterCharachteritics = { mStrength: 40, mStrengthBarWidth: 40, // 存储宽度数值 mDefence: parseInt(Math.random() * 80), mDefenceBar: parseInt(Math.random() * 80), mHealth: parseInt(Math.random() * 110), mHealthBarWidth: parseInt(Math.random() * 80) // 存储宽度数值 }; // 首次初始化时设置怪物状态为活跃 monsterActiveStatus = true; } // 读取到数据后渲染怪物 generateMonster(monsterActiveStatus); function generateMonster(monsterBooleanImage) { if (!monsterBooleanImage) return; let monsterHealthAdditionalHealthPoints = 800; monsterCharachteritics.mHealth += monsterHealthAdditionalHealthPoints; monsterCharachteritics.mStrength = 35; // 基础怪物攻击力 // 渲染DOM元素 divImage.innerHTML += ` <img alt="" class="first" fetchpriority="auto" loading="auto" src="https://i.pinimg.com/564x/85/c8/f3/85c8f3eca9a5cbdef756956ba16b89dd.jpg" id="gameCanvas" width="270" height="330" > `; monsterHealthDiv.innerHTML += ` <div id="monsterhealthbar"> <div class="monsterhealthfill" > <i class="hp3"> Monster Health Points -${monsterCharachteritics.mHealth}</i> </div> </div> <div id="monsterstrengthbar"> <div class="monsterstrengthfill" > <i class="hp3"> Monster Strength Points -${monsterCharachteritics.mStrength}</i> </div> </div> `; // 获取DOM元素(仅在当前页面使用,不存入LocalStorage) const monsterSDFbarFills = { mhFill: document.querySelector(".monsterhealthfill"), msFill: document.querySelector(".monsterstrengthfill") }; const monsterHealthBar = document.querySelector("#monsterhealthbar"); const monsterStrengthBar = document.querySelector("#monsterstrengthbar"); // 设置进度条宽度 monsterHealthBar.style.width = monsterCharachteritics.mHealthBarWidth + 'px'; monsterStrengthBar.style.width = monsterCharachteritics.mStrengthBarWidth + 'px'; checker2++; if (checker2 === 1) { divThrowButon.innerHTML = ` <button onclick="throwForStrengthHealth()"> Throw For Health and Base Strength</button> `; } attackDiv.innerHTML = ` <button class="button" onclick="monsterHit(${monsterBooleanImage})">Attack</button> `; // 存储数据到LocalStorage(仅存数值/布尔/数组,不存DOM) localStorage.setItem('monsterActiveStatus', JSON.stringify(monsterBooleanImage)); localStorage.setItem('playerCharachteristics', JSON.stringify(playerCharachteristics)); localStorage.setItem('monsterCharachteritics', JSON.stringify(monsterCharachteritics)); localStorage.setItem('monsterMarkers', JSON.stringify(objectForMonsterMarkers)); } function monsterHit(booleanGameMechanics) { if (!booleanGameMechanics) return; let playerThrowAdditionalAttackPoints = parseInt(Math.random() * 80); let overallPlayerDamage = playerCharachteristics.pStrength + playerThrowAdditionalAttackPoints; let monsterThrowAdditionalAttackPoints = parseInt(Math.random() * 90); let overallMonsterDamage = monsterThrowAdditionalAttackPoints + monsterCharachteritics.mStrength; if (overallMonsterDamage > overallPlayerDamage) { attackExchangeCounter++ } if (attackExchangeCounter >= 3) { attackDiv.innerHTML = ` <button onclick="secondAttack(${overallMonsterDamage},${booleanGameMechanics})"> Second Attack</button> <button onclick="lowerYourAttackPoints(${booleanGameMechanics})"> Lower your attack points</button> `; attackExchangeCounter = 0; } // 更新数值 playerCharachteristics.pHealth -= overallMonsterDamage; monsterCharachteritics.mHealth -= overallPlayerDamage; // 更新玩家生命值宽度 if (overallMonsterDamage > 100) { playerCharachteristics.pHealthBarWidth -= 100; } else if (overallMonsterDamage > 50) { playerCharachteristics.pHealthBarWidth -= 50; } else { playerCharachteristics.pHealthBarWidth -= 20; } // 获取DOM元素 const playerHealthBar = document.querySelector("#playerhealthbar"); const monsterHealthBar = document.querySelector("#monsterhealthbar"); const monsterStrengthBar = document.querySelector("#monsterstrengthbar"); const streDefeHealthBarFills = { hFill: document.querySelector(".playerhealthfill") }; const monsterSDFbarFills = { mhFill: document.querySelector(".monsterhealthfill"), msFill: document.querySelector(".monsterstrengthfill") }; // 更新DOM显示 playerHealthBar.style.width = playerCharachteristics.pHealthBarWidth + "px"; monsterHealthBar.style.width = monsterCharachteritics.mHealth + "px"; monsterStrengthBar.style.width = monsterCharachteritics.mStrength * 10 + "px"; monsterSDFbarFills.mhFill.innerHTML = ` <i class="hp3"> Monster Health Points -${monsterCharachteritics.mHealth}</i> `; monsterSDFbarFills.msFill.innerHTML = ` <i class="hp3"> Monster Strength Points -${monsterCharachteritics.mStrength}</i> `; streDefeHealthBarFills.hFill.innerHTML = ` <i class="i">Health Points -${playerCharachteristics.pHealth}</i> `; riddleContainer.innerHTML = ` <i class="hp3"> You dealt ${overallPlayerDamage} health points worth of damage to your opponent!</i> <i class="hp3"> You received an overall damage of ${overallMonsterDamage} health points by your opponent!</i> `; // 怪物死亡逻辑 if (monsterCharachteritics.mHealth < 0) { playerCharachteristics.pHealth += 300; playerCharachteristics.pHealthBarWidth = 1450; // 重置宽度 playerHealthBar.style.width = playerCharachteristics.pHealthBarWidth + "px"; moveButton.innerHTML += ` <button class="Move" onclick="move()"> Throw Dice To Move</button> `; divImage.innerHTML = ""; monsterHealthDiv.innerHTML = ""; attackDiv.innerHTML = ""; riddleContainer.innerHTML = ""; streDefeHealthBarFills.hFill.innerHTML = ` <i class="i">Health Points -${playerCharachteristics.pHealth}</i> `; monsterActiveStatus = false; // 设置怪物状态为非活跃 } // 玩家死亡逻辑 if (playerCharachteristics.pHealth < 0) { mainContainer.style.backgroundColor = "red"; mainContainer.innerHTML = ` <i class="hp6"> GAME OVER! YOU DIED!</i> `; } // 存储更新后的数据 localStorage.setItem('playerCharachteristics', JSON.stringify(playerCharachteristics)); localStorage.setItem('monsterCharachteritics', JSON.stringify(monsterCharachteritics)); localStorage.setItem('monsterActiveStatus', JSON.stringify(booleanGameMechanics)); localStorage.setItem('monsterMarkers', JSON.stringify(objectForMonsterMarkers)); }
内容的提问来源于stack exchange,提问作者CFHVDOPFBD
相关产品推荐
相关产品推荐

