質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

DXライブラリ

DXライブラリとは、DirectXを使ったWindowsソフトの開発に必ず付いて回るDirectXやWindows関連のプログラムを使い易くまとめた形で利用できるようにしたC++言語用のゲームライブラリです。

Q&A

解決済

4回答

686閲覧

プログラムの流れと説明

carnage0216

総合スコア194

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

DXライブラリ

DXライブラリとは、DirectXを使ったWindowsソフトの開発に必ず付いて回るDirectXやWindows関連のプログラムを使い易くまとめた形で利用できるようにしたC++言語用のゲームライブラリです。

0グッド

0クリップ

投稿2019/08/10 16:53

編集2019/08/10 17:19

以下はコード全体です。

#include "DxLib.h" // コマの横/縦数 #define FRAME_WIDTH 5 #define FRAME_HEIGHT 5 // コマの描画幅/高さ #define CELL_WIDTH 49 #define CELL_HEIGHT 66 // 描画マージン #define FIELD_MARGIN_X 50 #define FIELD_MARGIN_Y 50 typedef struct Player_t { int x; int y; int handle; } Player; // コマ(x,y)に外枠を描く[おまけ] int box_draw(int x, int y) { return DrawBox(x * CELL_WIDTH + FIELD_MARGIN_X, y * CELL_HEIGHT + FIELD_MARGIN_Y, (x + 1) * CELL_WIDTH + FIELD_MARGIN_X, (y + 1) * CELL_HEIGHT + FIELD_MARGIN_Y, GetColor(255, 255, 255), FALSE); } // コマ(x,y)に画像を描く int cell_draw(int x, int y, int handle) { return DrawGraph(x * CELL_WIDTH + FIELD_MARGIN_X, y * CELL_HEIGHT + FIELD_MARGIN_Y, handle, FALSE); } int Key[256]; // キーが押されているフレーム数を格納する // キーの入力状態を更新する 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; } void Player_update(Player* p) { int dx = 0; int dy = 0; if (Key[KEY_INPUT_RIGHT] == 1) { dx = dx + 1; p->handle = 2; } if (Key[KEY_INPUT_LEFT] == 1) { dx = dx - 1; p->handle = 1; } if (Key[KEY_INPUT_UP] == 1) { dy = dy - 1; p->handle = 5; } if (Key[KEY_INPUT_DOWN] == 1) { dy = dy + 1; p->handle = 11; } if (dx == 0 && dy == 0) { p->handle = 8; } /* 新たな位置へ移動可能であるならplayerの位置を更新する */ int newX = p->x + dx; int newY = p->y + dy; if (0 <= newX && newX < FRAME_WIDTH && 0 <= newY && newY < FRAME_HEIGHT) { p->x = newX; p->y = newY; } else { p->handle = 8; // 動けないなら正面を向く } } void Player_draw(const Player* p, const int* gh) { cell_draw(p->x, p->y, gh[p->handle]); } int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) { SetGraphMode(1300, 680, 32); // ウィンドウの大きさを指定 ChangeWindowMode(TRUE); if (DxLib_Init() == -1) { return -1; } //グラフィックハンドル格納用配列 int gh[12]; LoadDivGraph("charall.png", 12, 3, 4, 49, 66, gh); Player player; player.x = FRAME_WIDTH / 2; player.y = FRAME_HEIGHT / 2; SetDrawScreen(DX_SCREEN_BACK); while (ProcessMessage() == 0) { gpUpdateKey(); Player_update(&player); // ここから表現 ClearDrawScreen(); for (int x = 0; x < FRAME_WIDTH; ++x) for (int y = 0; y < FRAME_HEIGHT; ++y) box_draw(x, y); Player_draw(&player, gh); ScreenFlip(); } DxLib_End(); return 0; }

各プログラムを解読したいと思い質問します。
1、

void Player_update(Player* p) { int dx = 0; int dy = 0; }

関数void Player_updateが引数に関数Player* pを持ってきて、int型の変数dxの値0とint型の変数dyの値0に引数である関数Player* pを渡すと思いますが、この関数Player* p自体が何を持った関数かなのかわからないのですが、なんでしょうか?①

2、

nt Key[256]; // キーが押されているフレーム数を格納する // キーの入力状態を更新する 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; }

