nirasan's tech blog

趣味や仕事の覚え書きです。Linux, Perl, PHP, Ruby, Javascript, Android, Cocos2d-x, Unity などに興味があります。

cocos2d-xでテトリス

はじめに

「cocos2d-x 入門」を一通り写経してみたので、練習のためにcocos2d-xでテトリスを作ってみました。

設計概要

落ちてくるブロックや、ブロックの入るフィールド、それらの基本的なロジックを、プレーンなC++クラスで実装し、
ブロックの表示、タッチの取得、ゲームのフローなどをcocos2d-xのシーンクラスで実装します。

設計詳細

ゲーム開始

ゲームのメインフローは GameScene クラスで処理しています。
アプリが起動すると、AppDelegate::applicationDidFinishLaunching から GameScene::init が呼ばれて、
フィールドの初期化、コントロールボタンの初期化、一つ目のブロックの作成と自動落下処理、が順に実行されます。

フィールド初期化

フィールドは Field クラスで抽象化され、初期化時にブロックが入るための2次元配列が用意されます。
空のフィールドを表現するため、GameScene::makeField で「□」を描画しておきます。

コントロールボタンの初期化

ブロックの左右移動と、左右回転を行うため、GameScene::makeControlButton で Menu と MenuItem を使ってボタンを作ります。

一つ目のブロックの作成と自動落下処理

GameScene::startGame でゲーム全体のロジックを処理する Game クラスが初期化され、ブロック作成と自動落下処理が開始されます。

ブロック作成

個々のブロックは Block クラスで、ブロックのまとまりは Chunk クラスとして実装します。
GameScene::makeChunk で Block と Chunk を作成し、同時に対応する CCLabelTTF を作成します。
Block と CCLabelTTF のひも付けは、Block.number に入れた数字を CCLabelTTF に setTag することで行います。

自動落下処理

Chunk を下に移動させる GameScene::moveUnder を schedule で一定時間毎に呼び出して自動落下を表現します。
ブロックの移動は、Chunk の座標を移動させた後に、各 Block について number から対応する CCLabelTTF を参照して、setPosition で表示位置を移動させます。
下にブロックがあったりフィールドの底についた場合などで落下できない場合は、ブロックをフィールドに設置、そろった列の削除、ゲームオーバー判定などが行われます。

ブロックの移動と回転

GameScene の tapMoveLeft, tapMoveRight, tapTurnLeft, tapTurnRight でそれぞれ、左移動、右移動、左回転、右回転を行います。
回転後の座標がフィールドの範囲外だったり、既にブロックが積んである場合は回転できません。

ブロックのフィールドへの設置

Game::copyBlocks で Chunk の Block を Field へコピーすることで、ブロックの設置を表現します。

そろった列の削除

Game::checkDeletableLines で削除できる列を取得し、GameScene::deleteLines で CCLabelTTF を削除すると、Game::deleteDeletableLines で Block も削除します。

ゲームオーバー判定

フィールドの上部にブロックが積まれると、GameScene::resetIfGameover で新しい GameScene が作成され、シーンの切り替えでリセットが実行されます。

おわりに

cocos2d-x と C++ が写経以外でほぼ初体験で、実装だけで1週間くらいかかりました。
何十分でテトリス作った、とか見ると若干へこみますが、とりあえずできてよかったです。