問答収集 カテゴリ:Flashプログラミング
現在のスレッド一覧 / 新規に質問を投稿
1 名前:中島尚樹 PR: 709709.com クリスマス脱出ゲームを鋭意製作中です。このままではお蔵入りかもですが…。 日付:2010/10/17(日)16:43:10 ID:nTQ9WAPnHg9S
サイトはいつも拝見し参考にさせて頂いておりますが、ここに質問するのは初めてです。
脱出ゲームを製作中で、進行状況を保存できるようにSharedObjectを使用しました。
サイト内の『ローカルへの変数の保存について』のサンプルをほぼ流用しております。
過去にはそんな症状もなかったのですが、現在、製作中のゲームに限って

【変数が勝手に保存される】

現象に悩まされております。

症状は以下の通りです。
ゲームを開始する。
鍵を手に入れる。
セーブする。
扉を開けて次の部屋へ行く。
次の部屋でゲームのウィンドウを閉じる。
再度、ゲームを立ち上げ、ロードを選択する。
鍵を手に入れた状態で再開されず、鍵を使用した次の部屋でゲームが再開される。

セーブボタンが勝手に押される処理がゴミとしてあるのかな?と思い、色々と調べるのですが、これと言った箇所は見当たりませんでした。

再度、サイトを拝見し、読み進めていくと気になる文言がありました。

   flush() メソッドを呼び出さなくても共有オブジェクトが
   ガベージコレクションに回収されるタイミングで
   自動的にハードディスクに書き込み処理が走ります。

早速、ガベージコレクションをWikiで調べたのですが、意味が分からず、困っております。
自動的に…と言う部分が今回の不本意な結果に繋がっているのでは?と思ってはいるのですが対処法が見付かりません。
『オートセーブ機能付き!』にしようとも考えたのですが、勝手に保存してくれる(?)変数にもバラつきがあり、それも断念。
万策尽きて、こちらに相談させて頂きます。

どこまで説明したものか分かりませんので、症状だけ書きましたが、情報が足りなければ、書き込みますので、
解決策の分かる方は是非、お願いします。
2 日付:2010/10/17(日)18:46:48 ID:vWZfJ/Iu.7sO
ゲームで使用するデータを Object 型で管理していて
共有オブジェクトに保存するときに Object 型のまま渡してるようでしたら
そのような動作をするように感じると思いますがいかがでしょうか?

---------------------------------------------------------------
// ゲームで使用するワーク
var game_info_obj = new Object();


// 共有オブジェクトを作成
var so = SharedObject.getLocal("save_test","/");
if(so){
trace("保存状態:" + so.data.save.test);
}

// 共有オブジェクトにゲームで使用するワークを保存(Object型なので参照渡し)
so.data.save = game_info_obj;

// ワークにデータをセット
game_info_obj.test = "保存テスト";

// 中身を確認
trace("ゲームで使用するワーク:" + game_info_obj.test);
trace("共有オブジェクト:" + so.data.save.test);
---------------------------------------------------------------

flush()メソッドを呼び出さなかった場合ですが
通常であれば、 Flash Player が閉じられるタイミングで実際に保存されます。
しかし、Flash Player がクラッシュ等の理由で強制終了した場合は、保存に失敗する恐れがあります。
3 名前:中島尚樹 日付:2010/10/17(日)21:31:53 ID:nTQ9WAPnHg9S
早速のご回答ありがとうございます。
早い段階で回答に気付いたのですが、内容が把握できず、お礼が遅れました。
独学な上に「動けば良し」で来たツケが今になってやって来たと言ったところでしょうか?

現在、用語の勉強をしております。(汗)
AS部分以外はさすがに理解できましたが、AS部分を再度勉強してみます。
4 名前:中島尚樹 日付:2010/10/17(日)23:26:18 ID:nTQ9WAPnHg9S
FLASHのヘルプを(今頃になって)参照したりしますと、
ユーザー名の記憶やカウンターなどに使用する例題があり、
そもそも論として、Flash Playerが閉じられるタイミングでの保存が
大前提の命令だったと言うことが(やはり今頃になって)分かりました。

「勝手に保存される」のが大前提ならば、ゲームのセーブやロードのように
保存したい時、読み込みたい時をこちらで決められる方法はあるのでしょうか?
flush()がそれに該当するのは分かりますので、逆に
自動で保存されても影響のないようにするにはどうするのでしょうか?

解釈が既に間違っているかもですが、引き続きご指導いただければ幸いです。
宜しくお願いします。
5 日付:2010/10/17(日)23:42:46 ID:8d7uAYrQHgxE
原因は >>2 という事でよろしいですか?


6 名前:中島尚樹 日付:2010/10/18(月)07:55:59 ID:nTQ9WAPnHg9S
おはようございます。返信遅くなりました。

