【雑談?】自分の書いたソースを見てください

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
Rittai_3D
記事: 525
登録日時: 11年前

【雑談?】自分の書いたソースを見てください

#1

投稿記事 by Rittai_3D » 10年前

お世話になります。3Dです。

今日は自分の書いたプログラムを見てほしくて投稿しました。

自分の日記を見てくださった方なら分かると思いますが、一昨日からC++を勉強し始めました。

クラスの勉強がてら以前C言語でつくった東方ProjectというゲームのミュージックルームをC++で作り直してみました。

main.cpp

コード:

#define _CRT_SECURE_NO_WARNINGS 1
#include "DxLib.h"
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "main.h"

static int Key[ 256 ];

MusicRoom Music_Room,Music[ MUSIC_NUM ]; // インスタンス化

int gpUpdateKey()
{
	char tmpKey[256]; // 現在のキーの入力状態を格納する

	GetHitKeyStateAll( tmpKey );//全てのキーの入力状態を得る

	for( int i=0; i<256; i++ ){
		if( tmpKey[i] != 0 )//i番のキーコードに対応するキーが押されていたら
			Key[i]++;		//加算
		else				//押されていなければ
			Key[i] = 0;		//0にする
	}

	return 0;
}

int ProcessLoop() // 毎回行う重要なループ
{
	if( ProcessMessage()  != 0 ) return 1;
	if( ClearDrawScreen() != 0 ) return 1;
	if( gpUpdateKey()     != 0 ) return 1;
	return 0;
}

void MusicRoom::Load_Script()
{
	char FileName[] = "dat/bgm/musiccmt.txt"; // ファイルの名前
	int i,num=0,n=0,line=0; // n曲目の判断やfor文関係 
	int  input[128];		// 一文字読み込むのに必要
	char inputc[128];	// 上に同じ

	FILE* fp = fopen( FileName , "r" ); // ファイルを開く

	if( fp == NULL ){ // ファイルが無い時の処理
		MSG( "No Script File !" );
		exit(1);
	}

	for(i=0 ; i<4 ; i++ ) // 最初の4行はコメントなので読み飛ばす
		while( fgetc( fp ) != '\n' );

	while( 1 ){
		for(i=0 ; i<128 ; i++ ){ // 横64文字まで読み込んで
			input[i] = inputc[i] = fgetc( fp );

			if( input[i] == '#' ){ // コメント記号ならば
				while( fgetc( fp ) != '\n' ); // その行の終わりまでループして
				i = -1; // カウンタを戻して
				continue;
			}

			if( input[i] == '\n' ){	// 改行記号なら(独自フォーマットのファイルだから改行で区切る)
				inputc[i] = '\0';	// そこまでを文字列にして
				break;
			}

			if( input[i] == EOF ){	// EOFなら(ここは、charで判断はしないほうが良い)
				goto EXFILE;		// ファイルクローズタグにジャンプ( でいいのかな? )
			}
		}

		switch( num ){ // 読み込んだファイルから構造体にコピーする
			case 0: strcpy( Music[n].m_path   , inputc ); break; // 音楽再生の為のパス
			case 1: strcpy( Music[n].m_name[0], inputc ); break; // 名前1 : No.~
			case 2: strcpy( Music[n].m_name[1], inputc ); break; // 名前2 : ♪~
				// -----------------以下、コメント読み込み----------------- //
			case 3: strcpy( Music[n].m_comme[ line ]    , inputc );break;
			case 4: strcpy( Music[n].m_comme[ line + 1 ], inputc );break;
			case 5: strcpy( Music[n].m_comme[ line + 2 ], inputc );break;
			case 6: strcpy( Music[n].m_comme[ line + 3 ], inputc );break;
			case 7: strcpy( Music[n].m_comme[ line + 4 ], inputc );break;
			case 8: strcpy( Music[n].m_comme[ line + 5 ], inputc );break;
			case 9: strcpy( Music[n].m_comme[ line + 6 ], inputc );break;
				// -------------------------------------------------------- //
		}

		num++; // num加算

		if( num == 10 ){ // numの値が9(1曲分のファイル読み込みが終わったら)なら
			num = 0;	// numを加算
			n++;		// nも加算
		}
	}
EXFILE: // ファイルクローズ
	fclose( fp );
}

