鼠标移动绘制刚体(同发泰然)

2 篇文章 0 订阅
1 篇文章 0 订阅
解决方式:
引擎版本:cocos2d2.1beta3 + box2d 2.2.1
可以有两种方式
                    1 b2PolygonShape 绘制  (缺点:每段刚体的大小可能不会一直,有误差)
                    2 b2EdgeShape绘制  (缺点:1 没找到旋转方式,问题待解决。。。 2 与b2EdgeShape绘制的地面不发生碰撞 3 鼠标关节不能移动该刚体)
                   两种方法其实很类似
思路:1 保存鼠标 按下及移动时的点坐标
          2 通过点坐标绘制刚体

1 保存两点坐标而且还需要一些其他的值 比如:两点间距离 /两点间中心点/两点相减所构成的向量旋转角度等 而且还涉及到cocos2d-x坐标系与box2d坐标系的数值转换问题,所以我将其封装成一个类,以方便获取相应的值 (类并不全面,而且有些实现可能会有更方便的方法,希望有各位多多指点)代码如下:
///
.h 文件
#ifndef _BODYSEGMENT_H_
#define _BODYSEGMENT_H_

//像素比米比例 1米=32像素
#define PTM_RATIO 32

#include "cocos2d.h"
#include "Box2D/Box2D.h"
using namespace cocos2d;

class BodySegment
{
public:
        //根据传入的两个点 计算所需要的值
        BodySegment(CCPoint p1, CCPoint p2);
        ~BodySegment();
        //将中心点位置由 CCPoint转换为b2Vec类型
        void ConvertPointTob2Vec(CCPoint cp);

        //返回第一个点 cocos2d-x下坐标
        CCPoint ccpos_GetPoint1();
        //返回第二个点 cocos2d-x下坐标
        CCPoint ccpos_GetPoint2();

        //返回转换为b2vec的point1
        b2Vec2 b2pos_vGetPoint1();
        //返回转换为b2vec的point2
        b2Vec2 b2pos_vGetPoint2();

        //返回第一个点 box2d-x下坐标
        CCPoint b2pos_GetPoint1();
        //返回第二个点 box2d-x下坐标
        CCPoint b2pos_GetPoint2();

        //返回中心点 cocos2d-x下坐标
        b2Vec2 ccpos_GetCenter();
        //返回中心点 box2d-x下坐标
        b2Vec2 b2pos_GetCenter();

        //返回中心点X坐标 cocos2d-x下坐标
        float ccpos_GetCenterX();
        //返回中心点X坐标 box2d-x下坐标
        float b2pos_GetCenterX();

        //返回中心点Y坐标 cocos2d-x下坐标
        float ccpos_GetCenterY();
        //返回中心点Y坐标 box2d-x下坐标
        float b2pos_GetCenterY();

        //返回两点相减后的向量旋转弧度
        float  GetAngle();
        //返回两点间的长度 标量
        float cc_GetLength(); //cocos2d-x中的长度
        float b2_GetLength(); //box2d中的长度
private:
        //两个点
        CCPoint m_cpPoint1;
        CCPoint m_cpPoint2;
        //将两个点转换为b2vec 并且为box2d坐标
        b2Vec2  m_bvPoint1;
        b2Vec2  m_bvPoint2;

        //两点中心位置
        CCPoint m_cCenter;  //CCPoint类型用于两点计算值
        b2Vec2 m_vCenter;   //由CCPoint类型转换
        //向量旋转的弧度
        float  m_fAngle;
        //两点间的长度
        float  m_fLength;
};
#endif
/
.cpp 文件

#include "BodySegment.h"

//根据传入的两个点 计算所需要的值
BodySegment::BodySegment(CCPoint p1, CCPoint p2)
{
        //点坐标为cocos2d坐标系坐标
        m_cpPoint1 = p1;
        m_cpPoint2 = p2;
        //计算两点的中心点
        m_cCenter = ccpMidpoint(m_cpPoint1,m_cpPoint2);
        //给m_vCenter 赋值
        ConvertPointTob2Vec(m_cCenter);
        //两点旋转的弧度值 两点相减求出向量后计算旋转角度
        m_fAngle = ccpToAngle(ccpSub(m_cpPoint2,m_cpPoint1));
        //求出两点间距离
        m_fLength = ccpDistance(m_cpPoint1,m_cpPoint2);
}

