Selene で Lifegame 作ってみた。
Selene というゲームエンジンをちょっと触ってみた。例によってライフゲーム。
DirectX を直で扱うのは面倒なのでこういったライブラリはありがたいですね。
公式サイトは以下
http://selene-lue.halfmoon.jp/
XNA で作ったときと基本的な部分は変わらないのでソースコード載せようかどうか迷ったけど載せとく。ちょっと長いけど。しかも C++ 全然分かってないけど。
#include <Selene.h>
namespace Selene
{
const Point2DI SCREEN_SIZE( 500, 500 );
const Uint32 BOARD_WIDTH = 50;
const Uint32 BOARD_HEIGHT = 50;
const Uint32 CELL_SIZE = 10;
}
using namespace Selene;
int board[BOARD_WIDTH][BOARD_HEIGHT];
int _board[BOARD_WIDTH][BOARD_HEIGHT];
int glider_gun[BOARD_WIDTH][BOARD_HEIGHT] = {
// グライダーガンの二次元配列。長いから省略。
};
const wchar_t* MOUSE_BUTTON_STATE_TABLE[] = {
L"BUTTON_STATE_FREE", // マウスボタンは押されていない
L"BUTTON_STATE_PULL", // マウスボタンは離された
L"BUTTON_STATE_PUSH", // マウスボタンは押された
L"BUTTON_STATE_HOLD", // マウスボタンは押されつづけている
};
void drawSprite(Engine::Graphics::Simple::ISpriteRenderer* pSprite)
{
for (Uint32 i=0; i<BOARD_WIDTH; i++) {
for (Uint32 j=0; j<BOARD_HEIGHT; j++) {
// pos.x, pos.y, size.x, size.y
RectF dst = RectF( float(i*CELL_SIZE) , float(j*CELL_SIZE) , float(CELL_SIZE), float(CELL_SIZE) );
ColorF color = ColorF( 1.0f , 1.0f , 1.0f , 1.0f );
if (board[i][j] == 1) {
// red, green, blue, alpha
color = ColorF( 1.0f , 1.0f , 1.0f , 1.0f );
} else {
// red, green, blue, alpha
color = ColorF( 0.0f , 0.0f , 0.0f , 1.0f );
}
// 描画矩形 描画プライオリティ 描画色 不透明描画
pSprite->SquareRequest( dst, i, color, Engine::Graphics::State::AB_OPACITY );
}
}
}
void clickCell(Engine::Input::IMouse* pMouse) {
for (Uint32 i=0; i<BOARD_WIDTH; i++) {
for (Uint32 j=0; j<BOARD_HEIGHT; j++) {
if ( pMouse->GetPositionX() > (signed int)(i * CELL_SIZE)
&& pMouse->GetPositionX() <= (signed int)(i * CELL_SIZE + CELL_SIZE)
&& pMouse->GetPositionY() > (signed int)(j * CELL_SIZE)
&& pMouse->GetPositionY() <= (signed int)(j * CELL_SIZE + CELL_SIZE)
) {
board[i][j] = (board[i][j] == 0) ? 1 : 0;
}
}
}
}
void boardInit(wchar_t *src) {
if (src == L"glider_gun") {
for (Uint32 i=0; i<BOARD_WIDTH; i++) {
for (Uint32 j=0; j<BOARD_HEIGHT; j++) {
board[i][j] = glider_gun[j][i];
}
}
} else {
for (Uint32 i=0;i<BOARD_WIDTH;i++) {
for (Uint32 j=0;j<BOARD_HEIGHT;j++) {
board[i][j] = 0;
}
}
}
}
void boardCopy(wchar_t *dst) {
if (dst == L"_board") {
for (Uint32 i=0; i<BOARD_WIDTH; i++) {
for (Uint32 j=0; j<BOARD_HEIGHT; j++) {
_board[i][j] = board[i][j];
}
}
}
else {
for (Uint32 i=0; i<BOARD_WIDTH; i++) {
for (Uint32 j=0; j<BOARD_HEIGHT; j++) {
board[i][j] = _board[i][j];
}
}
}
}
void updateCell() {
boardCopy(L"_board");
for (Uint32 i=0; i<BOARD_WIDTH; i++) {
for (Uint32 j=0; j<BOARD_HEIGHT; j++) {
Uint32 count = 0;
if (i - 1 > 0 && j - 1 > 0 && _board[i - 1][ j - 1] == 1) count++;
if ( j - 1 > 0 && _board[i][j - 1] == 1) count++;
if (i + 1 < BOARD_WIDTH && j - 1 > 0 && _board[i + 1][j - 1] == 1) count++;
if (i - 1 > 0 && _board[i - 1][j] == 1) count++;
if (i + 1 < BOARD_WIDTH && _board[i + 1][j] == 1) count++;
if (i - 1 > 0 && j + 1 < BOARD_HEIGHT && _board[i - 1][j + 1] == 1) count++;
if ( j + 1 < BOARD_HEIGHT && _board[i][j + 1] == 1) count++;
if (i + 1 < BOARD_WIDTH && j + 1 < BOARD_HEIGHT && _board[i + 1][j + 1] == 1) count++;
if (_board[i][j] == 1 && (count == 2 || count == 3)) {
board[i][j] = 1;
} else if (_board[i][j] == 0 && count == 3) {
board[i][j] = 1;
} else {
board[i][j] = 0;
}
}
}
}
//
int WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR, int )
{
Engine::ICore* pCore = NULL;
Engine::Graphics::Simple::ISpriteRenderer* pSprite = NULL;
// エンジンアクセス用のコアを生成
// 複数作成は出来ない
#if defined(SLN_PROFILE)
if ( !InitializeEngine( L"Selene.Profile.dll" ) )
#elif defined(SLN_DEVELOP)
if ( !InitializeEngine( L"Selene.Develop.dll" ) )
#elif defined(SLN_DEBUG)
if ( !InitializeEngine( L"Selene.Debug.dll" ) )
#else
if ( !InitializeEngine( L"Selene.dll" ) )
#endif
{
goto EXIT;
}
pCore = CreateCore();
// コアの初期化
// この中にEngineの利用準備が集約
if ( !pCore->Initialize( L"Lifegame for Selene", SCREEN_SIZE, true, true ) )
{
goto EXIT;
}
// 入力デバイスシステム初期化
pCore->CreateInputManager();
// グラフィックシステムの初期化
// 描画に利用するドライバーを初期化して
// エンジンの描画エンジンを初期化します。
if ( !pCore->CreateGraphicsManager() )
{
goto EXIT;
}
// スプライト用インターフェイスの作成
pSprite = pCore->GetGraphicsManager()->CreateSpriteRenderer();
// Initialize board
boardInit(L"glider_gun");
Uint32 counter = 0;
// メインループ
// Seleneを利用する上でのメインループの書き方です
// ICore::DoEvent()でOSのイベント処理を行います。
while ( pCore->DoEvent( 60 ) ) // 引数はフレームレートです
{
counter += 1;
if (counter == 60) {
counter = 0;
}
// 画面のクリア
pCore->GetGraphicsManager()->Clear( true, false, ColorF(0.50f,0.50f,0.50f) );
// 入力デバイスの更新
pCore->GetInputManager()->Update();
// フレームの開始
pCore->FrameBegin();
// マウスインターフェイスを取得
Engine::Input::IMouse* pMouse = pCore->GetInputManager()->GetMouse();
// スプライトの描画
// スプライト内のキャッシュをリセット
pSprite->CacheReset();
if (MOUSE_BUTTON_STATE_TABLE[pMouse->GetStateL()] == L"BUTTON_STATE_PULL") {
clickCell(pMouse);
}
if (counter % 20 == 0 && MOUSE_BUTTON_STATE_TABLE[pMouse->GetStateR()] == L"BUTTON_STATE_FREE") {
updateCell();
}
drawSprite(pSprite);
// スプライトの描画
// キャッシュにたまったデータを一気に描画します
pSprite->CacheDraw();
// フレームの終了
pCore->FrameEnd();
// 画面の更新
pCore->GetGraphicsManager()->Present();
}
// 終了処理
// 終了時には生成したインターフェイスを解放し、
// 最後にICoreを解放してください。
EXIT:
SAFE_RELEASE( pCore );
FinalizeEngine();
return 0;
}