void MusicRoom::Load_LoopFile()
{
	char FileName[] = "dat/bgm/loop.txt"; // ファイル名( path )
	int  input[32];  // 一文字読み込み
	char inputc[32]; // 一文字読み込み
	int i,n=0;

	FILE* fp = fopen( FileName, "r" ); // ファイルをリード形式で展開

	if( fp == NULL ){ // ファイルが無い時の処理
		MSG( "No Loop File !" );
		exit(1);
	}

	for(i=0 ; i<4 ; i++ ) // 最初の4行はコメントなので飛ばす
		while( fgetc( fp ) != '\n' );

	while( 1 ){
		for(i=0 ; i<32 ; i++ ){
			input[i] = inputc[i] = fgetc( fp );

			if( input[i] == '#' ){ // コメント記号なら
				while( fgetc( fp ) != '\n' ); // 改行までループして
				i = -1; // カウンタを戻して
				continue;
			}

			if( input[i] == ';' ){ // 終了記号なら
				inputc[i] = '\0';  // そこまでを文字列として
				break;
			}

			if( input[i] == EOF ){ // ファイルの終わりなら
				goto EXFILE;
			}
		}
		Music[n].m_loop = atoi( inputc ); // 読みとったループ位置を構造体のloopに代入
		n++; // 曲加算
	}

EXFILE:
	fclose( fp );
}

void MusicRoom::Load_BGM()
{
	int i;

	for(i=0 ; i<MUSIC_NUM ; i++ ){
		Music[i].m_BGM = LoadBGM( Music[i].m_path ); // BGMを流し込む

		if( Music[i].m_BGM == NULL ){
			MSG( "Waveファイルがないぞぅ" ) ;
			exit(1);
		}
	}

	SetLoopTimePosSoundMem( Music[0].m_loop , Music[0].m_BGM );	// 最初の曲のループ位置を設定
	PlaySoundMem( Music[0].m_BGM, DX_PLAYTYPE_BACK );			// 最初の曲を流しておく

}

void MusicRoom::Init()
{
	Music_Room.m_Font[0] = CreateFontToHandle( "MSPゴシック", 16, 16, DX_FONTTYPE_ANTIALIASING_EDGE_8X8, -1, 1, 0, -1 ); // フォント1
	Music_Room.m_Font[1] = CreateFontToHandle( "MSPゴシック", 14, 10, DX_FONTTYPE_ANTIALIASING_EDGE_8X8, -1, 1, 0, -1 ); // フォント2

	Music_Room.m_img_back[0] = LoadGraph( "dat/img/title03a.png" );	// 画像を読み込む
	Music_Room.m_img_back[1] = LoadGraph( "dat/img/title03b.png" );	// 画像を読み込む

	Music_Room.m_se_select  = LoadSoundMem( "dat/se/se_select00.wav" );	// seを読み込む

}

void MusicRoom::Load() // 読み込みメイン
{
	Load_Script();
	Load_LoopFile();
	Load_BGM();
}

void MusicRoom::Draw() // 項目を描写
{
	int i,j;

	DrawGraph(   0, 0, Music_Room.m_img_back[0], TRUE);	// 画像を描写
	DrawGraph( 512, 0, Music_Room.m_img_back[1], TRUE);	// 同上

	for(i=0 , j=0 ; i<MUSIC_NUM ; j++ , i++ ){ // No.~の部分
		if( i == Music_Room.m_SelectNum ) // もし選択中なら
			DrawFormatStringToHandle( 60, 130+18*j, GetColor(240,210,210), Music_Room.m_Font[0], "%s", Music[i].m_name[0] );
		else  // そうで無ければ
			DrawFormatStringToHandle( 65, 130+18*j, GetColor(130,105,105), Music_Room.m_Font[0], "%s", Music[i].m_name[0] );
	}

	for(i=0 ; i<MUSIC_NUM ; i++ ){// 曲名を表示
		DrawFormatStringToHandle( 60, 320, GetColor(240,210,210), Music_Room.m_Font[1], "%s", Music[ Music_Room.m_SelectedMusicNo ].m_name[1] );
	}

	for(i=0 ; i<7 ; i++ ){// コメントの行数
		DrawFormatStringToHandle( 80, 340+18*i, GetColor(240,210,210), Music_Room.m_Font[1], "%s", Music[ Music_Room.m_SelectedMusicNo ].m_comme[i] );
	}
}

