👏

DXライブラリを使ってLive2Dモデルを動かし、描画しよう

2024/04/19に公開

はじめに

本記事はかの有名なDirectX APIを簡易化したライブラリ「DXライブラリ」を使用して、現在流行のLive2Dモデルを描画し、さらにモーションを制御する簡単なやり方を紹介します。

目次

  1. Visual Studioの準備
  2. DXライブラリの導入
  3. Live2D Cubism 4 SDKとLive2Dモデルの導入
  4. コーディング
  5. 最終成果
  6. 参考文献

Visual Studioの準備

スクリーンショット 2024-04-18 232011.png

初期セットアップする時に必ず入れて欲しいのは「ユニバーサルWindowsプラットフォーム開発」

スクリーンショット 2024-04-18 232341.png

DXライブラリの導入

スクリーンショット 2024-04-18 233013.png

<a id="#Live2DSample"></a>

Live2D Cubism 4 SDKとLive2Dモデルの導入

スクリーンショット 2024-04-18 231552.png

  • サンプルデータをダウンロード
    元々私が使用するモデルは当時無料配布だった「ミアラ」だが、この記事を執筆した現在は有料になりましたので、他の無料モデルを使用してください。
    https://www.live2d.com/learn/sample/

スクリーンショット 2024-04-19 005434.png

  • Visual Studioの設定

▼DXライブラリSDKのパス設定(すべての構成に設定)
パスは相対パス、絶対パスどちらでも構いません

スクリーンショット 2024-04-18 224806.png

スクリーンショット 2024-04-18 224817.png

▼リンカーのシステムを「Windows(/SUBSYSTEM:WINDOWS)に設定」
スクリーンショット 2024-04-18 224826.png

▼Live2D Cubism 4 SDKをプロジェクトのディレクトリ下に入れる(プロジェクトディレクトリ以外のローカル外部でも良いですが、ファイルをどこかにクローンする時に参照がずれて、また再設定しないといけない)
スクリーンショット 2024-04-18 233650.png

コーディング

  • まずはLive2Dモデルを読み込む準備をします
Live2D.h
#pragma once
#include"DxLib.h"

class Live2D
{
public:
	Live2D(int modelHandle);
	~Live2D();
	void Initialize();
	void Load(const TCHAR *filePath);
	void Update(const TCHAR* motion);
	void DrawBegin();
	void DrawModel();
	void DrawEnd();
	void DeleteModel();

private:
	int ModelHandle;
};
Live2D.cpp
#include"Live2D.h"

Live2D::Live2D(int modelHandle)
	:ModelHandle(modelHandle)
{
	
}

Live2D::~Live2D()
{

}

void Live2D::Initialize()
{

#ifdef _WIN64
	Live2D_SetCubism4CoreDLLPath(L"../CubismSdkForNative-4-r.1/Core/dll/windows/x86_64/Live2DCubismCore.dll");
#else
	Live2D_SetCubism4CoreDLLPath(L"../CubismSdkForNative-4-r.1/Core/dll/windows/x86/Live2DCubismCore.dll");
#endif

}

void Live2D::Load(const TCHAR* filePath)
{
	// Live2Dモデルの読み込み
	ModelHandle = Live2D_LoadModel(filePath);
}

void Live2D::Update(const TCHAR* motion)
{
	// モーション再生が終了していたらアイドリングモーションをランダムで再生
	if (Live2D_Model_IsMotionFinished(ModelHandle) == TRUE)
	{
		Live2D_Model_StartMotion(ModelHandle, motion, GetRand(8));
	}

	// モデルの状態を60分の1秒分進める
	Live2D_Model_Update(ModelHandle, 1 / 60.0f);
}

void Live2D::DrawBegin()
{
	// Live2D描画の開始
	Live2D_RenderBegin();
}

void Live2D::DrawModel()
{
	// モデルの描画
	Live2D_Model_Draw(ModelHandle);
}

void Live2D::DrawEnd()
{
	// Live2D描画の終了
	Live2D_RenderEnd();
}

void Live2D::DeleteModel()
{
	// Live2D モデルの削除
	Live2D_DeleteModel(ModelHandle);
}
  • おまけに入力系のクラスも書いておきます
Input.h
#pragma once
#include"DxLib.h"

class Input
{
public:
	static char currentKey[256];
	static char previousKey[256];
	static int mousePosX, mousePosY, mouseLeftButt, mouseRightButt, mouseMidButt;
public:
	static void Mouse(int*, int*);
	static int MouseLeftButton();
	static int MouseRightButton();
	static int MouseMiddleButton();
	static int Key(int key);
	static bool KeyTrigger(int key);
	static void Update();
	static void Draw();
};
Input.cpp
#include"Input.h"

