zoukankan      html  css  js  c++  java
  • chipmunk 物理引擎的基本概念和基本用法

    chipmunk是一个开源2D物理引擎,

    项目主页:http://code.google.com/p/chipmunk-physics/ 

    工作需要研究了一下,这个引擎的资料还是不多,我阅读了所有的文档,7个demo,和一个教学程序,得出如下一些理解。

    一,基本概念

    space: 发生物理模拟的空间,可容纳body, shape,joint

    body:刚体,可被赋予shape。刚体具有质量,转动惯量,位置,线性速度,加速度,角度,角速度,角加速度等属性。刚体之间可通过joint连接

    shape:决定刚体的碰撞外形。一个刚体上可覆盖上多个shape,同属于一个刚体的shape不会互相发生碰撞。shape同样需要加到space中。有圆,线段,凸多边形这三种shape类型。

     

    joint: 用于连接刚体。有4种类型:

    pin joint: 相当于一根棍子(质量忽略)加两个大头针(锚点),两个刚体如果用pin joint连接,他们之间的距离不会改变,他们各自可绕锚点转动(如果有力矩的话)
    slide joint: 相当于把pin joint的棍子换成了滑槽。这个滑槽有最大和最小长度。
    pivot joint: 即一个旋转轴。两个刚体都绕这个轴旋转
    groove joint:相当于可滑动的pivot joint。将刚体2的旋转轴挂到处于刚体1的一段滑槽上。

    坐标系:demo里都使用的是2d笛卡尔坐标系。猜想对于2d游戏如果使用屏幕坐标系应该也可以(只是y反了)。或者在绘制2d sprite的时候自己转换一下坐标吧,应该更清楚些。
    单位:引擎没有指定,最好使用国际单位制如kg,m,s,保持单位一致很重要

    二,基本用法
    0)初始化chipmunk引擎,调用cpInitChipmunk()  -- 现在已经不需要这个函数!!
    1)构建sapce,使用cpSpaceNew()
    2) 构建一个static body,作为关卡的物理环境。这个body不需要加入到space中,否则会受重力作用。但这个body的shape需要加入到space中,用作碰撞检测。
    staticBody = cpBodyNew(INFINITY, INFINITY); //生成static body,一般一个场景有一个够了
    shape = cpSegmentShapeNew(staticBody, cpv(-320,-240), cpv(-320,240), 0.0f);//在static body上生成一个线段shape,也可以使用圆和多边形
    cpSpaceAddStaticShape(space, shape);//将这个shape加入到space中
    3)生成刚体body,和static body类似,只是使用cpBodyNew,另外需要使用cpSpaceAddBody(space, body);将body加入到space中。例子:
    cpVect verts[] = {
    cpv(-15,-7),
    cpv(-15, 7),
    cpv( 15, 7),
    cpv( 15,-7),
    };

    cpBody *body = cpBodyNew(1.0, cpMomentForPoly(1.0, num, verts, cpv(0,0)));//第二个参数是转动惯量,一般用这个函数计算就可以了
    body->p = cpv(x, y);//可设置body的位置
    cpSpaceAddBody(space, body);//body要加入space中
    cpShape *shape = cpPolyShapeNew(body, num, verts, cpv(0,0));
    shape->e = 0.0; shape->u = 1.0;
    cpSpaceAddShape(space, shape);//shape要加入space中
    4) 加入joint:每个joint都是对于两个body的。使用cpPivotJointNew之类的方法加入joint,然后还要使用cpSpaceAddJoint将joint加入到space中
    5)进行物理模拟计算:
    其 实只要调用cpSpaceStep(space, dt);就可以了。如果使用了外力,比如cpDampedSpring这样的方法,就要先清除一下body上的力和力矩,使用 cpBodyResetForces,另外如果需要提高精度,可以将dt分为几个step。例子:
    void demo7_update(int ticks)
    {
    int steps = 3;
    cpFloat dt = 1.0/60.0/(cpFloat)steps;

    for(int i=0; i
    cpBodyResetForces(chassis);
    cpBodyResetForces(wheel1);
    cpBodyResetForces(wheel2);
    cpDampedSpring(chassis, wheel1, cpv(40, 15), cpvzero, 50.0f, 150.0f, 10.0f, dt);
    cpDampedSpring(chassis, wheel2, cpv(-40, 15), cpvzero, 50.0f, 150.0f, 10.0f, dt);

    cpSpaceStep(space, dt);
    }
    }

    6)释放对象
    这样就可以全部释放:
    cpSpaceFreeChildren(space); //释放所有加入到space中的body, shape, joint
    cpSpaceFree(space);
    cpBodyFree(staticBody);//静态body没有加入space需要单独释放

    三,碰撞回调
    物理引擎本身会让物体在碰撞后产生“正确”的反应。但是你还是可以让碰撞时调用自己的方法,甚至取消掉碰撞。
    使用:cpSpaceAddCollisionPairFunc(space, 1, 0, &collFunc, &some_value);

    static int
    collFunc(cpShape *a, cpShape *b, cpContact *contacts, int numContacts, cpFloat normal_coef, void *data)
    {
    int *some_ptr = (int *)data;

    // Do various things with the contact information. 
    // Make particle effects, estimate the impact damage from the relative velocities, etc.
    // for(int i=0; i
    // printf("Collision at %s. (%d - %d) %d ", cpvstr(contacts[i].p), a->collision_type, b->collision_type, *some_ptr);

    // Returning 0 will cause the collision to be discarded. This allows you to do conditional collisions.
    return 1;
    }

    四,速度函数
    body->velocity_func = apply_buoyancy;//设定了一个自定义的速度计算函数
    这个函数给刚体加入了水面的浮力(demo6)。
    // Apply an approximate bouyancy and drag force to an object.
    static void
    apply_buoyancy(cpBody *body, cpVect gravity, cpFloat damping, cpFloat dt)
    {
    int numx = 20;
    int numy = 4;

    float stepx = (float)WIDTH/(float)numx;
    float stepy = (float)HEIGHT/(float)numy;

    cpBodyResetForces(body);//先清除力和力矩

    for(int x=0; x
    for(int y=0; y
    cpVect p_sample = cpv((x + 0.5)*stepx - WIDTH/2, (y + 0.5)*stepy - HEIGHT/2);
    cpVect p = cpBodyLocal2World(body, p_sample);
    cpVect r = cpvsub(p, body->p);

    if(p.y < 0){
    cpVect v = cpvadd(body->v, cpvmult(cpvperp(r), body->w));
    cpVect f_damp = cpvmult(v, -0.0003*cpvlength(v));
    cpVect f = cpvadd(cpv(0, 2.0), f_damp);//计算浮力
    cpBodyApplyForce(body, f, r);//将力作用上
    }
    }
    }

    cpBodyUpdateVelocity(body, gravity, damping, dt);//默认的应该只有这句吧,作用上重力和阻力。
    }

    五,其他
    可以加上冲量:
  • 相关阅读:
    【已解决】github中git push origin master出错:error: failed to push some refs to
    好记心不如烂笔头,ssh登录 The authenticity of host 192.168.0.xxx can't be established. 的问题
    THINKPHP 5.0目录结构
    thinkphp5.0入口文件
    thinkphp5.0 生命周期
    thinkphp5.0 架构
    Django template
    Django queryset
    Django model
    Python unittest
  • 原文地址:https://www.cnblogs.com/decode1234/p/7183443.html
Copyright © 2011-2022 走看看