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

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

新規登録して質問してみよう
ただいま回答率
85.44%
Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

C++

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

Q&A

2回答

1344閲覧

c++でアニメーション描画

退会済みユーザー

退会済みユーザー

総合スコア0

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

C++

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

0グッド

0クリップ

投稿2023/05/27 02:24

実現したいこと

アニメーションを描画したい。

前提

visualstudioのc++でアニメーションを描画するプログラムを制作しています。
アニメーションの内容は画面に表示させたプレイヤーの画像が、進行方向と同じ方向に向き、それぞれに応じたアニメーションを表示するようにしたいです。アニメーションの元となる画像は上下左右一つにつき4枚あります。
それをtimer変数(time関数ではないです)、while文を用いり変数の値が特定の数値になったときアニメーションの画像を切り替えるようにします。数値は60までで、0以上15未満の時は1枚目の画像を、15以上30未満の時は2枚目を表示します。(30以降も同じ)
今悩んでいるのはこの部分で、現在画像読み込みの変数を
int grHandle1 = LoadTexture("right0.png");   int grHandle2 = LoadTexture("right1.png");
int grHandle3 = LoadTexture("right2.png");  int grHandle4 = LoadTexture("right3.png");
int grHandle5 = LoadTexture("left0.png");   int grHandle6 = LoadTexture("left1.png");
int grHandle7 = LoadTexture("left2.png"); int grHandle8 = LoadTexture("left3.png");
int grHandle9 = LoadTexture("back0.png"); int grHandle10 = LoadTexture("back1.png");
int grHandle11= LoadTexture("back2.png"); int grHandle12= LoadTexture("back3.png");
int grHandle13= LoadTexture("front0.png"); int grHandle14= LoadTexture("front1.png");
int grHandle15 = LoadTexture("front2.png"); int grHandle16= LoadTexture("front3.png");
このようにしていますが一つの方向につき四枚あるのでこれら全部のアニメーションを表示するとなると
1つのwhile文では足りません。この場合while文は4方向分用意する必要があるということでしょうか?
その場合コードが多くなってごちゃごちゃしてしまうので簡潔にする方法があればより良いですが…

