Vec2 Box2::getCenter() const { Vec2 center; center.add(min,max); center *= NxReal(0.5); return center; }
void HRocker::onTouchMoved(Touch* touch, Event* event) { Vec2 touchPoint = touch->getLocationInView(); touchPoint = Director::getInstance()->convertToGL(touchPoint); if (touchPoint.distance(centerPoint) > radius) { touchPoint.subtract(centerPoint); touchPoint.normalize(); touchPoint *= radius; touchPoint.add(centerPoint); currentPoint = touchPoint; // currentPoint = ccpAdd(centerPoint, // ccpMult(ccpNormalize(ccpSub(touchPoint, centerPoint)), radius)); } else { currentPoint = touchPoint; } }
void Joint::update(float delta) { Vec2 pa = pA; Vec2 pb = pB; RotMat mA(A->angle); RotMat mB(B->angle); pa.rotate(mA); pb.rotate(mB); pa.add(A->position); pb.add(B->position); Vec2 ra = pa - A->position; Vec2 rpa = Vec2(-ra.y, ra.x); Vec2 rb = pb - B->position; Vec2 rpb(-rb.y, rb.x); float d = distance - (pa-pb).value(); Vec2 n = pa-pb; if (n.value() == 0.0f) return; n.normalize(); //position correction float s = d / (A->inv_mass + B->inv_mass ); if(A->dynamic == true ) A->translate(n * s * A->inv_mass ); if(B->dynamic == true ) B->translate( n * s * B->inv_mass * -1); //relative velocities Vec2 v1 = A->velocity + rpa*A->omega; Vec2 v2 = B->velocity + rpb*B->omega; Vec2 v = v1-v2; //calculate impulse float j = -Scalar(v, n) / (A->inv_mass + B->inv_mass + Scalar(rpa, n)*Scalar(rpa, n)*A->inv_inertia + Scalar(rpb, n)*Scalar(rpb, n)*B->inv_inertia ); //apply impulse if(A->dynamic == true ) { A->velocity.add( n * A->inv_mass * j ); A->omega += Scalar(rpa, n*j) * A->inv_inertia ; } if(B->dynamic == true ) { B->velocity.add (n * B->inv_mass * j * -1 ); B->omega -= Scalar(rpb, n*j) * B->inv_inertia ; } /* Vec2 AB = Vector(A->position , B->position ); // Wektor AB float translation = AB.value() - distance; // wymagana translacja cia³ AB.normalize(); // normalizuje wektor Vec2 RelVel = B->velocity - A->velocity ; // Wypadkowa prêdkoœæ cia³ float vel = Scalar(RelVel , AB) + translation; vel = vel / ( A->inv_mass + B->inv_mass ); AB = AB * vel; A->ApplyImpulse(AB); B->ApplyImpulse(AB * -1); */ }
void SimplePhysicObject::updateForStatic(float dt, const std::vector<SimplePhysicObject*>& staticObjs) { if (this->type == SPOT::SPOT_DYNAMIC){ //if (isOnPlatform) return; //--- flag to check what kind if collision has occurred bool collideX = true, collideBottom = true, collideTop = true; for (int iteration = 0; iteration < 3 && (collideX || collideTop || collideBottom); iteration++){ //------------ for each iterating std::set<int> boundObjects; //--- get next position Vec2 nextPosition = this->getPosition(); nextPosition.add(verlocity); //--- create next position bounding box Rect nextPositionRect = Rect( std::min(this->getPosition().x, nextPosition.x), std::min(this->getPosition().y, nextPosition.y), size.width, size.height ); //--- check each object to see whether it intersects with this object's bounding box for (int i = 0; i < staticObjs.size(); i++) { //--- create bounding box for this static object Rect staticObjRect = Rect(staticObjs[i]->getPosition().x, staticObjs[i]->getPosition().y, staticObjs[i]->getSize().width, staticObjs[i]->getSize().height); //--- create bounding box that used to check collide Rect bounds = Rect(nextPositionRect); bounds.merge(staticObjRect); //--- If a bnounding box intersects with this object's bounding box, add the geometry to to list to check for collisions if (bounds.getMaxX() - bounds.getMinX() < staticObjRect.getMaxX() - staticObjRect.getMinX() + nextPositionRect.getMaxX() - nextPositionRect.getMinX() && bounds.getMaxY() - bounds.getMinY() < staticObjRect.getMaxY() - staticObjRect.getMinY() + nextPositionRect.getMaxY() - nextPositionRect.getMinY()) { //-- add this index to bound objects to check collision boundObjects.insert(i); } } //-- No collisions found yet collideX = collideTop = collideBottom = false; //--------------------------------------------------- float projectedMoveX, projectedMoveY, originalMoveX, originalMoveY, nextMoveX, nextMoveY; float vectorLength; int segments; //--- store original move originalMoveX = nextPosition.x - this->getPosition().x; originalMoveY = nextPosition.y - this->getPosition().y; nextMoveX = originalMoveX; nextMoveY = originalMoveY; //-- iterate over each object whose boudning box intersects with this object's bounding box //-- until a collision is found for (auto it = boundObjects.begin(); it != boundObjects.end() && !collideX && !collideTop && !collideBottom; ++it) { //---------------------------------------------------- // Speculative contacts section //---------------------------------------------------- //-- get this static rect Rect staticObjRect = Rect(staticObjs[*it]->getPosition().x, staticObjs[*it]->getPosition().y, staticObjs[*it]->getSize().width, staticObjs[*it]->getSize().height); Rect specIntersection; specIntersection = CCRectMake(std::max(nextPositionRect.getMinX(), staticObjRect.getMinX()), std::max(nextPositionRect.getMinY(), staticObjRect.getMinY()), 0, 0); specIntersection.size.width = std::min(nextPositionRect.getMaxX(), staticObjRect.getMaxX()) - specIntersection.getMinX(); specIntersection.size.height = std::min(nextPositionRect.getMaxY(), staticObjRect.getMaxY()) - specIntersection.getMinY(); if (specIntersection.getMaxY() - specIntersection.getMinY() >= 1 && specIntersection.getMaxX() - specIntersection.getMinX() >= 1) { //-- Test four possible directions //-- dir: 0 = top, 1 = bottom, 2 = left, 3 = right for (int dir = 0; dir < 4; dir++) { // skip test if the expected direction of movement make the test irrelevent //----------------------------------------------------------------------- if (dir == 0 && originalMoveY < 0) continue; if (dir == 1 && originalMoveY > 0) continue; if (dir == 2 && originalMoveX > 0) continue; if (dir == 3 && originalMoveX < 0) continue; float safeMoveX = std::max(std::max(specIntersection.getMinX() - (this->getPosition().x + size.width), this->getPosition().x - specIntersection.getMaxX()), 0.0f); float safeMoveY = std::max(std::max(specIntersection.getMinY() - (this->getPosition().y + size.height), this->getPosition().y - specIntersection.getMaxY()), 0.0f); float safeVecLen = std::sqrt(safeMoveX * safeMoveX + safeMoveY * safeMoveY); //-- calculate the lehgth of the movement vector using pythagoras vectorLength = std::sqrt(originalMoveX * originalMoveX + originalMoveY* originalMoveY); //-- our current position along the anticipated movement vector of this object in this frame projectedMoveX = originalMoveX * (safeMoveX / vectorLength); projectedMoveY = originalMoveY * (safeMoveY / vectorLength); //-- update vector lenght vectorLength -= safeVecLen; segments = 0; //-- we advence along the vector until it intersect with some box while (!staticObjRect.containsPoint(Vec2( static_cast<int>(objectCollisionPoints[dir * 2].x + this->getPosition().x + projectedMoveX), static_cast<int>(objectCollisionPoints[dir * 2].y + this->getPosition().y + projectedMoveY))) && !staticObjRect.containsPoint(Vec2( static_cast<int>(objectCollisionPoints[dir * 2 + 1].x + this->getPosition().x + projectedMoveX), static_cast<int>(objectCollisionPoints[dir * 2 + 1].y + this->getPosition().y + projectedMoveY))) && segments < vectorLength) { projectedMoveX += originalMoveX / vectorLength; projectedMoveY += originalMoveY / vectorLength; segments++; } //--- if an intersection occurred if (segments < vectorLength){ //--- apply correction for over-movemnt if (segments > 0){ projectedMoveX -= originalMoveX / vectorLength; projectedMoveY -= originalMoveY / vectorLength; } //--- adjust the X or Y component of the vector depending on //--- which direction we are currently testing if (dir >= 2 && dir <= 3) nextMoveX = projectedMoveX; if (dir >= 0 && dir <= 1) nextMoveY = projectedMoveY; } } } //---------------------------------------------------- // Penetration resolution //---------------------------------------------------- Rect objectNextBound = Rect( static_cast<int>(this->getPosition().x + nextMoveX), static_cast<int>(this->getPosition().y + nextMoveY), size.width, size.height ); //--- get intersection of new bounding box to static box Rect intersection; intersection = CCRectMake(std::max(objectNextBound.getMinX(), staticObjRect.getMinX()), std::max(objectNextBound.getMinY(), staticObjRect.getMinY()), 0, 0); intersection.size.width = std::min(objectNextBound.getMaxX(), staticObjRect.getMaxX()) - intersection.getMinX(); intersection.size.height = std::min(objectNextBound.getMaxY(), staticObjRect.getMaxY()) - intersection.getMinY(); //--- convert to int to prevent juddering due to floating point dounding errors int intX = static_cast<int>(intersection.getMaxX() - intersection.getMinX()); int intY = static_cast<int>(intersection.getMaxY() - intersection.getMinY()); for (int dir = 0; dir < 4; dir++) { if (intersection.containsPoint(Vec2( static_cast<int>(objectCollisionPoints[dir * 2].x + this->getPosition().x + nextMoveX), static_cast<int>(objectCollisionPoints[dir * 2].y + this->getPosition().y + nextMoveY))) || intersection.containsPoint(Vec2( static_cast<int>(objectCollisionPoints[dir * 2 + 1].x + this->getPosition().x + nextMoveX), static_cast<int>(objectCollisionPoints[dir * 2 + 1].y + this->getPosition().y + nextMoveY))) ) { switch (dir) { case 0: nextMoveY -= intY; break; case 1: nextMoveY += intY; break; case 2: nextMoveX += intX; break; case 3: nextMoveX -= intX; break; } } } //--- Detect what type of contact has occurred based on a comparison of the original if (nextMoveY > originalMoveY && originalMoveY < 0) collideBottom = true; if (nextMoveY < originalMoveY && originalMoveY > 0) collideTop = true; if (std::abs(nextMoveX - originalMoveX) > 0.01f) collideX = true; //--- in this case object cant jump because hit side of something //--- must fall down instead //--- without this object will still continue trying to travel upwards ( for jump thought behaviour ) if (collideX && collideTop && verlocity.y > 0) { verlocity.y = 0; } } //-- if a contact has been deteced, apply the recalculate movement vector if (collideBottom || collideTop){ this->setPositionY(this->getPosition().y + nextMoveY); verlocity.y = 0; if (collideBottom){ //TODO: set jumping = false here to reset jump if (isJump) { isJump = false; verlocity.x = 0; } } } if (collideX){ this->setPositionX(this->getPosition().x + nextMoveX); verlocity.x = 0; } } //-------------------------------------------------------------------------- // update object position by verlocity //-------------------------------------------------------------------------- this->setPositionX(verlocity.x + this->getPosition().x); this->setPositionY(verlocity.y + this->getPosition().y); ////////////////////////////////////////////////////////////////////////////// //--- apply gravity /////////////////////////////////////////////////////////////////////////////// if (!isOnPlatform) { verlocity.y -= 0.5f; } }// END IF check object is dynamic object }
Vec2 operator+(Vec2 left, const Vec2& right) { return left.add(right); }
void ExecFrame::execute_ops(int num) { int opcode, param; floatval fa,fb; int ia, ib, ifor, iparam, ijmp; //char opfor,pfor; Vec2 *v1,*v2; Vec2 v; VMInterface* obj; ExecFrame* frame; CodeObj* cobj; while(num-- != 0) { opcode = (int)code->code[iptr++]; param = (int)code->code[iptr++]; //std::cout << opcode << ':' << param << std::endl; switch(opcode) { case OPC_EXIT: iptr-=2; return; case OPC_VMCALL: cobj = (CodeObj*)popp(); ia = popi(); frame = new ExecFrame(cobj); frame->restart(); if (param > 0) move(param, frame); frame->execute(); if (ia > 0) frame->move(ia, this); delete frame; break; case OPC_CONSTF: pushf(code->conarray_f[param]); break; case OPC_CONSTI: pushi(code->conarray_i[param]); break; case OPC_CONSTV: pushv(code->conarray_v[param]); break; case OPC_CONSTP: pushp(code->conarray_p[param]); break; case OPC_PUSHVARF: pushf(vararray_f[param]); break; case OPC_PUSHVARI: pushi(vararray_i[param]); break; case OPC_PUSHVARV: pushv(vararray_v[param]); break; case OPC_PUSHVARP: pushp(vararray_p[param]); break; case OPC_POP: top -= param; break; case OPC_SETVARF: vararray_f[param] = popf(); break; case OPC_SETVARI: vararray_i[param] = popi(); break; case OPC_SETVARV: fb = popf(); fa = popf(); vararray_v[param].set(fa,fb); break; case OPC_SETVARP: vararray_p[param] = popp(); break; case OPC_GETPROP: obj = (VMInterface*)popp(); obj->VM_GetProp(this, param); break; case OPC_SETPROP: obj = (VMInterface*)popp(); obj->VM_SetProp(this, param); break; case OPC_METCALL: obj = (VMInterface*)popp(); obj->VM_MetCall(this, param); break; case OPC_GETPROPV: v1 = (Vec2*)popp(); v1->VM_GetProp(this, param); break; case OPC_SETPROPV: v1 = (Vec2*)popp(); v1->VM_SetProp(this, param); break; case OPC_METCALLV: v1 = (Vec2*)popp(); v1->VM_MetCall(this, param); break; case OPC_JUMP: iptr += param*2; break; case OPC_IFJUMP: ia = popi(); if (ia == 0) iptr += param*2; break; case OPC_INITFOR: ib = popi(); ia = popi(); ++iptr; iparam = code->code[iptr++]; ijmp = iptr; for(ifor=ia;ifor<ib;++ifor) { iptr = ijmp; vararray_i[param] = ifor; execute_ops(iparam); /*for(iptr=ijmp;iptr<ijmp+iparam*2;++iptr) { opfor = code->code[iptr]; pfor = code->code[++iptr]; if (opfor == OPC_EXIT) { --iptr; return; } execute_op(opfor, pfor); }*/ } break; case OPC_LOOP: ; // TODO break; case OPC_I2F: // this will break is floatval uses doubles !! /* ia = *((int*)top); *((floatval*)top) = (float)ia;*/ ia = popi(); pushf((floatval)ia); break; case OPC_F2I: /*fa = *((floatval*)top); *((int*)top) = (int)fa;*/ fa = popf(); pushi((int)fa); break; case OPC_VEC2P: fb = popf(); fa = popf(); v1 = vectemp + (vecidx % 5); ++vecidx; v1->set(fa,fb); pushp(v1); break; case OPC_P2VEC: v1 = popv(); pushv(*v1); break; case OPC_LASTVEC: v1 = vectemp + ((vecidx-1)%5); pushv(*v1); break; // -------------------------------------------------- // -------------------- OPERATORS ------------------- // -------------------------------------------------- case OPC_OP_ADDFF: fa = popf(); *(((floatval*)top)-1) += fa; break; case OPC_OP_ADDII: ia = popi(); *(((int*)top)-1) += ia; break; case OPC_OP_ADDVV: v2 = popv(); v1 = popv(); v.set(*v1); v.add(*v2); pushv(v); break; case OPC_OP_ANDBB: ib = popi(); ia = popi(); pushi(ia & ib); break; case OPC_OP_DIVFF: fa = popf(); *(((floatval*)top)-1) /= fa; break; case OPC_OP_DIVII: ia = popi(); *(((int*)top)-1) /= ia; break; case OPC_OP_DIVVF: fa = popf(); v1 = (Vec2*)popp(); v.set(*v1); v.div(fa); pushv(v); break; case OPC_OP_EQFF: fb = popf(); fa = popf(); pushi((int)(fa == fb)); break; case OPC_OP_EQII: ib = popi(); ia = popi(); pushi((int)(ia == ib)); break; case OPC_OP_EQVV: v2 = popv(); v1 = popv(); pushi((int)(ia == ib)); break; case OPC_OP_GEFF: fb = popf(); fa = popf(); pushi((int)(fa >= fb)); break; case OPC_OP_GEII: ib = popi(); ia = popi(); pushi((int)(ia >= ib)); break; case OPC_OP_GTFF: fb = popf(); fa = popf(); pushi((int)(fa > fb)); break; case OPC_OP_GTII: ib = popi(); ia = popi(); pushi((int)(ia > ib)); break; case OPC_OP_LEFF: fb = popf(); fa = popf(); pushi((int)(fa <= fb)); break; case OPC_OP_LEII: ib = popi(); ia = popi(); pushi((int)(ia <= ib)); break; case OPC_OP_LTFF: fb = popf(); fa = popf(); pushi((int)(fa < fb)); break; case OPC_OP_LTII: ib = popi(); ia = popi(); pushi((int)(ia < ib)); break; case OPC_OP_MULFF: fa = popf(); *(((floatval*)top)-1) *= fa; break; case OPC_OP_MULII: ia = popi(); *(((int*)top)-1) *= ia; break; case OPC_OP_MULVF: fa = popf(); v1 = popv(); v.set(*v1); v.mul(fa); pushv(v); break; case OPC_OP_NEFF: fb = popf(); fa = popf(); pushi((int)(fa != fb)); break; case OPC_OP_NEGF: *(((floatval*)top)-1) = -(*((floatval*)top)); break; case OPC_OP_NEGI: *(((int*)top)-1) = -(*((int*)top)); break; case OPC_OP_NEGV: v1 = popv(); v.set(-v1->x, -v1->y); pushv(v); break; case OPC_OP_NEII: ib = popi(); ia = popi(); pushi((int)(ia != ib)); break; case OPC_OP_NEVV: v2 = popv(); v1 = popv(); pushi((int)(ia != ib)); break; case OPC_OP_NOTBB: ; // TODO break; case OPC_OP_ORBB: ; // TODO break; case OPC_OP_SUBFF: fa = popf(); *(((floatval*)top)-1) -= fa; break; case OPC_OP_SUBII: ia = popi(); *(((int*)top)-1) -= ia; break; case OPC_OP_SUBVV: v2 = (Vec2*)popp(); v1 = (Vec2*)popp(); v.set(*v1); v.sub(*v2); pushv(v); break; case OPC_OP_XORBB: ; // TODO break; } } }
// on "init" you need to initialize your instance bool HelloWorld::init() { ////////////////////////////// // 1. super init first if ( !Layer::init() ) { return false; } Size visibleSize = Director::getInstance()->getVisibleSize(); Vec2 origin = Director::getInstance()->getVisibleOrigin(); auto bg = Sprite::create("HelloWorld.png"); bg->setScale(this->getContentSize().width / bg->getContentSize().width, this->getContentSize().height / bg->getContentSize().height); bg->setColor(Color3B::ORANGE); bg->setAnchorPoint(Vec2::ANCHOR_BOTTOM_LEFT); addChild(bg); m_gameLy = Layer::create(); m_gameLy->setContentSize(Size(visibleSize.width, visibleSize.height * 4)); addChild(m_gameLy, 1); m_hubLy = HubLayer::create(); m_hubLy->setContentSize(Size(visibleSize.width * 0.25, visibleSize.height * 4 * 0.15)); m_hubLy->setPosition(Vec2(1, (this->getContentSize().height - m_hubLy->getContentSize().height) / 2)); addChild(m_hubLy, 1); m_hubLy->setgLayer(m_gameLy); auto lD = LayerColor::create(Color4B(255.0, 0, 0, 255.0), visibleSize.width, 30); lD->setTag(10); lD->setPosition(Vec2(0, m_gameLy->getContentSize().height - lD->getContentSize().height)); m_gameLy->addChild(lD); auto lP = LayerColor::create(Color4B(0, 255.0, 0, 255.0), visibleSize.width, 30); m_gameLy->addChild(lP); lP->setTag(11); auto dispatcher = Director::getInstance()->getEventDispatcher(); auto touchListener = EventListenerTouchOneByOne::create(); touchListener->setSwallowTouches(true); touchListener->onTouchBegan = [this](Touch *touch, Event *event)->bool { m_lastMove = this->convertTouchToNodeSpace(touch); return true; }; touchListener->onTouchMoved = [this](Touch *touch, Event *event) { auto location = this->convertTouchToNodeSpace(touch); Vec2 v = Vec2(location.x - m_lastMove.x, location.y - m_lastMove.y); Vec2 des = m_gameLy->getPosition(); des.add(v); m_gameLy->setPosition(boundeEdge(des)); m_lastMove = location; }; touchListener->onTouchEnded = [this](Touch *touch, Event *event){}; touchListener->onTouchCancelled = [this](Touch *touch, Event *event){}; dispatcher->addEventListenerWithSceneGraphPriority(touchListener, this); schedule(schedule_selector(HelloWorld::step)); return true; }