Explorar el Código

Chapter 3 code done

Sanjay Madhav hace 8 años
padre
commit
25cb1fe08e

+ 18 - 0
Chapter03/Actor.cpp

@@ -53,6 +53,24 @@ void Actor::UpdateActor(float deltaTime)
 {
 }
 
+void Actor::ProcessInput(const uint8_t* keyState)
+{
+	if (mState == EActive)
+	{
+		// First process input for components
+		for (auto comp : mComponents)
+		{
+			comp->ProcessInput(keyState);
+		}
+
+		ActorInput(keyState);
+	}
+}
+
+void Actor::ActorInput(const uint8_t* keyState)
+{
+}
+
 void Actor::AddComponent(Component* component)
 {
 	// Find the insertion point in the sorted vector

+ 7 - 0
Chapter03/Actor.h

@@ -9,6 +9,8 @@
 #pragma once
 #include <vector>
 #include "Math.h"
+#include <cstdint>
+
 class Actor
 {
 public:
@@ -29,6 +31,11 @@ public:
 	// Any actor-specific update code (overridable)
 	virtual void UpdateActor(float deltaTime);
 
+	// ProcessInput function called from Game (not overridable)
+	void ProcessInput(const uint8_t* keyState);
+	// Any actor-specific input code (overridable)
+	virtual void ActorInput(const uint8_t* keyState);
+
 	// Getters/setters
 	const Vector2& GetPosition() const { return mPosition; }
 	void SetPosition(const Vector2& pos) { mPosition = pos; }

+ 46 - 0
Chapter03/Asteroid.cpp

@@ -0,0 +1,46 @@
+// ----------------------------------------------------------------
+// From Game Programming in C++ by Sanjay Madhav
+// Copyright (C) 2017 Sanjay Madhav. All rights reserved.
+// 
+// Released under the BSD License
+// See LICENSE in root directory for full details.
+// ----------------------------------------------------------------
+
+#include "Asteroid.h"
+#include "SpriteComponent.h"
+#include "MoveComponent.h"
+#include "Game.h"
+#include "Random.h"
+#include "CircleComponent.h"
+
+Asteroid::Asteroid(Game* game)
+	:Actor(game)
+	,mCircle(nullptr)
+{
+	// Initialize to random position/orientation
+	Vector2 randPos = Random::GetVector(Vector2::Zero,
+		Vector2(1024.0f, 768.0f));
+	SetPosition(randPos);
+
+	SetRotation(Random::GetFloatRange(0.0f, Math::TwoPi));
+
+	// Create a sprite component
+	SpriteComponent* sc = new SpriteComponent(this);
+	sc->SetTexture(game->GetTexture("Assets/Asteroid.png"));
+
+	// Create a move component, and set a forward speed
+	MoveComponent* mc = new MoveComponent(this);
+	mc->SetForwardSpeed(150.0f);
+
+	// Create a circle component (for collision)
+	mCircle = new CircleComponent(this);
+	mCircle->SetRadius(40.0f);
+
+	// Add to mAsteroids in game
+	game->AddAsteroid(this);
+}
+
+Asteroid::~Asteroid()
+{
+	GetGame()->RemoveAsteroid(this);
+}

+ 20 - 0
Chapter03/Asteroid.h

@@ -0,0 +1,20 @@
+// ----------------------------------------------------------------
+// From Game Programming in C++ by Sanjay Madhav
+// Copyright (C) 2017 Sanjay Madhav. All rights reserved.
+// 
+// Released under the BSD License
+// See LICENSE in root directory for full details.
+// ----------------------------------------------------------------
+
+#pragma once
+#include "Actor.h"
+class Asteroid : public Actor
+{
+public:
+	Asteroid(class Game* game);
+	~Asteroid();
+	
+	class CircleComponent* GetCircle() { return mCircle; }
+private:
+	class CircleComponent* mCircle;
+};

+ 40 - 0
Chapter03/CircleComponent.cpp

@@ -0,0 +1,40 @@
+// ----------------------------------------------------------------
+// From Game Programming in C++ by Sanjay Madhav
+// Copyright (C) 2017 Sanjay Madhav. All rights reserved.
+// 
+// Released under the BSD License
+// See LICENSE in root directory for full details.
+// ----------------------------------------------------------------
+
+#include "CircleComponent.h"
+#include "Actor.h"
+
+CircleComponent::CircleComponent(class Actor* owner)
+:Component(owner)
+,mRadius(0.0f)
+{
+	
+}
+
+const Vector2& CircleComponent::GetCenter() const
+{
+	return mOwner->GetPosition();
+}
+
+float CircleComponent::GetRadius() const
+{
+	return mOwner->GetScale() * mRadius;
+}
+
+bool Intersect(const CircleComponent& a, const CircleComponent& b)
+{
+	// Calculate distance squared
+	Vector2 diff = a.GetCenter() - b.GetCenter();
+	float distSq = diff.LengthSq();
+
+	// Calculate sum of radii squared
+	float radiiSq = a.GetRadius() + b.GetRadius();
+	radiiSq *= radiiSq;
+
+	return distSq <= radiiSq;
+}

+ 26 - 0
Chapter03/CircleComponent.h

@@ -0,0 +1,26 @@
+// ----------------------------------------------------------------
+// From Game Programming in C++ by Sanjay Madhav
+// Copyright (C) 2017 Sanjay Madhav. All rights reserved.
+// 
+// Released under the BSD License
+// See LICENSE in root directory for full details.
+// ----------------------------------------------------------------
+
+#pragma once
+#include "Component.h"
+#include "Math.h"
+
+class CircleComponent : public Component
+{
+public:
+	CircleComponent(class Actor* owner);
+	
+	void SetRadius(float radius) { mRadius = radius; }
+	float GetRadius() const;
+	
+	const Vector2& GetCenter() const;
+private:
+	float mRadius;
+};
+
+bool Intersect(const CircleComponent& a, const CircleComponent& b);

+ 4 - 0
Chapter03/Component.h

@@ -7,6 +7,8 @@
 // ----------------------------------------------------------------
 
 #pragma once
+#include <cstdint>
+
 class Component
 {
 public:
@@ -17,6 +19,8 @@ public:
 	virtual ~Component();
 	// Update this component by delta time
 	virtual void Update(float deltaTime);
+	// Process input for this component
+	virtual void ProcessInput(const uint8_t* keyState) {}
 
 	int GetUpdateOrder() const { return mUpdateOrder; }
 protected:

+ 37 - 6
Chapter03/Game.cpp

@@ -12,6 +12,8 @@
 #include "Actor.h"
 #include "SpriteComponent.h"
 #include "Ship.h"
+#include "Asteroid.h"
+#include "Random.h"
 
 Game::Game()
 :mWindow(nullptr)
@@ -50,6 +52,8 @@ bool Game::Initialize()
 		return false;
 	}
 
+	Random::Init();
+
 	LoadData();
 
 	mTicksCount = SDL_GetTicks();
@@ -80,14 +84,18 @@ void Game::ProcessInput()
 		}
 	}
 	
