リテラルを使わないでロード

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
てつ

リテラルを使わないでロード

#1

投稿記事 by てつ » 18年前

質問です。

今現在DXライブラリでゲームを作っているのですが、例えば効果音をロードする時

int hSE = LoadSoundMem("push.wav");
.
.
.
.
.
などと一つずつ記述すると、後からデータが追加されたらまたコンパイルしなくては
いけません。これは余り宜しい事ではないと思います。なのでテキストファイルに
効果音名を書き、それを読み込む事でロードすれば良いと考えたのですが、それが
出来ません。何故か読み込みエラーになります。以下はそのプログラムの重要な部分を
簡略化したもの。修正願います。
//file_list.txt/////////////////////////////////////////////////////////////////
"push.wav"

//main.cpp//////////////////////////////////////////////////////////////////////
#include "DxLib.h"
#include<stdio.h>

int hSE;

//効果音ロード------------------------------------------------------------------------------------
void LoadSe(void)
{
	FILE *fp = fopen("file_list.txt", "r");
	char file_name[256];
	
	fgets(file_name, 255, fp);
	
	hSE = LoadSoundMem(file_name); //ここがおかしいようです
	
	fclose(fp);
}

//ゲームメイン関数--------------------------------------------------------------------------------
void GameMain(void)
{
   LoadSe();
                 
   while(!ProcessMessage() && !CheckHitKey(KEY_INPUT_ESCAPE)) //ESCで終了
  {
      PlaySoundMem(hSE, DX_PLAYTYPE_BACK);  //再生されない。読み込みエラー
  }
}

//メイン関数-------------------------------------------------------------------------------------
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
	
	ChangeWindowMode(TRUE); //ウインドウモード
	
	if(DxLib_Init() == -1)	//DXライブラリ初期化処理
	{
		 return -1;			//エラーが起きたら直ちに終了
	}
	
		
	GameMain();             //ゲームメイン関数

	DxLib_End() ;		    //DXライブラリ使用の終了処理

	return 0 ;			    //ソフトの終了
}

Justy

Re:リテラルを使わないでロード

#2

投稿記事 by Justy » 18年前

> 何故か読み込みエラーになります
 読みとった文字列の最後に改行コードが入っているからでは?

てつ

Re:リテラルを使わないでロード

#3

投稿記事 by てつ » 18年前

Justyさん、お返事ありがとうございます。

>読みとった文字列の最後に改行コードが入っているからでは?

それは私も考えました。ですが改行コードを入れなくても、やはり
思った通りに動きません。以下に上記のプログラムを更に改良した
ソースを書きます。出来れば皆さんのパソコンでも実行してみて下さい。
//file_list.txt///////////////////////////////////////////////////////////////////////////////////
"push.wav"


//main.cpp////////////////////////////////////////////////////////////////////////////////////////
//テキストファイルから効果音ファイル名を読み込み
//効果音をロードし再生するプログラム
#include "DxLib.h"
#include<stdio.h>
#include<string.h>

int  hSE;           //効果音ハンドル
char FileName[256]; //効果音ファイル名
int  Length;        //効果音ファイル名文字列長

//効果音ロード------------------------------------------------------------------------------------
void LoadSe(void)
{
	FILE *fp = fopen("file_list.txt", "r"); //ファイルリストオープン

	
	fgets(FileName, 255, fp);  //ファイルから一行読み込む
	Length = strlen(FileName); //文字列長を得る
	FileName[Length] = '\0';   //文字列の終わりは'\0'
	
	hSE = LoadSoundMem(FileName); //効果音ロード
	
	fclose(fp); //ファイルを閉じる
}

//ゲームメイン関数--------------------------------------------------------------------------------
void GameMain(void)
{
	LoadSe(); //初期化処理

	while(!ProcessMessage() && !CheckHitKey(KEY_INPUT_ESCAPE)) //ESCで終了
	{
		ClearDrawScreen();                   //画面を初期化
		PlaySoundMem(hSE, DX_PLAYTYPE_BACK); //再生されない。効果音ファイルは指定の場所にあります
		printfDx("hSE     :%d\n", hSE);      //何故か-1
		printfDx("FileName:%s\n", FileName); //ファイル名は正常に読み込めているみたい
		printfDx("Length  :%d\n", Length);   //"push.wav"の文字列長は10。間違いない
		ScreenFlip();                        //裏画面の内容を表画面に反映
	}
}

