• No results found

A robust and generous welfare state

Este sub-módulo é responsável pela verificação das jogadas. Descreve o comportamento dos objetos virtuais por meio de fórmulas matemáticas e envia atualizações ao distribuidor de eventos que atualiza os clientes conectados ao servidor. Tais operações são implementadas a partir do TorqueScript.

As peças se movimentam de acordo com uma função de projeção realizada pela API

OpenGL, usando a função gluUnProject que converte um ponto da tela para o cenário, a partir

de algum ponto que seria o observador, no caso a câmera. Exemplo da definição da função

gluUnProject, com os parâmetros a ser passados para execução.

GLint gluUnProject( GLdouble winX, GLdouble winY, GLdouble winZ, const GLdouble

*model, const GLdouble *proj, const GLint *view, GLdouble* objX, GLdouble* objY,

Na Figura 5-7, mostrando o código fonte da torque enfocando a função para executar o movimento de uma peça.

Figura 5-7: Implementação na biblioteca da Torque em C++.

O funcionamento das jogadas do Quarto começa com o jogador entregando ao adversário uma peça. Para fazer esse movimento é necessário que primeiramente ele selecione uma jogada.

Os arquivos que compõem esses algoritmos são quarto.contents/client/scripts/

playGui.cs e quarto.contents.server/scripts/commands.cs. Esses arquivos contêm toda a parte

de logística de movimentação do mouse.

O objeto PlayGui (Figura 5-8) é o responsável por capturar as ações do mouse (Mouse Down, Mouse Up, Mouse Move (Figura 5-9) e Mouse Dragged). Cada um desses eventos possui uma aplicação no jogo.

Figura 5-8: Codificação de eventos do mouse em C++. // Em engine/game/GameTSCtrl.h /*…*/ private: Point3F mMouse3DVec; Point3F mMouse3DPos; Point3F mObjReferencePos; public:

void onMouseMove(const GuiEvent &evt); void onMouseDown(const GuiEvent &evt); void onMouseUp(const GuiEvent &evt); void onMouseDragged(const GuiEvent &evt); Point3F getMouse3DVec() {return mMouse3DVec;}; Point3F getMouse3DPos() {return mMouse3DPos;}; /*…*/

// Em engine/gui/core/GuiTSCtrl.cc

// Utilização da gluUnProject dentro da Engine TGE /*…*/

bool GuiTSCtrl::unproject(const Point3F &pt, Point3F *dest) {

GLdouble objx, objy, objz;

GLint result = gluUnProject(pt.x, pt.y, pt.z,

mSaveModelview, mSaveProjection, mSaveViewport, &objx, &objy, &objz);

if(result == GL_FALSE) return false;

dest->set(objx, objy, objz); return true;

} /*…*/

A PlayGui é uma instância do objeto GameTSCtrl (Figura 5-9). Esta classe inicialmente não possui os eventos de mouse implementados. Por essa razão foi necessário fazer a implementação destas funções para que pudéssemos utilizar o Mouse 3D.

Figura 5-9: Implementação da função onMouseMove().

Na Figura 5-10, apresenta a função PlayGui::onMouseDown(%this) armazena a posição 3D do mouse e a sua direção a partir da câmera. Ao fazer isso, ele envia um comando ao Servidor, contendo essas informações.

commandToServer('selectObject', %mouseVec, %cameraPoint);

Esse comando tem como função dizer ao servidor que o botão do mouse foi clicado, e se for durante sua própria jogada, ele poderá evoluir o onMouseDown para onMouseDragged e arrastar uma peça para que seja jogada no tabuleiro por meio da função onMouseUp.

Entretanto, na Figura 5-10 descreve a implementação do código que refere-se ao processo de seleção e movimentação das peças.

// Em engine/game/GameTSCtrl.cc // Demonstração do onMouseMove.

void GameTSCtrl::onMouseMove(const GuiEvent &evt) { if(gSnapLine) return; MatrixF mat; Point3F vel; if ( GameGetCameraTransform(&mat, &vel) ) {

Point3F pos;// = mObjReferencePos; mat.getColumn(3,&pos);

const Point3F screenPoint(evt.mousePoint.x, evt.mousePoint.y, 1); Point3F worldPoint;

if (unproject(screenPoint, &worldPoint)) {

Point3F vec = worldPoint - pos; lineTestStart = pos;

vec.normalizeSafe(); mMouse3DPos = pos; mMouse3DVec = vec;

// Função que leva para a PlayGui::onMouseMove Con::executef(this, 2, "onMouseMove");

} }

Figura 5-10: Exemplificando a execução da função pela Torque.

Ao ativar o evento onMouseDown da PlayGui, o mouse envia por meio do comando

commandToServer, e o jogador consegue “empacotar” os dados com relação à posição do

mouse do cliente, e sua câmera. A partir disso, em serverCmdSelectObject, é definido o range, ou seja, uma distância de até onde será traçado o ContainerRayCast, uma função que recupera o primeiro objeto com as características enviadas, no nosso caso

$TypeMasks::StaticShapeObjectType.

A seguir, ele verifica qual o estado em que o turno está e dependendo de cada um desses estados ele processará de uma maneira diferente. Por exemplo, se for o estado

$ESTADO_ESCOLHER_PECA ele irá criar uma área com um objeto que utiliza uma IFL

para fazer animações, informando para onde deve ser levada a peça.

A peça seguirá o mouse por meio do evento onMouseDragged da PlayGui e depois será colocada no lugar onde foi deixada ao realizar o onMouseUp, após uma prévia certificação.

// Em PlayGui.cs

function PlayGui::onMouseDown(%this) {

// Recupera o vetor direção em relação a câmera e a posição 3D do mouse. %mouseVec = %this.getMouse3DVec();

// Posição 3D da câmera.

%cameraPoint = %this.getMouse3DPos();

// Mensagem enviada ao servidor dizer para selecionar um Objeto. commandToServer('selectObject', %mouseVec, %cameraPoint);

}

// Em Commands.cs

function serverCmdSelectObject(%client, %mouseVec, %cameraPoint) {

/*…*/

%selectRange = 200;

%mouseScaled = VectorScale(%mouseVec, %selectRange); %rangeEnd = VectorAdd(%cameraPoint, %mouseScaled); %searchMasks = $TypeMasks::StaticShapeObjectType;

%scanTarg = ContainerRayCast (%cameraPoint, %rangeEnd, %searchMasks, false);

O botão Quarto (Q) foi implementado para que qualquer um dos dois jogadores possa apertá-lo em qualquer momento do jogo.22 Uma vez apertado, este jogador irá para o estado

$ESTADO_SELECIONAR_QUARTO, enquanto o outro vai para o $ESTADO_AGUARDAR_QUARTO.

Cada peça selecionada é armazenada em uma variável do tipo Array. Após o Jogador terminar de selecionar as peças que ele julga formar Quarto, imediatamente o servidor executa a função (Figura 5-11) verificaQuarto(). Essa função tem como objetivo, conferir primeiramente se as peças selecionadas estão em posição de formar um Quarto.

Figura 5-11: Algoritmo de execução das regras do jogo.

Caso ele não esteja em posição de formar Quarto, então cancela-se o estado, caso contrário ele faz a verificação das peças e se estiver correto, declara final de jogo conforme detalhado na Figura 5-12. // Em Quarto.cs function verificaQuarto() { /*…*/

// Verifica se a linha é valida.

if(!((%ind(0) == 1 && %ind(1) == 2 && %ind(2) == 3 && %ind(3) == 4) || (%ind(0) == 5 && %ind(1) == 6 && %ind(2) == 7 && %ind(3) == 8) || (%ind(0) == 9 && %ind(1) == 10 && %ind(2) == 11 && %ind(3) == 12) || (%ind(0) == 13 && %ind(1) == 14 && %ind(2) == 15 && %ind(3) == 16) || (%ind(0) == 1 && %ind(1) == 5 && %ind(2) == 9 && %ind(3) == 13) || (%ind(0) == 2 && %ind(1) == 6 && %ind(2) == 10 && %ind(3) == 14) || (%ind(0) == 3 && %ind(1) == 7 && %ind(2) == 11 && %ind(3) == 15) || (%ind(0) == 4 && %ind(1) == 8 && %ind(2) == 12 && %ind(3) == 16) || (%ind(0) == 1 && %ind(1) == 6 && %ind(2) == 11 && %ind(3) == 16) || (%ind(0) == 4 && %ind(1) == 7 && %ind(2) == 10 && %ind(3) == 13))) { cancelaQuarto(); return; } if(verificaPecas($Game::pecasQuarto(0), $Game::pecasQuarto(1), $Game::pecasQuarto(2), $Game::pecasQuarto(3))) {

iluminaCilindros(%ind(0), %ind(1), %ind(2), %ind(3)); // Fim de jogo fimDeJogo(); return true; } else { return false; } }

Figura 5-12: Código de verificação do alinhamento do quarto.