関数gpUpdateKey()はchar tmpKey[256]// 現在のキーの入力状態を格納して、さらにtmpKey[256]によりメモリに収納した256のキーが関数GetHitKeyStateAllによりメモリにある収納した256のキーをキーボードで押すことで呼び出せるようになった。
これにより全てのキーの入力状態を得るのですが、そのあとに続くfor (int i = 0; i < 256; i++) は何のためにあるのでしょうか。
また、

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

tmpKeyは入力状態になりましたが、tmpKeyは「GetHitKeyStateAll(tmpKey); // 全てのキーの入力状態を得る」より、いつ256のキーを押されても反応できる状態である。そしてif (tmpKey[i])より押される準備をした256のキー中ののi番目(GetHitKeyStateAll(tmpKey);より押される準備をしている256のキーの何が押されても大丈夫なことを「if (tmpKey[i] != 0)② { // i番のキーコードに対応するキーが押されていたら」表します。ですが、そのあとの「Key[i]++; // 加算」は何を言っているのでしょうか?キーボードでi番のキーコードに対応するキーが押されていた後で、Key[i]++; // 加算」を行いう理由がわかりません。③

其のあとの

else { // 押されていなければ Key[i] = 0; // 0にする }

iに対応するキーを押さなかったら、0とありますが、押さないならば、何も起きないのでこの部分を書く必要があるのか疑問です④

} return 0; }

最後は異常が無ければ0が来る。

長くなりました。
以上のプログラムで疑問に起こったに関する答えがほしいです。もう一つはプログラムの流れが合っているかを確認して頂きたいです。
どうかよろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

gentaro

2019/08/10 17:03

前回に続いて意味がわかりません。文章を推敲しましょう。 ・「書くプログラム」とは「各プログラム」でしょうか ・「4バイトを占める」とはどういう意味でしょうか ・「渡しますと思います」という日本語はありません ・「この関数Player* p自体が何を持った関数かなのかわからない」と言われでもこのコード断片だけ見せられた側にもわかりません この調子でやってたら全文全箇所おかしいところだらけな気がするのでここで切り上げますが。
gentaro

2019/08/10 17:46

「推敲しましょう」と促しても「疑問に起こったに」という記述が残ってたり。 厳しいことを言うようですが、全ての誤りを指摘してもらえないと修正できない人は、プログラマに向いてないです。 だんだん「触れてはいけない人」のような気がしてきた。
Zuishin

2019/08/10 23:32

プログラマに向いてはないですよ。それと、彼が文章をいくら推敲しようとこれ以上にはなりません。推敲をさぼっているわけではなく、これが限界なんです。怠惰ではないと思います。 だから細かいところはこちらで想像し、大事なところは確認を取り、返ってくる意味不明な返答にまたその手続きを取るという面倒な作業が必要ですね。
fana

2019/08/11 02:06

以前は少なくとも日本語面は普通だったような…?
carnage0216

2019/08/11 02:22

皆さま、本当にごめんなさい。 皆さんの貴重なお時間を無駄にしてしまい。 僕が嫌でしたらブロックして頂いて構いませんし、通報してください。 悪いのは答えられないような意味不明な質問をした私なので。 本当にすいませんでした。
gentaro

2019/08/11 02:36

糾弾したいとか嫌いになるとか謝罪がほしいとか、そういうレベルの話ではなく、ただただ「投稿」ボタンを押す前にもうちょっと慎重に文章を見直して欲しいだけですよ。 基本的には自分に理解できる内容なら回答をしよう、というスタンスで読んでますんで、そうお願いしてるだけです。 それを無視するかのように同じ失敗を繰り返されるんだとしたら、そのうち勝手にスルーしますんで。
fana

2019/08/11 02:40

ある物事の理解度が低い場合にその物事に関して論じようとすると内容が支離滅裂気味になることに関しては,ある程度仕方ないと思うのですが… 内容がどうこう以前に日本語の側に問題が生じていると情報伝達が困難です. せっかく質問してもその質問内容が読み手に伝わらなければ意味がないですから,もう少し「伝える」ことを意識して文章を書かれると良いのではないかと思います.
carnage0216

2019/08/11 02:44

