From bc446d457b7caf947304a7bcc3d37196d5b85f21 Mon Sep 17 00:00:00 2001 From: Barry Kane Date: Sun, 15 Oct 2023 01:47:23 +0100 Subject: [PATCH] Current Working Tree On <2023-10-15> --- source/Spacewar-Client.c | 11 ++++-- source/Spacewar-Physics.c | 82 +++++++++++++++++++++++++++++++++++++++ source/Spacewar-Physics.h | 12 ++++-- source/Spacewar-Server.c | 57 ++++++++++++++++----------- source/Spacewar-Server.h | 3 +- source/xyVector.h | 1 - 6 files changed, 134 insertions(+), 32 deletions(-) create mode 100644 source/Spacewar-Physics.c diff --git a/source/Spacewar-Client.c b/source/Spacewar-Client.c index 50c96cd..a79362a 100644 --- a/source/Spacewar-Client.c +++ b/source/Spacewar-Client.c @@ -79,6 +79,8 @@ int main(int argc, char ** argv) { titlescreenInput = true; } + + // Check if Space was pressed: if(keyboardState[SDL_SCANCODE_SPACE] == 1 && !runServer) { runServer = true; @@ -149,13 +151,14 @@ int main(int argc, char ** argv) printf("Player Number: %u\n" "Secret Key: %u\n", playerNumber, secretKey); - // Spawn network thread: + // Spawn network input thread: - // Spawn game thread: - while(keepRunning) + // Spawn client-side-prediction thread: + if (!runServer) { + pthread_t clientSidePredictionThread; } - + // Spawn graphics thread: return 0; diff --git a/source/Spacewar-Physics.c b/source/Spacewar-Physics.c new file mode 100644 index 0000000..5b11cc5 --- /dev/null +++ b/source/Spacewar-Physics.c @@ -0,0 +1,82 @@ +// ========================================= +// | Spacewar-Physics.c | +// | Copyright (C) 2023, Barra Ó Catháin | +// | See end of file for copyright notice. | +// ========================================= +#include "Spacewar-Physics.h" + +void doPhysicsTick(SpacewarState * state) +{ + double gravityMagnitude, gravityAcceleration; + for (int shipIndex = 0; shipIndex < 32; shipIndex++) + { + SpacewarShipState * currentShip = state->playerStates[shipIndex]; + if (currentShip->inPlay) + { + // Calculate Gravity: + xyVectorBetweenPoints(currentShip->position.xComponent, currentShip->position.yComponent, + 0, 0, currentShip.gravity); + gravityMagnitude = normalizeXYVector(currentShip.gravity); + gravityAcceleration = 0; + + // Some maths that felt okay: + if (gravityMagnitude >= 116) + { + gravityAcceleration = pow(2, (3000 / (gravityMagnitude << 1)))) >> 3; + } + // We're actually in the black hole; teleport: + else + { + ship->position.xComponent = random() % 8000; + ship->position.yComponent = random() % 8000; + ship->velocity.xComponent *= 0.01; + ship->velocity.yComponent *= 0.01; + } + + multiplyXYVector(currentShip.gravity, gravityAcceleration); + + // Apply Inputs: + + // Apply Gravity and Velocity to Position: + addXYVector(currentShip.position, currentShip.gravity); + + // Wrap position to game field: + if (currentShip->position.xComponent > 8000) + { + state->playerStates[shipIndex].position.xComponent = -7999; + state->playerStates[shipIndex].velocity.xComponent *= 0.9; + } + if (currentShip->position.xComponent < -8000) + { + state->playerStates[shipIndex].position.xComponent = 7999; + state->playerStates[shipIndex].velocity.xComponent *= 0.9; + } + if (currentShip->position.yComponent > 8000) + { + state->playerStates[shipIndex].position.yComponent = -7999; + state->playerStates[shipIndex].velocity.yComponent *= 0.9; + } + if (currentShip->position.yComponent < -8000) + { + state->playerStates[shipIndex].position.xComponent = 7999; + state->playerStates[shipIndex].velocity.yComponent *= 0.9; + } + } + } +} +// ======================================================== +// | End of Spacewar-Physics.c, copyright notice follows. | +// ======================================================== + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. + +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . diff --git a/source/Spacewar-Physics.h b/source/Spacewar-Physics.h index f8d946b..0ea6f24 100644 --- a/source/Spacewar-Physics.h +++ b/source/Spacewar-Physics.h @@ -18,12 +18,18 @@ typedef struct SpacewarShipState xyVector velocity; } SpacewarShipState; + +typedef struct SpacewarShipInput +{ + double turningAmount, acceleratingAmount; + bool turningClockwise, turningAnticlockwise, accelerating; +} SpacewarShipInput; + typedef struct SpacewarClientInput { uint8_t playerNumber; uint32_t secret; - double turningAmount, acceleratingAmount; - bool turningClockwise, turningAnticlockwise, accelerating; + SpacewarShipInput input; } SpacewarClientInput; typedef struct SpacewarState @@ -31,7 +37,7 @@ typedef struct SpacewarState uint64_t tickNumber; struct timeval timestamp; SpacewarShipState playerStates[32]; - SpacewarClientInput playerInputs[32]; + SpacewarShipInput playerInputs[32]; } SpacewarState; // Does a single step of the physics: diff --git a/source/Spacewar-Server.c b/source/Spacewar-Server.c index 7855de6..b563d34 100644 --- a/source/Spacewar-Server.c +++ b/source/Spacewar-Server.c @@ -31,40 +31,30 @@ SpacewarConnection * getConnectionBySocket(SpacewarConnection * connections, siz void * runServerPhysics(void * parameters) { - SpacewarState * state = (SpacewarState *)parameters; + SpacewarServerSharedState * sharedState = (SpacewarServerSharedState *)parameters; while (true) { - //doPhysicsTick(state); - //sendCurrentState(); +// doPhysicsTick(sharedState->physicsState); +// sendCurrentState(sharedState->physicsState, sharedState->connections); usleep(15625); } return NULL; } -void * runUDPSocket(void * parameters) +void * runInputReceiver(void * parameters) { SpacewarServerSharedState * sharedState = (SpacewarServerSharedState *)parameters; - int udpSocket, bytesRead; + int bytesRead; socklen_t socketAddressLength; - struct sockaddr_in clientAddress, serverAddress; - if ((udpSocket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) - { - exit(EXIT_FAILURE); - } - - memset(&serverAddress, 0, sizeof(serverAddress)); - serverAddress.sin_family = AF_INET; - serverAddress.sin_port = htons(5200); - serverAddress.sin_addr.s_addr = INADDR_ANY; + struct sockaddr_in clientAddress; SpacewarClientInput input; - bind(udpSocket, (struct sockaddr *)&serverAddress, sizeof(struct sockaddr_in)); while (true) { - bytesRead = recvfrom(udpSocket, &input, sizeof(SpacewarClientInput), 0, + bytesRead = recvfrom(sharedState->udpSocket, &input, sizeof(SpacewarClientInput), 0, (struct sockaddr *)&clientAddress, &socketAddressLength); if (bytesRead == sizeof(SpacewarClientInput)) { @@ -72,10 +62,11 @@ void * runUDPSocket(void * parameters) { if (input.secret == sharedState->connections[input.playerNumber].playerSecret) { + sharedState->physicsState->playerStates[input.playerNumber].inPlay = true; memcpy(&sharedState->connections[input.playerNumber].clientAddress, &clientAddress, sizeof(struct sockaddr_in)); - memcpy(&sharedState->state->playerInputs[input.playerNumber], &input, - sizeof(struct SpacewarClientInput)); + memcpy(&sharedState->physicsState->playerInputs[input.playerNumber], &(input.input), + sizeof(struct SpacewarShipInput)); } } } @@ -144,15 +135,35 @@ void * runSpacewarServer(void * configuration) { connectedClients[index].active = false; } + + // Create a UDP socket: + int udpSocket = 0; + if ((udpSocket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) + { + exit(EXIT_FAILURE); + } + + // Create a struct to bind the UDP socket to a port: + struct sockaddr_in serverAddress; + memset(&serverAddress, 0, sizeof(serverAddress)); + serverAddress.sin_family = AF_INET; + serverAddress.sin_port = htons(5200); + serverAddress.sin_addr.s_addr = INADDR_ANY; + + // Bind it: + bind(udpSocket, (struct sockaddr *)&serverAddress, sizeof(struct sockaddr_in)); - // Begin the simulation: - pthread_t physicsThread, udpThread; + // Setup the server threads: + pthread_t physicsThread, inputThread; SpacewarState * currentState = calloc(1, sizeof(SpacewarState)); SpacewarServerSharedState threadState; - threadState.state = currentState; + threadState.udpSocket = udpSocket; + threadState.physicsState = currentState; threadState.connections = connectedClients; + + // Begin the simulation: + pthread_create(&inputThread, NULL, runInputReceiver, &threadState); pthread_create(&physicsThread, NULL, runServerPhysics, &threadState); - pthread_create(&udpThread, NULL, runUDPSocket, &threadState); // Manage clients and sending packets back and forth: while (true) diff --git a/source/Spacewar-Server.h b/source/Spacewar-Server.h index b7a6311..99429fa 100644 --- a/source/Spacewar-Server.h +++ b/source/Spacewar-Server.h @@ -32,7 +32,8 @@ typedef struct SpacewarServerConfiguration typedef struct SpacewarServerSharedState { - SpacewarState * state; + int udpSocket; + SpacewarState * physicsState; SpacewarConnection * connections; } SpacewarServerSharedState; diff --git a/source/xyVector.h b/source/xyVector.h index ad32290..5eee9a8 100644 --- a/source/xyVector.h +++ b/source/xyVector.h @@ -13,7 +13,6 @@ static inline double angleBetweenVectors(xyVector * vectorA, xyVector * vectorB) { double dotProduct = (vectorA->xComponent * vectorB->xComponent) + (vectorA->yComponent * vectorB->yComponent); double determinant = (vectorA->xComponent * vectorB->yComponent) - (vectorA->yComponent * vectorB->xComponent); - return atan2(dotProduct, determinant) / 0.01745329; }