ゲームプログラミングの骨組み:その2 後編

アバター
a5ua
記事: 199
登録日時: 14年前

ゲームプログラミングの骨組み:その2 後編

投稿記事 by a5ua » 14年前

「2.画像や音楽などのリソース管理」の続きです。

まず、画像と音を扱うクラスを作成します。といっても、ほとんどDXライブラリの機能で実現されているので、大したクラスではありません。これらのクラスでは、コンストラクタでファイル名などを指定し、内部でハンドルを保持します。デストラクタでは、データを解放します。

画像データを表すImageクラスは以下のとおりです。
【Image.h】

CODE:

#pragma once
#include 
namespace a5ua
{
	class Image
	{
	public:
		// コンストラクタ:ファイル名を指定
		Image(const TCHAR *file_name);
		// コンストラクタ:ファイル名と分割数と分割サイズを指定
		Image(const TCHAR *file_name, int num_all, int num_x, int num_y, int width, int height);
		// デストラクタ
		~Image();
		// 総分割数を取得
		int division_number() const;
		// 描画:位置と透過フラグを指定
		void draw(int x, int y, bool transparent) const;
		// 描画:分割時のインデックスおよび位置と透過フラグを指定
		void draw(int index, int x, int y, bool transparent) const;
	private:
		int m_num_all;	// 総分割数
		int *m_handle;	// 画像ハンドルの配列
	};
}
【Image.cpp】

CODE:

#include "Image.h"
#include 
#include 
namespace a5ua
{
	// 通常の読み込み
	Image::Image(const TCHAR *file_name) : m_num_all(1)
	{
		m_handle = new int [1];
		m_handle[0] = LoadGraph(file_name);
		assert(m_handle[0] != -1);
	}

	// 分割読み込み
	Image::Image(const TCHAR *file_name, int num_all, int num_x, int num_y, int width, int height) : m_num_all(num_all)
	{
		m_handle = new int [m_num_all];
		int result = LoadDivGraph(file_name, num_all, num_x, num_y, width, height, m_handle);
		assert(result != -1);
	}

	// 画像データの解放
	Image::~Image()
	{
		for (int i = 0; i 
namespace a5ua
{
	class Sound
	{
	public:
		// コンストラクタ:ファイル名とデータタイプを指定
		Sound(const TCHAR *file_name, int data_type);
		// デストラクタ
		~Sound();
		// 通常再生
		void play();
		// ループ再生
		void loop();
		// 停止
		void stop();
	private:
		int m_handle;	// サウンドハンドル
	};
}
【Sound.cpp】

CODE:

#include "Sound.h"
#include 
#include 
namespace a5ua
{
	Sound::Sound(const TCHAR *file_name, int data_type)
	{
		SetCreateSoundDataType(data_type);
		m_handle = LoadSoundMem(file_name);
		assert(m_handle != -1);
	}

	Sound::~Sound()
	{
		DeleteSoundMem(m_handle);
	}
	
	void Sound::play()
	{
		PlaySoundMem(m_handle, DX_PLAYTYPE_BACK);
	}
	
	void Sound::loop()
	{
		PlaySoundMem(m_handle, DX_PLAYTYPE_LOOP);
	}

	void Sound::stop()
	{
		StopSoundMem(m_handle);
	}

}
次に、前回作成したBasicFactoryを使って、Image/Soundを文字列パラメータを使って生成するImageFactory/SoundFactoryを作成します。ここでは、実装は省略します。(要望があれば追記します。)
また、ImageやらSoundを保持するStoreをまとめて、ResourceSetクラスを作りました。
【ResourceSet.h】

CODE:

#pragma once
#include 
#include "Factory.hpp"
#include "Store.hpp"
#include "Image.h"
#include "Sound.h"
namespace a5ua
{
	class ImageFactory : public BasicFactory
	{
	public:
		ImageFactory(const TCHAR *database_name);
		Image *create(const TCHAR *name) const;
	};

	class SoundFactory : public BasicFactory
	{
	public:
		SoundFactory(const TCHAR *database_name);	
		Sound *create(const TCHAR *name) const;
	};
	
	class ResourceSet
	{
	public:
		ResourceSet(const TCHAR *image_database_name, const TCHAR *sound_database_name);
		Store &image_store();
		Store &sound_store();
	private:
		Store m_image_store;
		Store m_sound_store;
	};
}
最後にサンプルコードを示します。
【image_list.txt】を以下の内容としておきます。【sound_list.txt】は今回は使っていないので、空とします。

CODE:

test_image:image.bmp,4,2,2,64,64
これは、「image.bmpを2×2で4分割(それぞれのサイズは64×64)した画像のIDをtest_imageとする」という意味になります。image.bmpは写真でアップしたような画像です。実行結果のキャプチャもアップしています。

CODE:

#include 
#include "ResourceSet.h"

// サンプルコード用
namespace test
{
	struct Object
	{
	public:
		Object(int x, int y, a5ua::Handle image) : x(x), y(y), image(image)
		{

		}

		void move()
		{
			x = (x + 3) % 640;
		}

		void draw() const
		{
			int index = (x / 80) % image->division_number();
			image->draw(index, x, y, false);
		}
	private:
		int x;
		int y;
		a5ua::Handle image;
	};
}

#include 
#include 

int APIENTRY _tWinMain(HINSTANCE, HINSTANCE, LPTSTR, int)
{	
	ChangeWindowMode(TRUE);

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

	SetDrawScreen(DX_SCREEN_BACK);

	// データベースファイルを指定する
	a5ua::ResourceSet resource(_T("image_list.txt"), _T("sound_list.txt"));

	// 画像ハンドルを取得
	a5ua::Handle test_image = resource.image_store().get(_T("test_image"));

	// オブジェクトの配列
	std::vector v;

	for (int i = 0; i < 500; ++i) {
		// オブジェクトにパラメータを設定
		v.push_back(test::Object(GetRand(640 - 1), GetRand(480 - 1), test_image));
	}

	while (ProcessMessage() == 0 && ClearDrawScreen() == 0 && CheckHitKeyAll() == 0) {
		std::for_each(v.begin(), v.end(), std::mem_fun_ref(&test::Object::move));
		std::for_each(v.begin(), v.end(), std::mem_fun_ref(&test::Object::draw));
		ScreenFlip();
	}

	DxLib_End();

	return 0;
}
次回予定:その1とその2の実装を静的リンクライブラリとして作成することに挑戦します。
添付ファイル
image.jpg
image.jpg (434 バイト) 閲覧数: 77 回
ss.jpg
ss.jpg (25.06 KiB) 閲覧数: 69 回
最後に編集したユーザー a5ua on 2010年11月10日(水) 22:39 [ 編集 1 回目 ]

コメントはまだありません。