cocos2D-x ver 3.xの描画処理について

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
池田

cocos2D-x ver 3.xの描画処理について

#1

投稿記事 by 池田 » 10年前

こちらでの質問すみません。
こちらで質問することが適切かどうか判断出来ないため、不適切でしたら言って頂けますと助かります!

OpenGL系を軽く触った程度の知識しかないのですが、
cocos2D-xについて勉強しております。
Spriteという描画処理で戸惑っており、こちらを自作用に修正したいと考えております。

Dxライブラリなどでもそうだと思うのですが、
「毎フレーム画面をリセット」→「Draw系の関数を呼んで描画」
みたな流れだと思います。
↑このようにライブラリを改造したいです。

こういったことは可能なのでしょうか。
cocos2D-xだと描画処理をInitなどでセットして、
動かしたい時だけspriteの情報をgetByNameやらTagやらで
取得しないといけなく、直感的に修正したいです。

そこで無理やり描画用のクラスを作ってみたのですが、
処理落ちがひどくて何とか修正したいです。

何とかアドバイスを頂けないでしょうか。

コード:


■使うシーン例

void TitleScene::update( float delta ){
   
    // 画面を初期化
    this->removeAllChildren();

    TitleScene::Loop();
    TitleScene::Draw();
}

■DrawUtill.h

#ifndef __Game__DrawUtill__
#define __Game__DrawUtill__

#include "cocos2d.h"

USING_NS_CC;

class DrawUtill{
public:
    
    static int test;

    /******************** ロード関連 ********************/

    static std::string LoadImage( const std::string& filename );
    
    /******************** 画像描画関連 ********************/

    static void DrawMulti( cocos2d::Layer *layer, int x, int y, const std::string& filename, int sx, int sy, int cx, int cy, int color, int alpha, float scaleX, float scaleY, float angle );
    static void DrawScale( cocos2d::Layer *layer, int x, int y, const std::string& filename, int sx, int sy, int cx, int cy, int color, int alpha, float scaleX, float scaleY );
    static void DrawRotation( cocos2d::Layer *layer, int x, int y, const std::string& filename, int sx, int sy, int cx, int cy, int color, int alpha, float angle );
    static void DrawTexture( cocos2d::Layer *layer, int x, int y, const std::string& filename, int sx, int sy, int cx, int cy, int color, int alpha );

    /******************** 図形描画関連 ********************/

    static void DrawLine( cocos2d::Layer *layer, Point p1, Point p2, float width, int color, int alpha );
    static void DrawTriangle( cocos2d::Layer *layer, Point p1, Point p2, Point p3, int color, int alpha );
    static void DrawBox( cocos2d::Layer *layer, Point p1, float width, float height, int color, int alpha );

};

#endif /* defined(__Game__DrawUtill__) */

■DrawUtill.cpp

#include "DrawUtill.h"
#include <array>

USING_NS_CC;

/******************** ロード関連 ********************/

std::string DrawUtill::LoadImage( const std::string& filename )
{
    return filename;
}

/******************** 画像描画関連 ********************/

void DrawUtill::DrawMulti( cocos2d::Layer *layer, int x, int y, const std::string& filename, int sx, int sy, int cx, int cy, int color, int alpha, float scaleX, float scaleY, float angle )
{
    
    int r = color >> 16;
    int g = (color >> 8) & 0xff;
    int b = color & 0xff;
    
    //auto sprite = (Sprite*)layer->getChildByName( filename );
    
    BlendFunc blend = { GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA };
    
    auto sprite = Sprite::create( filename );
    layer->addChild( sprite, 0 );

    sprite->setPosition( x, y );
    sprite->setTextureRect( Rect( sx, sy, cx, cy ) );
    sprite->setColor( Color3B( r, g, b ) );
    sprite->setOpacity( alpha );
    sprite->setScaleX( scaleX );
    sprite->setScaleY( scaleY );
    sprite->setRotation( angle );
    sprite->setBlendFunc( blend );
}

void DrawUtill::DrawScale( cocos2d::Layer *layer, int x, int y, const std::string& filename, int sx, int sy, int cx, int cy, int color, int alpha, float scaleX, float scaleY )
{
    DrawMulti( layer, x, y, filename, sx, sy, cx, cy, color, alpha, scaleX, scaleY, 0 );
}