BodySegment::~BodySegment()
{
}

//将中心点位置由 CCPoint转换为b2Vec类型
void BodySegment::ConvertPointTob2Vec(CCPoint cp)
{
        m_vCenter.x = cp.x;
        m_vCenter.y = cp.y;
}

//返回第一个点 cocos2d-x下坐标
CCPoint BodySegment::ccpos_GetPoint1()
{
        return m_cpPoint1;
}

//返回第二个点 cocos2d-x下坐标
CCPoint BodySegment::ccpos_GetPoint2()
{
        return m_cpPoint2;
}

//返回转换为b2vec的point1
b2Vec2 BodySegment::b2pos_vGetPoint1()
{
        m_bvPoint1.x = m_cpPoint1.x/PTM_RATIO;
        m_bvPoint1.y = m_cpPoint1.y/PTM_RATIO;

        return m_bvPoint1;
}

//返回转换为b2vec的point2
b2Vec2 BodySegment::b2pos_vGetPoint2()
{
        m_bvPoint2.x = m_cpPoint2.x/PTM_RATIO;
        m_bvPoint2.y = m_cpPoint2.y/PTM_RATIO;

        return m_bvPoint2;
}

//返回第一个点 box2d-x下坐标
CCPoint BodySegment::b2pos_GetPoint1()
{
        CCPoint b2Point1;
        b2Point1.x = m_cpPoint1.x/PTM_RATIO;
        b2Point1.y = m_cpPoint1.y/PTM_RATIO;
        return b2Point1;
}

//返回第二个点 box2d-x下坐标
CCPoint BodySegment::b2pos_GetPoint2()
{
        CCPoint b2Point2;
        b2Point2.x = m_cpPoint2.x/PTM_RATIO;
        b2Point2.y = m_cpPoint2.y/PTM_RATIO;

        return b2Point2;
}

//返回中心点 cocos2d-x下坐标
b2Vec2 BodySegment::ccpos_GetCenter()
{
        return m_vCenter;
}

//返回中心点 box2d-x下坐标
b2Vec2 BodySegment::b2pos_GetCenter()
{
        b2Vec2 b2Center;
        b2Center.x = m_vCenter.x/PTM_RATIO;
        b2Center.y = m_vCenter.y/PTM_RATIO;

        return b2Center;
}

//返回中心点X坐标 cocos2d-x下坐标
float BodySegment::ccpos_GetCenterX()
{
        return m_vCenter.x;
}

//返回中心点X坐标 box2d-x下坐标
float BodySegment::b2pos_GetCenterX()
{
        return m_vCenter.x/PTM_RATIO;
}

//返回中心点Y坐标 cocos2d-x下坐标
float BodySegment::ccpos_GetCenterY()
{
        return m_vCenter.y;
}

//返回中心点Y坐标 box2d-x下坐标
float BodySegment::b2pos_GetCenterY()
{
        return m_vCenter.y/PTM_RATIO;
}

//返回两点相减后的向量旋转弧度
float  BodySegment::GetAngle()
{
        return m_fAngle;
}

//返回两点间的长度 标量
//cocos2d-x中的长度
float BodySegment::cc_GetLength()
{
        return m_fLength;
}

//box2d中的长度
float BodySegment::b2_GetLength()
{
        return m_fLength/PTM_RATIO;
}





类构建完成 下面开始创建
首先   介绍需要的变量:
        //世界
        b2World *m_pWorld;

        //绘制线段每段的长度 超过这个长度才保存点
        float m_fSegmentLength;

         //保存前一个point
         CCPoint m_PrePoint;
         //当前的point
         CCPoint m_CurPoint;

        //保存片段信息vector
        vector<BodySegment*> *m_Vec1;


