以下の本から、「重力加速度を使ったミニゲーム」の項目をCocos2d-xで実装してみたいと思います。
ゲームを作りながら楽しく学べるHTML5+CSS+JavaScriptプログラミング (NextPublishing)
- 作者: 田中賢一郎
- 出版社/メーカー: インプレスR&D
- 発売日: 2014/05/22
- メディア: オンデマンド (ペーパーバック)
- この商品を含むブログを見る
HTMLコード
「1-3 重力加速度」のミニゲーム、speed4.htmlを実装するとこんな感じです。
コードはこんな感じになります。
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>velocity</title> <script> var isFlying = false; var timer; var canvas; var posY = 300; var offcet = 0, speed = 10; var velocityY = -20, accelY = 5; function init() { canvas = document.getElementById("viewer").getContext("2d"); canvas.font = "24px sans-serif"; onkeydown = function () { isFlying = true; } onkeyup = function () { isFlying = false; } timer = setInterval(timer_tick, 100); } function timer_tick() { velocityY += isFlying ? -accelY : accelY; posY += velocityY; offcet += speed; if (offcet % 100 == 0) { speed += 2; } print(); } function print() { canvas.fillStyle = "green"; canvas.fillRect(0, 0, 600, 600); canvas.fillStyle = "brown"; canvas.beginPath(); canvas.moveTo(0, 0); for (var i = 0; i <= 600; i += 10) { var up = 200 + Math.sin((i + offcet) * Math.PI / 360) * 80; canvas.lineTo(i, up); if (i == 10 && posY < up) { clearInterval(timer); } } canvas.lineTo(600, 0); canvas.fill(); canvas.beginPath(); canvas.moveTo(0, 600); for (var i = 0; i <= 600; i += 10) { var down = 400 + Math.sin((i + offcet) * Math.PI / 340) * 80; canvas.lineTo(i, down); if (i == 10 && posY + 10> down) { clearInterval(timer); } } canvas.lineTo(620, 600); canvas.fill(); canvas.fillStyle = "white"; canvas.fillRect(10, posY, 10, 10); canvas.fillText(offcet, 500, 50); } </script> </head> <body onload="init()"> <canvas id="viewer" width="600" height="600" style="width:600px; height:600px"></canvas> </body> </html>
Cocos2d-x コード
作ってて思ったのですが、背景をFillで連続的に塗りつぶしたりすることはCocos2d-xの標準の操作ではちょっと難しみたいですね。なので背景と当たり判定は未実装となります。
こちらは上昇がタッチしているとき、タッチしていないときは落下の動きになります。
ヘッダー側の実装は以下の通り。
// HelloWorldScene.h #pragma once #include "cocos2d.h" class HelloWorld : public cocos2d::Scene { bool isFlying = false; double velocity_y = 0; double accel_y = 0.2; double score = 0; double elapsed_time = 0; static const int RECT_SPRITE_KEY; static const int SCORE_TEXT_KEY; static const double DEFAULT_VELOCITY_Y; public: static cocos2d::Scene* createScene(); virtual bool init(); static HelloWorld* create(); void update(float delta); };
実装側は以下の通りです。
// HelloWorldScene.cpp #include "HelloWorldScene.h" USING_NS_CC; const int HelloWorld::RECT_SPRITE_KEY = 0; const int HelloWorld::SCORE_TEXT_KEY = 1; const double HelloWorld::DEFAULT_VELOCITY_Y = 0; Scene* HelloWorld::createScene() { return HelloWorld::create(); } bool HelloWorld::init() { if (!Scene::init()) { return false; } double center = Director::getInstance()->getOpenGLView()->getFrameSize().height / 2; // 時期の表示 Sprite* rect_sprite = Sprite::create(); rect_sprite->setTag(RECT_SPRITE_KEY); rect_sprite->setTextureRect(Rect(0, 0, 10, 10)); rect_sprite->setPosition(10, center); rect_sprite->setAnchorPoint(Vec2::ANCHOR_MIDDLE_LEFT); this->addChild(rect_sprite); // スコア表示 Label* score_label = Label::createWithSystemFont("0", "Arial", 24); score_label->setTag(SCORE_TEXT_KEY); score_label->setPosition(Point(440, 290)); score_label->setString("0"); score_label->setAnchorPoint(Vec2::ANCHOR_MIDDLE_RIGHT); this->addChild(score_label); this->scheduleUpdate(); EventListenerTouchOneByOne* listner = EventListenerTouchOneByOne::create(); listner->onTouchBegan = [this](Touch *t, Event *e) { this->isFlying = true; return true; }; listner->onTouchEnded = [this](Touch *t, Event *e) { this->isFlying = false; }; this->getEventDispatcher()->addEventListenerWithSceneGraphPriority(listner, this); return true; } HelloWorld* HelloWorld::create() { HelloWorld *pRet = new(std::nothrow) HelloWorld(); if (pRet && pRet->init()) { pRet->autorelease(); return pRet; } else { delete pRet; pRet = nullptr; return nullptr; } } void HelloWorld::update(float delta) { auto sp = (Sprite*)this->getChildByTag(RECT_SPRITE_KEY); Point p = sp->getPosition(); this->velocity_y += this->isFlying ? this->accel_y : -this->accel_y; p.y += this->velocity_y; if (p.y > Director::getInstance()->getOpenGLView()->getFrameSize().height || p.y < 0) { p.y = Director::getInstance()->getOpenGLView()->getFrameSize().height / 2; this->velocity_y = DEFAULT_VELOCITY_Y; this->score = 0; this->elapsed_time = 0; } this->score += delta * 10 * 2.5; auto score_label = (Label*)this->getChildByTag(SCORE_TEXT_KEY); score_label->setString(std::to_string((int)this->score)); sp->setPosition(p); }