Jump to content
  • Advertisement


  • Content Count

  • Joined

  • Last visited

Community Reputation

1221 Excellent

About Finalspace

  • Rank
    Advanced Member

Personal Information


  • Github
  • Steam

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

  1. Finalspace

    What's your opinion on story centric games?

    I found 2015 by accident life is strange and was blown away by it. Since then, i am loving story centric gaming - especially if my choices has consequences. The best game in that region is "Beyond Two Souls" - i never enjoyed any game so much, as this one. So my oppion about this is simple: Interaction and Story-Telling at the same time works just fine.
  2. C#: I use C# at work every day and sure there is a few things to complain about: - new() allocates always on the heap and i havent found a way to allocate on the stack yet - Making a memory arena and just use memory like a stack is impossible, due to the lack of memory access - NuGet is a mess when you need them to make (Configuration, Creation, Publishing, Debugging). - Unit-Tests execution are extraordinary slow - Without unsafe you cannot define a "fixed" length-array -> int[1024] myArray; // Not possible - The industry standard of documenting C# code is really bad (Initializes a new instance of the <see cref="TheClassName"/> class, Gets or sets the value) etc. C++ (I have too much to complain, so i do the opposite: Writing down the stuff that i actually like in C++ instead): - I like operator overloading, so i can use vector/matrix stuff with normal math syntax - I like method overloading, because it can be useful sometimes - Structs and Unions without the need of writing "typedef X" all the time - I like enum class with support for changing the integral type (S8/U8, S16/U16, S32/U32, S64/U64) - I partly like nullptr, because defining something to null explicitly is more safe than just setting it to a zero as a number -> even if the meaning i basically the same - Everything else in C++, i dont like Visual Studio (C# and C++): - The built-in profiler in visual studio 2017/2019 is pretty much useless, because of its horrible not intuitive UI. Also there is no way add manual timining instructions for the profiler yourself. - Unit-Test exporer takes ages to update, after a rebuild - XAML text/visual editor is unstable/slow like hell Java: - Getters or setters are so annoying - Adapting tech from C# into java in the worst possible way
  3. Finalspace

    X11 window black fullscreen bug?

    I fixed it. The error was in the Visual and Colormap request. Also it looks like that XSelectInput requires StructureNotifyMask and ExposureMask, otherwise you will never get a ConfigureNotify event coming in - even though you had both already set in event_mask O_o -> X11 is weird. #if 0 // Wrong? XVisualInfo vinfo = {0}; if (!XMatchVisualInfo(windowState->display, windowState->screen, 32, DirectColor, &vinfo)) { if (!XMatchVisualInfo(windowState->display, windowState->screen, 24, DirectColor, &vinfo)) { Release(windowState); return(false); } } windowState->colorDepth = vinfo.depth; windowState->visual = vinfo.visual; windowState->colorMap = XCreateColormap(windowState->display, windowState->root, windowState->visual, AllocNone); #else windowState->colorDepth = XDefaultDepth(windowState->display, windowState->screen); windowState->visual = XDefaultVisual(windowState->display, windowState->screen); windowState->colorMap = XDefaultColormap(windowState->display, windowState->screen); #endif
  4. Finalspace

    X11 window black fullscreen bug?

    Yep, i saw that error too - results in never getting to the event when the window is closed
  5. Finalspace

    X11 window black fullscreen bug?

    Its not. Forgot to copy the break at the end from my actual code. I corrected the source. Thanks for the catch.
  6. Hi there, i am fighting against a weird bug in X11 where i only see a fullscreen black screen with my window behind it - but only when i do software rendering. If you tab switch into another window, or click outside of your actual window area, the desktop are shown - but my window are not. Only when i have a window manager with task icon preview (Linux Mint Cinnamon), i can actually see the window - but only when i hover it over the icon in the taskbar O_o. The last time i had run my x11 application was on my previous ubuntu linux installation. Now i have linux mint with cinnamon - and it does not work anymore. I have no idea why that is the case, nor how to fix it. Can you please have a look at my posted source, maybe i do something horrible wrong? I tried recording the issue with OBS - but weirdly the bug is not present in the OBS recording, the window is just shown just fine O_o. So i did a real screen capture with my iphone and uploaded it: Here is my code (main.c / C99): #if !defined(_XOPEN_SOURCE) # define _XOPEN_SOURCE 600 #endif #if !defined(_DEFAULT_SOURCE) # define _DEFAULT_SOURCE 1 #endif #if !defined(__STDC_FORMAT_MACROS) # define __STDC_FORMAT_MACROS #endif #if !defined(__STDC_LIMIT_MACROS) # define __STDC_LIMIT_MACROS #endif #if !defined(_LARGEFILE_SOURCE) # define _LARGEFILE_SOURCE #endif #if !defined(_LARGEFILE64_SOURCE) # define _LARGEFILE64_SOURCE #endif #if !defined(_FILE_OFFSET_BITS) # define _FILE_OFFSET_BITS 64 #endif #include <stdint.h> // uint32_t, ... #include <stddef.h> // size_t #include <stdbool.h> // bool #include <stdarg.h> // va_start, va_end, va_list, va_arg #include <stdio.h> #include <malloc.h> #include <limits.h> // UINT32_MAX, ... #include <assert.h> #include <sys/time.h> #include <unistd.h> #include <time.h> #include <X11/X.h> // Window #include <X11/Xlib.h> // Display #include <X11/Xutil.h> // XVisualInfo #include <X11/Xatom.h> // XA_CARDINAL #define ArrayCount(arr) (sizeof(arr) / (arr)[0]) typedef struct BackBuffer { uint32_t width; uint32_t height; uint32_t pixelStride; uint32_t lineWidth; uint32_t *pixels; XImage *image; } BackBuffer; typedef struct WindowState { BackBuffer backbuffer; Window root; Window window; Colormap colorMap; GC gc; Display *display; Visual *visual; int colorDepth; int screen; int width; int height; Atom wmProtocols; Atom wmDeleteWindow; Atom netWMPing; Atom netWMPid; bool isRunning; } WindowState; void FillBackbuffer(BackBuffer *backbuffer, uint32_t color) { for (size_t i = 0; i < backbuffer->width * backbuffer->height; ++i) { backbuffer->pixels[i] = color; } } void InitBackBuffer(Display *display, Visual *visual, BackBuffer *backbuffer, uint32_t w, uint32_t h) { backbuffer->width = w; backbuffer->height = h; backbuffer->pixelStride = sizeof(uint32_t); backbuffer->lineWidth = backbuffer->width * backbuffer->pixelStride; size_t size = backbuffer->lineWidth * backbuffer->height; assert(backbuffer->pixels == NULL); backbuffer->pixels = (uint32_t *)malloc(size); FillBackbuffer(backbuffer, 0xFF000000); assert(backbuffer->image == NULL); backbuffer->image = XCreateImage(display, visual, 24, ZPixmap, 0, (char *)backbuffer->pixels, backbuffer->width, backbuffer->height, 32, (int)backbuffer->lineWidth); } void FreeBackBuffer(BackBuffer *backbuffer) { if (backbuffer->image){ XFree(backbuffer->image); backbuffer->image = NULL; } if (backbuffer->pixels){ free(backbuffer->pixels); backbuffer->pixels = NULL; } } void ResizeBackBuffer(Display *display, Visual *visual, BackBuffer *backbuffer, uint32_t w, uint32_t h) { FreeBackBuffer(backbuffer); InitBackBuffer(display, visual, backbuffer, w, h); } void HandleEvent(WindowState *windowState, XEvent *ev) { switch (ev->type) { case ConfigureNotify: { uint32_t w = (uint32_t)ev->xconfigure.width; uint32_t h = (uint32_t)ev->xconfigure.height; windowState->width = w; windowState->height = h; ResizeBackBuffer(windowState->display, windowState->visual, &windowState->backbuffer, w, h); } break; case ClientMessage: { if (ev->xclient.message_type == windowState->wmProtocols) { const Atom protocol = (Atom)ev->xclient.data.l[0]; if (protocol != None) { if (protocol == windowState->wmDeleteWindow) { windowState->isRunning = false; } } else if (protocol == windowState->netWMPing) { XEvent reply = *ev; reply.xclient.window = windowState->root; XSendEvent(windowState->display, windowState->root, False, SubstructureNotifyMask | SubstructureRedirectMask, &reply); } } } break; case Expose: { } break; default: break; } } void Release(WindowState *windowState) { if (windowState->gc) { XFree(windowState->gc); windowState->gc = NULL; } if (windowState->window) { XUnmapWindow(windowState->display, windowState->window); XDestroyWindow(windowState->display, windowState->window); windowState->window = 0; } if (windowState->colorMap) { XFreeColormap(windowState->display, windowState->colorMap); windowState->colorMap = 0; } if (windowState->display) { XCloseDisplay(windowState->display); windowState->display = NULL; } } void ProcessEvents(WindowState *windowState) { XEvent ev; while (XPending(windowState->display)) { XNextEvent(windowState->display, &ev); HandleEvent(windowState, &ev); } } bool Init(WindowState *windowState) { windowState->display = XOpenDisplay(":0"); if (!windowState->display) { printf("ERROR: No display found!\n"); return(false); } windowState->screen = XDefaultScreen(windowState->display); windowState->root = XRootWindow(windowState->display, windowState->screen); // Visual XVisualInfo vinfo = {0}; if (!XMatchVisualInfo(windowState->display, windowState->screen, 32, DirectColor, &vinfo)) { if (!XMatchVisualInfo(windowState->display, windowState->screen, 24, DirectColor, &vinfo)) { Release(windowState); return(false); } } windowState->visual = vinfo.visual; windowState->colorDepth = vinfo.depth; windowState->colorMap = XCreateColormap(windowState->display, windowState->root, windowState->visual, AllocNone); XSetWindowAttributes swa = {0}; swa.colormap = windowState->colorMap; swa.event_mask = StructureNotifyMask | ExposureMask | FocusChangeMask | VisibilityChangeMask | EnterWindowMask | LeaveWindowMask | PropertyChangeMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | ButtonMotionMask; swa.background_pixel = BlackPixel(windowState->display, windowState->screen); swa.border_pixel = WhitePixel(windowState->display, windowState->screen); swa.bit_gravity = NorthWestGravity; swa.win_gravity = NorthWestGravity; int flags = CWColormap | CWBackPixel | CWBorderPixel | CWEventMask | CWBitGravity | CWWinGravity; int windowX = 0; int windowY = 0; int windowWidth = 400; int windowHeight = 400; windowState->window = XCreateWindow(windowState->display, windowState->root, windowX, windowY, windowWidth, windowHeight, 0, windowState->colorDepth, InputOutput, windowState->visual, flags, &swa); if (!windowState->window) { Release(windowState); return(false); } windowState->width = windowWidth; windowState->height = windowHeight; XSelectInput(windowState->display, windowState->window, KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | ButtonMotionMask); // Window manager atoms windowState->wmDeleteWindow = XInternAtom(windowState->display, "WM_DELETE_WINDOW", False); windowState->netWMPid = XInternAtom(windowState->display, "_NET_WM_PID", False); windowState->netWMPing = XInternAtom(windowState->display, "_NET_WM_PING", False); windowState->wmProtocols = XInternAtom(windowState->display, "WM_PROTOCOLS", False); Atom protocols[] = { windowState->wmDeleteWindow, windowState->netWMPing }; XSetWMProtocols(windowState->display, windowState->window, protocols, ArrayCount(protocols)); const long pid = getpid(); XChangeProperty(windowState->display, windowState->window, windowState->netWMPid, XA_CARDINAL, 32, PropModeReplace, (unsigned char*)&pid, 1); XMapWindow(windowState->display, windowState->window); XFlush(windowState->display); InitBackBuffer(windowState->display, windowState->visual, &windowState->backbuffer, windowState->width, windowState->height); windowState->gc = XCreateGC(windowState->display, windowState->window, 0, 0); XPutImage(windowState->display, windowState->window, windowState->gc, windowState->backbuffer.image, 0, 0, 0, 0, windowState->backbuffer.width, windowState->backbuffer.height); XSync(windowState->display, False); return(true); } void ColorTimeUpdate(float *t, int *d, const float speed) { *t += (float)*d * speed; if (*t <= 0.0f) { *t = 0.0f; *d = -*d; } else if (*t >= 1.0f) { *t = 1.0f; *d = -*d; } } static long timestamp(void) { struct timeval tv; if (gettimeofday(&tv, NULL) < 0) return 0; return (long)((long)tv.tv_sec * 1000 + (long)tv.tv_usec/1000); } static void sleep_for(long t) { struct timespec req; const time_t sec = (int)(t/1000); const long ms = t - (sec * 1000); req.tv_sec = sec; req.tv_nsec = ms * 1000000L; while(-1 == nanosleep(&req, &req)); } int main() { const long DTIME = 1000 / 60; WindowState windowState = {0}; float tR = 0.0f; float tG = 0.0f; float tB = 0.0f; int dR = 1; int dG = 1; int dB = 1; if (Init(&windowState)) { windowState.isRunning = true; long timeStart = timestamp(); while (windowState.isRunning) { ProcessEvents(&windowState); uint8_t r = (uint32_t)(tR * 255.0f + 0.5f); uint8_t g = (uint32_t)(tG * 255.0f + 0.5f); uint8_t b = (uint32_t)(tB * 255.0f + 0.5f); uint8_t a = 255; uint32_t color = (a << 24) | (r << 16) | (g << 8) | (b << 0); FillBackbuffer(&windowState.backbuffer, color); XPutImage(windowState.display, windowState.window, windowState.gc, windowState.backbuffer.image, 0, 0, 0, 0, windowState.backbuffer.width, windowState.backbuffer.height); XFlush(windowState.display); ColorTimeUpdate(&tR, &dR, 0.1f); ColorTimeUpdate(&tG, &dG, 0.01f); ColorTimeUpdate(&tB, &dB, 0.001f); long timeEnd = timestamp(); long dt = timeEnd - timeStart; timeStart = timeEnd; if (dt < DTIME){ sleep_for(DTIME - dt); } } Release(&windowState); } return 0; }
  7. I am not sure if this issue is new, but it looks like that project filterings (Types, Genres) are not passed to the "Prev" and "Next" paging controls. Steps to reproduce: - Click on the https://www.gamedev.net/projects/type/2-game-asset/ - Jump to the "Next" page, Now the type filter is reset to nothing - showing everything, not just game assets, which is wrong.
  8. Finalspace

    Poll: How often do you buy the latest gaming PC?

    I never buy new PCs. I always upgrade my existing ones every 4 years. And i most likely just upgrade the graphics card or the memory only. In very rare circumstances, i will buy a full-upgrade for one system with the newest components - which fits in a price range (~1500 bucks). To give an example: Just half a year ago i swapped out every component of my HDPC (i5 2500k, GTX 650 TI, SATA SSDs) with a i7 8086k with a GTX 1060. Reasons: - Gaming performance was not that great - Full-HD movies was not playing smoothly at all times - Video encoding was slow like hell - Wanted to use modern game engines on my HDPC as well I will expect this system to last at least 3-4 years.
  9. I decided not to check it and leave it as is is. If it crashes, it just crashes. But thanks for your tips.
  10. Finalspace

    Side-Scroller Movement in a Tile-Based Game

    I forgot, there is a fifth solution: 5.) Use handmade hero style physics In the very beginnings of the video series handmade hero, casey built a very easy and stable custom physics solution which relies heavy on minkowski difference and velocitiy projection. I used that technique in a platformer project a few years ago successfully, but i never got moving platforms working. If you got time, watch the episodes Day 042 to Day 050, which explains equation of motion, line segment intersection tests and other stuff in very detail: https://handmadehero.org/watch
  11. Finalspace

    Side-Scroller Movement in a Tile-Based Game

    I have a few tips for you. 1.) Sonic physics guide: http://info.sonicretro.org/Sonic_Physics_Guide In the past this helped me implementing pure tilebased platformer physics successfully. 2.) Box2D as your pure physics solution This has a lot of pitfalls: Friction, Sensors, Ground tracing, etc. Also you may need to convert the solid tiles to connected line segments, otherwise you may encounter ghost collisions when you just create one body for each tile. Doing this conversion is not that easy, so i have written a library for that: https://github.com/f1nalspace/final_game_tech/blob/master/final_tiletrace.hpp 3.) Box2D but dont use dynamic bodies for all entities, use kinematic bodies and implement all the movement code yourself. 4.) Speculative contacts: https://wildbunny.co.uk/blog/2011/12/11/how-to-make-a-2d-platform-game-part-1/ Great solution, especially for platformer - with very easy math. The only hard part is to write a stable contact generator for angular dynamics. If you dont need angular dynamics, then its really easy.
  12. Hi there, i previously had a function which can wait for a array of threads to finish - implemented in C99: bool fpl__Win32ThreadWaitForMultiple(fplThreadHandle **threads, const size_t count, const fplTimeoutValue timeout) { for (size_t index = 0; index < count; ++index) { fplThreadHandle *thread = threads[index]; if (thread == fpl_null) { return false; } // ... Check the thread } return true; } This was fine for a very long time, but now i encountered a case where my thread handle pointers are not following in order (Not contiguously), so i introduced a "stride" argument to account for that: bool fpl__Win32ThreadWaitForMultiple(fplThreadHandle **threads, const size_t count, const size_t stride, const fplTimeoutValue timeout { for (size_t index = 0; index < count; ++index) { fplThreadHandle *thread = *(fplThreadHandle **)((uint8_t *)threads + index * stride); if (thread == fpl_null) { return false; } // ... Check the thread } return true; } This works fine unless you pass an invalid stride which results in either a invalid memory address or just garbage. Now it comes the actual question -> Is there a way to detect such garbage memory addresses? Obviously a NULL check is not sufficient enough. Visual studio reported a 0x21 as a write access violation... I understand that i can detect any cases, but i would love to detect at least the most common cases. I dont assume i can just check for "0x0000000000000021" on x64 isn´t it?
  13. Finalspace

    GameDev.net will be 20 years old on June 15 😮

    When did you join? I joined late in March 2012, but i knew gamedev.net since ~2000. Thats the the time i started doing tons and tons of OpenGL development. What brought you here? Initially the NeHe tutorials brought me here, which lead me eventually to other articles and forum topics. Why do you participate? In ~2011 i started doing heavy physics programming and had a lot of trouble with, so i joined the forums to get help. Eventually i started answering some questions myself and posted some projects of mine to get feedback. or just to giving somethink back to this awesome community. Nowadays i am not that active very much, but i reguraly visit this site, thus reading articles/posts and answering some questions if i can.
  14. Hi, i am trying to migrate from CLion to QTCreator (Linux), but it looks like the locator search (Ctrl+K) for symbols does not work for any kind of macros i have defined in my c/c++ files. Do i miss something or is it simply not supported? I dont see any command for searching for macros ... just symbols, classes, files and stuff. Is it so hard to provide a generic search for any kind of symbols?
  15. Finalspace

    Critique My Serialization API

    Its a programming mistake if you pass the wrong length or the wrong pointer, so why care? It should crash or throw a exception. Also using std::string wont protect you as well, because the ctor std::string(const char *s, size_t n) with passing the wrong ptr or length will result in undefined behavior as well -> See http://www.cplusplus.com/reference/string/string/string/ (Exception safety).
  • Advertisement

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!