void renderScene(GLFWwindow *window, ShadowMap *shadowMap) { glUseProgram(ShadeProg); glUniform3f(h_uLightColor, 0.4, 0.4, 0.38); glUniform4f(h_uLightVec, 0.0, 1.0, 1.0, 0.0); // Render depth info from light's perspective shadowMap->BindFBO(); glClear(GL_DEPTH_BUFFER_BIT); curView = SetView(); // CHANGE TO LIGHT'S PERSPECTIVE, NOT EYE curProj = SetOrthoProjectionMatrix(); glUniform3f(h_uCamPos, 0.0, 1.0, 1.0); glfwDraw(window); // Render scene normally and draw shadowMap->UnbindFBO(); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); curView = SetView(); curProj = SetProjectionMatrix(); glUniform3f(h_uCamPos, GetEye().x, GetEye().y, GetEye().z); glfwDraw(window); // Disable the shaders glUseProgram(0); glfwSwapBuffers(window); }
//移動の向きを得る Vector3 Player::GetAngle(){ Vector3 Angle(0, 0, 0); //コントローラの取得 auto CntlVec = App::GetApp()->GetInputDevice().GetControlerVec(); if (CntlVec[0].bConnected){ if (CntlVec[0].fThumbLX != 0 && CntlVec[0].fThumbLY != 0){ float MoveLength = 0; //動いた時のスピード auto PtrTransform = GetComponent<Transform>(); auto PtrCamera = GetStage()->GetCamera(0); //進行方向の向きを計算 Vector3 Front = PtrTransform->GetPosition() - PtrCamera->GetEye(); Front.y = 0; Front.Normalize(); //進行方向向きからの角度を算出 float FrontAngle = atan2(Front.z, Front.x); //コントローラの向き計算 float MoveX = CntlVec[0].fThumbLX; float MoveZ = CntlVec[0].fThumbLY; //コントローラの向きから角度を計算 float CntlAngle = atan2(-MoveX, MoveZ); //トータルの角度を算出 float TotalAngle = FrontAngle + CntlAngle; //角度からベクトルを作成 Angle = Vector3(cos(TotalAngle), 0, sin(TotalAngle)); //正規化する Angle.Normalize(); //Y軸は変化させない Angle.y = 0; } } return Angle; }
bool physGrapple(float lx,float ly,float lz){ bool ret = false; flip = 0; dir = glm::normalize(glm::vec3(-lx,ly,-lz)); //printf("grapple in dir %f %f %f\n",dir.x,dir.y,dir.z); //printf("looks at is %f %f %f\n",lookAt.x,lookAt.y,lookAt.z); /* btCollisionWorld::ClosestRayResultCallback RayCallback(btVector3(lookAt.x+.0*dir.x,lookAt.y-.0*dir.y,lookAt.z+.0*dir.z), btVector3(lookAt.x+50*dir.x,lookAt.y-50*dir.y,lookAt.z+50*dir.z)); dynamicsWorld->rayTest(btVector3(lookAt.x+.0*dir.x,lookAt.y-.0*dir.y,lookAt.z+.0*dir.z), btVector3(lookAt.x+50*dir.x,lookAt.y-50*dir.y,lookAt.z+50*dir.z), RayCallback); */ ////////////////////////////// glm:: vec3 ggaze = GetLookAt() - GetEye(); glm::vec3 gw = ggaze/magnitude(ggaze); gw = glm::vec3(-1.0 * gw.x, -1.0 * gw.y, -1.0 * gw.z); glm::vec3 gu = glm::cross(GetUp(), gw)/magnitude(glm::cross(GetUp(), gw)); gu *= 2; lookAt += glm::vec3(gu.x, 0, gu.z); /////////////////////////////// btCollisionWorld::ClosestRayResultCallback RayCallback(btVector3(lookAt.x+1.6*dir.x,lookAt.y-1.6*dir.y,lookAt.z+1.6*dir.z), btVector3(lookAt.x+75*dir.x,lookAt.y-75*dir.y,lookAt.z+75*dir.z)); dynamicsWorld->rayTest(btVector3(lookAt.x+1.6*dir.x,lookAt.y-1.6*dir.y,lookAt.z+1.6*dir.z), btVector3(lookAt.x+75*dir.x,lookAt.y-75*dir.y,lookAt.z+75*dir.z), RayCallback); //player->setLinearVelocity(btVector3(dir.x*50,dir.y*50,dir.z*50)); btTransform plPos; player->getMotionState()->getWorldTransform(plPos); if(RayCallback.hasHit()&& !playerGrappleActive && RayCallback.m_hitPointWorld.distance(plPos.getOrigin())>1.8) { playerJump=0; //End = RayCallback.m_hitPointWorld; //Normal = RayCallback.m_hitNormalWorld; //printf("hit!\n"); btVector3 go=RayCallback.m_hitNormalWorld*-5+player->getLinearVelocity(); if (go.length()>10)(go/go.length())*10; //player->setLinearVelocity(go); //printf("%f %f %f on hit norm",RayCallback.m_hitNormalWorld.getX(),RayCallback.m_hitNormalWorld.getY(),RayCallback.m_hitNormalWorld.getZ()); tmp = RayCallback.m_hitPointWorld; // Do some clever stuff here if(tmp.getY()>1){ playerGrappleActive =1; //SFX HERE //Sound s = Sound(); //s.playSFX("../Assets/Sounds/HookShot.mp3"); //printf("%f %f %f - player loc; %f %f %f grapple loc\n", physGetPlayerX(), physGetPlayerY(), physGetPlayerZ(), grapplingHookLocation().x, grapplingHookLocation().y, grapplingHookLocation().z); //printf("%f %f %f grapple sfx distance\n", abs(grapplingHookLocation().x - physGetPlayerX()), abs(grapplingHookLocation().y - physGetPlayerY()), abs(grapplingHookLocation().z - physGetPlayerZ())); musicPlayer.BGM.play3DSFX("../Assets/Sounds/HookShot.mp3", physGetPlayerX(), physGetPlayerY(), physGetPlayerZ(), grapplingHookLocation().x, grapplingHookLocation().y, grapplingHookLocation().z); ret = true; } } lookAt -= glm::vec3(gu.x, 0, gu.z); return ret; }
// Tests Identity Matrix Function //////////////////////////////////////////////////////////////////////////////// TEST_F(LAopsTest, create_identity_matrix) { GetEye(m_matdim, m_testmat); ASSERT_FLOAT_EQ(m_testmat[2][2], 1); ASSERT_FLOAT_EQ(m_testmat[0][0], 1); ASSERT_FLOAT_EQ(m_testmat[2][3], 0); ASSERT_FLOAT_EQ(m_testmat[7][2], 0); float accumulator = 0; for (int i = 0; i < m_matdim; ++i) { accumulator += m_testmat[3][i]; } ASSERT_FLOAT_EQ(accumulator, 1); }
void glfwEditGetCursorPos(GLFWwindow *window, double xpos, double ypos) { //printf("%f %f\n", xpos, g_height - ypos); lastCurPos = glm::vec2(xpos, g_height - ypos - 1); //If in GUI Selection, disable pitch and yaw if(eKeysPressed['G'] == 0) { if(xpos > g_width || xpos < 0 || ypos < 0 || ypos > g_height) { return; } //Get rid of if unneeded egaze = GetLookAt() - GetEye(); ew = glm::vec3(-1.0 * ew.x, -1.0 * ew.y, -1.0 * ew.z); ew = glm::normalize(ew); eu = glm::cross(GetUp(), ew)/magnitude(glm::cross(GetUp(), ew)); eu = glm::normalize(eu); eendX = xpos; eendY = g_height-ypos-1; float diff; //Calculate change in X if(estartX < eendX) { diff = eendX - estartX; ebeta = incrementYaw((diff * M_PI)/g_width); } else if(estartX > eendX){ diff = estartX - eendX; ebeta = incrementYaw((-diff * M_PI)/g_width); } //Calculate change in Y if(eendY > estartY && ealpha <= 0.98) { diff = eendY - estartY; ealpha = incrementPitch((diff * M_PI)/g_width); } else if(eendY < estartY && ealpha >= -0.98) { diff = estartY - eendY; ealpha = incrementPitch(-(diff * M_PI)/g_width); } estartX = g_width/2.0;// = endX; estartY = g_height/2.0-1;// endY; } }
int grappleInRange(float lx,float ly,float lz){ //glm::vec3 tempLookAt; dir = glm::normalize(glm::vec3(-lx,ly,-lz)); glm:: vec3 ggaze = GetLookAt() - GetEye(); glm::vec3 gw = ggaze/magnitude(ggaze); gw = glm::vec3(-1.0 * gw.x, -1.0 * gw.y, -1.0 * gw.z); glm::vec3 gu = glm::cross(GetUp(), gw)/magnitude(glm::cross(GetUp(), gw)); gu *= 2; lookAt += glm::vec3(gu.x, 0, gu.z); btCollisionWorld::ClosestRayResultCallback RayCallback(btVector3(lookAt.x+1.6*dir.x,lookAt.y-1.6*dir.y,lookAt.z+1.6*dir.z), btVector3(lookAt.x+75*dir.x,lookAt.y-75*dir.y,lookAt.z+75*dir.z)); dynamicsWorld->rayTest(btVector3(lookAt.x+1.6*dir.x,lookAt.y-1.6*dir.y,lookAt.z+1.6*dir.z), btVector3(lookAt.x+75*dir.x,lookAt.y-75*dir.y,lookAt.z+75*dir.z), RayCallback); lookAt -= glm::vec3(gu.x, 0, gu.z); // int ret = //inRange(50,75,glm::lookAt(playerPoss(),glm::vec3(tempLookAt.x+75*dir.x,tempLookAt.y+75*dir.y,tempLookAt.z+75*dir.z),glm::vec3(0,1,0))); //printf("grapple is %d range\n",RayCallback.hasHit()); //if(RayCallback.hasHit()) printf("%f %f %f",RayCallback.m_hitPointWorld.getX(),RayCallback.m_hitPointWorld.getY(),RayCallback.m_hitPointWorld.getZ()); return RayCallback.hasHit(); }
//-------------------------------------------------------------------------------------- /// プレイヤーの行動クラス //-------------------------------------------------------------------------------------- Vec3 PlayerBehavior::GetMoveVector() const { Vec3 Angle(0, 0, 0); //コントローラの取得 auto CntlVec = App::GetApp()->GetInputDevice().GetControlerVec(); if (CntlVec[0].bConnected) { if (CntlVec[0].fThumbLX != 0 || CntlVec[0].fThumbLY != 0) { float MoveLength = 0; //動いた時のスピード auto PtrTransform = GetGameObject()->GetComponent<Transform>(); auto PtrCamera = GetGameObject()->OnGetDrawCamera(); //進行方向の向きを計算 Vec3 Front = PtrTransform->GetPosition() - PtrCamera->GetEye(); Front.y = 0; Front.normalize(); //進行方向向きからの角度を算出 float FrontAngle = atan2(Front.z, Front.x); //コントローラの向き計算 float MoveX = CntlVec[0].fThumbLX; float MoveZ = CntlVec[0].fThumbLY; Vec2 MoveVec(MoveX, MoveZ); float MoveSize = MoveVec.length(); //コントローラの向きから角度を計算 float CntlAngle = atan2(-MoveX, MoveZ); //トータルの角度を算出 float TotalAngle = FrontAngle + CntlAngle; //角度からベクトルを作成 Angle = Vec3(cos(TotalAngle), 0, sin(TotalAngle)); //正規化する Angle.normalize(); //移動サイズを設定。 Angle *= MoveSize; //Y軸は変化させない Angle.y = 0; } } return Angle; }
void MyCamera::Update(){ auto CntlVec = App::GetApp()->GetInputDevice().GetControlerVec(); //前回のターンからの時間 float ElapsedTime = App::GetApp()->GetElapsedTime(); if (CntlVec[0].bConnected){ Vector3 NewAt(0, 0, 0); auto TargetPtr = GetTargetObject(); if (TargetPtr){ //目指したい場所 Vector3 ToAt = TargetPtr->GetComponent<Transform>()->GetPosition(); NewAt = Lerp::CalculateLerp(GetAt(), ToAt, 0, 1.0f, m_ToTargetLerp, Lerp::Linear); } //ステップ1、注視点と位置の変更 Vector3 Span = GetAt() - GetEye(); Vector3 NewEye = NewAt - Span; SetAt(NewAt); SetEye(NewEye); //ステップ2、ズームの変更 //カメラ位置と注視点の間のベクトルを算出 Span = GetAt() - GetEye(); //正規化 Span.Normalize(); //変化値の決定 Span = Span * ElapsedTime * 10.0f; Vector3 NewArm = GetAt() - GetEye(); //Dパッド下 //カメラを引く if (CntlVec[0].wButtons & XINPUT_GAMEPAD_DPAD_DOWN){ //カメラ位置を引く NewEye = NewEye - Span; NewArm = NewAt - NewEye; if (NewArm.Length() > (GetFar() * 0.1f)){ NewEye = NewEye + Span; NewArm = NewAt - NewEye; } } //Dパッド上 //カメラを寄る if (CntlVec[0].wButtons & XINPUT_GAMEPAD_DPAD_UP){ //カメラ位置を寄る NewEye = NewEye + Span; NewArm = NewAt - NewEye; if (NewArm.Length() < GetNear() * 2.0f){ NewEye = NewEye - Span; NewArm = NewAt - NewEye; } } SetAt(NewAt); SetEye(NewEye); //ステップ3角度の変更 //現在のAtとEyeの角度を得る Vector3 ArmInv = GetEye() - GetAt(); //右スティックX方向 FLOAT AngleY = 0; //右スティックY方向 FLOAT AngleX = 0; FLOAT AngleZ = 0; if (CntlVec[0].fThumbRX != 0){ //右スティックを聞かないようにする // AngleY = -CntlVec[0].fThumbRX * ElapsedTime; } if (CntlVec[0].fThumbRY != 0){ //右スティックを聞かないようにする // AngleX = CntlVec[0].fThumbRY * ElapsedTime; // AngleZ = CntlVec[0].fThumbRY * ElapsedTime; } if (ArmInv.z > 0){ AngleX *= -1.0f; } if (ArmInv.x < 0){ AngleZ *= -1.0f; } Quaternion QtSpan(AngleX, AngleY, AngleZ); QtSpan.Normalize(); //回転先計算の行列を作成 Matrix4X4 Mat, Mat2; Mat.STRTransformation( Vector3(1.0f, 1.0f, 1.0f), ArmInv, QtSpan); Mat2.TranslationFromVector(GetAt()); Mat *= Mat2; NewEye = Mat.PosInMatrix(); if (NewEye.y < 0.5f){ NewEye.y = 0.5f; } //カメラが一定以上、上から視線にならなように調整 ArmInv = NewEye - GetAt(); ArmInv.Normalize(); float y2 = ArmInv.y * ArmInv.y; float x2 = ArmInv.x * ArmInv.x; float z2 = ArmInv.z * ArmInv.z; if (y2 <= (x2 + z2)){ SetEye(NewEye); } } Camera::Update(); }
void Player::FireWeapon() { SPADES_MARK_FUNCTION(); Vector3 muzzle = GetEye(); muzzle += GetFront() * 0.01f; // for hit-test debugging std::map<int, HitTestDebugger::PlayerHit> playerHits; std::vector<Vector3> bulletVectors; //Vector3 right = GetRight(); //Vector3 up = GetUp(); int pellets = weapon->GetPelletSize(); float spread = weapon->GetSpread(); GameMap *map = world->GetMap(); // pyspades takes destroying more than one block as a // speed hack (shotgun does this) bool blockDestroyed = false; Vector3 dir2 = GetFront(); for(int i =0 ; i < pellets; i++){ // AoS 0.75's way (dir2 shouldn't be normalized!) dir2.x += (GetRandom() - GetRandom()) * spread; dir2.y += (GetRandom() - GetRandom()) * spread; dir2.z += (GetRandom() - GetRandom()) * spread; Vector3 dir = dir2.Normalize(); bulletVectors.push_back(dir); // first do map raycast GameMap::RayCastResult mapResult; mapResult = map->CastRay2(muzzle, dir, 500); Player *hitPlayer = NULL; float hitPlayerDistance = 0.f; HitBodyPart hitPart = HitBodyPart::None; for(int i = 0; i < world->GetNumPlayerSlots(); i++){ Player *other = world->GetPlayer(i); if(other == this || other == NULL) continue; if(other == this || !other->IsAlive() || other->GetTeamId() >= 2) continue; // quickly reject players unlikely to be hit if(!other->RayCastApprox(muzzle, dir)) continue; HitBoxes hb = other->GetHitBoxes(); Vector3 hitPos; if(hb.head.RayCast(muzzle, dir, &hitPos)) { float dist = (hitPos - muzzle).GetLength(); if(hitPlayer == NULL || dist < hitPlayerDistance){ hitPlayer = other; hitPlayerDistance = dist; hitPart = HitBodyPart::Head; } } if(hb.torso.RayCast(muzzle, dir, &hitPos)) { float dist = (hitPos - muzzle).GetLength(); if(hitPlayer == NULL || dist < hitPlayerDistance){ hitPlayer = other; hitPlayerDistance = dist; hitPart = HitBodyPart::Torso; } } for(int j = 0; j < 3 ;j++){ if(hb.limbs[j].RayCast(muzzle, dir, &hitPos)) { float dist = (hitPos - muzzle).GetLength(); if(hitPlayer == NULL || dist < hitPlayerDistance){ hitPlayer = other; hitPlayerDistance = dist; switch(j) { case 0: hitPart = HitBodyPart::Limb1; break; case 1: hitPart = HitBodyPart::Limb2; break; case 2: hitPart = HitBodyPart::Arms; break; } } } } } Vector3 finalHitPos; finalHitPos = muzzle + dir * 128.f; if(hitPlayer == nullptr && !mapResult.hit) { // might hit water surface. } if(mapResult.hit && (mapResult.hitPos - muzzle).GetLength() < 128.f && (hitPlayer == NULL || (mapResult.hitPos - muzzle).GetLength() < hitPlayerDistance)){ IntVector3 outBlockCoord = mapResult.hitBlock; // TODO: set correct ray distance // FIXME: why ray casting twice? finalHitPos = mapResult.hitPos; if(outBlockCoord.x >= 0 && outBlockCoord.y >= 0 && outBlockCoord.z >= 0 && outBlockCoord.x < map->Width() && outBlockCoord.y < map->Height() && outBlockCoord.z < map->Depth()){ if(outBlockCoord.z == 63) { if(world->GetListener()) world->GetListener()->BulletHitBlock(mapResult.hitPos, mapResult.hitBlock, mapResult.normal); }else if(outBlockCoord.z == 62) { // blocks at this level cannot be damaged if(world->GetListener()) world->GetListener()->BulletHitBlock(mapResult.hitPos, mapResult.hitBlock, mapResult.normal); }else{ int x = outBlockCoord.x; int y = outBlockCoord.y; int z = outBlockCoord.z; SPAssert(map->IsSolid(x, y, z)); Vector3 blockF = {x + .5f, y + .5f, z + .5f}; float distance = (blockF - muzzle).GetLength(); uint32_t color = map->GetColor(x, y, z); int health = color >> 24; health -= weapon->GetDamage(HitTypeBlock, distance); if(health <= 0 && !blockDestroyed){ health = 0; blockDestroyed = true; //send destroy cmd if(world->GetListener() && world->GetLocalPlayer() == this) world->GetListener()->LocalPlayerBlockAction (outBlockCoord, BlockActionTool); } color = (color & 0xffffff) | ((uint32_t)health << 24); if(map->IsSolid(x, y, z)) map->Set(x, y, z, true, color); if(world->GetListener()) world->GetListener()->BulletHitBlock(mapResult.hitPos, mapResult.hitBlock, mapResult.normal); } } }else if(hitPlayer != NULL){
void Player::Update(float dt) { SPADES_MARK_FUNCTION(); auto* listener = world->GetListener(); MovePlayer(dt); if(!IsAlive()) { // do death cleanup blockCursorDragging = false; } if(tool == ToolSpade){ if(weapInput.primary){ if(world->GetTime() > nextSpadeTime){ UseSpade(); nextSpadeTime = world->GetTime() + GetToolPrimaryDelay(); } }else if(weapInput.secondary){ if(world->GetTime() > nextDigTime){ DigWithSpade(); nextDigTime = world->GetTime() + GetToolSecondaryDelay(); firstDig = false; } } }else if(tool == ToolBlock && IsLocalPlayer()){ GameMap::RayCastResult result; auto *map = GetWorld()->GetMap(); result = map->CastRay2(GetEye(), GetFront(), 12); canPending = false; if(blockCursorDragging) { // check the starting point is not floating auto start = blockCursorDragPos; if(map->IsSolidWrapped(start.x-1, start.y, start.z) || map->IsSolidWrapped(start.x, start.y-1, start.z) || map->IsSolidWrapped(start.x, start.y, start.z-1) || map->IsSolidWrapped(start.x+1, start.y, start.z) || map->IsSolidWrapped(start.x, start.y+1, start.z) || map->IsSolidWrapped(start.x, start.y, start.z+1)) { // still okay }else{ // cannot build; floating if(listener && this == world->GetLocalPlayer()) { listener-> LocalPlayerBuildError(BuildFailureReason::InvalidPosition); } blockCursorDragging = false; } } if(result.hit && (result.hitBlock + result.normal).z < 62 && (!OverlapsWithOneBlock(result.hitBlock + result.normal)) && BoxDistanceToBlock(result.hitBlock + result.normal) < 3.f && !pendingPlaceBlock){ // Building is possible, and there's no delayed block placement. blockCursorActive = true; blockCursorPos = result.hitBlock + result.normal; }else if(pendingPlaceBlock){ // Delayed Block Placement: When player attempts to place a block while jumping and // placing block is currently impossible, building will be delayed until it becomes // possible, as long as player is airborne. if(airborne == false || blockStocks <= 0){ // player is no longer airborne, or doesn't have a block to place. pendingPlaceBlock = false; lastSingleBlockBuildSeqDone = true; if(blockStocks > 0) { // cannot build; invalid position. } }else if((!OverlapsWithOneBlock(pendingPlaceBlockPos)) && BoxDistanceToBlock(pendingPlaceBlockPos) < 3.f){ // now building became possible. SPAssert(this == world->GetLocalPlayer()); if(GetWorld()->GetListener()) GetWorld()->GetListener()->LocalPlayerBlockAction(pendingPlaceBlockPos, BlockActionCreate); pendingPlaceBlock = false; lastSingleBlockBuildSeqDone = true; // blockStocks--; decrease when created nextBlockTime = world->GetTime() + GetToolPrimaryDelay(); } }else{ // Delayed Block Placement can be activated only when the only reason making placement // impossible is that block to be placed overlaps with the player's hitbox. canPending = result.hit && (result.hitBlock + result.normal).z < 62 && BoxDistanceToBlock(result.hitBlock + result.normal) < 3.f; blockCursorActive = false; int dist = 11; for(; dist >= 1 && BoxDistanceToBlock(result.hitBlock + result.normal) > 3.f ; dist--) { result = GetWorld()->GetMap()->CastRay2(GetEye(), GetFront(), dist); } for(; dist < 12 && BoxDistanceToBlock(result.hitBlock + result.normal) < 3.f ; dist++) { result = GetWorld()->GetMap()->CastRay2(GetEye(), GetFront(), dist); } blockCursorPos = result.hitBlock + result.normal; } }else if(tool == ToolWeapon){ }else if(tool == ToolGrenade){ if(holdingGrenade){ if(world->GetTime() - grenadeTime > 2.9f){ ThrowGrenade(); } } } if(tool != ToolWeapon) weapon->SetShooting(false); if(weapon->FrameNext(dt)){ FireWeapon(); } if(weapon->IsReloading()) { lastReloadingTime = world->GetTime(); }else if(reloadingServerSide) { // for some reason a server didn't return // WeaponReload packet. if(world->GetTime() + lastReloadingTime + .8f) { reloadingServerSide = false; weapon->ForceReloadDone(); } } }
void Player::FireWeapon() { SPADES_MARK_FUNCTION(); Vector3 muzzle = GetEye(); muzzle += GetFront() * 0.01f;/* muzzle += GetRight() * 0.4f; muzzle -= GetUp() * 0.3f;*/ Vector3 right = GetRight(); Vector3 up = GetUp(); int pellets = weapon->GetPelletSize(); float spread = weapon->GetSpread(); GameMap *map = world->GetMap(); // pyspades takes destroying more than one block as a // speed hack (shotgun does this) bool blockDestroyed = false; Vector3 dir2 = GetFront(); for(int i =0 ; i < pellets; i++){ // AoS 0.75's way (dir2 shouldn't be normalized!) dir2.x += (GetRandom() * 2.f - 1.f) * spread; dir2.y += (GetRandom() * 2.f - 1.f) * spread; dir2.z += (GetRandom() * 2.f - 1.f) * spread; Vector3 dir = dir2.Normalize(); // first do map raycast GameMap::RayCastResult mapResult; mapResult = map->CastRay2(muzzle, dir, 500); Player *hitPlayer = NULL; float hitPlayerDistance = 0.f; int hitFlag = 0; for(int i = 0; i < world->GetNumPlayerSlots(); i++){ Player *other = world->GetPlayer(i); if(other == this || other == NULL) continue; if(other == this || !other->IsAlive() || other->GetTeamId() >= 2) continue; if(!other->RayCastApprox(muzzle, dir)) continue; HitBoxes hb = other->GetHitBoxes(); Vector3 hitPos; if(hb.head.RayCast(muzzle, dir, &hitPos)) { float dist = (hitPos - muzzle).GetLength(); if(hitPlayer == NULL || dist < hitPlayerDistance){ if(hitPlayer != other){ hitPlayer = other; hitFlag = 0; } hitPlayerDistance = dist; hitFlag = 1; // head } } if(hb.torso.RayCast(muzzle, dir, &hitPos)) { float dist = (hitPos - muzzle).GetLength(); if(hitPlayer == NULL || dist < hitPlayerDistance){ if(hitPlayer != other){ hitPlayer = other; hitFlag = 0; } hitPlayerDistance = dist; hitFlag = 2; // torso } } for(int j = 0; j < 3 ;j++){ if(hb.limbs[j].RayCast(muzzle, dir, &hitPos)) { float dist = (hitPos - muzzle).GetLength(); if(hitPlayer == NULL || dist < hitPlayerDistance){ if(hitPlayer != other){ hitPlayer = other; hitFlag = 0; } hitPlayerDistance = dist; if(j == 2) hitFlag = 8; // arms else hitFlag = 4; // leg } } } } Vector3 finalHitPos; finalHitPos = muzzle + dir * 128.f; if(mapResult.hit && (mapResult.hitPos - muzzle).GetLength() < 128.f && (hitPlayer == NULL || (mapResult.hitPos - muzzle).GetLength() < hitPlayerDistance)){ IntVector3 outBlockCoord = mapResult.hitBlock; // TODO: set correct ray distance // FIXME: why ray casting twice? finalHitPos = mapResult.hitPos; if(outBlockCoord.x >= 0 && outBlockCoord.y >= 0 && outBlockCoord.z >= 0 && outBlockCoord.x < map->Width() && outBlockCoord.y < map->Height() && outBlockCoord.z < map->Depth()){ if(outBlockCoord.z < 62){ int x = outBlockCoord.x; int y = outBlockCoord.y; int z = outBlockCoord.z; SPAssert(map->IsSolid(x, y, z)); Vector3 blockF = {x + .5f, y + .5f, z + .5f}; float distance = (blockF - muzzle).GetLength(); uint32_t color = map->GetColor(x, y, z); int health = color >> 24; health -= weapon->GetDamage(HitTypeBlock, distance); if(health <= 0 && !blockDestroyed){ health = 0; blockDestroyed = true; //send destroy cmd if(world->GetListener() && world->GetLocalPlayer() == this) world->GetListener()->LocalPlayerBlockAction (outBlockCoord, BlockActionTool); } color = (color & 0xffffff) | ((uint32_t)health << 24); if(map->IsSolid(x, y, z)) map->Set(x, y, z, true, color); if(world->GetListener()) world->GetListener()->BulletHitBlock(mapResult.hitPos, mapResult.hitBlock, mapResult.normal); } } }else if(hitPlayer != NULL){
void Player::Update(float dt) { SPADES_MARK_FUNCTION(); MovePlayer(dt); if(tool == ToolSpade){ if(weapInput.primary){ if(world->GetTime() > nextSpadeTime){ UseSpade(); nextSpadeTime = world->GetTime() + GetToolPrimaryDelay(); } }else if(weapInput.secondary){ if(world->GetTime() > nextDigTime){ DigWithSpade(); nextDigTime = world->GetTime() + GetToolSecondaryDelay(); firstDig = false; } } }else if(tool == ToolBlock){ GameMap::RayCastResult result; result = GetWorld()->GetMap()->CastRay2(GetEye(), GetFront(), 12); canPending = false; if(result.hit && (result.hitBlock + result.normal).z < 62 && (!OverlapsWithOneBlock(result.hitBlock + result.normal)) && BoxDistanceToBlock(result.hitBlock + result.normal) < 3.f && !pendingPlaceBlock){ blockCursorActive = true; blockCursorPos = result.hitBlock + result.normal; }else if(pendingPlaceBlock){ if(airborne == false || blockStocks <= 0){ pendingPlaceBlock = false; }else if((!OverlapsWithOneBlock(pendingPlaceBlockPos)) && BoxDistanceToBlock(pendingPlaceBlockPos) < 3.f){ SPAssert(this == world->GetLocalPlayer()); if(GetWorld()->GetListener()) GetWorld()->GetListener()->LocalPlayerBlockAction(pendingPlaceBlockPos, BlockActionCreate); pendingPlaceBlock = false; // blockStocks--; decrease when created nextBlockTime = world->GetTime() + GetToolPrimaryDelay(); } }else{ canPending = result.hit && (result.hitBlock + result.normal).z < 62 && BoxDistanceToBlock(result.hitBlock + result.normal) < 3.f; blockCursorActive = false; blockCursorPos = result.hitBlock + result.normal; } }else if(tool == ToolWeapon){ }else if(tool == ToolGrenade){ if(holdingGrenade){ if(world->GetTime() - grenadeTime > 2.9f){ ThrowGrenade(); } } } if(tool != ToolWeapon) weapon->SetShooting(false); if(weapon->FrameNext(dt)){ FireWeapon(); } if(weapon->IsReloading()) { lastReloadingTime = world->GetTime(); }else if(reloadingServerSide) { // for some reason a server didn't return // WeaponReload packet. if(world->GetTime() + lastReloadingTime + .8f) { reloadingServerSide = false; weapon->ForceReloadDone(); } } }
// Tests Determinant of Identity //////////////////////////////////////////////////////////////////////////////// TEST_F(LAopsTest, det_of_identity_matrix) { GetEye(m_matdim, m_testmat); fem_float detval = det(m_matdim, m_testmat); ASSERT_FLOAT_EQ(detval, 1); }
Vect3f CFPSCamera::GetDirection () const { assert(m_pObject3D); return (GetLookAt() - GetEye()); }