現在シューティングゲームの環境設定などを保存する
セーブデータをプログラム側からでも直接テキストファイルからでも変更できるようにと
考えています。そこで↓のように
*---------------------[ 音量関係 ]---------------------
*BGM VOLUME
bgm volume = 100%
*SE VOLUME
se volume = 100%
テキストファイルに記述しているのですが思ったとおりに操作できなかったので質問させていただきます。
具体的にやりたいことは
・ファイルの数字の部分だけが読み込む
・プログラム側から変更を保存する場合できるだけ手間を減らしたい
("bgm volume = %d %%"と一々書くのを省略したい)
です、初歩的な質問かもしれませんがよろしくお願いします。
Cはファイル操作が苦手ですがポインタ操作の方法などは習得しています。
セーブデータ作成について
Re:セーブデータ作成について
テキストに書き出してるならINIでも良いんじゃないでしょうか。
// 書き出し char cBgm[ 64 ] = ""; char cSe[ 64 ] = ""; sprintf( cBgm, "%d", iBgmVolume ); // 文字列に変換 sprintf( cSe, "%d", iSeVolume ); // 文字列に変換 // 書き出し( セクション名、パラム名、書き出す文字、ファイル名 ) WritePrivateProfileString( "SOUND", "BGM_VOLUME", cBgm, "CONFIG.INI" ); WritePrivateProfileString( "SOUND", "SE_VOLUME", cSe, "CONFIG.INI" ); // 読み込み( セクション名、パラム名、データが無かった時の戻り値、ファイル名 ) iBgmVolume = GetPrivateProfileInt( "SOUND", "BGM_VOLUME", 100, "CONFIG.INI" ); iSeVolume = GetPrivateProfileInt( "SOUND", "SE_VOLUME", 100, "CONFIG.INI" ); // CONFIG.INIの中 [SOUND] BGM_VOLUME=100 SE_VOLUME=100
Re:セーブデータ作成について
御返信ありがとうございます。
できうる限りtxtファイルでの実装が好ましいのですが
ソースを拝見する限り簡潔で便利そうですね、
参考にさせていただきます。
できうる限りtxtファイルでの実装が好ましいのですが
ソースを拝見する限り簡潔で便利そうですね、
参考にさせていただきます。
Re:セーブデータ作成について
>・プログラム側から変更を保存する場合できるだけ手間を減らしたい
>("bgm volume = %d %%"と一々書くのを省略したい)
誰の手間を減らしたいのでしょうか?
すでにあるファイルの特定の場所の値だけを書き直すプログラムを作ると、
それ以上に面倒なプログラムになり、プログラマの手間は増えますが・・・・
>("bgm volume = %d %%"と一々書くのを省略したい)
誰の手間を減らしたいのでしょうか?
すでにあるファイルの特定の場所の値だけを書き直すプログラムを作ると、
それ以上に面倒なプログラムになり、プログラマの手間は増えますが・・・・
Re:セーブデータ作成について
現実逃避気味(苦笑)にお手軽保存&読み込み用のクラスを作成してみました。
汚いソースなのは仕様なので気にしないでください(笑)
まずは、クラスのソースを…
汚いソースなのは仕様なので気にしないでください(笑)
まずは、クラスのソースを…
#pragma once #include <map> #include <string> #include <fstream> #include <sstream> #include <iostream> class StatusFile { private: std::map<std::string, std::string> m_data; public: StatusFile(void) { clear(); } ~StatusFile(void) { } void clear(void) { m_data.clear(); } void set(std::string name, std::string data) { m_data.insert(std::map<std::string, std::string>::value_type(name, data)); } void set(const char* name, std::string data) { std::string buf = name; set(buf, data); } std::string get(std::string name) { return m_data[name]; } std::string get(const char* name) { std::string buf = name; return get(buf); } bool save(const char* path) { std::fstream fs(path, std::ios::out); if (fs.fail() == true) { return false; } for each (const std::pair<std::string, std::string> buf in m_data) { fs << buf.first << "=" << buf.second << std::endl; } fs.close(); return true; } bool load(const char* path) { std::fstream fs(path, std::ios::in); if (fs.fail() == true) { return false; } m_data.clear(); while (fs.eof() == false) { std::string buf, pat("="), rep(" "); std::getline(fs, buf); if (buf.length() < 3) continue; buf = replace(buf, pat, rep); std::stringstream ss(buf); std::string name, data; ss >> name >> data; set(name, data); } fs.close(); return true; } private: std::string replace(const std::string& source, const std::string& pattern, const std::string& placement) { std::string result; std::string::size_type pos_before = 0; std::string::size_type pos = 0; std::string::size_type len = pattern.size(); while ((pos = source.find(pattern, pos)) != std::string::npos) { result.append(source, pos_before, pos - pos_before); result.append(placement); pos += len; pos_before = pos; } result.append(source, pos_before, source.size() - pos_before); return result; } private: }; #include <string> #include <sstream> template <class Type> class Convert { public: static std::string toString(const Type& val) { std::stringstream ss; ss << val; return ss.str(); } static Type toValue(std::string str) { std::stringstream ss; ss << str; Type type; ss >> type; return type; } };次に使用例を…
#include <iostream> #include "StatusFile.h" void main(void) { // StatusFileクラスの実体を作成する StatusFile sf; // 保存したいデータをセットしていく sf.set("HP", Convert<int>::toString(10)); sf.set("MP", Convert<int>::toString(20)); sf.set("AP", Convert<int>::toString(30)); sf.set("DP", Convert<int>::toString(40)); sf.set("SP", Convert<int>::toString(50)); sf.set("PositionX", Convert<double>::toString(123.45)); sf.set("PositionY", Convert<double>::toString(678.90)); sf.set("EventFlag", Convert<bool>::toString(true)); sf.set("String", Convert<char*>::toString("TestString")); // パスを指定して保存する sf.save("test.txt"); // パスを指定してStatusFileクラス内へデータを展開する sf.load("test.txt"); // 値を取り出して、文字列→数値へ int hp = Convert<int>::toValue(sf.get("HP")); int mp = Convert<int>::toValue(sf.get("MP")); int ap = Convert<int>::toValue(sf.get("AP")); int dp = Convert<int>::toValue(sf.get("DP")); int sp = Convert<int>::toValue(sf.get("SP")); double posx = Convert<double>::toValue(sf.get("PositionX")); double posy = Convert<double>::toValue(sf.get("PositionY")); bool flag = Convert<bool>::toValue(sf.get("EventFlag")); }
Re:セーブデータ作成について
えっと、忘れてました…
上記使用例を実行した際のファイルへの出力です。
AP=30
DP=40
EventFlag=1
HP=10
MP=20
PositionX=123.45
PositionY=678.9
SP=50
String=TestString
こんな感じで出力されます。勿論、テキストエディタで編集してもらっても問題ありません。
大事な事を書き忘れておりました。このプログラムは、"="でステータス名とデータを分けていますので、文字列を保存する際に"="が含まれていると、正常に読み込む事が出来ません。
そういう訳ですので、どうしても"="を使いたい場合には、自分でなんとかしてください(ぉぃ)
上記使用例を実行した際のファイルへの出力です。
AP=30
DP=40
EventFlag=1
HP=10
MP=20
PositionX=123.45
PositionY=678.9
SP=50
String=TestString
こんな感じで出力されます。勿論、テキストエディタで編集してもらっても問題ありません。
大事な事を書き忘れておりました。このプログラムは、"="でステータス名とデータを分けていますので、文字列を保存する際に"="が含まれていると、正常に読み込む事が出来ません。
そういう訳ですので、どうしても"="を使いたい場合には、自分でなんとかしてください(ぉぃ)
Re:セーブデータ作成について
ご返信ありがとうございます。
>>すでにあるファイルの特定の場所の値だけを書き直すプログラムを作ると、
それ以上に面倒なプログラムになり、プログラマの手間は増えますが・・・・
確かにそうなってしまうようですね、設計を見直すことを考えてみます。
ソースコードありがとうございます。>>ハッカー氏
わからない所はググリながら参考にさせていただこうと思います、
皆様本当にありがとうございました。
>>すでにあるファイルの特定の場所の値だけを書き直すプログラムを作ると、
それ以上に面倒なプログラムになり、プログラマの手間は増えますが・・・・
確かにそうなってしまうようですね、設計を見直すことを考えてみます。
ソースコードありがとうございます。>>ハッカー氏
わからない所はググリながら参考にさせていただこうと思います、
皆様本当にありがとうございました。