diff options
-rw-r--r-- | Makefile | 27 | ||||
-rw-r--r-- | characters.h | 20 | ||||
-rw-r--r-- | config.mk | 14 | ||||
-rw-r--r-- | data/characters.txt | 0 | ||||
-rw-r--r-- | input.c | 61 | ||||
-rw-r--r-- | input.h | 22 | ||||
-rw-r--r-- | main.c | 268 | ||||
-rw-r--r-- | main.h | 11 | ||||
-rw-r--r-- | player.c | 54 | ||||
-rw-r--r-- | player.h | 26 | ||||
-rw-r--r-- | render.h | 6 | ||||
-rw-r--r-- | resources/OpenSans-Regular.ttf | bin | 0 -> 217276 bytes |
12 files changed, 509 insertions, 0 deletions
diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..abf6b40 --- /dev/null +++ b/Makefile @@ -0,0 +1,27 @@ +# mouse move + +include config.mk + +SRC = main.c player.c input.c +OBJ = ${SRC:.c=.o} + +all: main + +.c.o: + ${CC} -c ${CFLAGS} $< + +# ${OBJ}: + +main: ${OBJ} + ${CC} -o $@ ${OBJ} ${LDFLAGS} + +clean: + rm -f main ${OBJ} + +debug: clean debug_compile + +debug_compile: CFLAGS += -g -pg + # LDFLAGS += -g -pg +debug_compile: main + +.PHONY: all clean debug diff --git a/characters.h b/characters.h new file mode 100644 index 0000000..ba1ffb2 --- /dev/null +++ b/characters.h @@ -0,0 +1,20 @@ +#ifndef CHARACTERS_H_ +#define CHARACTERS_H_ + +#include "player.h" + +const struct Player TEMPLATE_1 = { + 100, // pos x + 100, // pos y + 100, // vel x + 100, // vel y + 0, // accel x + 0, // accel y + 100, // max vel x + 100, // max vel y + 100, // hp + 0, // geometry + 0 // geometry len +}; + +#endif // CHARACTERS_H_ diff --git a/config.mk b/config.mk new file mode 100644 index 0000000..f219d91 --- /dev/null +++ b/config.mk @@ -0,0 +1,14 @@ +# Initial Version +VERSION = 0.1 + +PKGS = sdl2 SDL2_gfx + +INCS = `pkg-config --cflags $(PKGS)` +LIBS = `pkg-config --libs $(PKGS)` -lSDL2_ttf -lm + +# flags +CFLAGS = -pedantic -Wall -Wextra -Werror -O3 ${INCS} +LDFLAGS = ${LIBS} + +# compiler and linker +CC = gcc diff --git a/data/characters.txt b/data/characters.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/data/characters.txt @@ -0,0 +1,61 @@ +#include "input.h" + +#include <stdio.h> + +void handleKeyboardEvent(int *action_states, SDL_Event event) +{ + if (event.key.repeat != 0) + return; + switch (event.type) { + case SDL_QUIT: + action_states[ACTION_QUIT] = 1; + break; + case SDL_KEYDOWN: + switch (event.key.keysym.sym) { + case SDLK_q: + action_states[ACTION_QUIT] = 1; + break; + case SDLK_w: + action_states[ACTION_MOVE_UP] = 1; + break; + case SDLK_s: + action_states[ACTION_MOVE_DOWN] = 1; + break; + case SDLK_a: + action_states[ACTION_MOVE_LEFT] = 1; + break; + case SDLK_d: + action_states[ACTION_MOVE_RIGHT] = 1; + break; + } + break; + case SDL_KEYUP: + switch (event.key.keysym.sym) { + case SDLK_w: + action_states[ACTION_MOVE_UP] = 0; + break; + case SDLK_s: + action_states[ACTION_MOVE_DOWN] = 0; + break; + case SDLK_a: + action_states[ACTION_MOVE_LEFT] = 0; + break; + case SDLK_d: + action_states[ACTION_MOVE_RIGHT] = 0; + break; + } + break; + } +} + +/* int action_status(enum Actions action) */ +/* { */ +/* return actions_state[action]; */ +/* } */ + +/* void action_toggle(enum Actions action) */ +/* { */ +/* printf("%d", actions_state[action]); */ +/* actions_state[action] = 1; */ +/* printf("%d", actions_state[action]); */ +/* } */ @@ -0,0 +1,22 @@ +#ifndef INPUT_H_ +#define INPUT_H_ + +#include <SDL2/SDL.h> + +enum Actions { + ACTION_QUIT, + ACTION_MOVE_UP, + ACTION_MOVE_DOWN, + ACTION_MOVE_LEFT, + ACTION_MOVE_RIGHT, + + ACTION_STATE_COUNT +}; + +void handleKeyboardEvent(int *action_states, SDL_Event event); + +/* int action_status(enum Actions action); */ + +/* void action_toggle(enum Actions action); */ + +#endif // INPUT_H_ @@ -0,0 +1,268 @@ +#include "main.h" +#include <SDL2/SDL_rect.h> +#include <SDL2/SDL_timer.h> +#include <stdio.h> +#include <SDL2/SDL.h> +#include <SDL2/SDL_ttf.h> + +#include "player.h" +#include "input.h" +#include "characters.h" + +#define DEFAULT_SCREEN_WIDTH 800 +#define DEFAULT_SCREEN_HEIGHT 600 + +#define SCREEN_FPS 60 +#define DELTA_TIME_SEC (1.0f / SCREEN_FPS) +#define DELTA_TIME_MS ((Uint32)floorf(DELTA_TIME_SEC * 1000.0f)) +#define SIMULATION_STEP_MS 10 + +#define RENDER_ENABLED 1 +#define SHOW_FPS 1 + +int main() +{ + SDL_Window *window; + SDL_Renderer *renderer; + /* SDL_Texture *fps_texture; */ + TTF_Font *Sans; + + if (SDL_Init(SDL_INIT_VIDEO) < 0) { + fprintf(stderr, "SDL ERROR: %s\n", SDL_GetError()); + exit(1); + } + window = + SDL_CreateWindow("Space Battle", 100, 100, DEFAULT_SCREEN_WIDTH, + DEFAULT_SCREEN_HEIGHT, SDL_WINDOW_RESIZABLE); + + if (window == NULL) { + fprintf(stderr, "COULD NOT CREATE SDL WINDOW: %s\n", + SDL_GetError()); + exit(1); + } + + if (RENDER_ENABLED) { + renderer = SDL_CreateRenderer(window, -1, + SDL_RENDERER_ACCELERATED); + + if (renderer == NULL) { + fprintf(stderr, "COULD NOT CREATE SDL RENDERER: %s\n", + SDL_GetError()); + exit(1); + } + TTF_Init(); + Sans = TTF_OpenFont("resources/OpenSans-Regular.ttf", 12); + if (!Sans) { + fprintf(stderr, "COULD NOT OPEN FONT: %s\n", + SDL_GetError()); + exit(1); + } + } + + // TODO: outsource shape definitions + SDL_Vertex vert[3]; + + // center + vert[0].position.x = 400; + vert[0].position.y = 0; + vert[0].color.r = 255; + vert[0].color.g = 0; + vert[0].color.b = 0; + vert[0].color.a = 255; + + // left + vert[1].position.x = 200; + vert[1].position.y = 450; + vert[1].color.r = 0; + vert[1].color.g = 0; + vert[1].color.b = 255; + vert[1].color.a = 255; + + // right + vert[2].position.x = 600; + vert[2].position.y = 450; + vert[2].color.r = 0; + vert[2].color.g = 255; + vert[2].color.b = 0; + vert[2].color.a = 255; + + struct Player player_1 = TEMPLATE_1; + player_1.geometry = vert; + player_1.geometry_len = 3; + + + int action_states[ACTION_STATE_COUNT]; + for (int i = 0; i < ACTION_STATE_COUNT; i++) { + action_states[i] = 0; + } + + int win_x = DEFAULT_SCREEN_WIDTH; + int win_y = DEFAULT_SCREEN_HEIGHT; + int quit = 0; + + // based on: + // https://gafferongames.com/post/fix_your_timestep/ + // doesn't include state-interpolation (yet?) + double physics_total_time = 0.0; + const double physics_timestep = 1 / 60.0; + const double render_timestep = 1 / 60.0; + double current_time = current_sdl_time_in_seconds(); + double physics_time_accumulator = 0.0; + double render_time_accumulator = 0.0; + + float fps = 0.0f; + char fps_text[123] = "start"; + + while (!quit) { + double new_time = current_sdl_time_in_seconds(); + double frame_time = new_time - current_time; + current_time = new_time; + + physics_time_accumulator += frame_time; + render_time_accumulator += frame_time; + + while (physics_time_accumulator >= physics_timestep) { + SDL_Event event; + while (!quit && SDL_PollEvent(&event)) { + /* // e.g. https://stackoverflow.com/a/1252996 */ + handleKeyboardEvent(action_states, event); + + if (action_states[ACTION_QUIT]) + quit = 1; + } + + execute_actions(&player_1, action_states, + physics_timestep); + /* player_move(&player_1, physics_timestep); */ + + physics_time_accumulator -= physics_timestep; + physics_total_time += physics_timestep; + } + + if (RENDER_ENABLED && + render_time_accumulator >= render_timestep) { + /* SDL_SetRenderDrawColor(renderer, HEX_COLOR(BACKGROUND_COLOR)); */ + SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0); + + SDL_RenderClear(renderer); + + /* render_my_stuff(renderer); */ + /* hexagon_draw(&hex, renderer); */ + + SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255); + + /* SDL_Rect box = { player_1.pos_x, player_1.pos_y, */ + /* player_1.pos_x + 200, */ + /* player_1.pos_y + 200 }; */ + /* SDL_RenderFillRect(renderer, &box); */ + + /* SDL_RenderDrawLine(renderer, 0, 0, 1000, 1000); */ + + SDL_RenderGeometry(renderer, NULL, player_1.geometry, + player_1.geometry_len, NULL, 0); + + SDL_GetWindowSize(window, &win_x, &win_y); + + if (SHOW_FPS) { + fps = round(1.0f / render_time_accumulator); + sprintf(fps_text, "FPS:%.0f", fps); + + SDL_Rect fps_pos = { 0, 0, 0, 0 }; + render_text(fps_text, fps_pos, Sans, renderer); + + // show action states + if (action_states[ACTION_MOVE_UP]) { + SDL_Rect up_text = { 100, 600, 120, + 620 }; + render_text("UP", up_text, Sans, + renderer); + } + if (action_states[ACTION_MOVE_DOWN]) { + SDL_Rect up_text = { 100, 620, 120, + 640 }; + render_text("DOWN", up_text, Sans, + renderer); + } + if (action_states[ACTION_MOVE_LEFT]) { + SDL_Rect up_text = { 60, 620, 80, 640 }; + render_text("LEFT", up_text, Sans, + renderer); + } + if (action_states[ACTION_MOVE_RIGHT]) { + SDL_Rect up_text = { 140, 620, 160, + 640 }; + render_text("RIGHT", up_text, Sans, + renderer); + } + + // show player attributes + char x_speed_text[123]; + sprintf(x_speed_text, "x-speed: %f", + player_1.vel_x); + SDL_Rect x_speed_text_pos = { 900, 900, 910, + 910 }; + render_text(x_speed_text, x_speed_text_pos, + Sans, renderer); + + char y_speed_text[123]; + sprintf(y_speed_text, "y-speed: %f", + player_1.vel_y); + SDL_Rect y_speed_text_pos = { 900, 920, 910, + 930 }; + render_text(y_speed_text, y_speed_text_pos, + Sans, renderer); + } + + render_time_accumulator = 0; + SDL_RenderPresent(renderer); + } + } + + if (RENDER_ENABLED) { + TTF_CloseFont(Sans); + TTF_Quit(); + + SDL_DestroyRenderer(renderer); + SDL_DestroyWindow(window); + } + SDL_Quit(); + return 0; +} + +void execute_actions(struct Player *player, int *action_states, float delta) +{ + if (action_states[ACTION_MOVE_UP]) { + player_move(player, UP, delta); + } + if (action_states[ACTION_MOVE_DOWN]) { + player_move(player, DOWN, delta); + } + if (action_states[ACTION_MOVE_LEFT]) { + player_move(player, LEFT, delta); + } + if (action_states[ACTION_MOVE_RIGHT]) { + player_move(player, RIGHT, delta); + } +} + +void render_text(char *text, SDL_Rect dest, TTF_Font *Sans, + SDL_Renderer *renderer) +{ + SDL_Color fps_color = { 0, 255, 0, 255 }; + SDL_Surface *surf = TTF_RenderText_Solid(Sans, text, fps_color); + + dest.w = surf->w; + dest.h = surf->h; + + SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer, surf); + SDL_RenderCopy(renderer, texture, NULL, &dest); + + SDL_DestroyTexture(texture); + SDL_FreeSurface(surf); +} + +double current_sdl_time_in_seconds() +{ + return ((double)SDL_GetPerformanceCounter() / + (double)SDL_GetPerformanceFrequency()); +} @@ -0,0 +1,11 @@ +#ifndef MAIN_H_ +#define MAIN_H_ + +#include "player.h" +#include <SDL2/SDL_ttf.h> + +void execute_actions(struct Player *player, int *action_states, float delta); +void render_text(char *text, SDL_Rect dest, TTF_Font *Sans, SDL_Renderer *renderer); +double current_sdl_time_in_seconds(); + +#endif // MAIN_H_ diff --git a/player.c b/player.c new file mode 100644 index 0000000..22e22f0 --- /dev/null +++ b/player.c @@ -0,0 +1,54 @@ +#include "player.h" +#include <math.h> + +#include <stdio.h> + +void player_accelerate(struct Player *player, int dir_x, int dir_y, float delta) +{ + double vel_x = player->vel_x + dir_x * delta * player->accel_x; + double vel_y = player->vel_y + dir_y * delta * player->accel_y; + + if (vel_x > player->max_vel_x) + vel_x = player->max_vel_x; + if (vel_x < -player->max_vel_x) + vel_x = -player->max_vel_x; + + if (vel_y > player->max_vel_y) + vel_y = player->max_vel_y; + if (vel_y < -player->max_vel_y) + vel_y = -player->max_vel_y; + + player->vel_x = vel_x; + player->vel_y = vel_y; + +} + +// TODO: field boundaries +void player_move(struct Player *player, enum Direction direction, float delta) +{ + if (direction == UP) { + player->pos_y -= player->vel_y * delta; + for (int i = 0; i < player->geometry_len; i++) { + player->geometry[i].position.y -= player->vel_y * delta; + } + } + if (direction == DOWN) { + player->pos_y += player->vel_y * delta; + for (int i = 0; i < player->geometry_len; i++) { + player->geometry[i].position.y += player->vel_y * delta; + } + } + if (direction == LEFT) { + player->pos_x -= player->vel_x * delta; + for (int i = 0; i < player->geometry_len; i++) { + player->geometry[i].position.x -= player->vel_x * delta; + } + } + if (direction == RIGHT) { + player->pos_x += player->vel_x * delta; + for (int i = 0; i < player->geometry_len; i++) { + player->geometry[i].position.x += player->vel_x * delta; + } + } + +} diff --git a/player.h b/player.h new file mode 100644 index 0000000..b250d0f --- /dev/null +++ b/player.h @@ -0,0 +1,26 @@ +#ifndef PLAYER_H_ +#define PLAYER_H_ + +#include <SDL2/SDL.h> + +struct Player { + float pos_x, pos_y; + double vel_x, vel_y; + int accel_x, accel_y; + int max_vel_x, max_vel_y; + int hp; + SDL_Vertex *geometry; + int geometry_len; +}; + +enum Direction { + UP, + DOWN, + LEFT, + RIGHT, +}; + +void player_accelerate(struct Player *player, int x, int y, float delta); +void player_move(struct Player *player, enum Direction direction, float delta); + +#endif // PLAYER_H_ diff --git a/render.h b/render.h new file mode 100644 index 0000000..e84cdfa --- /dev/null +++ b/render.h @@ -0,0 +1,6 @@ +#ifndef RENDER_H_ +#define RENDER_H_ + +void render_player(); + +#endif // RENDER_H_ diff --git a/resources/OpenSans-Regular.ttf b/resources/OpenSans-Regular.ttf Binary files differnew file mode 100644 index 0000000..2e31d02 --- /dev/null +++ b/resources/OpenSans-Regular.ttf |