This commit is contained in:
Alexandre 2025-05-13 22:06:00 +02:00
commit 6640b9d402
46 changed files with 1148 additions and 0 deletions

11
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,11 @@
{
"files.associations": {
"sdl.h": "c",
"assert.h": "c",
"display.h": "c",
"structure.h": "c",
"limits": "c",
"base.h": "c",
"cars.h": "c"
}
}

33
Makefile Normal file
View File

@ -0,0 +1,33 @@
CC = gcc
FLAGS = -Wall -Wextra -g
LFLAGS = -lSDL2 -lSDL2_image -lm
all: bin/back
test: bin/back
bin/back
mem: bin/back
valgrind --leak-check=full ./bin/back
bin/back: obj/main.o obj/display.o obj/base.o obj/cars.o obj/rooms.o
mkdir -p bin
$(CC) $(FLAGS) $^ $(LFLAGS) -o $@
obj/%.o: src/%.c
@mkdir -p obj
$(CC) -o $@ -c $(FLAGS) $<
obj/main.o: src/main.c
obj/display.o: src/display.c
obj/base.o: src/base.c
obj/cars.o: src/cars.c
obj/rooms.o: src/rooms.c
.PHONY: clean mrproper
clean:
rm -rf obj/
mrproper: clean
rm -rf bin/

152
README.md Normal file
View File

@ -0,0 +1,152 @@
# --| Controls |--
- in-game:
**WASD/ZQSD** (depends on keyboard, usually WASD) - movement
**QE/AE** (depends on keyboard, usually QE)- horizontal camera rotation
**PM** - vertical camera rotation
**ESC** - exit application
- creative tools:
**Y** select level destination
**R** warp to targetted level (resets player's position)
**T** warp to targetted level (no update top player's position)
- while in menus:
<!> when editing a value : **A** (add), **S** (subtract), **M** (multiply), **D** (divide), **ENTER/SPACE** (proceed)
# --| Mods (in case you find it easy) |--
*Hidden* (HD) : makes the terrain blink to be totally invisible sometimes
*HardRock* (HR) : multiplies damage taken, enables fall damage and kills you upon falling into the void
*DoubleTime* (DT) : makes everything faster
*SuddenDeath* (SD) : sets your HP at 1 and disables healing
*Flashlight* (FL) : drastically lowers your view distance
*Speedy* (SP) : makes you lose HP over time
*Flip* (FP) : flips the screen over the Y axis, inverting some directions
# --| Syntax for level files |--
1) **General rules**
. each file must be named "room_k" where k is a positive integer
if "room_k" exists then all "room_u" where 0 <= u < k exists
. you can add text at the end of each line as comments
but *do not use caps*, *this might confuse the parser*
. at the end of each file, the weight of the room is required (can be any positive integer)
if **there is only one file (==> its name is room_0) AND weight is 0**, the room will only generate at the central chunk (any other will be NULL)
use this if you want to create parkour levels, puzzles...
else, **make sure the total weight (the sum of all) is not equal to 0** *(you may end up with a floating point exception)*
. no matter what, room_0 will **always** generate at chunk (0, 0)
2) **Data structure**
below is a detailled list for all block types ;
each block type (Blocks, Teleporters, Entities) must have the corresponding word directly above it
not all three keywords have to be written
[] is mandatory data
{} is optionnal data
*Data-specific structure :*
```
blocks:
[x, y, z, w, h, d, rhz, rvt, r, g, b]
teleporters:
[x, y, z, w, h, d, rhz, rvt, r, g, b, dest_chx, dest_chy]
entities:
[x, y, z, w, h, d, rhz, rvt, r, g, b, hp, damage, entityType ..]
|> if entityType >= 4, use 1 for HP and 0 for damage <|
|> *Entity types are :* <|
-> 0 (coin) -> HP equals the coin's value
-> 1 (non-moving explosive)
-> 2 (damaging firebar/spinning platform (set damage to 0))
[.. hz_rps, vt_rps, x_offset, y_offset, z_offset, dps] with
{hz,vt}_rps = double
hz0, vt_0 = double
{x,y,z}_offset = double // if all is 0.0, the solid will rotate according to its center of mass, this shifts that center
dps = int[>0]
-> 3 (shooting (towards player), maybe moving explosive)
[.. proj_speed, shoot_speed, shot_freq, shot_ttl] with
{all} = double[>= 0.0]
-> 4 (moving platform)
[.. amplitude_x, amplitude_y, amplitude_z, mult, divd, phase, {initialState, triggerButton}] with
amplitude_{x,y,z} = double[>= 0.0]
{mult,divd} = int
{phase} = int[0, 360]
{..} = int(>=0)
-> 5 (linear moving platform)
[.. amplitude_x, amplitude_y, amplitude_z, speed_x, speed_y, speed_z, {initialState, triggerButton}] with
amplitude_{x,y,z} = double[>= 0.0]
speed_{x,y,z} = double
{..} = int(>=0)
-> 6 (text box)
[.. text, tred, tgreen, tblue] with
text = {char*}
-> 7 (warp text box)
[.. dest_folder, room_count, text, tred, tgreen, tblue] with
{dest_folder,text} = {char*} (length <= 50)
{r,g,b} = int[0-256]
-> 8 (lock box)
[.. cost, doPay, tred, tgreen, tblue] with
cost = int[> 0] (0 breaks)
doPay = {0, 1} (bool)
-> 9 (beat block)
[.. ontime, offtime, start] with
{ontime,offtime} = double[>0.0]
start = {0,1}
-> 10 (movable block)
[.. friction, mass] with
friction = double[>0.0]
mass = double[>0.0] (in kg)
-> 11 (button trigger)
[.. freq, dtime] with
freq = int[0 - 15]
dtime = double([>0.0] for time-limited press, or use -1.0 if no deactivation)
-> 12 (button block)
[.. freq, defaultState] with
freq = int[0 - 15]
defaultState = {0, 1}
-> 13 (math block)
[.. defaultState, timeOff] with
defaultState = {0, 1}
dtime = double([>0.0] for time-limited press, or use -1.0 if no deactivation)
-> 14 (movable object-related button)
[.. freq] with
freq = int[0 - 15]
-> 15 (gun)
[.. vx, vy, vz, ax, ay, az, cooldown, phase, ttl, dmg, psize_x, psize_y, psize_z] with
all\{dmg} = double (cooldown > 0.0 and ttl > 0.0 and psize_{x,y,z} > 0.0)
dmg = int (>0)
-> 16 (type 1 entity)
[.. speed, jump_height, dmg, kbPlayer, {buttonActivation}] with
all\{dmg} = double[>=0.0]
dmg = int (>=0)
buttonActivation = int[0-16]
-> 17 (type 2 entity)
[.. speed, jump_height, dmg, kbPlayer, kbEntity, {buttonActivation}] with
all\{dmg} = double[>=0.0]
dmg = int (>=0)
buttonActivation = int[0-16]
```

