Bläddra i källkod

Chapter 8 done

Sanjay Madhav 8 år sedan
förälder
incheckning
61782b541a
5 ändrade filer med 203 tillägg och 21 borttagningar
  1. 4 4
      Chapter08/InputComponent.cpp
  2. 136 2
      Chapter08/InputSystem.cpp
  3. 38 2
      Chapter08/InputSystem.h
  4. 22 13
      Chapter08/Ship.cpp
  5. 3 0
      Chapter08/Ship.h

+ 4 - 4
Chapter08/InputComponent.cpp

@@ -24,11 +24,11 @@ void InputComponent::ProcessInput(const InputState& state)
 {
 	// Calculate forward speed for MoveComponent
 	float forwardSpeed = 0.0f;
-	if (state.Keyboard.GetKeyValue(mForwardKey))
+	if (state.Keyboard.GetKeyValue(SDL_Scancode(mForwardKey)))
 	{
 		forwardSpeed += mMaxForwardSpeed;
 	}
-	if (state.Keyboard.GetKeyValue(mBackKey))
+	if (state.Keyboard.GetKeyValue(SDL_Scancode(mBackKey)))
 	{
 		forwardSpeed -= mMaxForwardSpeed;
 	}
@@ -36,11 +36,11 @@ void InputComponent::ProcessInput(const InputState& state)
 
 	// Calculate angular speed for MoveComponent
 	float angularSpeed = 0.0f;
-	if (state.Keyboard.GetKeyValue(mClockwiseKey))
+	if (state.Keyboard.GetKeyValue(SDL_Scancode(mClockwiseKey)))
 	{
 		angularSpeed += mMaxAngularSpeed;
 	}
-	if (state.Keyboard.GetKeyValue(mCounterClockwiseKey))
+	if (state.Keyboard.GetKeyValue(SDL_Scancode(mCounterClockwiseKey)))
 	{
 		angularSpeed -= mMaxAngularSpeed;
 	}

+ 136 - 2
Chapter08/InputSystem.cpp

@@ -10,12 +10,12 @@
 #include <SDL/SDL.h>
 #include <cstring>
 
-bool KeyboardState::GetKeyValue(int keyCode) const
+bool KeyboardState::GetKeyValue(SDL_Scancode keyCode) const
 {
 	return mCurrState[keyCode] == 1;
 }
 
-ButtonState KeyboardState::GetKeyState(int keyCode) const
+ButtonState KeyboardState::GetKeyState(SDL_Scancode keyCode) const
 {
 	if (mPrevState[keyCode] == 0)
 	{
@@ -73,6 +73,37 @@ ButtonState MouseState::GetButtonState(int button) const
 	}
 }
 
+bool ControllerState::GetButtonValue(SDL_GameControllerButton button) const
+{
+	return mCurrButtons[button] == 1;
+}
+
+ButtonState ControllerState::GetButtonState(SDL_GameControllerButton button) const
+{
+	if (mPrevButtons[button] == 0)
+	{
+		if (mCurrButtons[button] == 0)
+		{
+			return ENone;
+		}
+		else
+		{
+			return EPressed;
+		}
+	}
+	else // Prev state must be 1
+	{
+		if (mCurrButtons[button] == 0)
+		{
+			return EReleased;
+		}
+		else
+		{
+			return EHeld;
+		}
+	}
+}
+
 bool InputSystem::Initialize()
 {
 	// Keyboard
@@ -85,6 +116,16 @@ bool InputSystem::Initialize()
 	// Mouse (just set everything to 0)
 	mState.Mouse.mCurrButtons = 0;
 	mState.Mouse.mPrevButtons = 0;
+
+	// Get the connected controller, if it exists
+	mController = SDL_GameControllerOpen(0);
+	// Initialize controller state
+	mState.Controller.mIsConnected = (mController != nullptr);
+	memset(mState.Controller.mCurrButtons, 0,
+		SDL_CONTROLLER_BUTTON_MAX);
+	memset(mState.Controller.mPrevButtons, 0,
+		SDL_CONTROLLER_BUTTON_MAX);
+
 	return true;
 }
 
@@ -104,6 +145,11 @@ void InputSystem::PrepareForUpdate()
 	mState.Mouse.mPrevButtons = mState.Mouse.mCurrButtons;
 	mState.Mouse.mIsRelative = false;
 	mState.Mouse.mScrollWheel = Vector2::Zero;
+
+	// Controller
+	memcpy(mState.Controller.mPrevButtons,
+		mState.Controller.mCurrButtons,
+		SDL_CONTROLLER_BUTTON_MAX);
 }
 
 void InputSystem::Update()
