summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDobbertin, Niclas <niclas.dobbertin@gmx.de>2023-06-24 23:04:23 +0200
committerDobbertin, Niclas <niclas.dobbertin@gmx.de>2023-06-24 23:04:23 +0200
commit3422a87bdb087b6d927203e266beb71027779dbe (patch)
tree3d8381b27c94529c45ad7287695befe3eaa241c5
init codeHEADmaster
-rw-r--r--Makefile27
-rw-r--r--characters.h20
-rw-r--r--config.mk14
-rw-r--r--data/characters.txt0
-rw-r--r--input.c61
-rw-r--r--input.h22
-rw-r--r--main.c268
-rw-r--r--main.h11
-rw-r--r--player.c54
-rw-r--r--player.h26
-rw-r--r--render.h6
-rw-r--r--resources/OpenSans-Regular.ttfbin0 -> 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
diff --git a/input.c b/input.c
new file mode 100644
index 0000000..5318279
--- /dev/null
+++ b/input.c
@@ -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]); */
+/* } */
diff --git a/input.h b/input.h
new file mode 100644
index 0000000..716f48c
--- /dev/null
+++ b/input.h
@@ -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_
diff --git a/main.c b/main.c
new file mode 100644
index 0000000..53afb18
--- /dev/null
+++ b/main.c
@@ -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());
+}
diff --git a/main.h b/main.h
new file mode 100644
index 0000000..0a7ca75
--- /dev/null
+++ b/main.h
@@ -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
new file mode 100644
index 0000000..2e31d02
--- /dev/null
+++ b/resources/OpenSans-Regular.ttf
Binary files differ