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

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

解決済

3回答

3755閲覧

画像のように3D っぽい2Dの9マスA~I上をキャラにキー入力で移動させたい

carnage0216

総合スコア194

C

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

C++

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

DXライブラリ

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

1グッド

0クリップ

投稿2019/08/22 15:01

編集2019/08/24 07:19

行いたいこと
画像のように3D っぽい2Dの9マスA~I上をキャラにキー入力で移動させたいのですが、
今の(自分と何人かの方の協力で出来た)コードから展開するにはどうすればいいでしょうか。
どうすればできるか
個人的には、3D っぽくなるように座標を前もって指定して、その上だけを動くように
すればいいと考えました。ですが、どのサイトを見てもそのようなやり方が出来そうな方法が書いておらず、出来るとしても行う方法がわからずに止まっています。

座標Eに関しては真ん中をEとして表せていると思います。
あとの残りは斜線っぽい感じの座標で、座標を指定して、そこにキャラが移動する形になると考えています。
キャラの移動する9マスです

イメージとして以下のようにドットキャラを置きます。

以下は全体のコードです。初期値として座標nx,ny=(2,2)は中心Eを表しています。

#include "DxLib.h" 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; } // プログラムは WinMain から始まります int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { SetGraphMode(1600, 680, 32); // ウィンドウの大きさを指定 ChangeWindowMode(TRUE); if (DxLib_Init() == -1) // DXライブラリ初期化処理 { return -1; // エラーが起きたら直ちに終了 } //1. 3x3マスの2次元配列 int idou[5][5] = { {1,1,1,1,1 }, {1,0,0,0,1 }, {1,0,0,0,1 }, {1,0,0,0,1 }, {1,1,1,1,1 }, }; //グラフィックハンドル格納用配列 int gh[12]; LoadDivGraph("charall.png", 12, 3, 4, 49, 66, gh);//画像読み込み int nx = 2, ny = 2; // 最初のキャラのX座をdxとY座標をdyである。配列の真ん中の0を最初の座標としたため(2,2)となる SetDrawScreen(DX_SCREEN_BACK); while (ProcessMessage() == 0 && gpUpdateKey() == 0) { int playerphoto = gh[5];//ループに入れてしまうと移動した際もずっとそこにあるんでダメ。(2,2)から存在して、ずっとあるようにするためループ内に書いた。 //DrawGraph(50 * nx, 50 * ny, playerphoto, FALSE);//一瞬ではなくずっとあるようにするためにループに書いた。 // カーソルキーの右が押されている if (Key[KEY_INPUT_RIGHT] == 1) if (idou[ny + 0][nx + 1] == 0) { //移動しようとする先が空いていれば //移動可能 nx = nx + 1; //移動 playerphoto = gh[6]; } if (Key[KEY_INPUT_LEFT] == 1) if (idou[ny + 0][nx - 1] == 0) { //移動しようとする先が空いていれば //移動可能 nx = nx - 1; //移動 playerphoto = gh[4]; } if (Key[KEY_INPUT_UP] == 1) if (idou[ny - 1][nx + 0] == 0) { //移動しようとする先が空いていれば //移動可能 ny = ny - 1; //移動 playerphoto = gh[2]; } if (Key[KEY_INPUT_DOWN] == 1) if (idou[ny + 1][nx + 0] == 0) { //移動しようとする先が空いていれば //移動可能 ny = ny + 1; //移動 playerphoto = gh[8]; } //ScreenFlip(); // 画面をクリア ClearDrawScreen(); DrawGraph(50 * nx, 50 * ny, playerphoto, FALSE); ScreenFlip(); } DxLib_End(); // DXライブラリ使用の終了処理 return 0; // ソフトの終了 }

マルチポストをしていた質問です。
https://dixq.net/forum/viewtopic.php?p=154122#p154122

いろんな考えが見たかった故にマルチポストしました。
どうもすいませんでした、。

マルチポストをして、
得た回答でこちらのプログラムを回答にさせていただきました。
以下のコードを使い行いたいことを実行しました