@@ -123,6 +169,36 @@ void InputSystem::Update()
 
 	mState.Mouse.mMousePos.x = static_cast<float>(x);
 	mState.Mouse.mMousePos.y = static_cast<float>(y);
+
+	// Controller
+	// Buttons
+	for (int i = 0; i < SDL_CONTROLLER_BUTTON_MAX; i++)
+	{
+		mState.Controller.mCurrButtons[i] =
+			SDL_GameControllerGetButton(mController, 
+				SDL_GameControllerButton(i));
+	}
+
+	// Triggers
+	mState.Controller.mLeftTrigger =
+		Filter1D(SDL_GameControllerGetAxis(mController,
+			SDL_CONTROLLER_AXIS_TRIGGERLEFT));
+	mState.Controller.mRightTrigger =
+		Filter1D(SDL_GameControllerGetAxis(mController,
+			SDL_CONTROLLER_AXIS_TRIGGERRIGHT));
+
+	// Sticks
+	x = SDL_GameControllerGetAxis(mController,
+		SDL_CONTROLLER_AXIS_LEFTX);
+	y = -SDL_GameControllerGetAxis(mController,
+		SDL_CONTROLLER_AXIS_LEFTY);
+	mState.Controller.mLeftStick = Filter2D(x, y);
+
+	x = SDL_GameControllerGetAxis(mController,
+		SDL_CONTROLLER_AXIS_RIGHTX);
+	y = -SDL_GameControllerGetAxis(mController,
+		SDL_CONTROLLER_AXIS_RIGHTY);
+	mState.Controller.mRightStick = Filter2D(x, y);
 }
 
 void InputSystem::ProcessEvent(SDL_Event& event)
@@ -146,3 +222,61 @@ void InputSystem::SetRelativeMouseMode(bool value)
 
 	mState.Mouse.mIsRelative = value;
 }
+
+float InputSystem::Filter1D(int input)
+{
+	// A value < dead zone is interpreted as 0%
+	const int deadZone = 250;
+	// A value > max value is interpreted as 100%
+	const int maxValue = 30000;
+
+	float retVal = 0.0f;
+
+	// Take absolute value of input
+	int absValue = input > 0 ? input : -input;
+	// Ignore input within dead zone
+	if (absValue > deadZone)
+	{
+		// Compute fractional value between dead zone and max value
+		retVal = static_cast<float>(absValue - deadZone) /
+		(maxValue - deadZone);
+		// Make sure sign matches original value
+		retVal = input > 0 ? retVal : -1.0f * retVal;
+		// Clamp between -1.0f and 1.0f
+		retVal = Math::Clamp(retVal, -1.0f, 1.0f);
+	}
+
+	return retVal;
+}
+
+Vector2 InputSystem::Filter2D(int inputX, int inputY)
+{
+	const float deadZone = 8000.0f;
+	const float maxValue = 30000.0f;
+
+	// Make into 2D vector
+	Vector2 dir;
+	dir.x = static_cast<float>(inputX);
+	dir.y = static_cast<float>(inputY);
+
+	float length = dir.Length();
+
+	// If length < deadZone, should be no input
+	if (length < deadZone)
+	{
+		dir = Vector2::Zero;
+	}
+	else
+	{
+		// Calculate fractional value between
+		// dead zone and max value circles
+		float f = (length - deadZone) / (maxValue - deadZone);
+		// Clamp f between 0.0f and 1.0f
+		f = Math::Clamp(f, 0.0f, 1.0f);
+		// Normalize the vector, and then scale it to the
+		// fractional value
+		dir *= f / length;
+	}
+
+	return dir;
+}

+ 38 - 2
Chapter08/InputSystem.h

@@ -8,6 +8,8 @@
 
 #pragma once
 #include <SDL/SDL_scancode.h>
+#include <SDL/SDL_gamecontroller.h>
+#include <SDL/SDL_mouse.h>
 #include "Math.h"
 
 // The different button states
@@ -26,9 +28,9 @@ public:
 	// Friend so InputSystem can easily update it
 	friend class InputSystem;
 	// Get just the boolean true/false value of key