void DrawUtill::DrawRotation( cocos2d::Layer *layer, int x, int y, const std::string& filename, int sx, int sy, int cx, int cy, int color, int alpha, float angle )
{
    DrawMulti( layer, x, y, filename, sx, sy, cx, cy, color, alpha, 1.0f, 1.0f, angle );
}

void DrawUtill::DrawTexture( cocos2d::Layer *layer, int x, int y, const std::string& filename, int sx, int sy, int cx, int cy, int color, int alpha )
{
    DrawMulti( layer, x, y, filename, sx, sy, cx, cy, color, alpha, 1.0f, 1.0f, 0 );
}

/******************** 図形描画関連 ********************/

void DrawUtill::DrawLine( cocos2d::Layer *layer, Point p1, Point p2, float weight, int color, int alpha )
{
    // 各種色を個別に取得
    float r = (float)( color >> 16 ) / 255.0f;
    float g = (float)( (color >> 8) & 0xff ) / 255.0f;
    float b = (float)( color & 0xff ) / 255.0f;
    float alp = (float)alpha / 255.0f;

    // 描画用のノードを作成
    DrawNode* drawNode = DrawNode::create();
    drawNode->setPosition( Point(0.0f, 0.0f) );
    layer->addChild(drawNode);
    
    // 描画
    BlendFunc blend = { GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA };
    drawNode->setBlendFunc( blend );
    drawNode->drawSegment( p1, p2, weight, Color4F( r, g, b, alp ) );

}

void DrawUtill::DrawTriangle( cocos2d::Layer *layer, Point p1, Point p2, Point p3, int color, int alpha )
{
    // 各種色を個別に取得
    float r = (float)( color >> 16 ) / 255.0f;
    float g = (float)( (color >> 8) & 0xff ) / 255.0f;
    float b = (float)( color & 0xff ) / 255.0f;
    float alp = (float)alpha / 255.0f;
    
    // 描画用のノードを作成
    DrawNode* drawNode = DrawNode::create();
    drawNode->setPosition( Point(0.0f, 0.0f) );
    layer->addChild(drawNode);
    
    // 描画
    BlendFunc blend = { GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA };
    drawNode->setBlendFunc( blend );
    drawNode->drawTriangle( p1, p2, p3, Color4F( r, g, b, alp ));
}

void DrawUtill::DrawBox( cocos2d::Layer *layer, Point p1, float width, float height, int color, int alpha )
{
    
    int r = color >> 16;
    int g = (color >> 8) & 0xff;
    int b = color & 0xff;
  
    // 画面サイズ
    Size screenSize = Director::getInstance()->getVisibleSize();
    // 描画用のノードを作成
    DrawNode* drawNode = DrawNode::create();
    drawNode->setPosition(Point(0.0f, 0.0f));
    layer->addChild(drawNode);
    
    // 描画
    std::array<Point, 4> vertexes = {
        Point(50, 50),
        Point(screenSize.width - 50, 50),
        Point(screenSize.width - 50, screenSize.height - 50),
        Point(50, screenSize.height - 50),
    };
    
    float weight = 5.0f;
    BlendFunc blend = { GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA };
    drawNode->setBlendFunc( blend );
    drawNode->drawPolygon(vertexes.data(), vertexes.size(), Color4F::WHITE, weight, Color4F::RED);

}

■テクスチャーの作り方

cocos2d::Texture2D *tex =  Director::getInstance()->getTextureCache()->addImage( "card_back.png" );
auto sprite = Sprite::createWithTexture( tex );


アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: cocos2D-x ver 3.xの描画処理について

#2

投稿記事 by softya(ソフト屋) » 10年前

Cocos2d-xのフレームワークに反するのでDxライブラリの様に改造することはお勧めできません(描画の順番処理など最適化から外れます)。
【内容修正】
SceneやLayerなどを継承したクラスでupdate()からメンバ変数に作っておいたSpriteのクラス変数に操作を掛ければ毎フレーム操作できますよ。
DrawはCocos2d-xに任せたままにします。

【追記】
TitleScene::Loop();
TitleScene::Draw();
肝心のコードがないのですがupdateにLoop()は危険な気がします。処理落ちの原因の1つだと思います。
それと提示されたコード全体を見るとオブジェクト指向ではなくC言語の手続き指向で組みたいものと思ったのですが違いますか?

【その他気になること】
DrawLine()などなどaddChildしまくってますが毎フレームされるんでしょうか? removeChildしてますか?(累積して処理落ちします)
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