gentaroさん、fanaさん、私に重要なアドバイスありがとうございます。 もう一度基礎を固めながら、質問の仕方も勉強します。 どうかその時はお願いいたします。もちろん問題があれば遠慮なく言って下さい。 ありがとうございました。
guest

回答4

0

ベストアンサー

[1]

関数void Player_updateが引数に関数Player* pを持ってきて、int型の変数dxの値0とint型の変数dyの値0に引数である関数Player* pを渡すと思いますが、この関数Player* p自体が何を持った関数かなのかわからないのですが、なんでしょうか?

Playerは関数ではない。

C

1typedef struct Player_t { 2 int x; 3 int y; 4 int handle; 5} Player;

だから、Player は 構造体 struct Player_t の別名だ。

[2]

int Key[256]; // キーが押されているフレーム数を格納する

コメントのとおり、Key[n] にはnで指定されたキーが押され続けている間インクリメント、離されていたら0がセットされる。そうなるように gpUpdateKey() が実装されている。

Player_update() では

if (Key[KEY_INPUT_RIGHT] == 1) { ... }

とある。これは押された瞬間にのみ条件を満たす(押され続けていたら2,3,4...なので)。
これによりキーが押され続けているときキャラクタが右に移動し続けるのを抑止している。
( Key[KEY_INPUT_RIGHT] > 0 or Key[KEY_INPUT_RIGHT] != 0 ならキャラクタが右に流れるだろう )

投稿2019/08/10 23:31

編集2019/08/11 00:46
episteme

総合スコア16614

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

carnage0216

2019/08/11 01:52 編集

いつもいつもありがとうございます。裏切ってばかりで正しい理解でもないのに使って、しれすら判断できなくてすいません。
guest

0

C

1typedef struct Player_t { 2 int x; 3 int y; 4 int handle; 5} Player;

これは次の宣言を一つにしたものです。

C

1struct Player_t { 2 int x; 3 int y; 4 int handle; 5}; 6 7typedef struct Player_t Player;

Player_t は構造体のタグ名です。構造体名ではありません。
構造体型の変数 player を宣言するときは、常に、
strcut Player_t player; と書かなければなりません。
そこで、typedef を使って、struct Player_t に
Player という名前を付けています。
これで WindMain では、Player player; という宣言で、
構造体 Player の変数 player を実体化しています。

C

