03: refactor the code (client+server)
This commit is contained in:
parent
c048742117
commit
4542d4311f
|
@ -7,6 +7,11 @@
|
|||
#define SERVER_ADDR "127.0.0.1"
|
||||
#define SERVER_PORT 9080
|
||||
|
||||
// ERRORS
|
||||
#define STDOK 0
|
||||
#define STDERR -1
|
||||
#define MEMERR -2
|
||||
|
||||
// SDL2
|
||||
#define SCREEN_WIDTH 1000
|
||||
#define SCREEN_HEIGHT 480
|
||||
|
|
64
03-network/client/src/format.c
Normal file
64
03-network/client/src/format.c
Normal file
|
@ -0,0 +1,64 @@
|
|||
#include <SDL2/SDL.h>
|
||||
#include "defs.h"
|
||||
#include "structs.h"
|
||||
#include "format.h"
|
||||
|
||||
extern SDL_Texture *idle_animation;
|
||||
extern SDL_Texture *run_animation;
|
||||
extern SDL_Texture *jump_animation;
|
||||
extern struct object *create_object(SDL_Texture *texture, int scale, int resolution);
|
||||
|
||||
int handle_player_connect(int *message, struct object ***map, int *slots) {
|
||||
int object_id = message[1];
|
||||
|
||||
if (object_id >= *slots) {
|
||||
*slots = object_id+1;
|
||||
*map = realloc(*map, sizeof(struct object *)*(*slots));
|
||||
}
|
||||
|
||||
if (*map == NULL)
|
||||
return MEMERR;
|
||||
|
||||
struct object *new_object = create_object(idle_animation, 4, 48);
|
||||
if (new_object == NULL)
|
||||
return MEMERR;
|
||||
|
||||
new_object->id = object_id;
|
||||
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];
|
||||
(*map)[object_id] = new_object;
|
||||
|
||||
return STDOK;
|
||||
}
|
||||
|
||||
int handle_object_properties(int *message, struct object ***map, int *slots) {
|
||||
int object_id = message[1];
|
||||
|
||||
if (object_id >= *slots) {
|
||||
*slots = object_id+1;
|
||||
*map = realloc(*map, sizeof(struct object *)*(*slots));
|
||||
}
|
||||
|
||||
if (*map == NULL)
|
||||
return MEMERR;
|
||||
|
||||
if ((*map)[object_id] == NULL) {
|
||||
struct object *new_object = create_object(idle_animation, 4, 48);
|
||||
if (new_object == NULL)
|
||||
return MEMERR;
|
||||
|
||||
new_object->id = object_id;
|
||||
(*map)[object_id] = new_object;
|
||||
}
|
||||
|
||||
(*map)[object_id]->x = message[2];
|
||||
(*map)[object_id]->y = message[3];
|
||||
(*map)[object_id]->colliding = message[4];
|
||||
(*map)[object_id]->force = message[5];
|
||||
(*map)[object_id]->state = message[6];
|
||||
|
||||
return STDOK;
|
||||
}
|
9
03-network/client/src/format.h
Normal file
9
03-network/client/src/format.h
Normal file
|
@ -0,0 +1,9 @@
|
|||
#ifndef FORMAT_H
|
||||
#define FORMAT_H
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
int handle_player_connect(int *message, struct object ***map, int *slots);
|
||||
int handle_object_properties(int *message, struct object ***map, int *slots);
|
||||
|
||||
#endif
|
|
@ -4,6 +4,7 @@
|
|||
#include <SDL2/SDL_net.h>
|
||||
#include "structs.h"
|
||||
#include "defs.h"
|
||||
#include "format.h"
|
||||
|
||||
#define DEBUG 1
|
||||
|
||||
|
@ -16,15 +17,12 @@ double last_frame;
|
|||
// network
|
||||
TCPsocket server_socket;
|
||||
|
||||
// scene
|
||||
struct object *player;
|
||||
|
||||
// textures
|
||||
SDL_Texture *idle_animation;
|
||||
SDL_Texture *jump_animation;
|
||||
SDL_Texture *run_animation;
|
||||
SDL_Texture *jump_animation;
|
||||
|
||||
|
||||
// scene
|
||||
int objects_count = 0;
|
||||
struct object ** objects_map;
|
||||
|
||||
|
@ -75,59 +73,6 @@ SDL_Texture *load_texture(const char *path) {
|
|||
return texture;
|
||||
}
|
||||
|
||||
void switch_animation(struct object *object, SDL_Texture *animation) {
|
||||
if (object->texture == animation)
|
||||
return;
|
||||
|
||||
object->animation_slide = 0;
|
||||
object->texture = animation;
|
||||
}
|
||||
|
||||
struct object *create_object(SDL_Texture *texture, int scale, int resolution) {
|
||||
struct object *object = (struct object *) calloc(1, sizeof(struct object));
|
||||
|
||||
if (object == NULL) {
|
||||
fprintf(stderr, "Error: failed allocating memory for new object\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
object->texture = texture;
|
||||
object->resolution = resolution;
|
||||
object->animation_speed = 13;
|
||||
object->scale = scale;
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
void draw_object(struct object *object) {
|
||||
int texture_width;
|
||||
SDL_Rect src;
|
||||
SDL_Rect dest;
|
||||
|
||||
src.x = object->animation_slide * object->resolution;
|
||||
src.y = 0;
|
||||
|
||||
src.w = object->resolution;
|
||||
src.h = object->resolution;
|
||||
|
||||
dest.x = object->x;
|
||||
dest.y = object->y;
|
||||
dest.w = object->resolution * object->scale;
|
||||
dest.h = object->resolution * object->scale;
|
||||
|
||||
SDL_RenderCopyEx(game.renderer, object->texture, &src, &dest, 0, NULL, object->flip);
|
||||
|
||||
// update animation slide
|
||||
SDL_QueryTexture(object->texture, NULL, NULL, &texture_width, NULL);
|
||||
|
||||
object->animation_clock += object->animation_speed*(delta_time/1000);
|
||||
|
||||
if (object->animation_clock >= 1) {
|
||||
object->animation_clock = 0;
|
||||
object->animation_slide = (object->animation_slide+1) % (texture_width / object->resolution); // clock arithmetic: jump back to first animation slide
|
||||
}
|
||||
}
|
||||
|
||||
void present_scene(void) {
|
||||
SDL_RenderPresent(game.renderer);
|
||||
}
|
||||
|
@ -168,28 +113,11 @@ int handle_server(void *data) {
|
|||
if (DEBUG)
|
||||
fprintf(stdout, "DEBUG: PLAYER CONNECT MESSAGE\n");
|
||||
|
||||
if (message[1] >= objects_count) {
|
||||
objects_map = (struct object **) realloc(objects_map, sizeof(struct object *)*message[1]);
|
||||
objects_count = message[1]+1;
|
||||
int ret = handle_player_connect(message, &objects_map, &objects_count);
|
||||
if (ret == MEMERR) {
|
||||
fprintf(stderr, "MEMERR: Failed handling memory for player connect\n");
|
||||
return MEMERR;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
@ -198,32 +126,12 @@ int handle_server(void *data) {
|
|||
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;
|
||||
int ret = handle_object_properties(message, &objects_map, &objects_count);
|
||||
if (ret == MEMERR) {
|
||||
fprintf(stderr, "MEMERR: Failed handling memory for new object properties\n");
|
||||
return MEMERR;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -334,7 +242,7 @@ int main(int argc, char *argv[]) {
|
|||
if (obj->state & JUMP_MOVEMENT)
|
||||
switch_animation(obj, jump_animation);
|
||||
|
||||
draw_object(obj);
|
||||
draw_object(&game, obj);
|
||||
}
|
||||
|
||||
present_scene();
|
||||
|
|
54
03-network/client/src/object.c
Normal file
54
03-network/client/src/object.c
Normal file
|
@ -0,0 +1,54 @@
|
|||
#include "structs.h"
|
||||
|
||||
extern double delta_time;
|
||||
|
||||
struct object *create_object(SDL_Texture *texture, int scale, int resolution) {
|
||||
struct object *object = (struct object *) calloc(1, sizeof(struct object));
|
||||
|
||||
if (object == NULL)
|
||||
return NULL;
|
||||
|
||||
object->texture = texture;
|
||||
object->resolution = resolution;
|
||||
object->animation_speed = 13;
|
||||
object->scale = scale;
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
void draw_object(struct game *game, struct object *object) {
|
||||
int texture_width;
|
||||
SDL_Rect src;
|
||||
SDL_Rect dest;
|
||||
|
||||
src.x = object->animation_slide * object->resolution;
|
||||
src.y = 0;
|
||||
|
||||
src.w = object->resolution;
|
||||
src.h = object->resolution;
|
||||
|
||||
dest.x = object->x;
|
||||
dest.y = object->y;
|
||||
dest.w = object->resolution * object->scale;
|
||||
dest.h = object->resolution * object->scale;
|
||||
|
||||
SDL_RenderCopyEx(game->renderer, object->texture, &src, &dest, 0, NULL, object->flip);
|
||||
|
||||
// update animation slide
|
||||
SDL_QueryTexture(object->texture, NULL, NULL, &texture_width, NULL);
|
||||
|
||||
object->animation_clock += object->animation_speed*(delta_time/1000);
|
||||
|
||||
if (object->animation_clock >= 1) {
|
||||
object->animation_clock = 0;
|
||||
object->animation_slide = (object->animation_slide+1) % (texture_width / object->resolution); // clock arithmetic: jump back to first animation slide
|
||||
}
|
||||
}
|
||||
|
||||
void switch_animation(struct object *object, SDL_Texture *animation) {
|
||||
if (object->texture == animation)
|
||||
return;
|
||||
|
||||
object->animation_slide = 0;
|
||||
object->texture = animation;
|
||||
}
|
|
@ -22,8 +22,8 @@ struct animation {
|
|||
struct object {
|
||||
SDL_Texture *texture;
|
||||
int resolution; // of the texture/every tile
|
||||
|
||||
int id;
|
||||
|
||||
int x;
|
||||
int y;
|
||||
int scale;
|
||||
|
@ -40,4 +40,8 @@ struct object {
|
|||
int force;
|
||||
};
|
||||
|
||||
struct object *create_object(SDL_Texture *texture, int scale, int resolution);
|
||||
void draw_object(struct game *game, struct object *object);
|
||||
void switch_animation(struct object *object, SDL_Texture *animation);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -5,6 +5,10 @@
|
|||
#define GENERAL_DEBUG 0x0001
|
||||
#define PLAYER_DEBUG 0x0010
|
||||
|
||||
// ERRORS
|
||||
#define STDERR -1
|
||||
#define MEMERR -2
|
||||
|
||||
// MCS: Message Communication Standard
|
||||
#define SERVER_MESSAGE_LEN 10
|
||||
#define CLIENT_MESSAGE_LEN 7
|
||||
|
|
43
03-network/server/src/hashmap.c
Normal file
43
03-network/server/src/hashmap.c
Normal file
|
@ -0,0 +1,43 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "hashmap.h"
|
||||
#include "defs.h"
|
||||
|
||||
int find_empty_slot(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 allocate_value(void ***map, int *slots, int bytes) {
|
||||
int empty_slot = find_empty_slot(*map, *slots);
|
||||
|
||||
if (empty_slot == *slots) {
|
||||
(*slots)++;
|
||||
*map = realloc(*map, sizeof(void *)*(*slots));
|
||||
}
|
||||
|
||||
if (*map == NULL)
|
||||
return MEMERR;
|
||||
|
||||
void *new_value = calloc(1, bytes);
|
||||
if (new_value == NULL)
|
||||
return MEMERR;
|
||||
|
||||
(*map)[empty_slot] = new_value;
|
||||
|
||||
return empty_slot;
|
||||
}
|
9
03-network/server/src/hashmap.h
Normal file
9
03-network/server/src/hashmap.h
Normal file
|
@ -0,0 +1,9 @@
|
|||
#ifndef HASHMAP_H
|
||||
#define HASHMAP_H
|
||||
|
||||
#include "structs.h"
|
||||
|
||||
int find_empty_slot(void **map, int slots);
|
||||
int allocate_value(void ***map, int *slots, int bytes);
|
||||
|
||||
#endif
|
|
@ -4,8 +4,9 @@
|
|||
#include <SDL2/SDL.h>
|
||||
#include <SDL2/SDL_net.h>
|
||||
#include <SDL2/SDL_error.h>
|
||||
#include "structs.h"
|
||||
#include "defs.h"
|
||||
#include "structs.h"
|
||||
#include "hashmap.h"
|
||||
|
||||
#define DEBUG 0x0010
|
||||
#define PORT 9080
|
||||
|
@ -44,36 +45,7 @@ void handle_player_physics(struct object *obj) {
|
|||
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) {
|
||||
int broadcast_event(int format, int object_id) {
|
||||
struct object *obj = objects_map[object_id];
|
||||
|
||||
for (int iter = 0; iter < connections_count; iter++) {
|
||||
|
@ -82,7 +54,7 @@ int send_player_connect_event(int object_id) {
|
|||
continue;
|
||||
|
||||
int message[] = {
|
||||
PLAYER_CONNECT_FORMAT,
|
||||
format,
|
||||
obj->id,
|
||||
obj->x,
|
||||
obj->y,
|
||||
|
@ -91,36 +63,6 @@ int send_player_connect_event(int object_id) {
|
|||
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);
|
||||
}
|
||||
|
||||
|
@ -143,7 +85,7 @@ int handle_player(void *data) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
send_player_connect_event(connection_data->obj_id);
|
||||
broadcast_event(PLAYER_CONNECT_FORMAT, connection_data->obj_id);
|
||||
|
||||
for (;;) {
|
||||
char message[SERVER_MESSAGE_LEN];
|
||||
|
@ -170,11 +112,11 @@ int handle_player(void *data) {
|
|||
|
||||
update_client:
|
||||
handle_player_physics(obj);
|
||||
send_player_positions(connection_data->socket, connection_data->obj_id);
|
||||
broadcast_event(OBJECT_PROPERTIES_FORMAT, connection_data->obj_id);
|
||||
}
|
||||
|
||||
// Communicate client disconnect
|
||||
send_player_disconnect_event(connection_data->obj_id);
|
||||
broadcast_event(PLAYER_DISCONNECT_FORMAT, connection_data->obj_id);
|
||||
|
||||
SDLNet_FreeSocketSet(set);
|
||||
SDLNet_TCP_Close(connection_data->socket);
|
||||
|
@ -244,47 +186,28 @@ int main(int argc, char *argv[]) {
|
|||
|
||||
fprintf(stdout, "Notice: accepted a connection from client!\n");
|
||||
|
||||
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) {
|
||||
fprintf(stderr, "Error: failed reallocating objects hash map\n");
|
||||
return -1;
|
||||
int new_object_slot = allocate_value((void ***) &objects_map, &objects_count, sizeof(struct object));
|
||||
if (new_object_slot == MEMERR) {
|
||||
fprintf(stderr, "MEMERR: failed allocating memory for new object\n");
|
||||
return STDERR;
|
||||
}
|
||||
|
||||
struct object *new_object = (struct object *) calloc(1, sizeof(struct object));
|
||||
if (new_object == NULL) {
|
||||
fprintf(stderr, "Error: failed allocating memory for new object\n");
|
||||
return -1;
|
||||
int new_connection_slot = allocate_value((void ***) &connections_map, &connections_count, sizeof(struct connection));
|
||||
if (new_connection_slot == MEMERR) {
|
||||
fprintf(stderr, "MEMERR: failed allocating memory for new connection\n");
|
||||
return STDERR;
|
||||
}
|
||||
|
||||
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 object *new_object = objects_map[new_object_slot];
|
||||
struct connection *new_connection = connections_map[new_connection_slot];
|
||||
|
||||
struct connection *new_connection = (struct connection *) calloc(1, sizeof(struct connection));
|
||||
if (new_connection == NULL) {
|
||||
fprintf(stderr, "Error: failed allocating memory for new connection object\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
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_object->id = new_object_slot;
|
||||
new_connection->id = new_connection_slot;
|
||||
new_connection->socket = client;
|
||||
new_connection->obj_id = new_object_position;
|
||||
new_connection->obj_id = new_object_slot;
|
||||
|
||||
if (DEBUG & PLAYER_DEBUG)
|
||||
fprintf(stdout, "Notice: new player object id: %d\n", new_object_position);
|
||||
fprintf(stdout, "Created connection with id '%d' and object '%d'\n", new_connection->id, new_object->id);
|
||||
|
||||
SDL_CreateThread(handle_player, "client", new_connection);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user