-	const Uint8* state = SDL_GetKeyboardState(NULL);
-	if (state[SDL_SCANCODE_ESCAPE])
+	const Uint8* keyState = SDL_GetKeyboardState(NULL);
+	if (keyState[SDL_SCANCODE_ESCAPE])
 	{
 		mIsRunning = false;
 	}
 
-	// Process ship input
-	mShip->ProcessKeyboard(state);
+	mUpdatingActors = true;
+	for (auto actor : mActors)
+	{
+		actor->ProcessInput(keyState);
+	}
+	mUpdatingActors = false;
 }
 
 void Game::UpdateGame()
@@ -138,7 +146,7 @@ void Game::UpdateGame()
 
 void Game::GenerateOutput()
 {
-	SDL_SetRenderDrawColor(mRenderer, 0, 0, 0, 255);
+	SDL_SetRenderDrawColor(mRenderer, 220, 220, 220, 255);
 	SDL_RenderClear(mRenderer);
 	
 	// Draw all sprite components
@@ -154,7 +162,15 @@ void Game::LoadData()
 {
 	// Create player's ship
 	mShip = new Ship(this);
-	mShip->SetPosition(Vector2(100.0f, 384.0f));
+	mShip->SetPosition(Vector2(512.0f, 384.0f));
+	mShip->SetRotation(Math::PiOver2);
+
+	// Create asteroids
+	const int numAsteroids = 20;
+	for (int i = 0; i < numAsteroids; i++)
+	{
+		new Asteroid(this);
+	}
 }
 
 void Game::UnloadData()
@@ -207,6 +223,21 @@ SDL_Texture* Game::GetTexture(const std::string& fileName)
 	return tex;
 }
 