BIN
bin/back Executable file

Binary file not shown.

0
code Normal file
View File

BIN
obj/base.o Normal file

Binary file not shown.

BIN
obj/cars.o Normal file

Binary file not shown.

BIN
obj/display.o Normal file

Binary file not shown.

BIN
obj/main.o Normal file

Binary file not shown.

BIN
obj/rooms.o Normal file

Binary file not shown.

BIN
res/arrows.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 244 KiB

BIN
res/brick.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

BIN
res/brick.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

BIN
res/button_off.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

BIN
res/button_on.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 312 KiB

BIN
res/coin2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 127 KiB

BIN
res/container.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 181 KiB

BIN
res/exclamation_block.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

BIN
res/gateway.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
res/lock.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

BIN
res/lock.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
res/minecraft_lava.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

BIN
res/money.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

BIN
res/pi.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

BIN
res/pi.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

BIN
res/question_block.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

BIN
res/rotation.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

BIN
res/sq_dotted.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

BIN
res/sq_full.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

BIN
res/steel.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

BIN
res/tnt.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

BIN
res/white.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

72
src/base.c Normal file
View File

@ -0,0 +1,72 @@
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <math.h>
#include <stdbool.h>
#include <unistd.h>
#include <termios.h>
#include <limits.h>
#include <time.h>
#include <sys/time.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include "structure.h"
#include "cars.h"
#include "base.h"
int currentTurn;
int nPlayers;
carData* players;
void init_all(int nPl) {
nPlayers = nPl;
currentTurn = 0;
players = malloc(sizeof(carData)*nPlayers);
for(int p = 0; p < nPlayers; p++) {
players[p].curChunk = start;
players[p].c = init_car("player");
}
}
void destroy_all() {
for(int p = 0; p < nPlayers; p++) {
destroy_car(players[p].c);
}
free(players);
}
int ln_baseN(int n, int b) {
if(n<b) {
return 0;
}
return 1+ln_baseN(n/b, b);
}
int notLN(int n, int b) {
int r = 0;
while(n != 0) {
n = n/b;
r++;
}
return r;
}
int convex_seg(int x1, int x2, double theta) {
return (int)(((1.0f - theta) * x1 + theta * x2));
}
double to_double(int n) {
return (double)n;
}
int pw(int x, int n) {
if (n<0)
return 0;
if (n==0)
return 1;
if (n%2==0)
return pw(x*x, n/2);
return x*pw(x*x, n/2);
}
double distance_pt(int x1, int x2, int y1, int y2) {
return sqrt(to_double(pw(x2 - x1, 2) + pw(y2 - y1, 2)));
}
int max(int a, int b) {return (a>b)?(a):(b);}
int min(int a, int b) {return (a<b)?(a):(b);}

14
src/base.h Normal file
View File

@ -0,0 +1,14 @@
#ifndef BASE_H
#define BASE_H
void init_all(int nP);
void destroy_all();
int ln_baseN(int n, int b);
int notLN(int n, int b);
int convex_seg(int x1, int x2, double theta);
double to_double(int n);
int pw(int x, int n);
double distance_pt(int x1, int x2, int y1, int y2);
#endif

40
src/cars.c Normal file
View File

@ -0,0 +1,40 @@
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <math.h>
#include <stdbool.h>
#include <unistd.h>
#include <termios.h>
#include <limits.h>
#include <time.h>
#include <sys/time.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include "structure.h"
#include "base.h"
#include "cars.h"
car* init_car(const char* name) {
car* res = malloc(sizeof(car));
res->name = "e";
res->itm = NULL;
res->nCoins = 0;
res->pos = (ptf){.fx = 0.0, .fy = 0.0};
res->vel = (ptf){.fx = 0.0, .fy = 0.0};
return res;
}
void move_car(car* c, double x, double y) {
c->pos.fx = x;
c->pos.fy = y;
}
void set_speed_car(car* c, double vx, double vy) {
c->vel.fx = vx;
c->vel.fy = vy;
}
void destroy_car(car* c) {
free(c);
}