-	bool GetKeyValue(int keyCode) const;
+	bool GetKeyValue(SDL_Scancode keyCode) const;
 	// Get a state based on current and previous frame
-	ButtonState GetKeyState(int keyCode) const;
+	ButtonState GetKeyState(SDL_Scancode keyCode) const;
 private:
 	const Uint8* mCurrState;
 	Uint8 mPrevState[SDL_NUM_SCANCODES];
@@ -60,11 +62,42 @@ private:
 	bool mIsRelative;
 };
 
+// Helper for controller input
+class ControllerState
+{
+public:
+	friend class InputSystem;
+
+	// For buttons
+	bool GetButtonValue(SDL_GameControllerButton button) const;
+	ButtonState GetButtonState(SDL_GameControllerButton button) const;
+
+	const Vector2& GetLeftStick() const { return mLeftStick; }
+	const Vector2& GetRightStick() const { return mRightStick; }
+	float GetLeftTrigger() const { return mLeftTrigger; }
+	float GetRightTrigger() const { return mRightTrigger; }
+
+	bool GetIsConnected() const { return mIsConnected; }
+private:
+	// Current/previous buttons
+	Uint8 mCurrButtons[SDL_CONTROLLER_BUTTON_MAX];
+	Uint8 mPrevButtons[SDL_CONTROLLER_BUTTON_MAX];
+	// Left/right sticks
+	Vector2 mLeftStick;
+	Vector2 mRightStick;
+	// Left/right trigger
+	float mLeftTrigger;
+	float mRightTrigger;
+	// Is this controller connected?
+	bool mIsConnected;
+};
+
 // Wrapper that contains current state of input
 struct InputState
 {
 	KeyboardState Keyboard;
 	MouseState Mouse;
+	ControllerState Controller;
 };
 
 class InputSystem
@@ -84,5 +117,8 @@ public:
 
 	void SetRelativeMouseMode(bool value);
 private:
+	float Filter1D(int input);
+	Vector2 Filter2D(int inputX, int inputY);
 	InputState mState;
+	SDL_GameController* mController;
 };

+ 22 - 13
Chapter08/Ship.cpp

@@ -8,37 +8,37 @@
 
 #include "Ship.h"
 #include "SpriteComponent.h"
-#include "InputComponent.h"
 #include "Game.h"
 #include "Laser.h"
 #include "InputSystem.h"
 
 Ship::Ship(Game* game)
 	:Actor(game)
+	,mSpeed(400.0f)
 	,mLaserCooldown(0.0f)
 {
 	// Create a sprite component
 	SpriteComponent* sc = new SpriteComponent(this, 150);
 	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)
 {
 	mLaserCooldown -= deltaTime;
+
+	// Update position based on velocity
+	Vector2 pos = GetPosition();
+	pos += mVelocityDir * mSpeed * deltaTime;
+	SetPosition(pos);
+
+	// Update rotation
+	float angle = Math::Atan2(mRotationDir.y, mRotationDir.x);
+	SetRotation(angle);
 }
 
 void Ship::ActorInput(const InputState& state)
 {
-	if (state.Keyboard.GetKeyValue(SDL_SCANCODE_SPACE)
+	if (state.Controller.GetRightTrigger() > 0.25f
 		&& mLaserCooldown <= 0.0f)
 	{
 		// Create a laser and set its position/rotation to mine
@@ -46,7 +46,16 @@ void Ship::ActorInput(const InputState& state)
 		laser->SetPosition(GetPosition());
 		laser->SetRotation(GetRotation());
 
-		// Reset laser cooldown (half second)
-		mLaserCooldown = 0.5f;
+		// Reset laser cooldown (quarter second)
+		mLaserCooldown = 0.25f;
+	}
+
+	if (state.Controller.GetIsConnected())
+	{
+		mVelocityDir = state.Controller.GetLeftStick();
+		if (!Math::NearZero(state.Controller.GetRightStick().Length()))
+		{
+			mRotationDir = state.Controller.GetRightStick();
+		}
 	}
 }

+ 3 - 0
Chapter08/Ship.h

@@ -16,5 +16,8 @@ public:
 	void UpdateActor(float deltaTime) override;
 	void ActorInput(const struct InputState& state) override;
 private:
+	Vector2 mVelocityDir;
+	Vector2 mRotationDir;
+	float mSpeed;
 	float mLaserCooldown;
 };