cocos2dx 实现果冻,刀光等效果
随着cocos2dx的广泛应用,大量的游戏会有一些特效效果,比如割绳子中的绳子软体效果,切水果的刀光,扑鱼达人3的开场动画,闪电链效果等等,像这些高级效果,其实在cocos2dx的示例程序有些类似的影子,但是没有具体实现。比如说box2d的web效果,他就是实现果冻效果的一个原型,shader中的模糊,变色等等,目前市面上的一些高级效果可以在cocos2dx的sample中找到一些简单实现,但是还需要自己加工下。下面作为小白的我也要叙述下一些效果的实现原理,说错的地方,望各位不要喷啊~。
首先说一下果冻效果,果冻它是变形的,而且碰撞的时候,在碰撞点有挤压,所以呢,实现它还得用物理引擎,这里我用的是box2d。具体的做法实现可以参考l示例程序中的box2d web效果,这里就不多讲了。然后要让果冻随意变形,这个可以绘制一个4个顶点的网格然后附上对应的纹理,然后随着box2d的4个刚体改变顶点的位置,就可以看到变形效果啦。
b2CircleShape shape;
shape.m_radius=4;
b2BodyDef bd;
bd.type = b2_dynamicBody;
bd.position.Set(-6.0f, 6.0f);
m_bodies[0] = m_world->CreateBody(&bd);
m_bodies[0]->CreateFixture(&shape, 5.0f); m_bodies[0]->SetBullet(true);
bd.position.Set(4.0f, 4.0f);
m_bodies[1] = m_world->CreateBody(&bd);
m_bodies[1]->CreateFixture(&shape, 5.0f); m_bodies[1]->SetBullet(true);
bd.position.Set(6.0f, 14.0f);
m_bodies[2] = m_world->CreateBody(&bd);
m_bodies[2]->CreateFixture(&shape, 5.0f); m_bodies[2]->SetBullet(true);
bd.position.Set(-4.0f, 16.0f);
m_bodies[3] = m_world->CreateBody(&bd);
m_bodies[3]->CreateFixture(&shape, 5.0f); m_bodies[3]->SetBullet(true);
b2Vec2 v1=m_bodies[0]->GetWorldCenter();
b2Vec2 v2=m_bodies[1]->GetWorldCenter();
b2Vec2 v3=m_bodies[2]->GetWorldCenter();
b2Vec2 v4=m_bodies[3]->GetWorldCenter();
adjust(v1,v3); adjust(v2,v4);
Vertex Vertices[] = {
// Front
{{480+v1.x*32,v1.y*32, 0}, {1, 1, 0, 1}, {1, 0}},
{{480+v2.x*32,v2.y*32, 0}, {1, 1, 1,1}, {1, 1}},
{{480+v3.x*32,v3.y*32, 0}, {1, 1, 1, 1}, {0, 1}},
{{480+v4.x*32,v4.y*32, 0}, {0, 1, 1, 1}, {0, 0}}
};
刀光效果一般根据移动的轨迹动态计算出网格,然后给纹理,或者上色什么的。
看过shader示例的 应该都感觉很炫吧,没错,这个东东确实可以实现很多高级效果,如果你算法底子好,那么可以搞出一些 绚丽的 画面。
以上种种都需要有opengl基础额,所以呢,想实现高级效果的朋友不妨发点时间看看opengl 的知识,而且对将来实现3d场景也有很多益处。
好了,先讲到这里了。 下面贴出果冻的全部实现代码:
//HelloWorld.h
class HelloWorld : public cocos2d::Layer
{
public:
virtual bool init();
void onEnter();
void update(float dt);
void onDraw();
CustomCommand _customCommand;
CREATE_FUNC(HelloWorld);
Vec2 m_mouseWorld;
b2MouseJoint* m_mouseJoint;
b2Body* m_groundBody;
GLESDebugDraw *m_debugDraw;
b2World* m_world;
CCTexture2D* texture2d;
GLuint vertexBuffer;
GLuint indexBuffer;
GLProgram * pg;
b2Body* m_bodies[8];
void adjust(b2Vec2 &v1,b2Vec2 &v2);
bool onTouchBegan(Touch* touch, Event* event);
void onTouchMoved(Touch* touch, Event* event);
void onTouchEnded(Touch* touch, Event* event);
};
class QueryCallback : public b2QueryCallback
{
public:
QueryCallback(const b2Vec2& point)
{
m_point = point;
m_fixture = nullptr;
}
{
b2Body* body = fixture->GetBody();
if (body->GetType() == b2_dynamicBody)
{
bool inside = fixture->TestPoint(m_point);
if (inside)
{
m_fixture = fixture;
return false;
}
}
return true;
}
b2Fixture* m_fixture;
};
Scene* HelloWorld::createScene()
{
// 'scene' is an autorelease object
auto scene = Scene::create();
// 'layer' is an autorelease object
auto layer = HelloWorld::create();
scene->addChild(layer);
return scene;
}
void HelloWorld::draw(Renderer *renderer, const Mat4 &transform, uint32_t flags)
{
//
// IMPORTANT:
// This is only for debug purposes
// It is recommend to disable it
//
Layer::draw(renderer, transform, flags);
GL::enableVertexAttribs( cocos2d::GL::VERTEX_ATTRIB_FLAG_POSITION );
Director* director = Director::getInstance();
CCASSERT(nullptr != director, "Director is null when seting matrix stack");
director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
_customCommand.init(_globalZOrder);
_customCommand.func = CC_CALLBACK_0(HelloWorld::onDraw, this);
renderer->addCommand(&_customCommand);
#endif
}
void HelloWorld::adjust(b2Vec2 &v1,b2Vec2 &v2)
{
float dx1=v2.x-v1.x;
b2Vec2 midpos=b2Vec2((v2.x+v1.x)/2,(v1.y+v2.y)/2);;
if(dx1==0)
{
v1=b2Vec2(v1.x,midpos.y-abs(v1.y-v2.y)/2-4);
v2=b2Vec2(v1.x,midpos.y-abs(v1.y-v2.y)/2+4);
}
else
{
float k1=(v2.y-v1.y)/dx1;
float nxoff=midpos.x-abs(v1.x-v2.x)/2-4;
float pxoff=midpos.x+abs(v1.x-v2.x)/2+4;
float ny1=k1*(nxoff-v1.x)+v1.y;
float ny2=k1*(pxoff-v1.x)+v1.y;
v1=b2Vec2(nxoff,ny1);
v2=b2Vec2(pxoff,ny2);
}
}
void HelloWorld::onDraw()
{
Director* director = Director::getInstance();
CCASSERT(nullptr != director, "Director is null when seting matrix stack");
oldMV = director->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW, _modelViewMV);
m_world->DrawDebugData();
director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW, oldMV);
b2Vec2 v2=m_bodies[1]->GetWorldCenter();
b2Vec2 v3=m_bodies[2]->GetWorldCenter();
b2Vec2 v4=m_bodies[3]->GetWorldCenter();
adjust(v1,v3); adjust(v2,v4);
Vertex Vertices[] = {
{{480+v1.x*32,v1.y*32, 0}, {1, 1, 0, 1}, {1, 0}},
{{480+v2.x*32,v2.y*32, 0}, {1, 1, 1,1}, {1, 1}},
{{480+v3.x*32,v3.y*32, 0}, {1, 1, 1, 1}, {0, 1}},
{{480+v4.x*32,v4.y*32, 0}, {0, 1, 1, 1}, {0, 0}}
};
int vertexCount = sizeof(Vertices) / sizeof(Vertices[0]);
// Front
1, 2,0,3
};
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBufferData(GL_ARRAY_BUFFER,sizeof(Vertices),Vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(Indices),Indices,GL_STATIC_DRAW);
GLint _positionLocation = glGetAttribLocation(pg->getProgram(), "ja_position");
GLint _colorLocation = glGetAttribLocation(pg->getProgram(), "ja_color");
GLint _textureUniform = glGetUniformLocation(pg->getProgram(), "jjxx");
GLint val = glGetUniformLocation(pg->getProgram(), "val");
GLint resolution = glGetUniformLocation(pg->getProgram(), "resolution");
pg->use();
pg->setUniformsForBuiltins();
Size sz=Director::getInstance()->getWinSize();
glUniform2f(resolution,sz.width,sz.height);
glEnableVertexAttribArray(_positionLocation);
glEnableVertexAttribArray(_colorLocation);
glEnableVertexAttribArray(_textureLocation);
(GLvoid*)offsetof(Vertex, TexCoord));
//
set sampler
GL::bindTexture2DN(0, texture2d->getName());
glUniform1i(_textureUniform, 0); // unnecc in practice
glEnable(GL_BLEND);
BlendFunc bf=BlendFunc::ALPHA_NON_PREMULTIPLIED;
glBlendFunc(bf.src, bf.dst);
glEnable(GL_DEPTH_TEST);
glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, 0);
glDisable(GL_DEPTH_TEST);
}
void HelloWorld::update(float dt)
{
m_world->Step(dt,8,1);
}
void HelloWorld::onEnter()
{
Layer::onEnter();
}
bool HelloWorld::init()
{
//
// 1. super init first
Size visibleSize = Director::getInstance()->getVisibleSize();
Vec2 origin = Director::getInstance()->getVisibleOrigin();
ct=0.1;
pg=new GLProgram();
pg->initWithFilenames("ccShader_Position_uColor.vert","ccShader_Position_uColor.frag");
pg->link();
pg->updateUniforms();
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer );
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer );
//setScale(0.5);
setAnchorPoint( Vec2(0,0) );
setPosition( Vec2(origin.x+visibleSize.width/2, origin.y) );
m_mouseJoint=0;
b2Vec2 gravity;
gravity.Set(0.0f, -10.0f);
m_world = new b2World(gravity);
m_debugDraw=new GLESDebugDraw( 32 );
uint32 flags = 0;
//flags += b2Draw::e_shapeBit;
//flags += b2Draw::e_jointBit;
//flags += b2Draw::e_aabbBit;
m_debugDraw->SetFlags(flags);
m_world->SetDebugDraw(m_debugDraw);
m_world->SetAllowSleeping(true);
m_world->SetContinuousPhysics(true);
b2Body* ground = NULL;
{
b2BodyDef bd;
ground = m_world->CreateBody(&bd);
shape.Set(b2Vec2(-40.0f, 0), b2Vec2(40.0f, 0));
ground->CreateFixture(&shape, 0.0f);
shape.Set(b2Vec2(-480.0/32, -40), b2Vec2(-480.0/32, 40));
ground->CreateFixture(&shape, 0.0f);
shape.Set(b2Vec2(-40, 640.0/32), b2Vec2(40, 640.0/32));
ground->CreateFixture(&shape, 0.0f);
shape.Set(b2Vec2(480.0/32, -40), b2Vec2(480.0/32, 40));
ground->CreateFixture(&shape, 0.0f);
m_groundBody=ground;
}
{
b2CircleShape shape;
shape.m_radius=4;
bd.type = b2_dynamicBody;
m_bodies[0] = m_world->CreateBody(&bd);
m_bodies[0]->CreateFixture(&shape, 5.0f); m_bodies[0]->SetBullet(true);
bd.position.Set(4.0f, 4.0f);
m_bodies[1] = m_world->CreateBody(&bd);
m_bodies[1]->CreateFixture(&shape, 5.0f); m_bodies[1]->SetBullet(true);
bd.position.Set(6.0f, 14.0f);
m_bodies[2] = m_world->CreateBody(&bd);
m_bodies[2]->CreateFixture(&shape, 5.0f); m_bodies[2]->SetBullet(true);
bd.position.Set(-4.0f, 16.0f);
m_bodies[3] = m_world->CreateBody(&bd);
m_bodies[3]->CreateFixture(&shape, 5.0f); m_bodies[3]->SetBullet(true);
b2Vec2 p1, p2, d;
jd.dampingRatio = 0.0f;
jd.bodyB = m_bodies[1];
jd.localAnchorA.Set(0.5f, 0.0f);
jd.localAnchorB.Set(-0.5f, 0.0f);;
p1 = jd.bodyA->GetWorldPoint(jd.localAnchorA);
p2 = jd.bodyB->GetWorldPoint(jd.localAnchorB);
d = p2 - p1;
jd.length = d.Length();
m_joints[4] = m_world->CreateJoint(&jd);
jd.bodyB = m_bodies[2];
jd.localAnchorA.Set(0.5f, 0.0f);
jd.localAnchorB.Set(-0.5f, 0.0f);;
p1 = jd.bodyA->GetWorldPoint(jd.localAnchorA);
p2 = jd.bodyB->GetWorldPoint(jd.localAnchorB);
d = p2 - p1;
jd.length = d.Length();
m_joints[4] = m_world->CreateJoint(&jd);
jd.bodyB = m_bodies[2];
jd.localAnchorA.Set(0.0f, 0.5f);
jd.localAnchorB.Set(0.0f, -0.5f);
p1 = jd.bodyA->GetWorldPoint(jd.localAnchorA);
p2 = jd.bodyB->GetWorldPoint(jd.localAnchorB);
d = p2 - p1;
jd.length = d.Length();
m_joints[5] = m_world->CreateJoint(&jd);
jd.bodyB = m_bodies[3];
jd.localAnchorA.Set(0.5f, 0.0f);
jd.localAnchorB.Set(-0.5f, 0.0f);;
p1 = jd.bodyA->GetWorldPoint(jd.localAnchorA);
p2 = jd.bodyB->GetWorldPoint(jd.localAnchorB);
d = p2 - p1;
jd.length = d.Length();
m_joints[4] = m_world->CreateJoint(&jd);
jd.bodyB = m_bodies[3];
jd.localAnchorA.Set(-0.5f, 0.0f);
jd.localAnchorB.Set(0.5f, 0.0f);
p1 = jd.bodyA->GetWorldPoint(jd.localAnchorA);
p2 = jd.bodyB->GetWorldPoint(jd.localAnchorB);
d = p2 - p1;
jd.length = d.Length();
m_joints[6] = m_world->CreateJoint(&jd);
jd.bodyB = m_bodies[0];
jd.localAnchorA.Set(0.0f, -0.5f);
jd.localAnchorB.Set(0.0f, 0.5f);
p1 = jd.bodyA->GetWorldPoint(jd.localAnchorA);
p2 = jd.bodyB->GetWorldPoint(jd.localAnchorB);
d = p2 - p1;
jd.length = d.Length();
m_joints[7] = m_world->CreateJoint(&jd);
}
auto listener = EventListenerTouchOneByOne::create();
listener->setSwallowTouches(true);
listener->onTouchMoved = CC_CALLBACK_2(HelloWorld::onTouchMoved, this);
listener->onTouchEnded = CC_CALLBACK_2(HelloWorld::onTouchEnded, this);
_touchListener = listener;
return true;
}
bool HelloWorld::onTouchBegan(Touch* touch, Event* event)
{
auto touchLocation = touch->getLocation();
log("Box2DView::onTouchBegan, pos: %f,%f -> %f,%f", touchLocation.x, touchLocation.y, nodePosition.x,
{
return false;
}
b2AABB aabb;
b2Vec2 d,p(nodePosition.x/32,nodePosition.y/32);
aabb.lowerBound = p - d;
aabb.upperBound = p + d;
QueryCallback callback(p);
m_world->QueryAABB(&callback, aabb);
{
b2Body* body = callback.m_fixture->GetBody();
b2MouseJointDef md;
md.bodyA = m_groundBody;
md.bodyB = body;
md.target = p;
md.maxForce = 50 * body->GetMass();
m_mouseJoint = (b2MouseJoint*)m_world->CreateJoint(&md);
body->SetAwake(true);
return true;
}
}
{
auto touchLocation = touch->getLocation();
auto nodePosition = convertToNodeSpace( touchLocation );
m_mouseWorld = nodePosition;
{
m_mouseJoint->SetTarget(p);
}
}
{
auto touchLocation = touch->getLocation();
auto nodePosition = convertToNodeSpace( touchLocation );
{
m_world->DestroyJoint(m_mouseJoint);
m_mouseJoint = nullptr;
}
}
{
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WP8) || (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)
MessageBox("You pressed the close button. Windows Store Apps do not implement a close button.","Alert");
return;
#endif
exit(0);
#endif
}
效果:
Vec2 v2=touch->getLocation();touch->getDelta();
Vertex vx={{v2.x,v2.y,0},{CCRANDOM_0_1(),CCRANDOM_0_1()+0.5,CCRANDOM_0_1(),1},{0,0}};
varray.push_back(vx);
};
std::vector<Vertex>::iterator iter=varray.begin();
for(;iter!=varray.end();iter++)
{
Vertex vx=(*iter);
if(tarr.empty())
{
vx.Color[3]=0;
tarr.push_back(vx);
tarr2.push_back(vx);
}
else
{
if(iter==varray.end()-1)
{vx.Color[3]=0;
tarr.push_back(vx);tarr2.push_back(vx);
}
else
{
float k=0,nx1,nx2,ny1,ny2;
if(xoff!=0)
{
nx1=vx.Position[0]-rand()%20;xoff/2;
nx2=vx.Position[0]+rand()%20;xoff/2;
ny1=vx.Position[1];
ny2=vx.Position[1];
}
else
{
nx1=vx.Position[0]-rand()%20;
nx2=vx.Position[0]+rand()%20;
ny1=vx.Position[1];
ny2=vx.Position[1];
}
Vertex vx1={{nx1,ny1,0},
{0,1,0,0},{0,0}};
Vertex vx2={{nx2,ny2,0},
{0,1,1,0},{0,0}};
tarr.push_back(vx1); tarr.push_back(vx);
tarr2.push_back(vx); tarr2.push_back(vx2);
}
}
}
if(varray.size()>10)
varray.erase(varray.begin());
cocos2dx 实现果冻,刀光等效果相关推荐
- 用haXe+NME实现水果忍者的刀光效果,支持多点触摸,Flash10, Android通用
前两天玩了玩水果忍者,感觉这种输入方式是非常适合多点触摸屏的,输入直观而且爽快感十足,于是就想到了如何使用haxe+NME实现刀光的效果,今天按照我的想法把效果实现了,感觉还是很逼真的.估计即使不是水 ...
- U3D——刀光轨迹插件
原文地址:http://www.cnblogs.com/hellohuan/p/3478907.html 之前在PC端的游戏中实现过轨迹,算法喜闻乐见,收集每帧的控制点,对其进行B样条插值,生成D3D ...
- Unity 刀光拖尾生成
在游戏中,我们经常会看到角色挥动武器的时候,拖尾的效果,以及折射扭曲.在Unity开发中大家可以使用RPG Pocket插件或者其他的插件,在这里主要是给大家介绍一下其生成原理. 首先,在舞动刀的时候 ...
- shader拖尾_【OpenGL编程】拖尾、刀光、剑光、尾焰效果的开发
1 说在开始 最近模拟了切水果里面的拖尾效果,其可以应用在许多的场景里面,例如,武器的刀光,飞机的尾焰效果等等.我开发的这个Demo是基于OpenGL ES的,开发环境(IDE)使用的Android ...
- 【OpenGL编程】拖尾、刀光、剑光、尾焰效果的开发
重要 为了方便大家共同交流学习,我对项目进行了升级,建议大家去我的GitHub去查看,本文章的算法部分还是可以借鉴的.改动具体如下. 1.添加详细类注释,概括类的功能. 2.修改了部分变量名称. 3. ...
- Unity3D 武器拖尾效果(刀光) 使用PocketRPG Trails
PocketRPG的示例下载:http://download.csdn.net/detail/xv_ly15/4999885 ------------------------------------- ...
- Cocos2D实现Fruit Ninja里面刀光效果教程
Cocos2D实现Fruit Ninja里面刀光效果教程 2011-08-16 17:13 佚名 CocoaChina 我要评论(1) 字号:T | T Cocos2D实现Fruit Ninja里面刀 ...
- 另一种实现 Fruit Ninja 里刀光效果的方法
Fruit Ninja 这款游戏在 iOS 平台上取得了巨大成功,尤其是手指划过屏幕时的刀锋特效大大提升了情节相对简单的切水果游戏的视觉体验和整体印象.我们此前介绍了一种实现 Fruit Ninja ...
- [Unity3d]水果忍者-声音和刀光的实现
继续水果忍者制作,写一下今天的学习心得,主要就是实现了一个切水果的刀光以及声音的实现. 主要效果 实现步骤 1.实现划线 原理:主要是用到Effet->Line Renderer组件(线渲染器) ...
最新文章
- win10系统启动服务器不可用,解决win10专业版windows installer服务不可用不能启动更不能访问...
- Nginx_日志文件讲解
- Web前端开发笔记——第二章 HTML语言 第四节 超链接标签
- 安装软件包的三种方法rpm包rpm工具yum工具
- mentor公司的PCB设计软件:PADs, Expedition,BoardStation
- win10下用docker安装onlyoffice服务
- 从曾经的无比辉煌,到如今彻底凉凉,万能充到底经历了什么?
- VB 去除文本框粘贴功能
- Java程序员从笨鸟到菜鸟之(四十八)细谈struts2(十)ognl概念和原理详解
- memcached主从复制
- Atitit 企业战略目标的艺术 目录 1. 企业战略目标	1 2. 特点 ▪ 宏观性 ▪ 长期性 ▪ 全面性 稳定性	1 3. 内容	2 3.1. 彼得·德鲁克在《管理实践》一书中提出了八个
- Super odometry:以IMU为核心的激光雷达视觉惯性融合框架(ICRA2021)
- crm系统服务器要求,crm系统需要配备什么云服务器
- 英语3500词(14/20)dynasty主题 (2022.1.26)
- angular烂笔头
- 实验吧-简单的登录题
- 【vue-router源码】五、router.addRoute、router.removeRoute、router.hasRoute、router.getRoutes源码分析
- 小程序社交电商案例分享
- Openstack虚拟机镜像深度实践
- java对象转换为JSON日期格式转换处理
热门文章
- javascript语言精粹数组篇之Array的方法注意事项
- XTS 测试环境搭建和介绍
- 能有更多机会来获得计算机相关领域或者大数据人工智能方面的知识
- SEP RU6 MP3 繁体中文版简体中文版在SEPM生成报告的树型图中显示乱码
- 《疯狂的JAVA讲义》笔记-第8章集合
- Django+python+web开发的思维导图式辅助记忆笔录
- Android中的invalidate()和postInvalidate()
- C++中贝叶斯滤波器包bfl的使用(1)-线性卡尔曼滤波器
- MAC vim 每次打开报错 E1208: -complete used without allowing argumentsError
- 在 Android 模拟器上设置 Sencha Touch