//メイン関数--------------------------------------------------------------------------------------
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
	ChangeWindowMode(TRUE);        //ウインドウモード
	
	if(DxLib_Init() == -1)	       //DXライブラリ初期化処理
	{
		 return -1;			       //エラーが起きたら直ちに終了
	}
	
	SetDrawScreen(DX_SCREEN_BACK); //描画先画面を裏にする
	
	GameMain();                    //ゲームメイン関数

	DxLib_End() ;		           //DXライブラリ使用の終了処理

	return 0 ;			           //ソフトの終了
}
細心の注意を払って書いたつもりですが、思い通りに動きません。
何とかコンパクWeb第9回までに作品を完成させたいのですがこれでは・・・・・。
どなたか助けて下さい。宜しくお願いします。

GPGA

Re:リテラルを使わないでロード

#4

投稿記事 by GPGA » 18年前

パスはあっているのでしょうか?
例えば読み込むリソースが実行ファイルに対して res/push.wav の位置にある場合、
LoadSoundMem("res/push.wav");
としないと読み込めないと思うのですが・・・。

YuO

Re:リテラルを使わないでロード

#5

投稿記事 by YuO » 18年前

> Length = strlen(FileName); //文字列長を得る
> FileName[Length] = '\0'; //文字列の終わりは'\0'
これは何がしたいのですか?
FileName[strlen(FileName)]は常に0ですが。
# FileNameの範囲をオーバーして未定義動作になる場合を除く。

デバッガで上記のあたりにブレイクポイントを置いて,FileNameやLengthが本当に正しいのかウォッチしてみるとよいでしょう。
# おそらく,FileName[Length - 1] = '\0;なのだと思いますが……。

てつ

Re:リテラルを使わないでロード

#6

投稿記事 by てつ » 18年前

GPGAさん、お返事ありがとうございます。

パスはあってます。自分はゲームを作る時、効果音は
materialフォルダ内のseというフォルダ内に入れています。
なのでロードする時は

hSE = LoadSoundMem("./material/se/push.wav");

のように記述しています。間違いは無いと思います。
私のパソコンがおかしいのでしょうか?一応2台のパソコンで
試したのですが・・・・・。とにかくコピーして実行してみて下さい。

てつ

Re:リテラルを使わないでロード

#7

投稿記事 by てつ » 18年前

YuOさん

>FileName[strlen(FileName)]は常に0ですが。

0とは\0のことですか?素人で良く分からないので念のため
ファイル名の末端に\0を入れました。

>デバッガで上記のあたりにブレイクポイントを置いて~
すみません。VisualC++はビルドボタンくらいしか使わないので
デバッガとかブレイクポイントなんてのは分かりません。
よろしければサンプルコードを頂けませんか?

てつ

Re:リテラルを使わないでロード

#8

投稿記事 by てつ » 18年前

追伸
FileName[Length - 1]をprintfDxで表示させたら何も出ませんでした。
これは何を意味するのでしょう。分かりません。

GPGA

Re:リテラルを使わないでロード

#9

投稿記事 by GPGA » 18年前

ファイル名を読み込んだ際FileNameの中には
FileName[0] == 'p'
FileName[1] == 'u'
FileName[2] == 's'
FileName[3] == 'h'
FileName[4] == '.'
FileName[5] == 'w'
FileName[6] == 'a'
FileName[7] == 'v'
FileName[8] == '\n'
FileName[9] == '\0'
となっています。
このときに
Length = strlen(FileName); //文字列長を得る
を行うと、Lengthに9が入ります。
FileName[Length] = '\0'; は FileName[9] = '\0'; となるため
意味のない処理になってしまいます。

これを
FileName[Length - 1] = '\0';
とすることで、\0を改行文字の上に上書きしてなくすことができます。

ちなみにprintfDxで改行コードを表示しようとしても、何もでません。

てつ

Re:リテラルを使わないでロード

#10

投稿記事 by てつ » 18年前

すみません、事情により返事は暫く後になります。

ま~く

Re:リテラルを使わないでロード

#11

投稿記事 by ま~く » 18年前

テキストデータに"(ダブルクォート)が入っているからじゃないんですか?

てつ

Re:リテラルを使わないでロード

#12

投稿記事 by てつ » 18年前

ま~くさん

>テキストデータに"(ダブルクォート)が入っているからじゃないんですか?
それですよ、それ!皆様のアドバイスをもとに色々試していたのですが
上手くいかず、どうしても分からないので、昔通っていた専門学校の先生に
質問のメールを書いていたところでした(自分は専門学校の落ちこぼれでして
ゲーム会社に就職できず、仕方ないので個人でやってやろうと思ってたりします。
かなり無謀ですが)。文字列はダブルクォートで括らないといけないという
思い込み。怖いですねぇ。


何とか問題解決できました。皆様ありがとうございました。

閉鎖

“C言語何でも質問掲示板” へ戻る