ページ 11

初心者質問場

Posted: 2011年6月09日(木) 02:48
by 闇噤
勝手に作らせていただきます
1からとなってるんで基本初心者が入ってきてもおかしくない・・・はず(なんせ自分が初心者)

質問場だとなんか質問しにくければここを使えばという案
ここなんか自己紹介だけでおわってるからw

んではー 答えれる人は答えて聞きたいことは聞こう
ちなみに現在画像がある地点に来ればある画像が発動する仕組みに四苦八苦

Re: 初心者質問場

Posted: 2011年6月18日(土) 14:19
by てんむすキツネ
こんにちは~
思いっきり初心者ですが自分なりに電卓をつくってみました!
省略できるところ
(int a;
int b;

int a,b;
などにするやつ)
とか
追加したらイイ機能をおしえてください!
#include <stdio.h>

int main(void){
double x,y,g;
char k = '\0',m = '\0',my[120],s[120];
printf("これは電卓です\nマニュアルを見ますか?\n~YES or NO~\n");
scanf("%s",&m);
if(m == 89)
{
FILE *fp;
printf("ok\n");
fp = fopen("マニュアル.txt","r");
if(fp == NULL)
printf("*エラー*\a\nファイルを読み込めませんでした\n");
while(1)
{
fgets(my,40,fp);
if(feof(fp))
break;
printf("%s",my);
}
fclose(fp);
}
else if(m == 78)
{
printf("ok\n");
}

scanf("%lf",&x);
scanf("%s",&k);
scanf("%lf",&y);
if(k == 43)
{
printf("%f%c%f=%f\n",x,k,y,x+y);
g = x + y;
}
else if(k == 45)
{
printf("%f%c%f=%f\n",x,k,y,x-y);
g = x - y;
}
else if(k == 42)
{
printf("%f×%f=%f\n",x,y,x*y);
g = x * y;
}
else if(k == 47)
{
printf("%f÷%f=%f\n",x,y,x/y);
g = x / y;
}
else
{
printf("*エラー*\a\n");
}


while(1)
{
scanf("%s",&k);
if(k == 82)
{
printf("リセットしました\n");
g = 0;
k = 0;
scanf("%lf",&g);
continue;
}
else if(k == 83)
{
FILE *fp;
printf("保存するものの名前を入力してください\n");
scanf("%s",&s);
printf("保存しています・・・\n");
fp = fopen("保存内容.txt","a");
fputs(s,fp);
fprintf(fp,"\n%f\n",g);
fclose(fp);
printf("正常に保存されました\n");
continue;
}
else if(k == 72)
{
FILE *fp;
printf("保存した内容を表示します・・・\n");
fp = fopen("保存内容.txt","r");
if(fp == NULL)
printf("*エラー*\a\nファイルを読み込めませんでした\n");
while(1)
{
fgets(my,40,fp);
if(feof(fp))
break;
printf("%s",my);
}
fclose(fp);
}
else if(k == 66)
{
FILE *fp;
printf("保存してあるデータを消します\nよろしいですか?\n~YESorNO~\n");
scanf("%s",&k);
if(k == 89)
{
fp = fopen("保存内容.txt","w");
if(fp== NULL)
printf("*エラー*\a\nファイルを読み込めませんでした\n");

fclose(fp);
printf("データを削除しました\n");
}
else
{
printf("データの削除を取り消しました\n");
}
}
scanf("%lf",&y);
if(k == 43)
{
printf("%f%c%f=%f\n",g,k,y,g+y);
g = g + y;
}
else if(k == 45)
{
printf("%f%c%f=%f\n",g,k,y,g-y);
g = g - y;
}
else if(k == 42)
{
printf("%f×%f=%f\n",g,y,g*y);
g = g * y;
}
else if(k == 47)
{
printf("%f÷%f=%f\n",g,y,g/y);
g = g / y;
}
else
{
printf("*エラー*\a\n");
}

}
}
ぐちゃぐちゃですみません・・・

