Refactored codebase and created new build system

This commit is contained in:
Sasha Koshka
2021-12-27 02:02:39 -05:00
parent 2a1452290b
commit 042d896562
24 changed files with 320 additions and 131 deletions

8
.gitignore vendored
View File

@@ -1,6 +1,4 @@
# Ignore executables
m4kc~
m4kc
m4kc-large~
m4kc-large
m4kc.exe
/bin/*
/win/bin/m4kc.exe
/o/*

View File

@@ -1,40 +0,0 @@
CC=gcc
CFLAGS=-Wall
CFLAGS_COMPACT=-Os -g0 -s -fno-stack-protector -fno-unwind-tables -fno-asynchronous-unwind-tables
CFLAGS_LARGE=-g
LIBS=-L/usr/local/lib -lSDL2 -lm
PREFIX=/usr
.PHONY: clean install install-large copy-files run uninstall
m4kc:
$(CC) main.c -o m4kc $(CFLAGS) $(CFLAGS_COMPACT) $(LIBS)
strip m4kc -S --strip-unneeded --remove-section=.note.gnu.gold-version --remove-section=.comment --remove-section=.note --remove-section=.note.gnu.build-id --remove-section=.note.ABI-tag
gzexe m4kc
ls -l m4kc
m4kc-large:
$(CC) main.c -o m4kc-large $(CFLAGS) $(CFLAGS_LARGE) $(LIBS)
install: m4kc copy-files
install -m 755 m4kc $(DESTDIR)$(PREFIX)/bin/m4kc
install-large: m4kc-large copy-files
install -m 755 m4kc-large $(DESTDIR)$(PREFIX)/bin/m4kc
copy-files:
install -d $(DESTDIR)$(PREFIX)/bin/
install -d $(DESTDIR)$(PREFIX)/share/applications/
install -d $(DESTDIR)$(PREFIX)/share/icons/
install -m 644 m4kc.desktop $(DESTDIR)$(PREFIX)/share/applications/m4kc.desktop
install -m 644 icon.png $(DESTDIR)$(PREFIX)/share/icons/m4kc.png
run: clean m4kc-large
./m4kc-large
make clean
clean:
rm -f m4kc m4kc~ m4kc-large
uninstall:
rm "$(DESTDIR)$(PREFIX)/bin/m4kc" "$(DESTDIR)$(PREFIX)/share/applications/m4kc.desktop" "$(DESTDIR)$(PREFIX)/share/icons/m4kc.png"

View File

@@ -1,6 +1,6 @@
# M4KC
![Grass block icon](icon.png)
![Grass block icon](icons/icon.png)
*Minecraft 4K - C Rewrite*
@@ -14,6 +14,7 @@ This project is an attempt to translate the game into C in order to increase its
* "Sticky" block collision - this behavior is present in the original version and I have been trying to work out ways to fix it for a while.
* Raycaster breaks at -64 along any axis
* Infinite terrain generation is not fully functional, issues such as chunks flashing in and out of existence are common
## Some goals for this project
@@ -33,10 +34,9 @@ This project is an attempt to translate the game into C in order to increase its
### Bare minimum to make this code run
* SDL2
* A C compiler
* A C compiler, such as gcc or clang
### To get it down to a small size, you need
* gcc (have not tried the flags with other compilers)
* gzexe
### On windows, you will need
@@ -45,13 +45,15 @@ This project is an attempt to translate the game into C in order to increase its
## Build instructions
### Linux, unix, etc
* To just get a binary, run `make` or `make m4kc`
* To run an uncompressed version, run `make run`
* To install the program, run `make install`
* To uninstall, run `make uninstall`
* To clean, run `make clean`
* To just get a binary, run `./build.sh small` or `./build.sh all small`
* To run an uncompressed version, run `./build.sh` or `./build.sh all`
* To install the program, run `./build.sh install`
* To uninstall, run `./build.sh uninstall`
* To clean, run `./build.sh clean`
### Windows
!!! NOTE !!! This doesn't work anymore. updated Windows build system coming soon.
Run `win-build.bat`. Inside of the `win` directory, you will find `m4kc.exe` and `SDL2.dll`. In order for `m4kc.exe` to run, these two must be in the same folder.
## Places
@@ -70,4 +72,4 @@ A lot of this code is decompiled from the original java version, and those are n
> Why is it so slow?
The game uses a 3D voxel raycaster to render things, which is a lot slower than more traditional methods of rendering. Luckily, C provides more powerful ways to optimize something like this than Java - and optimizations will keep coming.
The game uses a 3D voxel raycaster to render things, which is a lot slower than more traditional methods of rendering. Luckily, C provides more powerful ways to optimize something like this than Java - and optimizations will keep coming.

125
build.sh Normal file
View File

@@ -0,0 +1,125 @@
#!/bin/sh
# m4kc build system
# please keep this posix compliant!
CC="clang"
OBJ_PATH="o"
OUT_PATH="bin"
SRC_PATH="src"
SMALL_PATH="$OUT_PATH/m4kc"
DEBUG_PATH="$OUT_PATH/m4kc-debug"
FLAGS_SMALL="-Os -g0 -fno-stack-protector -fno-unwind-tables \
-fno-asynchronous-unwind-tables"
FLAGS_DEBUG="-g"
FLAGS_LIBS="-L/usr/local/lib -lSDL2 -lm"
# build a single module from src
buildModule () {
mkdir -p "$OBJ_PATH"
modOut="$OBJ_PATH/$1.o"
modIn="$SRC_PATH/$1.c"
modHead="$SRC_PATH/$1.h"
if [ ! -f "$modIn" ]; then
echo "!!! module $1 does not exist, skipping" >&2; return
fi
if [ "$modOut" -nt "$modIn" ] && [ "$modOut" -nt "$modHead" ]; then
echo "(i) skipping module $1, already built"; return
fi
echo "... building module $1: $1.c ---> $1.o"
flags="-c"
if [ "$2" = "small" ]
then flags="$flags $FLAGS_SMALL"
else flags="$flags $FLAGS_DEBUG"
fi
$CC "$modIn" -o "$modOut" $flags && echo ".// built module $1" \
|| echo "ERR could not build module $1" >&2
}
# build all modules in src, then link them together into final executable
buildAll () {
mkdir -p "$OUT_PATH"
echo "... building all modules"
for module in $SRC_PATH/*.c; do
buildModule $(basename "${module%.*}") "$1"
done
echo "... building entire executable"
flags="$FLAGS_LIBS"
if [ "$1" = "small" ]
then flags="$flags $FLAGS_SMALL -s"
allOut="$SMALL_PATH"
else flags="$flags $FLAGS_DEBUG"
allOut="$DEBUG_PATH"
fi
if $CC $OBJ_PATH/*.o -o "$allOut" $flags
then echo ".// built entire executable"
else echo "ERR could not build executable" >&2
return
fi
if [ "$1" = "small" ]; then
strip "$SMALL_PATH" -S --strip-unneeded \
--remove-section=.note.gnu.gold-version --remove-section=.comment \
--remove-section=.note --remove-section=.note.gnu.build-id \
--remove-section=.note.ABI-tag
gzexe "$SMALL_PATH"
ls -l "$SMALL_PATH"
fi
}
# clean everything
clean () {
rm -f $OBJ_PATH/* $OUT_PATH/* && echo "(i) cleaned"
}
# control script
case $1 in
all) buildAll $2 ;;
small) buildAll small ;;
"") buildAll ;;
clean)
clean
;;
run)
buildAll && "./$DEBUG_PATH"
;;
install)
clean
buildAll small \
&& echo "... installing" \
&& install -d /usr/games/ \
&& install -d /usr/share/applications/ \
&& install -d /usr/share/icons/ \
&& install -m 644 m4kc.desktop /usr/share/applications/m4kc.desktop \
&& install -m 644 icons/icon.png /usr/share/icons/m4kc.png \
&& install -m 755 "./$SMALL_PATH" /usr/games/m4kc \
&& echo ".// installed"
;;
uninstall)
rm "/usr/games/m4kc"
rm "/usr/share/applications/m4kc.desktop"
rm "/usr/share/icons/m4kc.png"
;;
*) buildModule $1 $2 ;;
esac

View File

Before

Width:  |  Height:  |  Size: 73 KiB

After

Width:  |  Height:  |  Size: 73 KiB

View File

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 40 KiB

43
old/Makefile Normal file
View File

@@ -0,0 +1,43 @@
CC=clang
WARN=-Wall -Wextra
COMPACT=-Os -g0 -s -fno-stack-protector -fno-unwind-tables -fno-asynchronous-unwind-tables
DEBUG=-g
LIBS=-L/usr/local/lib -lSDL2 -lm
.PHONY: warning all all-debug install run clean uninstall
warning:
@echo "DO NOT USE THIS FILE!!!!!!"
@echo "A NEW SCRIPT (build.sh) HAS BEEN MADE"
all:
mkdir -p bin
$(CC) src/*.c -o bin/m4kc $(WARN) $(LIBS) $(COMPACT)
strip bin/m4kc -S --strip-unneeded --remove-section=.note.gnu.gold-version \
--remove-section=.comment --remove-section=.note \
--remove-section=.note.gnu.build-id --remove-section=.note.ABI-tag
gzexe bin/m4kc
ls -l bin/m4kc
all-debug:
mkdir -p bin
$(CC) src/*.c -o bin/m4kc-debug $(WARN) $(LIBS) $(debug)
install: all
install -d /usr/games/
install -d /usr/share/applications/
install -d /usr/share/icons/
install -m 644 m4kc.desktop /usr/share/applications/m4kc.desktop
install -m 644 icons/icon.png /usr/share/icons/m4kc.png
install -m 755 bin/m4kc /usr/games/m4kc
run: all-debug
./bin/m4kc-debug
clean:
rm -f bin/*
uninstall:
rm "/usr/games/m4kc"
rm "/usr/share/applications/m4kc.desktop"
rm "/usr/share/icons/m4kc.png"

View File

@@ -1 +1 @@
gcc main.c -mwindows -Iwin\SDL2\include -Lwin\SDL2\lib -Wall -lmingw32 -lSDL2main -lSDL2 -o win\m4kc
gcc main.c -mwindows -Iwin\SDL2\include -Lwin\SDL2\lib -Wall -lmingw32 -lSDL2main -lSDL2 -o win\bin\m4kc

View File

@@ -1,15 +1,16 @@
#include "gameloop.h"
/*
gameLoop
Does all the raycasting stuff, moves the player around, etc.
If by chance the game ends, it returns false - which should
terminate the main while loop and end the program.
*/
int gameLoop(
int gameLoop (
unsigned int seed,
Inputs *inputs,
World *world,
SDL_Renderer *renderer,
SDL_Window *window
SDL_Renderer *renderer
) {
// We dont want to have to pass all of these by reference, so
// have all of them as static variables
@@ -97,11 +98,12 @@ int gameLoop(
chatDrawIndex,
fps_lastmil = 0,
fps_count = 0,
fps_now = 0,
chunkLoadNum;
static u_int32_t fps_lastmil = 0,
fps_count = 0,
fps_now = 0;
static char drawDistanceText [] = "Draw distance: 20\0";
static char trapMouseText [] = "Capture mouse: OFF";
@@ -136,15 +138,16 @@ int gameLoop(
static IntCoords coordPass = {0};
static IntCoords blockRayPosition = {0};
static Coords playerPosition = {0.0};
static Coords playerMovement = {0.0};
static Coords playerPosition = {0.0, 0.0, 0.0};
static Coords playerMovement = {0.0, 0.0, 0.0};
static Chunk *chunk;
static IntCoords chunkLoadCoords;
static int init = 0;
if(init) {
if (init) {
l = SDL_GetTicks();
gameTime = 2048;

15
src/gameloop.h Normal file
View File

@@ -0,0 +1,15 @@
#pragma once
#include <SDL2/SDL.h>
#include "utility.h"
#include "structs.h"
#include "gui.h"
#include "terrain.h"
#include "textures.h"
int gameLoop(
unsigned int seed,
Inputs *inputs,
World *world,
SDL_Renderer *renderer
);

View File

@@ -1,22 +1,4 @@
void strnum (char*, int, int);
int drawChar (SDL_Renderer*, int, int, int);
int drawStr (SDL_Renderer*, char*, int, int);
int centerStr (SDL_Renderer*, char*, int, int);
int drawBig (SDL_Renderer*, char*, int, int);
int drawBGStr (SDL_Renderer*, char*, int, int);
int button(
SDL_Renderer*, char*,
int, int, int, int, int
);
int drawSlot(
SDL_Renderer*, InvSlot*,
int, int, int, int
);
void dirtBg (SDL_Renderer*);
void loadScreen (SDL_Renderer*, char*, float, float);
void chatAdd (char[16][64], int*, int*, char*);
void white (SDL_Renderer*);
void tblack (SDL_Renderer*);
#include "gui.h"
const int BUFFER_W = 214;
const int BUFFER_H = 120;

34
src/gui.h Normal file
View File

@@ -0,0 +1,34 @@
#pragma once
#include <stdio.h>
#include <string.h>
#include <SDL2/SDL.h>
#include "structs.h"
#include "minecraftfont.h"
#include "textures.h"
void strnum (char*, int, int);
int drawChar (SDL_Renderer*, int, int, int);
int drawStr (SDL_Renderer*, char*, int, int);
int centerStr (SDL_Renderer*, char*, int, int);
int drawBig (SDL_Renderer*, char*, int, int);
int drawBGStr (SDL_Renderer*, char*, int, int);
int button(
SDL_Renderer*, char*,
int, int, int, int, int
);
int drawSlot(
SDL_Renderer*, InvSlot*,
int, int, int, int
);
void dirtBg (SDL_Renderer*);
void loadScreen (SDL_Renderer*, char*, float, float);
void chatAdd (char[16][64], int*, int*, char*);
void white (SDL_Renderer*);
void tblack (SDL_Renderer*);
extern const int BUFFER_W;
extern const int BUFFER_H;
extern const int BUFFER_SCALE;
extern const int BUFFER_HALF_W;
extern const int BUFFER_HALF_H;

View File

@@ -2,11 +2,9 @@
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include "structs.h"
#include "utility.h"
#include "textures.h"
#include "minecraftfont.h"
#include "terrain.h"
#include "structs.h"
#include "textures.h"
#include "gui.h"
#include "gameloop.h"
@@ -18,7 +16,6 @@
sashakoshka - C port, modifications
samsebe - deciphering the meaning of some of the code
gracie bell - daylight function
segfault - makefile
https://gist.github.com/nowl/828013 - perlin noise
samantaz - de-obfuscating controls code
@@ -26,7 +23,7 @@
notice.
*/
int main(int argc, char *argv[]) {
int main(/*int argc, char *argv[]*/) {
Inputs inputs = {0};
World world;
@@ -81,8 +78,7 @@ int main(int argc, char *argv[]) {
seed,
&inputs,
&world,
renderer,
window
renderer
)) {
SDL_PumpEvents();

View File

@@ -1,9 +1,11 @@
#include "minecraftfont.h"
/*
2D array, with 256 (planned) chars, where each char has an
eight 8bit ints for each row of pixels.
*/
Uint8 font[][9] = {
u_int8_t font[][9] = {
{0},
{0},
{0},

4
src/minecraftfont.h Normal file
View File

@@ -0,0 +1,4 @@
#pragma once
#include <stdlib.h>
extern u_int8_t font[256][9];

View File

@@ -1,3 +1,5 @@
#pragma once
#define CHUNKARR_DIAM 3
#define CHUNKARR_RAD (CHUNKARR_DIAM - 1) / 2
#define CHUNKARR_SIZE CHUNKARR_DIAM*CHUNKARR_DIAM*CHUNKARR_DIAM
@@ -80,7 +82,7 @@ struct _Player {
struct _InvSlot {
unsigned int amount:6;
unsigned int blockid;
} pack;
};
/*
_Inventory

View File

@@ -1,24 +1,4 @@
void initChunks (World*);
void sortChunks (World*);
Chunk* chunkLookup (World*, int, int, int);
int setBlock (World*, int, int, int, int, int);
int getBlock (World*, int, int, int);
int setCube(
World*,
int, int, int,
int, int, int,
int, int
);
int ch_setBlock (int*, int, int, int, int);
void genStructure (World*, int, int, int, int);
int genChunk(
World*,
unsigned int,
int, int, int,
int,
int,
Coords
);
#include "terrain.h"
/*
initChunks

29
src/terrain.h Normal file
View File

@@ -0,0 +1,29 @@
#pragma once
#include <stdlib.h>
#include <math.h>
#include <stdio.h>
#include "structs.h"
#include "utility.h"
void initChunks (World*);
void sortChunks (World*);
Chunk* chunkLookup (World*, int, int, int);
int setBlock (World*, int, int, int, int, int);
int getBlock (World*, int, int, int);
int setCube(
World*,
int, int, int,
int, int, int,
int, int
);
int ch_setBlock (int*, int, int, int, int);
void genStructure (World*, int, int, int, int);
int genChunk(
World*,
unsigned int,
int, int, int,
int,
int,
Coords
);

View File

@@ -1,5 +1,6 @@
#include "textures.h"
int textures[12288] = {0};
void genTextures(unsigned int);
/*
genTextures
@@ -79,3 +80,4 @@ void genTextures(unsigned int seed) {
}
}
}

7
src/textures.h Normal file
View File

@@ -0,0 +1,7 @@
#pragma once
#include "stdlib.h"
#include "utility.h"
extern int textures[12288];
void genTextures(unsigned int);

View File

@@ -1,6 +1,4 @@
int randm(int);
int nmod(int, int);
float perlin2d(int, double, double, double);
#include "utility.h"
/*
randm
@@ -14,7 +12,7 @@ int randm(int max) {
/*
nmod
Modulo operator that acts like java.
Modulo operator that acts like the java one.
*/
int nmod(int left, int right) {
left %= right;
@@ -23,14 +21,13 @@ int nmod(int left, int right) {
return left;
}
int noise2(int x, int y, Uint8 *hash, int seed) {
int perlin2d_noise2(int x, int y, u_int8_t *hash, int seed) {
static int tmp;
tmp = hash[(y + seed) % 256];
return hash[(tmp + x) % 256];
}
float smooth_inter(float x, float y, float s) {
float perlin2d_lerp(float x, float y, float s) {
return x + s * s * (3 - 2 * s) * (y - x);
}
@@ -39,7 +36,7 @@ float perlin2d(
double x, double y,
double freq
) {
static Uint8 hash[] =
static u_int8_t hash[] =
{208,34,231,213,32,248,233,56,161,78,24,140,
71,48,140,254,245,255,247,247,40,185,248,251,245,28,124,204,
@@ -72,14 +69,14 @@ float perlin2d(
int y_int = ya;
double x_frac = xa - x_int;
double y_frac = ya - y_int;
int s = noise2(x_int, y_int, hash, seed);
int t = noise2(x_int + 1, y_int, hash, seed);
int u = noise2(x_int, y_int + 1, hash, seed);
int v = noise2(x_int + 1, y_int + 1, hash, seed);
double low = smooth_inter(s, t, x_frac);
double high = smooth_inter(u, v, x_frac);
int s = perlin2d_noise2(x_int, y_int, hash, seed);
int t = perlin2d_noise2(x_int + 1, y_int, hash, seed);
int u = perlin2d_noise2(x_int, y_int + 1, hash, seed);
int v = perlin2d_noise2(x_int + 1, y_int + 1, hash, seed);
double low = perlin2d_lerp(s, t, x_frac);
double high = perlin2d_lerp(u, v, x_frac);
fin += smooth_inter(low, high, y_frac) * amp;
fin += perlin2d_lerp(low, high, y_frac) * amp;
amp /= 2;
xa *= 2;
ya *= 2;

8
src/utility.h Normal file
View File

@@ -0,0 +1,8 @@
#pragma once
#include <stdlib.h>
int randm(int);
int nmod(int, int);
float perlin2d(int, double, double, double);