+void Game::AddAsteroid(Asteroid* ast)
+{
+	mAsteroids.emplace_back(ast);
+}
+
+void Game::RemoveAsteroid(Asteroid* ast)
+{
+	auto iter = std::find(mAsteroids.begin(),
+		mAsteroids.end(), ast);
+	if (iter != mAsteroids.end())
+	{
+		mAsteroids.erase(iter);
+	}
+}
+
 void Game::Shutdown()
 {
 	UnloadData();

+ 6 - 0
Chapter03/Game.h

@@ -27,6 +27,11 @@ public:
 	void RemoveSprite(class SpriteComponent* sprite);
 	
 	SDL_Texture* GetTexture(const std::string& fileName);
+
+	// Game-specific (add/remove asteroid)
+	void AddAsteroid(class Asteroid* ast);
+	void RemoveAsteroid(class Asteroid* ast);
+	std::vector<class Asteroid*>& GetAsteroids() { return mAsteroids; }
 private:
 	void ProcessInput();
 	void UpdateGame();
@@ -54,4 +59,5 @@ private:
 
 	// Game-specific
 	class Ship* mShip; // Player's ship
+	std::vector<class Asteroid*> mAsteroids;
 };

+ 10 - 0
Chapter03/Game.vcxproj

@@ -12,20 +12,30 @@
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="Actor.cpp" />
+    <ClCompile Include="Asteroid.cpp" />
+    <ClCompile Include="CircleComponent.cpp" />
     <ClCompile Include="Component.cpp" />
     <ClCompile Include="Game.cpp" />
+    <ClCompile Include="InputComponent.cpp" />
+    <ClCompile Include="Laser.cpp" />
     <ClCompile Include="Main.cpp" />
     <ClCompile Include="Math.cpp" />
     <ClCompile Include="MoveComponent.cpp" />
+    <ClCompile Include="Random.cpp" />
     <ClCompile Include="Ship.cpp" />
     <ClCompile Include="SpriteComponent.cpp" />
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="Actor.h" />
+    <ClInclude Include="Asteroid.h" />
+    <ClInclude Include="CircleComponent.h" />
     <ClInclude Include="Component.h" />
     <ClInclude Include="Game.h" />
+    <ClInclude Include="InputComponent.h" />
+    <ClInclude Include="Laser.h" />
     <ClInclude Include="Math.h" />
     <ClInclude Include="MoveComponent.h" />
+    <ClInclude Include="Random.h" />
     <ClInclude Include="Ship.h" />
     <ClInclude Include="SpriteComponent.h" />
   </ItemGroup>

+ 30 - 0
Chapter03/Game.vcxproj.filters

@@ -31,6 +31,21 @@
     <ClCompile Include="MoveComponent.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="Asteroid.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="Random.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="InputComponent.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="CircleComponent.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="Laser.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="Actor.h">
@@ -54,5 +69,20 @@
     <ClInclude Include="MoveComponent.h">
       <Filter>Source Files</Filter>
     </ClInclude>
+    <ClInclude Include="Asteroid.h">
+      <Filter>Source Files</Filter>
+    </ClInclude>
+    <ClInclude Include="Random.h">
+      <Filter>Source Files</Filter>
+    </ClInclude>
+    <ClInclude Include="InputComponent.h">
+      <Filter>Source Files</Filter>
+    </ClInclude>
+    <ClInclude Include="CircleComponent.h">
+      <Filter>Source Files</Filter>
+    </ClInclude>
+    <ClInclude Include="Laser.h">
+      <Filter>Source Files</Filter>
+    </ClInclude>
   </ItemGroup>
 </Project>

+ 47 - 0
Chapter03/InputComponent.cpp