池田

Re: cocos2D-x ver 3.xの描画処理について

#3

投稿記事 by 池田 » 10年前

【追記用】
説明不足ですみません。
Loop用のVirtual関数をoverrideしており、
Loop関数が何回も回っているわけでは御座いません。

ただの関数をupdateで呼び出しているのですが、
こちら問題がありそうでしょうか。
TitleScene::がなくてわかりにくくてすみません。。。

C言語を使っているのですが、可能であればオブジェクト指向で組みたいです。
プログラムが独学なので、かなり書き方がメチャクチャです・・・。
見づらいもので申し訳ないです(汗)

そうなのですが・・・removeしてないです!
一度コメントアウトしてみます。

コード:

void TitleScene::Loop(){
    
    a++;
    if( a>=700 ) a = 0;
    
    static int cnt = 0;
    cnt++;
    if( cnt >= 180 ){
        cnt = 0;
        
        // 効果音を鳴らす
        //SoundUtill::PlaySE( seTest );

    }
}
【ご返答】

アドバイスありがとうございます!
周りにcocos触っている人がいなくて助かりました!!

何度も質問してしまい申し訳ないのですが、2点疑問に感じていることが御座います。

①描画における画像の扱い方について

描画関数にフラグを持たせて下記のように修正してみました。
1024×1024のspriteを2つ描画してるだけなのですが、FPSが30代まで落ちてしまいます。

画像管理の問題だと思うのですが、cocos2Dではどのように画像を管理したほうが良いのでしょうか。
画像が2のべき乗でなくても、自動的に判断してくれるみたいなのですが、
色々なサイトや本を見てみると、個別の画像をべき乗ではないもので管理しているものが殆どでした。

AppStoreなどででているアプリのリソース素材を見てみたところ、
テクスチャアトラスを使っているものもあったのですが、
小さいサイズの画像をそのまま使っているものが多かったです。

小さいサイズの画像を使う場合、現在の描画関数の切り取り位置を
指定する機能自体がない方が、使いやすいと思うのですが、如何なのでしょうか。
※キャラクターのアニメーションなどはしない場合に限ります。

本とかWebをかなり見てみたのですが、こういった考え方を見つけることが出来なくて。。。

②Spriteについて
Dxライブラリなどだと、1枚の画像に複数入れて、テクスチャーを保持する変数を1つだけ用意するかと思います。
cocos2dだと1枚の画像に対して、オブジェクト分のSpriteを用意するイメージで問題ないでしょうか。

例えば、ボタンで「ステージセレクト」、「オプション」があったとしたら、それぞれ画像をわけて、
Spriteを2つ用意して個別に処理みたいなイメージです。

コード:


■使うシーン例

class TitleScene : public MyScene
{

public:
    
    // 素材用
    static Texture texBack;
    static Texture texObject;
	
	~ 略 ~
	
}

void TitleScene::update( float delta ){
   
    // 画面を初期化
    // this->removeAllChildren();

    TitleScene::Loop();
    TitleScene::Draw();

}

void TitleScene::Draw(){

    // 背景
    DrawUtill::DrawTexture( this, WIN_W/2, WIN_H/2, texBack, 0, 0, 640, 960, 0xffffff, 255, true );
    DrawUtill::DrawTexture( this, WIN_W/2, WIN_H/2-150, texObject, 0, 0, 560, 140, 0xffffff, 255, true );
    
}


■DrawUtill.h

#ifndef __Game__DrawUtill__
#define __Game__DrawUtill__

#include "cocos2d.h"

USING_NS_CC;

class DrawUtill{
public:
    
    static int test;

    /******************** ロード関連 ********************/

    static Sprite* LoadImage( cocos2d::Layer *layer, const std::string& filename, bool flag );
    
    /******************** 画像描画関連 ********************/

    static void DrawMulti( cocos2d::Layer *layer, int x, int y, Sprite *sprite, int sx, int sy, int cx, int cy, int color, int alpha, float scaleX, float scaleY, float angle, bool flag );
    static void DrawScale( cocos2d::Layer *layer, int x, int y, Sprite *sprite, int sx, int sy, int cx, int cy, int color, int alpha, float scaleX, float scaleY, bool flag );
    static void DrawRotation( cocos2d::Layer *layer, int x, int y, Sprite *sprite, int sx, int sy, int cx, int cy, int color, int alpha, float angle, bool flag );
    static void DrawTexture( cocos2d::Layer *layer, int x, int y, Sprite *sprite, int sx, int sy, int cx, int cy, int color, int alpha, bool flag );

