PG日誌

各記事はブラウザの横幅を1410px以上にすると2カラムの見出しが表示されます。なるべく横に広げてみてください。

重力加速度をCocos2d-xで実装する

以下の本から、「重力加速度」の項目をCocos2d-xで実装してみたいと思います。

ゲームを作りながら楽しく学べるHTML5+CSS+JavaScriptプログラミング (NextPublishing)

ゲームを作りながら楽しく学べるHTML5+CSS+JavaScriptプログラミング (NextPublishing)

HTMLコード

「1-3 重力加速度」より、speed3.htmlを実装するとこんな感じです。頂点で重力を受けるようにY軸移動量が減少し、落下するときに加速します。

f:id:Takachan:20171223173322g:plain:h360

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <title>velocity</title>
    <script>
        var canvas;
        var posX = 0, posY = 600, velocityX = 5, velocityY = -20, accelY = 0.5;

        function init() {
            canvas = document.getElementById("viewer").getContext("2d");
            setInterval(timer_tick, 100);
        }

        function timer_tick() {
            posX += velocityX;
            velocityY += accelY;
            posY += velocityY;

            if (posX > 600) {
                posX = 0;
            }

            if (posY > 600) {
                velocityY = -20;
            }

            print();
        }

        function print() {
            canvas.fillStyle = "black";
            canvas.fillRect(0, 0, 600, 600);
            canvas.fillStyle = "white";
            canvas.fillRect(posX, posY, 10, 10);
            canvas.fill();
        }
    </script>
</head>

<body onload="init()">
    <canvas id="viewer" width="600" height="600" style="width:600px; height:600px"></canvas>
</body>

</html>

Cocos2d-x コード

ちょっと動きが違いますがCocos2d-xで実装するとこんな感じになります。

f:id:Takachan:20171223174411g:plain:h350

まぁわざわざ自分で書かないで、ゲームライブラリなので物理エンジンとかでもっといい感じになるのですが…

とりあえず、ヘッダー側の実装です。

// HelloWorldScene.h
#pragma once

#include "cocos2d.h"

class HelloWorld : public cocos2d::Scene
{
    double velocty_x = 2;
    double velocity_y = 5;
    double accel_y = 0.2;

    cocos2d::Sprite* rect_sprite;

    static const int RECT_SPRITE_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 double HelloWorld::DEFAULT_VELOCITY_Y = 5;

Scene* HelloWorld::createScene()
{
    return HelloWorld::create();
}

bool HelloWorld::init()
{
    if ( !Scene::init() )
    {
        return false;
    }

    Sprite* rect_sprite = Sprite::create();
    rect_sprite->setTextureRect(Rect(0, 0, 10, 10));
    rect_sprite->setPosition(0, 0);
    rect_sprite->setTag(RECT_SPRITE_KEY);
    rect_sprite->setAnchorPoint(Vec2::ANCHOR_MIDDLE_BOTTOM);

    this->addChild(rect_sprite);

    this->scheduleUpdate();

    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();
    p.x += this->velocty_x;
    p.y += this->velocity_y;
    this->velocity_y -= accel_y;

    if (p.x > Director::getInstance()->getOpenGLView()->getFrameSize().width)
    {
        p.x = 0;
    }

    if (p.y <= 0)
    {
        this->velocity_y = DEFAULT_VELOCITY_Y;
    }

    sp->setPosition(p);
}

まとめ

両方とも動きを表す部分は以下のようにほとんど同じですね。

// JavaScript
posX += velocityX;
velocityY += accelY;
posY += velocityY;

// C++
Point p = sp->getPosition();
p.x += this->velocty_x;
p.y += this->velocity_y;
this->velocity_y -= accel_y;