@@ -0,0 +1,47 @@
+// ----------------------------------------------------------------
+// From Game Programming in C++ by Sanjay Madhav
+// Copyright (C) 2017 Sanjay Madhav. All rights reserved.
+// 
+// Released under the BSD License
+// See LICENSE in root directory for full details.
+// ----------------------------------------------------------------
+
+#include "InputComponent.h"
+#include "Actor.h"
+
+InputComponent::InputComponent(class Actor* owner)
+:MoveComponent(owner)
+,mForwardKey(0)
+,mBackKey(0)
+,mClockwiseKey(0)
+,mCounterClockwiseKey(0)
+{
+	
+}
+
+void InputComponent::ProcessInput(const uint8_t* keyState)
+{
+	// Calculate forward speed for MoveComponent
+	float forwardSpeed = 0.0f;
+	if (keyState[mForwardKey])
+	{
+		forwardSpeed += mMaxForwardSpeed;
+	}
+	if (keyState[mBackKey])
+	{
+		forwardSpeed -= mMaxForwardSpeed;
+	}
+	SetForwardSpeed(forwardSpeed);
+
+	// Calculate angular speed for MoveComponent
+	float angularSpeed = 0.0f;
+	if (keyState[mClockwiseKey])
+	{
+		angularSpeed += mMaxAngularSpeed;
+	}
+	if (keyState[mCounterClockwiseKey])
+	{
+		angularSpeed -= mMaxAngularSpeed;
+	}
+	SetAngularSpeed(angularSpeed);
+}

+ 45 - 0
Chapter03/InputComponent.h

@@ -0,0 +1,45 @@
+// ----------------------------------------------------------------
+// From Game Programming in C++ by Sanjay Madhav
+// Copyright (C) 2017 Sanjay Madhav. All rights reserved.
+// 
+// Released under the BSD License
+// See LICENSE in root directory for full details.
+// ----------------------------------------------------------------
+
+#pragma once
+#include "MoveComponent.h"
+#include <cstdint>
+
+class InputComponent : public MoveComponent
+{
+public:
+	// Lower update order to update first
+	InputComponent(class Actor* owner);
+
+	void ProcessInput(const uint8_t* keyState) override;
+	
+	// Getters/setters for private variables
+	float GetMaxForward() const { return mMaxForwardSpeed; }
+	float GetMaxAngular() const { return mMaxAngularSpeed; }
+	int GetForwardKey() const { return mForwardKey; }
+	int GetBackKey() const { return mBackKey; }
+	int GetClockwiseKey() const { return mClockwiseKey; }
+	int GetCounterClockwiseKey() const { return mCounterClockwiseKey; }
+
+	void SetMaxForwardSpeed(float speed) { mMaxForwardSpeed = speed; }
+	void SetMaxAngularSpeed(float speed) { mMaxAngularSpeed = speed; }
+	void SetForwardKey(int key) { mForwardKey = key; }
+	void SetBackKey(int key) { mBackKey = key; }
+	void SetClockwiseKey(int key) { mClockwiseKey = key; }
+	void SetCounterClockwiseKey(int key) { mCounterClockwiseKey = key; }
+private:
+	// The maximum forward/angular speeds
+	float mMaxForwardSpeed;
+	float mMaxAngularSpeed;
+	// Keys for forward/back movement
+	int mForwardKey;
+	int mBackKey;
+	// Keys for angular movement
+	int mClockwiseKey;
+	int mCounterClockwiseKey;
+};

+ 56 - 0
Chapter03/Laser.cpp

@@ -0,0 +1,56 @@
+// ----------------------------------------------------------------
+// From Game Programming in C++ by Sanjay Madhav
+// Copyright (C) 2017 Sanjay Madhav. All rights reserved.
+// 
+// Released under the BSD License
+// See LICENSE in root directory for full details.
+// ----------------------------------------------------------------
+
+#include "Laser.h"
+#include "SpriteComponent.h"
+#include "MoveComponent.h"
+#include "Game.h"
+#include "CircleComponent.h"
+#include "Asteroid.h"
+
+Laser::Laser(Game* game)
+	:Actor(game)
+	,mDeathTimer(1.0f)
+{
+	// Create a sprite component
+	SpriteComponent* sc = new SpriteComponent(this);
+	sc->SetTexture(game->GetTexture("Assets/Laser.png"));
+
+	// Create a move component, and set a forward speed
+	MoveComponent* mc = new MoveComponent(this);
+	mc->SetForwardSpeed(800.0f);
+
+	// Create a circle component (for collision)
+	mCircle = new CircleComponent(this);
+	mCircle->SetRadius(11.0f);
+}
+
+void Laser::UpdateActor(float deltaTime)
+{
+	// If we run out of time, laser is dead
+	mDeathTimer -= deltaTime;
+	if (mDeathTimer <= 0.0f)
+	{
+		SetState(EDead);
+	}
+	else
+	{
+		// Do we intersect with an asteroid?
+		for (auto ast : GetGame()->GetAsteroids())
+		{
+			if (Intersect(*mCircle, *(ast->GetCircle())))
+			{
+				// The first asteroid we intersect with,
+				// set ourselves and the asteroid to dead
+				SetState(EDead);
+				ast->SetState(EDead);
+				break;
+			}
+		}
+	}
+}

