2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

C++の勉強しながらDxLibで2Dゲーム作ってみない?(実践編)⑤

Last updated at Posted at 2021-02-21

今回の目標

④-⑤の間でかなり期間が開いてしまって申し訳...
リアルの方でゲーム開発やらハードウェア開発がバタついていてQiitaに手が付けられませんでした><
さて、今回は前回の記事の最後に書いたアニメーションをやっていきます!!!

前回 : C++の勉強しながらDxLibで2Dゲーム作ってみない?(実践編)④

この記事の対象

・Dxlibを使いゲーム開発をしてみたい方

・C++を始めたばかりの初心者の方で作りながら覚えたい方

・何かしらのライブラリやツールを使ってゲーム開発をしてみたい人方

アニメーションといってもGIFなどではないお!!!

ではさっそくプログラミングをしていきましょう...とはいきません。
今回の目的はアニメーションですが、素材がないので作るところからです...
とは言ってもこの記事はプログラミングが目的なので今回は適当なのを用意しました。
player_animation.png
これは1764x245サイズの一枚のPNG画像ファイルです。
多くの方はこの画像を見てどのような動きをするか予想できると思います。
ではこの画像をどうやってアニメーションにしていくかを考えていきましょう。

まずは何フレームか知ろう

先ほどの画像はキャラクターが9つに分かれて描かれています。
すなわちこの画像を9枚に分割すると9フレームのアニメーションの素材ができます。
計算すると

X = 1764 / 9 = 196  
Y = 245(縦は変わらない)  

となります。
ただこの画像をペイントソフトで9枚に分割するのではありません。
これもプログラムから行うためにLoadDivGraphというものを使います。

LoadDivGraph

画像を分割読み込みするにはこのLoadDivGraphというDxLibの関数を使います。
この関数では分割した画像のハンドルをint型配列に格納します。
LoadDivGraphの引数は以下の通りです。

int LoadDivGraph(char *FileName, int AllNum, int XNum, int YNum, int XSize, int YSize, int *HandleBuf);

FileName : 画像ファイルのパス
AllNum : 画像の分割枚数
XNum : X軸の分割数
YNum : Y軸の分割数
XSize : X軸の一枚の大きさ
YSize : Y軸の一枚の大きさ
HandleBuf: int型配列

とりあえず読み込んでみて表示までしてみる

さっそく分割読み込みから表示までやってみましょう!
LoadDivGraphに渡す引数はこのようになります。

const int MaxFrame = 9;
int Ani_image[MaxFrame];
int LoadDivGraph("画像ファイルのパス", MaxFrame, MaxFrame, 1, 196, 245, Ani_image);

これを踏まえて前回覚えたDrawGraphを使用し表示してみましょう!

main.cpp
#include "DxLib.h"

const char *TITLE = "Untitled";
const int WIN_WIDTH = 960;
const int WIN_HEIGHT = 540;

int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nCmdShow)
{
    ChangeWindowMode(true);
    SetWindowSizeChangeEnableFlag(false, false);
    SetMainWindowText(TITLE);
    SetGraphMode(WIN_WIDTH, WIN_HEIGHT, 32);
    SetWindowSizeExtendRate(1.0);
    SetBackgroundColor(35, 35, 35);
    SetDrawScreen(DX_SCREEN_BACK);

    if (DxLib_Init() == -1) { return -1; }

    //画像の表示座標
    int Adjust_CenterX = (WIN_WIDTH / 2) - (196 / 2);
    int Adjust_CenterY = (WIN_HEIGHT / 2) - (245 / 2);

    //画像の分割読み込み
    const int MaxFrame = 9;
    int Ani_image[MaxFrame];
    LoadDivGraph("animation.png", MaxFrame, MaxFrame, 1, 196, 245, Ani_image);

    while (true) {
        ClearDrawScreen();

        //画像の表示
        DrawGraph(Adjust_CenterX, Adjust_CenterY, Ani_image[0], true);

        ScreenFlip();
        WaitTimer(20);
        if (ProcessMessage() == -1) { break; }
        if (CheckHitKey(KEY_INPUT_ESCAPE) == 1) { break; }
    }

    DxLib_End();
    return 0;
}