1void Player_update(Player* p) { 2 ... 3 int newX = p->x + dx; 4 int newY = p->y + dy; 5 if (0 <= newX && newX < FRAME_WIDTH && 0 <= newY && newY < FRAME_HEIGHT) { 6 p->x = newX; 7 p->y = newY; 8 } 9 else { 10 p->handle = 8; // 動けないなら正面を向く 11 } 12}

関数 Player_update は、WinMain から、
Player_update(&player) で呼び出しています。
WinMain の変数 player のアドレスを渡しています。
呼び出された関数 Player_update の引数 p がそのアドレスを受け取ります。
p は「構造体Player へのポインタ」ですから、これを使って、
WinMain の player にアクセスでき、値を参照したり、変更したりできます。
int newX = p->x + dx; で player.x の値を参照しています。
p->x = newX; で player.x の値を更新しています。

DxLib を使うプログラムは、C でなく、C++ のはずです。
C と違って、C++ では構造体のタグ名が構造体名として使えるので、
実は typedef は要らなかったのです。次のように書くだけでよいのです。

C

1struct Player { 2 int x; 3 int y; 4 int handle; 5};

とにかく、宣言された名前が関数名なのか、変数名なのか、型名なのかを
ちゃんと理解してください。名前は、大文字と小文字の区別があります。
Player と player は異なる名前です。

質問を編集して、正しい用語での質問を追記してもらえませんか?

投稿2019/08/11 10:51

編集2019/08/11 10:53
kazuma-s

総合スコア8224

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

関数void Player_updateが引数に関数Player* pを持ってきて、int型の変数dxの値0とint型の変数dyの値0に引数である関数Player* pを渡すと思いますが、この関数Player* p自体が何を持った関数かなのかわからないのですが、なんでしょうか?①

Player* pは関数ではなく仮引数です。

c++

1typedef struct Player_t { 2 int x; 3 int y; 4 int handle; 5} Player;

によって型定義されたPlayerへのポインタです。

関数gpUpdateKey()について

c++

1int Key[256]; // キーが押されているフレーム数を格納する 2 3// キーの入力状態を更新する 4int gpUpdateKey() {

正直、このコメント読むだけで終わる話だと思うのですが

リファレンスによるとGetHitKeyStateAll
キーボードの状態を
押されている: 1
押されていない: 0
で表現した配列を返します。

それを、
押されている: 押しっぱなしのままの経過フレーム数
押されていない: 0
の配列に変換し、Keyに格納しています。

投稿2019/08/10 23:54

asm

総合スコア15147

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

carnage0216

2019/08/11 01:52

お久しぶりです。ありがとうございます。
carnage0216

2019/08/11 05:27 編集

あの、void Player_update(Player* p) { int dx = 0; int dy = 0; }に関して、関数playerが引数になっていますが、この構造体である関数player_tの型はplayerですよね? しかし、型playerは引数にできないです。 上のプログラムの引数playerは変数だと思うのですが、どこで変数playerを定義しているのでしょうか?
carnage0216

2019/08/11 05:36

もう一つ、 Player* pは関数ではなく仮引数です。との事ですが、 構造体typedef struct Player_t { int x; int y; int handle; } Player; のplayerは型です。かつポインタの記述はないですが。 なぜ
carnage0216

2019/08/11 05:39

もう一つ、構造体typedef struct Player_t { int x; int y; int handle; } Player;は型はplayerで、ポインタの記事はないですが、 なぜPlayer* pとできたのでしょうか?型playerにポインタでしてされた箱があると思いますが、 型playerにポインタの表す箱をかける意味がわからないです。
carnage0216

2019/08/11 05:57

調べて思い出したのですが、確か、構造体typedef structで型と変数が同じ名前ならば一回playerと}の後に書けば良いのでしたっけ? ただ、ポインタpがどこにあり、何のために変数playerに掛けらいるのか、引数として利用されたのかわかりません。
asm

2019/08/11 06:23

定義を兼ねた関数宣言部なので 変数は一切関係ありません
carnage0216

2019/08/11 15:45

毎度毎度ありがとうございます。
guest

0

*Player p**は構造体のポインタじゃないのですか?
これだけの情報ではだれも回答できないと思います。

gpUpdateKey()関数に関してですが、

そのあとに続くfor (int i = 0; i < 256; i++)

tmpKey配列に入った256個キーの状態を調べるためのループですね。
if (tmpKey[i] != 0)の条件がTRUEになった場合、キーが押されていると判断します。
FALSEの場合はキーが押されていない(押されていたキーが離された場合も含む)と判断します。

Key[i]++; // 加算」を行いう理由がわかりません

加算している理由ですが、Key配列がキーが押されているフレーム数を記録する仕様となっているからでしょうね。

iに対応するキーを押さなかったら、0とありますが、押さないならば、何も起きないのでこの部分を書く必要があるのか

上述した通り、キーを離したことを認識するためFALSEの場合に、key=0としてあるのでしょう。

投稿2019/08/10 17:33

TaroToyotomi

総合スコア1430

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

carnage0216

2019/08/11 05:07 編集

ありがとうございます。 あの、char tmpKey[256]; // 現在のキーの入力状態を格納する より256のキーを収納したのに、なぜforを使うのでしょうか?
episteme

2019/08/11 06:56

tmpKey[256] を基に Key[256] の各要素の値を「ひとつづつ」決定するための for-loop。
fana

2019/08/11 08:06

>キーを収納した こういう言葉の使い方から直していったほうが良いと思う. 配列tmpKeyに格納されたのは,「キー」ではなく,その時点における「キーの押下状態」ですよね.
episteme

2019/08/11 08:12

だね。表現は正確に(できるだけ厳密に)
carnage0216

2019/08/11 15:49

お二方ありがとうございます。 なるほど、理由はわかりませんが押下状態のキーはひとつづつしか格納できないため、今回のように書いたのですね。
TaroToyotomi

2019/08/11 17:57

>理由はわかりませんが押下状態のキーはひとつづつしか格納できないため、今回のように書いたのですね。 理解できてなさそうです。
carnage0216

2019/08/12 09:28

分け合って理解できました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問