+ 20 - 0
Chapter03/Laser.h

@@ -0,0 +1,20 @@
+// ----------------------------------------------------------------
+// From Game Programming in C++ by Sanjay Madhav
+// Copyright (C) 2017 Sanjay Madhav. All rights reserved.
+// 
+// Released under the BSD License
+// See LICENSE in root directory for full details.
+// ----------------------------------------------------------------
+
+#pragma once
+#include "Actor.h"
+class Laser : public Actor
+{
+public:
+	Laser(class Game* game);
+
+	void UpdateActor(float deltaTime) override;
+private:
+	class CircleComponent* mCircle;
+	float mDeathTimer;
+};

+ 9 - 1
Chapter03/MoveComponent.cpp

@@ -29,7 +29,15 @@ void MoveComponent::Update(float deltaTime)
 	if (!Math::NearZero(mForwardSpeed))
 	{
 		Vector2 pos = mOwner->GetPosition();
-		pos += mOwner->GetForward() * mForwardSpeed * deltaTime;		
+		pos += mOwner->GetForward() * mForwardSpeed * deltaTime;
+		
+		// (Screen wrapping code only for asteroids)
+		if (pos.x < 0.0f) { pos.x = 1022.0f; }
+		else if (pos.x > 1024.0f) { pos.x = 2.0f; }
+
+		if (pos.y < 0.0f) { pos.y = 766.0f; }
+		else if (pos.y > 768.0f) { pos.y = 2.0f; }
+
 		mOwner->SetPosition(pos);
 	}
 }

+ 3 - 0
Chapter03/MoveComponent.h

@@ -14,6 +14,7 @@ class MoveComponent : public Component
 public:
 	// Lower update order to update first
 	MoveComponent(class Actor* owner, int updateOrder = 10);
+
 	void Update(float deltaTime) override;
 	
 	float GetAngularSpeed() const { return mAngularSpeed; }
@@ -21,6 +22,8 @@ public:
 	void SetAngularSpeed(float speed) { mAngularSpeed = speed; }
 	void SetForwardSpeed(float speed) { mForwardSpeed = speed; }
 private:
+	// Controls rotation (radians/second)
 	float mAngularSpeed;
+	// Controls forward movement (units/second)
 	float mForwardSpeed;
 };

+ 51 - 0
Chapter03/Random.cpp

@@ -0,0 +1,51 @@
+// ----------------------------------------------------------------
+// From Game Programming in C++ by Sanjay Madhav
+// Copyright (C) 2017 Sanjay Madhav. All rights reserved.
+// 
+// Released under the BSD License
+// See LICENSE in root directory for full details.
+// ----------------------------------------------------------------
+
+#include "Random.h"
+
+void Random::Init()
+{
+	std::random_device rd;
+	Random::Seed(rd());
+}
+
+void Random::Seed(unsigned int seed)
+{
+	sGenerator.seed(seed);
+}
+
+float Random::GetFloat()
+{
+	return GetFloatRange(0.0f, 1.0f);
+}
+
+float Random::GetFloatRange(float min, float max)
+{
+	std::uniform_real_distribution<float> dist(min, max);
+	return dist(sGenerator);
+}
+
+int Random::GetIntRange(int min, int max)
+{
+	std::uniform_int_distribution<int> dist(min, max);
+	return dist(sGenerator);
+}
+
+Vector2 Random::GetVector(const Vector2& min, const Vector2& max)
+{
+	Vector2 r = Vector2(GetFloat(), GetFloat());
+	return min + (max - min) * r;
+}
+
+Vector3 Random::GetVector(const Vector3& min, const Vector3& max)
+{
+	Vector3 r = Vector3(GetFloat(), GetFloat(), GetFloat());
+	return min + (max - min) * r;
+}
+
+std::mt19937 Random::sGenerator;

+ 36 - 0
Chapter03/Random.h