10
src/cars.h Normal file
View File

@ -0,0 +1,10 @@
#ifndef CARS_H
#define CARS_H
car* init_car(const char* name);
void destroy_car(car* c);
void move_car(car* c, double x, double y);
void set_speed_car(car* c, double vx, double vy);
#endif

547
src/display.c Normal file
View File

@ -0,0 +1,547 @@
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <math.h>
#include <stdbool.h>
#include <unistd.h>
#include <termios.h>
#include <limits.h>
#include <time.h>
#include <sys/time.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include "structure.h"
#include "base.h"
#include "display.h"
imgs* digits;
imgs* letters;
void updateRenderer(SDL_Renderer* renderer) {
//printf("E");
SDL_RenderPresent(renderer);
}
void resetRenderer(SDL_Renderer* renderer) {
SDL_SetRenderDrawColor(renderer, 128, 128, 128, 255);
SDL_RenderClear(renderer);
}
void drawRectToRenderer(SDL_Renderer* renderer, SDL_Rect* rect, int R, int G, int B, int A) {
SDL_SetRenderDrawColor(renderer, R, G, B, A);
SDL_RenderFillRect(renderer, rect);
}
void placeRectToRenderer(SDL_Renderer* renderer, int X, int Y, int W, int H, int R, int G, int B, int A) {
SDL_Rect rect;
rect.x = X;
rect.y = Y;
rect.w = W;
rect.h = H;
SDL_SetRenderDrawColor(renderer, R, G, B, A);
SDL_RenderFillRect(renderer, &rect);
}
void drawLineWithThicc(SDL_Renderer* renderer, int width, int x1, int x2, int y1, int y2, int R, int G, int B, int A) {
// draws line with width (native SDL cannot do that)
double theta = 0.0;
double seglen = distance_pt(x1, x2, y1, y2);
while(theta < 1.0) {
placeRectToRenderer(renderer, convex_seg(x1, x2, theta)-width/2, convex_seg(y1, y2, theta)-width/2, width, width, R, G, B, A);
theta += 1 / seglen;
}
}
void drawDigitToRenderer(SDL_Renderer* renderer, int digit, int X, int Y, int W, int H) {
if(digit == -727) {
SDL_Rect rect;
rect.x = X;
rect.y = Y;
rect.w = W;
rect.h = H;
SDL_Texture* texture = digits->arr[10];
SDL_RenderCopy(renderer, texture, NULL, &rect);
} else if (!(0 <= digit && digit <= 9)) {
fprintf(stderr, "Illegal digit : '%d'.\n", digit);
exit(1);
} else {
SDL_Rect rect;
rect.x = X;
rect.y = Y;
rect.w = W;
rect.h = H;
SDL_Texture* texture = digits->arr[digit];
SDL_RenderCopy(renderer, texture, NULL, &rect);
}
}
void drawCharToRenderer(SDL_Renderer* renderer, char c, int X, int Y, int W, int H) {
if ((int)c >= 97 && (int)c <= 122) {
SDL_Rect rect;
rect.x = X;
rect.y = Y;
rect.w = W;
rect.h = H;
SDL_Texture* texture = letters->arr[(int)c - 97];
SDL_RenderCopy(renderer, texture, NULL, &rect);
}
}
void drawNumberToRenderer(SDL_Renderer* renderer, int n, int X, int Y, int W, int H, int Woffset) {
if(n == 0) {
drawDigitToRenderer(renderer, 0, X + W, Y, W, H);
} else if(n > 0) {
int toDraw = 0, remaining = n, nIter = notLN(n, 10);
while(nIter != 0) {
toDraw = remaining%10;
remaining = remaining / 10;
drawDigitToRenderer(renderer, toDraw, X + (W-Woffset)*nIter, Y, W, H);
nIter--;
}
} else {
int toDraw = 0, remaining = -n, nIter = notLN(-n, 10);
drawDigitToRenderer(renderer, -727, X, Y, W, H);
while(nIter != 0) {
toDraw = remaining%10;
remaining = remaining / 10;
drawDigitToRenderer(renderer, toDraw, X + (W-Woffset)*nIter, Y, W, H);
nIter--;
}
}
}
void drawStringToRenderer(SDL_Renderer* renderer, char* s, int X, int Y, int W, int H) {
int k = 0;
while(s[k] != '\0') {
drawCharToRenderer(renderer, s[k], X + W*k, Y, W, H);
k += 1;
}
}
void draw7SegDigitToRenderer(SDL_Renderer* renderer, int n, int X, int Y, int W, int H, int thicc, int R, int G, int B, int A) {
if(n == 0) {
placeRectToRenderer(renderer, X+thicc, Y+thicc, W+thicc, thicc, R, G, B, A); // top
placeRectToRenderer(renderer, X+thicc, Y+thicc, thicc, H+thicc, R, G, B, A); // top left
placeRectToRenderer(renderer, X+W+thicc, Y+thicc, thicc, H+thicc, R, G, B, A); // top right
placeRectToRenderer(renderer, X+thicc, Y+H+thicc, thicc, H+thicc, R, G, B, A); // bottom left
placeRectToRenderer(renderer, X+W+thicc, Y+H+thicc, thicc, H+thicc, R, G, B, A); // bottom right
placeRectToRenderer(renderer, X+thicc, Y+2*H+thicc, W+thicc, thicc, R, G, B, A); // bottom
} else if(n == 1) {
placeRectToRenderer(renderer, X+W+thicc, Y+thicc, thicc, H+thicc, R, G, B, A); // top right
placeRectToRenderer(renderer, X+W+thicc, Y+H+thicc, thicc, H+thicc, R, G, B, A); // bottom right
} else if(n == 2) {
placeRectToRenderer(renderer, X+thicc, Y+thicc, W+thicc, thicc, R, G, B, A); // top
placeRectToRenderer(renderer, X+W+thicc, Y+thicc, thicc, H+thicc, R, G, B, A); // top right
placeRectToRenderer(renderer, X+thicc, Y+H+thicc, W+thicc, thicc, R, G, B, A); // mid
placeRectToRenderer(renderer, X+thicc, Y+H+thicc, thicc, H+thicc, R, G, B, A); // bottom left
placeRectToRenderer(renderer, X+thicc, Y+2*H+thicc, W+thicc, thicc, R, G, B, A); // bottom
} else if(n == 3) {
placeRectToRenderer(renderer, X+thicc, Y+thicc, W+thicc, thicc, R, G, B, A); // top
placeRectToRenderer(renderer, X+W+thicc, Y+thicc, thicc, H+thicc, R, G, B, A); // top right
placeRectToRenderer(renderer, X+thicc, Y+H+thicc, W+thicc, thicc, R, G, B, A); // mid
placeRectToRenderer(renderer, X+W+thicc, Y+H+thicc, thicc, H+thicc, R, G, B, A); // bottom right
placeRectToRenderer(renderer, X+thicc, Y+2*H+thicc, W+thicc, thicc, R, G, B, A); // bottom
} else if(n == 4) {
placeRectToRenderer(renderer, X+thicc, Y+thicc, thicc, H+thicc, R, G, B, A); // top left
placeRectToRenderer(renderer, X+W+thicc, Y+thicc, thicc, H+thicc, R, G, B, A); // top right
placeRectToRenderer(renderer, X+thicc, Y+H+thicc, W+thicc, thicc, R, G, B, A); // mid
placeRectToRenderer(renderer, X+W+thicc, Y+H+thicc, thicc, H+thicc, R, G, B, A); // bottom right
} else if(n == 5) {
placeRectToRenderer(renderer, X+thicc, Y+thicc, W+thicc, thicc, R, G, B, A); // top
placeRectToRenderer(renderer, X+thicc, Y+thicc, thicc, H+thicc, R, G, B, A); // top left
placeRectToRenderer(renderer, X+thicc, Y+H+thicc, W+thicc, thicc, R, G, B, A); // mid
placeRectToRenderer(renderer, X+W+thicc, Y+H+thicc, thicc, H+thicc, R, G, B, A); // bottom right
placeRectToRenderer(renderer, X+thicc, Y+2*H+thicc, W+thicc, thicc, R, G, B, A); // bottom
} else if(n == 6) {
placeRectToRenderer(renderer, X+thicc, Y+thicc, W+thicc, thicc, R, G, B, A); // top
placeRectToRenderer(renderer, X+thicc, Y+thicc, thicc, H+thicc, R, G, B, A); // top left
placeRectToRenderer(renderer, X+thicc, Y+H+thicc, W+thicc, thicc, R, G, B, A); // mid
placeRectToRenderer(renderer, X+thicc, Y+H+thicc, thicc, H+thicc, R, G, B, A); // bottom left
placeRectToRenderer(renderer, X+W+thicc, Y+H+thicc, thicc, H+thicc, R, G, B, A); // bottom right
placeRectToRenderer(renderer, X+thicc, Y+2*H+thicc, W+thicc, thicc, R, G, B, A); // bottom
} else if(n == 7) {
placeRectToRenderer(renderer, X+thicc, Y+thicc, W+thicc, thicc, R, G, B, A); // top
placeRectToRenderer(renderer, X+thicc, Y+thicc, thicc, H+thicc, R, G, B, A); // top left
placeRectToRenderer(renderer, X+W+thicc, Y+thicc, thicc, H+thicc, R, G, B, A); // top right
placeRectToRenderer(renderer, X+W+thicc, Y+H+thicc, thicc, H+thicc, R, G, B, A); // bottom right
} else if(n == 8) {
placeRectToRenderer(renderer, X+thicc, Y+thicc, W+thicc, thicc, R, G, B, A); // top
placeRectToRenderer(renderer, X+thicc, Y+thicc, thicc, H+thicc, R, G, B, A); // top left
placeRectToRenderer(renderer, X+W+thicc, Y+thicc, thicc, H+thicc, R, G, B, A); // top right
placeRectToRenderer(renderer, X+thicc, Y+H+thicc, W+thicc, thicc, R, G, B, A); // mid
placeRectToRenderer(renderer, X+thicc, Y+H+thicc, thicc, H+thicc, R, G, B, A); // bottom left
placeRectToRenderer(renderer, X+W+thicc, Y+H+thicc, thicc, H+thicc, R, G, B, A); // bottom right
placeRectToRenderer(renderer, X+thicc, Y+2*H+thicc, W+thicc, thicc, R, G, B, A); // bottom
} else if(n == 9) {
placeRectToRenderer(renderer, X+thicc, Y+thicc, W+thicc, thicc, R, G, B, A); // top
placeRectToRenderer(renderer, X+thicc, Y+thicc, thicc, H+thicc, R, G, B, A); // top left
placeRectToRenderer(renderer, X+W+thicc, Y+thicc, thicc, H+thicc, R, G, B, A); // top right
placeRectToRenderer(renderer, X+thicc, Y+H+thicc, W+thicc, thicc, R, G, B, A); // mid
placeRectToRenderer(renderer, X+W+thicc, Y+H+thicc, thicc, H+thicc, R, G, B, A); // bottom right
placeRectToRenderer(renderer, X+thicc, Y+2*H+thicc, W+thicc, thicc, R, G, B, A); // bottom
}
}
// H = size of ont segment (therefore the actual size of the number is W x 2H)
// side is -1 (alignedLeft), 0 (centered) or 1 (alignedRight)
// dot if for placing a dot (for decimals) at a specified place (enter -1 if none)
void draw7SegNumberToRenderer(SDL_Renderer* renderer, int n, int X, int Y, int W, int H, int thicc, int R, int G, int B, int A, int side, int dot) {
int nlen = 1+ln_baseN(n, 10);
int incrX = W+3*thicc;
int curX = X +(side==0)*(incrX*(nlen)/2-incrX) +(side==-1)*incrX*(nlen-1);
int curN = n;
int doot = (dot==-1)?(nlen+1):(nlen-(dot-1));
while(nlen > 0) {
draw7SegDigitToRenderer(renderer, curN%10, curX, Y, W, H, thicc, R, G, B, A);
curX -= incrX;
if(nlen == doot) {
placeRectToRenderer(renderer, curX-2*thicc+incrX, Y+2*H, 2*thicc, 2*thicc, R, G, B, A);
curX -= 6*thicc;
}
curN /= 10;
nlen -= 1;
}
}
//---------------------------------------------------------------------------------------------------------------------//
// circle functions by @Gumichan01 at https://gist.github.com/Gumichan01/332c26f6197a432db91cc4327fcabb1c (not native) //
//---------------------------------------------------------------------------------------------------------------------//
void SDL_RenderDrawCircle(SDL_Renderer * renderer, int x, int y, int radius) {
int offsetx, offsety, d;
int status;
offsetx = 0;
offsety = radius;
d = radius -1;
status = 0;
while (offsety >= offsetx) {
status += SDL_RenderDrawPoint(renderer, x + offsetx, y + offsety);
status += SDL_RenderDrawPoint(renderer, x + offsety, y + offsetx);
status += SDL_RenderDrawPoint(renderer, x - offsetx, y + offsety);
status += SDL_RenderDrawPoint(renderer, x - offsety, y + offsetx);
status += SDL_RenderDrawPoint(renderer, x + offsetx, y - offsety);
status += SDL_RenderDrawPoint(renderer, x + offsety, y - offsetx);
status += SDL_RenderDrawPoint(renderer, x - offsetx, y - offsety);
status += SDL_RenderDrawPoint(renderer, x - offsety, y - offsetx);
if (status < 0) {
status = -1;
break;
}
if (d >= 2*offsetx) {
d -= 2*offsetx + 1;
offsetx +=1;
} else if (d < 2 * (radius - offsety)) {
d += 2 * offsety - 1;
offsety -= 1;
} else {
d += 2 * (offsety - offsetx - 1);
offsety -= 1;
offsetx += 1;
}
}
//return status;
}
void SDL_RenderFillCircle(SDL_Renderer * renderer, int x, int y, int radius) {
int offsetx, offsety, d;
int status;
offsetx = 0;
offsety = radius;
d = radius -1;
status = 0;
while (offsety >= offsetx) {
status += SDL_RenderDrawLine(renderer, x - offsety, y + offsetx,
x + offsety, y + offsetx);
status += SDL_RenderDrawLine(renderer, x - offsetx, y + offsety,
x + offsetx, y + offsety);
status += SDL_RenderDrawLine(renderer, x - offsetx, y - offsety,
x + offsetx, y - offsety);
status += SDL_RenderDrawLine(renderer, x - offsety, y - offsetx,
x + offsety, y - offsetx);
if (status < 0) {
status = -1;
break;
}
if (d >= 2*offsetx) {
d -= 2*offsetx + 1;
offsetx +=1;
} else if (d < 2 * (radius - offsety)) {
d += 2 * offsety - 1;
offsety -= 1;
} else {
d += 2 * (offsety - offsetx - 1);
offsety -= 1;
offsetx += 1;
}
}
//return status;
}
// ------------------------------------------------------------------------------------------------------------------------- //
void import_digits(SDL_Renderer* renderer) {
imgs* res = malloc(sizeof(imgs));
res->arr = malloc(sizeof(SDL_Texture*)*11);
SDL_Texture* texture;
SDL_Surface* img;
// -------------------------------------------------------- //
img = SDL_LoadBMP("./res/digits/digit-0.bmp");
texture = SDL_CreateTextureFromSurface(renderer, img);
SDL_FreeSurface(img);
res->arr[0] = texture;
// -------------------------------------------------------- //
img = SDL_LoadBMP("./res/digits/digit-1.bmp");
texture = SDL_CreateTextureFromSurface(renderer, img);
SDL_FreeSurface(img);
res->arr[1] = texture;
// -------------------------------------------------------- //
img = SDL_LoadBMP("./res/digits/digit-2.bmp");
texture = SDL_CreateTextureFromSurface(renderer, img);
SDL_FreeSurface(img);
res->arr[2] = texture;
// -------------------------------------------------------- //
img = SDL_LoadBMP("./res/digits/digit-3.bmp");
texture = SDL_CreateTextureFromSurface(renderer, img);
SDL_FreeSurface(img);
res->arr[3] = texture;
// -------------------------------------------------------- //
img = SDL_LoadBMP("./res/digits/digit-4.bmp");
texture = SDL_CreateTextureFromSurface(renderer, img);
SDL_FreeSurface(img);
res->arr[4] = texture;
// -------------------------------------------------------- //
img = SDL_LoadBMP("./res/digits/digit-5.bmp");
texture = SDL_CreateTextureFromSurface(renderer, img);
SDL_FreeSurface(img);
res->arr[5] = texture;
// -------------------------------------------------------- //
img = SDL_LoadBMP("./res/digits/digit-6.bmp");
texture = SDL_CreateTextureFromSurface(renderer, img);
SDL_FreeSurface(img);
res->arr[6] = texture;
// -------------------------------------------------------- //
img = SDL_LoadBMP("./res/digits/digit-7.bmp");
texture = SDL_CreateTextureFromSurface(renderer, img);
SDL_FreeSurface(img);
res->arr[7] = texture;
// -------------------------------------------------------- //
img = SDL_LoadBMP("./res/digits/digit-8.bmp");
texture = SDL_CreateTextureFromSurface(renderer, img);
SDL_FreeSurface(img);
res->arr[8] = texture;
// -------------------------------------------------------- //
img = SDL_LoadBMP("./res/digits/digit-9.bmp");
texture = SDL_CreateTextureFromSurface(renderer, img);
SDL_FreeSurface(img);
res->arr[9] = texture;
// -------------------------------------------------------- //
img = SDL_LoadBMP("./res/digits/sign-minus.bmp");
texture = SDL_CreateTextureFromSurface(renderer, img);
SDL_FreeSurface(img);
res->arr[10] = texture;
res->len = 11;
digits = res;
}
void import_letters(SDL_Renderer* renderer) {
imgs* res = malloc(sizeof(imgs));
res->arr = malloc(sizeof(SDL_Texture*)*26);
SDL_Texture* texture;
SDL_Surface* img;
int cc = 0;
// -------------------------------------------------------- //
img = SDL_LoadBMP("./res/letters/letter-a.bmp");
texture = SDL_CreateTextureFromSurface(renderer, img);
SDL_FreeSurface(img);
res->arr[cc] = texture;
cc += 1;
// -------------------------------------------------------- //
img = SDL_LoadBMP("./res/letters/letter-b.bmp");
texture = SDL_CreateTextureFromSurface(renderer, img);
SDL_FreeSurface(img);
res->arr[cc] = texture;
cc += 1;
// -------------------------------------------------------- //
img = SDL_LoadBMP("./res/letters/letter-c.bmp");
texture = SDL_CreateTextureFromSurface(renderer, img);
SDL_FreeSurface(img);
res->arr[cc] = texture;
cc += 1;
// -------------------------------------------------------- //
img = SDL_LoadBMP("./res/letters/letter-d.bmp");
texture = SDL_CreateTextureFromSurface(renderer, img);
SDL_FreeSurface(img);
res->arr[cc] = texture;
cc += 1;
// -------------------------------------------------------- //
img = SDL_LoadBMP("./res/letters/letter-e.bmp");
texture = SDL_CreateTextureFromSurface(renderer, img);
SDL_FreeSurface(img);
res->arr[cc] = texture;
cc += 1;
// -------------------------------------------------------- //
img = SDL_LoadBMP("./res/letters/letter-f.bmp");
texture = SDL_CreateTextureFromSurface(renderer, img);
SDL_FreeSurface(img);
res->arr[cc] = texture;
cc += 1;
// -------------------------------------------------------- //
img = SDL_LoadBMP("./res/letters/letter-g.bmp");
texture = SDL_CreateTextureFromSurface(renderer, img);
SDL_FreeSurface(img);
res->arr[cc] = texture;
cc += 1;
// -------------------------------------------------------- //
img = SDL_LoadBMP("./res/letters/letter-h.bmp");
texture = SDL_CreateTextureFromSurface(renderer, img);
SDL_FreeSurface(img);
res->arr[cc] = texture;
cc += 1;
// -------------------------------------------------------- //
img = SDL_LoadBMP("./res/letters/letter-i.bmp");
texture = SDL_CreateTextureFromSurface(renderer, img);
SDL_FreeSurface(img);
res->arr[cc] = texture;
cc += 1;
// -------------------------------------------------------- //
img = SDL_LoadBMP("./res/letters/letter-j.bmp");
texture = SDL_CreateTextureFromSurface(renderer, img);
SDL_FreeSurface(img);
res->arr[cc] = texture;
cc += 1;
// -------------------------------------------------------- //
img = SDL_LoadBMP("./res/letters/letter-k.bmp");
texture = SDL_CreateTextureFromSurface(renderer, img);
SDL_FreeSurface(img);
res->arr[cc] = texture;
cc += 1;
// -------------------------------------------------------- //
img = SDL_LoadBMP("./res/letters/letter-l.bmp");
texture = SDL_CreateTextureFromSurface(renderer, img);
SDL_FreeSurface(img);
res->arr[cc] = texture;
cc += 1;
// -------------------------------------------------------- //
img = SDL_LoadBMP("./res/letters/letter-m.bmp");
texture = SDL_CreateTextureFromSurface(renderer, img);
SDL_FreeSurface(img);
res->arr[cc] = texture;
cc += 1;
// -------------------------------------------------------- //
img = SDL_LoadBMP("./res/letters/letter-n.bmp");
texture = SDL_CreateTextureFromSurface(renderer, img);
SDL_FreeSurface(img);
res->arr[cc] = texture;
cc += 1;
// -------------------------------------------------------- //
img = SDL_LoadBMP("./res/letters/letter-o.bmp");
texture = SDL_CreateTextureFromSurface(renderer, img);
SDL_FreeSurface(img);
res->arr[cc] = texture;
cc += 1;
// -------------------------------------------------------- //
img = SDL_LoadBMP("./res/letters/letter-p.bmp");
texture = SDL_CreateTextureFromSurface(renderer, img);
SDL_FreeSurface(img);
res->arr[cc] = texture;
cc += 1;
// -------------------------------------------------------- //
img = SDL_LoadBMP("./res/letters/letter-q.bmp");
texture = SDL_CreateTextureFromSurface(renderer, img);
SDL_FreeSurface(img);
res->arr[cc] = texture;
cc += 1;
// -------------------------------------------------------- //
img = SDL_LoadBMP("./res/letters/letter-r.bmp");
texture = SDL_CreateTextureFromSurface(renderer, img);
SDL_FreeSurface(img);
res->arr[cc] = texture;
cc += 1;
// -------------------------------------------------------- //
img = SDL_LoadBMP("./res/letters/letter-s.bmp");
texture = SDL_CreateTextureFromSurface(renderer, img);
SDL_FreeSurface(img);
res->arr[cc] = texture;
cc += 1;
// -------------------------------------------------------- //
img = SDL_LoadBMP("./res/letters/letter-t.bmp");
texture = SDL_CreateTextureFromSurface(renderer, img);
SDL_FreeSurface(img);
res->arr[cc] = texture;
cc += 1;
// -------------------------------------------------------- //
img = SDL_LoadBMP("./res/letters/letter-u.bmp");
texture = SDL_CreateTextureFromSurface(renderer, img);
SDL_FreeSurface(img);
res->arr[cc] = texture;
cc += 1;
// -------------------------------------------------------- //
img = SDL_LoadBMP("./res/letters/letter-v.bmp");
texture = SDL_CreateTextureFromSurface(renderer, img);
SDL_FreeSurface(img);
res->arr[cc] = texture;
cc += 1;
// -------------------------------------------------------- //
img = SDL_LoadBMP("./res/letters/letter-w.bmp");
texture = SDL_CreateTextureFromSurface(renderer, img);
SDL_FreeSurface(img);
res->arr[cc] = texture;
cc += 1;
// -------------------------------------------------------- //
img = SDL_LoadBMP("./res/letters/letter-x.bmp");
texture = SDL_CreateTextureFromSurface(renderer, img);
SDL_FreeSurface(img);
res->arr[cc] = texture;
cc += 1;
// -------------------------------------------------------- //
img = SDL_LoadBMP("./res/letters/letter-y.bmp");
texture = SDL_CreateTextureFromSurface(renderer, img);
SDL_FreeSurface(img);
res->arr[cc] = texture;
cc += 1;
// -------------------------------------------------------- //
img = SDL_LoadBMP("./res/letters/letter-z.bmp");
texture = SDL_CreateTextureFromSurface(renderer, img);
SDL_FreeSurface(img);
res->arr[cc] = texture;
res->len = 26;
letters = res;
}
void free_digits(imgs* dgts) {
for(int i = 0; i < dgts->len; i++) {
SDL_DestroyTexture(dgts->arr[i]);
}
free(dgts->arr);
free(dgts);
}