Re: 初心者質問場

Posted: 2011年6月19日(日) 10:28
by bitter_fox
月狐 さんが書きました: 思いっきり初心者ですが自分なりに電卓をつくってみました!

ぐちゃぐちゃですみません・・・
ソースコードを載せるときはcodeタグを使ってくださいね。
それからインデント(字下げ)も適切に行いましょう。

コード:

	if(m == 89) // if (m == 'Y')
	else if(m == 78) // if (m == 'N')
	if(k == 43) // if (k == '+')
	  .
	  .
	  .
また、文字の比較には文字コードを直接用いず'X'と言った風に文字として比較した方が可読性がありますので、そのようにしてはいかがでしょうか?

コード:

	char k = '\0',m = '\0',my[120],s[120];
	scanf("%s",&m);
	scanf("%s",&k);
scanfに%sを指定して文字列として受け取ろうとしていますが、m, kはchar型なので不適切で、アプリケーションエラーが発生する可能性が高いです。
%cを指定してください。

コード:

		if(fp == NULL)
			printf("*エラー*\a\nファイルを読み込めませんでした\n");
		while(1)
		{
			fgets(my,40,fp);
			if(feof(fp))
				break;
			printf("%s",my);
		}
これだとfpがNULLでも下のループに入ってしまうので、fgetsの第三引数及びfeofの第一引数にNULLを指定することになってしまい、アプリケーションエラーが発生していしまいます。
[hr][追記]
あと、自分が何に対して入力しているのかが分かりずらいので、何に対して入力しているのかを表示してほしいですね。

Re: 初心者質問場

Posted: 2011年6月20日(月) 06:34
by てんむすキツネ
とても参考になりました!ありがとうございます!!
これからは出来るだけ見やすくつくっていきます><

またまた質問 DXライブラリをインクルード

Posted: 2011年6月26日(日) 19:41
by てんむすキツネ
何度もすんませんー
DXライブラリ置き場に書いてあるとうりにやったんですけど
なぜか読み込んでくれません
vc2010をアンインストールしてインストールしなおしたんですが何回やってもうまくいきません
誰か教えてください
ビルドした際にでるエラー↓

1>------ ビルド開始: プロジェクト: あにまるしゅーてぃんぐ!, 構成: Debug Win32 ------
1>2011/06/26 19:38:20 にビルドを開始しました。
1>InitializeBuildStatus:
1> "Debug\●●.unsuccessfulbuild" のタッチ タスクを実行しています。
1>ClCompile:
1> メイン.cpp
1>c:\documents and settings\●●●\デスクトップ\●専用フォルダ\●●●\メイン.cpp(1): fatal error C1083: include ファイルを開けません。'DxLib.h': No such file or directory
1>
1>ビルドに失敗しました。
1>
1>経過時間 00:00:02.75
========== ビルド: 0 正常終了、1 失敗、0 更新不要、0 スキップ ==========

というかんじ です
もしかしたらDX置き場に書いてある通りに出来てないかもしれません・・・たぶん出来てるとおもうんですが

Re: またまた質問 DXライブラリをインクルード

Posted: 2011年6月26日(日) 22:08
by bitter_fox
月狐 さんが書きました: 1>c:\documents and settings\●●●\デスクトップ\●専用フォルダ\●●●\メイン.cpp(1): fatal error C1083: include ファイルを開けません。'DxLib.h': No such file or directory

もしかしたらDX置き場に書いてある通りに出来てないかもしれません・・・たぶん出来てるとおもうんですが
「構成プロパティー」->「C/C++」->「全般」->「追加のインクルードディレクトリ」にちゃんとDxLib.hがあるディレクトリが指定されていますか?
1.png
1.png (27.55 KiB) 閲覧数: 23021 回
2.png

Re: 初心者質問場

Posted: 2011年6月28日(火) 21:01
by てんむすキツネ
ありがとうございました!
参照するフォルダが間違っていたようです^^
本当にありがとうございました!

