| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369 |
- #include "LongboardGame.h"
- // Declare our game instance
- LongboardGame game;
- // Pick some arbitrarily large world size for our playground
- #define WORLD_SIZE 20.0f
- // Maximum velocity, in meters/sec
- #define VELOCITY_MAX 2.0f
- #define VELOCITY_MAX_MS (VELOCITY_MAX / 1000.0f)
- // Minimum velocity, in meters/sec
- #define VELOCITY_MIN 0.2f
- #define VELOCITY_MIN_MS (VELOCITY_MIN / 1000.0f)
- // Keyboard input bit-flags (powers of 2)
- #define ACCELERATE (1 << 0)
- #define BRAKE (1 << 1)
- #define STEER_LEFT (1 << 2)
- #define STEER_RIGHT (1 << 3)
- // Accelerometer pitch control
- #define PITCH_MIN 20.0f
- #define PITCH_MAX 70.0f
- #define PITCH_RANGE (PITCH_MAX - PITCH_MIN)
- // Maximum turn rate (rate of change in direction at full velocity), in degrees/sec
- #define TURN_RATE_MAX 75.0f
- #define TURN_RATE_MAX_MS (TURN_RATE_MAX / 1000.0f)
- #define ROLL_MAX 40.0f
- LongboardGame::LongboardGame()
- : _ground(NULL), _board(NULL), _wheels(NULL), _gradient(NULL), _stateBlock(NULL),
- _keyFlags(0), _simulatedPitch(0), _simulatedRoll(0), _velocity(VELOCITY_MIN_MS)
- {
- }
- LongboardGame::~LongboardGame()
- {
- }
- void LongboardGame::initialize()
- {
- // Display the gameplay splash screen for at least 1 second.
- displayScreen(this, &LongboardGame::drawSplash, NULL, 1000L);
- // Create our render state block that will be reused across all materials
- _stateBlock = RenderState::StateBlock::create();
- _stateBlock->setCullFace(true);
- _stateBlock->setBlend(true);
- _stateBlock->setBlendSrc(RenderState::BLEND_SRC_ALPHA);
- _stateBlock->setBlendDst(RenderState::BLEND_ONE_MINUS_SRC_ALPHA);
- // Calculate initial matrices
- Matrix::createPerspective(45.0f, (float)getWidth() / (float)getHeight(), 0.25f, 100.0f, &_projectionMatrix);
- Matrix::createLookAt(0, 1.75f, 1.35f, 0, 0, -0.15f, 0, 0.20f, -0.80f, &_viewMatrix);
- Matrix::multiply(_projectionMatrix, _viewMatrix, &_viewProjectionMatrix);
- // Build game entities
- buildGround();
- buildBoard();
- buildWheels();
- buildGradient();
- // Set initial board physics
- _direction.set(0, 0, -1);
- _velocity = VELOCITY_MIN_MS;
- }
- void LongboardGame::finalize()
- {
- SAFE_RELEASE(_stateBlock);
- SAFE_RELEASE(_ground);
- SAFE_RELEASE(_board);
- SAFE_RELEASE(_wheels);
- SAFE_RELEASE(_gradient);
- SAFE_RELEASE(_wheelsSound);
- }
- void LongboardGame::buildGround()
- {
- // Create a large quad for the ground
- Mesh* groundMesh = Mesh::createQuad(Vector3(-WORLD_SIZE, 0, -WORLD_SIZE),
- Vector3(-WORLD_SIZE, 0, WORLD_SIZE),
- Vector3(WORLD_SIZE, 0, -WORLD_SIZE),
- Vector3(WORLD_SIZE, 0, WORLD_SIZE));
- // Create the ground model
- _ground = Model::create(groundMesh);
- // Create the ground material
- Material* groundMaterial = _ground->setMaterial("res/shaders/textured-unlit.vert", "res/shaders/textured-unlit.frag", "TEXTURE_REPEAT;TEXTURE_OFFSET");
- // Set render state block
- groundMaterial->setStateBlock(_stateBlock);
- // Bind ground material parameters
- Texture::Sampler* groundSampler = groundMaterial->getParameter("u_diffuseTexture")->setValue("res/asphalt.png", true);
- groundSampler->setWrapMode(Texture::REPEAT, Texture::REPEAT);
- groundMaterial->getParameter("u_worldViewProjectionMatrix")->setValue(&_groundWorldViewProjectionMatrix);
- groundMaterial->getParameter("u_textureRepeat")->setValue(Vector2(WORLD_SIZE / 2, WORLD_SIZE / 2));
- groundMaterial->getParameter("u_textureOffset")->setValue(&_groundUVTransform);
- // Release objects that are owned by mesh instances
- SAFE_RELEASE(groundMesh);
- }
- void LongboardGame::buildBoard()
- {
- // Create longboard mesh
- Mesh* boardMesh = Mesh::createQuad(Vector3(-0.5f, 0.1f, -1.0f),
- Vector3(-0.5f, 0.1f, 1.0f),
- Vector3(0.5f, 0.1f, -1.0f),
- Vector3(0.5f, 0.1f, 1.0f) );
- // Create the board model
- _board = Model::create(boardMesh);
- // Create the board material
- Material* boardMaterial = _board->setMaterial("res/shaders/textured-unlit.vert", "res/shaders/textured-unlit.frag", "TEXTURE_REPEAT;TEXTURE_OFFSET");
- // Set render state block
- boardMaterial->setStateBlock(_stateBlock);
- // Bind board material parameters
- Texture::Sampler* boardSampler = boardMaterial->getParameter("u_diffuseTexture")->setValue("res/longboard.png", true);
- boardSampler->setWrapMode(Texture::CLAMP, Texture::CLAMP);
- boardMaterial->getParameter("u_worldViewProjectionMatrix")->setValue(&_boardWorldViewProjectionMatrix);
- boardMaterial->getParameter("u_textureRepeat")->setValue(Vector2::one());
- boardMaterial->getParameter("u_textureOffset")->setValue(Vector2::zero());
- // Release objects that are owned by mesh instances
- SAFE_RELEASE(boardMesh);
- }
- void LongboardGame::buildWheels()
- {
- // Create wheels mesh
- Mesh* wheelsMesh = Mesh::createQuad(Vector3(-0.5f, 0.025f, -0.25f),
- Vector3(-0.5f, 0.025f, 0.25f),
- Vector3(0.5f, 0.025f, -0.25f),
- Vector3(0.5f, 0.025f, 0.25f));
- // Create the wheels model
- _wheels = Model::create(wheelsMesh);
- // Create the wheels material
- Material* wheelsMaterial = _wheels->setMaterial("res/shaders/textured-unlit.vert", "res/shaders/textured-unlit.frag", "TEXTURE_REPEAT;TEXTURE_OFFSET");
- // Set render state block
- wheelsMaterial->setStateBlock(_stateBlock);
- // Bind wheels material parameters
- Texture::Sampler* wheelsSampler = wheelsMaterial->getParameter("u_diffuseTexture")->setValue("res/longboard_wheels.png", true);
- wheelsSampler->setWrapMode(Texture::CLAMP, Texture::CLAMP);
- wheelsMaterial->getParameter("u_worldViewProjectionMatrix")->setValue(&_wheelsWorldViewProjectionMatrix);
- wheelsMaterial->getParameter("u_textureRepeat")->setValue(Vector2::one());
- wheelsMaterial->getParameter("u_textureOffset")->setValue(Vector2::zero());
- // Load audio sound
- _wheelsSound = AudioSource::create("res/longboard.wav");
- if (_wheelsSound)
- _wheelsSound->setLooped(true);
- // Release objects that are owned by mesh instances
- SAFE_RELEASE(wheelsMesh);
- }
- void LongboardGame::buildGradient()
- {
- // Create a full-screen quad for rendering a screen-space gradient effect to the scene
- Mesh* gradientMesh = Mesh::createQuadFullscreen();
- // Create the wheels model
- _gradient = Model::create(gradientMesh);
- // Create the gradient material.
- Material* gradientMaterial = _gradient->setMaterial("res/shaders/textured-unlit.vert", "res/shaders/textured-unlit.frag");
- // Set render state block
- gradientMaterial->setStateBlock(_stateBlock);
- // Bind material parameters
- Texture::Sampler* gradientSampler = gradientMaterial->getParameter("u_diffuseTexture")->setValue("res/overlay_gradient.png", false);
- gradientSampler->setWrapMode(Texture::CLAMP, Texture::CLAMP);
- // Release objects that are owned by mesh instances
- SAFE_RELEASE(gradientMesh);
- }
- void LongboardGame::update(float elapsedTime)
- {
- // Query the accelerometer values.
- float pitch, roll;
- getAccelerometerValues(&pitch, &roll);
- // On desktop platforms without accelerometers, use key inputs instead.
- if (!Game::hasAccelerometer())
- {
- float pitchTarget = 0;
- float rollTarget = 0;
- pitch = _simulatedPitch;
- roll = _simulatedRoll;
- pitchTarget = -0.5f * (PITCH_MAX + PITCH_MIN);
- if (_keyFlags & BRAKE)
- {
- pitchTarget = -PITCH_MAX;
- }
- else if (_keyFlags & ACCELERATE)
- {
- pitchTarget = -PITCH_MIN;
- }
- if (_keyFlags & STEER_RIGHT)
- {
- rollTarget += ROLL_MAX;
- }
- if (_keyFlags & STEER_LEFT)
- {
- rollTarget -= ROLL_MAX;
- }
- MathUtil::smooth(&_simulatedPitch, pitchTarget, elapsedTime, 600);
- MathUtil::smooth(&_simulatedRoll, rollTarget, elapsedTime, 100);
- }
- // Clamp angles
- pitch = max(min(-pitch, PITCH_MAX), PITCH_MIN);
- roll = max(min(roll, ROLL_MAX), -ROLL_MAX);
-
- // Calculate the 'throttle' (which is the % controlling change in acceleration, similar to a car's gas pedal)
- float throttle = 1.0f - ((pitch - PITCH_MIN) / PITCH_RANGE);
- if (throttle > 0.0f)
- {
- if (_wheelsSound->getState() != AudioSource::PLAYING)
- _wheelsSound->play();
- _wheelsSound->setPitch(throttle);
- }
- else
- {
- _wheelsSound->stop();
- }
- // Update velocity based on current throttle.
- // Note that this is a very simplified calculation that ignores acceleration (assumes it's constant)
- _velocity = VELOCITY_MIN_MS + ((VELOCITY_MAX_MS - VELOCITY_MIN_MS) * throttle);
- // Update direction based on accelerometer roll and max turn rate
- static Matrix rotMat;
- Matrix::createRotationY(MATH_DEG_TO_RAD((TURN_RATE_MAX_MS * elapsedTime) * (roll / ROLL_MAX) * throttle), &rotMat);
- rotMat.transformVector(&_direction);
- _direction.normalize();
- // Transform the ground. We rotate the ground instead of the board since we don't actually
- // move the board along the ground (we just simulate moving it so it appears infinite).
- Matrix::multiply(rotMat, _groundWorldMatrix, &_groundWorldMatrix);
- Matrix::multiply(_viewProjectionMatrix, _groundWorldMatrix, &_groundWorldViewProjectionMatrix);
- // Transform the wheels
- Matrix::createScale(1.2f, 1.2f, 1.2f, &_wheelsWorldMatrix);
- _wheelsWorldMatrix.translate(roll / ROLL_MAX * 0.05f, 0, 0.05f);
- _wheelsWorldMatrix.rotateY(-MATH_DEG_TO_RAD(roll * 0.45f));
- Matrix::multiply(_viewProjectionMatrix, _wheelsWorldMatrix, &_wheelsWorldViewProjectionMatrix);
- // Transform and tilt the board
- Matrix::createScale(1.25f, 1.25f, 1.25f, &_boardWorldMatrix);
- _boardWorldMatrix.translate(0, 0, 0.65f);
- _boardWorldMatrix.rotateZ(-MATH_DEG_TO_RAD(roll * 0.5f));
- _boardWorldMatrix.rotateY(-MATH_DEG_TO_RAD(roll * 0.1f));
- Matrix::multiply(_viewProjectionMatrix, _boardWorldMatrix, &_boardWorldViewProjectionMatrix);
- // Transform the ground texture coords to give the illusion of the board moving.
- // We'll assume that a 'patch' of ground is equal to 1 meter.
- _groundUVTransform.x += -_direction.x * (_velocity * elapsedTime);
- _groundUVTransform.y += -_direction.z * (_velocity * elapsedTime);
- if (_groundUVTransform.x >= 1.0f)
- {
- _groundUVTransform.x = 1.0f - _groundUVTransform.x;
- }
- if (_groundUVTransform.y >= 1.0f)
- {
- _groundUVTransform.y = 1.0f - _groundUVTransform.y;
- }
- }
- void LongboardGame::keyEvent(Keyboard::KeyEvent evt, int key)
- {
- if (evt == Keyboard::KEY_PRESS)
- {
- switch (key)
- {
- case Keyboard::KEY_ESCAPE:
- exit();
- break;
- case Keyboard::KEY_A:
- case Keyboard::KEY_CAPITAL_A:
- case Keyboard::KEY_LEFT_ARROW:
- _keyFlags |= STEER_LEFT;
- break;
- case Keyboard::KEY_D:
- case Keyboard::KEY_CAPITAL_D:
- case Keyboard::KEY_RIGHT_ARROW:
- _keyFlags |= STEER_RIGHT;
- break;
- case Keyboard::KEY_W:
- case Keyboard::KEY_CAPITAL_W:
- case Keyboard::KEY_UP_ARROW:
- _keyFlags |= ACCELERATE;
- break;
- case Keyboard::KEY_S:
- case Keyboard::KEY_CAPITAL_S:
- case Keyboard::KEY_DOWN_ARROW:
- _keyFlags |= BRAKE;
- break;
- }
- }
- else if (evt == Keyboard::KEY_RELEASE)
- {
- switch (key)
- {
- case Keyboard::KEY_A:
- case Keyboard::KEY_CAPITAL_A:
- case Keyboard::KEY_LEFT_ARROW:
- _keyFlags &= ~STEER_LEFT;
- break;
- case Keyboard::KEY_D:
- case Keyboard::KEY_CAPITAL_D:
- case Keyboard::KEY_RIGHT_ARROW:
- _keyFlags &= ~STEER_RIGHT;
- break;
- case Keyboard::KEY_W:
- case Keyboard::KEY_CAPITAL_W:
- case Keyboard::KEY_UP_ARROW:
- _keyFlags &= ~ACCELERATE;
- break;
- case Keyboard::KEY_S:
- case Keyboard::KEY_CAPITAL_S:
- case Keyboard::KEY_DOWN_ARROW:
- _keyFlags &= ~BRAKE;
- break;
- }
- }
- }
- void LongboardGame::render(float elapsedTime)
- {
- // Clear the color and depth buffers.
- clear(CLEAR_COLOR, Vector4::one(), 1.0f, 0);
- // Draw the scene
- _ground->draw();
- _wheels->draw();
- _board->draw();
- _gradient->draw();
- }
- void LongboardGame::drawSplash(void* param)
- {
- clear(CLEAR_COLOR_DEPTH, Vector4(0, 0, 0, 1), 1.0f, 0);
- SpriteBatch* batch = SpriteBatch::create("res/logo_powered_white.png");
- batch->start();
- batch->draw(this->getWidth() * 0.5f, this->getHeight() * 0.5f, 0.0f, 512.0f, 512.0f, 0.0f, 1.0f, 1.0f, 0.0f, Vector4::one(), true);
- batch->finish();
- SAFE_DELETE(batch);
- }
|