そうです。原因は >>2 ということになります。
"保存テスト"の文字が何もせずに(=flush()もないのに)記録されたので
これはこれで正しい挙動なんですよね?
仰るとおり、自身のゲーム内のASもObject 型のまま渡しているようです。

例えば、

   ITEM=["なし","ドライバー","カギ"];

と言った配列も

   so.data.save = ITEM;

のようにしております。(参照渡しと言うもの?)

この参照渡しで、今まで問題なく動いていました。
(あくまで『こちらが意図する動作』と言う意味ですが…)
flush()が無いと一切、保存されないと思い込んでいたわけですが
ここに来て躓いて、共有オブジェクトの何たるかを知る良い機会になりました。

この際、「動けば良い」から「どうすれば動くのか」を
しっかりと学びたいと思います。
ご教授宜しくお願いします。
7 日付:2010/10/18(月)19:05:32 ID:jEpCmss4id9h
まず、
共有オブジェクトの data プロパティの中身を変更すると、
flush() を呼び出さなくても、強制終了でもしない限りは中身が保存されます。
------------------------------------------------------
// 共有オブジェクトを作成
var so = SharedObject.getLocal("save_test","/");

// data プロパティの中身を書き換えて更新
so.data.save = "保存";
------------------------------------------------------


問題は、Array 型や Object 型などの変数(リファレンスデータ)をそのまま共有オブジェクトに渡しているので、
ゲーム中に変数を変更すると、共有オブジェクトも更新した事になる点です。

参照(リファレンスデータ)について
http://hakuhin.jp/as/disposition.html#OBJECT_05
8 日付:2010/10/18(月)19:08:32 ID:jEpCmss4id9h
ゲーム中の変数と、保存したいデータを分ける方法ですが、

共有オブジェクトの data プロパティに配列やオブジェクトなどのデータを渡す直前に、
新規に配列やオブジェクトを作成して、中身をすべてコピーしたものを渡します。


今までの動作です。
------------------------------------------------------
// 共有オブジェクトを作成
var so = SharedObject.getLocal("save_test","/");

// ゲーム中のデータ
var ITEM=["なし","ドライバー","カギ"];

// 配列 ITEM の参照を渡す。 data プロパティの中身が更新されたので保存される
so.data.save = ITEM;

// 配列 ITEM の中身をを変更(so.data.save には「配列 ITEM への参照」が格納されているので、この時点で data プロパティの中身も更新された事になり変更は保存される)
ITEM.push("新規アイテム");

// 中身を確認
trace(ITEM);
trace(so.data.save);
------------------------------------------------------


変更後の動作です。
------------------------------------------------------
// 共有オブジェクトを作成
var so = SharedObject.getLocal("save_test","/");

// ゲーム中のデータ
var ITEM=["なし","ドライバー","カギ"];

// 配列 SAVE を新規に作成して中身をすべてコピーしてから渡す。 data プロパティの中身が更新されたので保存される
var SAVE = new Array();
for(var i=0;i<ITEM.length;i++){
SAVE[i] = ITEM[i];
}
so.data.save = SAVE;

// 配列 ITEM の中身をを変更(so.data.save には「配列 SAVE への参照」が格納されているので、この変更は data プロパティの中身に影響しない)
ITEM.push("新規アイテム");

// 中身を確認
trace(ITEM);
trace(so.data.save);
------------------------------------------------------
9 名前:中島尚樹 日付:2010/10/18(月)22:44:15 ID:nTQ9WAPnHg9S
返信遅くなりました。

丁寧な解説ありがとうございます。

早速、熟読させて頂きます!

まずは取り急ぎお礼まで。
10 名前:中島尚樹 日付:2010/10/19(火)13:29:50 ID:nTQ9WAPnHg9S
治りました!と言いますか、意図する動作になりました!
本当にありがとうございます!

今回の保存される変数のバラつきも、過去のケースが図らずも成功していた理由も
この度の丁寧なレクチャーで全て理解できました。

今後もサイトで勉強しながら、多くの無料ゲームを製作したいと思います。
重ねてありがとうございます!
11 名前:状態変更 日付:2010/10/19(火)13:31:55 ID:nTQ9WAPnHg9S
この質問の状態を『解決』に変更しました。
12 名前:状態変更 日付:2010/11/03(水)14:07:18 ID:3AcBzMZ4E7IS
この質問の状態を『受付』に変更しました。
13 名前:状態変更 日付:2010/11/04(木)12:49:22 ID:jEpCmss4id9h
この質問の状態を『解決』に変更しました。
このスレッドについて
質問の状態 :
解決済み
投稿開始日 :
2010/10/17(日)16:43:10
投稿終了日 :
2010/11/04(木)12:49:22
投稿者 :
中島尚樹
レス総数 :
13
スレッド番号 :
72
MondoCollectionSystem ver.0x00020000 by Hakuhin