あともう一つ悩んでいることがあり、下のコードのif(direction…)の部分でここにはdirectionの値によってプレイヤーのアニメーションを描画するコードです。
0の時上を向いている。1の時下を向いている。2の時左を向いている。3の時右を向いている。
先ほどの通り一つの方向につき四枚あるので、一つのif文に全てを書くとおかしくなります。
例としてif(direction == 0){
DrawSprite(posX,posY,grHandle1,1.0f,1.0f,0.0f,0xFFFFFFFF);
DrawSprite(posX, posY, grHandle2, 1.0f, 1.0f, 0.0f,0xFFFFFFF);以下grHandle3,4も書く
とすると一度に四枚の画像が読み込まれているのでエラーが発生します。
こちらもdirection == 0を複数書かなければいけないのでしょうか?

該当のソースコード

int posX = 400;int posY = 400;  int V = 3;//プレイヤーが動く速さ
int direction = 0;int timer = 0;

int grHandle1 = LoadTexture("right0.png"); int grHandle2 =LoadTexture("right1.png");
int grHandle3 = LoadTexture("right2.png"); int grHandle4 =LoadTexture("right3.png");
int grHandle5 = LoadTexture("left0.png"); int grHandle6 = LoadTexture("left1.png");
int grHandle7 = LoadTexture("left2.png"); int grHandle8 =LoadTexture("left3.png");
int grHandle9 =LoadTexture("back0.png"); int grHandle10 =LoadTexture("back1.png");
int grHandle11= LoadTexture("back2.png"); int grHandle12= LoadTexture("back3.png");
int grHandle13= LoadTexture("front0.png"); int grHandle14= LoadTexture("front1.png");
int grHandle15 = LoadTexture("front2.png");int grHandle16= LoadTexture("front3.png");

if (keys[DIK_W]) {posY = posY - V;direction = 0;}
if (keys[DIK_S]) {posY = posY + V;direction = 1;}
if (keys[DIK_A]) {posX = posX - V;direction = 2;}
if (keys[DIK_D]) {posX = posX + V;direction = 3;}

while (timer == 60) {
timer++;
if (timer >= 0 && timer < 15) {
//ここで悩んでいます}
}

if (direction == 0){
DrawSprite(posX, posY, grHandle1, 1.0f, 1.0f, 0.0f, 0xFFFFFFFF);//ここも悩んでいます。
}

c++ ### 試したこと 1つの方向四枚分をgrHandle1として一つにまとめてみたがgrHandle1が複数あるよというエラーが出てしまい断念。 ### 補足情報(FW/ツールのバージョンなど) visualstudio2022 ここにより詳細な情報を記載してください。

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

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

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

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

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

episteme

2023/05/28 10:37 編集

grHandleを配列にすればいいんじゃなくて? int grHandle[4][4]; // grHandle[方向][時間] みたいな
umimi

2023/05/28 21:12

[香車]東上☆あらし☆海美「 何のライブラリを使用していますか ? DxLib かと思ったけど、DrawSprite とか出てきたので、違いますよね ? 追加: 生の DirectX ですかね。 」
退会済みユーザー

退会済みユーザー

2023/05/29 05:16

DirectXです。
fana

2023/06/01 10:33

一度,問題を小さくして取り込んでみてはどうですか? 例えば,「向き」の要素はとりあえずは無視して,常に 下向き用 の表示をするならば, timer に関する話だけにフォーカスして取り組むことができますよね. 何ならアニメーションのパターン数の側も簡略化して2パターンアニメにでもしてみたらどうでしょう. これができたらアニメパターンを増やす(4に戻す)ことに関しては疑問点は生じないであろうと想像しますし,その後で「向き」を増やすことに関しても同様でしょう.
guest

回答2

0

(他の方がおっしゃっているように)いくらなんでも1から10まで説明するのは労力が半端ないことになるかもしれませんので,ざっくりとした方向性の話に留めます.


示されたコードの中で,おそらく画像を描画する処理は
DrawSprite(posX, posY, grHandle1, 1.0f, 1.0f, 0.0f, 0xFFFFFFFF);
であろうと見えます.
意味としては「 grHandle1 が指す画像を描画する」ですかね.

そしたら,別の画像を描画する場合,例えば「 grHandle9 が指す画像を描画する」ためには,別途
DrawSprite(posX, posY, grHandle9, 1.0f, 1.0f, 0.0f, 0xFFFFFFFF);
とか書くことを考えておられたりしませんでしょうか?

もしそうであれば,画像が16種類あると,ハンドル部分だけが違う DrawSprite(...) を16箇所書くことになるわけで,まぁ大変でしょう.
というわけで,ここを

//こんな変数を用意して… int HandleOfImage_ShouldBeDrawn_Now; //今現在描画するべき画像のハンドル ... //うまいことこの変数の値を各時刻で決める処理があるならば… HandleOfImage_ShouldBeDrawn_Now = 16個のハンドルのうちのいずれか; ... //描画箇所はこう書いとけばよい DrawSprite(posX, posY, HandleOfImage_ShouldBeDrawn_Now, 1.0f, 1.0f, 0.0f, 0xFFFFFFFF);

みたいにできないのか? という点を考えてみてはどうでしょうか.

HandleOfImage_ShouldBeDrawn_Now = 16個のハンドルのうちのいずれか;」の部分は
当然ながら,現在の directiontimer の値に基づいて決める処理を入れればよいということになります.
最も愚直には ifswitch あたりを使って怒涛の16分岐を書けば,とりあえずは動くでしょう.

で, そのような「怒涛の16分岐」を書きたくない,という場合には,
「16個の個別の変数があって…」というハンドルの持ち方を「16個のうちの何番目」という形で指定できるような持ち方に変えることを考えればよいでしょう.
(既に質問へのコメントで 「配列を使う」 旨が言及されています.)
そしたら,「怒涛の16分岐」だった箇所を【「16個のうちの何番目」という値を計算する処理】に置き換えればよいわけです.(この処理に関しては,単なる算数の話になるでしょう)

投稿2023/06/01 10:48

fana

総合スコア11729

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

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

0

[香車]東上☆あらし☆海美「
なんか、書込が消えてますね。まっ、いいか。
質問主の書込を読んで、まず思ったことは『これは、使用ライブラリを当てさせる、なぞなぞ、か?』でした。
一般論として、[生Windws][WinG][DiectX][OpenGL][DxLib]の様に、使用ライブラリ(もしくは使っていない)を明記した方がレスは付きやすいですよ、という意見だったのですが、言葉足らずだったようです。
『レスが遅い』というのは、他の場所でも、言われます。消された書込へのレスを追加していたら、遅くなりました。ごめんなさい。プリキュアを観ていました。別に、『Taratail へのレスに命をかけている』わけではないので、優先度は低いです。
Teratail 意見交換の『3 日たったら編集できなくなる』と言う仕様の元ネタは、富野由悠季監督『戦闘メカ・ザブングル』の『三日(みっか)の掟』ですかね ?
本題です。
一般論として、自キャラも、敵キャラも、弾も、バラバラのファイルで持つのではなく、全部くっつけて一枚絵にしたものから、切り分けて書き込みます。Windows の場合は、数字や文字は、Windows API で描いてもいいでしょうが、移植を前提とするなら、一枚絵に加えましょう。
こういう事は、現在の ChatGPT 等の AI では、教えてくれないようですね。

追記: 2023(05)-06-08
[香車]東上☆あらし☆海美「

C+

1#include <vector> 2class TObj { 3public: 4 virtual void draw() {} 5}; 6class TPlayerBase { 7public: 8 void draw(const int t) {} 9}; 10class TPlayerUp : public TPlayerBase { 11public: 12 void draw(const int t) { /* DrawSplight();*/ } 13}; 14class TPlayerRight : public TPlayerBase { 15public: 16 void draw(const int t) { /* DrawSplight();*/ } 17}; 18class TPlayerDown : public TPlayerBase { 19public: 20 void draw(const int t) { /* DrawSplight();*/ } 21}; 22class TPlayerLeft : public TPlayerBase { 23public: 24 void draw(const int t) { /* DrawSplight();*/ } 25}; 26class TPlayer : public TObj { 27 TPlayerBase* player[4]; 28 int vec, t; 29public: 30 void draw() { 31 player[ vec ]->draw(t); 32 } 33 TPlayer(): vec( 0 ), t( 0 ) { 34 player[0] = new TPlayerUp(); 35 player[1] = new TPlayerRight(); 36 player[2] = new TPlayerDown(); 37 player[3] = new TPlayerLeft(); 38 } 39}; 40class TEnemy : public TObj { 41public: 42 void draw() { /* You write. */ } 43}; 44int 45main() try 46{ 47 std::vector<TObj*> objs; 48 objs.push_back(new TPlayer()); 49 objs.push_back(new TEnemy()); 50 // 51 while ( true /* You write */) { 52 for (auto i: objs) { 53 i->draw(); 54 } 55 } 56 return EXIT_SUCCESS; 57} 58catch (...) 59{ 60 return EXIT_FAILURE; 61}

このままで Windows で走るわけでは、ありません。

投稿2023/05/31 13:03

編集2023/06/08 02:46
umimi

総合スコア243

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

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

fana

2023/06/01 01:20 編集

> 一般論として ...(中略)... バラバラのファイルで持つのではなく、全部くっつけて一枚絵にしたものから、切り分けて書き込みます (1)そうする理由とは何ですか? 例えば,3つの画像{A,B,C}が必要な場合において 【これらを素直に3つの画像ファイルとして用意して使う】ことに比べて【内容が{ABC}である単一の画像ファイルを用意して使う】ことの利点とは何なのですか? (また,何らかの利点があるのだとして,それはどの程度の差を生ずるのですか?) (2)そうすれば解決するのですか? 単一のファイルを用いる方法を質問者が採用することによって,質問者が抱えている問題はどのように解決するのですか?
fana

2023/06/01 01:29 編集

(3) かえって面倒ではないのですか? 1画像内に複数のコンテンツが含まれている場合,「個々のコンテンツのサイズや画像内に配されている場所等に関する情報」が追加で存在していないと使いようがないように思えます. それは 「一般論」 ではどこからどうやって得ることになっているのでしょうか? 各コンテンツが個別の画像ファイルになっている場合には,こういうことを特段考える必要も無いように思えるので,(素人目には)1画像にくっつけてしまうと,かえって厄介事が増えてしまうように思えてしまいます.
fana

2023/06/01 02:14

……と,3つほど疑問を書きましたが,Q&Aの場という意味において最も重要だろうと思う (2) が不明瞭であると思えるので,その意味で 「質問に対する回答となっていない投稿」 とかいうのを付けています. 理由: この質問の内容は結局のところ 「16個の絵があって,それらのうちの どれか1つ を現状に応じて選択的に表示する必要があるのだけど…?」 という話だと見えるのですが,であれば,この回答の内容を採用したところで 「1枚の大きな絵があって,そのうちの どこか一部 を現状に応じて選択的に表示する必要があるのだけど…?」 となるだけで,何も解決しないであろうと想像するので. 要は,本件は「16分岐を達成するために 愚直に長大な if や switch のようなものを書きたくない(それを書くこともできていない?)」という話と見えるわけで,そこのところに対して この回答がどれほど有益な影響を与え得るのか? という点に疑問がある,ということです.
umimi

2023/06/01 05:28

[香車]東上☆あらし☆海美「 16 個のグラフィック・ハンドルが、ひとつで、すむようになるみみ。 海美の書込は、貴方のゲーム・プログラミングを否定するものではありません。 この質問に回答するのって、『新たに、ミニ・ゲームを一個作る以上の労力が必要』だと思うのですが、 それが面倒くさかった、果たして無償で行うべき範囲になるのかとの疑問が湧きました。 しかし、誰もレスしないのは質問者が気の毒、と思って、軽いレスをしたわけで。 『質問に対する不十分な投稿』であることは、否定しません。 >「16分岐を達成するために 愚直に長大な if や switch のようなものを書きたくない(それを書くこともできていない?)」という話と見えるわけで 貴方が、そう思うなら、貴方が、質問者に回答すればいいと思います。 海美は、もう降りるので、あと、よろしく~。 『回答が3つ分かれていますが、3つに分割した利点は ?」とかいう書込がついたら、 やる気を削がれると思います。こういう絡まれ方をされるなら、Teratail は、BAN でいいや。 」
fana

2023/06/01 09:18

単に,回答内容の 意味/意義/利点 等を明確にしたく問うているだけなのですが, このように まるでこちらに攻撃的な意図があるかのように 一方的に捉える人が何故か異様に多いのがこの teratail の残念なところですね.
umimi

2023/06/08 02:41

```C+ + #include <vector> class TObj { public: virtual void draw() {} }; class TPlayerBase { public: void draw(const int t) {} }; class TPlayerUp : public TPlayerBase { public: void draw(const int t) { /* DrawSplight();*/ } }; class TPlayerRight : public TPlayerBase { public: void draw(const int t) { /* DrawSplight();*/ } }; class TPlayerDown : public TPlayerBase { public: void draw(const int t) { /* DrawSplight();*/ } }; class TPlayerLeft : public TPlayerBase { public: void draw(const int t) { /* DrawSplight();*/ } }; class TPlayer : public TObj { TPlayerBase* player[4]; int vec, t; public: void draw() { player[ vec ]->draw(t); } TPlayer(): vec( 0 ), t( 0 ) { player[0] = new TPlayerUp(); player[1] = new TPlayerRight(); player[2] = new TPlayerDown(); player[3] = new TPlayerLeft(); } }; class TEnemy : public TObj { public: void draw() { /* You write. */ } }; int main() try { std::vector<TObj*> objs; objs.push_back(new TPlayer()); objs.push_back(new TEnemy()); // while ( true /* You write */) { for (auto i: objs) { i->draw(); } } return EXIT_SUCCESS; } catch (...) { return EXIT_FAILURE; } ```
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.44%

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

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

質問する

関連した質問