void GameLayer::roleJumpDownLogic() { /** 1, 先判断是否到地面下了 2, 检测右边的碰撞 3, 检测下面的碰撞 **/ float roleY = mRole->getPositionY(); roleY -= getRoleYSpeed(); if (roleY < getGroundHeight()) { gameOver(); CCLOG("正在下降, 撞地了"); return; } BarPipe *willCollisionBar = getWillCollisionBar(); if (isCollisionWithBar(COLL_STATE_RIGHT, willCollisionBar)) { gameOver(); CCLOG("正在下降, 右边发生碰撞"); return; } if (isCollisionWithBar(COLL_STATE_BOTTOM, willCollisionBar)) { gameOver(); CCLOG("正在下降, 下边发生碰撞"); return; } mRole->setPositionY(roleY); setRoleYSpeed(getRoleYSpeed() + getRoleAccelerate()); }
void FirstPersonGravityCamera::Update(float dt){ //getting initial position glm::vec3 initialPosition = getPosition(); float height = initialPosition.y; //updating the camera as if it were a normal FP camera FirstPersonCamera::Update(dt); glm::vec3 nextPosition = getPosition(); /*----applying the Gravity and Jump constraints----*/ //if the player is on the ground and has pressed space if(glfwGetKey(EventManager::GetWindow(), GLFW_KEY_SPACE) == GLFW_PRESS && grounded == true){ //set the initial vertical velocity for a jump verticalVelocity = 100; //set the horizontal velocity to the current horizontal velocity horizontalVelocity = glm::vec3(nextPosition.x - initialPosition.x, 0, nextPosition.z - initialPosition.z)/dt; grounded = false; } //if the player is in the air, the change in x and z must correspond to the initial velocity at the beginning of the jump. if(grounded == false){ nextPosition = glm::vec3(initialPosition.x + horizontalVelocity.x*dt, 0, initialPosition.z + horizontalVelocity.z*dt); } //apply gravity to velocity verticalVelocity -= 100 * dt; //apply velocity to position height += verticalVelocity * dt; float groundHeight = getGroundHeight(nextPosition.x, nextPosition.z); if (height < groundHeight) { grounded = true; height = groundHeight; } nextPosition.y = height; setPosition (nextPosition); //hasMoved = false; }
void BoidsAngle(CompScreen *s, int i) { ATLANTIS_SCREEN (s); float x = as->fish[i].x; float y = as->fish[i].y; float z = as->fish[i].z; float psi = as->fish[i].psi; float theta = as->fish[i].theta; int type = as->fish[i].type; float factor = 5+5*fabsf(symmDistr()); float randPsi = 10*symmDistr(); float randTh = 10*symmDistr(); /* (X,Y,Z) is the boids vector */ float X = factor * cosf ((psi + randPsi) * toRadians) * cosf ((theta + randTh) * toRadians) / 50000; float Y = factor * sinf ((psi + randPsi) * toRadians) * cosf ((theta + randTh) * toRadians) / 50000; float Z = factor * sinf ((theta + randTh) * toRadians) / 50000; float tempAng = atan2f (y, x); float dist = hypotf (x, y); float perpDist; int j; for (j = 0; j < as->hsize; j++) { /* consider side walls */ float wTheta = j * as->arcAngle*toRadians; float cosAng = cosf (fmodf (j * as->arcAngle * toRadians - tempAng, 2 * PI)); perpDist = fabsf (as->sideDistance - as->fish[i].size / 2 - dist * cosAng); if (perpDist > 50000) continue; if (perpDist <= as->fish[i].size / 2) perpDist = as->fish[i].size / 2; factor = 1 / ((float) as->hsize); if (perpDist <= as->fish[i].size) factor *= as->fish[i].size / perpDist; X -= factor * cosf (wTheta) / perpDist; Y -= factor * sinf (wTheta) / perpDist; } perpDist = as->waterHeight - z; /* top wall */ if (perpDist <= as->fish[i].size / 2) perpDist = as->fish[i].size / 2; factor = 1; if (perpDist <= as->fish[i].size) factor = as->fish[i].size / perpDist; Z -= factor / perpDist; perpDist = z - getGroundHeight(s, x, y); /* bottom wall */ if (perpDist <= as->fish[i].size / 2) perpDist = as->fish[i].size / 2; factor = 1; if (perpDist <= as->fish[i].size) factor = as->fish[i].size / perpDist; Z += factor / perpDist; for (j = 0; j < as->numFish; j++) { /* consider other fish */ if (j != i) { factor = 1; /* positive means form group, negative means stay away. the amount is proportional to the relative importance of the pairs of fish.*/ if (type < as->fish[j].type) { if (as->fish[j].type <= FISH2) factor =-1; /* fish is coming up against different fish */ else factor = (float) (type - as->fish[j].type) * 3; /* fish is coming against a shark, etc. */ } else if (type == as->fish[j].type) { if (as->fish[i].group != as->fish[j].group && !atlantisGetSchoolSimilarGroups(s)) factor =-1; /* fish is coming up against different fish */ } else continue; /* whales are not bothered, sharks are not bothered by fish, etc. */ if (atlantisGetSchoolSimilarGroups(s)) { if ( (type == CHROMIS && (as->fish[j].type == CHROMIS2 || as->fish[j].type == CHROMIS3)) || (type == CHROMIS2 && (as->fish[j].type == CHROMIS || as->fish[j].type == CHROMIS3)) || (type == CHROMIS3 && (as->fish[j].type == CHROMIS || as->fish[j].type == CHROMIS2))) factor = 1; } float xt = (as->fish[j].x - x); float yt = (as->fish[j].y - y); float zt = (as->fish[j].z - z); float d = sqrtf (xt * xt + yt * yt + zt * zt); float th = fmodf (atan2f (yt, xt) * toDegrees - psi, 360); if (th > 180) th -= 360; if (th <- 180) th += 360; if (fabsf (th) < 80 && fabsf (asinf (zt / d) * toDegrees - theta ) < 80) { /* in field of view of fish */ th = fmodf(as->fish[j].psi - psi, 360); if (th <- 180) th += 360; if (th > 180) th -= 360; if (factor>0 && (fabsf (th) > 90 || fabsf (as->fish[j].theta - theta) < 90)) { /* other friendly fish heading in near opposite direction the idea is to turn to form a group by taking the lead or sneaking behind */ if (d > 50000 / 2) { /* varies as distance to power [1,2] after this distance */ d = powf(d, 1 + (d - 50000 / 2) / (2 * 50000 - 50000 / 2)); } factor /= d; X += factor * cosf (as->fish[j].psi * toRadians) * cosf (as->fish[j].theta * toRadians); Y += factor * sinf (as->fish[j].psi * toRadians) * cosf (as->fish[j].theta * toRadians); Z += factor * sinf (as->fish[j].theta * toRadians); } else { if (d > 50000 / 2) { /* varies as distance to power [1,2] after this distance */ d = powf (d, 2 + (d - 50000 / 2) / (2 * 50000 - 50000 / 2)); } else { /* varies as distance */ d *= d; } /* note an extra factor of d due to normalizing (xt, yt, zt) */ factor /= d; X += factor * xt; Y += factor * yt; Z += factor * zt; } } } } as->fish[i].boidsPsi = atan2f (Y, X) * toDegrees; /* needs fmoding, etc to get into range [-180,180] angle not relative to fish angle (have to minus as->fish.psi when using this angle) */ if (isnan (as->fish[i].boidsPsi)) as->fish[i].boidsPsi = psi; /* precaution */ as->fish[i].boidsTheta = asinf (Z / sqrtf (X * X + Y * Y + Z * Z)) * toDegrees; if (isnan (as->fish[i].boidsTheta)) as->fish[i].boidsTheta = theta; /* precaution */ }
void FishPilot (CompScreen *s, int index) { ATLANTIS_SCREEN (s); fishRec * fish = &(as->fish[index]); int i, j; float speed = fish->speed; float x = fish->x; float y = fish->y; float z = fish->z; float maxVel = as->speedFactor * speed; float maxTurnAng = 15 * as->speedFactor; /* left/right angle (in degrees) */ float maxTurnTh = 5 * as->speedFactor; /* up/down angle (in degrees) */ //float minOppTurnAng[2]= { -maxTurnAng, -maxTurnAng }; float minOppTurnAng[2]= { 0, 0 }; float ang; /* angle of the fish so that 90-ang is the turn remaining for each wall */ float tTemp[as->hsize]; /* distance to wall when not changing angle */ float tempAng = atan2f(y, x); float dist = hypotf(x, y); float perpDist = (as->sideDistance - fish->size/2); float t = FLT_MAX; int iWall = 0; /* The number of the wall most in the way of the fish */ float distRem, cosAng; float mota; /* MIN opposite turn angle */ float turnRem[2]; /* right/left */ float sign[2] = { 1, -1 }; float top[2], bottom[2]; float Q1; float turnAng = 0, turnTh = 0; float prefTurnAng, prefTurnTh; fish->psi = fmodf(fish->psi, 360); if (fish->psi>180) fish->psi-=360; else if (fish->psi<-180) fish->psi+=360; if (as->waterHeight-fish->size/2-z<0 && fish->type!=DOLPHIN) { /* dolphins are allowed to jump out top briefly */ fish->z = as->waterHeight-fish->size/2; } float bottomTank = getGroundHeight(s, x, y); if (z-bottomTank-fish->size/2<0) { /* stop all fish from going too far down */ fish->z = bottomTank+fish->size/2; } for (i=0; i<as->hsize; i++) { float cosAng = cosf (fmodf (i * as->arcAngle * toRadians - tempAng, 2 * PI)); tTemp[i] = (perpDist - dist * cosAng) / cosf ( fmodf (fish->psi * toRadians - i * as->arcAngle * toRadians, 2*PI)); if (cosAng > 0) { float d = dist * cosAng - perpDist; if (d > 0) { x -= d * cosf (tempAng) * fabsf (cosf (i * as->arcAngle * toRadians)); y -= d * sinf (tempAng) * fabsf (sinf (i * as->arcAngle * toRadians)); fish->x = x; fish->y = y; tTemp[i] = 0.1; tempAng = atan2f (y, x); dist = hypotf (x, y); } } if ((tTemp[i] < t && tTemp[i] >= 0)) { t = tTemp[i]; iWall = i; } } /* need to consider walls iWall, iWall+1 for clockwise iWall, iWall-1 for anticlockwise. want the angle that the fish can turn minimally right/left such that the fish can still dodge the wall smoothly in the next frame. */ /* turnRem should be 90 degrees if heading straight at a wall, etc. distRem shoud be positive if inside aquarium and negative if outside. */ ang = fish->psi - iWall * as->arcAngle; for (j = 0; j < 2; j++) { float signAng = sign[j] * ang; i = iWall; cosAng = cosf (fmodf (iWall * as->arcAngle * toRadians - tempAng, 2 * PI)); distRem = fabsf (perpDist - dist * cosAng); turnRem[j] = fmodf(90 - signAng, 360); if (turnRem[j] < 0) turnRem[j] += 360; top[j] = sinf ((signAng + turnRem[j]) * toRadians) - sinf (signAng * toRadians); bottom[j] = 2 * distRem / maxVel + cosf (signAng * toRadians) - cosf ((signAng + turnRem[j]) * toRadians); Q1 = 2 * atan2f (top[j], bottom[j]) * toDegrees; Q1 = fmodf(Q1, 360); if (Q1 < 0) Q1 += 360.0f; mota = turnRem[j] - maxTurnAng * (turnRem[j] / Q1 - 1); if (turnRem[j] / Q1 <= 1 && turnRem[j] / Q1 >= 0) mota = Q1; if (mota > minOppTurnAng[j] && mota < 300) minOppTurnAng[j] = mota; signAng -= sign[j] * as->arcAngle; turnRem[j] = fmodf (90 - signAng, 360); if (turnRem[j] < 0) turnRem[j] += 360; if (j == 0) i = (iWall + 1) % as->hsize; else i = (iWall + as->hsize - 1) % as->hsize; cosAng = cosf (fmodf (i * as->arcAngle * toRadians - tempAng, 2 * PI)); distRem = fabsf (perpDist - dist * cosAng); top[j] = sinf ((signAng + turnRem[j]) * toRadians) - sinf (signAng * toRadians); bottom[j] = 2 * distRem / maxVel + cosf (signAng * toRadians) - cosf ((signAng + turnRem[j]) * toRadians); Q1 = 2 * atan2f (top[j], bottom[j]) * toDegrees; Q1 = fmodf (Q1, 360); if (Q1 < 0) Q1 += 360.0f; mota = turnRem[j] - maxTurnAng * (turnRem[j] / Q1 - 1); if (turnRem[j] / Q1 <= 1 && turnRem[j] / Q1 >= 0) mota = Q1; if (mota > minOppTurnAng[j]) minOppTurnAng[j] = mota; } if (fish->boidsCounter <= 0) { /* update the boidsAngles */ BoidsAngle (s, index); fish->boidsCounter = 2 + NUM_GROUPS / as->speedFactor; } fish->boidsCounter--; boidsPsi = fish->boidsPsi; boidsTheta = fish->boidsTheta; prefTurnTh = fmodf (boidsTheta - fish->theta, 360); if (prefTurnTh > 180) prefTurnTh -= 360; if (prefTurnTh <- 180) prefTurnTh += 360; if (fish->smoothTurnCounter <= 0) { float divideAmount; prefTurnAng = fmodf(boidsPsi - fish->psi, 360); /* boids turn angle*/ if (prefTurnAng>180) prefTurnAng-=360; if (prefTurnAng<-180) prefTurnAng+=360; fish->smoothTurnCounter = 5 + NRAND( (int) (20.0 / as->speedFactor)); fish->smoothTurnAmount = turnAng; switch (fish->type) { case SHARK: divideAmount = 5 + 10000 / fish->size + randf (10000 / fish->size + 8); break; case DOLPHIN: divideAmount = 4 + 10000 / fish->size + randf (10000 / fish->size + 5); break; default: divideAmount = 1 + 10000 / fish->size + randf(1.2 * 10000 / fish->size + 5); break; } if (divideAmount <= 1) divideAmount = 1; fish->smoothTurnCounter = (int) 1 + fabsf (prefTurnAng / (divideAmount * as->speedFactor / 2)); turnAng = prefTurnAng / ((float) fish->smoothTurnCounter); fish->smoothTurnAmount = turnAng; turnTh = prefTurnTh / ((float) fish->smoothTurnCounter); fish->smoothTurnTh = turnTh; } else { prefTurnAng = fish->smoothTurnAmount; turnAng = prefTurnAng; prefTurnAng = fish->smoothTurnTh; turnTh = prefTurnTh; if (minOppTurnAng[0] > prefTurnAng && -minOppTurnAng[0] < prefTurnAng) { if (fabsf ( minOppTurnAng[0] - prefTurnAng) < fabsf (-minOppTurnAng[1] - prefTurnAng)) turnAng = minOppTurnAng[0]; else turnAng = -minOppTurnAng[1]; } } fish->smoothTurnCounter--; fish->speed += randf(40) - 20; /* new speed */ if (fish->speed > 200) fish->speed = 200; if (fish->speed < 50) fish->speed = 50; if (turnAng > maxTurnAng) fish->psi += maxTurnAng; else if (turnAng < -maxTurnAng) fish->psi -= maxTurnAng; else fish->psi += turnAng; fish->psi = fmodf (fish->psi, 360); if (fish->psi > 180) fish->psi -= 360; else if (fish->psi <- 180) fish->psi += 360; if (turnTh > maxTurnTh) fish->theta += maxTurnTh; else if (turnTh <- maxTurnTh) fish->theta -= maxTurnTh; else fish->theta += turnTh; if (fish->theta > 50) fish->theta = 50; else if (fish->theta <- 50) fish->theta =- 50; fish->x += maxVel * cosf (fish->psi * toRadians) * cosf (fish->theta * toRadians); fish->y += maxVel * sinf (fish->psi * toRadians) * cosf (fish->theta * toRadians); fish->z += maxVel * sinf (fish->theta * toRadians); }