LongboardGame.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369
  1. #include "LongboardGame.h"
  2. // Declare our game instance
  3. LongboardGame game;
  4. // Pick some arbitrarily large world size for our playground
  5. #define WORLD_SIZE 20.0f
  6. // Maximum velocity, in meters/sec
  7. #define VELOCITY_MAX 2.0f
  8. #define VELOCITY_MAX_MS (VELOCITY_MAX / 1000.0f)
  9. // Minimum velocity, in meters/sec
  10. #define VELOCITY_MIN 0.2f
  11. #define VELOCITY_MIN_MS (VELOCITY_MIN / 1000.0f)
  12. // Keyboard input bit-flags (powers of 2)
  13. #define ACCELERATE (1 << 0)
  14. #define BRAKE (1 << 1)
  15. #define STEER_LEFT (1 << 2)
  16. #define STEER_RIGHT (1 << 3)
  17. // Accelerometer pitch control
  18. #define PITCH_MIN 20.0f
  19. #define PITCH_MAX 70.0f
  20. #define PITCH_RANGE (PITCH_MAX - PITCH_MIN)
  21. // Maximum turn rate (rate of change in direction at full velocity), in degrees/sec
  22. #define TURN_RATE_MAX 75.0f
  23. #define TURN_RATE_MAX_MS (TURN_RATE_MAX / 1000.0f)
  24. #define ROLL_MAX 40.0f
  25. LongboardGame::LongboardGame()
  26. : _ground(NULL), _board(NULL), _wheels(NULL), _gradient(NULL), _stateBlock(NULL),
  27. _keyFlags(0), _simulatedPitch(0), _simulatedRoll(0), _velocity(VELOCITY_MIN_MS)
  28. {
  29. }
  30. LongboardGame::~LongboardGame()
  31. {
  32. }
  33. void LongboardGame::initialize()
  34. {
  35. // Display the gameplay splash screen for at least 1 second.
  36. displayScreen(this, &LongboardGame::drawSplash, NULL, 1000L);
  37. // Create our render state block that will be reused across all materials
  38. _stateBlock = RenderState::StateBlock::create();
  39. _stateBlock->setCullFace(true);
  40. _stateBlock->setBlend(true);
  41. _stateBlock->setBlendSrc(RenderState::BLEND_SRC_ALPHA);
  42. _stateBlock->setBlendDst(RenderState::BLEND_ONE_MINUS_SRC_ALPHA);
  43. // Calculate initial matrices
  44. Matrix::createPerspective(45.0f, (float)getWidth() / (float)getHeight(), 0.25f, 100.0f, &_projectionMatrix);
  45. Matrix::createLookAt(0, 1.75f, 1.35f, 0, 0, -0.15f, 0, 0.20f, -0.80f, &_viewMatrix);
  46. Matrix::multiply(_projectionMatrix, _viewMatrix, &_viewProjectionMatrix);
  47. // Build game entities
  48. buildGround();
  49. buildBoard();
  50. buildWheels();
  51. buildGradient();
  52. // Set initial board physics
  53. _direction.set(0, 0, -1);
  54. _velocity = VELOCITY_MIN_MS;
  55. }
  56. void LongboardGame::finalize()
  57. {
  58. SAFE_RELEASE(_stateBlock);
  59. SAFE_RELEASE(_ground);
  60. SAFE_RELEASE(_board);
  61. SAFE_RELEASE(_wheels);
  62. SAFE_RELEASE(_gradient);
  63. SAFE_RELEASE(_wheelsSound);
  64. }
  65. void LongboardGame::buildGround()
  66. {
  67. // Create a large quad for the ground
  68. Mesh* groundMesh = Mesh::createQuad(Vector3(-WORLD_SIZE, 0, -WORLD_SIZE),
  69. Vector3(-WORLD_SIZE, 0, WORLD_SIZE),
  70. Vector3(WORLD_SIZE, 0, -WORLD_SIZE),
  71. Vector3(WORLD_SIZE, 0, WORLD_SIZE));
  72. // Create the ground model
  73. _ground = Model::create(groundMesh);
  74. // Create the ground material
  75. Material* groundMaterial = _ground->setMaterial("res/shaders/textured-unlit.vert", "res/shaders/textured-unlit.frag", "TEXTURE_REPEAT;TEXTURE_OFFSET");
  76. // Set render state block
  77. groundMaterial->setStateBlock(_stateBlock);
  78. // Bind ground material parameters
  79. Texture::Sampler* groundSampler = groundMaterial->getParameter("u_diffuseTexture")->setValue("res/asphalt.png", true);
  80. groundSampler->setWrapMode(Texture::REPEAT, Texture::REPEAT);
  81. groundMaterial->getParameter("u_worldViewProjectionMatrix")->setValue(&_groundWorldViewProjectionMatrix);
  82. groundMaterial->getParameter("u_textureRepeat")->setValue(Vector2(WORLD_SIZE / 2, WORLD_SIZE / 2));
  83. groundMaterial->getParameter("u_textureOffset")->setValue(&_groundUVTransform);
  84. // Release objects that are owned by mesh instances
  85. SAFE_RELEASE(groundMesh);
  86. }
  87. void LongboardGame::buildBoard()
  88. {
  89. // Create longboard mesh
  90. Mesh* boardMesh = Mesh::createQuad(Vector3(-0.5f, 0.1f, -1.0f),
  91. Vector3(-0.5f, 0.1f, 1.0f),
  92. Vector3(0.5f, 0.1f, -1.0f),
  93. Vector3(0.5f, 0.1f, 1.0f) );
  94. // Create the board model
  95. _board = Model::create(boardMesh);
  96. // Create the board material
  97. Material* boardMaterial = _board->setMaterial("res/shaders/textured-unlit.vert", "res/shaders/textured-unlit.frag", "TEXTURE_REPEAT;TEXTURE_OFFSET");
  98. // Set render state block
  99. boardMaterial->setStateBlock(_stateBlock);
  100. // Bind board material parameters
  101. Texture::Sampler* boardSampler = boardMaterial->getParameter("u_diffuseTexture")->setValue("res/longboard.png", true);
  102. boardSampler->setWrapMode(Texture::CLAMP, Texture::CLAMP);
  103. boardMaterial->getParameter("u_worldViewProjectionMatrix")->setValue(&_boardWorldViewProjectionMatrix);
  104. boardMaterial->getParameter("u_textureRepeat")->setValue(Vector2::one());
  105. boardMaterial->getParameter("u_textureOffset")->setValue(Vector2::zero());
  106. // Release objects that are owned by mesh instances
  107. SAFE_RELEASE(boardMesh);
  108. }
  109. void LongboardGame::buildWheels()
  110. {
  111. // Create wheels mesh
  112. Mesh* wheelsMesh = Mesh::createQuad(Vector3(-0.5f, 0.025f, -0.25f),
  113. Vector3(-0.5f, 0.025f, 0.25f),
  114. Vector3(0.5f, 0.025f, -0.25f),
  115. Vector3(0.5f, 0.025f, 0.25f));
  116. // Create the wheels model
  117. _wheels = Model::create(wheelsMesh);
  118. // Create the wheels material
  119. Material* wheelsMaterial = _wheels->setMaterial("res/shaders/textured-unlit.vert", "res/shaders/textured-unlit.frag", "TEXTURE_REPEAT;TEXTURE_OFFSET");
  120. // Set render state block
  121. wheelsMaterial->setStateBlock(_stateBlock);
  122. // Bind wheels material parameters
  123. Texture::Sampler* wheelsSampler = wheelsMaterial->getParameter("u_diffuseTexture")->setValue("res/longboard_wheels.png", true);
  124. wheelsSampler->setWrapMode(Texture::CLAMP, Texture::CLAMP);
  125. wheelsMaterial->getParameter("u_worldViewProjectionMatrix")->setValue(&_wheelsWorldViewProjectionMatrix);
  126. wheelsMaterial->getParameter("u_textureRepeat")->setValue(Vector2::one());
  127. wheelsMaterial->getParameter("u_textureOffset")->setValue(Vector2::zero());
  128. // Load audio sound
  129. _wheelsSound = AudioSource::create("res/longboard.wav");
  130. if (_wheelsSound)
  131. _wheelsSound->setLooped(true);
  132. // Release objects that are owned by mesh instances
  133. SAFE_RELEASE(wheelsMesh);
  134. }
  135. void LongboardGame::buildGradient()
  136. {
  137. // Create a full-screen quad for rendering a screen-space gradient effect to the scene
  138. Mesh* gradientMesh = Mesh::createQuadFullscreen();
  139. // Create the wheels model
  140. _gradient = Model::create(gradientMesh);
  141. // Create the gradient material.
  142. Material* gradientMaterial = _gradient->setMaterial("res/shaders/textured-unlit.vert", "res/shaders/textured-unlit.frag");
  143. // Set render state block
  144. gradientMaterial->setStateBlock(_stateBlock);
  145. // Bind material parameters
  146. Texture::Sampler* gradientSampler = gradientMaterial->getParameter("u_diffuseTexture")->setValue("res/overlay_gradient.png", false);
  147. gradientSampler->setWrapMode(Texture::CLAMP, Texture::CLAMP);
  148. // Release objects that are owned by mesh instances
  149. SAFE_RELEASE(gradientMesh);
  150. }
  151. void LongboardGame::update(float elapsedTime)
  152. {
  153. // Query the accelerometer values.
  154. float pitch, roll;
  155. getAccelerometerValues(&pitch, &roll);
  156. // On desktop platforms without accelerometers, use key inputs instead.
  157. if (!Game::hasAccelerometer())
  158. {
  159. float pitchTarget = 0;
  160. float rollTarget = 0;
  161. pitch = _simulatedPitch;
  162. roll = _simulatedRoll;
  163. pitchTarget = -0.5f * (PITCH_MAX + PITCH_MIN);
  164. if (_keyFlags & BRAKE)
  165. {
  166. pitchTarget = -PITCH_MAX;
  167. }
  168. else if (_keyFlags & ACCELERATE)
  169. {
  170. pitchTarget = -PITCH_MIN;
  171. }
  172. if (_keyFlags & STEER_RIGHT)
  173. {
  174. rollTarget += ROLL_MAX;
  175. }
  176. if (_keyFlags & STEER_LEFT)
  177. {
  178. rollTarget -= ROLL_MAX;
  179. }
  180. MathUtil::smooth(&_simulatedPitch, pitchTarget, elapsedTime, 600);
  181. MathUtil::smooth(&_simulatedRoll, rollTarget, elapsedTime, 100);
  182. }
  183. // Clamp angles
  184. pitch = max(min(-pitch, PITCH_MAX), PITCH_MIN);
  185. roll = max(min(roll, ROLL_MAX), -ROLL_MAX);
  186. // Calculate the 'throttle' (which is the % controlling change in acceleration, similar to a car's gas pedal)
  187. float throttle = 1.0f - ((pitch - PITCH_MIN) / PITCH_RANGE);
  188. if (throttle > 0.0f)
  189. {
  190. if (_wheelsSound->getState() != AudioSource::PLAYING)
  191. _wheelsSound->play();
  192. _wheelsSound->setPitch(throttle);
  193. }
  194. else
  195. {
  196. _wheelsSound->stop();
  197. }
  198. // Update velocity based on current throttle.
  199. // Note that this is a very simplified calculation that ignores acceleration (assumes it's constant)
  200. _velocity = VELOCITY_MIN_MS + ((VELOCITY_MAX_MS - VELOCITY_MIN_MS) * throttle);
  201. // Update direction based on accelerometer roll and max turn rate
  202. static Matrix rotMat;
  203. Matrix::createRotationY(MATH_DEG_TO_RAD((TURN_RATE_MAX_MS * elapsedTime) * (roll / ROLL_MAX) * throttle), &rotMat);
  204. rotMat.transformVector(&_direction);
  205. _direction.normalize();
  206. // Transform the ground. We rotate the ground instead of the board since we don't actually
  207. // move the board along the ground (we just simulate moving it so it appears infinite).
  208. Matrix::multiply(rotMat, _groundWorldMatrix, &_groundWorldMatrix);
  209. Matrix::multiply(_viewProjectionMatrix, _groundWorldMatrix, &_groundWorldViewProjectionMatrix);
  210. // Transform the wheels
  211. Matrix::createScale(1.2f, 1.2f, 1.2f, &_wheelsWorldMatrix);
  212. _wheelsWorldMatrix.translate(roll / ROLL_MAX * 0.05f, 0, 0.05f);
  213. _wheelsWorldMatrix.rotateY(-MATH_DEG_TO_RAD(roll * 0.45f));
  214. Matrix::multiply(_viewProjectionMatrix, _wheelsWorldMatrix, &_wheelsWorldViewProjectionMatrix);
  215. // Transform and tilt the board
  216. Matrix::createScale(1.25f, 1.25f, 1.25f, &_boardWorldMatrix);
  217. _boardWorldMatrix.translate(0, 0, 0.65f);
  218. _boardWorldMatrix.rotateZ(-MATH_DEG_TO_RAD(roll * 0.5f));
  219. _boardWorldMatrix.rotateY(-MATH_DEG_TO_RAD(roll * 0.1f));
  220. Matrix::multiply(_viewProjectionMatrix, _boardWorldMatrix, &_boardWorldViewProjectionMatrix);
  221. // Transform the ground texture coords to give the illusion of the board moving.
  222. // We'll assume that a 'patch' of ground is equal to 1 meter.
  223. _groundUVTransform.x += -_direction.x * (_velocity * elapsedTime);
  224. _groundUVTransform.y += -_direction.z * (_velocity * elapsedTime);
  225. if (_groundUVTransform.x >= 1.0f)
  226. {
  227. _groundUVTransform.x = 1.0f - _groundUVTransform.x;
  228. }
  229. if (_groundUVTransform.y >= 1.0f)
  230. {
  231. _groundUVTransform.y = 1.0f - _groundUVTransform.y;
  232. }
  233. }
  234. void LongboardGame::keyEvent(Keyboard::KeyEvent evt, int key)
  235. {
  236. if (evt == Keyboard::KEY_PRESS)
  237. {
  238. switch (key)
  239. {
  240. case Keyboard::KEY_ESCAPE:
  241. exit();
  242. break;
  243. case Keyboard::KEY_A:
  244. case Keyboard::KEY_CAPITAL_A:
  245. case Keyboard::KEY_LEFT_ARROW:
  246. _keyFlags |= STEER_LEFT;
  247. break;
  248. case Keyboard::KEY_D:
  249. case Keyboard::KEY_CAPITAL_D:
  250. case Keyboard::KEY_RIGHT_ARROW:
  251. _keyFlags |= STEER_RIGHT;
  252. break;
  253. case Keyboard::KEY_W:
  254. case Keyboard::KEY_CAPITAL_W:
  255. case Keyboard::KEY_UP_ARROW:
  256. _keyFlags |= ACCELERATE;
  257. break;
  258. case Keyboard::KEY_S:
  259. case Keyboard::KEY_CAPITAL_S:
  260. case Keyboard::KEY_DOWN_ARROW:
  261. _keyFlags |= BRAKE;
  262. break;
  263. }
  264. }
  265. else if (evt == Keyboard::KEY_RELEASE)
  266. {
  267. switch (key)
  268. {
  269. case Keyboard::KEY_A:
  270. case Keyboard::KEY_CAPITAL_A:
  271. case Keyboard::KEY_LEFT_ARROW:
  272. _keyFlags &= ~STEER_LEFT;
  273. break;
  274. case Keyboard::KEY_D:
  275. case Keyboard::KEY_CAPITAL_D:
  276. case Keyboard::KEY_RIGHT_ARROW:
  277. _keyFlags &= ~STEER_RIGHT;
  278. break;
  279. case Keyboard::KEY_W:
  280. case Keyboard::KEY_CAPITAL_W:
  281. case Keyboard::KEY_UP_ARROW:
  282. _keyFlags &= ~ACCELERATE;
  283. break;
  284. case Keyboard::KEY_S:
  285. case Keyboard::KEY_CAPITAL_S:
  286. case Keyboard::KEY_DOWN_ARROW:
  287. _keyFlags &= ~BRAKE;
  288. break;
  289. }
  290. }
  291. }
  292. void LongboardGame::render(float elapsedTime)
  293. {
  294. // Clear the color and depth buffers.
  295. clear(CLEAR_COLOR, Vector4::one(), 1.0f, 0);
  296. // Draw the scene
  297. _ground->draw();
  298. _wheels->draw();
  299. _board->draw();
  300. _gradient->draw();
  301. }
  302. void LongboardGame::drawSplash(void* param)
  303. {
  304. clear(CLEAR_COLOR_DEPTH, Vector4(0, 0, 0, 1), 1.0f, 0);
  305. SpriteBatch* batch = SpriteBatch::create("res/logo_powered_white.png");
  306. batch->start();
  307. 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);
  308. batch->finish();
  309. SAFE_DELETE(batch);
  310. }