22
src/display.h Normal file
View File

@ -0,0 +1,22 @@
#ifndef DISPLAY_H
#define DISPLAY_H
void updateRenderer(SDL_Renderer* renderer);
void resetRenderer(SDL_Renderer* renderer);
void drawRectToRenderer(SDL_Renderer* renderer, SDL_Rect* rect, int R, int G, int B, int A);
void placeRectToRenderer(SDL_Renderer* renderer, int X, int Y, int W, int H, int R, int G, int B, int A);
void drawLineWithThicc(SDL_Renderer* renderer, int width, int x1, int x2, int y1, int y2, int R, int G, int B, int A);
void drawDigitToRenderer(SDL_Renderer* renderer, int digit, int X, int Y, int W, int H);
void drawCharToRenderer(SDL_Renderer* renderer, char c, int X, int Y, int W, int H);
void drawNumberToRenderer(SDL_Renderer* renderer, int n, int X, int Y, int W, int H, int Woffset);
void drawStringToRenderer(SDL_Renderer* renderer, char* s, int X, int Y, int W, int H);
void draw7SegDigitToRenderer(SDL_Renderer* renderer, int n, int X, int Y, int W, int H, int thicc, int R, int G, int B, int A);
void draw7SegNumberToRenderer(SDL_Renderer* renderer, int n, int X, int Y, int W, int H, int thicc, int R, int G, int B, int A, int side, int dot);
void SDL_RenderDrawCircle(SDL_Renderer * renderer, int x, int y, int radius);
void SDL_RenderFillCircle(SDL_Renderer * renderer, int x, int y, int radius);
void import_digits(SDL_Renderer* renderer);
void import_letters(SDL_Renderer* renderer);
void free_digits(imgs* dgts);
#endif