このコードではDrawDivGraphで分割読み込みをした画像の一枚目(配列の0番目)だけを画面中央に表示しています。
引数のファイルパスは前回同様ソースコードと同じフォルダにcharacterという名前で画像を保存したのでcharacter.pngになっています。

実際にアニメーションを再生してみる

ではさっそくアニメーションにしてみましょう!
アニメーションとして再生するためには配列の要素を順に変えていけばいいだけなので簡単です!
コードは以下になります。

main.cpp
#include "DxLib.h"

const char *TITLE = "Untitled";
const int WIN_WIDTH = 960;
const int WIN_HEIGHT = 540;

int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nCmdShow)
{
    ChangeWindowMode(true);
    SetWindowSizeChangeEnableFlag(false, false);
    SetMainWindowText(TITLE);
    SetGraphMode(WIN_WIDTH, WIN_HEIGHT, 32);
    SetWindowSizeExtendRate(1.0);
    SetBackgroundColor(35, 35, 35);
    SetDrawScreen(DX_SCREEN_BACK);

    if (DxLib_Init() == -1) { return -1; }

    //画像の表示座標
    int Adjust_CenterX = (WIN_WIDTH / 2) - (196 / 2);
    int Adjust_CenterY = (WIN_HEIGHT / 2) - (245 / 2);

    //画像の分割読み込み
    const int MaxFrame = 9;
    int Ani_image[MaxFrame];
    LoadDivGraph("animation.png", MaxFrame, MaxFrame, 1, 196, 245, Ani_image);

    //アニメーション再生用変数
    int Frame = 0;
    int Frame_adjust = 0;

    while (true) {
        ClearDrawScreen();

        //画像の表示
        if (Frame_adjust == 5) {
            Frame++;
            Frame_adjust = 0;
        }
        if (Frame == MaxFrame - 1) {
            Frame = 0;
        }
        Frame_adjust++;
        DrawGraph(Adjust_CenterX, Adjust_CenterY, Ani_image[Frame], true);

        ScreenFlip();
        if (ProcessMessage() == -1) { break; }
        if (CheckHitKey(KEY_INPUT_ESCAPE) == 1) { break; }
    }

    DxLib_End();
    return 0;
}

実行結果は以下のようになります
animation.gif

このアニメーションのカギとなる変数はFrameというint型の変数です。
今回は変数Frame_Adjustが5回インクリメントされた場合にFrameがインクリメントされるif文でアニメーションを動かしています。
Frame_Adjustに関してはなくても大丈夫ですが、今回の場合60FPS想定でコードを書いているため、とても早く上下に動く謎のやつになると思います...w

ざっくりした仕組み

一応仕組みを簡単に説明します。
このアニメーションの仕組みはパラパラ漫画と全く同じ仕組みで、複数の画像を連続して表示させることによってアニメーションにしています。
(まぁアニメーションってそういうものですが)
ですので別に9フレームじゃなければだめというわけではなく、多くなっても少なくなっても臨機応変に変数の値やら定数を変えてやればいいのです。
簡単ですね!

次回

全く考えてないので少々お待ちください...
そろそろ時間同期とか関数、ポインタ、クラスをやりたいと考えてます(早い)

あとがき

お疲れ様でした!まゆC#です(*'▽')
今回の記事はいかがだったでしょうか?
おそらく「こいつ今回適当だな」って思われてるんじゃないかなと思いながら書いてましたw
まぁ実際、今回は若干適当です(アニメーション、踏み込むと長いので)
ではまた次回、近いうちにお会いしましょう!!!

作者について

詳しくはわんころメソッド();HPにどうぞ(*'▽')

・わんころメソッド();HP
・Twitter(まゆC#)
・GitHub(まゆC#)

コミュニティ

Discordで雑談から質問まで様々なチャンネルがあるまゆC#のコミュニティサーバーがあります!
わからないことがあればこちらでもお答えするのでぜひ!
Discordサーバー : わんころメソッド(雑談);

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?