其次  应用:
1  HelloWorld::init() 方法中 初始化                    m_Vec1 = new vector<BodySegment*>();
每段绳索的小段      m_iSegmentLength = 20.0f;
2 box2d世界的创建 与 step 这个就不说了 
3 触摸消息 (我用的是单点触摸) 
   3.1  ccTouchBegan(CCTouch* touch, CCEvent* event)   方法中 
               //获得点 将点转换为cocos2d-x坐标
        CCPoint touchLocation = touch->getLocation();   
        CCPoint nodePosition = convertToNodeSpace( touchLocation );

        //做个判断 清空vector1中的值  
        if (!m_Vec1->empty())
        {
                m_Vec1->clear();
        }

        //保存起始点
        m_PrePoint = nodePosition;

   3.2  ccTouchMoved(CCTouch* touch, CCEvent* event)  方法中
        //获得点 将点转换为cocos2d-x坐标
        CCPoint touchLocation = touch->getLocation();    
        CCPoint nodePosition = convertToNodeSpace( touchLocation );

        //获得当前点
        m_CurPoint = nodePosition;
        //计算当前点到上一点的距离
        float distance = ccpDistance(m_CurPoint,m_PrePoint);

        //如果两点的距离大于预定长度
        if (distance>=m_iSegmentLength)

        {
                //创建BodySegment 并用vector保存
                BodySegment *sg = new BodySegment(m_PrePoint,m_CurPoint);        
                m_Vec1->push_back(sg);
                //让上一点等于当前点
                m_PrePoint = m_CurPoint;

        }
     3.3 ccTouchEnded(CCTouch* touch, CCEvent* event) 方法中 做绘制 怕看着乱 单独又写了两个方法
        //DrawLineBody();                       //刚体段绘制线段
          DrawEdgeLineBody();                //片刚体绘制


重点来了:
DrawLineBody()
{        
        //做个m_Vec1 的迭代器
        vector<BodySegment*>::iterator it = m_Vec1->begin();
        //刚体定义
        b2BodyDef bd;
        bd.type = b2_dynamicBody;
        //创建刚体
        b2Body* body = m_World->CreateBody(&bd);
        //迭代循环 提取保存的点信息
        for (;it!=m_Vec1->end();it++)
        {
               //定义多边形
                b2PolygonShape shape;
               //创建盒子  SetAsBox在box2d中重载了 4个参数的这个 
                shape.SetAsBox(((*it)->b2_GetLength())/2.0f,   1.0f/PTM_RATIO,                             //参数一和二 是盒子的宽高 
                        (b2Vec2((*it)->b2pos_GetCenterX(), (*it)->b2pos_GetCenterY())),                   //盒子绘制的中心点位置 
                        ((*it)->GetAngle()) );                                                                                         //盒子旋转的角度
                //盒子绘制的位置
                bd.position.Set((*it)->b2pos_GetCenterX(),(*it)->b2pos_GetCenterY());
                //是否旋转
                bd.fixedRotation = true;
                //夹具的定义
                b2FixtureDef fd;
                fd.density = 20.0f;
                fd.friction = 0.2f;
                fd.shape = &shape;
                //给刚体创建夹具
                body->CreateFixture(&fd);
        }
}

DrawEdgeLineBody()
{
        vector<BodySegment*>::iterator it = m_Vec1->begin();
        b2BodyDef bd;
        bd.type = b2_dynamicBody;
        b2Body* body = m_World->CreateBody(&bd);

        for (;it!=m_Vec1->end();it++)
        {
                b2EdgeShape shape;
                //这里设置刚体的时候是通过点设置 其他和上面一样
                shape.Set((*it)->b2pos_vGetPoint1(),(*it)->b2pos_vGetPoint2());
                bd.position.Set((*it)->b2pos_GetCenterX(),(*it)->b2pos_GetCenterY());
                bd.fixedRotation = true;
                b2FixtureDef fd;
                fd.density = 20.0f;
                fd.friction = 0.2f;
                fd.shape = &shape;

                body->CreateFixture(&fd);
        }

}
注:ccpToAngle ccpDistance 等数学函数式cocos2d-x提供的,用起来很方便, 还有很多就不一一列举了
总结来说呢,其实这个并不难,就是 实时创建刚体和在一个刚体上绑定多个夹具的应用 ,一个刚体绑定多个夹具就像BOX2D给的例子 ApplyForce 中的小飞机制作是一个道理
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值