04: add boilerplate map generation code

This commit is contained in:
0xdeadbeer 2023-11-23 19:58:37 +01:00
parent 1ddd9cd174
commit f0f6a723b3
41 changed files with 510 additions and 607 deletions

View File

@ -1,3 +0,0 @@
# Collision - Client
Client-side code for 04-collision

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 878 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 921 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 725 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.6 KiB

View File

@ -1,62 +0,0 @@
#include <SDL2/SDL.h>
#include "defs.h"
#include "structs.h"
#include "format.h"
extern SDL_Texture *idle_down_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_down_animation, 4, 64);
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_down_animation, 4, 64);
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;
}

View File

@ -1,9 +0,0 @@
#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

View File

@ -1,278 +0,0 @@
#include <stdio.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <SDL2/SDL_net.h>
#include "structs.h"
#include "defs.h"
#include "format.h"
#define DEBUG 1
int game_running = 1;
struct game game;
int movement_speed = 10;
double delta_time;
double last_frame;
// network
TCPsocket server_socket;
// textures
SDL_Texture *idle_animation;
SDL_Texture *move_left_animation;
SDL_Texture *move_right_animation;
SDL_Texture *move_up_animation;
SDL_Texture *move_down_animation;
SDL_Texture *idle_left_animation;
SDL_Texture *idle_right_animation;
SDL_Texture *idle_up_animation;
SDL_Texture *idle_down_animation;
// scene
int objects_count = 0;
struct object ** objects_map;
void prepare_scene(void) {
SDL_SetRenderDrawColor(game.renderer, 96, 128, 255, 255);
SDL_RenderClear(game.renderer);
}
void key(SDL_KeyboardEvent *event) {
if (event->repeat != 0)
return;
if (event->keysym.scancode == SDL_SCANCODE_D)
game.left = !game.left;
if (event->keysym.scancode == SDL_SCANCODE_F)
game.right = !game.right;
if (event->keysym.scancode == SDL_SCANCODE_K)
game.up = !game.up;
if (event->keysym.scancode == SDL_SCANCODE_J)
game.down = !game.down;
}
void handle_input(void) {
SDL_Event event;
while (SDL_PollEvent(&event)) {
switch (event.type) {
case SDL_QUIT:
game_running = 0;
break;
case SDL_KEYDOWN:
case SDL_KEYUP:
key(&event.key);
break;
default:
break;
}
if (event.type == SDL_QUIT)
game_running = 0;
}
}
SDL_Texture *load_texture(const char *path) {
SDL_Texture *texture;
SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO, "Loading %s", path);
texture = IMG_LoadTexture(game.renderer, path);
return texture;
}
void present_scene(void) {
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) {
for (;;) {
int message[CLIENT_MESSAGE_LEN];
int recv_len = SDLNet_TCP_Recv(server_socket, message, sizeof(int)*CLIENT_MESSAGE_LEN);
if (!recv_len) {
fprintf(stderr, "Error: failed receiving message from server\n%s\n", SDLNet_GetError());
break;
}
if (DEBUG)
fprintf(stdout, "Notice: received '%d' bytes from server\n", recv_len);
if (message[0] == PLAYER_CONNECT_FORMAT) {
if (DEBUG)
fprintf(stdout, "DEBUG: PLAYER CONNECT MESSAGE\n");
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;
}
continue;
}
if (message[0] == OBJECT_PROPERTIES_FORMAT) {
if (DEBUG)
fprintf(stdout, "DEBUG: OBJECT PROPERTIES MESSAGE FOR ID %d\n", message[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;
}
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;
}
int connect_to_server(void) {
IPaddress ip;
if (SDLNet_ResolveHost(&ip, SERVER_ADDR, SERVER_PORT) != 0) {
fprintf(stderr, "Error: resolving host of server\n%s\n", SDLNet_GetError());
return -1;
}
server_socket = SDLNet_TCP_Open(&ip);
if (!server_socket) {
fprintf(stderr, "Error: failed opening socket to '%s' at '%d'\n%s\n", SERVER_ADDR, SERVER_PORT, SDLNet_GetError());
return -1;
}
SDL_CreateThread(handle_server, "server", NULL);
return 0;
}
int main(int argc, char *argv[]) {
if (SDL_Init(SDL_INIT_VIDEO) != 0) {
fprintf(stderr, "Error: could not initialize SDL\n%s\n", SDL_GetError());
return -1;
}
if (SDLNet_Init() != 0) {
fprintf(stderr, "Error: could not initialize SDL net\n%s\n", SDL_GetError());
return -1;
}
game.window = SDL_CreateWindow("03-network", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, WINDOW_FLAGS);
if (game.window == NULL) {
fprintf(stderr, "Error: could not create window\n%s\n", SDL_GetError());
return -1;
}
game.renderer = SDL_CreateRenderer(game.window, -1, RENDERER_FLAGS);
if (game.renderer == NULL) {
fprintf(stderr, "Error: could not create renderer\n%s\n", SDL_GetError());
return -1;
}
// load player animations
move_left_animation = load_texture("assets/player/move_left.png");
move_right_animation = load_texture("assets/player/move_right.png");
move_up_animation = load_texture("assets/player/move_up.png");
move_down_animation = load_texture("assets/player/move_down.png");
idle_left_animation = load_texture("assets/player/idle_left.png");
idle_right_animation = load_texture("assets/player/idle_right.png");
idle_up_animation = load_texture("assets/player/idle_up.png");
idle_down_animation = load_texture("assets/player/idle_down.png");
idle_animation = idle_down_animation;
if (connect_to_server() != 0)
return -1;
// game loop
while (game_running) {
double current_frame = SDL_GetTicks();
delta_time = current_frame - last_frame;
last_frame = current_frame;
prepare_scene();
handle_input();
uint8_t message[SERVER_MESSAGE_LEN];
message[0] = (game.left << 7) |
(game.right << 6) |
(game.up << 5) |
(game.down << 4);
SDLNet_TCP_Send(server_socket, message, sizeof(uint8_t)*SERVER_MESSAGE_LEN);
for (int iter = 0; iter < objects_count; iter++) {
struct object *obj = objects_map[iter];
if (obj == NULL)
continue;
if (obj->state & LEFT_MOVEMENT) {
switch_animation(obj, move_left_animation);
idle_animation = idle_left_animation;
}
if (obj->state & RIGHT_MOVEMENT) {
switch_animation(obj, move_right_animation);
idle_animation = idle_right_animation;
}
if (obj->state & UP_MOVEMENT) {
switch_animation(obj, move_up_animation);
idle_animation = idle_up_animation;
}
if (obj->state & DOWN_MOVEMENT) {
switch_animation(obj, move_down_animation);
idle_animation = idle_down_animation;
}
if (obj->state == NO_MOVEMENT)
switch_animation(obj, idle_animation);
obj->animation_speed = 6;
draw_object(&game, obj);
}
present_scene();
SDL_Delay(16);
}
SDL_DestroyWindow(game.window);
SDL_Quit();
return 0;
}

View File

@ -1,3 +0,0 @@
# Collision - Server
Server-side code for 04-collision

View File

@ -1,216 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_net.h>
#include <SDL2/SDL_error.h>
#include "defs.h"
#include "structs.h"
#include "structures.h"
#define DEBUG 0x0010
#define PORT 9080
struct object **objects_map;
int objects_map_size = 0;
int objects_count = 0;
struct connection **connections_map;
int connections_map_size = 0;
int connections_count = 0;
void handle_player_input(struct object *obj, char *message) {
uint8_t action = message[0];
if (action & LEFT_MOVEMENT)
obj->x -= MOVEMENT_SPEED;
if (action & RIGHT_MOVEMENT)
obj->x += MOVEMENT_SPEED;
if (action & UP_MOVEMENT)
obj->y -= MOVEMENT_SPEED;
if (action & DOWN_MOVEMENT)
obj->y += MOVEMENT_SPEED;
obj->state = action;
}
void handle_player_physics(struct object *obj) {
}
int broadcast_event(int format, int object_id) {
struct object *obj = objects_map[object_id];
for (int iter = 0; iter < connections_map_size; iter++) {
struct connection *con = connections_map[iter];
if (con == NULL)
continue;
int message[] = {
format,
obj->id,
obj->x,
obj->y,
obj->colliding,
obj->force,
obj->state
};
SDLNet_TCP_Send(con->socket, message, sizeof(int)*CLIENT_MESSAGE_LEN);
}
return 0;
}
int handle_player(void *data) {
struct connection *connection_data = (struct connection *) data;
struct object *obj = objects_map[connection_data->obj_id];
SDLNet_SocketSet set = SDLNet_AllocSocketSet(1);
if (set == NULL) {
fprintf(stderr, "Error: cannot allocate memory for a new socket set\n");
return -1;
}
int ret = SDLNet_TCP_AddSocket(set, connection_data->socket);
if (ret == -1) {
fprintf(stderr, "Error: max socket count in socket set reached\n");
return -1;
}
broadcast_event(PLAYER_CONNECT_FORMAT, connection_data->obj_id);
for (;;) {
char message[SERVER_MESSAGE_LEN];
int ready_sockets = SDLNet_CheckSockets(set, 100);
if (ready_sockets == -1) {
fprintf(stderr, "Error: cannot call select() system call with SDLNet_CheckSockets()\n");
continue;
}
if (ready_sockets == 0)
goto update_client;
int recv_len = SDLNet_TCP_Recv(connection_data->socket, message, SERVER_MESSAGE_LEN);
if (!recv_len) {
// player disconnected
fprintf(stderr, "Error: failed receiving message\n%s\n", SDLNet_GetError());
break;
}
if (DEBUG & GENERAL_DEBUG)
fprintf(stdout, "Notice: received '%s' and '%d' bytes\n", message, recv_len);
handle_player_input(obj, message);
update_client:
handle_player_physics(obj);
broadcast_event(OBJECT_PROPERTIES_FORMAT, connection_data->obj_id);
}
// Communicate client disconnect
broadcast_event(PLAYER_DISCONNECT_FORMAT, connection_data->obj_id);
SDLNet_FreeSocketSet(set);
SDLNet_TCP_Close(connection_data->socket);
objects_map[connection_data->obj_id] = NULL;
objects_count--;
connections_map[connection_data->id] = NULL;
connections_count--;
free(obj);
free(data);
return 0;
}
void catch_alarm(int sig) {
fprintf(stdout, "Notice: force stopping server...\n");
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[]) {
signal(SIGINT, catch_alarm);
if (SDL_Init(SDL_INIT_VIDEO) != 0) {
fprintf(stderr, "Error: could not initialize SDL\n%s\n", SDL_GetError());
return -1;
}
if (SDLNet_Init() != 0) {
fprintf(stderr, "Error: could not initialize SDL net\n%s\n", SDL_GetError());
return -1;
}
IPaddress ip;
if (SDLNet_ResolveHost(&ip, NULL, PORT) == -1) {
fprintf(stderr, "Error: failed resolving host \n%s\n", SDL_GetError());
return -1;
}
TCPsocket server = SDLNet_TCP_Open(&ip);
if (!server) {
fprintf(stderr, "Error: failed opening socket at %d\n%s\n", PORT, SDL_GetError());
return -1;
}
for (;;) {
TCPsocket client = SDLNet_TCP_Accept(server);
if (!client) {
SDL_Delay(100);
continue;
}
fprintf(stdout, "Notice: accepted a connection from client!\n");
int new_object_slot = map_allocate_value((void ***) &objects_map, &objects_map_size, &objects_count, sizeof(struct object));
if (new_object_slot == MEMERR) {
fprintf(stderr, "MEMERR: failed allocating memory for new object\n");
return STDERR;
}
int new_connection_slot = map_allocate_value((void ***) &connections_map, &connections_map_size, &connections_count, sizeof(struct connection));
if (new_connection_slot == MEMERR) {
fprintf(stderr, "MEMERR: failed allocating memory for new connection\n");
return STDERR;
}
struct object *new_object = objects_map[new_object_slot];
struct connection *new_connection = connections_map[new_connection_slot];
new_object->id = new_object_slot;
new_connection->id = new_connection_slot;
new_connection->socket = client;
new_connection->obj_id = new_object_slot;
if (DEBUG & PLAYER_DEBUG)
fprintf(stdout, "Created connection with id '%d' and object '%d'\n", new_connection->id, new_object->id);
SDL_CreateThread(handle_player, "client", new_connection);
}
return 0;
}

View File

@ -1,9 +0,0 @@
#ifndef STRUCTURES_H
#define STRUCTURES_H
#include "structs.h"
int map_find_empty_slot(void **map, int slots);
int map_allocate_value(void ***map, int *total_slots, int *used_slots, int bytes);
#endif

View File

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

7
04-map/README.md Normal file
View File

@ -0,0 +1,7 @@
<!-- <p align="center"> -->
<!-- <img src=".imgs/showcase.png" width="300" /> -->
<!-- </p> -->
# Map
My first attempt to recreate map generation in SDL. Both the server and the client run off of the SDL2 library. (alongside some extensions)

7
04-map/client/README.md Normal file
View File

@ -0,0 +1,7 @@
<!-- <p align="center"> -->
<!-- <img src=".imgs/showcase.png" width="300" /> -->
<!-- </p> -->
# Map - Client
Client-side code for 04-map

Binary file not shown.

After

Width:  |  Height:  |  Size: 945 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 839 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

@ -13,14 +13,12 @@
#define MEMERR -2
// 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
#define CLIENT_MESSAGE_LEN 10
// MFS: Message Format Standard
#define PLAYER_CONNECT_FORMAT 0
@ -30,8 +28,12 @@
// MSCA: Message Communication Standard Actions
#define LEFT_MOVEMENT 0b10000000
#define RIGHT_MOVEMENT 0b01000000
#define UP_MOVEMENT 0b00100000
#define DOWN_MOVEMENT 0b00010000
#define NO_MOVEMENT 0b00000000
#define JUMP_MOVEMENT 0b00100000
#define CROUCH_MOVEMENT 0b00010000
// BS: Block Standard
#define GRASS_BLOCK 0b10000000
#define COBBLE_BLOCK 0b01000000
#define LAVA_BLOCK 0b00100000
#endif

View File

@ -0,0 +1,40 @@
#include <SDL2/SDL.h>
#include "defs.h"
#include "structs.h"
#include "format.h"
extern SDL_Texture *grass_texture;
extern SDL_Texture *cobble_texture;
extern SDL_Texture *lava_texture;
extern struct object *create_object(SDL_Texture *texture, int scale, int resolution);
int handle_block_creation(int id, int type, struct object ***map, int *slots) {
(*slots)++;
*map = realloc(*map, sizeof(struct object *)*(*slots));
if (*map == NULL)
return MEMERR;
SDL_Texture *texture;
switch (type) {
case 0:
texture = grass_texture;
break;
case 1:
texture = cobble_texture;
break;
case 2:
texture = lava_texture;
break;
default:
texture = grass_texture;
break;
}
struct object *new_block = create_object(texture, 1, 32);
if (new_block == NULL)
return MEMERR;
(*map)[id] = new_block;
return STDOK;
}

View File

@ -0,0 +1,10 @@
#ifndef FORMAT_H
#define FORMAT_H
#include <stdlib.h>
int handle_block_creation(int id, int type, struct object ***map, int *slots);
// int handle_player_connect(int *message, struct object ***map, int *slots);
// int handle_object_properties(int *message, struct object ***map, int *slots);
#endif

241
04-map/client/src/main.c Normal file
View File

@ -0,0 +1,241 @@
#include <stdio.h>
#include <signal.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <SDL2/SDL_net.h>
#include <SDL2/SDL_mutex.h>
#include "structs.h"
#include "format.h"
#include "defs.h"
#define DEBUG 1
#define MAP_WIDTH 100
#define MAP_HEIGHT 100
int original_width = 1000;
int original_height = 480;
int screen_width = 1000;
int screen_height = 480;
int game_running = 1;
struct game game;
int movement_speed = 10;
double delta_time;
double last_frame;
// network
TCPsocket server_socket;
// Textures
SDL_Texture *grass_texture;
SDL_Texture *cobble_texture;
SDL_Texture *lava_texture;
// scene
int objects_count = 0;
struct object ** objects_map;
SDL_mutex *objects_map_mutex;
void prepare_scene(void) {
SDL_SetRenderDrawColor(game.renderer, 0, 0, 0, 0);
SDL_RenderClear(game.renderer);
}
void key(SDL_KeyboardEvent *event) {
if (event->repeat != 0)
return;
if (event->keysym.scancode == SDL_SCANCODE_J)
game.left = !game.left;
if (event->keysym.scancode == SDL_SCANCODE_K)
game.right = !game.right;
if (event->keysym.scancode == SDL_SCANCODE_SPACE)
game.jump = !game.jump;
}
void handle_input(void) {
SDL_Event event;
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT)
game_running = 0;
}
}
SDL_Texture *load_texture(const char *path) {
SDL_Texture *texture;
SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO, "Loading %s", path);
texture = IMG_LoadTexture(game.renderer, path);
return texture;
}
void present_scene(void) {
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 message[MAP_WIDTH*MAP_HEIGHT];
int recv_len = SDLNet_TCP_Recv(server_socket, message, sizeof(int)*MAP_WIDTH*MAP_HEIGHT);
if (!recv_len) {
fprintf(stderr, "Error: failed receiving message from server\n%s\n", SDLNet_GetError());
return MEMERR;
}
if (DEBUG)
fprintf(stdout, "Notice: received '%d' bytes from server\n", recv_len);
SDL_LockMutex(objects_map_mutex);
int blocks_num = recv_len / sizeof(int);
for (int y = 0; y < MAP_HEIGHT; y++) {
for (int x = 0; x < MAP_WIDTH; x++) {
int iter = (y*MAP_WIDTH)+x;
int ret = handle_block_creation(iter, message[iter], &objects_map, &objects_count);
if (ret == MEMERR) {
fprintf(stderr, "Error: failed creating new block\n");
return MEMERR;
}
struct object *block = objects_map[iter];
block->x = x * block->resolution * block->scale;
block->y = y * block->resolution * block->scale;
}
}
SDL_UnlockMutex(objects_map_mutex);
return 0;
}
int connect_to_server(void) {
IPaddress ip;
if (SDLNet_ResolveHost(&ip, SERVER_ADDR, SERVER_PORT) != 0) {
fprintf(stderr, "Error: resolving host of server\n%s\n", SDLNet_GetError());
return -1;
}
server_socket = SDLNet_TCP_Open(&ip);
if (!server_socket) {
fprintf(stderr, "Error: failed opening socket to '%s' at '%d'\n%s\n", SERVER_ADDR, SERVER_PORT, SDLNet_GetError());
return -1;
}
SDL_CreateThread(handle_server, "server", NULL);
return 0;
}
void catch_alarm(int sig) {
exit(EXIT_FAILURE);
}
void handle_events() {
SDL_Event event;
while (SDL_PollEvent(&event)) {
switch (event.type) {
case SDL_WINDOWEVENT:
if (event.window.event == SDL_WINDOWEVENT_RESIZED)
SDL_GetWindowSize(game.window, &screen_width, &screen_height);
break;
case SDL_QUIT:
exit(EXIT_SUCCESS);
break;
}
}
}
int main(int argc, char *argv[]) {
signal(SIGINT, catch_alarm);
if (SDL_Init(SDL_INIT_VIDEO) != 0) {
fprintf(stderr, "Error: could not initialize SDL\n%s\n", SDL_GetError());
return -1;
}
if (SDLNet_Init() != 0) {
fprintf(stderr, "Error: could not initialize SDL net\n%s\n", SDL_GetError());
return -1;
}
game.window = SDL_CreateWindow("03-network", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, screen_width, screen_height, WINDOW_FLAGS);
SDL_SetWindowResizable(game.window, 1);
if (game.window == NULL) {
fprintf(stderr, "Error: could not create window\n%s\n", SDL_GetError());
return -1;
}
game.renderer = SDL_CreateRenderer(game.window, -1, RENDERER_FLAGS);
if (game.renderer == NULL) {
fprintf(stderr, "Error: could not create renderer\n%s\n", SDL_GetError());
return -1;
}
// load textures
grass_texture = load_texture("assets/floor/grass.png");
cobble_texture = load_texture("assets/floor/cobble.png");
lava_texture = load_texture("assets/floor/lava.png");
// create mutexes
objects_map_mutex = SDL_CreateMutex();
if (connect_to_server() != 0)
return -1;
while (game_running) {
prepare_scene();
handle_events();
int lock = SDL_TryLockMutex(objects_map_mutex);
if (lock == 0) {
for (int iter = 0; iter < objects_count; iter++) {
struct object *object = objects_map[iter];
if (object == NULL)
continue;
object->x = object->x - (object->scale * object->resolution * (original_width - original_width));
object->y = object->y - (object->scale * object->resolution * (original_height - original_height));
draw_object(&game, object);
}
SDL_UnlockMutex(objects_map_mutex);
}
present_scene();
SDL_Delay(100);
}
SDL_DestroyWindow(game.window);
SDL_Quit();
return 0;
}