void MusicRoom::Update()
{
	int i;
	if( Key[ KEY_INPUT_DOWN ] == 1 || ( Key[ KEY_INPUT_DOWN ] % 5 == 0 && Key[ KEY_INPUT_DOWN ] > 30 ) ){ // ↓キーが押されたら
		Music_Room.m_SelectNum = ( Music_Room.m_SelectNum + 1 ) % MUSIC_NUM;
	}

	if( Key[ KEY_INPUT_UP ] == 1  || ( Key[ KEY_INPUT_UP ] % 5== 0 && Key[ KEY_INPUT_UP ]> 30 ) ){ // ↑キーが押されたら
		Music_Room.m_SelectNum = ( Music_Room.m_SelectNum + ( MUSIC_NUM - 1 ) ) % MUSIC_NUM;
	}

	if( Key[ KEY_INPUT_DOWN ] == 1 || Key[ KEY_INPUT_UP ] == 1 || ( Key[ KEY_INPUT_DOWN ] % 5 == 0 && Key[ KEY_INPUT_DOWN ] > 30 )||
		( Key[ KEY_INPUT_UP ] % 5 == 0 && Key[ KEY_INPUT_UP ] > 30 ) ){ // 上下どちらかのキーが押されたら

			PlaySoundMem( Music_Room.m_se_select, DX_PLAYTYPE_BACK ); // 選択音を再生
	}

	if( Key[ KEY_INPUT_Z ] == 1 || Key[ KEY_INPUT_RETURN ] == 1 ){ // Z Key と Enter Key が押されたら
		Music_Room.m_SelectedMusicNo = Music_Room.m_SelectNum; // 選択された項目を更新する

		for(i=0 ; i<MUSIC_NUM+1 ; i++ ){
			if( CheckSoundMem( Music[i].m_BGM ) == 1 ){	// 再生中なら
				StopSoundMem(  Music[i].m_BGM );		// サウンドファイルを停止する
			} else {
				SetLoopTimePosSoundMem( Music[ Music_Room.m_SelectedMusicNo ].m_loop, Music[ Music_Room.m_SelectedMusicNo ].m_BGM ); // 選択された曲のループ位置
				PlaySoundMem( Music[ Music_Room.m_SelectedMusicNo ].m_BGM , DX_PLAYTYPE_BACK );										 // 音楽を再生
			}
		}
	}
}

void MusicRoom::Finalize() // 終了処理( 確か、書かなくてもOK )
{
	InitGraph();
	InitFontToHandle();
	InitSoundMem();
}

int WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR, int )
{
	ChangeWindowMode( TRUE ), SetAlwaysRunFlag( TRUE ), DxLib_Init(), SetDrawScreen( DX_SCREEN_BACK ); // いつもの処理

	/* -----------------------初期化と読み込み--------------------------- */
	Music_Room.Init();
	Music_Room.Load();
	/* ------------------------------------------------------------------ */

	while( !ProcessLoop() ){ // メインループ

		Music_Room.Update(); // 更新
		Music_Room.Draw();   // 描写

		ScreenFlip();
	}

	// 終了処理
	Music_Room.Finalize();

	DxLib_End();
	return 0;
}
main.h

コード:

#pragma once

#define MUSIC_NUM 6
#define MSG( message ) { MessageBox( NULL, _T( message ), _T( "Message" ), MB_OK ); }

class MusicRoom
{
private: // 変数のみを書くようにしています.

	/* ---------------------ファイルの読み込みで使う--------------------- */
	int  m_loop;			// 曲のループ位置
	char m_path[ 256 ];		// 曲のコメント(パス)
	char m_name[2][ 256 ];	// [0] = (名前1),[1] = (名前2)
	char m_comme[7][ 256 ];	// (コメント)
	/* ------------------------------------------------------------------ */

	/* ----------------------表示に関係する変数-------------------------- */
	int m_img_back[2];			// 背景画像を読み込む
	int m_se_select  ;			// seを読み込む
	int m_Font[2]    ;			// フォントを設定する

	int m_SelectNum       ;	// 現在選択中
	int m_SelectMusicCmt  ;	// 現在表示している曲のコメント
	int m_SelectedMusicNo ;	// コメントを表示する曲の番号を保持
	int m_BGM;				// BGMをメモリに読み込む為の変数
	/* ------------------------------------------------------------------ */

public: // 関数のみを書くようにしています。

	/* ---------------------読み込み関数--------------------------------- */
	void Load_Script();
	void Load_LoopFile();
	void Load_BGM();

	void Load(); // 読み込みメイン
	/* ------------------------------------------------------------------ */

	/* ----------------------初期化処理関数------------------------------ */
	void Init();
	/* ------------------------------------------------------------------ */

	/* ---------------------メインループで毎回行う処理------------------- */
	void Draw();
	void Update();
	/* ------------------------------------------------------------------ */

