Re: セーブ場所について ( No.1 ) |
- 名前:はるかぜ 日時:2020/10/13 20:04
最近のソフトだとWindows環境ではユーザーフォルダにデータを保存するものが多いと思います。
SHGetSpecialFolderPathのCSIDL_APPDATAで取得できるパスの下に、自分が作ったソフトの名前等でフォルダを作成してその中にファイルを作るといいと思います。
この場所であればログインしているユーザーなら必ず権限を持っているはずなので権限周りについては気にする必要はありません。
具体的な使い方等はSHGetSpecialFolderPathで検索してみてください。
|
Re: セーブ場所について ( No.2 ) |
- 名前:たろう 日時:2020/10/13 22:38
はるかぜさん、貴重な情報をありがとうございます
SHGetSpecialFolderPathで安全な場所を取得してセーブ場所とするんですね
これなら私でも出来そうです<(_ _)>
以前作ったゲームはスチーム経由でインストールすると
program files(x86)> steam > steamapps > common > ゲームのフォルダ > セーブファイルのあるフォルダ > セーブファイル
という場所で展開されて、セーブファイルはゲームのフォルダの二つ下に確かにあるのですが、
これがなぜちゃんとセーブできるのか分からず不思議に思っていました(スチーム関連は別の方にお任せだったので)
これはどういう仕組みが考えられるでしょうか?
はるかぜさんに教えていただいた方法が一番よさそうですが
スチーム経由であれば問題なくセーブできるのであれば、多くの場合直下でも問題ないかもしれないので
それで悩んでいます…
|
Re: セーブ場所について ( No.3 ) |
- 名前:管理人 日時:2020/10/15 20:53
私もあまり詳しくありませんが、現在は Program Files (x86) 以下のフォルダは
管理者権限で起動していないと書き込みアクセスができない筈ですので、
Steam のソフトが Program Files (x86) 以下に保存しているのは特殊な例だと思います
何かしら手段があるのかもしれませんが、基本的には現在ははるかぜさんが
ご紹介されているフォルダに保存する方が良いです
( もしどうしても気になられるということでしたらスチーム関連をお任せされた
という方にお訊ねになってみられては如何でしょうか? )
|
Re: セーブ場所について ( No.4 ) |
- 名前:たろう 日時:2020/10/16 03:40
ご返信いただきありがとうございます
SHGetSpecialFolderPath CSIDL_APPDATAを試してみて気づいたのですが
これだと途中にユーザー名のフォルダが入ってくるので
とくにutf-8で作っているとユーザー名に日本語が入ると文字化けの可能性が発生するので
例えば
char saveLoc[260]={0},savePath[260]={0};
SHGetSpecialFolderPath(NULL, saveLoc, CSIDL_APPDATA, FALSE);
ConvertStringCharCodeFormat( DX_CHARCODEFORMAT_SHIFTJIS, saveLoc, DX_CHARCODEFORMAT_UTF8, savePath );
などとして得たパスをUTF-8に変換して、さらに得たパスを使ってセーブファイルを作る際に使う
fopenにパスを渡す際も
ConvertStringCharCodeFormat( DX_CHARCODEFORMAT_UTF8, savePath , DX_CHARCODEFORMAT_SHIFTJIS ,saveLoc );
のようにしてS-JISに戻してからfopenをつかうようになるという感じでしょうか?
|
Re: セーブ場所について ( No.5 ) |
- 名前:管理人 日時:2020/10/16 21:25
日本語でしたら SHIFT-JIS で問題ありませんが、海外のユーザーの場合は
日本語以外の文字( SHIFT-JISには無い文字 )でユーザー名を作成している可能性がありますので、
SHGetSpecialFolderPath ではなく SHGetSpecialFolderPathW を使用するようにして
文字列を UTF-16LE で取得した方が良いと思います
( SHGetSpecialFolderPathW は文字列を UTF-16LE で取得する関数です
( 引数の型が char ではなく wchar_t になります ) )
UTF-16LE の場合は fopen の代わりに _wfopen、または CreateFileW でファイルを
オープンする形となります( _wfopen や CreateFileW も同様に文字列を UTF-16LE の
形式( wchar_t )で渡す関数です )
もし一時的に utf-8 にした場合も _wfopen や CreateFileW に渡す際には UTF-16LE に
変換する必要があります
wchar_t saveLoc[2048]={0};
char savePath[2048]={0};
SHGetSpecialFolderPathW(NULL, saveLoc, CSIDL_APPDATA, FALSE);
ConvertStringCharCodeFormat( DX_CHARCODEFORMAT_UTF16LE, ( char * )saveLoc, DX_CHARCODEFORMAT_UTF8, savePath );
ConvertStringCharCodeFormat( DX_CHARCODEFORMAT_UTF8, savePath , DX_CHARCODEFORMAT_UTF16LE ,( char * )saveLoc );
因みに Windows10 ではかなり長いファイルパスも許可されるようになったので、文字列の
バッファのサイズは結構大きめにしておいた方が良いと思います
( あと、Windows環境では wchar_t の形式は UTF-16LE ですが、あくまで Windows環境での話で、
必ずしも wchar_t = UTF-16LE ではありませんのでご注意ください( 例えば Android では wchar_t は UTF-32LE です ) )
|
Re: セーブ場所について ( No.6 ) |
- 名前:たろう 日時:2020/10/17 18:41
いつもご返信いただきありがとうございます
頂いた情報から、utf-8でゲームを作成している際の
CSIDL_APPDATA(C:\Users\ユーザー名\AppData\Roaming)に
「ゲームフォルダ」と、テキストファイル「ゲームファイル.txt」を作成して、
その後それを読みこんで表示するサンプルを作ってみました。
なにか間違いがございましたらご指摘いただけますでしょうか
お手すきの時で結構です。宜しくお願いいたします<(_ _)>
(修正:Get_wchar_t_CharCodeFormat()を見つけたので使ってみました。lpCmdLineを使う場合を考えてwWinMainにしました)
------------------------------------------------------------
#define _CRT_SECURE_NO_WARNINGS
#include "DxLib.h"
#include <locale.h>
#include <shlobj.h>
#include <direct.h>
char 文[5][260];
void フォルダ作成(wchar_t *path)
{
if(_wmkdir(path) == 0){;}
}
void テキストファイル作成(wchar_t *path)
{
FILE *fp; if( ( fp=_wfopen( path, L"w" ) )==NULL){return;} for(int i=0;i<5;i++){fprintf(fp, u8"テスト(%d行目)\n",i);} fclose(fp);
}
void テキストファイル読込(char *path)
{
int FH= FileRead_open(path);FileRead_set_format(FH, DX_CHARCODEFORMAT_UTF8);
for(int i=0;i<5;i++){ FileRead_gets(文[i],260,FH);} FileRead_close(FH);
}
int WINAPI wWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow )
{
setlocale( LC_ALL, ".utf8" );
SetUseCharCodeFormat( DX_CHARCODEFORMAT_UTF8 );
ChangeWindowMode(TRUE);
if( DxLib_Init() < 0 ) return -1;
wchar_t saveLoc[2048]={0};
wchar_t folderpath[2048]={0};
wchar_t filepath[2048]={0};
char readpath[2048]={0};
SHGetSpecialFolderPathW(NULL, saveLoc, CSIDL_APPDATA, FALSE);
swprintf(folderpath,sizeof(folderpath),L"%ls\\ゲームフォルダ",saveLoc);
swprintf(filepath ,sizeof(filepath ),L"%ls\\ゲームファイル.txt",folderpath);
フォルダ作成(folderpath);テキストファイル作成(filepath);
ConvertStringCharCodeFormat( Get_wchar_t_CharCodeFormat(), (char *)filepath, DX_CHARCODEFORMAT_UTF8,readpath);
テキストファイル読込(readpath);
while( ProcessMessage() == 0 )
{
ClearDrawScreen() ;
DrawFormatString( 0,10,GetColor(255,255,255),u8"(%s)",readpath);
for(int i=0;i<5;i++)DrawFormatString( 0,i*30+50,GetColor(255,255,255),u8"(%s)",文[i]);
ScreenFlip();
}
DxLib_End();
return 0;
}
|
Re: セーブ場所について ( No.7 ) |
- 名前:管理人 日時:2020/10/18 02:37
> なにか間違いがございましたらご指摘いただけますでしょうか
載せていただいたプログラムを手元で実行したところ正常に動作しました
コードを拝見する限りでは間違いは無いと思います
|
Re: セーブ場所について ( No.8 ) |
- 名前:kanamaru 日時:2020/10/18 10:56
実行してみましたけど正常に動くんですね。
while文の中でScreenFlipを実行してますが、
このプログラム、SetDrawScreen使ってないので使う必要はないはずです。
ScreenFlip()という関数は裏画面の内容を表画面に描画する関数なのですが、
SetDrawScreenを使ってないので裏画面には描画していないはずなんです。
で、確かdxlibは描画しなければ真っ黒の画面のはずなので、
表示した文字列を真っ黒で塗りつぶして表示したはずの文字列が見えなくなると考えていたんですが。
うまく画面の更新のタイミングが良かったのでしょうか?
ゲームのセーブデータの話みたいなのでもしかしたらScreenFlip()を消すより
Dxlib_Initの下の行に
SetDrawScreen( DX_SCREEN_BACK );
を追加した方がいいかもしれません。
|
Re: セーブ場所について ( No.9 ) |
- 名前:たろう(解決) 日時:2020/10/18 11:30
管理人さん、ご確認いただきありがとうございます
一応動くのですが、私の知らない何かの要因で、環境によっては
問題がある箇所などを想定していましたが
見ていただいて安心できました。ありがとうございました<(_ _)>
kanamaruさんすみません、その個所は短いプログラムにしようと削る際に変な事になっていました
読んだファイルの内容を一度表示したいだけですので、下のように修正しました<(_ _)>
-----------------------------------------------------------
#define _CRT_SECURE_NO_WARNINGS
#include "DxLib.h"
#include <locale.h>
#include <shlobj.h>
#include <direct.h>
char 文[5][260];
void フォルダ作成(wchar_t *path)
{
if(_wmkdir(path) == 0){;}
}
void テキストファイル作成(wchar_t *path)
{
FILE *fp; if( ( fp=_wfopen( path, L"w" ) )==NULL){return;} for(int i=0;i<5;i++){fprintf(fp, u8"テスト(%d行目)\n",i);} fclose(fp);
}
void テキストファイル読込(char *path)
{
int FH= FileRead_open(path);FileRead_set_format(FH, DX_CHARCODEFORMAT_UTF8);
for(int i=0;i<5;i++){ FileRead_gets(文[i],260,FH);} FileRead_close(FH);
}
int WINAPI wWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow )
{
setlocale( LC_ALL, ".utf8" );
SetUseCharCodeFormat( DX_CHARCODEFORMAT_UTF8 );
ChangeWindowMode(TRUE);
if( DxLib_Init() < 0 ) return -1;
wchar_t saveLoc[2048]={0};
wchar_t folderpath[2048]={0};
wchar_t filepath[2048]={0};
char readpath[2048]={0};
SHGetSpecialFolderPathW(NULL, saveLoc, CSIDL_APPDATA, FALSE);
swprintf(folderpath,sizeof(folderpath),L"%ls\\ゲームフォルダ",saveLoc);
swprintf(filepath ,sizeof(filepath ),L"%ls\\ゲームファイル.txt",folderpath);
フォルダ作成(folderpath);テキストファイル作成(filepath);
ConvertStringCharCodeFormat( Get_wchar_t_CharCodeFormat(), (char *)filepath, DX_CHARCODEFORMAT_UTF8,readpath);
テキストファイル読込(readpath);
DrawFormatString( 0,10,GetColor(255,255,255),u8"(%s)",readpath);
for(int i=0;i<5;i++)DrawFormatString( 0,i*30+50,GetColor(255,255,255),u8"(%s)",文[i]);
WaitKey();
DxLib_End();
return 0;
}
|
|