67
src/main.c Normal file
View File

@ -0,0 +1,67 @@
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <math.h>
#include <stdbool.h>
#include <unistd.h>
#include <termios.h>
#include <limits.h>
#include <time.h>
#include <sys/time.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include "structure.h"
#include "base.h"
#include "display.h"
#include "rooms.h"
#include "cars.h"
const int WIDTH = 1000;
const int HEIGHT = 800;
const int N_PLAYERS = 4;
int main() {
srand(time(NULL));
if (SDL_Init(SDL_INIT_EVERYTHING) != 0) {
printf("error initializing SDL: %s\n", SDL_GetError());
}
SDL_Window* win = SDL_CreateWindow("Game",
SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED,
WIDTH, HEIGHT, 0);
Uint32 render_flags = SDL_RENDERER_ACCELERATED;
SDL_Renderer* rend = SDL_CreateRenderer(win, -1, render_flags);
SDL_SetRenderDrawBlendMode(rend, SDL_BLENDMODE_BLEND);
import_letters(rend);
import_digits(rend);
init_rooms();
init_all(N_PLAYERS);
// ---------------------------- //
usleep(1000000);
// ---------------------------- //
free_digits(digits);
free_digits(letters);
destroy_rooms();
SDL_DestroyRenderer(rend);
SDL_DestroyWindow(win);
SDL_Quit();
return 0;
}
/* TODO :
- add display
- add collisions
- add level parsing/generation
- add player input parsing (and some dumb code to test it)
- add function that gives players the necessary data to play
- check seg faults
+ add items
+ add hazards
*/

