cocos2dx 3.6 如何写一个ting wings :动态
首先,几年前曾经玩过一段时间游戏开发,当时没用什么游戏引擎,整个开发过程很繁琐,但流程很清晰。现在各种引擎,遍地开花,开发方便,效果绚丽,但封装过于复杂,好多时候,是知其然而不知其所以然。还是要踏踏实实的走啊。
最近刚好离职,也不着急找工作,索性把以前未完成的想法,实现一下。
参考文章:
how-to-create-dynamic-textures-with-ccrendertexture-in-cocos2d-2-x
how-to-create-a-game-like-tiny-wings-with-cocos2d-2-x-part-1
how-to-create-a-game-like-tiny-wings-with-cocos2d-2-x-part-2
(译)如何使用CCRenderTexture来创建动态纹理
(译)如何制作一个类似tiny wings的游戏:第一部分
(译)如何制作一个类似tiny wings的游戏:第二部分(完)
如何使用CCRenderTexture创建动态纹理 Cocos2d-x 2.1.4
如何制作一个类似Tiny Wings的游戏 Cocos2d-x 2.1.4
如何制作一个类似Tiny Wings的游戏(2) Cocos2d-x 2.1.4
Cocos2d-x3.2与OpenGL渲染总结(一)Cocos2d-x3.2的渲染流程
这个教程,原版是ios下得,在最后一个链接,作者进行了相应的移植,使用的时cocos2dx 2.1.4。我在学习得过程中,发现cocos2dx的v2和v3版本,api变化比较大,核心的渲染过程也有了明显的差异。
在测试创建动态纹理时,发现作者在2.1.4版本下得代码,在3.6版本下没有实现渐变,和条纹的效果,经过几天时间的研究,整理出一份可以在3.6版本下,实现动态纹理的代码。为方便大家互相学习,将代码附在下文。
iOS Simulator Screen Shot 2015年7月15日 9.22.19.png
//
// TextureTestScene.h
// MyTestGame
//
// Created by shutup on 15-7-15.
//
//
#ifndef __MyTestGame__TextureTestScene__
#define __MyTestGame__TextureTestScene__
#include "cocos2d.h"
class TextureTestScene : public cocos2d::Layer
{
public:
// there's no 'id' in cpp, so we recommend returning the class instance pointer
static cocos2d::Scene* createScene();
// Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone
virtual bool init();
// implement the "static create()" method manually
CREATE_FUNC(TextureTestScene);
virtual void onEnter();
//单色渐变
cocos2d::Sprite *spriteWithColor(cocos2d::Color4F bgColor, float textureWidth, float textureHeight);
//渐变加条纹
cocos2d::Sprite * spriteWithColor1AndColor2(cocos2d::Color4F c1, cocos2d::Color4F c2, float textureWidth, float textureHeight, int nStripes);
//随机颜色
cocos2d::Color4F randombrightColor();
//生成背景
void genBackground();
//触屏事件
virtual bool onTouchBegan(cocos2d::Touch *touch,cocos2d::Event * event);
TextureTestScene();
virtual ~TextureTestScene();
//绘制条纹的回调
void drawStripes(cocos2d::Color4F c2, float textureWidth, float textureHeight, int nStripes);
//绘制渐变的回调
void drawGridient(float textureWidth, float textureHeight);
private :
cocos2d::Sprite* _background;
cocos2d::CustomCommand _customCommand;
};
#endif /* defined(__MyTestGame__TextureTestScene__) */
//
// TextureTestScene.cpp
// MyTestGame
//
// Created by shutup on 15-7-15.
//
//
#include "TextureTestScene.h"
USING_NS_CC;
TextureTestScene::TextureTestScene() {
// TODO Auto-generated constructor stub
_background = nullptr;
}
TextureTestScene::~TextureTestScene() {
// TODO Auto-generated destructor stub
}
bool TextureTestScene::init() {
if ( !Layer::init() )
{
return false;
}
return true;
}
Scene* TextureTestScene::createScene() {
auto scene = Scene::create();
auto layer = TextureTestScene::create();
scene->addChild(layer);
return scene;
}
void TextureTestScene::onEnter()
{
Layer::onEnter();
genBackground();
setTouchEnabled(true);
//设置为单点触摸
setTouchMode(Touch::DispatchMode::ONE_BY_ONE);
}
bool TextureTestScene::onTouchBegan(Touch *pTouches, Event *pEvent)
{
this->genBackground();
return true;
}
Color4F TextureTestScene::randombrightColor()
{
while(true)
{
float requiredBrightness = 192;
Color4B randomColor = Color4B(rand()%255,rand()%255,rand()%255,255);
if(randomColor.r > requiredBrightness || randomColor.g > requiredBrightness || randomColor.b >requiredBrightness)
{
return Color4F(randomColor);
}
}
return Color4F();
}
void TextureTestScene::genBackground()
{
if (_background)
{
_background->removeFromParentAndCleanup(true);
}
//渐变纹理
// Color4F bgColor = this->randombrightColor();
// _background = this->spriteWithColor(bgColor, 512, 512);
//条纹纹理
Color4F bgColor = this->randombrightColor();
Color4F color2 = this->randombrightColor();
int nStripes =((rand() % 4) + 1) * 2;
_background = this->spriteWithColor1AndColor2(bgColor, color2, 512, 512, nStripes);
Size winSize = Director::getInstance()->getVisibleSize();
_background->setPosition(Vec2(winSize.width / 2, winSize.height / 2));
this->addChild(_background, -1);
}
Sprite* TextureTestScene::spriteWithColor(Color4F bgColor,float textureWidth,float textureHeight) {
RenderTexture* rt = RenderTexture::create(textureWidth,textureHeight);
rt->beginWithClear(bgColor.r,bgColor.g,bgColor.b,bgColor.a);
//draw the gradient
_customCommand.init(_globalZOrder);
_customCommand.func = CC_CALLBACK_0(TextureTestScene::drawGridient, this,textureWidth,textureHeight);
auto renderer = Director::getInstance()->getRenderer();
renderer->addCommand(&_customCommand);
//do something more
// draw the noise
Sprite* noise = Sprite::create("Noise.png");
BlendFunc blendFunc = {GL_DST_COLOR,GL_ZERO};
noise->setBlendFunc(blendFunc);
noise->setPosition(Vec2(textureWidth/2,textureHeight/2));
noise->visit();
rt->end();
return Sprite::createWithTexture(rt->getSprite()->getTexture());
}
Sprite * TextureTestScene::spriteWithColor1AndColor2(Color4F c1, Color4F c2, float textureWidth, float textureHeight, int nStripes)
{
// 1: Create new RenderTexture
RenderTexture *rt = RenderTexture::create(textureWidth, textureHeight);
// 2: Call CCRenderTexture:begin
rt->beginWithClear(c1.r, c1.g, c1.b, c1.a);
// 3: Draw into the texture
_customCommand.init(_globalZOrder);
_customCommand.func = CC_CALLBACK_0(TextureTestScene::drawStripes, this,c2,textureWidth,textureHeight,nStripes);
auto renderer = Director::getInstance()->getRenderer();
renderer->addCommand(&_customCommand);
// Layer 4: Noise
Sprite *noise = Sprite::create("Noise.png");
BlendFunc blendFunc = {GL_DST_COLOR, GL_ZERO};
noise->setBlendFunc(blendFunc);
noise->setPosition(Vec2(textureWidth / 2, textureHeight / 2));
noise->visit();
// 4: Call CCRenderTexture:end
rt->end();
// 5: Create a new Sprite from the texture
return Sprite::createWithTexture(rt->getSprite()->getTexture());
}
void TextureTestScene::drawStripes(Color4F c2, float textureWidth, float textureHeight, int nStripes)
{
this->setGLProgram(GLProgramCache::getInstance()->getGLProgram(GLProgram::SHADER_NAME_POSITION_COLOR));
CC_NODE_DRAW_SETUP();
{
// Layer 1: Stripes
Point *vertices = new Point[nStripes * 6];
Color4F *colors = new Color4F[nStripes * 6];
int nVertices = 0;
float x1 = -textureHeight;
float x2;
float y1 = textureHeight;
float y2 = 0;
float dx = textureWidth / nStripes * 2;
float stripeWidth = dx / 2;
for (int i = 0; i < nStripes; ++i)
{
x2 = x1 + textureHeight;
vertices[nVertices] = Point(x1, y1);
colors[nVertices++] = Color4F(c2.r, c2.g, c2.b, c2.a);
vertices[nVertices] = Point(x1 + stripeWidth, y1);
colors[nVertices++] = Color4F(c2.r, c2.g, c2.b, c2.a);
vertices[nVertices] = Point(x2, y2);
colors[nVertices++] = Color4F(c2.r, c2.g, c2.b, c2.a);
vertices[nVertices] = vertices[nVertices - 2];
colors[nVertices++] = Color4F(c2.r, c2.g, c2.b, c2.a);
vertices[nVertices] = vertices[nVertices - 2];
colors[nVertices++] = Color4F(c2.r, c2.g, c2.b, c2.a);
vertices[nVertices] = Point(x2 + stripeWidth, y2);
colors[nVertices++] = Color4F(c2.r, c2.g, c2.b, c2.a);
x1 += dx;
}
// glEnableVertexAttribArray(GLProgram::VERTEX_ATTRIB_POSITION|GLProgram::VERTEX_ATTRIB_COLOR);
GL::enableVertexAttribs(GL::VERTEX_ATTRIB_FLAG_POSITION | GL::VERTEX_ATTRIB_FLAG_COLOR);
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_COLOR, 4, GL_FLOAT, GL_FALSE, 0, colors);
glBlendFunc(CC_BLEND_SRC, CC_BLEND_DST);
glDrawArrays(GL_TRIANGLES, 0, (GLsizei)nVertices);
//通知cocos2d-x 的renderer,让它在合适的时候调用这些OpenGL命令
// CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1, 3);
//如果出错了,可以使用这个函数来获取出错信息
CHECK_GL_ERROR_DEBUG();
CC_SAFE_DELETE_ARRAY(vertices);
CC_SAFE_DELETE_ARRAY(colors);
}
{float gradientAlpha = 0.7f;
Point vertices[4];
Color4F colors[4];
int nVertices =0;
vertices[nVertices] = Point(0,0);
colors[nVertices++] = Color4F(0,0,0,0);
vertices[nVertices] = Point(textureWidth,0);
colors[nVertices++] = Color4F(0,0,0,0);
vertices[nVertices] = Point(0,textureHeight);
colors[nVertices++] = Color4F(0,0,0,gradientAlpha);
vertices[nVertices] = Point(textureWidth,textureHeight);
colors[nVertices++] = Color4F(0,0,0,gradientAlpha);
//这句有点问题
// glEnableVertexAttribArray(GLProgram::VERTEX_ATTRIB_POSITION|GLProgram::VERTEX_ATTRIB_COLOR);
GL::enableVertexAttribs(GL::VERTEX_ATTRIB_FLAG_POSITION | GL::VERTEX_ATTRIB_FLAG_COLOR);
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION,2,GL_FLOAT,GL_FALSE,0,vertices);
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_COLOR,4,GL_FLOAT,GL_FALSE,0,colors);
glBlendFunc(CC_BLEND_SRC,CC_BLEND_DST);
glDrawArrays(GL_TRIANGLE_STRIP,0,(GLsizei)nVertices);
CHECK_GL_ERROR_DEBUG();
}
}
void TextureTestScene::drawGridient(float textureWidth, float textureHeight)
{
this->setGLProgram(GLProgramCache::getInstance()->getGLProgram(GLProgram::SHADER_NAME_POSITION_COLOR));
CC_NODE_DRAW_SETUP();
{
float gradientAlpha = 0.7f;
Point vertices[4];
Color4F colors[4];
int nVertices =0;
vertices[nVertices] = Point(0,0);
colors[nVertices++] = Color4F(0,0,0,0);
vertices[nVertices] = Point(textureWidth,0);
colors[nVertices++] = Color4F(0,0,0,0);
vertices[nVertices] = Point(0,textureHeight);
colors[nVertices++] = Color4F(0,0,0,gradientAlpha);
vertices[nVertices] = Point(textureWidth,textureHeight);
colors[nVertices++] = Color4F(0,0,0,gradientAlpha);
//这句有点问题
// glEnableVertexAttribArray(GLProgram::VERTEX_ATTRIB_POSITION|GLProgram::VERTEX_ATTRIB_COLOR);
GL::enableVertexAttribs(GL::VERTEX_ATTRIB_FLAG_POSITION | GL::VERTEX_ATTRIB_FLAG_COLOR);
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION,2,GL_FLOAT,GL_FALSE,0,vertices);
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_COLOR,4,GL_FLOAT,GL_FALSE,0,colors);
glBlendFunc(CC_BLEND_SRC,CC_BLEND_DST);
glDrawArrays(GL_TRIANGLE_STRIP,0,(GLsizei)nVertices);
CHECK_GL_ERROR_DEBUG();
}
}