    /******************** 図形描画関連 ********************/

    static void DrawLine( cocos2d::Layer *layer, Point p1, Point p2, float width, int color, int alpha );
    static void DrawTriangle( cocos2d::Layer *layer, Point p1, Point p2, Point p3, int color, int alpha );
    static void DrawBox( cocos2d::Layer *layer, Point p1, float width, float height, int color, int alpha );

};

#endif /* defined(__Game__DrawUtill__) */

■DrawUtill.cpp

#include "DrawUtill.h"
#include <array>

USING_NS_CC;
BlendFunc blend = { GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA }; // 後々メソッドに追加

/******************** ロード関連 ********************/

Sprite* DrawUtill::LoadImage( cocos2d::Layer *layer, const std::string& filename, bool flag )
{
    Sprite *sprite = Sprite::create( filename );
    sprite->setVisible( flag );
    layer->addChild( sprite );
    return sprite;
}

/******************** 画像描画関連 ********************/

void DrawUtill::DrawMulti( cocos2d::Layer *layer, int x, int y, Sprite *sprite, int sx, int sy, int cx, int cy, int color, int alpha, float scaleX, float scaleY, float angle, bool flag )
{
    
    int r = color >> 16;
    int g = (color >> 8) & 0xff;
    int b = color & 0xff;
    
    //auto sprite = (Sprite*)layer->getChildByName( filename );
    
    
    sprite->setVisible( flag );
    sprite->setPosition( x, y );
    sprite->setTextureRect( Rect( sx, sy, cx, cy ) );
    sprite->setColor( Color3B( r, g, b ) );
    sprite->setOpacity( alpha );
    sprite->setScaleX( scaleX );
    sprite->setScaleY( scaleY );
    sprite->setRotation( angle );
    sprite->setBlendFunc( blend );
    
}

void DrawUtill::DrawScale( cocos2d::Layer *layer, int x, int y, Sprite *sprite, int sx, int sy, int cx, int cy, int color, int alpha, float scaleX, float scaleY, bool flag )
{
    DrawMulti( layer, x, y, sprite, sx, sy, cx, cy, color, alpha, scaleX, scaleY, 0, flag );
}

void DrawUtill::DrawRotation( cocos2d::Layer *layer, int x, int y, Sprite *sprite, int sx, int sy, int cx, int cy, int color, int alpha, float angle, bool flag )
{
    DrawMulti( layer, x, y, sprite, sx, sy, cx, cy, color, alpha, 1.0f, 1.0f, angle, flag );
}

void DrawUtill::DrawTexture( cocos2d::Layer *layer, int x, int y, Sprite *sprite, int sx, int sy, int cx, int cy, int color, int alpha, bool flag )
{
    DrawMulti( layer, x, y, sprite, sx, sy, cx, cy, color, alpha, 1.0f, 1.0f, 0, flag );
}

/******************** 図形描画関連 ********************/

void DrawUtill::DrawLine( cocos2d::Layer *layer, Point p1, Point p2, float weight, int color, int alpha )
{
    /*
    // 各種色を個別に取得
    float r = (float)( color >> 16 ) / 255.0f;
    float g = (float)( (color >> 8) & 0xff ) / 255.0f;
    float b = (float)( color & 0xff ) / 255.0f;
    float alp = (float)alpha / 255.0f;

    // 描画用のノードを作成
    DrawNode* drawNode = DrawNode::create();
    drawNode->setPosition( Point(0.0f, 0.0f) );
    layer->addChild(drawNode);
    
    // 描画
    BlendFunc blend = { GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA };
    drawNode->setBlendFunc( blend );
    drawNode->drawSegment( p1, p2, weight, Color4F( r, g, b, alp ) );
    */

}

void DrawUtill::DrawTriangle( cocos2d::Layer *layer, Point p1, Point p2, Point p3, int color, int alpha )
{
    /*
    // 各種色を個別に取得
    float r = (float)( color >> 16 ) / 255.0f;
    float g = (float)( (color >> 8) & 0xff ) / 255.0f;
    float b = (float)( color & 0xff ) / 255.0f;
    float alp = (float)alpha / 255.0f;
    
    // 描画用のノードを作成
    DrawNode* drawNode = DrawNode::create();
    drawNode->setPosition( Point(0.0f, 0.0f) );
    layer->addChild(drawNode);
    
    // 描画
    BlendFunc blend = { GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA };
    drawNode->setBlendFunc( blend );
    drawNode->drawTriangle( p1, p2, p3, Color4F( r, g, b, alp ));
     */
}

