Commit 0d26b0b8 authored by 魔大农's avatar 魔大农 🍀

Implemented piece putting (random square for now)

parent 115bf766
......@@ -23,7 +23,8 @@ SOURCES += \
quattercam.cpp \
board.cpp \
piece.cpp \
master.cpp
master.cpp \
squarepicker.cpp
HEADERS += \
luckey.h \
......@@ -32,4 +33,5 @@ HEADERS += \
quattercam.h \
board.h \
piece.h \
master.h
master.h \
squarepicker.h
# [:four_leaf_clover:] (http://www.luckeyproductions.nl/) Quatter
A digital version of [the Quarto boardgame](https://en.wikipedia.org/wiki/Quarto_%28board_game%29) by Blaise Müller, made using the Urho3D game engine.
![Screenshot](https://raw.githubusercontent.com/Modanung/Quatter/master/Screenshots/Screenshot_Wed_May_25_04_42_57_2016.png)
\ No newline at end of file
![Screenshot](https://raw.githubusercontent.com/Modanung/Quatter/master/Screenshot_Wed_May_25_10_10_24_2016.png)
\ No newline at end of file
This diff is collapsed.
......@@ -9,7 +9,7 @@
<parameter name="VOffset" value="0 1 0 0" />
<parameter name="MatDiffColor" value="1 1 1 1" />
<parameter name="MatEmissiveColor" value="0 0 0" />
<parameter name="MatEnvMapColor" value="0.05 0.05 0.05" />
<parameter name="MatEnvMapColor" value="0.023 0.023 0.023" />
<parameter name="MatSpecColor" value=".34 .34 .34 5" />
<cull value="ccw" />
<shadowcull value="ccw" />
......
<material>
<technique name="Techniques/NoTextureAddAlpha.xml" />
<parameter name="MatDiffColor" value="0.125 1 0.666 0.7" />
<parameter name="MatDiffColor" value="0.125 1 0.666 0.5" />
<parameter name="MatSpecColor" value="1 1 1 16" />
</material>
\ No newline at end of file
......@@ -4,6 +4,7 @@
<texture unit="diffuse" name="Textures/StoneDiffuse.dds" />
<texture unit="normal" name="Textures/StoneNormal.dds" />
<texture unit="environment" name="Textures/LeafyKnoll.xml" />
<parameter name="MatEnvMapColor" value="0.08 0.08 0.08" />
<parameter name="MatSpecColor" value="0.3 0.3 0.3 16" />
<parameter name="MatDiffColor" value="1.0 0.0 0.0 1" />
<parameter name="MatEnvMapColor" value="0.08 0.1 0.08" />
<parameter name="MatSpecColor" value="0.08 0.08 0.13 10" />
</material>
\ No newline at end of file
This diff is collapsed.
......@@ -10,33 +10,35 @@ template <> unsigned MakeHash(const IntVector2& value)
Board::Board(): Object(MC->GetContext()),
squares_{}
{
Node* rootNode = MC->world.scene->CreateChild("Board");
model_ = rootNode->CreateComponent<StaticModel>();
rootNode_ = MC->world.scene->CreateChild("Board");
model_ = rootNode_->CreateComponent<StaticModel>();
model_->SetModel(MC->cache_->GetResource<Model>("Resources/Models/Board.mdl"));
model_->SetMaterial(MC->cache_->GetResource<Material>("Resources/Materials/Board.xml"));
model_->SetCastShadows(true);
for (int i{0}; i < BOARD_HEIGHT; ++i)
for (int j{0}; j < BOARD_WIDTH; ++j){
Square square{};
square.coords_ = IntVector2(i, j);
square.node_ = rootNode->CreateChild("Square");
square.node_->SetPosition(SquarePosition(square.coords_));
Square* square{new Square};
square->coords_ = IntVector2(i, j);
square->node_ = rootNode_->CreateChild("Square");
square->node_->SetPosition(SquarePosition(square->coords_));
square->free_ = true;
square->selected_ = false;
Node* lightNode{square.node_->CreateChild("Light")};
Node* lightNode{square->node_->CreateChild("Light")};
lightNode->SetPosition(Vector3::UP * 0.23f);
square.light_ = square.node_->CreateComponent<Light>();
square.light_->SetColor(Color(0.0f, 0.8f, 0.5f));
square.light_->SetBrightness(0.5f);
square.light_->SetRange(5.0f);
square.light_->SetEnabled(false);
square->light_ = square->node_->CreateComponent<Light>();
square->light_->SetColor(Color(0.0f, 0.8f, 0.5f));
square->light_->SetBrightness(0.5f);
square->light_->SetRange(5.0f);
square->light_->SetEnabled(false);
StaticModel* slotModel{square.node_->CreateComponent<StaticModel>()};
StaticModel* slotModel{square->node_->CreateComponent<StaticModel>()};
// slotModel->SetModel(MC->GetModel("Slot")->Clone());
// slotModel->SetMaterial(MC->GetMaterial("Slot.xml"));
slotModel->SetCastShadows(true);
squares_[square.coords_] = square;
squares_[square->coords_] = square;
}
}
......@@ -55,8 +57,8 @@ bool Board::CheckQuatter()
Piece::Attributes first{};
for (int j{0}; j < BOARD_WIDTH; ++j){
IntVector2 coords(i, j);
if (squares_[coords].piece_){
auto attributes(squares_[coords].piece_->GetAttributes());
if (squares_[coords]->piece_){
auto attributes(squares_[coords]->piece_->GetAttributes());
if (j == 0) {
first = attributes;
} else {
......@@ -82,8 +84,8 @@ bool Board::CheckQuatter()
Piece::Attributes first{};
for (int i{0}; i < BOARD_HEIGHT; ++i){
IntVector2 coords(i, j);
if (squares_[coords].piece_){
auto attributes(squares_[coords].piece_->GetAttributes());
if (squares_[coords]->piece_){
auto attributes(squares_[coords]->piece_->GetAttributes());
if (j == 0) {
first = attributes;
} else {
......@@ -108,8 +110,8 @@ bool Board::CheckQuatter()
Piece::Attributes first{};
for (int i{0}; i < BOARD_WIDTH; ++i){
IntVector2 coords(i, direction ? i : (BOARD_WIDTH - i - 1));
if (squares_[coords].piece_){
auto attributes(squares_[coords].piece_->GetAttributes());
if (squares_[coords]->piece_){
auto attributes(squares_[coords]->piece_->GetAttributes());
if (i == 0) {
first = attributes;
} else {
......@@ -135,8 +137,8 @@ bool Board::CheckQuatter()
Piece::Attributes first{};
for (int m : {0, 1}) for (int n : {0, 1}){
IntVector2 coords(k + m, l + n);
if (squares_[coords].piece_){
auto attributes(squares_[coords].piece_->GetAttributes());
if (squares_[coords]->piece_){
auto attributes(squares_[coords]->piece_->GetAttributes());
if (m == 0 && n == 0) {
first = attributes;
} else {
......@@ -159,3 +161,17 @@ bool Board::CheckQuatter()
//No Quatter
return false;
}
void Board::PutPiece(Piece* piece, IntVector2 coords)
{
Square* square{squares_[coords]};
square->piece_ = piece;
piece->Put(square->node_->GetWorldPosition() + GetThickness() * Vector3::UP);
}
Square* Board::GetSelectedSquare()
{
for (Square* s : squares_.Values()){
if (s->selected_)
return s;
}
}
......@@ -14,11 +14,16 @@ using namespace Urho3D;
#define BOARD_WIDTH 4
#define BOARD_HEIGHT 4
typedef struct Square{
typedef class Square : public Object{
URHO3D_OBJECT(Square, Object);
public:
Square() : Object(MC->GetContext()) {}
IntVector2 coords_;
SharedPtr<Node> node_;
SharedPtr<Light> light_;
Piece* piece_;
bool free_;
bool selected_;
}Square;
class Board : public Object
......@@ -28,11 +33,17 @@ public:
Board();
float GetThickness() const { return model_->GetBoundingBox().Size().y_; }
bool CheckQuatter();
void PutPiece(Piece* piece, IntVector2 coords);
void PutPiece(Piece* piece) { PutPiece(piece, IntVector2{Random(BOARD_HEIGHT), Random(BOARD_HEIGHT)}); }//GetSelectedSquare().coords_); }
Node* GetRootNode() const { return rootNode_; }
private:
SharedPtr<Node> rootNode_;
StaticModel* model_;
HashMap<IntVector2, Square> squares_;
HashMap<IntVector2, SharedPtr<Square>> squares_;
Vector3 SquarePosition(IntVector2 coords);
Square* GetSelectedSquare();
};
#endif // BOARD_H
#include "inputmaster.h"
#include "quattercam.h"
#include "board.h"
#include "piece.h"
InputMaster::InputMaster() : Master(),
......@@ -23,20 +24,16 @@ void InputMaster::HandleKeyDown(StringHash eventType, VariantMap &eventData)
float volumeStep{0.1f};
switch (key){
//Exit when ESC is pressed
case KEY_SPACE:{
HandleActionButtonPressed();
} break;
//Exit when ESC is pressed
case KEY_ESC:{
MC->Exit();
} break;
//Take screenshot when 9 is pressed
case KEY_9:{
Graphics* graphics = GetSubsystem<Graphics>();
Image screenshot(context_);
graphics->TakeScreenShot(screenshot);
//Here we save in the Screenshots folder with date and time appended
String fileName = GetSubsystem<FileSystem>()->GetProgramDir() + "Screenshots/Screenshot_" +
Time::GetTimeStamp().Replaced(':', '_').Replaced('.', '_').Replaced(' ', '_')+".png";
Log::Write(1, fileName);
screenshot.SavePNG(fileName);
Screenshot();
} break;
case KEY_M: {
MC->ToggleMusic();
......@@ -53,14 +50,14 @@ void InputMaster::HandleKeyDown(StringHash eventType, VariantMap &eventData)
void InputMaster::HandleKeyUp(StringHash eventType, VariantMap &eventData)
{
using namespace KeyUp;
int key = eventData[P_KEY].GetInt();
int key{eventData[P_KEY].GetInt()};
if (pressedKeys_.Contains(key)) pressedKeys_.Erase(key);
}
void InputMaster::HandleMouseButtonDown(StringHash eventType, VariantMap &eventData)
{
using namespace MouseButtonDown;
int button = eventData[P_BUTTON].GetInt();
int button{eventData[P_BUTTON].GetInt()};
pressedMouseButtons_.Insert(button);
}
......@@ -68,24 +65,48 @@ void InputMaster::HandleMouseButtonDown(StringHash eventType, VariantMap &eventD
void InputMaster::HandleMouseButtonUp(StringHash eventType, VariantMap &eventData)
{
using namespace MouseButtonUp;
int button = eventData[P_BUTTON].GetInt();
int button{eventData[P_BUTTON].GetInt()};
if (pressedMouseButtons_.Contains(button)) pressedMouseButtons_.Erase(button);
}
void InputMaster::HandleJoystickButtonDown(StringHash eventType, VariantMap &eventData)
{
using namespace JoystickButtonDown;
int joystickId = eventData[P_JOYSTICKID].GetInt();
int button = eventData[P_BUTTON].GetInt();
pressedJoystickButtons_.Insert(button);
int joystickId{eventData[P_JOYSTICKID].GetInt()};
int button{eventData[P_BUTTON].GetInt()};
switch (button){
case 14: HandleActionButtonPressed();
break;
default: break;
}
pressedJoystickButtons_[joystickId].Insert(button);
}
void InputMaster::HandleJoystickButtonUp(StringHash eventType, VariantMap &eventData)
{
using namespace JoystickButtonUp;
int joystickId = eventData[P_JOYSTICKID].GetInt();
int button = eventData[P_BUTTON].GetInt();
if (pressedJoystickButtons_.Contains(button)) pressedJoystickButtons_.Erase(button);
int joystickId{eventData[P_JOYSTICKID].GetInt()};
int button{eventData[P_BUTTON].GetInt()};
if (pressedJoystickButtons_[joystickId].Contains(button)) pressedJoystickButtons_.Erase(button);
}
void InputMaster::HandleActionButtonPressed()
{
if (MC->GetGamePhase() == GamePhase::PLAYER1PICKS ||
MC->GetGamePhase() == GamePhase::PLAYER2PICKS )
{
Piece* selectedPiece{MC->GetSelectedPiece()};
if (selectedPiece){
selectedPiece->Pick();
MC->NextPhase();
}
} else if (MC->GetGamePhase() == GamePhase::PLAYER1PUTS ||
MC->GetGamePhase() == GamePhase::PLAYER2PUTS )
{
MC->world.board_->PutPiece(MC->GetPickedPiece());
MC->NextPhase();
}
}
void InputMaster::HandleUpdate(StringHash eventType, VariantMap &eventData)
......@@ -93,12 +114,20 @@ void InputMaster::HandleUpdate(StringHash eventType, VariantMap &eventData)
float t{eventData[Update::P_TIMESTEP].GetFloat()};
idleTime_ += t;
HandleCameraMovement(t);
}
void InputMaster::HandleCameraMovement(float t)
{
Vector2 camRot{};
float camZoom{};
float keyRotMultiplier{0.5f};
float keyZoomSpeed{0.1f};
float joyRotMultiplier{80.0f};
float joyZoomSpeed{3.4f};
if (pressedKeys_.Size()) idleTime_ = 0.0f;
for (int key : pressedKeys_){
switch (key){
......@@ -118,20 +147,21 @@ void InputMaster::HandleUpdate(StringHash eventType, VariantMap &eventData)
}
}
if (input_->GetMouseButtonDown(MOUSEB_RIGHT)){
if (pressedMouseButtons_.Contains(MOUSEB_RIGHT)){
idleTime_ = 0.0f;
IntVector2 mouseMove = input_->GetMouseMove();
camRot += Vector2(mouseMove.x_, mouseMove.y_) * 0.1f;
}
//Should check whose turn it is
JoystickState* joy0 = input_->GetJoystickByIndex(0);
///Should check whose turn it is when two joysticks are connected
JoystickState* joy0{input_->GetJoystickByIndex(0)};
if (joy0){
Vector2 rotation{-Vector2(joy0->GetAxisPosition(2), joy0->GetAxisPosition(3))};
Vector2 rotation{-Vector2(joy0->GetAxisPosition(0), joy0->GetAxisPosition(1))
-Vector2(joy0->GetAxisPosition(2), joy0->GetAxisPosition(3))};
if (rotation.Length()){
idleTime_ = 0.0f;
camRot += rotation * t * 42.0f;
camRot += rotation * t * joyRotMultiplier;
}
camZoom += t * (joy0->GetAxisPosition(12) - joy0->GetAxisPosition(13));
camZoom += t * joyZoomSpeed * (joy0->GetAxisPosition(12) - joy0->GetAxisPosition(13));
}
float idleThreshold{5.0f};
......@@ -148,10 +178,58 @@ void InputMaster::HandleUpdate(StringHash eventType, VariantMap &eventData)
} else {
if (idle_) idle_ = false;
}
//Speed up camera movement when shift key is held down
if (pressedKeys_.Contains(KEY_SHIFT)){
camRot *= 3.0f;
camZoom *= 2.0f;
}
smoothCamRotate_ = 0.1f * (camRot + smoothCamRotate_ * 9.0f);
smoothCamZoom_ = 0.1f * (camZoom + smoothCamZoom_ * 9.0f);
//Slow down up and down rotation when nearing extremes
SmoothCameraMovement(camZoom, camRot);
CAMERA->Rotate(smoothCamRotate_);
CAMERA->Zoom(smoothCamZoom_);
}
void InputMaster::SmoothCameraMovement(float camZoom, Vector2 camRot)
{
float pitchBrake{1.0f};
if (Sign(camRot.y_) > 0.0f){
float pitchLeft{LucKey::Delta(CAMERA->GetPitch(), PITCH_MAX)};
if (pitchLeft < PITCH_EDGE)
pitchBrake = pitchLeft / PITCH_EDGE;
} else {
float pitchLeft{LucKey::Delta(CAMERA->GetPitch(), PITCH_MIN)};
if (pitchLeft < PITCH_EDGE)
pitchBrake = pitchLeft / PITCH_EDGE;
}
camRot.y_ *= pitchBrake;
smoothCamRotate_.y_ *= pitchBrake;
//Slow down zooming when nearing extremes
float zoomBrake{1.0f};
if (Sign(camZoom) < 0.0f){
float zoomLeft{LucKey::Delta(CAMERA->GetDistance(), ZOOM_MAX)};
if (zoomLeft < ZOOM_EDGE)
zoomBrake = zoomLeft / ZOOM_EDGE;
} else {
float zoomLeft{LucKey::Delta(CAMERA->GetDistance(), ZOOM_MIN)};
if (zoomLeft < ZOOM_EDGE)
zoomBrake = zoomLeft / ZOOM_EDGE;
}
camZoom *= zoomBrake;
smoothCamZoom_ *= zoomBrake;
smoothCamRotate_ = 0.0666f * (camRot + smoothCamRotate_ * 14.0f);
smoothCamZoom_ = 0.05f * (camZoom + smoothCamZoom_ * 19.0f);
}
void InputMaster::Screenshot()
{
Graphics* graphics{GetSubsystem<Graphics>()};
Image screenshot{context_};
graphics->TakeScreenShot(screenshot);
//Here we save in the Screenshots folder with date and time appended
String fileName{GetSubsystem<FileSystem>()->GetProgramDir() + "Screenshots/Screenshot_" +
Time::GetTimeStamp().Replaced(':', '_').Replaced('.', '_').Replaced(' ', '_')+".png"};
Log::Write(1, fileName);
screenshot.SavePNG(fileName);
}
......@@ -5,8 +5,6 @@
enum class JoystickButton {SELECT, LEFTSTICK, RIGHTSTICK, START, DPAD_UP, DPAD_RIGHT, DPAD_DOWN, DPAD_LEFT, L2, R2, L1, R1, TRIANGLE, CIRCLE, CROSS, SQUARE};
#define CAMERA MC->world.camera
class InputMaster : public Master
{
URHO3D_OBJECT(InputMaster, Master);
......@@ -15,6 +13,9 @@ public:
WeakPtr<Node> firstHit_;
bool IsIdle() const noexcept { return idle_; }
void HandleActionButtonPressed();
private:
Input* input_;
......@@ -25,7 +26,7 @@ private:
HashSet<int> pressedKeys_;
HashSet<int> pressedMouseButtons_;
HashSet<int> pressedJoystickButtons_;
HashMap< int, HashSet<int> > pressedJoystickButtons_;
void HandleKeyDown(StringHash eventType, VariantMap &eventData);
void HandleKeyUp(StringHash eventType, VariantMap &eventData);
......@@ -34,6 +35,10 @@ private:
void HandleJoystickButtonDown(StringHash eventType, VariantMap &eventData);
void HandleJoystickButtonUp(StringHash eventType, VariantMap &eventData);
void HandleUpdate(StringHash eventType, VariantMap &eventData);
void SmoothCameraMovement(float camZoom, Vector2 camRot);
void HandleCameraMovement(float t);
void Screenshot();
};
#endif // INPUTMASTER_H
......@@ -22,6 +22,8 @@ MasterControl::MasterControl(Context *context):
void MasterControl::Setup()
{
SetRandomSeed(GetSubsystem<Time>()->GetSystemTime());
engineParameters_["WindowTitle"] = "Quatter";
engineParameters_["LogName"] = GetSubsystem<FileSystem>()->GetAppPreferencesDir("urho3d", "logs")+"Quatter.log";
engineParameters_["ResourcePaths"] = "Data;CoreData;Resources";
......@@ -68,8 +70,8 @@ void MasterControl::CreateScene()
CreateLights();
//Create skybox
Node* skyNode = world.scene->CreateChild("Sky");
Skybox* skybox = skyNode->CreateComponent<Skybox>();
Node* skyNode{world.scene->CreateChild("Sky")};
Skybox* skybox{skyNode->CreateComponent<Skybox>()};
skybox->SetModel(GetModel("Box"));
skybox->SetMaterial(GetMaterial("LeafyKnoll"));
......@@ -90,7 +92,7 @@ void MasterControl::CreateScene()
for (int p{0}; p < NUM_PIECES; ++p){
Piece* newPiece = new Piece(Piece::Attributes(p));
world.pieces_.Push(SharedPtr<Piece>(newPiece));
newPiece->SetPosition(AttributesToPosition(p));
newPiece->SetPosition(AttributesToPosition(p) + Vector3(Random(0.23f), 0.0f, Random(0.23f)));
}
}
......@@ -98,12 +100,12 @@ void MasterControl::CreateScene()
void MasterControl::CreateLights()
{
//Add a directional light to the world. Enable cascaded shadows on it
Node* downardsLightNode = world.scene->CreateChild("DirectionalLight");
downardsLightNode->SetPosition(Vector3(-5.0f, 23.0f, -2.0f));
Node* downardsLightNode{world.scene->CreateChild("DirectionalLight")};
downardsLightNode->SetPosition(Vector3(2.0f, 23.0f, -3.0f));
downardsLightNode->LookAt(Vector3(0.0f, 0.0f, 0.0f));
Light* downwardsLight = downardsLightNode->CreateComponent<Light>();
Light* downwardsLight{downardsLightNode->CreateComponent<Light>()};
downwardsLight->SetLightType(LIGHT_DIRECTIONAL);
downwardsLight->SetBrightness(0.88f);
downwardsLight->SetBrightness(0.8f);
downwardsLight->SetColor(Color(0.8f, 0.9f, 0.95f));
downwardsLight->SetCastShadows(true);
downwardsLight->SetShadowIntensity(0.23f);
......@@ -111,15 +113,45 @@ void MasterControl::CreateLights()
downwardsLight->SetShadowCascade(CascadeParameters(1.0f, 5.0f, 23.0f, 100.0f, 0.8f));
//Create a point light.
Node* pointLightNode_ = world.scene->CreateChild("PointLight");
pointLightNode_->SetPosition(Vector3(0.0f, -1.0f, -13.0f));
Light* pointLight = pointLightNode_->CreateComponent<Light>();
Node* pointLightNode_{world.scene->CreateChild("PointLight")};
pointLightNode_->SetPosition(Vector3(-10.0f, -1.0f, 23.0f));
Light* pointLight{pointLightNode_->CreateComponent<Light>()};
pointLight->SetLightType(LIGHT_POINT);
pointLight->SetBrightness(0.23f);
pointLight->SetBrightness(0.42f);
pointLight->SetRange(42.0f);
pointLight->SetColor(Color(0.75f, 1.0f, 0.75f));
}
Piece* MasterControl::GetSelectedPiece() const
{
for (Piece* p: world.pieces_){
if (p->GetState() == PieceState::SELECTED){
return p;
}
}
return nullptr;
}
Piece* MasterControl::GetPickedPiece() const
{
for (Piece* p: world.pieces_){
if (p->GetState() == PieceState::PICKED){
return p;
}
}
return nullptr;
}
int MasterControl::CountFreePieces()
{
int count{0};
for (Piece* p: world.pieces_){
if (p->GetState() == PieceState::FREE){
++count;
}
}
return count;
}
void MasterControl::HandleUpdate(StringHash eventType, VariantMap& eventData)
{
// float t{eventData[Update::P_TIMESTEP].GetFloat()};
......@@ -127,7 +159,7 @@ void MasterControl::HandleUpdate(StringHash eventType, VariantMap& eventData)
for (Piece* p: world.pieces_){
if (LucKey::Delta(CAMERA->GetYaw(), p->GetAngle(), true) < 180.0f / NUM_PIECES){
p->Select();
} else {
} else if (p->GetState() != PieceState::PICKED){
p->Deselect();
}
}
......
......@@ -18,7 +18,7 @@ class InputMaster;
class Board;
class Piece;
enum class GamePhase{PLAYER1PICKS, PLAYER2PUTS, PLAYER2PICKS, PLAYER1PUTS};
enum class GamePhase{PLAYER1PICKS, PLAYER2PUTS, PLAYER2PICKS, PLAYER1PUTS, QUATTER};
typedef struct GameWorld
{
......@@ -33,8 +33,9 @@ typedef struct GameWorld
} cursor;
} GameWorld;
#define NUM_PIECES 16
#define MC MasterControl::GetInstance()
#define CAMERA MC->world.camera
#define NUM_PIECES 16
class MasterControl : public Application
{
......@@ -59,11 +60,14 @@ public:
void CreateLights();
inline GamePhase GetGamePhase() const noexcept { return gamePhase_; }
float AttributesToAngle(int attributes) const { return 360.0f/NUM_PIECES * attributes; }
float AttributesToAngle(int attributes) const { return (360.0f/NUM_PIECES * attributes) + 180.0f/NUM_PIECES + 23.5f; }
Vector3 AttributesToPosition(int attributes) const {
return Quaternion(AttributesToAngle(attributes), Vector3::UP) * Vector3::FORWARD * 7.0f
+ Vector3::DOWN * 0.23f;
+ Vector3::DOWN * 0.21f;
}
Piece* GetSelectedPiece() const;
Piece* GetPickedPiece() const;
int CountFreePieces();
Material* GetMaterial(String name) const { return cache_->GetResource<Material>("Materials/"+name+".xml"); }
Model* GetModel(String name) const { return cache_->GetResource<Model>("Models/"+name+".mdl"); }
......
#include "quattercam.h"
#include "board.h"
#include "piece.h"
Piece::Piece(Attributes attributes): Object(MC->GetContext()),
state_{PieceState::FREE},
attributes_{attributes}
state_{PieceState::FREE },
attributes_{attributes},
sinceStateChange_{0.0f}
{
rootNode_ = MC->world.scene->CreateChild("Piece"+GetCodon(4));
rootNode_->SetRotation(Quaternion(Random(360.0f), Vector3::UP));
StaticModel* pieceModel{rootNode_->CreateComponent<StaticModel>()};
pieceModel->SetCastShadows(true);
pieceModel->SetModel(MC->GetModel("Piece_"+GetCodon(3)));
if (attributes[3]){
pieceModel->SetMaterial(MC->cache_->GetResource<Material>("Resources/Materials/Wood_light.xml"));
pieceModel->SetMaterial(MC->GetMaterial("Wood_light"));
}
else pieceModel->SetMaterial(MC->cache_->GetResource<Material>("Resources/Materials/Wood_dark.xml"));
else pieceModel->SetMaterial(MC->GetMaterial("Wood_dark"));
outlineModel_ = rootNode_->CreateComponent<StaticModel>();
outlineModel_->SetCastShadows(false);
outlineModel_->SetModel(MC->GetModel("Piece_"+GetCodon(2)+"_outline"));
outlineModel_->SetMaterial(MC->cache_->GetResource<Material>("Resources/Materials/Glow.xml"));
Select();
outlineModel_->SetMaterial(MC->GetMaterial("Glow")->Clone());
outlineModel_->GetMaterial()->SetShaderParameter("MatDiffColor", Color(0.0f, 0.0f, 0.0f));
outlineModel_->SetEnabled(false);
}
String Piece::GetCodon(int length) const
{
if (length > attributes_.size() || length < 1)
if (length > static_cast<int>(attributes_.size()) || length < 1)
length = static_cast<int>(attributes_.size());
String codon{};
......@@ -45,9 +47,83 @@ String Piece::GetCodon(int length) const
void Piece::Select()
{
outlineModel_->SetEnabled(true);
if (MC->GetGamePhase() == GamePhase::PLAYER1PICKS ||
MC->GetGamePhase() == GamePhase::PLAYER2PICKS )
{
outlineModel_->SetEnabled(true);
if (state_ == PieceState::FREE){
state_ = PieceState::SELECTED;
Material* glow{outlineModel_->GetMaterial()};
Material* originalGlow{MC->GetMaterial("Glow")};
Color glowColor{glow->GetShaderParameter("MatDiffColor").GetColor()};
Color originalGlowColor{originalGlow->GetShaderParameter("MatDiffColor").GetColor()};
ValueAnimation* fadeIn_{new ValueAnimation(context_)};
fadeIn_->SetKeyFrame(0.0f, glowColor);
fadeIn_->SetKeyFrame(0.23f, originalGlowColor);
glow->SetShaderParameterAnimation("MatDiffColor", fadeIn_, WM_ONCE);
outlineModel_->SetEnabled(true);
}
}
}
void Piece::Deselect()
{
outlineModel_->SetEnabled(false);
if (state_ == PieceState::SELECTED){
state_ = PieceState::FREE;
Material* glow{outlineModel_->GetMaterial()};
Color glowColor{glow->GetShaderParameter("MatDiffColor").GetColor()};
ValueAnimation* fadeOut_{new ValueAnimation(context_)};
fadeOut_->SetKeyFrame(0.0f, glowColor);
fadeOut_->SetKeyFrame(0.23f, glowColor * 0.0f);
glow->SetShaderParameterAnimation("MatDiffColor", fadeOut_, WM_ONCE);
}
// outlineModel_->SetEnabled(false);
}
void Piece::Pick()
{
if (state_ == PieceState::SELECTED){
state_ = PieceState::PICKED;
if (MC->GetGamePhase() == GamePhase::PLAYER1PICKS)
rootNode_->SetParent(CAMERA->GetPocket(false));
if (MC->GetGamePhase() == GamePhase::PLAYER2PICKS)
rootNode_->SetParent(CAMERA->GetPocket(true));
ValueAnimation* intoPocketPos{new ValueAnimation(context_)};
intoPocketPos->SetKeyFrame(0.0f, rootNode_->GetPosition());
intoPocketPos->SetKeyFrame(1.0f, Vector3::DOWN);
rootNode_->SetAttributeAnimation("Position", intoPocketPos, WM_ONCE);
ValueAnimation* intoPocketRot{new ValueAnimation(context_)};
intoPocketRot->SetKeyFrame(0.0f, rootNode_->GetRotation());
intoPocketRot->SetKeyFrame(1.0f, Quaternion(10.0f, Vector3(1.0f, 0.0f, 0.5f)));
rootNode_->SetAttributeAnimation("Rotation", intoPocketRot, WM_ONCE);
//Fade out outline
Material* glow{outlineModel_->GetMaterial()};
Color glowColor{glow->GetShaderParameter("MatDiffColor").GetColor()};
ValueAnimation* fadeOut{new ValueAnimation(context_)};
fadeOut->SetKeyFrame(0.0f, glowColor);
fadeOut->SetKeyFrame(0.23f, glowColor * 0.0f);
glow->SetShaderParameterAnimation("MatDiffColor", fadeOut, WM_ONCE);
}
}
void Piece::Put(Vector3 position)
{
if (state_ == PieceState::PICKED){
state_ = PieceState::PUT;
rootNode_->SetParent(MC->world.scene);