@@ -0,0 +1,36 @@
+// ----------------------------------------------------------------
+// From Game Programming in C++ by Sanjay Madhav
+// Copyright (C) 2017 Sanjay Madhav. All rights reserved.
+// 
+// Released under the BSD License
+// See LICENSE in root directory for full details.
+// ----------------------------------------------------------------
+
+#pragma  once
+#include <random>
+#include "Math.h"
+
+class Random
+{
+public:
+	static void Init();
+
+	// Seed the generator with the specified int
+	// NOTE: You should generally not need to manually use this
+	static void Seed(unsigned int seed);
+
+	// Get a float between 0.0f and 1.0f
+	static float GetFloat();
+	
+	// Get a float from the specified range
+	static float GetFloatRange(float min, float max);
+
+	// Get an int from the specified range
+	static int GetIntRange(int min, int max);
+
+	// Get a random vector given the min/max bounds
+	static Vector2 GetVector(const Vector2& min, const Vector2& max);
+	static Vector3 GetVector(const Vector3& min, const Vector3& max);
+private:
+	static std::mt19937 sGenerator;
+};

+ 23 - 45
Chapter03/Ship.cpp

@@ -8,65 +8,43 @@
 
 #include "Ship.h"
 #include "SpriteComponent.h"
+#include "InputComponent.h"
 #include "Game.h"
+#include "Laser.h"
 
 Ship::Ship(Game* game)
 	:Actor(game)
-	,mRightSpeed(0.0f)
-	,mDownSpeed(0.0f)
+	,mLaserCooldown(0.0f)
 {
-	// Create an animated sprite component
+	// Create a sprite component
 	SpriteComponent* sc = new SpriteComponent(this);
 	sc->SetTexture(game->GetTexture("Assets/Ship.png"));
+
+	// Create an input component and set keys/speed
+	InputComponent* ic = new InputComponent(this);
+	ic->SetForwardKey(SDL_SCANCODE_W);
+	ic->SetBackKey(SDL_SCANCODE_S);
+	ic->SetClockwiseKey(SDL_SCANCODE_A);
+	ic->SetCounterClockwiseKey(SDL_SCANCODE_D);
+	ic->SetMaxForwardSpeed(300.0f);
+	ic->SetMaxAngularSpeed(Math::TwoPi);
 }
 
 void Ship::UpdateActor(float deltaTime)
 {
-	Actor::UpdateActor(deltaTime);
-	// Update position based on speeds and delta time
-	Vector2 pos = GetPosition();
-	pos.x += mRightSpeed * deltaTime;
-	pos.y += mDownSpeed * deltaTime;
-	// Restrict position to left half of screen
-	if (pos.x < 25.0f)
-	{
-		pos.x = 25.0f;
-	}
-	else if (pos.x > 500.0f)
-	{
-		pos.x = 500.0f;
-	}
-	if (pos.y < 25.0f)
-	{
-		pos.y = 25.0f;
-	}
-	else if (pos.y > 743.0f)
-	{
-		pos.y = 743.0f;
-	}
-	SetPosition(pos);
+	mLaserCooldown -= deltaTime;
 }
 
-void Ship::ProcessKeyboard(const uint8_t* state)
+void Ship::ActorInput(const uint8_t* keyState)
 {
-	mRightSpeed = 0.0f;
-	mDownSpeed = 0.0f;
-	// right/left
-	if (state[SDL_SCANCODE_D])
-	{
-		mRightSpeed += 250.0f;
-	}
-	if (state[SDL_SCANCODE_A])
-	{
-		mRightSpeed -= 250.0f;
-	}
-	// up/down
-	if (state[SDL_SCANCODE_S])
-	{
-		mDownSpeed += 300.0f;
-	}
-	if (state[SDL_SCANCODE_W])
+	if (keyState[SDL_SCANCODE_SPACE] && mLaserCooldown <= 0.0f)
 	{
-		mDownSpeed -= 300.0f;
+		// Create a laser and set it's position/rotation to mine
+		Laser* laser = new Laser(GetGame());
+		laser->SetPosition(GetPosition());
+		laser->SetRotation(GetRotation());
+
+		// Reset laser cooldown (half second)
+		mLaserCooldown = 0.5f;
 	}
 }

+ 3 - 5
Chapter03/Ship.h

@@ -12,11 +12,9 @@ class Ship : public Actor
 {
 public:
 	Ship(class Game* game);
+
 	void UpdateActor(float deltaTime) override;
-	void ProcessKeyboard(const uint8_t* state);
-	float GetRightSpeed() const { return mRightSpeed; }
-	float GetDownSpeed() const { return mDownSpeed; }
+	void ActorInput(const uint8_t* keyState) override;
 private:
-	float mRightSpeed;
-	float mDownSpeed;
+	float mLaserCooldown;
 };