int Input::mousePosX = 0;
int Input::mousePosY = 0;
int Input::mouseLeftButt = 0;
int Input::mouseRightButt = 0;
int Input::mouseMidButt = 0;
char Input::currentKey[256] = { 0 };
char Input::previousKey[256] = { 0 };

void Input::Update() 
{
	GetMousePoint(&mousePosX, &mousePosY);
	if ((GetMouseInput() & MOUSE_INPUT_LEFT) != 0) mouseLeftButt++;
	else mouseLeftButt = 0;
	if ((GetMouseInput() & MOUSE_INPUT_RIGHT) != 0) mouseRightButt++;
	else mouseRightButt = 0;
	if ((GetMouseInput() & MOUSE_INPUT_MIDDLE) != 0) mouseMidButt++;
	else mouseMidButt = 0;

	memcpy(previousKey, currentKey, sizeof(previousKey));

	GetHitKeyStateAll(currentKey);
}

void Input::Mouse(int* x, int* y) 
{
	*x = mousePosX;
	*y = mousePosY;
}

int Input::MouseLeftButton() { return mouseLeftButt; }
int Input::MouseRightButton() { return mouseRightButt; }
int Input::MouseMiddleButton() { return mouseMidButt; }

int Input::Key(int key) 
{
	return currentKey[key];
}

bool Input::KeyTrigger(int key)
{
	return !previousKey[key] && currentKey[key];
}

void Input::Draw() {

}

  • 次にゲームの環境を整う
Game.h
#pragma once
#include"DxLib.h"

class Game 
{
public:
	Game();
	~Game();
	void Initialize();
	void Load();
	void Update();
	void Draw();

public:
	int LoadTexture(TCHAR* fileName) 
	{
		int tex = LoadGraph(fileName);
		if (tex == -1) {
			MessageBox(NULL, L"画像の読み込みに失敗しました", ERROR, MB_OK);
			return 0;
		}
	};
	
private:
	int texture;
	float texturePosX;
	float texturePosY;
	bool controllSwitch;
};

#include"Game.h"
#include"Input.h"

Game::Game() 
{
	this->Initialize();
}

Game::~Game() 
{

}

void Game::Initialize() 
{
	texture = NULL;
	texturePosX = 600;
	texturePosY = 400;
	controllSwitch = false;
}

void Game::Load() {

}

void Game::Update() 
{
	if (!controllSwitch) 
	{
		texturePosX = 600;
		texturePosY = 400;
	}
	else
	{
		texturePosX = 800;
		texturePosY = 600;
	}
	if (Input::Key(KEY_INPUT_SPACE) == 1) {
		controllSwitch = !controllSwitch;
	}

}

void Game::Draw() {

}
  • 最後にモデルを描画し、スペースキーで動作変えましょう
#include"Game.h"
#include"Input.h"
#include"Live2D.h"

int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nCmdShow)
{
	//ウィンドウモードに設定
	ChangeWindowMode(TRUE);

	SetMainWindowText(L"Live2D Test Program");

	// 画面解像度を設定
	SetGraphMode(1280, 720, 0);

	//ウィンドウサイズを手動では変更できず、
    //かつウィンドウサイズに合わせて拡大できないようにする
	SetWindowSizeChangeEnableFlag(FALSE, FALSE);

	bool motionChange = false;

	int live2DHandle = 0;

	Live2D* live2D = new Live2D(live2DHandle);	

	live2D->Initialize();

	// DXライブラリ初期化処理
	if (DxLib_Init() == -1) return -1;

	Game game;
	game.Initialize();
	game.Load();

	live2D->Load(L"../Assets/miara_pro_jp/runtime/miara_pro_t04.model3.json");

	// 描画先を裏画面に変更
	SetDrawScreen(DX_SCREEN_BACK);

	// メインループ
	while (ScreenFlip() == 0 && ProcessMessage() == 0 && ClearDrawScreen() == 0)
	{
		Input::Update();

		game.Update();
		game.Draw();

		if (Input::KeyTrigger(KEY_INPUT_SPACE))
		{
			motionChange = !motionChange;
		}

		if (!motionChange)
		{
			live2D->Update(L"Idle");
		}
		else
		{
			live2D->Update(L"Flick");
		}

		live2D->DrawBegin();

		live2D->DrawModel();

		live2D->DrawEnd();

		if (CheckHitKey(KEY_INPUT_ESCAPE) != 0) break;
	}

	live2D->DeleteModel();

	delete live2D;

	// DXライブラリ使用の終了処理
	DxLib_End();

	// ソフトの終了
	return 0;
}
  • Live2Dモデルモーションに関してですが、ご自身がダウンロードしたサンプルデータのなかの「runtime」フォルダの中にある「OOO.model3.json」のような名前のファイルから見えます。

スクリーンショット 2024-04-19 002748.png

▲私の場合IdleとFlickを切り替えて使用してます

最終成果

miara.gif

参考文献

Discussion