#include "DxLib.h" int Key[256]; int gpUpdateKey() { char tmpKey[256]; GetHitKeyStateAll(tmpKey); for (int i = 0; i < 256; i++) (tmpKey[i] == 0) ? (Key[i] = 0) : Key[i]++; return 0; } int idou[5][5] = { { 1, 1, 1, 1, 1 }, { 1, 0, 0, 0, 1 }, { 1, 0, 0, 0, 1 }, { 1, 0, 0, 0, 1 }, { 1, 1, 1, 1, 1 }, }; int box[4][7][2], player[5][5][2]; void init_box() { for (int j = 0; j < 7; j++) { int w = (j - 3) * 100, h = 600; for (int i = 4; --i >= 0; ) { box[i][j][0] = w + 400, box[i][j][1] = h - 200; w = w * 9 / 10, h = h * 9 / 10; } } for (int i = 1; i <= 3; i++) for (int j = 1; j <= 3; j++) { player[i][j][0] = (box[i-1][j-1][0] + box[i][j][0])/2 - 25; player[i][j][1] = (box[i-1][j-1][1] + box[i][j][1])/2 - 66; } } int WINAPI WinMain(HINSTANCE hi, HINSTANCE hp, LPSTR cl, int cs) { SetGraphMode(1200, 680, 32); // ウィンドウの大きさを指定 ChangeWindowMode(TRUE); // 全画面ではなくウインドウを使用 if (DxLib_Init() == -1) return -1; // DXライブラリ初期化処理 SetDrawScreen(DX_SCREEN_BACK); // 裏画面を使用する設定 init_box(); int boxColor = GetColor(160, 64, 64); int nx = 2, ny = 2; // プレイヤーの初期位置 int px = player[ny][nx][0], py = player[ny][nx][1]; // 表示位置 int keep = 0; // 移動不可能状態継続カウンタ int gh[12]; //グラフィックハンドル格納用配列 // 5:正面、7:右向き、2:左向き、4:上向き、3:下向き、9:移動不可 LoadDivGraph("charall.png", 12, 3, 4, 49, 66, gh); //画像読み込み int playerphoto = gh[5]; while (ProcessMessage() == 0) { gpUpdateKey(); // キーの入力状態を取得 if (Key[KEY_INPUT_RIGHT] == 1) { // 右キーが押されている if (idou[nx + 1][ny] == 0) { // 移動先が空いていれば nx++; playerphoto = gh[7]; // 右向き } else { keep = 1; playerphoto = gh[9]; // 移動不可能 } } if (Key[KEY_INPUT_LEFT] == 1) { if (idou[nx - 1][ny] == 0) { // 移動先が空いていれば nx--; playerphoto = gh[2]; // 左向き } else { keep = 1; playerphoto = gh[9]; // 移動不可能 } } if (Key[KEY_INPUT_UP] == 1) { if (idou[nx][ny - 1] == 0) { // 移動先が空いていれば ny--; playerphoto = gh[4]; // 上向き } else { keep = 1; playerphoto = gh[9]; // 移動不可能 } } if (Key[KEY_INPUT_DOWN] == 1) { if (idou[nx][ny + 1] == 0) { // 移動先が空いていれば ny++; playerphoto = gh[3]; // 下向き } else { keep = 1; playerphoto = gh[9]; // 移動不可能 } } ClearDrawScreen(); // 裏画面をクリア for (int i = 0; i < 4; i++) DrawLine(box[i][0][0], box[i][0][1], box[i][6][0], box[i][6][1], boxColor); for (int j = 0; j < 7; j++) DrawLine(box[0][j][0], box[0][j][1], box[3][j][0], box[3][j][1], boxColor); int x = player[ny][nx][0], y = player[ny][nx][1]; // 表示位置に変換 if (x == px && y == py) { if (keep == 0 || ++keep == 10) { keep = 0; playerphoto = gh[5]; } } else { if (abs(x - px) < 8) px = x; else if (x > px) px += 8; else if (x < px) px -= 8; if (abs(y - py) < 6) py = y; else if (y > py) py += 6; else if (y < py) py -= 6; } DrawGraph(px, py, playerphoto, FALSE); // プレイヤーを裏画面に描画 ScreenFlip(); // 裏画面を表画面に反映 } DxLib_End(); // DXライブラリ使用の終了処理 return 0; // ソフトの終了 }
bochan2👍を押しています

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

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

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

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

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

can110

2019/08/24 05:10

https://teratail.com/help#posted-otherservice やむを得ず複数のサイトに質問を投稿された場合は、質問内容にマルチポストをする理由を書き、他のサイトの投稿へのリンクを貼ってください。また、解決した際には必ずteratail及びすべての投稿に解決した旨と、どのように解決したかを記載してください。
can110

2019/08/24 05:49

「どのように解決したか」も記載してください。
carnage0216

2019/08/24 05:50

えと、回答者カズマ様のおかげ解決したという回答を両方に書けばよいでしょうか。
can110

