void Player::Update(float dt) { if (this->m_Dead) { return; } // Fix the velocity this->m_Body->v = cpvmult(this->m_Body->v, this->m_Speed / cpvdist(cpVect(), this->m_Body->v)); // Force the player in the upward direction if (this->m_Body->v.y > 0.0f) { this->m_Body->v = cpvneg(this->m_Body->v); } // Update the position cpVect bv(cpBodyGetPos(this->m_Body)); this->m_Position.x = bv.x; this->m_Position.y = bv.y; // Set the steering value this->m_Body->v.x = -this->m_SteeringValue * 5.0f * dt; //#ifdef true int KEY_MAP[5][3] = { {HGEK_LEFT, HGEK_RIGHT, HGEK_O}, {HGEK_A, HGEK_S, HGEK_D} }; // Process keys if (this->m_Hge->Input_GetKeyState(HGEK_ESCAPE)) { this->m_Engine->Shutdown(); } if (this->m_Hge->Input_GetKeyState(KEY_MAP[this->m_PlayerIndex][0])) { this->m_Body->v.x -= SPEED * dt; } if (this->m_Hge->Input_GetKeyState(KEY_MAP[this->m_PlayerIndex][1])) { this->m_Body->v.x += SPEED * dt; } if (this->m_Hge->Input_GetKeyState(KEY_MAP[this->m_PlayerIndex][2])) { this->CycleWeapons(); } //#endif // Do some movement calculations and collision detection this->m_Body->v.x *= FRICTION; this->m_Body->v.y *= FRICTION; // Update particle system float a = abs(this->m_Body->v.x) * 50.0f; float b = abs(this->m_Body->v.y) * 50.0f; this->m_ParticleSystem->info.nEmission = (int) (a * a + b * b); this->m_ParticleSystem->MoveTo(this->m_Position.x, this->m_Position.y); this->m_ParticleSystem->Update(dt); }
static void cpPolyShapeNearestPointQuery(cpPolyShape *poly, cpVect p, cpNearestPointQueryInfo *info) { int count = poly->numVerts; cpSplittingPlane *planes = poly->tPlanes; cpVect *verts = poly->tVerts; cpVect v0 = verts[count - 1]; cpFloat minDist = INFINITY; cpVect closestPoint = cpvzero; cpBool outside = cpFalse; for(int i=0; i<count; i++) { if(cpSplittingPlaneCompare(planes[i], p) > 0.0f) outside = cpTrue; cpVect v1 = verts[i]; cpVect closest = cpClosetPointOnSegment(p, v0, v1); cpFloat dist = cpvdist(p, closest); if(dist < minDist) { minDist = dist; closestPoint = closest; } v0 = v1; } info->shape = (cpShape *)poly; info->p = closestPoint; // TODO div/0 info->d = (outside ? minDist : -minDist); }
cpFloat cpMomentForSegment(cpFloat m, cpVect a, cpVect b, cpFloat r) { cpVect offset = cpvlerp(a, b, 0.5f); // This approximates the shape as a box for rounded segments, but it's quite close. cpFloat length = cpvdist(b, a) + 2.0f*r; return m*((length*length + 4.0f*r*r)/12.0f + cpvlengthsq(offset)); }
// determines mass of freestyle shape // does this by assigning mass to each segment... static double core_freestyle_mass ( cpVect * verts, const int num_verts, const double density ) { double mass = 0; for ( int i = 0; i < num_verts - 1; i++ ) { cpFloat seg_length = cpvdist ( verts[i], verts[i + 1] ); mass += seg_length * density; } return mass; }
// Check if a cpPolyline is longer than a certain length // Takes a range which can wrap around if the polyline is looped. static cpBool cpPolylineIsShort(cpVect *points, int count, int start, int end, cpFloat min) { cpFloat length = 0.0f; for(int i=start; i!=end; i=Next(i, count)){ length += cpvdist(points[i], points[Next(i, count)]); if(length > min) return cpFalse; } return cpTrue; }
// determines moment of freestyle shape // dos this by determining individual moments of segments, //offsetting by distance to center squared static double core_freestyle_moment ( cpVect * verts, const int num_verts, cpVect center, const double density ) { double moment = 0; for ( int i = 0; i < num_verts - 1; i++ ) { cpFloat seg_length = cpvdist ( verts[i], verts[i + 1] ); double seg_mass = seg_length * density; double moment_seg = seg_mass * seg_length * seg_length / 12.0; // moment around center of segment // moment around center of object cpVect seg_center = cpvadd ( verts[i], cpvmult ( cpvsub ( verts[i + 1], verts[i] ) ,seg_length / 2.0 ) ); // center of mass of segment cpFloat seg_disp = cpvdist ( seg_center, center ); // distance of center of mass from center double moment_disp = seg_mass * seg_disp * seg_disp; moment += moment_seg + moment_disp; // add the two moments to total moment } return moment; }
static struct cpShapeMassInfo cpSegmentShapeMassInfo(cpFloat mass, cpVect a, cpVect b, cpFloat r) { struct cpShapeMassInfo info = { mass, cpMomentForBox(1.0f, cpvdist(a, b) + 2.0f*r, 2.0f*r), // TODO is an approximation. cpvlerp(a, b, 0.5f), cpAreaForSegment(a, b, r), }; return info; }
static void draw(void) { ChipmunkDemoDefaultDrawImpl(); cpVect start = QUERY_START; cpVect end = ChipmunkDemoMouse; ChipmunkDebugDrawSegment(start, end, RGBAColor(0,1,0,1)); ChipmunkDemoPrintString("Query: Dist(%f) Point%s, ", cpvdist(start, end), cpvstr(end)); cpSegmentQueryInfo segInfo = {}; if(cpSpaceSegmentQueryFirst(space, start, end, CP_ALL_LAYERS, CP_NO_GROUP, &segInfo)){ cpVect point = cpSegmentQueryHitPoint(start, end, segInfo); // Draw red over the occluded part of the query ChipmunkDebugDrawSegment(point, end, RGBAColor(1,0,0,1)); // Draw a little blue surface normal ChipmunkDebugDrawSegment(point, cpvadd(point, cpvmult(segInfo.n, 16)), RGBAColor(0,0,1,1)); // Draw a little red dot on the hit point. ChipmunkDebugDrawPoints(3, 1, &point, RGBAColor(1,0,0,1)); ChipmunkDemoPrintString("Segment Query: Dist(%f) Normal%s", cpSegmentQueryHitDist(start, end, segInfo), cpvstr(segInfo.n)); } else { ChipmunkDemoPrintString("Segment Query (None)"); } cpNearestPointQueryInfo nearestInfo = {}; cpSpaceNearestPointQueryNearest(space, ChipmunkDemoMouse, 100.0, CP_ALL_LAYERS, CP_NO_GROUP, &nearestInfo); if(nearestInfo.shape){ // Draw a grey line to the closest shape. ChipmunkDebugDrawPoints(3, 1, &ChipmunkDemoMouse, RGBAColor(0.5, 0.5, 0.5, 1.0)); ChipmunkDebugDrawSegment(ChipmunkDemoMouse, nearestInfo.p, RGBAColor(0.5, 0.5, 0.5, 1.0)); // Draw a red bounding box around the shape under the mouse. if(nearestInfo.d < 0) ChipmunkDebugDrawBB(cpShapeGetBB(nearestInfo.shape), RGBAColor(1,0,0,1)); } }
void Renderer::drawBar(const cpShape* shape) { const auto p1 = cpSegmentShapeGetA(shape); const auto p2 = cpSegmentShapeGetB(shape); const auto radius = static_cast<float>(cpSegmentShapeGetRadius(shape)); auto rect = RoundedBar(radius); rect.setOutlineColor(sf::Color::Green); rect.setOutlineThickness(1.0f); rect.setFillColor(sf::Color::Transparent); const auto sfp1 = Utils::toSfv(p1, mTargetSize); const auto sfp2 = Utils::toSfv(p2, mTargetSize); const auto len = static_cast<float>(cpvdist(p1, p2)); if (p1.x == p2.x) { rect.setLength(len); auto y = std::min(sfp1.y, sfp2.y); rect.setRotation(90); rect.setPosition(sfp1.x, y + len / 2 - radius); rect.adjustOrigin(); } else if (p1.y == p2.y) { rect.setLength(len); auto x = std::min(sfp1.x, sfp2.x); rect.setPosition(x + len / 2 - radius, sfp1.y); rect.adjustOrigin(); } { for (auto& target : mTargets) { auto view = target->getView(); auto center = view.getCenter(); auto pieceW = view.getSize().x * 1.0f; auto pieceH = view.getSize().y * 1.0f; auto x = center.x - pieceW / 2.0f; auto y = center.y - pieceH / 2.0f; auto vRect = sf::FloatRect(x, y, pieceW, pieceH); if (vRect.intersects(rect.getGlobalBounds())) { target->draw(rect); } } } }
static void cpPolyShapeNearestPointQuery(cpPolyShape *poly, cpVect p, cpNearestPointQueryInfo *info){ int count = poly->numVerts; cpSplittingPlane *planes = poly->tPlanes; cpVect *verts = poly->tVerts; cpFloat r = poly->r; cpVect v0 = verts[count - 1]; cpFloat minDist = INFINITY; cpVect closestPoint = cpvzero; cpVect closestNormal = cpvzero; cpBool outside = cpFalse; for(int i=0; i<count; i++){ if(cpSplittingPlaneCompare(planes[i], p) > 0.0f) outside = cpTrue; cpVect v1 = verts[i]; cpVect closest = cpClosetPointOnSegment(p, v0, v1); cpFloat dist = cpvdist(p, closest); if(dist < minDist){ minDist = dist; closestPoint = closest; closestNormal = planes[i].n; } v0 = v1; } cpFloat dist = (outside ? minDist : -minDist); cpVect g = cpvmult(cpvsub(p, closestPoint), 1.0f/dist); info->shape = (cpShape *)poly; info->p = cpvadd(closestPoint, cpvmult(g, r)); info->d = dist - r; // Use the normal of the closest segment if the distance is small. info->g = (minDist > MAGIC_EPSILON ? g : closestNormal); }
static void update(int ticks) { messageString[0] = '\0'; cpVect start = cpvzero; cpVect end = /*cpv(0, 85);//*/mousePoint; cpVect lineEnd = end; { char infoString[1024]; sprintf(infoString, "Query: Dist(%f) Point%s, ", cpvdist(start, end), cpvstr(end)); strcat(messageString, infoString); } cpSegmentQueryInfo info = {}; if(cpSpaceSegmentQueryFirst(space, start, end, CP_ALL_LAYERS, CP_NO_GROUP, &info)){ cpVect point = cpSegmentQueryHitPoint(start, end, info); lineEnd = cpvadd(point, cpvzero);//cpvmult(info.n, 4.0f)); char infoString[1024]; sprintf(infoString, "Segment Query: Dist(%f) Normal%s", cpSegmentQueryHitDist(start, end, info), cpvstr(info.n)); strcat(messageString, infoString); } else { strcat(messageString, "Segment Query (None)"); } cpSegmentShapeSetEndpoints(querySeg, start, lineEnd); cpShapeCacheBB(querySeg); // force it to update it's collision detection data so it will draw // normal other stuff. int steps = 1; cpFloat dt = 1.0f/60.0f/(cpFloat)steps; for(int i=0; i<steps; i++){ cpSpaceStep(space, dt); } }
static void cpPolyShapePointQuery(cpPolyShape *poly, cpVect p, cpPointQueryInfo *info){ int count = poly->count; struct cpSplittingPlane *planes = poly->planes; cpFloat r = poly->r; cpVect v0 = planes[count - 1].v0; cpFloat minDist = INFINITY; cpVect closestPoint = cpvzero; cpVect closestNormal = cpvzero; cpBool outside = cpFalse; for(int i=0; i<count; i++){ cpVect v1 = planes[i].v0; outside = outside || (cpvdot(planes[i].n, cpvsub(p,v1)) > 0.0f); cpVect closest = cpClosetPointOnSegment(p, v0, v1); cpFloat dist = cpvdist(p, closest); if(dist < minDist){ minDist = dist; closestPoint = closest; closestNormal = planes[i].n; } v0 = v1; } cpFloat dist = (outside ? minDist : -minDist); cpVect g = cpvmult(cpvsub(p, closestPoint), 1.0f/dist); info->shape = (cpShape *)poly; info->point = cpvadd(closestPoint, cpvmult(g, r)); info->distance = dist - r; // Use the normal of the closest segment if the distance is small. info->gradient = (minDist > MAGIC_EPSILON ? g : closestNormal); }
// takes array of vertices, returns center x and y coordinates in address of x and y // algorithm: take average x value average y value static void core_freestyle_center ( cpVect * verts, const int num_verts, cpVect * center ) { cpFloat tot_length = 0.0; // assume uniform mass, so length can be substitued as mass cpVect center_of_mass = cpvzero; for ( int i = 0; i< num_verts - 1; i++ ) { cpFloat length = cpvdist ( verts[i], verts[i+1] ); cpVect to_cent = cpvmult ( cpvsub ( verts[i+1], verts[i] ), 0.5 ); cpVect loc_center = cpvadd ( verts[i], to_cent ); center_of_mass = cpvadd ( center_of_mass, cpvmult ( loc_center, length ) ); tot_length += length; } center_of_mass = cpvmult ( center_of_mass, 1/tot_length ); center->x = center_of_mass.x; center->y = center_of_mass.y; return; }
Size PhysicsShapeBox::getSize() const { cpShape* shape = _cpShapes.front(); return PhysicsHelper::cpv2size(cpv(cpvdist(cpPolyShapeGetVert(shape, 1), cpPolyShapeGetVert(shape, 2)), cpvdist(cpPolyShapeGetVert(shape, 0), cpPolyShapeGetVert(shape, 1)))); }
cpFloat cpAreaForSegment(cpVect a, cpVect b, cpFloat r) { return 2.0f*r*((cpFloat)M_PI*r + cpvdist(a, b)); }