感谢原文:http://blog.muditjaju.infiniteeurekas.in/?p=1

我是从这里看到的:http://blog.csdn.net/xiebaochun/article/details/26455027
原文是cocos2dx 2.x的,我修改了一下,这个版本是Cocos2d-x 3.x可用版本。

Pixel Perfect Collision Detection (Using Cocos2d-x 3.x)

This post found its way because I couldnt find the answer to one of the questions I asked on StackOverflow (http://stackoverflow.com/questions/18546066/pixel-perfect-collision-detection-in-cocos2dx) and thought there would be others like me in search for an answer.

Collision detection is an integral part of almost all games. It is used to find when a bullet hits an enemy or when you bump into a wall etc.
There are many different requirements when we do collision detection and depending on our game we choose one of the many detection techniques.

The default Collision detection mechanism used by games and provided in almost all game engines and frameworks is a “Bounding Box” collision.
Simply put, a “Bounding Box” collision detection system the sprites/objects being checked for collision are treated as the smallest rectangle which completely engulfs them. Then these two Boxes are checked if they are colliding with each other.

But sometimes this very simple collision detection system is not accurate. Specially when we use sprites with alpha values (mostly png files) or when our objects are rotated by some angles. See the image below:

     
Pixel – Perfect collision detection is a system where we check if the objects concerned are actually colliding rather than just being part of a bounding box which is bigger than their size. WARNING: This system though more accurate is obviously more performance intensive and hence depending on your game requirements choose wisely about which of the different systems you want to use.

TIP: This system though written specially for Cocos2d-x framework can be easily understood and implemented for any language/framework you are using.

So its time to get our hands dirty,

We are going to develop a Singleton Class for collision detection and just plug and play this in any project we are doing.

Things used:
1. Singleton Class – CollisionDetection
2. Opengl Vertex and Fragment Shaders
3. CCRenderTexture Class – Cocos2d-x

Theory:
1. Create a CCRenderTexture which is going to serve as a secondary draw buffer.
2. We first do a simple collision detection (Bounding Box) to check if the two sprite’s bounds are colliding
3. If step 2 is a success then we are going to draw the two concerned objects in our secondary buffer we created in step 1. (We are going to set its visibility to false, so that even though we draw something, nothing will we visible to the end user)
4. Using openGL fragment shaders we are going to draw one of the objects completely RED and the other completely BLUE!

5. Using another of openGL functionality glReadPixels we are going to read the pixels data of all the pixels in the Rectangular area (Intersection area) of the bounding box collision
6. We are then going to loop through all the pixel values and check if a single pixel has BOTH the RED and the BLUE pixels. If they have then the objects are actually colliding or else not.

Now here is the code for the above steps. I have commented the code for you to understand what is going on. If there are any questions please leave in the comments and I will try and answer to the best of my knowledge

CollisionDetection.h

//
//  CollisionDetection.h
//  Created by Mudit Jaju on 30/08/13.
//
//  SINGLETON class for checking Pixel Based Collision Detection#ifndef __CollisionDetection__
#define __CollisionDetection__#include <iostream>
#include "cocos2d.h"class CollisionDetection {
public://Handle for getting the Singleton Objectstatic CollisionDetection* GetInstance();//Function signature for checking for collision detection spr1, spr2 are the concerned sprites//pp is bool, set to true if Pixel Perfection Collision is required. Else set to false//_rt is the secondary buffer used in our systembool areTheSpritesColliding(cocos2d::Sprite* spr1, cocos2d::Sprite* spr2, bool pp, cocos2d::RenderTexture* _rt);
private:static CollisionDetection* instance;CollisionDetection();// Values below are all required for openGL shadingcocos2d::GLProgram *glProgram;cocos2d::Color4B *buffer;int uniformColorRed;int uniformColorBlue;};#endif /* defined(__CollisionDetection__) */

CollisionDetection.cpp

//
//  CollisionDetection.cpp
//  Created by Mudit Jaju on 30/08/13.
//
//  SINGLETON class for checking Pixel Based Collision Detection#include "CollisionDetection.h"USING_NS_CC;// Singleton Instance set to NULL initially
CollisionDetection* CollisionDetection::instance = NULL;// Handle to get Singleton Instance
CollisionDetection* CollisionDetection::GetInstance() {if (instance == NULL) {instance = new CollisionDetection();}return instance;
}// Private Constructor being called from within the GetInstance handle
CollisionDetection::CollisionDetection() {// Code below to setup shaders for use in Cocos2d-xglProgram = new GLProgram();glProgram->retain();glProgram->initWithFilenames("SolidVertexShader.vsh", "SolidColorShader.fsh");glProgram->bindAttribLocation(GLProgram::ATTRIBUTE_NAME_POSITION,  GLProgram::VERTEX_ATTRIB_POSITION);glProgram->bindAttribLocation(GLProgram::ATTRIBUTE_NAME_TEX_COORD, GLProgram::VERTEX_ATTRIB_TEX_COORDS);glProgram->link();glProgram->updateUniforms();glProgram->use();uniformColorRed = glGetUniformLocation(glProgram->getProgram(), "u_color_red");uniformColorBlue = glGetUniformLocation(glProgram->getProgram(), "u_color_blue");// A large buffer created and re-used again and again to store glReadPixels databuffer = (Color4B *)malloc( sizeof(Color4B) * 10000 );
}bool CollisionDetection::areTheSpritesColliding(cocos2d::Sprite* spr1, cocos2d::Sprite* spr2, bool pp, RenderTexture* _rt) {bool isColliding = false;// Rectangle of the intersecting area if the sprites are colliding according to Bounding Box collisionRect intersection;// Bounding box of the Two concerned sprites being savedRect r1 = spr1->getBoundingBox();Rect r2 = spr2->getBoundingBox();// Look for simple bounding box collisionif (r1.intersectsRect(r2)) {// If we're not checking for pixel perfect collisions, return trueif (!pp) {return true;}float tempX;float tempY;float tempWidth;float tempHeight;//OPTIMIZE FURTHER//CONSIDER THE CASE WHEN ONE BOUDNING BOX IS COMPLETELY INSIDE ANOTHER BOUNDING BOX!if (r1.getMaxX() > r2.getMinX()) {tempX = r2.getMinX();tempWidth = r1.getMaxX() - r2.getMinX();} else {tempX = r1.getMinX();tempWidth = r2.getMaxX() - r1.getMinX();}if (r2.getMaxY() < r1.getMaxY()) {tempY = r1.getMinY();tempHeight = r2.getMaxY() - r1.getMinY();} else {tempY = r2.getMinY();tempHeight = r1.getMaxY() - r2.getMinY();}// We make the rectangle for the intersection areaintersection = Rect(tempX * CC_CONTENT_SCALE_FACTOR(), tempY * CC_CONTENT_SCALE_FACTOR(), tempWidth * CC_CONTENT_SCALE_FACTOR(), tempHeight * CC_CONTENT_SCALE_FACTOR());unsigned int x = intersection.origin.x;unsigned int y = intersection.origin.y;unsigned int w = intersection.size.width;unsigned int h = intersection.size.height;// Total pixels whose values we will get using glReadPixels depends on the Height and Width of the intersection areaunsigned int numPixels = w * h;// Setting the custom shader to be usedspr1->setGLProgram(glProgram);spr2->setGLProgram(glProgram);glProgram->use();// Clearing the Secondary Draw buffer of all previous values_rt->beginWithClear( 0, 0, 0, 0);// The below two values are being used in the custom shaders to set the value of RED and BLUE colors to be usedglUniform1i(uniformColorRed, 255);glUniform1i(uniformColorBlue, 0);BlendFunc blen_SRCAlpha_ONE={GL_SRC_ALPHA, GL_ONE};BlendFunc blen_BLEND_SRC_BLEND_DST={CC_BLEND_SRC, CC_BLEND_DST};// The blend function is important we don't want the pixel value of the RED color being over-written by the BLUE color.// We want both the colors at a single pixel and hence get a PINK color (so that we have both the RED and BLUE pixels)spr1->setBlendFunc(blen_SRCAlpha_ONE);// The visit() function draws the sprite in the _rt draw buffer its a Cocos2d-x functionspr1->visit();// Setting the shader program back to the default shader being used by our game        spr1->setGLProgram(ShaderCache::getInstance()->getGLProgram(GLProgram::SHADER_NAME_POSITION_TEXTURE_COLOR_NO_MVP));// Setting the default blender function being used by the gamespr1->setBlendFunc(blen_BLEND_SRC_BLEND_DST);// Setting new values for the same shader but for our second sprite as this time we want to have an all BLUE spriteglUniform1i(uniformColorRed, 0);glUniform1i(uniformColorBlue, 255);spr2->setBlendFunc(blen_SRCAlpha_ONE);spr2->visit();spr2->setGLProgram(CCShaderCache::getInstance()->getGLProgram(GLProgram::SHADER_NAME_POSITION_TEXTURE_COLOR_NO_MVP));spr2->setBlendFunc(blen_BLEND_SRC_BLEND_DST);// Get color values of intersection areaglReadPixels(x, y, w, h, GL_RGBA, GL_UNSIGNED_BYTE, buffer);_rt->end();// Read bufferunsigned int step = 1;for(unsigned int i=0; i<numPixels; i+=step) {Color4B color = buffer[i];// Here we check if a single pixel has both RED and BLUE pixelsif (color.r > 0 && color.b > 0) {isColliding = true;break;}}}return isColliding;
}

SolidColorShader.fsh

#ifdef GL_ES
precision lowp float;
#endifvarying vec2 v_texCoord;
uniform sampler2D u_texture;
uniform int u_color_red;
uniform int u_color_blue;void main()
{vec4 color = texture2D(u_texture, v_texCoord);gl_FragColor = vec4(u_color_red, 0, u_color_blue, color.a);}

SolidVertexShader.vsh

attribute vec4 a_position;
attribute vec2 a_texCoord;
attribute vec4 a_color;                             #ifdef GL_ES
varying lowp vec4 v_fragmentColor;
varying mediump vec2 v_texCoord;
#else
varying vec4 v_fragmentColor;
varying vec2 v_texCoord;
#endif                                              void main()
{                                                   gl_Position = CC_MVPMatrix * a_position;       v_fragmentColor = a_color;                     v_texCoord = a_texCoord;
}

For using the Collision Detection Class:

1. Initialize the CCRenderTexture object

    _rt = RenderTexture::create(visibleSize.width * 2, visibleSize.height * 2);_rt->setPosition(ccp(visibleSize.width, visibleSize.height));_rt->retain();_rt->setVisible(false);

2. Call the Singleton function whenever collision detection required

if (CollisionDetection::GetInstance()->areTheSpritesColliding(pSprite, pCurrentSpriteToDrag, true, _rt)) {//Code here
}

基于像素的碰撞检测(移植到cocos2dx 3.x)相关推荐

  1. java 像素级碰撞检测,» 像素级碰撞检测类

    //像素级碰撞检测 package { import flash.display.BitmapData; import flash.display.BlendMode; import flash.di ...

  2. 4种基于像素分割的文本检测算法

    摘要:文本检测是文本读取识别的第一步,对后续的文本识别有着重大的影响.一般场景下,可以通过对通用目标检测算法进行配置修改,来实现对文本行的检测定位.本文主要介绍基于像素分割的文本检测算法. 本文分享自 ...

  3. python矩形碰撞检测算法_简易夺旗游戏(python像素级碰撞检测之颜色碰撞)

    以下是部分代码预览: """ 简易夺旗游戏(python像素级碰撞检测之颜色碰撞) 按上下左右方向箭头操作小虫子去碰到小旗子,游戏就胜利了, 否则如果碰到黑色,游戏就失败 ...

  4. 基于STM32F4的CANOpen移植教程(超级详细)

    CANopen移植到STM32F4平台 前言 1 物品准备 2 相关软件安装 2.1 CAN上位机 2.2 对象字典生成工具objdictedit环境配置 3 将CANopen移植到STM32F407 ...

  5. 基于Linux的kfifo移植到STM32(支持os的互斥访问)

    基于Linux的kfifo移植到STM32(支持os的互斥访问) 声明:本文为杰杰原创,转载请说明出处 https://blog.csdn.net/jiejiemcu/article/details/ ...

  6. 基于像素匹配的MATLAB平台身份证号码实时识别

    基于像素匹配的MATLAB平台身份证号码实时识别 引言 随着信息化技术的发展和智能手机的日益普及和平民化,以MATLAB应用为代表的移动应用越来越广泛,为人们的生活带来了诸多方便.一款移动应用能否赢得 ...

  7. TL437x-IDK基于AM437x的OpenCV移植教程

    1基于AM437x的OpenCV移植 表 1 开发板型号 是否支持本实验 TL437x-EVM 支持 TL437x-EasyEVM 支持 TL437x-IDK 支持 TL437xF-EVM 支持 AM ...

  8. 基于像素的皮肤检测技术

    基于像素的皮肤检测技术 介绍一种基于颜色空间的皮肤检测技术,可以检测亚洲人种与白人的皮肤,皮肤检测 人脸识别的基础,也是很多人像识别技术的基础操作,在实际应用中还是非常有用的. 基于像素的皮肤检测主要 ...

  9. 基于龙芯2K1000移植uboot之DDR

    基于龙芯2K1000移植uboot之DDR 移植环境 开始移植 额外说明 移植环境 CPU:LS2K1000 DDR:SCB13H8G162BF-13KI 编译环境:Ubuntu16.04+gcc-4 ...

最新文章

  1. php中(foreach)用法介绍
  2. CSS的clear去除清除浮动元素
  3. 区块链随想:共识不等于信用
  4. 在web3上搭建ecshop网上商城
  5. mt4 python神经网络_迈达克软件公司承认Python运算对量化交易的重要性----将Python与Metatrader 5集成一体...
  6. LeetCode 111. Minimum Depth of Binary Tree (二叉树最小的深度)
  7. scala从url或者其他数据源读取数据
  8. 163邮箱怎么申请?手机号怎么申请注册邮箱?
  9. Three.js地球开发—1.经纬度转球面坐标
  10. level2行情接口十档行情快照如何去运用?
  11. 11n/11ac/11ax 速率速查表
  12. Rais.vim 配置问题
  13. 硅谷开始玩中国玩剩下的了?
  14. 如何查看.net core 最新版本的功能
  15. 从零开始学习软件测试
  16. 告别流氓播放器不让截屏,win10自带截屏快捷键
  17. 蓝牙耳机哪个牌子运动舒适?2021音质卓越佩戴舒适这五款不要错过
  18. Java—手写服务器
  19. 软考-信息系统项目管理师-项目风险管理
  20. GSMA RCS标准的演变

热门文章

  1. jw player 源码编译运行笔记
  2. Android项目实战之尚硅谷_硅谷p2p金融
  3. UI设计准则在360云盘的运用
  4. 提高论文写作质量和效率的小工具
  5. Open3D 点云颜色渲染
  6. 工业4.0 资产管理壳学习笔记( 5) 模型中的语义,概念和字典
  7. 计算机右键有时不好用,右键不能用怎么办?电脑无法正常使用鼠标右键
  8. 全国电子设计大赛2019年前历届优秀作品,肯定对你电赛之路有所帮助!
  9. STM32CubeMX | 33-使用GPIO读取温度传感器数据(DS18B20)
  10. 胡新宇.华为.过劳死