void Physics::TestCollision(Shape *a, Shape *b) { if (!(a->layerMask & b->layerMask)) return; if (a->object == b->object) return; int typeA = a->GetType(), typeB = b->GetType(); if (typeA == Polygon::ShapeType && typeB == Polygon::ShapeType) return TestCollision((Polygon *)a, (Polygon *)b); if (typeA == Circle::ShapeType && typeB == Circle::ShapeType) return TestCollision((Circle *)a, (Circle *)b); if (typeA == Circle::ShapeType && typeB == Polygon::ShapeType) return TestCollision((Circle *)a, (Polygon *)b); if (typeA == Polygon::ShapeType && typeB == Circle::ShapeType) return TestCollision((Circle *)b, (Polygon *)a); }
void Tetris::KeyRepeat(game_info* gi) { if (gi->state != STATE_TETRIS) { return; } if (engine.keys[SDLK_UP]) { gi->curdir++; gi->curdir %= 4; if (TestCollision(gi)) { gi->curdir--; gi->curdir += 4; gi->curdir %= 4; } engine.PassMessage(MSG_UPDATEPIECE, gi->pos, gi->curdir, gi->curpiece); } else if (engine.keys[SDLK_LEFT]) { gi->pos--; // test collisions! if (TestCollision(gi)) { gi->pos++; } engine.PassMessage(MSG_UPDATEPIECE, gi->pos, gi->curdir, gi->curpiece); } else if (engine.keys[SDLK_RIGHT]) { gi->pos++; // test collisions! if (TestCollision(gi)) { gi->pos--; } engine.PassMessage(MSG_UPDATEPIECE, gi->pos, gi->curdir, gi->curpiece); } }
/// Obj : 被移动的对象 /// enDir : 移动方向 /// nStep : 移动步长 /// return : 是否移动 xgc_bool XGameMap::DynamicMoveTo( XGameObject* pObject, XVector3 &vPositionNew, xgc_uint32 nCollistionMask, xgc_uintptr lpContext ) { XGC_CHECK_REENTER_CALL( mDynamicChecker ); XGC_ASSERT_RETURN( pObject->GetParent() == GetObjectID(), false, "对象不在该场景,却请求在该场景移动。" ); xgc_bool ret = true; XVector3 vPositionOld = pObject->GetPosition(); if( !( nCollistionMask & EYESHOTAREA_FORCEfLUSH ) && vPositionOld == vPositionNew ) { return ret; } if( !( nCollistionMask & COLLISION_NOMOVEFLAG ) && ( false == pObject->GetMoveFlag() || false == GetMoveFlag() ) ) { return false; } iPoint iOldCell = WorldToCell( vPositionOld.x, vPositionOld.y ); iPoint iNewCell = WorldToCell( vPositionNew.x, vPositionNew.y ); if( nCollistionMask & COLLISION_PATH ) { if( TestCollision( iOldCell.x, iOldCell.y, iNewCell.x, iNewCell.y, pObject->GetBarrierFlag() ) ) { // 设置为非碰撞格子的中心点 XVector2 fPosition = CellToWorld( iNewCell.x, iNewCell.y ); vPositionNew.x = fPosition.x; vPositionNew.y = fPosition.y; vPositionNew.z = 0.0f; iNewCell = WorldToCell( vPositionNew.x, vPositionNew.y ); ret = false; } } if( nCollistionMask & COLLISION_DEST ) { if( IsCellBlock( iNewCell.x, iNewCell.y, pObject->GetBarrierFlag() ) ) { return false; } } iPoint iOldArea = WorldToArea( vPositionOld.x, vPositionOld.y ); iPoint iNewArea = WorldToArea( vPositionNew.x, vPositionNew.y ); pObject->SetPosition( vPositionNew ); //设置新位置 ExchangeBlock( pObject, iOldCell, iNewCell ); //XGC_DEBUG_CODE( CMapBlock *pArea = GetBlock(x,y); if( pArea ) XGC_ASSERT_MSG( pArea->CheckExist(pObj->GetObjID()), "发现飞机。" ); ) ExchangeArea( pObject, iOldArea, iNewArea, mMapConf.mEyesight, nCollistionMask ); //放在ExchangeEyeshotArea后触发 pObject->OnMove( vPositionOld, lpContext ); return ret; }
void WallProjectile::Tick(World & world){ Uint8 life = 20; if(state_i == 1){ EmitSound(world, world.resources.soundbank["!laserel.wav"], 64); } if(state_i < 7){ res_index = state_i; } if(state_i >= 7){ if(state_i > 12 + life){ world.MarkDestroyObject(id); res_index = 12; return; } if(state_i >= 12 + life - 5){ res_index = state_i - life; }else{ res_index = 7; } } if(state_i >= 7){ Object * object = 0; Platform * platform = 0; if(TestCollision(*this, world, &platform, &object)){ Overlay * overlay = (Overlay *)world.CreateObject(ObjectTypes::OVERLAY); if(overlay){ overlay->res_bank = 222; overlay->x = x; overlay->y = y; if(platform){ if(rand() % 2 == 0){ overlay->EmitSound(world, world.resources.soundbank["strike03.wav"], 96); }else{ overlay->EmitSound(world, world.resources.soundbank["strike04.wav"], 96); } } } float xn = 0, yn = 0; if(platform){ platform->GetNormal(x, y, &xn, &yn); } for(int i = 0; i < 8; i++){ Shrapnel * shrapnel = (Shrapnel *)world.CreateObject(ObjectTypes::SHRAPNEL); if(shrapnel){ shrapnel->x = x; shrapnel->y = y; shrapnel->xv = (rand() % 9) - 4; shrapnel->yv = (rand() % 9) - 8; shrapnel->xv = (xn * abs(shrapnel->xv)) + (rand() % 9) - 4; shrapnel->yv = (yn * abs(shrapnel->yv)) + (rand() % 9) - 8; } } world.MarkDestroyObject(id); } } state_i++; }
OvBool OvCollisionFinder::TestCollision(OvBox& _rBox0,OvSphere& _rSphere0) { OvPoint3 kpt3NearPt = (_rBox0.GetPosition() - _rSphere0.GetCenter()).Normalize(); kpt3NearPt = kpt3NearPt*_rSphere0.GetRadius(); kpt3NearPt = _rSphere0.GetCenter() + kpt3NearPt; for (size_t i = 0 ; i < OvBox::PLANE_COUNT ; ++i) { if (!TestCollision(_rSphere0,_rBox0.GetPlane((OvBox::BOX_PLANE)i))) return false; } return true; }
void Tetris::DropPiece(game_info* gi) { while(!TestCollision(gi)) { gi->fine+=0.25; } engine.PassMessage(MSG_UPDATEPIECE, gi->pos, gi->curdir, gi->curpiece); engine.PassMessage(MSG_UPDATEPIECEY, (unsigned char)((gi->fine / 11.0f) * 255.0f), 0, 0); AddPiece(gi); }
/// Compare each dynamic entity with every other entity in it's current vfcOctree node, /// all nodes below it as well the direct parents above it. int PhysicsOctree::FindCollisions(Entity * targetEntity, List<Collision> & collissionList, int entrySubdivisionLevel) { if (entrySubdivisionLevel == -1) entrySubdivisionLevel = this->subdivision; int collissionsTested = 0; /// First it's current node: for (int i = 0; i < entities.Size(); ++i){ Entity * e = entities[i]; assert(e && "Nullentity in PhysicsOctree::FindCollisions"); TestCollision(targetEntity, e, collissionList); ++collissionsTested; } /// If entry node, begin all recursion. if (this->subdivision == entrySubdivisionLevel){ /// Then all children if (child[0] && this->subdivision >= entrySubdivisionLevel) for (int i = 0; i < MAX_CHILDREN; ++i){ /// Do the actual culling with this continue-statement, yo! if (child[i]->IsEntityInside(targetEntity) == OUTSIDE) continue; collissionsTested += child[i]->FindCollisions(targetEntity, collissionList, entrySubdivisionLevel); } /// And at last all parents if (parent && this->subdivision <= entrySubdivisionLevel) collissionsTested += parent->FindCollisions(targetEntity, collissionList, entrySubdivisionLevel); return collissionsTested; } /// Process children if subdivision level is higher (further down the tree.) else if (this->subdivision > entrySubdivisionLevel){ /// Then all children if (child[0]){ for (int i = 0; i < MAX_CHILDREN; ++i){ /// Do the actual culling with this continue-statement, yo! if (child[i]->IsEntityInside(targetEntity) == OUTSIDE) continue; collissionsTested += child[i]->FindCollisions(targetEntity, collissionList, entrySubdivisionLevel); } } return collissionsTested; } /// And process parents only if lesser subdivision else if (this->subdivision < entrySubdivisionLevel){ /// Then go to next parent. if (parent && this->subdivision <= entrySubdivisionLevel) collissionsTested += parent->FindCollisions(targetEntity, collissionList, entrySubdivisionLevel); return collissionsTested; } assert(false && "PhysicsOctree::FindCollisions at a point where it shouldn't be!"); return 0; }
void Map::RotatePiece(int direction) { if (currentPiece == NULL) return; int rotation[4][4]; for (int i = 0; i < 4; i++) for (int j = 0; j < 4; j++) if (direction > 0) rotation[j][3-i] = currentPiece->area[i][j]; else rotation[3-j][i] = currentPiece->area[i][j]; memcpy(currentPiece->area, rotation, sizeof(int) * 4 * 4); int result = TestCollision(currentX, currentY); int tempX = -1; for (int i = 0; i < 5 && result > 0; i++) { tempX = currentX + (2 - i); result = TestCollision(tempX, currentY); } // Can't rotate it if (result > 0) { for (int i = 0; i < 4; i++) for (int j = 0; j < 4; j++) if (direction <= 0) currentPiece->area[j][3-i] = rotation[i][j]; else currentPiece->area[3-j][i] = rotation[i][j]; } else if (tempX > 0) { currentX = tempX; } }
void Map::MovePiece(int x, int y) { currentX += x; if (currentX > width-1) currentX = width -1; // HERE IS THE PROBLEM. // Not any more, sucker! if (currentX < -(width / 2.0f)) currentX = -(width / 2.0f); int response = TestCollision(currentX, currentY); if (response > 0) { if (response == 2) { PlacePiece(currentX, currentY); } currentX -= x; } currentY += y; if (currentY <= -(height / 2.0f)) PlacePiece(currentX, currentY-y); response = TestCollision(currentX, currentY); if (response > 0) { PlacePiece(currentX, currentY - y); currentY -= y; } if (response > 0 && currentY > (height / 2.0f)) { // Game Over! MessageBox(NULL, "Game Over!", "Game Over!", MB_OK); g_App->done = true; } }
// This runs once every physics timestep. void update() { if (TestCollision(*aabbCollider, box->GetModelMatrix(), glm::vec3(point->translation[3][0], point->translation[3][1], point->translation[3][2]))) { //Turn red on hue[0][0] = 1.0f; } else { //Turn red off hue[0][0] = 0.0f; } }
// This runs once every physics timestep. void update() { //Check if the mouse button is being pressed if (isMousePressed) { //Get the current mouse position double currentMouseX, currentMouseY; glfwGetCursorPos(window, ¤tMouseX, ¤tMouseY); //Get the difference in mouse position from last frame float deltaMouseX = (float)(currentMouseX - prevMouseX); float deltaMouseY = (float)(currentMouseY - prevMouseY); glm::mat4 yaw; glm::mat4 pitch; //Rotate the selected shape by an angle equal to the mouse movement if (deltaMouseX != 0.0f) { yaw = glm::rotate(glm::mat4(1.0f), deltaMouseX * rotationSpeed, glm::vec3(0.0f, 1.0f, 0.0f)); } if (deltaMouseY != 0.0f) { pitch = glm::rotate(glm::mat4(1.0f), deltaMouseY * rotationSpeed, glm::vec3(1.0f, 0.0f, 0.0f)); } selectedShape->rotation = yaw * pitch * selectedShape->rotation; //Update previous positions prevMouseX = currentMouseX; prevMouseY = currentMouseY; } if (TestCollision(*boxCollider, box->translation, box->rotation, box->scale, glm::vec3(point->translation[3][0], point->translation[3][1], point->translation[3][2]))) { //Turn red on hue[0][0] = 1.0f; } else { //Turn red off hue[0][0] = 0.0f; } }
// This runs once every physics timestep. void update() { if (TestCollision(*sphereCollider, //Sphere collider glm::vec3(sphere->translation[3][0], sphere->translation[3][1], sphere->translation[3][2]), //Sphere position glm::vec3(point->translation[3][0], point->translation[3][1], point->translation[3][2]))) //Point position { //Turn red on hue[0][0] = 1.0f; } else { //Turn red off hue[0][0] = 0.0f; } }
// This runs once every physics timestep. void update() { //Check if the mouse button is being pressed if (isMousePressed) { //Get the current mouse position double currentMouseX, currentMouseY; glfwGetCursorPos(window, ¤tMouseX, ¤tMouseY); //Get the difference in mouse position from last frame float deltaMouseX = (float)(currentMouseX - prevMouseX); float deltaMouseY = (float)(currentMouseY - prevMouseY); //Rotate the selected shape by an angle equal to the mouse movement if (deltaMouseX != 0.0f) { glm::mat4 yaw = glm::rotate(glm::mat4(1.0f), deltaMouseX * rotationSpeed, glm::vec3(0.0f, 1.0f, 0.0f)); plane->rotation = plane->rotation * yaw; } if (deltaMouseY != 0.0f) { glm::mat4 pitch = glm::rotate(glm::mat4(1.0f), deltaMouseY * -rotationSpeed, glm::vec3(1.0f, 0.0f, 0.0f)); plane->rotation = pitch * plane->rotation; } //Update previous positions prevMouseX = currentMouseX; prevMouseY = currentMouseY; } if (TestCollision(*sphereCollider, sphere->translation, *planeCollider, plane->translation, plane->rotation)) { //Turn red on hue[0][0] = 1.0f; } else { //Turn red off hue[0][0] = 0.0f; } }
void FlamerProjectile::Tick(World & world){ for(int i = 0; i < plumecount; i++){ if(!plumeids[i]){ Plume * plume = (Plume *)world.CreateObject(ObjectTypes::PLUME); if(plume){ plume->type = 4; plume->xv = (rand() % 17) - 8 + (xv * 8); plume->yv = (rand() % 17) - 8 + (yv * 8); plume->SetPosition(x + (xv * (i * 1)), y + (yv * (i * 1))); plumeids[i] = plume->id; plume->state_i = i; } } } Object * object = 0; Platform * platform = 0; if(TestCollision(*this, world, &platform, &object)){ float xn = 0, yn = 0; if(platform){ platform->GetNormal(x, y, &xn, &yn); for(int i = 0; i < plumecount; i++){ Plume * plume = (Plume *)world.GetObjectFromId(plumeids[i]); if(plume){ plume->xv /= 3; plume->yv /= 3; //world->MarkDestroyObject(plumeids[i]); } } } //world->MarkDestroyObject(id); } res_index = state_i; if(state_i >= 14){ world.MarkDestroyObject(id); } state_i++; }
bool Tetris::TestCollision(game_info *gi) { return TestCollision(gi, (0.5) * (double)gi->pos, gi->fine); }
void Tetris::Update(game_info* gi, float deltatime) { if (gi->state == STATE_TETRIS_TRANS) { gi->rot2 += TRANSITION_SPEED * deltatime; if (gi->rot2 >= 180) { gi->rot2 = 180; engine.ChangeState(gi, STATE_BREAKOUT); } engine.PassMessage(MSG_ROT_BOARD2, (gi->rot2 / 180.0f) * 255.0f, 0,0); return; } if (gi->attacking) { gi->rot += TETRIS_ATTACK_ROT_SPEED * deltatime; gi->attack_rot += TETRIS_ATTACK_ROT_SPEED * deltatime; if (gi->attack_rot >= 360) { gi->rot = -BOARD_NORMAL_ROT; gi->attack_rot = 0; gi->attacking = 0; gi->score += (10 * 100); engine.PassMessage(MSG_APPENDSCORE, 100, 10, 0); } engine.PassMessage(MSG_ROT_BOARD, (gi->rot / 360.0f) * 255.0f, 0,0); } if (!engine.network_thread) { if (engine.keys[SDLK_DOWN]) { gi->fine += deltatime * (TETRIS_SPEED + 4.3 + 0.3 * LEVEL); } else { gi->fine += deltatime * (TETRIS_SPEED + 0.3 * LEVEL); } } else { if (engine.keys[SDLK_DOWN]) { gi->fine += deltatime * (TETRIS_SPEED + 4.3); } else { gi->fine += deltatime * TETRIS_SPEED; } } //gi->rot2+=50.0 * deltatime; if (TestCollision(gi)) { // we collided! oh no! if (TestGameOver(gi)) { engine.GameOver(); } else { AddPiece(gi); } } //printf("%f\n", gi->fine); engine.PassMessage(MSG_UPDATEPIECEY, (unsigned char)((gi->fine / 11.0f) * 255.0f), 0, 0); }
//************************************************************************************************* // Test a potential collision pair //************************************************************************************************* void PhysicsManager::testCollision(PhysicsBody* body1, PhysicsBody* body2) { TestCollision(body1->getAABB(), body2->getAABB()); int a = 0; }
void RocketProjectile::Tick(World & world){ if(yv < 0 && xv == 0){ // up res_index = 4; } if(yv < 0 && xv > 0){ // up right res_index = 3; mirrored = false; } if(yv == 0 && xv > 0){ // right res_index = 0; mirrored = false; } if(yv > 0 && xv > 0){ // down right res_index = 1; mirrored = false; } if(yv > 0 && xv == 0){ // down res_index = 2; } if(yv > 0 && xv < 0){ // down left res_index = 1; mirrored = true; } if(yv == 0 && xv < 0){ // left res_index = 0; mirrored = true; } if(yv < 0 && xv < 0){ // up left res_index = 3; mirrored = true; } if(state_i == 100){ oldxv = xv; oldyv = yv; xv = ceil(float(xv) * 0.3); yv = ceil(float(yv) * 0.3); soundchannel = EmitSound(world, world.resources.soundbank["rocket4.wav"], 128); state_i = 11; res_bank = 87; } if(state_i == 0){ oldxv = xv; oldyv = yv; xv = ceil(float(xv) * 0.2); yv = ceil(float(yv) * 0.2); soundchannel = EmitSound(world, world.resources.soundbank["rocket9.wav"], 128); } if(state_i == 3){ res_bank = 87; } if(state_i == 11){ if(xv > 0){ xv++; }else{ xv--; } if(yv > 0){ yv++; }else{ yv--; } if(abs(xv) > abs(oldxv)){ xv = oldxv; } if(abs(yv) > abs(oldyv)){ yv = oldyv; } Platform * platform = 0; Object * object = 0; Sint16 oldx = x; Sint16 oldy = y; if(TestCollision(*this, world, &platform, &object)){ float xn = 0, yn = 0; if(platform){ platform->GetNormal(x, y, &xn, &yn); } int numplumes = 6; float anglen = (rand() % 100) / float(100); for(int i = 0; i < numplumes; i++){ Plume * plume = (Plume *)world.CreateObject(ObjectTypes::PLUME); if(plume){ plume->type = 4; /*plume->xv = (rand() % 17) - 8; plume->yv = (rand() % 17) - 8; plume->xv = (xn * abs(plume->xv)) + (rand() % 33) - 16; plume->yv = (yn * abs(plume->yv)) + (rand() % 33) - 16;*/ float angle = (i / float(numplumes)) * (2 * 3.14); angle += anglen; plume->xv = (sin(angle)) * 15; plume->yv = (cos(angle)) * 15; if(xn || yn){ plume->xv = (xn * abs(plume->xv)) + (rand() % 17) - 8; plume->yv = (yn * abs(plume->yv)) + (rand() % 17) - 8; } plume->SetPosition(x, y); Plume * plume2 = (Plume *)world.CreateObject(ObjectTypes::PLUME); if(plume2){ plume2->type = 4; plume2->xv = plume->xv + (rand() % 7) - 3; plume2->yv = plume->yv + (rand() % 7) - 3; plume2->SetPosition(x, y); } } } std::vector<Uint8> types; types.push_back(ObjectTypes::PLAYER); types.push_back(ObjectTypes::GUARD); types.push_back(ObjectTypes::ROBOT); types.push_back(ObjectTypes::CIVILIAN); types.push_back(ObjectTypes::FIXEDCANNON); types.push_back(ObjectTypes::WALLDEFENSE); types.push_back(ObjectTypes::TECHSTATION); Object * owner = world.GetObjectFromId(ownerid); Uint16 teamid = 0; bool issecurity = false; if(owner){ switch(owner->type){ case ObjectTypes::PLAYER:{ Player * player = static_cast<Player *>(owner); Team * team = player->GetTeam(world); if(team){ teamid = team->id; } }break; case ObjectTypes::ROBOT:{ Robot * robot = static_cast<Robot *>(owner); teamid = robot->virusplanter; issecurity = world.IsSecurity(*robot); }break; case ObjectTypes::GUARD:{ issecurity = true; }break; } } std::vector<Object *> objects = world.TestAABB(x - 30, y - 30, x + 30, y + 30, types, ownerid, teamid); for(std::vector<Object *>::iterator it = objects.begin(); it != objects.end(); it++){ if(!object || (object && (*it)->id != object->id)){ if(!issecurity || (issecurity && !world.IsSecurity(*(*it)))){ // prevents robots/rocket guards from doing slash damage to other security Object damageprojectile(ObjectTypes::ROCKETPROJECTILE); damageprojectile.healthdamage = healthdamage; damageprojectile.shielddamage = shielddamage; damageprojectile.ownerid = ownerid; (*it)->HandleHit(world, 50, 50, damageprojectile); } } } xv = 0; yv = 0; res_bank = 0xFF; if(soundchannel){ Audio::GetInstance().Stop(soundchannel, 100); } EmitSound(world, world.resources.soundbank["seekexp1.wav"], 128); } for(int i = 0; i < 2; i++){ int xv2 = (signed(oldx) - x) * (1.25 * i); int yv2 = (signed(oldy) - y) * (1.25 * i); Plume * plume = (Plume *)world.CreateObject(ObjectTypes::PLUME); if(plume){ plume->type = 3; plume->xv = rand() % 7 - 3; plume->yv = rand() % 7 - 3; plume->SetPosition(x + xv2, y + yv2); } } } if(state_i < 11 || (state_i >= 11 && xv == 0 && yv == 0)){ state_i++; } if(state_i >= 25){ world.MarkDestroyObject(id); }else{ Player * localplayer = world.GetPeerPlayer(world.localpeerid); if(localplayer && ownerid == localplayer->id){ //if(!world.systemcameraactive[0]){ world.SetSystemCamera(0, id, 0, 20); //} } } }