diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..2a19646 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,10 @@ + +# You are free to modify this file + +cmake_minimum_required(VERSION 3.0) +project(game) +find_package(X11 REQUIRED) +set(CMAKE_CONFIGURATION_TYPES "Debug" "Release") +file(GLOB SRC *.cpp) +add_executable(game ${SRC}) +target_link_libraries(game m X11) diff --git a/Engine.cpp b/Engine.cpp new file mode 100644 index 0000000..878683e --- /dev/null +++ b/Engine.cpp @@ -0,0 +1,186 @@ + +// +// DO NOT MODIFY THIS FILE +// + +#include "Engine.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +uint32_t buffer[SCREEN_HEIGHT][SCREEN_WIDTH] = { 0 }; + +static bool keys[VK__COUNT] = { 0 }; + +static Display * display = NULL; +static Window window; +static Visual * visual = NULL; +static GC gc = 0; +static Pixmap pixmap = 0; +static XEvent event; +static int screen = 0; +static bool quit = false; +static Atom wmDeleteMessage = 0; +static XClassHint * classhint = NULL; +static XWMHints * wmhints = NULL; +static XSizeHints * sizehints = NULL; +static char title[] = "game"; + +static void term_sig_handler(int) +{ + quit = true; +} + +bool is_key_pressed(int button_vk_code) +{ + if (unsigned(button_vk_code) >= VK__COUNT) + return false; + return keys[button_vk_code]; +} + +static void on_key_event(XKeyEvent & event, bool pressed) +{ + const int buf_size = 256; + char buf[buf_size]; + KeySym ks; + XLookupString(&event, buf, buf_size, &ks, NULL); + + switch (ks) + { + case XK_Left: + keys[VK_LEFT] = pressed; + break; + case XK_Right: + keys[VK_RIGHT] = pressed; + break; + case XK_Down: + keys[VK_DOWN] = pressed; + break; + case XK_Up: + keys[VK_UP] = pressed; + break; + case XK_Escape: + keys[VK_ESCAPE] = pressed; + break; + case XK_space: + keys[VK_SPACE] = pressed; + break; + case XK_Return: + keys[VK_RETURN] = pressed; + break; + } +} + +void schedule_quit_game() +{ + quit = true; +} + +uint64_t get_nsec() +{ + timespec ts = { 0, 0 }; + clock_gettime(CLOCK_MONOTONIC, &ts); + return uint64_t(ts.tv_sec) * 1000000000 + uint64_t(ts.tv_nsec); +} + +int main(int, const char **) +{ + if ((display = XOpenDisplay(getenv("DISPLAY"))) == NULL) + { + fprintf(stderr, "Cannot connect X server: %s\n", strerror(errno)); + exit(1); + } + + screen = XDefaultScreen(display); + visual = DefaultVisual(display, screen); + gc = DefaultGC(display, screen); + window = XCreateWindow(display, DefaultRootWindow(display), + 10, 10, SCREEN_WIDTH, SCREEN_HEIGHT, 1, 24, InputOutput, CopyFromParent, 0, 0); + + classhint = XAllocClassHint(); + classhint->res_name = title; + classhint->res_class = title; + + wmhints = XAllocWMHints(); + wmhints->input = true; + wmhints->flags = InputHint; + + sizehints = XAllocSizeHints(); + sizehints->flags = PMaxSize | PMinSize; + sizehints->min_width = sizehints->max_width = SCREEN_WIDTH; + sizehints->min_height = sizehints->max_height = SCREEN_HEIGHT; + XSetWMProperties(display, window, NULL, NULL, NULL, 0, sizehints, wmhints, classhint); + + pixmap = XCreatePixmap(display, window, SCREEN_WIDTH, SCREEN_HEIGHT, 24); + + XSelectInput(display, window, ExposureMask | KeyPressMask | KeyReleaseMask); + XMapWindow(display, window); + wmDeleteMessage = XInternAtom(display, "WM_DELETE_WINDOW", false); + XSetWMProtocols(display, window, &wmDeleteMessage, 1); + + XFlush(display); + + initialize(); + + uint64_t prevTime = get_nsec(); + + XImage * image = XCreateImage(display, visual, 24, ZPixmap, 0, (char*)buffer, SCREEN_WIDTH, SCREEN_HEIGHT, 32, 0); + + signal(SIGINT, term_sig_handler); + signal(SIGTERM, term_sig_handler); + + for (;;) + { + sched_yield(); + + while (XPending(display)) + { + XNextEvent(display, &event); + + if (event.type == KeyPress) + on_key_event(event.xkey, true); + + if (event.type == KeyRelease) + on_key_event(event.xkey, false); + + if (event.type == ClientMessage && event.xclient.data.l[0] == (int)wmDeleteMessage) + quit = true; + } + + uint64_t curTime = get_nsec(); + if (curTime == prevTime) + continue; + + float dt = float(double(curTime - prevTime) * 1e-9); + if (dt > 0.1f) + dt = 0.1f; + act(dt); + prevTime = curTime; + + if (quit) + break; + + draw(); + XPutImage(display, pixmap, gc, image, 0, 0, 0, 0, image->width, image->height); + XCopyArea(display, pixmap, window, gc, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0); + XFlush(display); + } + + finalize(); + + XFree(classhint); + XFree(wmhints); + XFree(sizehints); + XFreePixmap(display, pixmap); + XCloseDisplay(display); + + return 0; +} diff --git a/Engine.h b/Engine.h new file mode 100644 index 0000000..0396c8a --- /dev/null +++ b/Engine.h @@ -0,0 +1,37 @@ +#pragma once + +// +// DO NOT MODIFY THIS FILE +// + +#include + +#define SCREEN_WIDTH 1024 +#define SCREEN_HEIGHT 768 + +// backbuffer +extern uint32_t buffer[SCREEN_HEIGHT][SCREEN_WIDTH]; + +enum +{ + VK_ESCAPE, + VK_SPACE, + VK_LEFT, + VK_UP, + VK_RIGHT, + VK_DOWN, + VK_RETURN, + + VK__COUNT +}; + +// VK_SPACE, VK_RIGHT, VK_LEFT, VK_UP, VK_DOWN, etc. +bool is_key_pressed(int button_vk_code); + +void initialize(); +void finalize(); + +void act(float dt); +void draw(); + +void schedule_quit_game(); diff --git a/Game.cpp b/Game.cpp new file mode 100644 index 0000000..8cbbd92 --- /dev/null +++ b/Game.cpp @@ -0,0 +1,45 @@ +#include "Engine.h" +#include +#include + +#include + +// +// You are free to modify this file +// + +// is_key_pressed(int button_vk_code) - check if a key is pressed, +// use keycodes (VK_SPACE, VK_RIGHT, VK_LEFT, VK_UP, VK_DOWN, VK_RETURN) +// +// schedule_quit_game() - quit game after act() + + + +// initialize game data in this function +void initialize() +{ +} + +// this function is called to update game data, +// dt - time elapsed since the previous update (in seconds) +void act(float dt) +{ + if (is_key_pressed(VK_ESCAPE)) + schedule_quit_game(); + +} + +// fill buffer in this function +// uint32_t buffer[SCREEN_HEIGHT][SCREEN_WIDTH] - is an array of 32-bit colors (8 bits per R, G, B) +void draw() +{ + // clear backbuffer + memset(buffer, 0, SCREEN_HEIGHT * SCREEN_WIDTH * sizeof(uint32_t)); + +} + +// free game data in this function +void finalize() +{ +} + diff --git a/LICENSE b/LICENSE index 42e6b2d..3b2f0a4 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2022 imp5imp5 +Copyright (c) 2022 Gaijin Games Kft. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal