• 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);//默认的应该只有这句吧,作用上重力和阻力。
    }

    五,其他
    可以加上冲量:
  • 相关阅读:
    LINQ查询操作符之First、FirstOrDefault、Last、LastOrDefault、ElementAt、ElementAtOrDefault、Contains、Any、All、Coun
    .Net 使用的快捷键
    P2073 送花
    洛谷P1514 引水入城
    花园
    八数码难题
    并查集题目整理
    树链剖分(强势借鉴)
    模拟题
    考试整理
  • 原文地址:https://www.cnblogs.com/decode1234/p/7183443.html
Copyright © 2020-2023  润新知