Vector3 CharacterController::handleCollision(Collision collision, Vector3 pos, Vector3 bounds) { bool stillColliding = true; Vector3 newPos = pos; float amount = 0.0f; Vector3 origPos = pos; while(stillColliding == true) { stillColliding = false; amount += 0.025f; for(int i = 0; i < collision.contacts.size(); i++) { ContactPoint c = collision.contacts.at(i); newPos = pos - (c.normal * amount); if(colliding(newPos, bounds, c.a, c.b, c.c) == true) { stillColliding = true; } else { pos = newPos; amount = 0.0f; collision.contacts.erase(collision.contacts.begin() + i); i--; } } } return pos - origPos; //return pos; }
// check if given rect is within the rects of any enemies in the room // return true if at least one enemy collides and apply damage to that enemies health // this version takes in a float to use as output for interpenatration distance bool Spawner::collEnemies(FRect a_rect, float a_dmg, V2DF pos, V2DF* pen, SIDE side) { // check against all enemies in the room for(int i = 0; i < m_enemies.size(); i++) { // first calculate its bounding rect FRect eRect = m_enemies.get(i)->getBoundRect(); if( colliding(a_rect, eRect) ) { m_enemies.get(i)->takeDmg(a_dmg); //pos = m_enemies.get(i)->getPosition(); // this enemy collides with the given rect // assume collision rects are both 8x8 switch(side) { case RIGHT: pen->x = (a_rect.right - eRect.left); break; case LEFT: pen->x = (a_rect.left - eRect.right); break; case TOP: pen->y = (a_rect.top - eRect.bottom); break; case BOT: pen->y = (a_rect.bottom - eRect.top); break; } return true; } } // no collisions occured return false; }
// check if given rect is within the rects of any enemies in the room // return true if at least one enemy collides and apply damage to that enemies health bool Spawner::collEnemies(FRect a_rect, float a_dmg) { // check against all enemies in the room for(int i = 0; i < m_enemies.size(); i++) { // first calculate its bounding rect FRect eRect = m_enemies.get(i)->getBoundRect(); if( colliding(a_rect, eRect) ) { m_enemies.get(i)->takeDmg(a_dmg); // this enemy collides with the given rect return true; } } // no collisions occured return false; }
Vector3 CharacterController::handleStep(Collision collision, Vector3 pos, Vector3 bounds) { bool stillColliding = true; Vector3 change; while(stillColliding == true) { stillColliding = false; change.y += 0.01f; for(int i = 0; i < collision.contacts.size(); i++) { ContactPoint c = collision.contacts.at(i); if(colliding(pos + change, bounds, c.a, c.b, c.c) == true) { stillColliding = true; } } } return change; }
int main() { die_if(SDL_Init(SDL_INIT_VIDEO), "unable to init SDL"); die_if(!(g_window = SDL_CreateWindow(WIN_TITLE, WIN_X, WIN_Y, WIN_WIDTH, WIN_HEIGHT, 0)), "unable to create window"); die_if(!(g_screen = SDL_GetWindowSurface(g_window)), "unable to create window surface"); die_if(!(g_renderer = SDL_CreateRenderer(g_window, -1, SDL_RENDERER_ACCELERATED)), "unable to create renderer"); die_if(SDL_SetRenderDrawColor( g_renderer, 0x0, 0x0, 0x0, 0xFF ), "unable to set draw color"); g_perf_freq = SDL_GetPerformanceFrequency(); // init textures { SDL_Surface *srfc = NULL; for(unsigned int i = 0; i < NUM_TEX; ++i) { die_if(!(srfc = SDL_LoadBMP((char*)g_tex[i])), "unable to load bitmap"); die_if(!(g_tex[i] = SDL_CreateTextureFromSurface(g_renderer, srfc)) , "unable to create bmp texture"); g_tex_w[i] = srfc->w; g_tex_h[i] = srfc->h; SDL_FreeSurface(srfc); } } alloc_obj(SHIP_TID); int nufos = NUM_UFOS; for(int i = 0; i < nufos; ++i) { alloc_obj(UFO_TID); } Uint64 t0 = SDL_GetPerformanceCounter(); /* used to optimize (minimize) calls to rand() */ #define HASBITS(x,y) (((x) & (y)) == (y)) /* int foo = 0; */ /* for(int i = 0; i < 100000; ++i) */ /* { */ /* int r = rand(); */ /* if (HASBITS(r,0x7) || HASBITS(r,0x70)) ++foo; */ /* } */ // printf("%d\n", foo); // exit(-1); while (1) { // SDL_Delay(10); SDL_Event e; Uint64 t1 = SDL_GetPerformanceCounter(); float dt; dt = (float)(t1 - t0)/g_perf_freq; t0 = t1; /* user events */ if (SDL_PollEvent(&e)) { if (e.type == SDL_QUIT) { exit_cleanup(0); } if (e.type == SDL_KEYDOWN) { SDL_Keycode sym = e.key.keysym.sym; if(sym == SDLK_SPACE) { alloc_timer_1s(alloc_obj(PHOTON_TID), t1); } g_obj_ax[0] = sym == SDLK_LEFT ? -(X_ACC) : (sym == SDLK_RIGHT ? X_ACC : 0.0f); g_obj_ay[0] = sym == SDLK_UP ? -(Y_ACC) : (sym == SDLK_DOWN ? Y_ACC : 0.0f); } } /* ai events */ for(int i = 1; i < nufos + 1; ++i) { int r = rand(); #define RAND_FREQ 0xf g_obj_ax[i] = HASBITS(r,RAND_FREQ) ? X_ACC : 0.0f; g_obj_ax[i] += HASBITS(r,RAND_FREQ << 8) ? -(X_ACC) : 0.0f; g_obj_ax[i] /= 100.0f; g_obj_ay[i] = HASBITS(r,RAND_FREQ << 16) ? Y_ACC : 0.0f; g_obj_ay[i] += HASBITS(r,RAND_FREQ << 24) ? -(Y_ACC) : 0.0f; g_obj_ay[i] /= 100.0f; } /* timer events */ for(int i = 0; i < g_ntimers; ++i) { if(t1 >= g_timer_expire[i]) { dealloc_timer_1s(i); } } /* physics update */ for(int i = g_nobjs - 1; i >= 0 ; --i) { update(&g_obj_x[i], &g_obj_vx[i], &g_obj_ax[i], dt, -OBJ_W(i), WIN_WIDTH); update(&g_obj_y[i], &g_obj_vy[i], &g_obj_ay[i], dt, -OBJ_H(i), WIN_HEIGHT); } /* collisions */ for(int i = g_nobjs - 1; i >= 0 ; --i) { for(int j = i - 1; j >= 0 ; --j) { if (colliding(i,j)) { } } } /* rendering */ SDL_RenderClear(g_renderer); /* ignore return */ SDL_Texture *tex = g_tex[UFO_TID]; for(int i = 1; i < nufos + 1; ++i) { render(i, tex); } render(0, g_tex[SHIP_TID]); tex = g_tex[PHOTON_TID]; for(int i = 1 + nufos; i < 1 + nufos + g_ntimers; ++i) { render(i, tex); } SDL_RenderPresent(g_renderer); } return 0; }
void CharacterController::checkCollision(MeshCollider* collider) { Vector3 pos = getGameObject()->getTransform()->getPosition(); Mesh* mesh = collider->getMesh(); std::vector<Vector3>* vertices = mesh->getVertices(); // We basically want to set the mesh to the origin, including its rotation. // If we rotate the mesh, then we need to make sure we rotate the characters bounds too // so that the angle between the mesh and character remains the same. // If we set position to 0, 0, then we need to make the characters bounds box move the same way // (minus the mesh's position) so that it doesn't get closer. Matrix4x4 mat = Matrix4x4::getTrs(collider->getGameObject()->getTransform()->getPosition(), collider->getGameObject()->getTransform()->getRotation(), Vector3(1, 1, 1)); mat = mat.inverse(); Vector3 relPos = mat * pos; Vector3 extents = bounds.extents; extents.y = extents.y / 2.0f; // Set to 20.0f for a large step //********************************************** Collision collision; //collision.relativeVelocity = frameMoveSpeed; for(int v = 0; v < vertices->size(); v+=3) { Vector3 a = vertices->at(v); Vector3 b = vertices->at(v+1); Vector3 c = vertices->at(v+2); if(colliding(relPos, extents, a, b, c) == true) { ContactPoint contact; contact.normal = findNormal(a, b, c); contact.thisCollider = this; contact.otherCollider = collider; contact.a = a; contact.b = b; contact.c = c; collision.contacts.push_back(contact); } } Matrix4x4 rotMat = Matrix4x4::getIdentity(); rotMat = rotMat.rotate(collider->getGameObject()->getTransform()->getRotation() * -1.0f); if(collision.contacts.size() > 0) { //relPos = handleCollision(collision, relPos, extents); //relPos = relPos + (rotMat * handleCollision(collision, relPos, extents)); relPos = relPos + handleCollision(collision, relPos, extents); } //******************************************* /////////////////////////////////// Collision stepCollision; Vector3 stepExtents = bounds.extents; stepExtents.x = stepExtents.x / 2.0f; stepExtents.z = stepExtents.z / 2.0f; stepExtents.y = stepExtents.y + 0.01f; for(int v = 0; v < vertices->size(); v+=3) { Vector3 a = vertices->at(v); Vector3 b = vertices->at(v+1); Vector3 c = vertices->at(v+2); if(colliding(relPos, stepExtents, a, b, c) == true) { ContactPoint contact; contact.normal = findNormal(a, b, c); contact.thisCollider = this; contact.otherCollider = collider; contact.a = a; contact.b = b; contact.c = c; stepCollision.contacts.push_back(contact); } } stepExtents.y = stepExtents.y - 0.01f; if(stepCollision.contacts.size() > 0) { grounded = true; relPos = relPos + (rotMat * handleStep(stepCollision, relPos, stepExtents)); } else { //grounded = false; } /////////////////////////////////// mat = mat.inverse(); getGameObject()->getTransform()->setPosition(mat * relPos); }
mousestate uielement::sendmouse(vector2d pos, mousestate state) { if (active) { mousestate ret = state; bool drag = false; for (vector<dragicon>::iterator dgit = dragicons.begin(); dgit != dragicons.end(); ++dgit) { if (colliding(pos, dgit->bounds(), position)) { drag = true; if (!dgit->dragged()) { switch (state) { case MST_IDLE: case MST_CANCLICK: case MST_CANCLICK2: ret = MST_CANGRAB; break; case MST_CLICKING: dgit->setdrag(pos, position); app.getui()->seticon(dgit._Ptr); ret = MST_GRABBING; break; } } } if (drag) { return ret; } } bool anycoll = false; for (map<short, button>::iterator itbt = buttons.begin(); itbt != buttons.end(); ++itbt) { string btst = itbt->second.getstate(); if (util::colliding(pos, itbt->second.bounds(), position) && itbt->second.isactive()) { anycoll = true; switch (state) { case MST_IDLE: case MST_CANCLICK: if (btst == "normal") { itbt->second.setstate("mouseOver"); ret = MST_CANCLICK; } break; case MST_CLICKING: if (btst == "normal" || btst == "mouseOver") { itbt->second.setstate("pressed"); buttonpressed(itbt->first); ret = MST_CANCLICK; } } } else { switch (state) { case MST_IDLE: case MST_CANCLICK: if (btst == "mouseOver") { itbt->second.setstate("normal"); } break; } } } bool anytext = false; for (map<short, textfield>::iterator txtit = textfields.begin(); txtit != textfields.end(); txtit++) { if (util::colliding(pos, txtit->second.bounds(), position)) { switch (state) { case MST_CLICKING: txtit->second.setstate("active"); app.getui()->settextfield(&txtit->second); anytext = true; break; } } else { switch (state) { case MST_CLICKING: txtit->second.setstate("inactive"); if (!anytext) { app.getui()->settextfield(0); } break; } } } if (!anycoll) { switch (state) { case MST_CANCLICK: case MST_CANGRAB: ret = MST_IDLE; break; } } return ret; } else { return state; } }
void RobotTestBackend::RenderWorld() { ViewRobot& viewRobot = world->robotViews[0]; //WorldViewProgram::RenderWorld(); glDisable(GL_LIGHTING); drawCoords(0.1); glEnable(GL_LIGHTING); for(size_t i=0;i<world->terrains.size();i++) world->terrains[i]->DrawGL(); for(size_t i=0;i<world->rigidObjects.size();i++) world->rigidObjects[i]->DrawGL(); if(draw_sensors) { if(robotSensors.sensors.empty()) { robotSensors.MakeDefault(robot); } for(size_t i=0;i<robotSensors.sensors.size();i++) { vector<double> measurements; if(0 == strcmp(robotSensors.sensors[i]->Type(),"CameraSensor")) { robotSensors.sensors[i]->SimulateKinematic(*robot,*world); robotSensors.sensors[i]->GetMeasurements(measurements); } robotSensors.sensors[i]->DrawGL(*robot,measurements); } } if(draw_geom) { //set the robot colors GLColor highlight(1,1,0); GLColor driven(1,0.5,0); GLColor colliding(1,0,0); GLColor blue(0,0,1); viewRobot.RestoreAppearance(); viewRobot.PushAppearance(); for(size_t i=0;i<robot->links.size();i++) { if(self_colliding[i]) viewRobot.SetColor(i,colliding); if((int)i == cur_link) viewRobot.SetColor(i,highlight); else if(cur_driver >= 0 && cur_driver < (int)robot->drivers.size() && robot->DoesDriverAffect(cur_driver,i)) viewRobot.SetColor(i,driven); if(draw_self_collision_tests) { //draw a little blue if(robot->selfCollisions(i,cur_link) || robot->selfCollisions(cur_link,i) ) { GLDraw::GeometryAppearance &app = viewRobot.Appearance(i); app.ModulateColor(blue,0.5); } } } //this will set the hover colors allWidgets.DrawGL(viewport); //viewRobot.Draw(); viewRobot.PopAppearance(); } else { for(size_t i=0;i<robotWidgets.size();i++) robotWidgets[i].linkPoser.draw = 0; allWidgets.DrawGL(viewport); for(size_t i=0;i<robotWidgets.size();i++) robotWidgets[i].linkPoser.draw = 1; } if(draw_com) { viewRobot.DrawCenterOfMass(); for(size_t i=0;i<robot->links.size();i++) viewRobot.DrawLinkCenterOfMass(i,0.01); } if(draw_frame) { viewRobot.DrawLinkFrames(); glDisable(GL_DEPTH_TEST); glPushMatrix(); glMultMatrix((Matrix4)robot->links[cur_link].T_World); drawCoords(0.2); glPopMatrix(); glEnable(GL_DEPTH_TEST); } if(draw_self_collision_tests) { glDisable(GL_LIGHTING); glLineWidth(2.0); glColor3f(1,0,0); glBegin(GL_LINES); for(size_t i=0;i<robot->links.size();i++) { Vector3 comi = robot->links[i].T_World*robot->links[i].com; for(size_t j=0;j<robot->links.size();j++) { if(robot->selfCollisions(i,j)) { Vector3 comj = robot->links[j].T_World*robot->links[j].com; glVertex3v(comi); glVertex3v(comj); } } } glEnd(); } if(draw_bbs) { for(size_t j=0;j<robot->geometry.size();j++) { if(robot->IsGeometryEmpty(j)) continue; Box3D bbox = robot->geometry[j]->GetBB(); Matrix4 basis; bbox.getBasis(basis); glColor3f(1,0,0); drawOrientedWireBox(bbox.dims.x,bbox.dims.y,bbox.dims.z,basis); } } }