65
src/rooms.c Normal file
View File

@ -0,0 +1,65 @@
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <math.h>
#include <stdbool.h>
#include <unistd.h>
#include <termios.h>
#include <limits.h>
#include <time.h>
#include <sys/time.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include "structure.h"
#include "base.h"
#include "rooms.h"
chunk* start;
chunk** allRooms;
int nMaxRooms;
int curRoom;
int build_empty_room(int CX, int CY, int w, int h, chunk* north, chunk* east, chunk* south, chunk* west) {
if(curRoom < nMaxRooms) {
chunk* res = malloc(sizeof(chunk));
res->north = north;
res->east = east;
res->south = south;
res->west = west;
res->chW = w;
res->chH = h;
res->chX = CX;
res->chY = CY;
res->rects = malloc(sizeof(rectangle)*32);
res->nRects = 0;
res->circles = malloc(sizeof(circle)*32);
res->nCircles = 0;
allRooms[curRoom] = res;
curRoom += 1;
return (curRoom-1);
} else {
fprintf(stderr, "ERROR : all rooms are filled, cannot create a new one\n");
return (-1);
}
}
void init_rooms() {
nMaxRooms = 128;
curRoom = 0;
allRooms = malloc(sizeof(chunk*)*nMaxRooms);
int id0 = build_empty_room(0, 0, 500, 500, NULL, NULL, NULL, NULL);
start = allRooms[id0];
}
void destroy_rooms() {
for(int r = 0; r < curRoom; r++) {
free(allRooms[r]->circles);
free(allRooms[r]->rects);
free(allRooms[r]);
}
free(allRooms);
}