void DrawUtill::DrawBox( cocos2d::Layer *layer, Point p1, float width, float height, int color, int alpha )
{
    
    /*
    int r = color >> 16;
    int g = (color >> 8) & 0xff;
    int b = color & 0xff;
  
    // 画面サイズ
    Size screenSize = Director::getInstance()->getVisibleSize();
    // 描画用のノードを作成
    DrawNode* drawNode = DrawNode::create();
    drawNode->setPosition(Point(0.0f, 0.0f));
    layer->addChild(drawNode);
    
    // 描画
    std::array<Point, 4> vertexes = {
        Point(50, 50),
        Point(screenSize.width - 50, 50),
        Point(screenSize.width - 50, screenSize.height - 50),
        Point(50, screenSize.height - 50),
    };
    
    float weight = 5.0f;
    BlendFunc blend = { GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA };
    drawNode->setBlendFunc( blend );
    drawNode->drawPolygon(vertexes.data(), vertexes.size(), Color4F::WHITE, weight, Color4F::RED);
    */

}

■テクスチャーの作り方

cocos2d::Texture2D *tex =  Director::getInstance()->getTextureCache()->addImage( "card_back.png" );
auto sprite = Sprite::createWithTexture( tex );


池田

Re: cocos2D-x ver 3.xの描画処理について

#4

投稿記事 by 池田 » 10年前

誤字です。
そうなのですが → そうなのですか で御座います。
スレ汚し申し訳ないです!

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: cocos2D-x ver 3.xの描画処理について

#5

投稿記事 by softya(ソフト屋) » 10年前

コードは後ほど見させていただきます。
質問だけ答えます

・テクスチャアトラスの使用について
スマホなどのGPUメモリの制限に引っかからなければ結構大雑把でよいです。
引っかかりそうな場合は使用しないと話になりません。
shoeboxと言う無料ツールがあるので、これを使いテクスチャアトラスを作成しましょう。

②Spriteについて
CocoStudioのAnimetionStudioでアニメパターンを管理できます。テクスチャアトラスも作成します。
アニメパターンに名前を付けれるので、これでアニメパターンを呼び出します。
移動は自前でやって、アニメだけ自動再生とか1周毎にトリガ発生させてアニメ切り替えとか色々出来ます。
研究してみてください。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

池田

Re: cocos2D-x ver 3.xの描画処理について

#6

投稿記事 by 池田 » 10年前

ありがとうございます!
ソースを見て頂ける可能性があるというだけで助かります。

ゲームの規模としてはよくあるカジュアルゲーム規模で、そこまで凄いものを想定しておりません。
「タイトル→ステージセレクト→ゲーム→リザルト+ヘルプ」の画面遷移程度で御座います。

今まで試したことないのですが、個別に画像を管理しようと思うのですが、
描画関数は切り取り位置とか設定できなくても大丈夫そうでしょうか?

おそらくSpriteをロードする時に、切り取り位置を設定出来たほうが使いやすいのかなーと。

研究してみます!!!

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: cocos2D-x ver 3.xの描画処理について

#7

投稿記事 by softya(ソフト屋) » 10年前

ソースを見ても特に問題点はわかりませんでした。毎回設定してレンダーステートなどの負荷がかかるかはCocos2d-x側のソースコードまで追っかけてないので不明です。
素直に組んだ場合と比較してみるしか無いと思います。
私の感想としてはCocos2d-xよりもコードを追うことが難しくなっている印象を持ちました。


>ゲームの規模としてはよくあるカジュアルゲーム規模で、そこまで凄いものを想定しておりません。
>今まで試したことないのですが、個別に画像を管理しようと思うのですが、
>描画関数は切り取り位置とか設定できなくても大丈夫そうでしょうか?

よく有るカジュアルゲームと言われてもそれぞれ違いますので何とも言えません。

> おそらくSpriteをロードする時に、切り取り位置を設定出来たほうが使いやすいのかなーと。

それがテクスチャアトラスだと思います。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

閉鎖

“C言語何でも質問掲示板” へ戻る