ゲームで使うグラフィック

Posted: 2011年6月29日(水) 18:14
by てんむすキツネ
DXライブラリの勉強しながらゲームのグラフィックも作りたいと
思ったので質問です!((意味不
ゲームを作る際グラフィックはどのようにして書いているの
ですか?おすすめのソフトなどあれば教えてください!(無料のものがいいです)

Re: ゲームで使うグラフィック

Posted: 2011年7月01日(金) 07:03
by bitter_fox
月狐 さんが書きました:DXライブラリの勉強しながらゲームのグラフィックも作りたいと
思ったので質問です!((意味不
ゲームを作る際グラフィックはどのようにして書いているの
ですか?おすすめのソフトなどあれば教えてください!(無料のものがいいです)
グラフィックの知識には明るくないのですが、GIMPなどが定番ではないでしょうか?
http://www.gimp.org/ - GIMP公式サイト(英語)
http://www.geocities.jp/gimproject/gimp2.0.html - GIMPの使い方(日本語)

Re: 初心者質問場

Posted: 2011年7月01日(金) 19:46
by てんむすキツネ
毎回ありがとうございます!なんとお礼を言ったらいいか・・・^^
さっそくDLしてみますね!

Posted: 2016年6月26日(日) 08:41
by らっせる
DXライブラリを使い始めた者なのですが、てんむすキツネさんとは違う要因(多分..)でプロジェクトがうまく実行されません

1>------ ビルド開始: プロジェクト:GameProg, 構成:Debug Win32 ------
1>test.obj : warning LNK4075: /EDITANDCONTINUE は /SAFESEH の指定によって無視されます。
1>DxUseCLib_d.lib(DxUseCLib.obj) : error LNK2026: モジュールは SAFESEH[hr] イメージには安全ではありません。

以下この"イメージには安全ではありません"の文字がエラーのなかにいっぱい表示されます。
どなたか解説お願いします。

Re: 初心者質問場

Posted: 2016年6月26日(日) 13:22
by らっせる
申し訳ないです。
構成プロパティをいじっていたらできました。

Re: 初心者質問場

Posted: 2017年5月11日(木) 11:25
by surach
DXライブラリを勉強して始めて作りました!いろんなサイトを参考にしてタイトル画面とプレイ画面を切り替えるだけのゲームなんですがどうでしょうか?うまく行ってたらここから何かのゲームを作っていく予定です。

コード:

//ゲームタイトル
#include "DxLib.h"

int Key[256]; // キーが押されているフレーム数を格納する
//Process関数 裏画面を表画面に反映, メッセージ処理, 画面クリア,キー更新の順番で行う
int Process() {
	if (ScreenFlip() != 0)return -1;
	if (ProcessMessage() != 0)return -1;
	if (ClearDrawScreen() != 0)return -1;

	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 white = GetColor( 255 , 255 , 255 ) ; //白色を取得

// メニュー項目の表示に必要な構造体を用意する
typedef struct {
	int x, y;       // 座標格納用変数
	char name[128]; // 項目名格納用変数
} MenuElement_t;
// メニュー項目要素を5つ作る
MenuElement_t MenuElement[5] = {
	{ 80, 100, "レベル1" }, // タグの中身の順番で格納される。xに80が、yに100が、nameに"ゲームスタート"が
	{ 100, 150, "レベル2" },
	{ 100, 200, "ゲームオーバー" },
	{ 100, 250, "ゲームクリア" },
	{ 100, 300, "ゲーム終了" },
};
int SelectNum = 0; // 現在の選択番号


//現在のステータス
enum {TITLE,PLAY,OVER,CLEAR};
int status = TITLE;

//ステータスがゲームタイトル状態の時の関数
int title() {

	// 下キーが押された瞬間だけ処理する。現在の項目SelectNumも一つ下にずらす
	if (Key[KEY_INPUT_DOWN] == 1) SelectNum = (SelectNum + 1) % 5;

	// 上キーが押された瞬間だけ処理する。
	if (Key[KEY_INPUT_UP] == 1) SelectNum = (SelectNum + 4) % 5;

	//すべてのメニュー項目の座標を計算する。
	if (Key[KEY_INPUT_DOWN] == 1 || Key[KEY_INPUT_UP] == 1) { // 下キーか、上キーが押された瞬間
		for (int i = 0; i<5; i++) {              // メニュー項目数である5個ループ処理
			if (i == SelectNum) MenuElement[i].x = 80; // 今処理しているのが、選択番号と同じ要素なら座標を80にする

			else MenuElement[i].x = 100;// 選択番号以外なら座標を100にする
		}
	}

	//メニュー項目のどこでEnterが押されたかを確認して、ステータスの状態を変える。
	if (Key[KEY_INPUT_RETURN] == 1) {

		switch (SelectNum) {
		case 0:
			return PLAY;
			break;
		case 1:
			return PLAY;
			break;
		case 2:
			return OVER;
			break;
		case 3:
			return CLEAR;
			break;
		case 4:
			DxLib_End();
			break;
		}
	}


	//メニュー画面を描画する
	for (int i = 0; i<5; i++) {
		DrawFormatString(MenuElement[i].x, MenuElement[i].y, GetColor(255, 255, 255), MenuElement[i].name);
	}

	DrawString(0, 0, "決定はエンター", white);

	return TITLE;
}

//ステータスがプレイ状態の時の関数
int play() {
	DrawString(280, 230, "ゲームオーバーはX、タイトルはQ", white); //描画する

	if (Key[KEY_INPUT_X] == 1) return OVER; //Xが押されていたらステータスをゲームオーバーにする
	if (Key[KEY_INPUT_Q] == 1) return TITLE; //Qが押されていたらステータスをゲームオーバーにする

	return PLAY; //XとQが押されていなければ引き続きプレイ状態にする
}

//ステータスがゲームオーバー状態の時の関数
int over() {
	DrawString(280, 230, "GAME OVER タイトルに戻るにはEnter", white);

	if (Key[KEY_INPUT_RETURN] == 1) return TITLE;

	return OVER;
}

//ステータスがゲームクリア状態の時の関数
int clear() {
	DrawString(280, 230, "GAME CLEAR タイトルに戻るにはEnter", white);

	if (Key[KEY_INPUT_RETURN] == 1) return TITLE;

	return CLEAR;
}


int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) {
	ChangeWindowMode(TRUE), DxLib_Init(), SetDrawScreen(DX_SCREEN_BACK); //ウィンドウモード変更と初期化と裏画面設定

	// while(裏画面を表画面に反映, メッセージ処理, 画面クリア, キー更新)
	while (Process() == 0) {

		//現在のステータス画面の状態にする
		switch (status) {
		case TITLE:
			status = title();
			break;
		case PLAY:
			status = play();
			break;
		case OVER:
			status = over();
			break;
		case CLEAR:
			status = clear();
			break;
		
		}

	}

	DxLib_End(); // DXライブラリ終了処理
	return 0;
}

Re: 初心者質問場

Posted: 2017年5月11日(木) 14:36
by purin52002
よくできていると思います^^

言語はcですか?c++ですか??
cなら関数ポインタ、c++ならクラスを使うともっと汎用性が高くなるとおもいます。

Re: 初心者質問場

Posted: 2017年5月11日(木) 15:12
by surach
プリンさんありがとうございます^^

言語はcです~。関数ポインタやってみます!

Re: 初心者質問場

Posted: 2017年5月11日(木) 19:49
by surach
DXライブラリでマップを作りたいんですが、リプレイするときにマップがリセットするいい方法ってありますか?

Re: 初心者質問場

Posted: 2017年5月11日(木) 22:45
by purin52002
うーむ、、、日本語力が低いので何がしたいのかいまいちわかりません^^;
マップをリセットって何だろう、、?

Re: 初心者質問場

Posted: 2017年5月12日(金) 07:07
by surach
説明が下手ですいません。マップを二次元配列で作って使ってるんですが、プレイするときにマップの内容を書き変えててゲームオーバーしたりしたらタイトル画面に戻ってもう一度やるとマップが書き変えられた状態で始まるのです。このマップを初期状態にする方法ということです。

例:map[2][2]={1,0},{1,1};→play関数を呼び出す→マップの内容が書き変えられる→map[2][2]={0,0,}{0,1}→ゲームオーバー→タイトル画面→play関数→map[2][2]={1,0},{1,1};

例のようにしたいわけですが伝わってるでしょうか?

Re: 初心者質問場

Posted: 2017年5月12日(金) 08:50
by purin52002
なるほど、なんとなくわかりました^^
おそらくmapをグローバルかstaticな変数にしてるんだと思います。

コード:

int map[2][2]={1,0},{1,1};

void play()
{
    //map[2][2]={0,0,}{0,1}に変更
}

void main()
{
    play();//この時点でmap[2][2]={1,0},{1,1};
    play();//この時点でmap[2][2]={0,0},{0,1};
}
おそらくこういうことですよね?

対策を2つほど思いつきました。

まず1つはmapをローカル変数(play関数の中だけの変数)にすること。
こうするとplay関数が呼び出されるたびにmapが初期化されます。
問題として、play関数とmenu関数とで行き来したい場合もmapが保存されずに初期化されてしまいます。

コード:

void play()
{
    int map[2][2]={1,0},{1,1};

    //map[2][2]={0,0,}{0,1}に変更
}

void main()
{
    play();//この時点でmap[2][2]={1,0},{1,1};
    play();//この時点でmap[2][2]={1,0},{1,1};
}
もう一つは保存用のmapと変更用のmapを用意する方法です。(コレクターみたいな言い方ですねw)
rpgの戦闘などで一時的にステータスを上昇させることがあります。
その時に、元のステータスを変えてしまうと後で元に戻さないといけないので面倒です。
元のステータス+上昇した分のステータス変数を作れば、後処理が簡単そうですよね。

コード:

int original_map[2][2]={1,0},{1,1};
int using_map[2][2];

void play()
{
    //using_map[2][2]=original_map[2][2]に初期化

    //using_map[2][2]={0,0,}{0,1}に変更
}

void main()
{
    play();//この時点でusing_map[2][2]={1,0},{1,1};
    play();//この時点でusing_map[2][2]={1,0},{1,1};
}
他にもいい方法があるかもしれませんが、私が思いついたのはこれくらいです^^;
オフトピック
私がc言語を使っていた時はグローバル変数大好きでしたが、c++を使うようになってからグローバル変数が嫌いになりました。

どこからでも変数にアクセスできるということは気づかない不具合の原因になりやすいからです。

昔はそれで苦労しました^^;

Re: 初心者質問場

Posted: 2017年5月12日(金) 10:12
by surach
プリンさんどうもありがとうございます!試してみますね!

Re: 初心者質問場

Posted: 2017年5月12日(金) 13:26
by surach
プリンさんありがとうございます!すごく不細工なコードになりましたが一応できました!笑

Re: 初心者質問場

Posted: 2017年5月12日(金) 19:12
by purin52002
よかったです^^

自分のコードを不細工と思えるのは素晴らしいことです。
きれいだと思えるコードが書けるようお互い頑張りましょうw

Re: 初心者質問場

Posted: 2017年5月13日(土) 10:16
by surach
読み返してて気づいたんですが、関数ポインタとは関数を作るときにポインタを使うことじゃなくて関数ポインタというのがあるんですね!
勘違いしてました笑

Re: 初心者質問場

Posted: 2017年5月13日(土) 15:25
by surach
(-ω-;)ウーン
関数ポインタを勉強してタイトル画面ゲームのプログラムを見直して、いろいろ考えて試行錯誤したんですが使う場所がわかりません。

Re: 初心者質問場

Posted: 2017年5月13日(土) 23:41
by purin52002
main文のswitch文を関数ポインタで置き換えると多少管理が楽になるかもしれません。

コード:

int title();
int play();
int over();
int clear();

enum {TITLE,PLAY,OVER,CLEAR};
int status = TITLE;

typedef int (* SCENE)() ;

int main()
{
    const SCENE scene[] = {title, play, over, clear } ;
    while(1)
    {
        status = scene[status]();
    }

}

このように、switch文を関数ポインタの配列で代用できます。
こうするとあとでシーン関係の関数が増えたときに、case~:のように書かなくても、
配列sceneの中に代入するだけでいいのでちょっとだけ楽になるかもしれません。

Re: 初心者質問場

Posted: 2017年5月14日(日) 10:08
by surach
私もこの部分考えたんですけど、statusが文字列なのでint型ではできないのでできないと思ってました!
なるほどこのようにするんですね参考になりました!(人''▽`)ありがとう

Re: 初心者質問場

Posted: 2017年5月14日(日) 20:43
by surach
何とかパックマンゲーム完成しました!!プリンさん本当にありがとうございます!
次は3×3将棋に挑戦したいと思います!!

Re: 初心者質問場

Posted: 2017年5月15日(月) 00:40
by purin52002
おめでとうございます^^
しかしパックマンとはなかなか懐かしいですねw

将棋も頑張ってください^^

Re: 初心者質問場

Posted: 2017年5月15日(月) 20:37
by surach
パックマンみたいにサンプルが多いと検索しながら作るのは楽なんですが、何も参考がなくてゲームを作るのはすごく難しいですね・・・

Re: 初心者質問場

Posted: 2017年5月19日(金) 22:31
by surach
質問です。
パックマンの口を周期的に開けたり閉じたりしたいです。
自分の方法
・口を閉じてる画像と空いてる画像を用意して、ループごとに描画する画像を変化させる

例)

コード:

int px = 32, py = 32; //自機の座標
int player[2];
int pa; //プレイヤーの向き

LoadDivGraph("player2.png", 2, 2, 1, 32, 32, player); //配列playerに保管

while (1) {

	pa = 1 - pa; //ループごとに0と1に代わる。
	DrawGraph(px, py, player[pa], FALSE);
}
自分のアイディアを簡単に上記の例のようにしましたが、問題が口を開けたり閉じたるする速度が速すぎました。
何かいい方法はありますか?
(waitkey();はなるべく使用したくはないです)

Re: 初心者質問場

Posted: 2017年5月19日(金) 23:50
by surach

コード:

// ループ外
int bunsyu = 0;

// ループ内
bunsyu++;
if (bunsyu >= 5) { // 数字を大きくすると間隔が大きくなる
    pa = 1 - pa;
    bunsyu = 0;
}
上記のようにするとうまく行きました!自己解決してすいません!

Re: 初心者質問場

Posted: 2017年5月20日(土) 09:57
by みけCAT
surach さんが書きました:

コード:

// ループ外
int bunsyu = 0;

// ループ内
bunsyu++;
if (bunsyu >= 5) { // 数字を大きくすると間隔が大きくなる
    pa = 1 - pa;
    bunsyu = 0;
}
上記のようにするとうまく行きました!自己解決してすいません!
このコードは私がチャットで教えたものです。
丸パクリして自己解決したことにするのは剽窃だと思います。
やめてください。

Re: 初心者質問場

Posted: 2017年6月06日(火) 08:13
by surach
みけCATさん大変失礼しました。
問題解決したことを掲示板に言っておかないといけないと思ってそういう風に書いたんですが、みけCATさんに教えてもらって解決しましたという書き方のほうがよかったですねすみません(*- -)(*_ _)ペコリ