View File

@ -16,7 +16,7 @@ struct object *create_object(SDL_Texture *texture, int scale, int resolution) {
return object;
}
void draw_object(struct game *game, struct object *object) {
void frame_draw_object(struct game *game, struct object *object) {
int texture_width;
SDL_Rect src;
SDL_Rect dest;
@ -45,6 +45,24 @@ void draw_object(struct game *game, struct object *object) {
}
}
void draw_object(struct game *game, struct object *object) {
SDL_Rect src;
SDL_Rect dest;
src.x = 0;
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, SDL_FLIP_NONE);
}
void switch_animation(struct object *object, SDL_Texture *animation) {
if (object->texture == animation)
return;

View File

@ -9,8 +9,7 @@ struct game {
int left;
int right;
int up;
int down;
int jump;
};
struct animation {
@ -43,6 +42,7 @@ struct object {
struct object *create_object(SDL_Texture *texture, int scale, int resolution);
void draw_object(struct game *game, struct object *object);
void frame_draw_object(struct game *game, struct object *object);
void switch_animation(struct object *object, SDL_Texture *animation);
#endif

3
04-map/server/README.md Normal file
View File

@ -0,0 +1,3 @@
# Map - Server
Server-side code for 04-map

View File

@ -21,11 +21,16 @@
// MCSA: Message Communication Standard Actions
#define LEFT_MOVEMENT 0b10000000
#define RIGHT_MOVEMENT 0b01000000
#define UP_MOVEMENT 0b00100000
#define DOWN_MOVEMENT 0b00010000
#define JUMP_MOVEMENT 0b00100000
#define CROUCH_MOVEMENT 0b00010000
// OC: Object Constants
#define GRAVITY 2
#define MOVEMENT_SPEED 10
// BS: Block Standard
#define GRASS_BLOCK 1
#define COBBLE_BLOCK 2
#define LAVA_BLOCK 3
#endif

View File

@ -1,9 +1,9 @@
#include <stdio.h>
#include <stdlib.h>
#include "structures.h"
#include "hashmap.h"
#include "defs.h"
int map_find_empty_slot(void **map, int slots) {
int find_empty_slot(void **map, int slots) {
int slot = 0;
if (slots <= 0)
@ -25,12 +25,12 @@ int map_find_empty_slot(void **map, int slots) {
// If there's Nx fewer used slots than total slots in the map, find the first possible one.
// Else reallocate the map and use the end slot
// Then allocate an object of size BYTES and add it into the map.
int map_allocate_value(void ***map, int *total_slots, int *used_slots, int bytes) {
int allocate_value(void ***map, int *total_slots, int *used_slots, int bytes) {
int half_slots = (*total_slots) / 2;
int empty_slot = 0;
if (*used_slots < half_slots) {
empty_slot = map_find_empty_slot(*map, *used_slots);
empty_slot = find_empty_slot(*map, *used_slots);
goto jump;
}
@ -51,5 +51,3 @@ jump:
return empty_slot;
}

View 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 *total_slots, int *used_slots, int bytes);
#endif

118
04-map/server/src/main.c Normal file
View File

@ -0,0 +1,118 @@
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <signal.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_net.h>
#include <SDL2/SDL_error.h>
#include "defs.h"
#include "structs.h"
#include "hashmap.h"
#define DEBUG 0x0010
#define PORT 9080
#define MAP_WIDTH 100
#define MAP_HEIGHT 100
struct connection **connections_map;
int connections_map_size = 0;
int connections_count = 0;
int handle_connection(void *data) {
struct connection *connection_data = (struct connection *) data;
struct map *new_map = generate_map(MAP_WIDTH, MAP_HEIGHT);
if (new_map == NULL) {
fprintf(stderr, "Erorr: failed generating map\n");
goto end;
}
SDLNet_TCP_Send(connection_data->socket, new_map->blocks, new_map->width*new_map->height*sizeof(int));
end:
SDLNet_TCP_Close(connection_data->socket);
connections_map[connection_data->id] = NULL;
connections_count--;
free(data);
return 0;
}
void catch_alarm(int sig) {
fprintf(stdout, "Notice: force stopping server...\n");
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[]) {
signal(SIGINT, catch_alarm);
srand(time(NULL));
if (SDL_Init(SDL_INIT_VIDEO) != 0) {
fprintf(stderr, "Error: could not initialize SDL\n%s\n", SDL_GetError());
return -1;
}
if (SDLNet_Init() != 0) {
fprintf(stderr, "Error: could not initialize SDL net\n%s\n", SDL_GetError());
return -1;
}
IPaddress ip;
if (SDLNet_ResolveHost(&ip, NULL, PORT) == -1) {
fprintf(stderr, "Error: failed resolving host \n%s\n", SDL_GetError());
return -1;
}
TCPsocket server = SDLNet_TCP_Open(&ip);
if (!server) {
fprintf(stderr, "Error: failed opening socket at %d\n%s\n", PORT, SDL_GetError());
return -1;
}
for (;;) {
TCPsocket client = SDLNet_TCP_Accept(server);
if (!client) {
SDL_Delay(100);
continue;
}
fprintf(stdout, "Notice: accepted a connection from client!\n");
int new_connection_slot = allocate_value((void ***) &connections_map, &connections_map_size, &connections_count, sizeof(struct connection));
if (new_connection_slot == MEMERR) {
fprintf(stderr, "MEMERR: failed allocating memory for new connection\n");
return STDERR;
}
struct connection *new_connection = connections_map[new_connection_slot];
new_connection->id = new_connection_slot;
new_connection->socket = client;
if (DEBUG & PLAYER_DEBUG)
fprintf(stdout, "Created connection with id '%d'\n", new_connection->id);
SDL_CreateThread(handle_connection, "client", new_connection);
}
return 0;
}

29
04-map/server/src/map.c Normal file
View File

@ -0,0 +1,29 @@
#include <stdlib.h>
#include "structs.h"
struct map *generate_map(int width, int height) {
struct map *new_map = (struct map *) calloc(1, sizeof(struct map));
if (new_map == NULL)
return NULL;
int *map_blocks = (int *) calloc(width*height, sizeof(int));
if (map_blocks == NULL)
return NULL;
new_map->width = width;
new_map->height = height;
new_map->blocks = map_blocks;
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
double scale = ((double) rand() / RAND_MAX);
int block = scale * 3;
int index = (y*width)+x;
map_blocks[index] = block;
}
}
fprintf(stdout, "Value of first block -> %d\n", map_blocks[0]);
return new_map;
}

View File

@ -5,19 +5,15 @@
struct connection {
int id;
int obj_id;
TCPsocket socket;
};
struct object {
int id;
int x;
int y;
int colliding;
int force;
uint8_t state;
struct map {
int width;
int height;
int *blocks;
};
struct map *generate_map(int width, int height);
#endif