03: show other players in game as well
Will refactor in the future. This was just a PoC
This commit is contained in:
parent
51177e3a19
commit
c048742117
31
03-network/client/src/defs.h
Normal file
31
03-network/client/src/defs.h
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
#ifndef DEFS_H
|
||||||
|
#define DEFS_H
|
||||||
|
|
||||||
|
#include <SDL2/SDL.h>
|
||||||
|
|
||||||
|
// Server details
|
||||||
|
#define SERVER_ADDR "127.0.0.1"
|
||||||
|
#define SERVER_PORT 9080
|
||||||
|
|
||||||
|
// SDL2
|
||||||
|
#define SCREEN_WIDTH 1000
|
||||||
|
#define SCREEN_HEIGHT 480
|
||||||
|
#define WINDOW_FLAGS SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL
|
||||||
|
#define RENDERER_FLAGS SDL_RENDERER_ACCELERATED
|
||||||
|
|
||||||
|
// MCS: Message Communication Standard
|
||||||
|
#define SERVER_MESSAGE_LEN 10
|
||||||
|
#define CLIENT_MESSAGE_LEN 7
|
||||||
|
|
||||||
|
// MFS: Message Format Standard
|
||||||
|
#define PLAYER_CONNECT_FORMAT 0
|
||||||
|
#define OBJECT_PROPERTIES_FORMAT 1
|
||||||
|
#define PLAYER_DISCONNECT_FORMAT 2
|
||||||
|
|
||||||
|
// MSCA: Message Communication Standard Actions
|
||||||
|
#define LEFT_MOVEMENT 0b10000000
|
||||||
|
#define RIGHT_MOVEMENT 0b01000000
|
||||||
|
#define JUMP_MOVEMENT 0b00100000
|
||||||
|
#define CROUCH_MOVEMENT 0b00010000
|
||||||
|
|
||||||
|
#endif
|
|
@ -3,18 +3,11 @@
|
||||||
#include <SDL2/SDL_image.h>
|
#include <SDL2/SDL_image.h>
|
||||||
#include <SDL2/SDL_net.h>
|
#include <SDL2/SDL_net.h>
|
||||||
#include "structs.h"
|
#include "structs.h"
|
||||||
|
#include "defs.h"
|
||||||
|
|
||||||
#define DEBUG 1
|
#define DEBUG 1
|
||||||
#define SERVER_ADDR "127.0.0.1"
|
|
||||||
#define SERVER_PORT 9080
|
|
||||||
#define SERVER_MESSAGE_LEN 10 // 0-1 BYTE: Action details, 2-9: Other data (not sure we even need this)
|
|
||||||
#define CLIENT_MESSAGE_LEN 4 // 4 PROPERTIES (each of 4 BYTES)
|
|
||||||
|
|
||||||
const int SCREEN_WIDTH = 1000;
|
int game_running = 1;
|
||||||
const int SCREEN_HEIGHT = 480;
|
|
||||||
const Uint32 WINDOW_FLAGS = SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL;
|
|
||||||
const Uint32 RENDERER_FLAGS = SDL_RENDERER_ACCELERATED;
|
|
||||||
int GAME_RUNNING = 1;
|
|
||||||
struct game game;
|
struct game game;
|
||||||
int movement_speed = 10;
|
int movement_speed = 10;
|
||||||
double delta_time;
|
double delta_time;
|
||||||
|
@ -26,6 +19,15 @@ TCPsocket server_socket;
|
||||||
// scene
|
// scene
|
||||||
struct object *player;
|
struct object *player;
|
||||||
|
|
||||||
|
// textures
|
||||||
|
SDL_Texture *idle_animation;
|
||||||
|
SDL_Texture *jump_animation;
|
||||||
|
SDL_Texture *run_animation;
|
||||||
|
|
||||||
|
|
||||||
|
int objects_count = 0;
|
||||||
|
struct object ** objects_map;
|
||||||
|
|
||||||
void prepare_scene(void) {
|
void prepare_scene(void) {
|
||||||
SDL_SetRenderDrawColor(game.renderer, 96, 128, 255, 255);
|
SDL_SetRenderDrawColor(game.renderer, 96, 128, 255, 255);
|
||||||
SDL_RenderClear(game.renderer);
|
SDL_RenderClear(game.renderer);
|
||||||
|
@ -49,7 +51,7 @@ void handle_input(void) {
|
||||||
while (SDL_PollEvent(&event)) {
|
while (SDL_PollEvent(&event)) {
|
||||||
switch (event.type) {
|
switch (event.type) {
|
||||||
case SDL_QUIT:
|
case SDL_QUIT:
|
||||||
GAME_RUNNING = 0;
|
game_running = 0;
|
||||||
break;
|
break;
|
||||||
case SDL_KEYDOWN:
|
case SDL_KEYDOWN:
|
||||||
case SDL_KEYUP:
|
case SDL_KEYUP:
|
||||||
|
@ -58,9 +60,8 @@ void handle_input(void) {
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (event.type == SDL_QUIT) {
|
if (event.type == SDL_QUIT)
|
||||||
GAME_RUNNING = 0;
|
game_running = 0;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,6 +132,25 @@ void present_scene(void) {
|
||||||
SDL_RenderPresent(game.renderer);
|
SDL_RenderPresent(game.renderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int new_key_position(void **map, int slots) {
|
||||||
|
int slot = 0;
|
||||||
|
|
||||||
|
if (slots <= 0)
|
||||||
|
return slot;
|
||||||
|
|
||||||
|
if (map == NULL)
|
||||||
|
return slot;
|
||||||
|
|
||||||
|
while (slot <= slots) {
|
||||||
|
if (map[slots] == NULL)
|
||||||
|
break;
|
||||||
|
|
||||||
|
slot++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return slot;
|
||||||
|
}
|
||||||
|
|
||||||
int handle_server(void *data) {
|
int handle_server(void *data) {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
int message[CLIENT_MESSAGE_LEN];
|
int message[CLIENT_MESSAGE_LEN];
|
||||||
|
@ -144,10 +164,80 @@ int handle_server(void *data) {
|
||||||
if (DEBUG)
|
if (DEBUG)
|
||||||
fprintf(stdout, "Notice: received '%d' bytes from server\n", recv_len);
|
fprintf(stdout, "Notice: received '%d' bytes from server\n", recv_len);
|
||||||
|
|
||||||
player->x = message[0];
|
if (message[0] == PLAYER_CONNECT_FORMAT) {
|
||||||
player->y = message[1];
|
if (DEBUG)
|
||||||
player->colliding = message[2];
|
fprintf(stdout, "DEBUG: PLAYER CONNECT MESSAGE\n");
|
||||||
player->force = message[3];
|
|
||||||
|
if (message[1] >= objects_count) {
|
||||||
|
objects_map = (struct object **) realloc(objects_map, sizeof(struct object *)*message[1]);
|
||||||
|
objects_count = message[1]+1;
|
||||||
|
}
|
||||||
|
if (objects_map == NULL) {
|
||||||
|
fprintf(stderr, "Error: failed reallocating objects hash map\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct object *new_object = create_object(idle_animation, 4, 48);
|
||||||
|
if (new_object == NULL) {
|
||||||
|
fprintf(stderr, "Error: failed allocating memory for new object\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
new_object->id = message[1];
|
||||||
|
new_object->x = message[2];
|
||||||
|
new_object->y = message[3];
|
||||||
|
new_object->colliding = message[4];
|
||||||
|
new_object->force = message[5];
|
||||||
|
new_object->state = message[6];
|
||||||
|
objects_map[message[1]] = new_object;
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (message[0] == OBJECT_PROPERTIES_FORMAT) {
|
||||||
|
if (DEBUG)
|
||||||
|
fprintf(stdout, "DEBUG: OBJECT PROPERTIES MESSAGE FOR ID %d\n", message[1]);
|
||||||
|
|
||||||
|
if (message[1] >= objects_count) {
|
||||||
|
objects_map = (struct object **) realloc(objects_map, sizeof(struct object *)*message[1]);
|
||||||
|
objects_count = message[1]+1;
|
||||||
|
}
|
||||||
|
if (objects_map == NULL) {
|
||||||
|
fprintf(stderr, "Error: failed reallocating objects hash map\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (objects_map[message[1]] == NULL) {
|
||||||
|
struct object *new_object = create_object(idle_animation, 4, 48);
|
||||||
|
if (new_object == NULL) {
|
||||||
|
fprintf(stderr, "Error: failed allocating memory for new object\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
new_object->id = message[1];
|
||||||
|
objects_map[message[1]] = new_object;
|
||||||
|
}
|
||||||
|
|
||||||
|
objects_map[message[1]]->x = message[2];
|
||||||
|
objects_map[message[1]]->y = message[3];
|
||||||
|
objects_map[message[1]]->colliding = message[4];
|
||||||
|
objects_map[message[1]]->force = message[5];
|
||||||
|
|
||||||
|
objects_map[message[1]]->state = message[6];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (message[0] == PLAYER_DISCONNECT_FORMAT) {
|
||||||
|
if (DEBUG)
|
||||||
|
fprintf(stdout, "DEBUG: PLAYER DISCONNECT MESSAGE\n");
|
||||||
|
|
||||||
|
int object_id = message[1];
|
||||||
|
|
||||||
|
free(objects_map[object_id]);
|
||||||
|
objects_map[object_id] = NULL;
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -197,17 +287,15 @@ int main(int argc, char *argv[]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// load player animations
|
// load player animations
|
||||||
SDL_Texture *idle_animation = load_texture("assets/player/idle.png");
|
idle_animation = load_texture("assets/player/idle.png");
|
||||||
SDL_Texture *jump_animation = load_texture("assets/player/jump.png");
|
jump_animation = load_texture("assets/player/jump.png");
|
||||||
SDL_Texture *run_animation = load_texture("assets/player/run.png");
|
run_animation = load_texture("assets/player/run.png");
|
||||||
|
|
||||||
player = create_object(idle_animation, 4, 48);
|
|
||||||
|
|
||||||
if (connect_to_server() != 0)
|
if (connect_to_server() != 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
// game loop
|
// game loop
|
||||||
while (GAME_RUNNING) {
|
while (game_running) {
|
||||||
double current_frame = SDL_GetTicks();
|
double current_frame = SDL_GetTicks();
|
||||||
delta_time = current_frame - last_frame;
|
delta_time = current_frame - last_frame;
|
||||||
last_frame = current_frame;
|
last_frame = current_frame;
|
||||||
|
@ -215,43 +303,40 @@ int main(int argc, char *argv[]) {
|
||||||
prepare_scene();
|
prepare_scene();
|
||||||
handle_input();
|
handle_input();
|
||||||
|
|
||||||
|
uint8_t message[SERVER_MESSAGE_LEN];
|
||||||
|
message[0] = (game.left << 7) |
|
||||||
|
(game.right << 6) |
|
||||||
|
(game.jump << 5);
|
||||||
|
|
||||||
|
SDLNet_TCP_Send(server_socket, message, sizeof(uint8_t)*SERVER_MESSAGE_LEN);
|
||||||
|
|
||||||
// The reason why I don't do
|
// The reason why I don't do
|
||||||
// that much game development
|
// that much game development
|
||||||
// in my free time. Damn youuu ifs
|
// in my free time. Damn youuu ifs
|
||||||
if (player->colliding) {
|
for (int iter = 0; iter < objects_count; iter++) {
|
||||||
if (game.left)
|
struct object *obj = objects_map[iter];
|
||||||
switch_animation(player, run_animation);
|
if (obj == NULL)
|
||||||
if (game.right)
|
continue;
|
||||||
switch_animation(player, run_animation);
|
|
||||||
if (!game.left && !game.right)
|
|
||||||
switch_animation(player, idle_animation);
|
|
||||||
if (game.jump) {
|
|
||||||
switch_animation(player, jump_animation);
|
|
||||||
|
|
||||||
uint8_t message[SERVER_MESSAGE_LEN];
|
if (obj->state & LEFT_MOVEMENT) {
|
||||||
message[0] = 2;
|
switch_animation(obj, run_animation);
|
||||||
|
obj->flip = SDL_FLIP_HORIZONTAL;
|
||||||
SDLNet_TCP_Send(server_socket, message, sizeof(uint8_t)*SERVER_MESSAGE_LEN);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (obj->state & RIGHT_MOVEMENT) {
|
||||||
|
switch_animation(obj, run_animation);
|
||||||
|
obj->flip = SDL_FLIP_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(obj->state & LEFT_MOVEMENT) && !(obj->state & RIGHT_MOVEMENT))
|
||||||
|
switch_animation(obj, idle_animation);
|
||||||
|
|
||||||
|
if (obj->state & JUMP_MOVEMENT)
|
||||||
|
switch_animation(obj, jump_animation);
|
||||||
|
|
||||||
|
draw_object(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (game.left) {
|
|
||||||
player->flip = SDL_FLIP_HORIZONTAL;
|
|
||||||
uint8_t message[SERVER_MESSAGE_LEN];
|
|
||||||
message[0] = 1;
|
|
||||||
|
|
||||||
SDLNet_TCP_Send(server_socket, message, sizeof(uint8_t)*SERVER_MESSAGE_LEN);
|
|
||||||
}
|
|
||||||
if (game.right) {
|
|
||||||
player->flip = SDL_FLIP_NONE;
|
|
||||||
uint8_t message[SERVER_MESSAGE_LEN];
|
|
||||||
message[0] = 0;
|
|
||||||
|
|
||||||
SDLNet_TCP_Send(server_socket, message, sizeof(uint8_t)*SERVER_MESSAGE_LEN);
|
|
||||||
}
|
|
||||||
|
|
||||||
draw_object(player);
|
|
||||||
|
|
||||||
present_scene();
|
present_scene();
|
||||||
|
|
||||||
SDL_Delay(16);
|
SDL_Delay(16);
|
||||||
|
|
|
@ -23,6 +23,7 @@ struct object {
|
||||||
SDL_Texture *texture;
|
SDL_Texture *texture;
|
||||||
int resolution; // of the texture/every tile
|
int resolution; // of the texture/every tile
|
||||||
|
|
||||||
|
int id;
|
||||||
int x;
|
int x;
|
||||||
int y;
|
int y;
|
||||||
int scale;
|
int scale;
|
||||||
|
@ -33,6 +34,8 @@ struct object {
|
||||||
double animation_speed; // how fast will the clock reach 1 with respect to delta_time
|
double animation_speed; // how fast will the clock reach 1 with respect to delta_time
|
||||||
int animation_slide; // the current slide of the animation
|
int animation_slide; // the current slide of the animation
|
||||||
|
|
||||||
|
uint8_t state;
|
||||||
|
|
||||||
int colliding;
|
int colliding;
|
||||||
int force;
|
int force;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,17 +1,24 @@
|
||||||
#ifndef DEFS_H
|
#ifndef DEFS_H
|
||||||
#define DEFS_H
|
#define DEFS_H
|
||||||
|
|
||||||
#include <SDL2/SDL.h>
|
// DEBUG
|
||||||
|
#define GENERAL_DEBUG 0x0001
|
||||||
|
#define PLAYER_DEBUG 0x0010
|
||||||
|
|
||||||
// MCS: Message Communication Standard
|
// MCS: Message Communication Standard
|
||||||
#define SERVER_MESSAGE_LEN 10
|
#define SERVER_MESSAGE_LEN 10
|
||||||
#define CLIENT_MESSAGE_LEN 4
|
#define CLIENT_MESSAGE_LEN 7
|
||||||
|
|
||||||
|
// MFS: Message Format Standard
|
||||||
|
#define PLAYER_CONNECT_FORMAT 0
|
||||||
|
#define OBJECT_PROPERTIES_FORMAT 1
|
||||||
|
#define PLAYER_DISCONNECT_FORMAT 2
|
||||||
|
|
||||||
// MCSA: Message Communication Standard Actions
|
// MCSA: Message Communication Standard Actions
|
||||||
#define RIGHT_MOVEMENT 0
|
#define LEFT_MOVEMENT 0b10000000
|
||||||
#define LEFT_MOVEMENT 1
|
#define RIGHT_MOVEMENT 0b01000000
|
||||||
#define JUMP_MOVEMENT 2
|
#define JUMP_MOVEMENT 0b00100000
|
||||||
#define CROUCH_MOVEMENT 3
|
#define CROUCH_MOVEMENT 0b00010000
|
||||||
|
|
||||||
// OC: Object Constants
|
// OC: Object Constants
|
||||||
#define GRAVITY 2
|
#define GRAVITY 2
|
||||||
|
|
|
@ -7,18 +7,130 @@
|
||||||
#include "structs.h"
|
#include "structs.h"
|
||||||
#include "defs.h"
|
#include "defs.h"
|
||||||
|
|
||||||
|
#define DEBUG 0x0010
|
||||||
#define PORT 9080
|
#define PORT 9080
|
||||||
#define DEBUG 1
|
|
||||||
|
|
||||||
int objects_count = 0;
|
int objects_count = 0;
|
||||||
struct object **objects_map;
|
struct object **objects_map;
|
||||||
|
|
||||||
|
int connections_count = 0;
|
||||||
|
struct connection **connections_map;
|
||||||
|
|
||||||
|
void handle_player_input(struct object *obj, char *message) {
|
||||||
|
uint8_t action = message[0];
|
||||||
|
|
||||||
|
if (action & RIGHT_MOVEMENT)
|
||||||
|
obj->x += MOVEMENT_SPEED;
|
||||||
|
|
||||||
|
if (action & LEFT_MOVEMENT)
|
||||||
|
obj->x -= MOVEMENT_SPEED;
|
||||||
|
|
||||||
|
if (action & JUMP_MOVEMENT) {
|
||||||
|
obj->force -= MOVEMENT_SPEED;
|
||||||
|
obj->colliding = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
obj->state = action;
|
||||||
|
}
|
||||||
|
|
||||||
|
void handle_player_physics(struct object *obj) {
|
||||||
|
if (obj->y < 200)
|
||||||
|
obj->force += GRAVITY;
|
||||||
|
else {
|
||||||
|
obj->colliding = 1;
|
||||||
|
obj->y = 200;
|
||||||
|
}
|
||||||
|
|
||||||
|
obj->y += obj->force;
|
||||||
|
}
|
||||||
|
|
||||||
|
void send_player_positions(TCPsocket socket, int player_id) {
|
||||||
|
if (objects_map == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (int iter = 0; iter < objects_count; iter++) {
|
||||||
|
struct object *obj = objects_map[iter];
|
||||||
|
if (obj == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Update the client with every object's information
|
||||||
|
// Note: the order OBVIOUSLY matters
|
||||||
|
int reply[] = {
|
||||||
|
OBJECT_PROPERTIES_FORMAT,
|
||||||
|
obj->id,
|
||||||
|
obj->x,
|
||||||
|
obj->y,
|
||||||
|
obj->colliding,
|
||||||
|
obj->force,
|
||||||
|
obj->state
|
||||||
|
};
|
||||||
|
|
||||||
|
if (DEBUG & PLAYER_DEBUG)
|
||||||
|
fprintf(stdout, "PLAYER_DEBUG: player '%d' properties (%d, %d, %d, %d)\n",
|
||||||
|
obj->id, obj->x, obj->y, obj->colliding, obj->force);
|
||||||
|
|
||||||
|
SDLNet_TCP_Send(socket, reply, sizeof(int)*CLIENT_MESSAGE_LEN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int send_player_connect_event(int object_id) {
|
||||||
|
struct object *obj = objects_map[object_id];
|
||||||
|
|
||||||
|
for (int iter = 0; iter < connections_count; iter++) {
|
||||||
|
struct connection *con = connections_map[iter];
|
||||||
|
if (con == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
int message[] = {
|
||||||
|
PLAYER_CONNECT_FORMAT,
|
||||||
|
obj->id,
|
||||||
|
obj->x,
|
||||||
|
obj->y,
|
||||||
|
obj->colliding,
|
||||||
|
obj->force,
|
||||||
|
obj->state
|
||||||
|
};
|
||||||
|
|
||||||
|
if (DEBUG & PLAYER_DEBUG)
|
||||||
|
fprintf(stdout, "PLAYER_DEBUG: new player '%d' has connected to the server\n", obj->id);
|
||||||
|
|
||||||
|
SDLNet_TCP_Send(con->socket, message, sizeof(int)*CLIENT_MESSAGE_LEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int send_player_disconnect_event(int object_id) {
|
||||||
|
struct object *obj = objects_map[object_id];
|
||||||
|
|
||||||
|
for (int iter = 0; iter < connections_count; iter++) {
|
||||||
|
struct connection *con = connections_map[iter];
|
||||||
|
if (con == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
int message[] = {
|
||||||
|
PLAYER_DISCONNECT_FORMAT,
|
||||||
|
obj->id,
|
||||||
|
obj->x,
|
||||||
|
obj->y,
|
||||||
|
obj->colliding,
|
||||||
|
obj->force,
|
||||||
|
obj->state
|
||||||
|
};
|
||||||
|
|
||||||
|
if (DEBUG & PLAYER_DEBUG)
|
||||||
|
fprintf(stdout, "PLAYER_DEBUG: player '%d' has disconnected from the server\n", obj->id);
|
||||||
|
|
||||||
|
SDLNet_TCP_Send(con->socket, message, sizeof(int)*CLIENT_MESSAGE_LEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int handle_player(void *data) {
|
int handle_player(void *data) {
|
||||||
struct connection *connection_data = (struct connection *) data;
|
struct connection *connection_data = (struct connection *) data;
|
||||||
struct object *obj = objects_map[connection_data->obj_id];
|
struct object *obj = objects_map[connection_data->obj_id];
|
||||||
|
|
||||||
memset(obj, 0, sizeof(struct object));
|
|
||||||
|
|
||||||
SDLNet_SocketSet set = SDLNet_AllocSocketSet(1);
|
SDLNet_SocketSet set = SDLNet_AllocSocketSet(1);
|
||||||
if (set == NULL) {
|
if (set == NULL) {
|
||||||
fprintf(stderr, "Error: cannot allocate memory for a new socket set\n");
|
fprintf(stderr, "Error: cannot allocate memory for a new socket set\n");
|
||||||
|
@ -31,10 +143,11 @@ int handle_player(void *data) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
send_player_connect_event(connection_data->obj_id);
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
char message[SERVER_MESSAGE_LEN];
|
char message[SERVER_MESSAGE_LEN];
|
||||||
|
int ready_sockets = SDLNet_CheckSockets(set, 100);
|
||||||
int ready_sockets = SDLNet_CheckSockets(set, 10);
|
|
||||||
if (ready_sockets == -1) {
|
if (ready_sockets == -1) {
|
||||||
fprintf(stderr, "Error: cannot call select() system call with SDLNet_CheckSockets()\n");
|
fprintf(stderr, "Error: cannot call select() system call with SDLNet_CheckSockets()\n");
|
||||||
continue;
|
continue;
|
||||||
|
@ -44,65 +157,29 @@ int handle_player(void *data) {
|
||||||
goto update_client;
|
goto update_client;
|
||||||
|
|
||||||
int recv_len = SDLNet_TCP_Recv(connection_data->socket, message, SERVER_MESSAGE_LEN);
|
int recv_len = SDLNet_TCP_Recv(connection_data->socket, message, SERVER_MESSAGE_LEN);
|
||||||
|
|
||||||
if (!recv_len) {
|
if (!recv_len) {
|
||||||
// player disconnected
|
// player disconnected
|
||||||
fprintf(stderr, "Error: failed receiving message\n%s\n", SDLNet_GetError());
|
fprintf(stderr, "Error: failed receiving message\n%s\n", SDLNet_GetError());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DEBUG)
|
if (DEBUG & GENERAL_DEBUG)
|
||||||
fprintf(stdout, "Notice: received '%s' and '%d' bytes\n", message, recv_len);
|
fprintf(stdout, "Notice: received '%s' and '%d' bytes\n", message, recv_len);
|
||||||
|
|
||||||
// parsing the message
|
handle_player_input(obj, message);
|
||||||
uint8_t action = message[0];
|
|
||||||
|
|
||||||
switch (action) {
|
|
||||||
case RIGHT_MOVEMENT:
|
|
||||||
obj->x += MOVEMENT_SPEED;
|
|
||||||
break;
|
|
||||||
case LEFT_MOVEMENT:
|
|
||||||
obj->x -= MOVEMENT_SPEED;
|
|
||||||
break;
|
|
||||||
case JUMP_MOVEMENT:
|
|
||||||
obj->force -= MOVEMENT_SPEED * 2.5;
|
|
||||||
obj->colliding = 0;
|
|
||||||
break;
|
|
||||||
case CROUCH_MOVEMENT: // TODO
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
update_client:
|
update_client:
|
||||||
if (obj->y < 200) {
|
handle_player_physics(obj);
|
||||||
obj->force += GRAVITY;
|
send_player_positions(connection_data->socket, connection_data->obj_id);
|
||||||
} else {
|
|
||||||
obj->colliding = 1;
|
|
||||||
// obj->force = 0;
|
|
||||||
obj->y = 200;
|
|
||||||
}
|
|
||||||
|
|
||||||
// gravity
|
|
||||||
obj->y += obj->force;
|
|
||||||
|
|
||||||
// Update the client with information
|
|
||||||
// Note: the order OBVIOUSLY matters
|
|
||||||
int reply[] = {
|
|
||||||
obj->x,
|
|
||||||
obj->y,
|
|
||||||
obj->colliding,
|
|
||||||
obj->force
|
|
||||||
};
|
|
||||||
|
|
||||||
if (DEBUG)
|
|
||||||
fprintf(stdout, "Notice: new player properties (%d, %d, %d, %d)\n", reply[0], reply[1], reply[2], reply[3]);
|
|
||||||
|
|
||||||
SDLNet_TCP_Send(connection_data->socket, reply, sizeof(int)*CLIENT_MESSAGE_LEN);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Communicate client disconnect
|
||||||
|
send_player_disconnect_event(connection_data->obj_id);
|
||||||
|
|
||||||
SDLNet_FreeSocketSet(set);
|
SDLNet_FreeSocketSet(set);
|
||||||
SDLNet_TCP_Close(connection_data->socket);
|
SDLNet_TCP_Close(connection_data->socket);
|
||||||
|
objects_map[connection_data->obj_id] = NULL;
|
||||||
|
connections_map[connection_data->id] = NULL;
|
||||||
free(obj);
|
free(obj);
|
||||||
free(data);
|
free(data);
|
||||||
|
|
||||||
|
@ -114,6 +191,25 @@ void catch_alarm(int sig) {
|
||||||
exit(EXIT_SUCCESS);
|
exit(EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int new_key_position(void **map, int slots) {
|
||||||
|
int slot = 0;
|
||||||
|
|
||||||
|
if (slots <= 0)
|
||||||
|
return slot;
|
||||||
|
|
||||||
|
if (map == NULL)
|
||||||
|
return slot;
|
||||||
|
|
||||||
|
while (slot <= slots) {
|
||||||
|
if (map[slot] == NULL)
|
||||||
|
break;
|
||||||
|
|
||||||
|
slot++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return slot;
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
signal(SIGINT, catch_alarm);
|
signal(SIGINT, catch_alarm);
|
||||||
|
|
||||||
|
@ -148,7 +244,11 @@ int main(int argc, char *argv[]) {
|
||||||
|
|
||||||
fprintf(stdout, "Notice: accepted a connection from client!\n");
|
fprintf(stdout, "Notice: accepted a connection from client!\n");
|
||||||
|
|
||||||
objects_map = (struct object **) realloc(objects_map, sizeof(struct object *)*(objects_count+1));
|
int new_object_position = new_key_position((void **) objects_map, objects_count);
|
||||||
|
if (new_object_position == objects_count) {
|
||||||
|
objects_map = (struct object **) realloc(objects_map, sizeof(struct object *)*objects_count);
|
||||||
|
objects_count++;
|
||||||
|
}
|
||||||
if (objects_map == NULL) {
|
if (objects_map == NULL) {
|
||||||
fprintf(stderr, "Error: failed reallocating objects hash map\n");
|
fprintf(stderr, "Error: failed reallocating objects hash map\n");
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -160,7 +260,15 @@ int main(int argc, char *argv[]) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
objects_map[objects_count] = new_object;
|
int new_connection_position = new_key_position((void **) connections_map, connections_count);
|
||||||
|
if (new_connection_position == connections_count) {
|
||||||
|
connections_map = (struct connection **) realloc(connections_map, sizeof(struct connection *)*connections_count);
|
||||||
|
connections_count++;
|
||||||
|
}
|
||||||
|
if (connections_map == NULL) {
|
||||||
|
fprintf(stderr, "Error: failed reallocating connections hash map\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
struct connection *new_connection = (struct connection *) calloc(1, sizeof(struct connection));
|
struct connection *new_connection = (struct connection *) calloc(1, sizeof(struct connection));
|
||||||
if (new_connection == NULL) {
|
if (new_connection == NULL) {
|
||||||
|
@ -168,11 +276,15 @@ int main(int argc, char *argv[]) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
new_object->id = objects_count;
|
objects_map[new_object_position] = new_object;
|
||||||
|
connections_map[new_connection_position] = new_connection;
|
||||||
|
new_object->id = new_object_position;
|
||||||
|
new_connection->id = new_connection_position;
|
||||||
new_connection->socket = client;
|
new_connection->socket = client;
|
||||||
new_connection->obj_id = objects_count;
|
new_connection->obj_id = new_object_position;
|
||||||
|
|
||||||
objects_count++;
|
if (DEBUG & PLAYER_DEBUG)
|
||||||
|
fprintf(stdout, "Notice: new player object id: %d\n", new_object_position);
|
||||||
|
|
||||||
SDL_CreateThread(handle_player, "client", new_connection);
|
SDL_CreateThread(handle_player, "client", new_connection);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,8 +4,9 @@
|
||||||
#include <SDL2/SDL_net.h>
|
#include <SDL2/SDL_net.h>
|
||||||
|
|
||||||
struct connection {
|
struct connection {
|
||||||
TCPsocket socket;
|
int id;
|
||||||
int obj_id;
|
int obj_id;
|
||||||
|
TCPsocket socket;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct object {
|
struct object {
|
||||||
|
@ -15,6 +16,8 @@ struct object {
|
||||||
|
|
||||||
int colliding;
|
int colliding;
|
||||||
int force;
|
int force;
|
||||||
|
|
||||||
|
uint8_t state;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue
Block a user