JavaScriptのenchant.jsというフレームワークでノベルゲームを制作しておりますが、セーブ機能の実装がイマイチ上手くできません。
●実現したいこと
・セーブ・ロードが行える
・シーン、テキスト再開位置、主人公のフラグや得点を記録する
・得点を得られるシーンをロードし直しても得点が増えない(1つのデータで同じ処理を繰り返さない)
・1人のユーザーで複数のデータを保存できる(とりあえず今回は3つ)
ゲームの基礎的な部分はこちらで紹介されているエンジンを使っています。
game.jsが今回主に対象となるファイルです。
document.cookie = ●●
として縦に長々と書いていけば当機能は実現できると思われますが、それでは長くなりすぎるので、何とか上手く構造化したいと思っています。
今回、セーブ機能を実装するための案として、SaveData.jsを作りSaveDataクラス内のコンストラクタにデータを保存し、連想配列として取り出していくことなどを考えましたが、cookieを使う場合、このようにファイルを分けてしまうと自分の能力では意味がないように思います。
もしcookie以外の他の機能を使った方が良いということであればやり方を変えてみようと思います。
現在はsaveScene(シーン),saveData(テキストの再開位置)だけをcookieに保存し、取得することが可能となった状態です。
以下、ソースコードです。(文字数制限にかかるため一部省略しています)
今回私が弄った部分は200行目あたりです。
enchant(); var saveScene; var saveData; var loadFlag = 0; class CurrentScene{ //コンストラクタ constructor(){ //特に処理なしにしています } ・ ・ ・ //テキストをシーンに設定する SetText(args){ //フラグ用使いまわします。 let i = 1; if(loadFlag == 1){ i = saveData; loadFlag = 0; } //引数例 ["ねね","あっ!進!","おはよう","今日は転校生が来るんだよね!","噂だと女の子なんだって!"], //iは初期値1なのは、発言者だからです。 //発言者がいない場合は無視する if(args[0] != ""){ let whosay = new Label("「" + args[0] + "」"); whosay.font = "16px monospace"; whosay.color = "rgb(0, 0, 0)"; whosay.y = 180; whosay.x = 10; whosay.width = 300; whosay.height = 120; whosay.opacity = 0; whosay.tl.fadeIn(15); textLayer.addChild(whosay); } //発言内容を表示する let text = new Label( args[i] ); text.font = "16px monospace"; text.color = "rgb(0, 0, 0)"; text.y = 200; text.x = 10; text.width = 300; text.height = 120; text.opacity = 0; text.tl.fadeIn(15); textLayer.addChild(text); //次へボタン let nextlabel = new Label("< ▼ >"); nextlabel.font = "16px monospace"; nextlabel.color = "rgb(0, 0, 0)"; nextlabel.y = 280; nextlabel.x = 270; nextlabel.opacity = 0; nextlabel.tl.fadeIn(20); textLayer.addChild(nextlabel); //戻るボタン let backLabel = new Label("< ▲ >"); backLabel.font = "16px monospace"; backLabel.color = "rgb(0, 0, 0)"; backLabel.y = 280; backLabel.x = 0; backLabel.opacity = 0; backLabel.tl.fadeIn(20); textLayer.addChild(backLabel); //セーブボタン let saveLabel = new Label("セーブ"); saveLabel.font = "16px monospace"; saveLabel.color = "rgb(0, 0, 0)"; saveLabel.y = 280; saveLabel.x = 130; saveLabel.opacity = 0; saveLabel.tl.fadeIn(20); textLayer.addChild(saveLabel); let saveFinish = new Label("セーブが完了しました"); saveFinish.font = "16px monospace"; saveFinish.color = "rgb(0, 0, 0)"; saveFinish.y = 140; saveFinish.x = 120; saveFinish.opacity = 0; saveFinish.tl.fadeIn(20); let saveOK = new Label("OK"); saveOK.font = "16px monospace"; saveOK.color = "rgb(0, 0, 0)"; saveOK.y = 160; saveOK.x = 120; saveOK.opacity = 0; saveOK.tl.fadeIn(20); let saveBG = new Sprite(320,180); saveBG.image = core.assets["./img/serifu.png"]; saveBG.x = 50; saveBG.y = 90; saveBG.scaleY = 0.5; let loadLabel = new Label("ロード"); loadLabel.font = "16px monospace"; loadLabel.color = "rgb(0, 0, 0)"; loadLabel.y = 280; loadLabel.x = 190; loadLabel.opacity = 0; loadLabel.tl.fadeIn(20); textLayer.addChild(loadLabel); //次へボタン //配列に要素があればラベルを書き換える nextlabel.addEventListener('touchstart',function(e){ if(i != args.length -1){ i++; text.text = args[i]; }else{ //セリフの配列が空になった時に次のシーンへ飛ばす executeNext(eval(getNextSceneName()),1); } }); //戻るボタン backLabel.addEventListener('touchstart',function(e){ if(i != 1){ i--; text.text = args[i]; }else{ //処理なし } }); saveLabel.addEventListener('touchstart',function(e){ saveScene = getCurrentSceneName(); textLayer.addChild(saveFinish); textLayer.addChild(saveOK); bgLayer.addChild(saveBG); saveData = i; document.cookie = 'saveScene=' + encodeURIComponent(saveScene); document.cookie = 'saveData=' + encodeURIComponent(saveData); console.log(saveData); console.log(i); console.log(document.cookie); }); saveOK.addEventListener('touchstart',function(e){ textLayer.removeChild(saveFinish); textLayer.removeChild(saveOK); bgLayer.removeChild(saveBG); }); if(!document.cookie){ loadLabel.color = "#ccc"; }else{ loadLabel.addEventListener('touchstart',function(e){ loadFlag = 1; console.log(document.cookie.split(';')[0].split('=')[1]); console.log(document.cookie.split('=')[2]); saveScene = document.cookie.split(';')[0].split('=')[1] saveData = document.cookie.split('=')[2]; executeNext(eval(saveScene),saveData); }); } }//end SetText SetCurrentSceneName(name){ this.currentSceneName = name; } SetNextSceneName(name){ this.nextSceneName = name; } //次のシーンへ遷移する GoNextScene(args){ //テキストと次へボタンを削除する textLayer.removeChild(textLayer.firstChild); textLayer.removeChild(textLayer.firstChild); textLayer.removeChild(textLayer.lastChild); textLayer.removeChild(textLayer.lastChild); textLayer.removeChild(textLayer.firstChild); textLayer.removeChild(textLayer.firstChild); textLayer.removeChild(textLayer.firstChild); textLayer.removeChild(textLayer.lastChild); textLayer.removeChild(textLayer.lastChild); textLayer.removeChild(textLayer.firstChild); //ここで関数名と引数のセットを持ってきています for(let val in args){ _currentScene[val](args[val]); } } ・ ・ ・ // シナリオを実行する関数 function executeNext(args , saveData) { _currentScene.GoNextScene(args , saveData); } function getNextSceneName(){ return _currentScene.nextSceneName; } function getCurrentSceneName(){ return _currentScene.currentSceneName; } ////////////////////////////////////// // 各種設定等 ////////////////////////////////////// imglist = ["./img/serifu.png","./img/material.png"] //bgmlist = ["やばいシーン.mp3","家.mp3","ホップ.mp3","明るい街.mp3","バッドエンド.mp3","可愛い.mp3","ノーマルエンドに最適.mp3","op.mp3"] // シーンを生成する let _currentScene = new CurrentScene(); //プレイヤーを作成する //var player = new MainPlayer(); ////////////////////////////////////// // 初期化処理 ////////////////////////////////////// window.onload = function() { core = new Core(640, 320); core.fps = 16; //使用する画像をプリロードする(配列を渡せばOK) core.preload(imglist); //core.preload(bgmlist); // core.bgm = Sound.load('op.mp3'); //ここで初期化処理が始まる core.onload = function() { // core.bgm.volume = 0.3; // core.bgm.play(); //core.bgm.loop = true; //レイヤーで管理する bgLayer = new Group(); core.rootScene.addChild(bgLayer); imageLayer = new Group(); core.rootScene.addChild(imageLayer); textLayer = new Group(); core.rootScene.addChild(textLayer); /*これが最初のシーンです */ _currentScene.SetBackGroundImage("./img/serifu.png"); //引数リスト //選択肢1 遷移先1 選択肢2 遷移先2 //最初は選択肢のあるシーンを作成しています。 _currentScene.SetChoiceScene(["初めから",TitleScene,"あはん",TitleScene]); let loadLabel = new Label("続きから"); loadLabel.font = "16px monospace"; loadLabel.color = "rgb(0, 0, 0)"; loadLabel.y = 280; loadLabel.x = 10; textLayer.addChild(loadLabel); if(!document.cookie){ loadLabel.color = "#ccc"; }else{ loadLabel.addEventListener('touchstart',function(e){ loadFlag = 1; console.log(document.cookie.split(';')[0].split('=')[1]); console.log(document.cookie.split('=')[2]); saveScene = document.cookie.split(';')[0].split('=')[1] saveData = document.cookie.split('=')[2]; executeNext(eval(saveScene),saveData); }); } } core.start(); }
どなたかご助言いただけないでしょうか
よろしくお願いいたします
回答2件
あなたの回答
tips
プレビュー