kmBool kmRay2IntersectTriangle(const kmRay2* ray, const kmVec2* p1, const kmVec2* p2, const kmVec2* p3, kmVec2* intersection, kmVec2* normal_out) { kmVec2 intersect; kmVec2 final_intersect; kmVec2 normal; kmScalar distance = 10000.0f; kmBool intersected = KM_FALSE; if(kmRay2IntersectLineSegment(ray, p1, p2, &intersect)) { intersected = KM_TRUE; kmVec2 tmp; kmScalar this_distance = kmVec2Length(kmVec2Subtract(&tmp, &intersect, &ray->start)); if(this_distance < distance) { final_intersect.x = intersect.x; final_intersect.y = intersect.y; distance = this_distance; calculate_line_normal(*p1, *p2, &normal); } } if(kmRay2IntersectLineSegment(ray, p2, p3, &intersect)) { intersected = KM_TRUE; kmVec2 tmp; kmScalar this_distance = kmVec2Length(kmVec2Subtract(&tmp, &intersect, &ray->start)); if(this_distance < distance) { final_intersect.x = intersect.x; final_intersect.y = intersect.y; distance = this_distance; calculate_line_normal(*p2, *p3, &normal); } } if(kmRay2IntersectLineSegment(ray, p3, p1, &intersect)) { intersected = KM_TRUE; kmVec2 tmp; kmScalar this_distance = kmVec2Length(kmVec2Subtract(&tmp, &intersect, &ray->start)); if(this_distance < distance) { final_intersect.x = intersect.x; final_intersect.y = intersect.y; distance = this_distance; calculate_line_normal(*p3, *p1, &normal); } } if(intersected) { intersection->x = final_intersect.x; intersection->y = final_intersect.y; if(normal_out) { normal_out->x = normal.x; normal_out->y = normal.y; } } return intersected; }
void calculate_line_normal(kmVec2 p1, kmVec2 p2, kmVec2 other_point, kmVec2* normal_out) { /* A = (3,4) B = (2,1) C = (1,3) AB = (2,1) - (3,4) = (-1,-3) AC = (1,3) - (3,4) = (-2,-1) N = n(AB) = (-3,1) D = dot(N,AC) = 6 + -1 = 5 since D > 0: N = -N = (3,-1) */ kmVec2 edge, other_edge; kmVec2Subtract(&edge, &p2, &p1); kmVec2Subtract(&other_edge, &other_point, &p1); kmVec2Normalize(&edge, &edge); kmVec2Normalize(&other_edge, &other_edge); kmVec2 n; n.x = edge.y; n.y = -edge.x; kmScalar d = kmVec2Dot(&n, &other_edge); if(d > 0.0f) { n.x = -n.x; n.y = -n.y; } normal_out->x = n.x; normal_out->y = n.y; kmVec2Normalize(normal_out, normal_out); }
/** * Reflects a vector about a given surface normal. The surface normal is * assumed to be of unit length. */ kmVec2* kmVec2Reflect(kmVec2* pOut, const kmVec2* pIn, const kmVec2* normal) { kmVec2 tmp; kmVec2Scale(&tmp, normal, 2.0f * kmVec2Dot(pIn, normal)); kmVec2Subtract(pOut, pIn, &tmp); return pOut; }
bool BattleManagerScreen::GetVecBetween( ICastEntity* from, ICastEntity* to, kmVec2& distVec ) { CastWorldModel* world = CastWorldModel::get(); if( !world->isValid(from) || !world->isValid(to) ) return false; kmVec2 pFrom; pFrom.x = pFrom.y = 0; GameEntityView* fromView = getViewForEntity(from); if( fromView != NULL ) { pFrom.x = fromView->getPositionX(); pFrom.y = fromView->getPositionY(); } kmVec2 pTo; pTo.x = pTo.y = 0; GameEntityView* toView = getViewForEntity(to); if( toView != NULL ) { pTo.x = toView->getPositionX(); pTo.y = toView->getPositionY(); }else { CCLog("uhoh.."); } kmVec2Subtract( &distVec, &pFrom, &pTo ); kmVec2Scale(&distVec, &distVec, GAME_UNIT_CONVERSION ); //safe to operate on same vector return true; }
/** * Returns the point mid-way between two others */ kmVec2* kmVec2MidPointBetween(kmVec2* pOut, const kmVec2* v1, const kmVec2* v2) { kmVec2 diff; kmVec2Subtract(&diff, v2, v1); kmVec2Normalize(&diff, &diff); kmVec2Scale(&diff, &diff, kmVec2DistanceBetween(v1, v2) * 0.5); kmVec2Add(pOut, v1, &diff); return pOut; }
void calculate_line_normal(kmVec2 p1, kmVec2 p2, kmVec2* normal_out) { kmVec2 tmp; kmVec2Subtract(&tmp, &p2, &p1); //Get direction vector normal_out->x = -tmp.y; normal_out->y = tmp.x; kmVec2Normalize(normal_out, normal_out); //TODO: should check that the normal is pointing out of the triangle }
static void cxJumpStep(cxAny pav,cxFloat dt,cxFloat time) { cxJump this = pav; cxFloat frac = fmodf( time * this->jumps, 1.0f ); cxFloat y = this->height * 4 * frac * (1 - frac) + this->position.y * time; cxFloat x = this->position.x * time; cxVec2f diff; cxVec2f currPos = this->super.view->position; kmVec2Subtract(&diff, &currPos, &this->prevPos); kmVec2Add(&this->startPos, &diff, &this->startPos); cxVec2f nPos; kmVec2Add(&nPos, &this->startPos, &cxVec2fv(x, y)); this->prevPos = nPos; cxViewSetPos(this->super.view, nPos); }
kmBool kmRay2IntersectBox(const kmRay2* ray, const kmVec2* p1, const kmVec2* p2, const kmVec2* p3, const kmVec2* p4, kmVec2* intersection, kmVec2* normal_out) { kmBool intersected = KM_FALSE; kmVec2 intersect, final_intersect, normal; kmScalar distance = 10000.0f; const kmVec2* points[4]; points[0] = p1; points[1] = p2; points[2] = p3; points[3] = p4; unsigned int i = 0; for(; i < 4; ++i) { const kmVec2* this_point = points[i]; const kmVec2* next_point = (i == 3) ? points[0] : points[i+1]; const kmVec2* other_point = (i == 3 || i == 0) ? points[1] : points[0]; if(kmRay2IntersectLineSegment(ray, this_point, next_point, &intersect)) { kmVec2 tmp; kmScalar this_distance = kmVec2Length(kmVec2Subtract(&tmp, &intersect, &ray->start)); kmVec2 this_normal; calculate_line_normal(*this_point, *next_point, *other_point, &this_normal); if(this_distance < distance && kmVec2Dot(&this_normal, &ray->dir) < 0.0f) { kmVec2Assign(&final_intersect, &intersect); distance = this_distance; intersected = KM_TRUE; kmVec2Assign(&normal, &this_normal); } } } if(intersected) { intersection->x = final_intersect.x; intersection->y = final_intersect.y; if(normal_out) { normal_out->x = normal.x; normal_out->y = normal.y; } } return intersected; }
bool BattleManagerScreen::GetEntitiesInRadius( kmVec2 p, float r, std::vector<ICastEntity*>& entities ) { bool found = false; float upscale = VIEW_UNIT_CONVERSION; kmVec2Scale( &p, &p, upscale ); r *= VIEW_UNIT_CONVERSION; //convert to pixels float rSq = r*r; for( int i=0; i< m_allEntities.size(); i++) { kmVec2 ePos; ePos.x = m_allEntities[i].view->getPositionX(); ePos.y = m_allEntities[i].view->getPositionY(); float distSq = 0; if( ePos.x == p.x ) //handle simple cases first { distSq = ePos.y - p.y; distSq *= distSq; }else if( ePos.y == p.y ) { distSq = ePos.x - p.x; distSq *= distSq; }else { kmVec2 dist; kmVec2Subtract( &dist, &p, &ePos ); distSq = kmVec2LengthSq(&dist); } CCLog("ent %d in radius dist %f", i, sqrt(distSq)); if( distSq <= rSq ) { entities.push_back( m_allEntities[i].model ); found = true; } } return found; }
void BattleManagerScreen::onEntityEffectEvent( CCObject* e ) { GameEntityEffectEvt* evt = dynamic_cast<GameEntityEffectEvt*>(e); if(!evt) return; if( evt->name.compare("Death Grip") == 0 ) { CCLog("death grip"); kmVec2 pOrigin; kmVec2 pTarget; if( !GetEntityPosition(evt->origin, pOrigin) || !GetEntityPosition(evt->target, pTarget) ) { CCLog("aborting death grip evt due to invalid target(s)"); } kmVec2 toTarget; kmVec2Subtract(&toTarget, &pTarget, &pOrigin); kmVec2 u_toTarget; kmVec2Normalize(&u_toTarget, &toTarget); float leashDistance = 1; //one game unit kmVec2 dv; kmVec2Scale(&dv, &u_toTarget, leashDistance ); kmVec2 posEnd; kmVec2Add(&posEnd, &pOrigin, &dv); //convert back to screen coordinates kmVec2Scale(&posEnd, &posEnd, VIEW_UNIT_CONVERSION); GameEntityView* tView = getViewForEntity(evt->target); tView->setPosition(posEnd.x, posEnd.y); } }
/** * Returns the distance between the two points */ kmScalar kmVec2DistanceBetween(const kmVec2* v1, const kmVec2* v2) { kmVec2 diff; kmVec2Subtract(&diff, v2, v1); return fabs(kmVec2Length(&diff)); }