はかせのラボ

私の頭の中を書いていく雑記ブログです

DirectX データ読み込み

あいさつ

11月最終日、皆様いかがお過ごしでしょうか。
私はいつも通り開発しております。はかせです。
今回はCSVデータを読み込んでみたです。

なぜデータ読み込み?

ゲームは大量のデータを扱います。
そのすべてのデータをプログラムに埋め込むのは
現実的ではないですし、よろしくありません。

大体が何かしらのフォーマットで外部でデータを管理し読み込んで使います。
私は今回Google SpreadSheetを使ってCSV形式で管理したいと思います。
理由はオンラインでどこでも編集出来て共有もしやすいからです。

データ読み込み実装

今回はこのデータを読み込んでみたいと思います。
f:id:hakase0274:20181130231426p:plain
c++でのファイル読み込みはifstreamというものを使って行うそうです。

//タグ
enum Tag
{
	PlayerTag = 0,
	EnemyTag = 1,
	PlayerBullet = 2,
	EnemyBullet = 3,
};

//データ構造体
struct DATA
{
	std::string Name;
	DirectX::XMFLOAT3 StartPos;
	double HP;
	Tag Tag;
};

//ファイルを読み込みデータ構造体に格納
vector<DATA> LoadData(const char* filePath)
{
	//返す配列
	vector<DATA> DataTable;

	//ファイルオープン
	ifstream fileStream(filePath);
	if (!fileStream)
	{
		cout << "ファイルオープン失敗" << endl;
		return DataTable;
	}
	
	//何行目か
	int i = 0;

	//ファイルが終わるまで読み込み
	while (!fileStream.eof())
	{
		i++;
		string bufferString;
		fileStream >> bufferString;
		//1行目は列名でデータではないためスキップ
		if (i <= 1) continue;

		//データを項目ごとに抽出
		istringstream stringStream(bufferString);
		vector<string> datas;
		string tmp;
		//カンマ区切りでデータを切り分け
		while (getline(stringStream, tmp, ','))
		{
			datas.push_back(tmp);
		}
		//切り分けたデータを構造体に格納
		DATA data;
		data.Name = datas[0];
		data.StartPos.x = strtof(datas[1].c_str(), NULL);
		data.StartPos.y = strtof(datas[2].c_str(), NULL);
		data.StartPos.z = strtof(datas[3].c_str(), NULL);
		data.HP = strtod(datas[4].c_str(), NULL);
		auto tag = datas[5];
		if (tag == "Player")
		{
			data.Tag = PlayerTag;
		}
		if (tag == "Boss")
		{
			data.Tag = EnemyTag;
		}
		DataTable.push_back(data);
	}
	//ファイルクローズ
	fileStream.close();
	return DataTable;
}

実行結果が
f:id:hakase0274:20181130231632p:plain

無事データを読み込めたようです。

ソースコード

今回作ったものは使い捨てのテスト用なのでgithubではなく
ここに全文上げようと思います。
(コピペしやすいようデータ型や名前は合わせてます)

#pragma once
#include<stdio.h>
#include <string>
#include <vector>
#include<DirectXMath.h>

enum Tag
{
	PlayerTag = 0,
	EnemyTag = 1,
	PlayerBullet = 2,
	EnemyBullet = 3,
};


struct DATA
{
	std::string Name;
	DirectX::XMFLOAT3 StartPos;
	double HP;
	Tag Tag;
};
#include "Main.h"
#include <iostream>
#include <fstream>
#include <sstream>  

using namespace std;

vector<DATA> LoadData(const char* filePath);

int main()
{
	//データ読み込み
	vector<DATA> DataTable = LoadData("Data/TestData.csv");
	//読み込んだデータ表示
	for(auto data:DataTable)
	{
		cout << data.Name << endl;
		cout << to_string(data.StartPos.x) << "," << to_string(data.StartPos.y) << "," << to_string(data.StartPos.z) << "," << endl;
		cout << data.HP <<endl;
		cout << data.Tag << endl;
		cout << endl;
	}

	getchar();
}

//ファイルを読み込みデータ構造体に格納
vector<DATA> LoadData(const char* filePath)
{
	//返す配列
	vector<DATA> dataTable;

	//ファイルオープン
	ifstream fileStream(filePath);
	if (!fileStream)
	{
		cout << "ファイルオープン失敗" << endl;
		return dataTable;
	}
	
	//何行目か
	int i = 0;

	//ファイルが終わるまで読み込み
	while (!fileStream.eof())
	{
		i++;
		string bufferString;
		fileStream >> bufferString;
		//1行目は列名でデータではないためスキップ
		if (i <= 1) continue;

		//データを項目ごとに抽出
		istringstream stringStream(bufferString);
		vector<string> datas;
		string tmp;
		//カンマ区切りでデータを切り分け
		while (getline(stringStream, tmp, ','))
		{
			datas.push_back(tmp);
		}
		//切り分けたデータを構造体に格納
		DATA data;
		data.Name = datas[0];
		data.StartPos.x = strtof(datas[1].c_str(), NULL);
		data.StartPos.y = strtof(datas[2].c_str(), NULL);
		data.StartPos.z = strtof(datas[3].c_str(), NULL);
		data.HP = strtod(datas[4].c_str(), NULL);
		auto tag = datas[5];
		if (tag == "Player")
		{
			data.Tag = PlayerTag;
		}
		if (tag == "Boss")
		{
			data.Tag = EnemyTag;
		}
		dataTable.push_back(data);
	}
	//ファイルクローズ
	fileStream.close();
	return dataTable;
}

あとがき

ファイル操作は大体どの言語も変わらないので、
大して詰まることなくできました。

今回はファイル読み込みのテストということで
空のコンソールアプリケーションで作ってみました。

次回はこれをモジュール化し、
私のゲームに組み込んでみたいと思います。

それでは今回はこの辺でノシ