	// 終了処理
	void Finalize();

};
かなり長いコードを張ってしまい申し訳ありません。

このプログラムを見て、「ここをこうしたほうがいいよ」等のアドバイスがいただけたらと思います。

上にも書いた通り、一昨日からC++を勉強始めたので滅茶苦茶な部分があると思います。そういった部分も指摘していただけたらと思います。

ソースが汚い部分はスルーで(ぉぃ
初心者です

アバター
usao
記事: 1887
登録日時: 11年前

Re: 【雑談?】自分の書いたソースを見てください

#2

投稿記事 by usao » 10年前

各メソッドが外部変数Music_Roomの存在を前提に書かれているように見えますが…
クラスについてもう少し文法レベルでの理解が必要なのではないでしょうか.

・コンストラクタとデストラクタ
・メンバ変数
・メンバ関数
くらいをちゃんと勉強してもう一度書いてみては?

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: 【雑談?】自分の書いたソースを見てください

#3

投稿記事 by softya(ソフト屋) » 10年前

MusicRoom Music_Room,Music[ MUSIC_NUM ]; // インスタンス化
ここのMusic[ MUSIC_NUM ];がすごく気になります。クラスのインスタンスが存在する前提なのが超マズイです。
MusicRoom Music_Room;だけで動くようにしてください。あとmainのローカルでインスタンス化してください。

【追記】
つまり、これのデータの持ち方が変なのです。

コード:

    int  m_loop;            // 曲のループ位置
    char m_path[ 256 ];     // 曲のコメント(パス)
    char m_name[2][ 256 ];  // [0] = (名前1),[1] = (名前2)
    char m_comme[7][ 256 ]; // (コメント)
→とにかく、構造体にする事です。

それとstd::stringは利用して欲しいです。[追記]すっきり書くためにはfstreamも使ったほうが良いでしょうね。

本当は、コメント・曲名管理とBGM管理とSE管理と統括クラスに分けて欲しい所ですね。
【追記】 クラスをただの関数をまとめる場所だと思うとオブジェクト指向の道から外れていくので要注意です。

C++の勉強を始めてから実際に書くまですごく早かったですが、下記のサイトのようなのを1つ1つ丁寧に理解されたほうがよい気がしますね。
「ロベールのC++教室」
http://www7b.biglobe.ne.jp/~robe/cpphtml/
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: 【雑談?】自分の書いたソースを見てください

#4

投稿記事 by softya(ソフト屋) » 10年前

追記を書きすぎたので、別に書いときます。
void Load_Script();
void Load_LoopFile();
void Load_BGM();
はpublicにする必要性がありません。
なぜなら、クラス外から呼び出されないからです。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
みけCAT
記事: 6734
登録日時: 13年前
住所: 千葉県
連絡を取る:

Re: 【雑談?】自分の書いたソースを見てください

#5

投稿記事 by みけCAT » 10年前

せっかくC++なので、

コード:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

コード:

#include <cstdio>
#include <cstdlib>
#include <cstring>
としてみたらどうですか?
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

Rittai_3D
記事: 525
登録日時: 11年前

Re: 【雑談?】自分の書いたソースを見てください

#6

投稿記事 by Rittai_3D » 10年前

>>usao様

返信ありがとうございます。

>各メソッドが外部変数Music_Roomの存在を前提に書かれているように見えますが…
クラスについてもう少し文法レベルでの理解が必要なのではないでしょうか.

>・コンストラクタとデストラクタ
>・メンバ変数
>・メンバ関数
>くらいをちゃんと勉強してもう一度書いてみては?

わかりました。softya様の返信のリンクで勉強してきます。

今回は何故かすぐに書きたくなったので書いてしまいました。
初心者です

アバター
usao
記事: 1887
登録日時: 11年前

Re: 【雑談?】自分の書いたソースを見てください

#7

投稿記事 by usao » 10年前

まず最初は「クラス書いてみた」程度の小さい例をやってみてはいかがでしょう?

コード:

class CMy1stClass
{
public:
    CMy1stClass( int val=0 ){  SetVal(val);  }
    ~CMy1stClass(){  printf( "destructor of CMy1stClass\n" );  }
public:
    void SetVal( int val ){  m_Val=val;  }
    int GetVal() const {  return m_Val;  }
    void PrintVal() const {  printf( "m_Val=%d\n", m_Val );  }
private:
    int m_Val;
};

int main()
{
  {
    CMy1stClass ClassInstance( 82 );
    ClassInstance.PrintVal();
    ClassInstance.SetVal( 4 );
    printf( "After SetVal : %d\n", ClassInstance.GetVal() );
  }

  printf( "=== End of All ===\n" );
  return 0;
}
自分の問題に使うのはいろいろ試してみた後で良いかと思いますよ.

Rittai_3D
記事: 525
登録日時: 11年前

Re: 【雑談?】自分の書いたソースを見てください

#8

投稿記事 by Rittai_3D » 10年前

>>softya様

返信ありがとうございます。

>MusicRoom Music_Room,Music[ MUSIC_NUM ]; // インスタンス化
>ここのMusic[ MUSIC_NUM ];がすごく気になります。クラスのインスタンスが存在する前提なのが超マズイです。
>MusicRoom Music_Room;だけで動くようにしてください。あとmainのローカルでインスタンス化してください。

わかりました。学校の課題の提出やらが忙しいので、少し時間が掛かりますがやってみます。

>とにかく、構造体にする事です。

構造体の事を忘れていました。これから修正します。

>それとstd::stringは利用して欲しいです。[追記]すっきり書くためにはfstreamも使ったほうが良いでしょうね。

std::stringとfstreamは調べて使ってみます

>本当は、コメント・曲名管理とBGM管理とSE管理と統括クラスに分けて欲しい所ですね。

class Cmt_name //コメントと名前管理
class Se //se管理
class Bgm //bgm管理
class MusicRoom //総括クラス

と分けてやってみます。

>【追記】 クラスをただの関数をまとめる場所だと思うとオブジェクト指向の道から外れていくので要注意です。

クラスは変数を纏めるものだと思っていました。勉強し直します。

オブジェクト指向も勉強が足りないですね。オブジェクト指向は理解しづらいです。

>C++の勉強を始めてから実際に書くまですごく早かったですが、下記のサイトのようなのを1つ1つ丁寧に理解されたほうがよい気がしますね。
>「ロベールのC++教室」
> http://www7b.biglobe.ne.jp/~robe/cpphtml/

リンクありがとうございます。基礎をしっかりします。

>追記を書きすぎたので、別に書いときます。
>void Load_Script();
>void Load_LoopFile();
>void Load_BGM();
>はpublicにする必要性がありません。
>なぜなら、クラス外から呼び出されないからです。

ではクラス分けした後で、privateに書きます。
初心者です

Rittai_3D
記事: 525
登録日時: 11年前

Re: 【雑談?】自分の書いたソースを見てください

#9

投稿記事 by Rittai_3D » 10年前

>>みけCAT様

返信ありがとうございます。
みけCAT さんが書きました:せっかくC++なので、

コード:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

コード:

#include <cstdio>
#include <cstdlib>
#include <cstring>
としてみたらどうですか?
cのくせで
#include<stdio.h>
としてしまいました。

#include <cstdio>
の書き方に早く慣れたいです。
初心者です

Rittai_3D
記事: 525
登録日時: 11年前

Re: 【雑談?】自分の書いたソースを見てください

#10

投稿記事 by Rittai_3D » 10年前

>>usao様

返信ありがとうございます。
usao さんが書きました:まず最初は「クラス書いてみた」程度の小さい例をやってみてはいかがでしょう?

コード:

class CMy1stClass
{
public:
    CMy1stClass( int val=0 ){  SetVal(val);  }
    ~CMy1stClass(){  printf( "destructor of CMy1stClass\n" );  }
public:
    void SetVal( int val ){  m_Val=val;  }
    int GetVal() const {  return m_Val;  }
    void PrintVal() const {  printf( "m_Val=%d\n", m_Val );  }
private:
    int m_Val;
};

int main()
{
  {
    CMy1stClass ClassInstance( 82 );
    ClassInstance.PrintVal();
    ClassInstance.SetVal( 4 );
    printf( "After SetVal : %d\n", ClassInstance.GetVal() );
  }

  printf( "=== End of All ===\n" );
  return 0;
}
自分の問題に使うのはいろいろ試してみた後で良いかと思いますよ.
アドバイスありがとうございます。まだまだ初心者なので、サンプルをいじくって勉強したいと思います。

課題と部活と勉強でC++の勉強時間が少ないてますが、理解していきたいです。
初心者です

Rittai_3D
記事: 525
登録日時: 11年前

Re: 【雑談?】自分の書いたソースを見てください

#11

投稿記事 by Rittai_3D » 10年前

解決にするのをすっかり忘れていました。

返信して下さった皆様、本当にありがとうございました。
初心者です


閉鎖

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