#include #include #include #include #include #include "textures.h" #include "gameloop.h" #include "options.h" #include "terrain.h" #include "data.h" #include "main.h" #include "gui.h" /* Minecraft 4k, C edition. Version 0.8.0 KolibriOS * * Credits: * notch - creating the original game * sashakoshka - C port, modifications * samsebe - deciphering the meaning of some of the code * gracie bell - daylight function * https://gist.github.com/nowl/828013 - perlin noise * * ... & contributors on github! * https://github.com/sashakoshka/m4kc/graphs/contributors * * If you distribute a modified copy of this, just include this * notice. */ #define MAX_FPS 60 #define MIN_FRAME_MILLISECONDS 1000 / MAX_FPS static int controlLoop(Inputs *, const uint8_t *); static int handleEvent(Inputs *, const uint8_t *, SDL_Event); int main(int argc, char *argv[]) { (void)(argc); (void)(argv); //---- initializing SDL ----// SDL_Window *window = NULL; SDL_Renderer *renderer = NULL; const uint8_t *keyboard = SDL_GetKeyboardState(NULL); if (SDL_Init(SDL_INIT_VIDEO) < 0) { printf("cant make window\n"); goto exit; } window = SDL_CreateWindow( "M4KC 0.8.0 KOLIBRI", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, WINDOW_W, WINDOW_H, SDL_WINDOW_SHOWN); if (window == NULL) { printf("%s\n", SDL_GetError()); goto exit; } #ifdef _KOLIBRI renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_SOFTWARE | SDL_RENDERER_PRESENTVSYNC); #else renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); #endif if (renderer == NULL) { printf("%s\n", SDL_GetError()); goto exit; } SDL_RenderSetScale(renderer, BUFFER_SCALE, BUFFER_SCALE); #ifndef _KOLIBRI SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND); #endif //--- initializing modules ---// int err = 0; err = data_init(); if (err) { gameLoop_error("Cannot initialize data module."); } err = options_init(); if (err) { gameLoop_error("Cannot initialize options module."); } //---- generating assets ----// genTextures(45390874); //---- main game loop ----// Inputs inputs = {0}; int running = 1; while (running) { uint32_t frameStartTime = SDL_GetTicks(); running &= controlLoop(&inputs, keyboard); running &= gameLoop(&inputs, renderer); SDL_RenderPresent(renderer); // SDL_UpdateWindowSurface(window); // Clean up input struct inputs.keyTyped = 0; inputs.keySym = 0; // Limit FPS uint32_t frameDuration = SDL_GetTicks() - frameStartTime; if (frameDuration < MIN_FRAME_MILLISECONDS) { SDL_Delay(MIN_FRAME_MILLISECONDS - frameDuration); } } exit: SDL_Quit(); return 0; } static int controlLoop(Inputs *inputs, const Uint8 *keyboard) { SDL_PumpEvents(); int mouseX = 0, mouseY = 0; SDL_GetMouseState(&mouseX, &mouseY); // Detect movement controls inputs->keyboard.space = keyboard[SDL_SCANCODE_SPACE]; inputs->keyboard.w = keyboard[SDL_SCANCODE_W]; inputs->keyboard.s = keyboard[SDL_SCANCODE_S]; inputs->keyboard.a = keyboard[SDL_SCANCODE_A]; inputs->keyboard.d = keyboard[SDL_SCANCODE_D]; if (!SDL_GetRelativeMouseMode()) { inputs->mouse.x = mouseX; inputs->mouse.y = mouseY; } SDL_Event event; while (SDL_PollEvent(&event)) { if (!handleEvent(inputs, keyboard, event)) { return 0; } } return 1; } static char scancodeToChar(SDL_Scancode scancode, int shiftPressed) { // Basic mapping from scancodes to characters switch (scancode) { case SDL_SCANCODE_A: return shiftPressed ? 'A' : 'a'; case SDL_SCANCODE_B: return shiftPressed ? 'B' : 'b'; case SDL_SCANCODE_C: return shiftPressed ? 'C' : 'c'; case SDL_SCANCODE_D: return shiftPressed ? 'D' : 'd'; case SDL_SCANCODE_E: return shiftPressed ? 'E' : 'e'; case SDL_SCANCODE_F: return shiftPressed ? 'F' : 'f'; case SDL_SCANCODE_G: return shiftPressed ? 'G' : 'g'; case SDL_SCANCODE_H: return shiftPressed ? 'H' : 'h'; case SDL_SCANCODE_I: return shiftPressed ? 'I' : 'i'; case SDL_SCANCODE_J: return shiftPressed ? 'J' : 'j'; case SDL_SCANCODE_K: return shiftPressed ? 'K' : 'k'; case SDL_SCANCODE_L: return shiftPressed ? 'L' : 'l'; case SDL_SCANCODE_M: return shiftPressed ? 'M' : 'm'; case SDL_SCANCODE_N: return shiftPressed ? 'N' : 'n'; case SDL_SCANCODE_O: return shiftPressed ? 'O' : 'o'; case SDL_SCANCODE_P: return shiftPressed ? 'P' : 'p'; case SDL_SCANCODE_Q: return shiftPressed ? 'Q' : 'q'; case SDL_SCANCODE_R: return shiftPressed ? 'R' : 'r'; case SDL_SCANCODE_S: return shiftPressed ? 'S' : 's'; case SDL_SCANCODE_T: return shiftPressed ? 'T' : 't'; case SDL_SCANCODE_U: return shiftPressed ? 'U' : 'u'; case SDL_SCANCODE_V: return shiftPressed ? 'V' : 'v'; case SDL_SCANCODE_W: return shiftPressed ? 'W' : 'w'; case SDL_SCANCODE_X: return shiftPressed ? 'X' : 'x'; case SDL_SCANCODE_Y: return shiftPressed ? 'Y' : 'y'; case SDL_SCANCODE_Z: return shiftPressed ? 'Z' : 'z'; case SDL_SCANCODE_1: return shiftPressed ? '!' : '1'; case SDL_SCANCODE_2: return shiftPressed ? '@' : '2'; case SDL_SCANCODE_3: return shiftPressed ? '#' : '3'; case SDL_SCANCODE_4: return shiftPressed ? '$' : '4'; case SDL_SCANCODE_5: return shiftPressed ? '%' : '5'; case SDL_SCANCODE_6: return shiftPressed ? '^' : '6'; case SDL_SCANCODE_7: return shiftPressed ? '&' : '7'; case SDL_SCANCODE_8: return shiftPressed ? '\0' : '8'; // KolibriOS file can't contain * in name case SDL_SCANCODE_9: return shiftPressed ? '(' : '9'; case SDL_SCANCODE_0: return shiftPressed ? ')' : '0'; case SDL_SCANCODE_MINUS: return shiftPressed ? '_' : '-'; case SDL_SCANCODE_EQUALS: return shiftPressed ? '+' : '='; case SDL_SCANCODE_SPACE: return ' '; case SDL_SCANCODE_RETURN: return '\n'; case SDL_SCANCODE_BACKSPACE: return '\b'; default: return '\0'; // Unsupported scancodes } } static int handleEvent(Inputs *inputs, const uint8_t *keyboard, SDL_Event event) { switch (event.type) { case SDL_QUIT: return 0; case SDL_MOUSEBUTTONDOWN: switch (event.button.button) { case SDL_BUTTON_LEFT: inputs->mouse.left = 1; break; case SDL_BUTTON_RIGHT: inputs->mouse.right = 1; break; } break; case SDL_MOUSEBUTTONUP: switch (event.button.button) { case SDL_BUTTON_LEFT: inputs->mouse.left = 0; break; case SDL_BUTTON_RIGHT: inputs->mouse.right = 0; break; } break; case SDL_KEYDOWN: inputs->keySym = event.key.keysym.sym; if (event.key.repeat == 0) { // Detect UI hotkeys using scancodes SDL_Scancode scancode = event.key.keysym.scancode; int shiftPressed = keyboard[SDL_SCANCODE_LSHIFT] || keyboard[SDL_SCANCODE_RSHIFT]; char typedChar = scancodeToChar(scancode, shiftPressed); if (typedChar != '\0') { inputs->keyTyped = (int)typedChar; // Store the character as int // printf("Typed char: %c", typedChar); } // Update hotkey states inputs->keyboard.esc = keyboard[SDL_SCANCODE_ESCAPE]; inputs->keyboard.f1 = keyboard[SDL_SCANCODE_F1]; inputs->keyboard.f2 = keyboard[SDL_SCANCODE_F2]; inputs->keyboard.f3 = keyboard[SDL_SCANCODE_F3]; inputs->keyboard.f4 = keyboard[SDL_SCANCODE_F4]; inputs->keyboard.e = keyboard[SDL_SCANCODE_E]; inputs->keyboard.t = keyboard[SDL_SCANCODE_T]; inputs->keyboard.f = keyboard[SDL_SCANCODE_F]; inputs->keyboard.num0 = keyboard[SDL_SCANCODE_0]; inputs->keyboard.num1 = keyboard[SDL_SCANCODE_1]; inputs->keyboard.num2 = keyboard[SDL_SCANCODE_2]; inputs->keyboard.num3 = keyboard[SDL_SCANCODE_3]; inputs->keyboard.num4 = keyboard[SDL_SCANCODE_4]; inputs->keyboard.num5 = keyboard[SDL_SCANCODE_5]; inputs->keyboard.num6 = keyboard[SDL_SCANCODE_6]; inputs->keyboard.num7 = keyboard[SDL_SCANCODE_7]; inputs->keyboard.num8 = keyboard[SDL_SCANCODE_8]; inputs->keyboard.num9 = keyboard[SDL_SCANCODE_9]; } break; case SDL_MOUSEWHEEL: inputs->mouse.wheel = event.wheel.y; break; case SDL_MOUSEMOTION: if (SDL_GetRelativeMouseMode()) { inputs->mouse.x = event.motion.xrel; inputs->mouse.y = event.motion.yrel; } break; } return 1; }