void fanLens::computeLensSpace( fanVector3<float> pos, fanVector3<float> lookAt, fanVector3<float> up, fanVector3<float> dimens ) { mPos = pos; mLookAt = lookAt; mUp = up; mDimens = dimens; fanVector3<float> look = lookAt - pos; fanVector3<float> toUp = up - pos; fanVector3<float> z = normalize( look ); /* * up * ^^ * toUp / | * / | y * / | * pos--->-------->lookAt * a look */ float lookLengthSqu = lengthSquare(look); fanVector3<float> a = look * ((look*toUp)/(lookLengthSqu)); fanVector3<float> y = normalize(toUp - a); fanVector3<float> x = normalize(cross( z, y )); mLensSpace[0] = x; mLensSpace[1] = y; mLensSpace[2] = z; fanMatrix<float, 4, 4> childTransform = getTransformation(); mViewTransformation = mLensSpace; mViewTransformation[3][3] = 1; mViewTransformation = childTransform * mViewTransformation; fanMatrix<float, 4, 4> unitBox; unitBox[0][0] = 1/mDimens[0]; unitBox[0][3] = 0.5f; unitBox[1][1] = 1/mDimens[1]; unitBox[1][3] = 0.5f; unitBox[2][2] = 1/mDimens[2]; unitBox[3][3] = 1; mViewTransformation = unitBox * mViewTransformation; }
/** * Tests if this vector is normalized * @return true if this vector is normalized, otherwise return false */ inline bool isNormalized() { return equal(lengthSquare(), (RealType)1); }
/** * Returns the length of this vector. * @return the length of this vector */ inline Real length() { return sqrt(lengthSquare()); }
const float length() const { return sqrt(lengthSquare()); }
void moveEntity(PlayState *playState, Entity *entity, GameContext *gameContext, UserInput *userInput) { V2D screenPosition = getEntityScreenPosition(entity, gameContext->cameraPosition); if (entity->type != PLAYER_TYPE) { if ((screenPosition.x > gameContext->gameWidth + entity->bitmap.width) || (screenPosition.x < -entity->bitmap.width)) { return; } } switch (entity->type) { case PLAYER_TYPE: { // if the level is complete then fly off the screen if (gameContext->isLevelCompleted) { if (screenPosition.x >= gameContext->gameWidth + entity->bitmap.width) { ++gameContext->currentLevel; gameContext->stateChange = BETWEEN_LEVEL; } else { entity->velocity = V2D{3, 0}; entity->position += entity->velocity; } } else { // if the player is not dying then update it normally if (entity->dyingCounter == 0) { V2D target = {(float) userInput->mousePositionX, (float) userInput->mousePositionY}; V2D entityVelocity = V2D{gameContext->scrollSpeed, 0} + (target - screenPosition) / (entity->maxSpeed * entity->maxSpeed); if (lengthSquare(entityVelocity) > entity->maxSpeed * entity->maxSpeed) { normalize(entityVelocity); entityVelocity *= entity->maxSpeed; } entity->velocity = entityVelocity; } else { // if the player is dying entity->velocity += V2D{0, .05}; } doEntityMovement(playState, entity, gameContext); } // change the angle with the velocity to give the impression of a moving helicopter if (entity->velocity.x < 0) { entity->bitmap.angle = -10.0; } else if (entity->velocity.y > 0) { entity->bitmap.angle = 10.0; } else { entity->bitmap.angle = 0.0; } break; } case GLIDER_TYPE: { if (entity->dyingCounter == 0) { if (entity->position.y >= entity->initialPosition.y + entity->deltaMovement) { entity->velocity.y = -entity->maxSpeed; } else if (entity->position.y <= entity->initialPosition.y - entity->deltaMovement) { entity->velocity.y = entity->maxSpeed; } doEntityMovement(playState, entity, gameContext); // TODO: improve movement with collision detection if (entity->position.y < 0) { entity->position.y = 0; entity->velocity.y = entity->maxSpeed; } else if (entity->position.y > gameContext->gameHeight) { entity->position.y = gameContext->gameHeight; entity->velocity.y = -entity->maxSpeed; } } break; } case SHOT_GLIDER_TYPE: { break; } case PLAYER_BULLET_TYPE: case ENEMY_BULLET_TYPE: { if (entity->dyingCounter == 0) { doEntityMovement(playState, entity, gameContext); } break; } case TURRET_TYPE: { break; } case ROOF_TURRET_TYPE: { break; } case ESKELETOR_TYPE: { if (entity->dyingCounter == 0) { if (entity->velocity.y == 0) { entity->velocity.y = entity->maxSpeed; } doEntityMovement(playState, entity, gameContext); if (entity->velocity.y < 0 && entity->position.y <= entity->initialPosition.y) { entity->velocity.y *= -1; } } break; } case LEVEL_1_BOSS_TYPE: { if (screenPosition.x > gameContext->gameWidth - 32) { entity->velocity.x = -entity->maxSpeed; entity->position += entity->velocity; } else { if (entity->dyingCounter == 0) { entity->velocity.x = 0; if (entity->velocity.y == 0) { entity->velocity.y = (random() % 2) ? entity->maxSpeed : -entity->maxSpeed; } if (screenPosition.y + 32 + entity->bitmap.height / 2 >= gameContext->gameHeight) { entity->velocity.y = -entity->maxSpeed; } else if (screenPosition.y - entity->bitmap.height / 2 <= 0) { entity->velocity.y = entity->maxSpeed; } doEntityMovement(playState, entity, gameContext); } } break; } case TILE_TYPE: case NULL_ENTITY_TYPE: { break; } } }