void Mage::specialAttack() { _specialAttackChance = MageValues._specialAttackChance; _angry = ActorCommonValues._angry; struct MESSAGE_ANGRY_CHANGE angryChange = { _name, _angry, _angryMax }; MessageDispatchCenter::getInstance()->dispatchMessage(ANGRY_CHANGE, this); experimental::AudioEngine::play2d(MageProperty.specialAttackShout, false, 0.5); experimental::AudioEngine::play2d(MageProperty.ice_special, false, 1); //mage will create 3 ice spikes on the ground auto pos1 = getPosTable(this); auto pos2 = pos1; auto pos3 = pos2; pos1.x += 130; pos2.x += 330; pos3.x += 530; pos1 = ccpRotateByAngle(pos1, _myPos, _curFacing); pos2 = ccpRotateByAngle(pos2, _myPos, _curFacing); pos3 = ccpRotateByAngle(pos3, _myPos, _curFacing); MageIceSpikes::CreateWithPos(pos1, _curFacing, _specialAttack, this); auto spike2 = [&]() { experimental::AudioEngine::play2d(MageProperty.specialAttackShout, false, 0.5); MageIceSpikes::CreateWithPos(pos2, _curFacing, _specialAttack, this); }; auto spike3 = [&]() { experimental::AudioEngine::play2d(MageProperty.specialAttackShout, false, 0.5); MageIceSpikes::CreateWithPos(pos3, _curFacing, _specialAttack, this); }; auto wait2 = DelayTime::create(0.25); this->runAction(Sequence::create(wait2, CallFunc::create(spike2), wait2->clone(), CallFunc::create(spike3), NULL)); //this->runAction(Sequence::create(wait3, CallFunc::create(spike3), NULL)); }
void f1(CCPoint p1, CCPoint p2, float d, CCPoint *o1, CCPoint *o2) { float l = ccpDistance(p1, p2); float angle = fangle(ccpSub(p2, p1)); *o1 = ccpRotateByAngle(ccp(p1.x + l,p1.y + d), p1, angle); *o2 = ccpRotateByAngle(ccp(p1.x + l,p1.y - d), p1, angle); }
Point Terrain::movingRevision(const Point& last, const Point& updated) { CC_UNUSED_PARAM(last); if (isInStandGround(updated)) { return ccp(0.0f, 0.0f); } BorderNode* pSgmt = borderEntry; Point wallVect, nextWallVect, sgmtStart, sgmtEnd, nextEnd, dividerVect; Point revised; do { sgmtStart = ccp(tileSize * pSgmt->segment.start.col, tileSize * pSgmt->segment.start.row); sgmtEnd = ccp(tileSize * pSgmt->segment.end.col, tileSize * pSgmt->segment.end.row); nextEnd = ccp(tileSize * pSgmt->next->segment.end.col, tileSize * pSgmt->next->segment.end.row); wallVect = ccpRotateByAngle(sgmtEnd - sgmtStart, ccp(0, 0), CC_DEGREES_TO_RADIANS(-90)); nextWallVect = ccpRotateByAngle(nextEnd - sgmtEnd, ccp(0, 0), CC_DEGREES_TO_RADIANS(-90)); if (ccpCross(sgmtEnd - sgmtStart, nextEnd - sgmtEnd) > 0) // 凸角 { if (pointOnLineSide(updated, sgmtStart, sgmtEnd) == POS_ON_THE_RIGHT && pointOnLineSide(updated, sgmtStart, sgmtStart + wallVect) == POS_ON_THE_LEFT && pointOnLineSide(updated, sgmtEnd, sgmtEnd + wallVect) == POS_ON_THE_RIGHT) { // 作个垂线修正.. revised = sgmtStart + ccpProject(updated - sgmtStart, sgmtEnd - sgmtStart); break; } else if (pointOnLineSide(updated, sgmtEnd, sgmtEnd + wallVect) == POS_ON_THE_LEFT && pointOnLineSide(updated, sgmtEnd, sgmtEnd + nextWallVect) == POS_ON_THE_RIGHT) { // 修正到当前边末端的凸角点.. revised = sgmtEnd; break; } } else // 凹角 { dividerVect = ccpNormalize(nextEnd - sgmtEnd) - ccpNormalize(sgmtEnd - sgmtStart); if (pointOnLineSide(updated, sgmtStart, sgmtEnd) == POS_ON_THE_RIGHT && pointOnLineSide(updated, sgmtStart, sgmtStart + wallVect) == POS_ON_THE_LEFT && pointOnLineSide(updated, sgmtEnd, sgmtEnd + dividerVect) == POS_ON_THE_RIGHT) { // 作个垂线修正.. revised = sgmtStart + ccpProject(updated - sgmtStart, sgmtEnd - sgmtStart); break; } } pSgmt = pSgmt->next; } while (pSgmt != borderEntry); return (revised - updated); }
void RippleNode::draw() { CCNodeRGBA::draw(); ccGLBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); ccDrawInit(); ccDrawColor4B(getColor().r, getColor().g, getColor().b, getOpacity()); glLineWidth(3.f * SCREEN_SCALE()); ccPointSize(3.f * SCREEN_SCALE() * 0.5f); Rig rig; rig.reserve(RIG_VERTEXES()); for(int i = 0; i < RIG_VERTEXES(); i++) { CCPoint vertex = ccpRotateByAngle(CCPointMake(0, 200.f * SCREEN_SCALE()), CCPointZero, M_PI * 2 * i / RIG_VERTEXES() + getRotation()); rig.push_back(vertex); } ccDrawPoly(&rig[0], rig.size(), true); ccDrawPoint(CCPointZero); ccDrawFree(); ccGLBlendFunc(CC_BLEND_SRC, CC_BLEND_DST); CC_INCREMENT_GL_DRAWS(1); }
void Joystick::drawArrow() { CCPoint point=ccpAdd(_touchedPoint, _vector); ccVertex2F vertices[4]={{point.x,point.y},{point.x-25,point.y-15},{point.x,point.y+35},{point.x+25,point.y-15}}; for (int i=0; i<4; ++i) { CCPoint tempPoint=ccpRotateByAngle(ccp(vertices[i].x,vertices[i].y), ccp(point.x,point.y),-1*ccpToAngle(ccp(_vector.y,_vector.x))); vertices[i]=vertex2(tempPoint.x, tempPoint.y); } ccColor4F colors[4]={{0,0,0,1},{0,0,0,1},{0,0,0,1},{0,0,0,1}}; ccGLEnableVertexAttribs(kCCVertexAttribFlag_Position|kCCVertexAttribFlag_Color); glVertexAttribPointer(kCCVertexAttrib_Position, 2, GL_FLOAT, GL_FALSE, 0, vertices); glVertexAttribPointer(kCCVertexAttrib_Color, 4, GL_FLOAT, GL_FALSE, 0, colors); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); }
void LFTwirl::update(float time) { //// 优化部分 //{ // flag ++; // if (flag % 2 != 0) // return; // flag = 0; //} int i, j; int index = 0; for (i = 0; i < m_sGridSize.width + 1; ++i) { for (j = 0; j < m_sGridSize.height + 1; ++j) { ccVertex3F v = originalVertex(ccp(i, j)); CCPoint relativedPos = ccp(v.x - m_position.x,v.y - m_position.y); CCPoint newPos; float dis = 0.0f; if (gridDistanceArray) { dis = gridDistanceArray[index];index++; }else { dis = ccpLength(relativedPos) + 1.0f; } // 基于相对中心坐标计算 { float tempAngle = mAngle; tempAngle = tempAngle / dis * (mRadius*10);// 跟半径成反比,半径越大,转动角度越小 newPos = ccpRotateByAngle(relativedPos,ccp(1,0),CC_DEGREES_TO_RADIANS(tempAngle)); newPos.x *= mScale; newPos.y *= mScale; } v.x = newPos.x + m_position.x ; v.y = newPos.y + m_position.y; setVertex(ccp(i, j), v); } } mScale *= mScaleFactor; mAngle += mAngleFactor; }
void RigRandom(Rig& targetRig, int vertexes) { //Other implementations can be found at: //http://pastebin.com/wdKmSrL3 //Let's create the goal polygon first. //Due to preventing intersections, one more vertex maybe created that stated over here. unsigned int vertexNum = vertexes; //Now that we have the number of vertexes, let's create the number of angles needed. std::vector<float> angles; angles.reserve(vertexNum); for(int angleIter = 0; angleIter < vertexNum; angleIter++) { //angles.push_back(angleIter * (angleSize + CCRANDOM_0_1())); angles.push_back(GetRandomAngle()); } std::sort(angles.begin(), angles.end()); //Iterate over the angles, create a vertexes stack. targetRig.reserve(vertexNum); for(std::vector<float>::iterator iter = angles.begin(); iter != angles.end(); iter++) { float angle = (*iter); CCPoint highPoint = ccp(0, RIG_MIN_RADIUS() + (RIG_MAX_RADIUS()-RIG_MIN_RADIUS()) * CCRANDOM_0_1()); targetRig.push_back(ccpRotateByAngle(highPoint, CCPointZero, angle)); } //Make sure the first and last point doesn't intersect. for(int i = 0; i < targetRig.size()-1; i++) { CCPoint startPoint = targetRig[i]; CCPoint endPoint = targetRig[i+1]; if(ccpSegmentIntersect(startPoint, endPoint, targetRig.front(), targetRig.back())) { targetRig.push_back(CCPointZero); break; } } }
void CArmySprite::fireBullet(float fEscapeTime) { CCNode *m_pTarget = (CCNode*)(getParent()->getChildByTag(PALYER_TYPE)); m_fTime += fEscapeTime; if (m_sCurData.mKind == AK_MISSILEARMY && m_fTime > 1.5f) { BULLET_DATA mData; mData.mAttack = m_sCurData.mAttack * 2; mData.mKind = BK_TARCKROCKET; mData.mMoveSpeed = 200.0f; mData.mDirection = ccpNormalize(ccpSub(m_pTarget->getPosition(), getPosition())); CBullet *pBullet = CBullet::createBullet(ENEMY_BULLET, mData, BK_TARCKROCKET); pBullet->setPosition(ccp(getPositionX(), getPositionY())); getParent()->addChild(pBullet, ABULLET_ZORDER); } if (m_fTime > 0.5f) { if (m_nBulletNum >= 2) { m_fFireCoolTime = 0.0f; m_nBulletNum = 0; } m_fTime = 0.0f; m_nBulletNum ++; BULLET_DATA mData; mData.mAttack = m_sCurData.mAttack; if (m_sCurData.mKind != AK_MISSILEARMY) { mData.mDirection = ccpNormalize(ccpSub(m_pTarget->getPosition(), getPosition())); mData.mKind = BK_ARMY01; mData.mMoveSpeed = 300.0f; CBullet *pBullet = CBullet::createBullet(ENEMY_BULLET, mData, BK_ARMY01); CCPoint mPos = ccpRotateByAngle(ccp(0, -48), ccp(0,0), -CC_DEGREES_TO_RADIANS(m_pTurretSprite->getRotation())); pBullet->setPosition(ccp(getPositionX() + mPos.x, getPositionY() + mPos.y)); getParent()->addChild(pBullet, ABULLET_ZORDER); } } }
HitTestResult* hitTestRoundRect(RoundBodyNode* a, RectBodyNode* b) { Point ca = a->getCenter(); float ra = a->getRadius(); Point cb = b->getCenter(); float wb = b->getWidth(); float hb = b->getHeight(); float ab = CC_DEGREES_TO_RADIANS(-b->getAngle()); float rb = b->getRadius(); Point rrp; bool hit = isRoundCrossRect(ca, ra, cb, wb, hb, ccpForAngle(ab), &rrp); if( hit ) { float distance; float angle = ccpToAngle(rrp); Point hp = ccp(cos(angle), sin(angle)) * rb; if(hp.x > wb/2) hp.x = wb/2; else if(hp.x < -wb/2) hp.x = -wb/2; if(hp.y > hb/2) hp.y = hb/2; else if(hp.y < -hb/2) hp.y = -hb/2; hp = cb + ccpRotateByAngle(hp, POINT_ZERO, ab); distance = ccpDistance(ca, hp); return HitTestResult::create(HTRT_CROSS, hp, distance); } else { return HitTestResult::create(HTRT_NONE); } }
/// // Update does the work of mapping the texture onto the triangles // It now doesn't occur the cost of free/alloc data every update cycle. // It also only changes the percentage point but no other points if they have not // been modified. // // It now deals with flipped texture. If you run into this problem, just use the // sprite property and enable the methods flipX, flipY. /// void CCProgressTimer::updateRadial() { if (!m_pSprite) { return; } float alpha = m_fPercentage / 100.f; float angle = 2.f*((float)M_PI) * ( m_bReverseDirection ? alpha : 1.0f - alpha); // We find the vector to do a hit detection based on the percentage // We know the first vector is the one @ 12 o'clock (top,mid) so we rotate // from that by the progress angle around the m_tMidpoint pivot CCPoint topMid = ccp(m_tMidpoint.x, 1.f); CCPoint percentagePt = ccpRotateByAngle(topMid, m_tMidpoint, angle); int index = 0; CCPoint hit = CCPoint::zero; if (alpha == 0.f) { // More efficient since we don't always need to check intersection // If the alpha is zero then the hit point is top mid and the index is 0. hit = topMid; index = 0; } else if (alpha == 1.f) { // More efficient since we don't always need to check intersection // If the alpha is one then the hit point is top mid and the index is 4. hit = topMid; index = 4; } else { // We run a for loop checking the edges of the texture to find the // intersection point // We loop through five points since the top is split in half float min_t = FLT_MAX; for (int i = 0; i <= kProgressTextureCoordsCount; ++i) { int pIndex = (i + (kProgressTextureCoordsCount - 1))%kProgressTextureCoordsCount; CCPoint edgePtA = boundaryTexCoord(i % kProgressTextureCoordsCount); CCPoint edgePtB = boundaryTexCoord(pIndex); // Remember that the top edge is split in half for the 12 o'clock position // Let's deal with that here by finding the correct endpoints if(i == 0){ edgePtB = ccpLerp(edgePtA, edgePtB, 1-m_tMidpoint.x); } else if(i == 4){ edgePtA = ccpLerp(edgePtA, edgePtB, 1-m_tMidpoint.x); } // s and t are returned by ccpLineIntersect float s = 0, t = 0; if(ccpLineIntersect(edgePtA, edgePtB, m_tMidpoint, percentagePt, &s, &t)) { // Since our hit test is on rays we have to deal with the top edge // being in split in half so we have to test as a segment if ((i == 0 || i == 4)) { // s represents the point between edgePtA--edgePtB if (!(0.f <= s && s <= 1.f)) { continue; } } // As long as our t isn't negative we are at least finding a // correct hitpoint from m_tMidpoint to percentagePt. if (t >= 0.f) { // Because the percentage line and all the texture edges are // rays we should only account for the shortest intersection if (t < min_t) { min_t = t; index = i; } } } } // Now that we have the minimum magnitude we can use that to find our intersection hit = ccpAdd(m_tMidpoint, ccpMult(ccpSub(percentagePt, m_tMidpoint),min_t)); } // The size of the vertex data is the index from the hitpoint // the 3 is for the m_tMidpoint, 12 o'clock point and hitpoint position. bool sameIndexCount = true; if(m_nVertexDataCount != index + 3){ sameIndexCount = false; CC_SAFE_FREE(m_pVertexData); m_nVertexDataCount = 0; } if(!m_pVertexData) { m_nVertexDataCount = index + 3; m_pVertexData = (ccV2F_C4B_T2F*)malloc(m_nVertexDataCount * sizeof(ccV2F_C4B_T2F)); CCAssert( m_pVertexData, "CCProgressTimer. Not enough memory"); } updateColor(); if (!sameIndexCount) { // First we populate the array with the m_tMidpoint, then all // vertices/texcoords/colors of the 12 'o clock start and edges and the hitpoint m_pVertexData[0].texCoords = textureCoordFromAlphaPoint(m_tMidpoint); m_pVertexData[0].vertices = vertexFromAlphaPoint(m_tMidpoint); m_pVertexData[1].texCoords = textureCoordFromAlphaPoint(topMid); m_pVertexData[1].vertices = vertexFromAlphaPoint(topMid); for(int i = 0; i < index; ++i){ CCPoint alphaPoint = boundaryTexCoord(i); m_pVertexData[i+2].texCoords = textureCoordFromAlphaPoint(alphaPoint); m_pVertexData[i+2].vertices = vertexFromAlphaPoint(alphaPoint); } } // hitpoint will go last m_pVertexData[m_nVertexDataCount - 1].texCoords = textureCoordFromAlphaPoint(hit); m_pVertexData[m_nVertexDataCount - 1].vertices = vertexFromAlphaPoint(hit); }
///*************************************************************************************** /// CalcIK_2D_CCD /// Given a bone chain located at the origin, this function will perform a single cyclic /// coordinate descent (CCD) iteration. This finds a solution of bone angles that places /// the final bone in the given chain at a target position. The supplied bone angles are /// used to prime the CCD iteration. If a valid solution does not exist, the angles will /// move as close to the target as possible. The user should resupply the updated angles /// until a valid solution is found (or until an iteration limit is met). /// /// returns: CCD_Result.Success when a valid solution was found. /// CCD_Result.Processing when still searching for a valid solution. /// CCD_Result.Failure when it can get no closer to the target. ///*************************************************************************************** CCD_Result CalcIK_CCD(Bone *startBone, Bone *endBone, CCPoint &targetPoint, float arrivalDist) { double arrivalDistSqr = arrivalDist * arrivalDist; //=== // Track the end effector position (the final bone) CCPoint endPoint = ccp(startBone->m_tWorldTransform.tx, startBone->m_tWorldTransform.ty); CCPoint currentPoint = ccp(0, 0); //=== // Perform CCD on the bones by optimizing each bone in a loop // from the final bone to the root bone bool modifiedBones = false; Bone *currentBone = startBone->getParentBone(); Bone *lastCurrentBone = startBone; while(!currentBone->getParentBone() == NULL) { currentPoint = ccp(currentBone->m_tWorldTransform.tx, currentBone->m_tWorldTransform.ty); // Get the vector from the current bone to the end effector position. double curToEndX = endPoint.x - currentPoint.x; double curToEndY = endPoint.y - currentPoint.y; double curToEndMag = ccpDistance(endPoint, currentPoint); // Get the vector from the current bone to the target position. double curToTargetX = targetPoint.x - currentPoint.x; double curToTargetY = targetPoint.y - currentPoint.y; double curToTargetMag = ccpDistance(targetPoint, currentPoint); // Get rotation to place the end effector on the line from the current // joint position to the target postion. double cosRotAng; double sinRotAng; double endTargetMag = (curToEndMag*curToTargetMag); if( endTargetMag <= epsilon ) { cosRotAng = 1; sinRotAng = 0; } else { cosRotAng = (curToEndX*curToTargetX + curToEndY*curToTargetY) / endTargetMag; sinRotAng = (curToEndX*curToTargetY - curToEndY*curToTargetX) / endTargetMag; } // Clamp the cosine into range when computing the angle (might be out of range // due to floating point error). double rotAng = acos( MAX(-1, MIN(1, cosRotAng) ) ); if( sinRotAng < 0.0 ) rotAng = -rotAng; // Rotate the end effector position. endPoint.x = currentPoint.x + cosRotAng*curToEndX - sinRotAng*curToEndY; endPoint.y = currentPoint.y + sinRotAng*curToEndX + cosRotAng*curToEndY; #if CS_DEBUG_FOR_EDIT // Rotate the current bone in local space (this value is output to the user) if (dynamic_cast<EditorTween*>(currentBone->getTween()) != 0) { EditorTween *tween = ((EditorTween*)currentBone->getTween()); if(currentBone == endBone || currentBone->getChildren()->count() > 1) { CCPoint p = ccpRotateByAngle(ccp(lastCurrentBone->m_tWorldTransform.tx, lastCurrentBone->m_tWorldTransform.ty), currentPoint, rotAng); ((EditorDisplayManager*)currentBone->getDisplayManager())->convertPointToSpace(p); ((EditorTween*)lastCurrentBone->getTween())->editPosition(p.x, p.y); } else { rotAng = tween->getRotation() - rotAng; rotAng = simplifyAngle(rotAng); ((EditorTween*)currentBone->getTween())->editRotation(rotAng); } } else { // if(currentBone == endBone || currentBone->getChildren()->count() > 1) // { // CCPoint p = rotatePointByPoint(currentPoint, ccp(lastCurrentBone->m_tWorldTransform.tx, lastCurrentBone->m_tWorldTransform.ty), rotAng); // lastCurrentBone->setPosition(p.x, p.y); // } // else // { // currentBone->setRotation(simplifyAngle(currentBone->getRotation() - rotAng)); // } } #endif // Check for termination double endToTargetX = (targetPoint.x-endPoint.x); double endToTargetY = (targetPoint.y-endPoint.y); if( endToTargetX*endToTargetX + endToTargetY*endToTargetY <= arrivalDistSqr ) { // We found a valid solution. return Success; } // Track if the arc length that we moved the end effector was // a nontrivial distance. if( !modifiedBones && fabsf(rotAng)*curToEndMag > trivialArcLength ) { modifiedBones = true; } if (currentBone == endBone || currentBone->getChildren()->count() > 1) { break; } lastCurrentBone = currentBone; currentBone = currentBone->getParentBone(); } // We failed to find a valid solution during this iteration. if( modifiedBones ) return Processing; else return Failure; }