2019/08/24 05:52

「行いたいこと」が実現できたコードを記載ください。
carnage0216

2019/08/24 05:53

あの、それはベストアンサーに書いてあり、選ばせて頂いたのですが、それではダメなのですか?
can110

2019/08/24 06:00 編集

回答者カズマ様とは誰でしょうか? また、どのベストアンサーに「コード」が記載しているのか私には分かりませんのでダメではないでしょうか? 「行いたいこと」が実現できた「コード」を記載ください。
can110

2019/08/24 06:04

コードはコードブロック```で囲んでください。 提示コードは質問者の環境で動作ができたか確認したでしょうか? また、「行いたいこと」が実現できたでしょうか?
carnage0216

2019/08/24 06:06

すいません。スマホで、少し扱いにくく、 私の誤りがあり、ベストアンサーはfana様ですが、 行いたい事が出来たのはkazuma-sさんのコードです。
can110

2019/08/24 06:11

なお「解決した際には必ずteratail及びすべての投稿に解決した旨と、どのように解決したかを記載してください。」 すなわちteratail以外のマルチポスト先にもどのように解決したかを記載しましたか? していなければ記載ください。
fana

2019/08/24 06:18

以前ベストアンサーを付け替えてるのを見た記憶があるので,変えれるんじゃないでしょうか. 必要なら変えても構いませんよ.(私はベストアンサーとか+評価とかに特にこだわりませんで)
carnage0216

2019/08/24 06:24

いえ、最初にfanaさんが考案された考えが私は気に入り、 それをコードにしてくださったkazuma-sなので、出来ればお二方をベストアンサーにしたいですが、それが出来ないため、fanaさんをベストアンサーに、コードをkazuma-sさんから頂きました。 私ごとでご迷惑をおかけしてすいません。
carnage0216

2019/08/24 06:26

can110さん、ありがとうございます。 わかりました。 もう一つの方にも使うコードを貼ります。
fana

2019/08/24 06:30

(第三者が自治行為に出ちゃうと,何というか,自分が発端でそういう流れ呼び寄せちゃった感じ?で申し訳ない気分.(アイコンがとてもこわい!))
carnage0216

2019/08/24 06:33

一番は自分の責任です。 fanaさん、ご迷惑をかけてしまいすいません。
carnage0216

2019/08/24 07:22

can110さん確認お願いいたします。
guest

回答3

0

ベストアンサー

【キャラクタがAのマスにいるとき→描画すべき場所(pixel座標)はどこか?】
という方向だけを解決すれば良いのであれば,各マスのpixel座標をテーブルで持ってしまうのが実装としては簡単でしょう.
(テーブルのデータをいい感じに用意する苦労はある)

【描画世界でのpixel座標(px,py)っていうのは → どのマスに入っているのか?】
みたいな方向の処理も必要になるとか,
前述の「テーブルデータの用意」を自動で計算させたいとかいう場合には,

  1. A~Iのマスが定義されている盤上の座標系:Aのマスが(0,0)で,Iのマスが(2,2)みたいな座標系
  2. 描画するpixel座標系

の2つの座標系の間の座標変換を計算で行う関数を実装するのが良いでしょう.
(「射影変換(Homography)」とかで検索すれば数式とか変換行列の求め方とかが見つかるでしょう)


ある程度計算な簡単な方法としては…
盤の横線の端点(下図の赤線で囲った範囲内の●)のpixel座標群をデータとして持つ,とかでしょうか.
図内灰色●群の座標は,横線を等間隔に分割する位置として容易に算出できますから,
各マスの四隅のpixel座標が簡単に手に入ります.
イメージ説明

投稿2019/08/23 01:20

編集2019/08/23 01:31
fana

総合スコア11654

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

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

fana

2019/08/23 04:59

(もうちょと傾けたいだとかサイズ感がどうのとか)表示具合の微調整がしたくなる場面もあるのかな?と思うので, 最終的にテーブルデータを持つタイプの実装方法を採る場合であっても,その値は手作業(って言うのか)でいちいち決めるのではなくて自動で求めるような手段を用意すると良いように思う. (例えば3次元表示できるライブラリに盤を描画させた結果画像に基づいてテーブルデータを得るとか)
fana

2019/08/23 05:33

(回答依頼とかいうのが飛んできたらから対応してみたんだけども, マルチポストで別のところで話が進んでこっちが放置されてる側っぽいのを後から見つけると何とも言えない気分になるね)
carnage0216

2019/08/23 11:15

遅くなり本当にすいません。本当にすいませんでした。二度としません。 信じて頂けないと思いますが、ほったらかしにしていたわけではありません。体調がすぐれず寝ていました。 ですが、マルチポストをしていたことに変わりはありません。どうか低評価を付けたり、通報して頂いて構いません。いつも回答して頂いているのにも関わらず、恩を仇で返しました。本当にすいませんでした。
fana

2019/08/24 01:19

マルチポストをまともにやるには類稀な能力が必要なので,お勧めしません. 圧倒的にマルチタスクに秀でた人間でもなければ, ある場所Aで話が進んでいる方法なりを試行している状態では,別の場所(B,C,...)に投下された方法について考えたり試したりすることには手が回らない.そこがマルチポストの問題点. 結果として話を投下した全ての箇所にまともな応答ができなくなる. (実際に今,ここに付いた回答の内容に関する話を一切できていないよね.) そうなると相手の心象を悪くする. ルール違反のマルチポストだとばれると(大抵ばれる)なおさら悪印象. →その結果として,協力者は減っていくかもしれない.
fana

2019/08/24 01:24

つまり, (1)ルール違反ではなくて (2)話を投下した全ての場所をまともにハンドリングできるなら マルチポストは広くアイデア等を募るための強力な方法になり得るだろう. このサイトはどうやら(1)側に引っかかるようなので,マルチポスト時には話の投下先に含めるべきではない.
can110

2019/08/24 05:35

以下、質問者へ。 https://teratail.com/help#posted-otherservice やむを得ず複数のサイトに質問を投稿された場合は、質問内容にマルチポストをする理由を書き、他のサイトの投稿へのリンクを貼ってください。また、解決した際には必ずteratail及びすべての投稿に解決した旨と、どのように解決したかを記載してください。 「すべての投稿に解決した旨と、どのように解決したかを記載」ください。
carnage0216

2019/08/24 06:00

今、pcが手元にないので、 帰宅次第、マルチポストとこちらの方で使ったコードを載せさせて頂きます。
guest

0

idou のような2次元配列を2つ作り, 1つはx座標, もう1つはy座標として初期値を設定しておき, それらから nx,ny で取り出して DrawGraph の座標指定に使用しては如何でしょう.
両方を合わせて3次元配列にしたり, 構造体(やクラス)の2次元配列でも良いかも知れません.

投稿2019/08/22 16:49

編集2019/08/22 16:56
jimbe

総合スコア12632

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

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

carnage0216

2019/08/22 16:52

なるほど、実際にやってみて考えてみます!(心配ですが。 いつもいつもありがとうございます!
guest

0

C++

1#include "DxLib.h" 2 3int Key[256]; 4 5int gpUpdateKey() 6{ 7 char tmpKey[256]; 8 GetHitKeyStateAll(tmpKey); 9 for (int i = 0; i < 256; i++) 10 (tmpKey[i] == 0) ? (Key[i] = 0) : Key[i]++; 11 return 0; 12} 13 14int idou[5][5] = { 15 { 1, 1, 1, 1, 1 }, 16 { 1, 0, 0, 0, 1 }, 17 { 1, 0, 0, 0, 1 }, 18 { 1, 0, 0, 0, 1 }, 19 { 1, 1, 1, 1, 1 }, 20}; 21 22int box[4][7][2], player[5][5][2]; 23 24void init_box() 25{ 26 for (int j = 0; j < 7; j++) { 27 int w = (j - 3) * 100, h = 600; 28 for (int i = 4; --i >= 0; ) { 29 box[i][j][0] = w + 400, box[i][j][1] = h - 200; 30 w = w * 9 / 10, h = h * 9 / 10; 31 } 32 } 33 for (int i = 1; i <= 3; i++) 34 for (int j = 1; j <= 3; j++) { 35 player[i][j][0] = (box[i-1][j-1][0] + box[i][j][0])/2 - 25; 36 player[i][j][1] = (box[i-1][j-1][1] + box[i][j][1])/2 - 66; 37 } 38} 39 40int WINAPI WinMain(HINSTANCE hi, HINSTANCE hp, LPSTR cl, int cs) 41{ 42 SetGraphMode(1200, 680, 32); // ウィンドウの大きさを指定 43 ChangeWindowMode(TRUE); // 全画面ではなくウインドウを使用 44 if (DxLib_Init() == -1) return -1; // DXライブラリ初期化処理 45 SetDrawScreen(DX_SCREEN_BACK); // 裏画面を使用する設定 46 47 init_box(); 48 int boxColor = GetColor(160, 64, 64); 49 50 int nx = 2, ny = 2; // プレイヤーの初期位置 51 int px = player[ny][nx][0], py = player[ny][nx][1]; // 表示位置 52 int keep = 0; // 移動不可能状態継続カウンタ 53 54 int gh[12]; //グラフィックハンドル格納用配列 55 // 5:正面、7:右向き、2:左向き、4:上向き、3:下向き、9:移動不可 56 LoadDivGraph("charall.png", 12, 3, 4, 49, 66, gh); //画像読み込み 57 int playerphoto = gh[5]; 58 59 while (ProcessMessage() == 0) { 60 gpUpdateKey(); // キーの入力状態を取得 61 if (Key[KEY_INPUT_RIGHT] == 1) { // 右キーが押されている 62 if (idou[nx + 1][ny] == 0) { // 移動先が空いていれば 63 nx++; playerphoto = gh[7]; // 右向き 64 } 65 else { 66 keep = 1; playerphoto = gh[9]; // 移動不可能 67 } 68 } 69 if (Key[KEY_INPUT_LEFT] == 1) { 70 if (idou[nx - 1][ny] == 0) { // 移動先が空いていれば 71 nx--; playerphoto = gh[2]; // 左向き 72 } 73 else { 74 keep = 1; playerphoto = gh[9]; // 移動不可能 75 } 76 } 77 if (Key[KEY_INPUT_UP] == 1) { 78 if (idou[nx][ny - 1] == 0) { // 移動先が空いていれば 79 ny--; playerphoto = gh[4]; // 上向き 80 } 81 else { 82 keep = 1; playerphoto = gh[9]; // 移動不可能 83 } 84 } 85 if (Key[KEY_INPUT_DOWN] == 1) { 86 if (idou[nx][ny + 1] == 0) { // 移動先が空いていれば 87 ny++; playerphoto = gh[3]; // 下向き 88 } 89 else { 90 keep = 1; playerphoto = gh[9]; // 移動不可能 91 } 92 } 93 94 ClearDrawScreen(); // 裏画面をクリア 95 96 for (int i = 0; i < 4; i++) 97 DrawLine(box[i][0][0], box[i][0][1], 98 box[i][6][0], box[i][6][1], boxColor); 99 for (int j = 0; j < 7; j++) 100 DrawLine(box[0][j][0], box[0][j][1], 101 box[3][j][0], box[3][j][1], boxColor); 102 103 int x = player[ny][nx][0], y = player[ny][nx][1]; // 表示位置に変換 104 if (x == px && y == py) { 105 if (keep == 0 || ++keep == 10) { 106 keep = 0; playerphoto = gh[5]; 107 } 108 } 109 else { 110 if (abs(x - px) < 8) px = x; 111 else if (x > px) px += 8; 112 else if (x < px) px -= 8; 113 if (abs(y - py) < 6) py = y; 114 else if (y > py) py += 6; 115 else if (y < py) py -= 6; 116 } 117 DrawGraph(px, py, playerphoto, FALSE); // プレイヤーを裏画面に描画 118 ScreenFlip(); // 裏画面を表画面に反映 119 } 120 121 DxLib_End(); // DXライブラリ使用の終了処理 122 return 0; // ソフトの終了 123}

次の質問に必ず答えてください。
(1) 希望通りの動作をしますか?
(2) 疑問点はどこですか?

投稿2019/08/23 07:54

kazuma-s

総合スコア8224

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

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

carnage0216

2019/08/23 11:07

どうやって、こんな凄いの作ったんですか? 市販できるくらいの技術のゲームを作られて大変びっくりしています。 できれば、どうやってこのように作ったのか詳しい過程の考えとどうやって関数を組み合わせたか教えてほしいです。 どうかよろしくお願いいたします
carnage0216

2019/08/23 11:09

(1) 希望通りの動作をしますか? はい、ジャンプはしませんが、ロックマンエグゼのように瞬間移動というかシュッと移動すれば ほぼ希望通りの動きです。 (2) 疑問点はどこですか? 疑問点は多いですが、まずは解読させて頂きます。どのようにしてこのような動きをさせたのか大変興味があります。なので読ませて頂いてから、質問させて頂きます。
kazuma-s

2019/08/26 12:14

解読できましたか?
carnage0216

2019/08/27 08:28

ま、まだ出来ていません。すいません。基礎力の無さ故に未だに解読しています。 そして、その後の敵キャラの移動方法などを考えています。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問