9
src/rooms.h Normal file
View File

@ -0,0 +1,9 @@
#ifndef ROOMS_H
#define ROOMS_H
int build_empty_room(int CX, int CY, int w, int h, chunk* north, chunk* east, chunk* south, chunk* west);
void init_rooms();
void destroy_rooms();
#endif

106
src/structure.h Normal file
View File

@ -0,0 +1,106 @@
#ifndef CONSTS_H
#define CONSTS_H
// ------------------------------------------------------------------------ //
// SDL-related struct
typedef struct imgs {
int len;
SDL_Texture** arr;
} imgs;
// ------------------------------------------------------------------------ //
// car shenanigans
typedef struct pt_t {
int ix;
int iy;
} pt;
typedef struct ptf_t {
double fx;
double fy;
} ptf;
typedef struct car_t car;
// unused for now
typedef struct item_t {
const char* name;
void (*onCollect)(car* user);
void (*onUse)(car* user);
} item;
typedef struct car_t {
const char* name;
ptf pos;
ptf vel;
int nCoins;
item* itm; // either NULL or a pointer to an item
} car;
// ------------------------------------------------------------------------ //
// (take a) map
typedef struct color_t {
uint8_t red;
uint8_t green;
uint8_t blue;
} color;
typedef struct rectangle_t {
int x;
int y;
int w;
int h;
color rgb;
double restitution;
void (*onHit)(struct rectangle_t * self, car* bonk);
void (*betweenTurn) (struct rectangle_t * self);
} rectangle;
typedef struct circle_t {
int x;
int y;
int r;
color rgb;
double restitution;
void (*onHit)(struct circle_t * self, car* bonk);
void (*betweenTurn) (struct circle_t * self);
} circle;
typedef struct chunk_t {
rectangle* rects;
int nRects;
circle* circles;
int nCircles;
int chW;
int chH;
// absolute coords
int chX;
int chY;
struct chunk_t* north;
struct chunk_t* east;
struct chunk_t* south;
struct chunk_t* west;
} chunk;
// global car data here
typedef struct carData_t {
car* c;
chunk* curChunk;
} carData;
// ------------------------------------------------------------------------ //
extern imgs* digits;
extern imgs* letters;
extern int currentTurn;
extern chunk* start;
extern chunk** allRooms;
extern int nMaxRooms;
extern carData* players;
extern int nPlayers;
#endif