Current Working Tree on <2023-10-08>
This commit is contained in:
parent
9349afbadc
commit
ce76166c3f
Binary file not shown.
|
@ -0,0 +1,138 @@
|
|||
// =========================================
|
||||
// | Spacewar-Client.c |
|
||||
// | Copyright (C) 2023, Barra Ó Catháin |
|
||||
// | See end of file for copyright notice. |
|
||||
// =========================================
|
||||
#include <stdbool.h>
|
||||
#include <SDL2/SDL.h>
|
||||
#include <SDL2/SDL_ttf.h>
|
||||
#include <SDL2/SDL_image.h>
|
||||
#include <SDL2/SDL_timer.h>
|
||||
|
||||
#include "Spacewar-Graphics.h"
|
||||
|
||||
int main(int argc, char ** argv)
|
||||
{
|
||||
// Initialize the SDL library, video, sound, and input:
|
||||
if (SDL_Init(SDL_INIT_EVERYTHING) != 0)
|
||||
{
|
||||
printf("SDL Initialization Error: %s\n", SDL_GetError());
|
||||
}
|
||||
|
||||
// Initialize image loading:
|
||||
IMG_Init(IMG_INIT_PNG);
|
||||
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "2");
|
||||
|
||||
// Initialize font support:
|
||||
TTF_Init();
|
||||
|
||||
// Create an SDL window and rendering context in that window:
|
||||
SDL_Window * window = SDL_CreateWindow("SDL_TEST", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 640, 360, 0);
|
||||
uint32_t rendererFlags = SDL_RENDERER_ACCELERATED;
|
||||
SDL_Renderer * renderer = SDL_CreateRenderer(window, -1, rendererFlags);
|
||||
SDL_SetWindowTitle(window, "Spacewar!");
|
||||
SDL_SetWindowResizable(window, SDL_TRUE);
|
||||
|
||||
// Set up keyboard input:
|
||||
int keyCount = 0;
|
||||
const uint8_t * keyboardState = SDL_GetKeyboardState(&keyCount);
|
||||
|
||||
// Prep the titlescreen struct:
|
||||
bool titlescreenInput = false;
|
||||
TTF_Font * font = TTF_OpenFont("../Robtronika.ttf", 12);
|
||||
SpacewarTitlescreen titlescreen = prepareTitleScreen(window, renderer,
|
||||
"../Images/Starfield.png",
|
||||
"../Images/Title.png", font,
|
||||
"Press Enter or Button 0.");
|
||||
// Set up event handling:
|
||||
SDL_Event event;
|
||||
bool keepRunning = true;
|
||||
|
||||
// Display the titlescreen until we get an input:
|
||||
while (!titlescreenInput && keepRunning)
|
||||
{
|
||||
// Update events and input:
|
||||
SDL_PumpEvents();
|
||||
SDL_GetKeyboardState(&keyCount);
|
||||
|
||||
// Check windowing system events:
|
||||
while (SDL_PollEvent(&event) != 0)
|
||||
{
|
||||
switch (event.type)
|
||||
{
|
||||
case SDL_QUIT:
|
||||
{
|
||||
keepRunning = false;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check if Enter was pressed:
|
||||
if(keyboardState[SDL_SCANCODE_RETURN] == 1)
|
||||
{
|
||||
titlescreenInput = true;
|
||||
}
|
||||
|
||||
// Draw the title screen:
|
||||
drawTitleScreen(&titlescreen);
|
||||
|
||||
// Delay enough so that we run at 60 frames in the menu:
|
||||
SDL_Delay(1000 / 60);
|
||||
}
|
||||
|
||||
|
||||
// Connect to server:
|
||||
while (keepRunning)
|
||||
{
|
||||
// Update events and input:
|
||||
SDL_PumpEvents();
|
||||
SDL_GetKeyboardState(&keyCount);
|
||||
|
||||
// Check windowing system events:
|
||||
while (SDL_PollEvent(&event) != 0)
|
||||
{
|
||||
switch (event.type)
|
||||
{
|
||||
case SDL_QUIT:
|
||||
{
|
||||
keepRunning = false;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
drawMenuScreen(&titlescreen);
|
||||
|
||||
// Delay enough so that we run at 60 frames in the menu:
|
||||
SDL_Delay(1000 / 60);
|
||||
}
|
||||
|
||||
// Spawn network thread:
|
||||
|
||||
// Spawn game thread:
|
||||
|
||||
// Spawn graphics thread:
|
||||
|
||||
return 0;
|
||||
}
|
||||
// =======================================================
|
||||
// | End of Spacewar-Client.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 <https://www.gnu.org/licenses/>.
|
||||
|
||||
// Local Variables:
|
||||
// compile-command: "gcc `sdl2-config --libs --cflags` Spacewar-Client.c Spacewar-Graphics.c -lSDL2_image -lSDL2_ttf -lm -o 'Spacewar-Client'"
|
||||
// End:
|
|
@ -0,0 +1,157 @@
|
|||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <SDL2/SDL.h>
|
||||
#include <SDL2/SDL_ttf.h>
|
||||
#include <SDL2/SDL_image.h>
|
||||
#include <SDL2/SDL_timer.h>
|
||||
|
||||
#include "Spacewar-Graphics.h"
|
||||
|
||||
SpacewarTitlescreen prepareTitleScreen(SDL_Window * window, SDL_Renderer * renderer,
|
||||
char * starfieldTexturePath, char * logoTexturePath,
|
||||
TTF_Font * font, char * text)
|
||||
{
|
||||
SpacewarTitlescreen newTitleScreen;
|
||||
|
||||
// Basic state:
|
||||
newTitleScreen.xScroll = 0;
|
||||
newTitleScreen.textAlpha = 0;
|
||||
newTitleScreen.titleAlpha = 0;
|
||||
|
||||
// Requirements for drawing:
|
||||
newTitleScreen.window = window;
|
||||
newTitleScreen.renderer = renderer;
|
||||
|
||||
// Textures:
|
||||
newTitleScreen.titleTexture = IMG_LoadTexture(renderer, logoTexturePath);
|
||||
newTitleScreen.starfieldTexture = IMG_LoadTexture(renderer, starfieldTexturePath);
|
||||
|
||||
// Text message:
|
||||
SDL_Color white = {255, 255, 255};
|
||||
SDL_Surface * fontSurface = TTF_RenderText_Blended(font, text, white);
|
||||
newTitleScreen.textTexture = SDL_CreateTextureFromSurface(renderer, fontSurface);
|
||||
SDL_FreeSurface(fontSurface);
|
||||
|
||||
// Rects:
|
||||
newTitleScreen.titleRectangle = calloc(1, sizeof(SDL_Rect));
|
||||
newTitleScreen.textRectangle = calloc(1, sizeof(SDL_Rect));
|
||||
newTitleScreen.starfieldRectangle = calloc(1, sizeof(SDL_Rect));
|
||||
|
||||
// Set the rects to the size of the textures:
|
||||
SDL_QueryTexture(newTitleScreen.textTexture, NULL, NULL, NULL, &newTitleScreen.textRectangle->h);
|
||||
SDL_QueryTexture(newTitleScreen.textTexture, NULL, NULL, &newTitleScreen.textRectangle->w, NULL);
|
||||
SDL_QueryTexture(newTitleScreen.titleTexture, NULL, NULL, NULL, &newTitleScreen.titleRectangle->h);
|
||||
SDL_QueryTexture(newTitleScreen.titleTexture, NULL, NULL, &newTitleScreen.titleRectangle->w, NULL);
|
||||
SDL_QueryTexture(newTitleScreen.starfieldTexture, NULL, NULL, NULL, &newTitleScreen.starfieldRectangle->h);
|
||||
SDL_QueryTexture(newTitleScreen.starfieldTexture, NULL, NULL, &newTitleScreen.starfieldRectangle->w, NULL);
|
||||
|
||||
return newTitleScreen;
|
||||
}
|
||||
|
||||
void drawTitleScreen(SpacewarTitlescreen * titlescreen)
|
||||
{
|
||||
// Get the current size of the window:
|
||||
int width = 0, height = 0;
|
||||
SDL_GetWindowSize(titlescreen->window, &width, &height);
|
||||
|
||||
// Position the elements on-screen:
|
||||
titlescreen->titleRectangle->x = (width/2) - (titlescreen->titleRectangle->w / 2);
|
||||
titlescreen->titleRectangle->y = (height/2) - titlescreen->titleRectangle->h;
|
||||
|
||||
titlescreen->textRectangle->x = (width/2) - (titlescreen->textRectangle->w / 2);
|
||||
titlescreen->textRectangle->y = (height/2) + (titlescreen->textRectangle->h * 2);
|
||||
|
||||
// Set the renderer colour to black and clear the screen:
|
||||
SDL_SetRenderDrawColor(titlescreen->renderer, 0, 0, 0, 255);
|
||||
SDL_RenderClear(titlescreen->renderer);
|
||||
|
||||
// Set the correct position to begin the starfield, and scroll it back for the next frame:
|
||||
titlescreen->starfieldRectangle->x = 0 - titlescreen->xScroll++;
|
||||
titlescreen->starfieldRectangle->y = 0;
|
||||
|
||||
// Draw the starfield by tiling the starfield texture:
|
||||
while (titlescreen->starfieldRectangle->x <= (width + titlescreen->starfieldRectangle->w))
|
||||
{
|
||||
// Go down, covering a column of the screen:
|
||||
while(titlescreen->starfieldRectangle->y <= (height + titlescreen->starfieldRectangle->h))
|
||||
{
|
||||
SDL_RenderCopy(titlescreen->renderer, titlescreen->starfieldTexture, NULL,
|
||||
titlescreen->starfieldRectangle);
|
||||
titlescreen->starfieldRectangle->y += titlescreen->starfieldRectangle->h;
|
||||
}
|
||||
|
||||
// Back to the top, move over one texture width:
|
||||
titlescreen->starfieldRectangle->y = 0;
|
||||
titlescreen->starfieldRectangle->x += titlescreen->starfieldRectangle->w;
|
||||
}
|
||||
|
||||
// Reset the xScroll if it goes farther than a texture width away:
|
||||
if (titlescreen->xScroll == titlescreen->starfieldRectangle->w + 1)
|
||||
{
|
||||
titlescreen->xScroll = 0;
|
||||
}
|
||||
|
||||
// Set the opacity of the logo so we can fade it in:
|
||||
if (titlescreen->titleAlpha < 254)
|
||||
{
|
||||
titlescreen->titleAlpha += 10;
|
||||
}
|
||||
if (titlescreen->titleAlpha >= 254)
|
||||
{
|
||||
titlescreen->titleAlpha = 254;
|
||||
}
|
||||
SDL_SetTextureAlphaMod(titlescreen->titleTexture, titlescreen->titleAlpha);
|
||||
|
||||
// Set the opacity of the text so we can fade it in after we fade in the logo:
|
||||
if (titlescreen->textAlpha < 254 && titlescreen->titleAlpha == 254)
|
||||
{
|
||||
titlescreen->textAlpha += 10;
|
||||
}
|
||||
if (titlescreen->textAlpha >= 254)
|
||||
{
|
||||
titlescreen->textAlpha = 254;
|
||||
}
|
||||
SDL_SetTextureAlphaMod(titlescreen->textTexture, titlescreen->textAlpha);
|
||||
|
||||
// Display the logo and text:
|
||||
SDL_RenderCopy(titlescreen->renderer, titlescreen->titleTexture, NULL, titlescreen->titleRectangle);
|
||||
SDL_RenderCopy(titlescreen->renderer, titlescreen->textTexture, NULL, titlescreen->textRectangle);
|
||||
|
||||
// Display to the renderer:
|
||||
SDL_RenderPresent(titlescreen->renderer);
|
||||
}
|
||||
|
||||
void drawMenuScreen(SpacewarMenuscreen * menuscreen)
|
||||
{
|
||||
// Get the current size of the window:
|
||||
int width = 0, height = 0;
|
||||
SDL_GetWindowSize(titlescreen->window, &width, &height);
|
||||
|
||||
// Set the renderer colour to black and clear the screen:
|
||||
SDL_SetRenderDrawColor(titlescreen->renderer, 0, 0, 0, 255);
|
||||
SDL_RenderClear(titlescreen->renderer);
|
||||
|
||||
// Set the correct position to begin the starfield, and scroll it back for the next frame:
|
||||
titlescreen->starfieldRectangle->x = 0 - titlescreen->xScroll++;
|
||||
titlescreen->starfieldRectangle->y = 0;
|
||||
|
||||
// Draw the starfield by tiling the starfield texture:
|
||||
while (titlescreen->starfieldRectangle->x <= (width + titlescreen->starfieldRectangle->w))
|
||||
{
|
||||
// Go down, covering a column of the screen:
|
||||
while(titlescreen->starfieldRectangle->y <= (height + titlescreen->starfieldRectangle->h))
|
||||
{
|
||||
SDL_RenderCopy(titlescreen->renderer, titlescreen->starfieldTexture, NULL,
|
||||
titlescreen->starfieldRectangle);
|
||||
titlescreen->starfieldRectangle->y += titlescreen->starfieldRectangle->h;
|
||||
}
|
||||
|
||||
// Back to the top, move over one texture width:
|
||||
titlescreen->starfieldRectangle->y = 0;
|
||||
titlescreen->starfieldRectangle->x += titlescreen->starfieldRectangle->w;
|
||||
}
|
||||
|
||||
// Display to the renderer:
|
||||
SDL_RenderPresent(titlescreen->renderer);
|
||||
}
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
// =========================================
|
||||
// | Spacewar-Graphics.h |
|
||||
// | Copyright (C) 2023, Barra Ó Catháin |
|
||||
// | See end of file for copyright notice. |
|
||||
// =========================================
|
||||
#ifndef SPACEWAR_GRAPHICS
|
||||
#define SPACEWAR_GRAPHICS
|
||||
|
||||
#include <stdint.h>
|
||||
#include <SDL2/SDL.h>
|
||||
|
||||
typedef struct SpacewarTitlescreen
|
||||
{
|
||||
SDL_Window * window;
|
||||
SDL_Renderer * renderer;
|
||||
uint16_t xScroll, titleAlpha, textAlpha;
|
||||
SDL_Texture * titleTexture, * textTexture, * starfieldTexture;
|
||||
SDL_Rect * titleRectangle, * textRectangle, * starfieldRectangle;
|
||||
} SpacewarTitlescreen;
|
||||
|
||||
typedef struct SpacewarMenuscreen
|
||||
{
|
||||
SDL_Window * window;
|
||||
SDL_Renderer * renderer;
|
||||
uint16_t xScroll;
|
||||
SDL_Texture * starfieldTexture;
|
||||
} SpacewarMenuscreen;
|
||||
|
||||
SpacewarTitlescreen prepareTitleScreen(SDL_Window * window, SDL_Renderer * renderer,
|
||||
char * starfieldTexturePath, char * logoTexturePath,
|
||||
TTF_Font * font, char * text);
|
||||
|
||||
SpacewarMenuscreen prepareMenuscreenFromTitle(SpacewarTitlescreen * titlescreen);
|
||||
|
||||
void drawTitleScreen(SpacewarTitlescreen * titlescreen);
|
||||
|
||||
void drawMenuScreen(SpacewarMenuscreen * menuscreen);
|
||||
|
||||
#endif
|
||||
// =========================================================
|
||||
// | End of Spacewar-Graphics.h, 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 <https://www.gnu.org/licenses/>.
|
|
@ -0,0 +1,42 @@
|
|||
// =========================================
|
||||
// | Spacewar-Messages.h |
|
||||
// | Copyright (C) 2023, Barra Ó Catháin |
|
||||
// | See end of file for copyright notice. |
|
||||
// =========================================
|
||||
#ifndef SPACEWAR_MESSAGES
|
||||
#define SPACEWAR_MESSAGES
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
const char * messageStrings[] = {"HELLO", "GOODBYE", "PING", "PONG"};
|
||||
|
||||
struct SpacewarMessage
|
||||
{
|
||||
uint8_t type;
|
||||
uint8_t content;
|
||||
};
|
||||
|
||||
/* Message Types:
|
||||
0 - HELLO: Contents sent to client indicate a given player number.
|
||||
1 - GOODBYE: No contents, end the connection.
|
||||
2 - PING: Contents indicate the missed amount of pongs.
|
||||
3 - PONG: No contents.
|
||||
*/
|
||||
|
||||
#endif
|
||||
// =========================================================
|
||||
// | End of Spacewar-Messages.h, 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 <https://www.gnu.org/licenses/>.
|
|
@ -0,0 +1,54 @@
|
|||
// =========================================
|
||||
// | Spacewar-Physics.h |
|
||||
// | Copyright (C) 2023, Barra Ó Catháin |
|
||||
// | See end of file for copyright notice. |
|
||||
// =========================================
|
||||
#ifndef SPACEWAR_PHYSICS
|
||||
#define SPACEWAR_PHYSICS
|
||||
|
||||
#include <stdint.h>
|
||||
#include "xyVector.h"
|
||||
|
||||
typedef struct SpacewarShipState
|
||||
{
|
||||
bool inPlay;
|
||||
xyVector engine;
|
||||
xyVector gravity;
|
||||
xyVector position;
|
||||
xyVector velocity;
|
||||
} SpacewarShipState;
|
||||
|
||||
typedef struct SpacewarClientInput
|
||||
{
|
||||
double turningAmount, acceleratingAmount;
|
||||
bool turningClockwise, turningAnticlockwise, accelerating;
|
||||
} SpacewarClientInput;
|
||||
|
||||
typedef struct SpacewarState
|
||||
{
|
||||
uint64_t tickNumber;
|
||||
struct timeval timestamp;
|
||||
SpacewarShipState playerStates[32];
|
||||
SpacewarClientInput playerInputs[32];
|
||||
} SpacewarState;
|
||||
|
||||
// Does a single step of the physics:
|
||||
void doPhysicsTick(SpacewarState * state);
|
||||
|
||||
#endif
|
||||
// ========================================================
|
||||
// | End of Spacewar-Physics.h, 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 <https://www.gnu.org/licenses/>.
|
|
@ -0,0 +1,138 @@
|
|||
// =========================================
|
||||
// | Spacewar Server.c |
|
||||
// | Copyright (C) 2023, Barra Ó Catháin |
|
||||
// | See end of file for copyright notice. |
|
||||
// =========================================
|
||||
#include <sys/epoll.h>
|
||||
|
||||
void * runServerPhysics(void * parameters)
|
||||
{
|
||||
struct SpacewarState * state = (struct SpacewarState *)parameters;
|
||||
|
||||
while (true)
|
||||
{
|
||||
doPhysicsTick(state);
|
||||
usleep(15625);
|
||||
}
|
||||
}
|
||||
|
||||
// Creates a Spacewar server, intended to be ran by the standalone server or forked by the game client:
|
||||
int runSpacewarServer(uint16_t port)
|
||||
{
|
||||
// Initialize a simulation:
|
||||
struct SpacewarState * currentState = calloc(1, sizeof(struct SpacewarState));
|
||||
|
||||
// Create our network listeners:
|
||||
int masterSocket = socket(AF_INET, SOCK_STREAM, 0);
|
||||
int masterListeningSocket = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
int masterSendingSocket = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
|
||||
if (masterListeningSocket < 0 || masterSendingSocket < 0 || masterSocket < 0)
|
||||
{
|
||||
fprintf(stderr, "Failed to create socket.\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// Make the socket timeout:
|
||||
struct timeval readTimeout;
|
||||
readTimeout.tv_sec = 0;
|
||||
readTimeout.tv_usec = 800;
|
||||
setsockopt(masterListeningSocket, SOL_SOCKET, SO_RCVTIMEO, &readTimeout, sizeof(readTimeout));
|
||||
|
||||
// Create a structure to store the address we're sending to:
|
||||
struct sockaddr_in sendingAddress;
|
||||
sendingAddress.sin_family = AF_INET; // IPv4
|
||||
sendingAddress.sin_addr.s_addr = inet_addr("127.0.0.1");
|
||||
sendingAddress.sin_port = htons(12000);
|
||||
|
||||
// Create a structure to bind the listening socket:
|
||||
struct sockaddr_in listeningAddress;
|
||||
memset(&listeningAddress, 0, sizeof(listeningAddress));
|
||||
listeningAddress.sin_family = AF_INET; // IPv4
|
||||
listeningAddress.sin_addr.s_addr = INADDR_ANY;
|
||||
listeningAddress.sin_port = port;
|
||||
|
||||
// Bind to the listening socket:
|
||||
if (bind(masterSocket, (const struct sockaddr *)&masterListeningAddress, sizeof(listeningAddress)) < 0)
|
||||
{
|
||||
fprintf(stderr, "Failed to bind socket.\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (bind(masterListeningSocket, (const struct sockaddr *)&masterListeningAddress, sizeof(listeningAddress)) < 0)
|
||||
{
|
||||
fprintf(stderr, "Failed to bind socket.\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// Begin the simulation:
|
||||
pthread_t physicsThread;
|
||||
pthread_create(&physicsThread, NULL, runServerPhysics, currentState);
|
||||
|
||||
// Begin listening on the master socket:
|
||||
listen(masterSocket, 32);
|
||||
|
||||
// Create an epoll descriptor to keep track of clients:
|
||||
int epollDescriptor = epoll_create1();
|
||||
|
||||
// Add the master socket to the epoll set:
|
||||
struct epoll_event requestedEvents;
|
||||
requestedEvents.events = EPOLLIN;
|
||||
requestedEvents.data.fd = masterSocket;
|
||||
epoll_ctl(epollDescriptor, EPOLL_CTL_ADD, masterSocket, &requestedEvents);
|
||||
|
||||
int recievedEventCount = 0;
|
||||
struct epoll_event receivedEvents[32];
|
||||
|
||||
// Manage clients and sending packets back and forth:
|
||||
while (true)
|
||||
{
|
||||
receivedEventCount = epoll_wait(epollDescriptor, receivedEvents, 32, -1);
|
||||
|
||||
for (int eventIndex = 0; eventIndex < receivedEventCount, eventIndex++)
|
||||
{
|
||||
// If there's activity on the master socket, there's a new connection:
|
||||
if (receivedEvents[eventIndex].data.fd == masterSocket)
|
||||
{
|
||||
struct sockaddr_in clientAddress;
|
||||
int newClientSocket = accept(masterSocket, (struct sockaddr *)&clientAddress,
|
||||
sizeof(struct sockaddr_in));
|
||||
|
||||
// Check that the socket is functional:
|
||||
if (newClientSocket < 0)
|
||||
{
|
||||
fprintf(stderr, "Failed to accept client connection.\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
// Register the new client in the epoll set:
|
||||
requestedEvents.events = EPOLLIN;
|
||||
requestedEvents.data.fd = newClientSocket;
|
||||
epoll_ctl(epollDescriptor, EPOLL_CTL_ADD, newClientSocket, &requestedEvents);
|
||||
|
||||
|
||||
}
|
||||
// Otherwise, we've been sent a packet from one of the connected clients:
|
||||
else
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// =======================================================
|
||||
// | End of Spacewar-Server.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 <https://www.gnu.org/licenses/>.
|
|
@ -0,0 +1,36 @@
|
|||
// =========================================
|
||||
// | Spacewar-Server.h |
|
||||
// | Copyright (C) 2023, Barra Ó Catháin |
|
||||
// | See end of file for copyright notice. |
|
||||
// =========================================
|
||||
#ifndef SPACEWAR_SERVER
|
||||
#define SPACEWAR_SERVER
|
||||
|
||||
typedef struct SpacewarConnection
|
||||
{
|
||||
uint8_t missedPongs;
|
||||
int clientSocket;
|
||||
int playerNumber;
|
||||
struct sockaddr_in clientAddress;
|
||||
} SpacewarConnection;
|
||||
|
||||
// Creates a spacewar server, intended to be ran by the standalone server or forked by the game client:
|
||||
int runSpacewarServer(uint16_t port);
|
||||
|
||||
#endif
|
||||
// =======================================================
|
||||
// | End of Spacewar-Server.h, 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 <https://www.gnu.org/licenses/>.
|
|
@ -0,0 +1,68 @@
|
|||
#ifndef XYVECTOR_H
|
||||
#define XYVECTOR_H
|
||||
#include <math.h>
|
||||
|
||||
// A 2D vector:
|
||||
typedef struct xyVector
|
||||
{
|
||||
double xComponent;
|
||||
double yComponent;
|
||||
} xyVector;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// Calculate the vector from point A to point B:
|
||||
static inline void xyVectorBetweenPoints(long ax, long ay, long bx, long by, xyVector * vector)
|
||||
{
|
||||
vector->xComponent = bx - ax;
|
||||
vector->yComponent = by - ay;
|
||||
}
|
||||
|
||||
// Normalize a vector, returning the magnitude:
|
||||
static inline double normalizeXYVector(xyVector * vector)
|
||||
{
|
||||
double magnitude = sqrt(pow(vector->xComponent, 2) + pow(vector->yComponent, 2));
|
||||
if(magnitude != 0)
|
||||
{
|
||||
vector->xComponent /= magnitude;
|
||||
vector->yComponent /= magnitude;
|
||||
}
|
||||
return magnitude;
|
||||
}
|
||||
|
||||
// Rotate XY vector by a given number of degrees:
|
||||
static inline void rotateXYVector(xyVector * vector, double degrees)
|
||||
{
|
||||
double xComponent = vector->xComponent, yComponent = vector->yComponent;
|
||||
vector->xComponent = (cos(degrees * 0.01745329) * xComponent) - (sin(degrees * 0.01745329) * yComponent);
|
||||
vector->yComponent = (sin(degrees * 0.01745329) * xComponent) + (cos(degrees * 0.01745329) * yComponent);
|
||||
}
|
||||
|
||||
// Add vector B to vector A:
|
||||
static inline void addXYVector(xyVector * vectorA, xyVector * vectorB)
|
||||
{
|
||||
vectorA->xComponent += vectorB->xComponent;
|
||||
vectorA->yComponent += vectorB->yComponent;
|
||||
}
|
||||
|
||||
// Add vector B to vector A, scaled for units per frame:
|
||||
static inline void addXYVectorDeltaScaled(xyVector * vectorA, xyVector * vectorB, double deltaTime)
|
||||
{
|
||||
vectorA->xComponent += vectorB->xComponent * (0.001 * deltaTime) * 60;
|
||||
vectorA->yComponent += vectorB->yComponent * (0.001 * deltaTime) * 60;
|
||||
}
|
||||
|
||||
// Multiply a vector by a scalar constant:
|
||||
static inline void multiplyXYVector(xyVector * vector, double scalar)
|
||||
{
|
||||
vector->xComponent *= scalar;
|
||||
vector->yComponent *= scalar;
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue