680 lines
28 KiB
C
680 lines
28 KiB
C
/// _
|
|
/// __ ____ _ _ __ | |_ ___ _ __
|
|
/// \ \/ / _` | '_ \| __/ _ \| '__|
|
|
/// > < (_| | |_) | || (_) | |
|
|
/// /_/\_\__,_| .__/ \__\___/|_|
|
|
/// |_|
|
|
///
|
|
/// Copyright (c) 1997 - Ognjen 'xolatile' Milan Robovic
|
|
///
|
|
/// xolatile@chud.cyou - xaptor - Carnivorous medium-to-large sized Xlib wrapper that has a hooked beak and large sharp talons.
|
|
///
|
|
/// This program is free software, free as in freedom and as in free beer, you can redistribute it and/or modify it under the terms of the GNU
|
|
/// General Public License as published by the Free Software Foundation, either version 3 of the License, or any later version if you wish...
|
|
///
|
|
/// This program is distributed in the hope that it will be useful, but it is probably not, and without any warranty, without even the implied
|
|
/// warranty of merchantability or fitness for a particular purpose, because it is pointless. Please see the GNU (Geenoo) General Public License
|
|
/// for more details, if you dare, it is a lot of text that nobody wants to read...
|
|
|
|
#include <X11/Xutil.h>
|
|
#include <X11/Xatom.h>
|
|
|
|
typedef struct {
|
|
Display * display;
|
|
Window window;
|
|
XVisualInfo visual;
|
|
GC context;
|
|
Pixmap pixmap;
|
|
XImage * image;
|
|
Atom atom_close_button;
|
|
Atom atom_transparency;
|
|
|
|
bool signal [signal_count];
|
|
bool cursor [cursor_count];
|
|
int cursor_x;
|
|
int cursor_y;
|
|
|
|
uint gameplay_framerate;
|
|
uint animation_framerate;
|
|
uint window_width;
|
|
uint window_height;
|
|
bool active;
|
|
uint framerate;
|
|
ulong frame_time;
|
|
ulong frame_begin;
|
|
ulong frame_end;
|
|
uint * framebuffer;
|
|
uint global_tick;
|
|
uint gameplay_tick;
|
|
uint animation_tick;
|
|
uint tab_width;
|
|
uint sprite_count;
|
|
uint font_count;
|
|
uint * * sprite_data;
|
|
uint * sprite_width;
|
|
uint * sprite_height;
|
|
uint * * font_index;
|
|
uint * * font_width;
|
|
uint * * font_height;
|
|
char * font_begin;
|
|
char * font_end;
|
|
} raptor_structure;
|
|
|
|
static raptor_structure * raptor_initialize (uint gameplay_framerate, uint animation_framerate) {
|
|
raptor_structure * raptor = allocate (sizeof (* raptor));
|
|
|
|
raptor->gameplay_framerate = gameplay_framerate;
|
|
raptor->animation_framerate = animation_framerate;
|
|
raptor->tab_width = 8;
|
|
|
|
return (raptor);
|
|
}
|
|
|
|
static raptor_structure * raptor_deinitialize (raptor_structure * raptor) {
|
|
for (uint index = 0; index < raptor->sprite_count; ++index) {
|
|
raptor->sprite_data [index] = deallocate (raptor->sprite_data [index]);
|
|
}
|
|
|
|
for (uint index = 0; index < raptor->font_count; ++index) {
|
|
raptor->font_index [index] = deallocate (raptor->font_index [index]);
|
|
raptor->font_width [index] = deallocate (raptor->font_width [index]);
|
|
raptor->font_height [index] = deallocate (raptor->font_height [index]);
|
|
}
|
|
|
|
raptor->font_index = deallocate (raptor->font_index);
|
|
raptor->font_width = deallocate (raptor->font_width);
|
|
raptor->font_height = deallocate (raptor->font_height);
|
|
raptor->font_begin = deallocate (raptor->font_begin);
|
|
raptor->font_end = deallocate (raptor->font_end);
|
|
|
|
raptor->sprite_data = deallocate (raptor->sprite_data);
|
|
raptor->sprite_width = deallocate (raptor->sprite_width);
|
|
raptor->sprite_height = deallocate (raptor->sprite_height);
|
|
|
|
if (raptor->framebuffer != null) {
|
|
raptor->framebuffer = deallocate (raptor->framebuffer);
|
|
}
|
|
|
|
XFreePixmap (raptor->display, raptor->pixmap);
|
|
XFreeGC (raptor->display, raptor->context);
|
|
XUnmapWindow (raptor->display, raptor->window);
|
|
XDestroyWindow (raptor->display, raptor->window);
|
|
|
|
XCloseDisplay (raptor->display);
|
|
|
|
return (deallocate (raptor));
|
|
}
|
|
|
|
static uint raptor_sprite_raw_import (raptor_structure * raptor, uint * data, uint width, uint height) {
|
|
++raptor->sprite_count;
|
|
|
|
raptor->sprite_data = reallocate (raptor->sprite_data, raptor->sprite_count * sizeof (* raptor->sprite_data));
|
|
raptor->sprite_width = reallocate (raptor->sprite_width, raptor->sprite_count * sizeof (* raptor->sprite_width));
|
|
raptor->sprite_height = reallocate (raptor->sprite_height, raptor->sprite_count * sizeof (* raptor->sprite_height));
|
|
|
|
raptor->sprite_data [raptor->sprite_count - 1] = data;
|
|
raptor->sprite_width [raptor->sprite_count - 1] = width;
|
|
raptor->sprite_height [raptor->sprite_count - 1] = height;
|
|
|
|
return (raptor->sprite_count - 1);
|
|
}
|
|
|
|
static uint raptor_font_raw_import (raptor_structure * raptor, uint * data, uint image_width, char begin, char end, uint separator_colour) {
|
|
uint pointer = 0;
|
|
uint width = 0;
|
|
uint height = 0;
|
|
uint * buffer = null;
|
|
|
|
uint current = raptor->font_count;
|
|
|
|
++raptor->font_count;
|
|
|
|
raptor->font_index = reallocate (raptor->font_index, raptor->font_count * sizeof (* raptor->font_index));
|
|
raptor->font_width = reallocate (raptor->font_width, raptor->font_count * sizeof (* raptor->font_width));
|
|
raptor->font_height = reallocate (raptor->font_height, raptor->font_count * sizeof (* raptor->font_height));
|
|
raptor->font_begin = reallocate (raptor->font_begin, raptor->font_count * sizeof (* raptor->font_begin));
|
|
raptor->font_end = reallocate (raptor->font_end, raptor->font_count * sizeof (* raptor->font_end));
|
|
|
|
raptor->font_begin [current] = begin;
|
|
raptor->font_end [current] = end;
|
|
|
|
raptor->font_index [current] = allocate ((ulong) (end - begin + 1) * sizeof (* * raptor->font_index));
|
|
raptor->font_width [current] = allocate ((ulong) (end - begin + 1) * sizeof (* * raptor->font_width));
|
|
raptor->font_height [current] = allocate ((ulong) (end - begin + 1) * sizeof (* * raptor->font_height));
|
|
|
|
for (char index = begin; index <= end; ++index) {
|
|
for ( ; data [pointer] == separator_colour; ++pointer);
|
|
for (width = 0; data [pointer + width] != separator_colour; ++width);
|
|
for (height = 0; data [pointer + height * image_width] != separator_colour; ++height);
|
|
|
|
buffer = allocate (width * height * sizeof (* buffer));
|
|
|
|
for (uint y = 0; y < height; ++y) {
|
|
for (uint x = 0; x < width; ++x) {
|
|
buffer [y * width + x] = data [pointer + (y * image_width) + x];
|
|
}
|
|
}
|
|
|
|
raptor->font_index [current] [index - begin] = raptor_sprite_raw_import (raptor, buffer, width, height);
|
|
raptor->font_width [current] [index - begin] = width;
|
|
raptor->font_height [current] [index - begin] = height;
|
|
|
|
pointer += width;
|
|
|
|
for (; data [pointer] == separator_colour; ++pointer);
|
|
|
|
if (pointer % image_width == 2) {
|
|
pointer += height * image_width;
|
|
}
|
|
}
|
|
|
|
return (current);
|
|
}
|
|
|
|
static uint raptor_sprite_import (raptor_structure * raptor, char * path) {
|
|
uint width = 0;
|
|
uint height = 0;
|
|
uint * data = null;
|
|
|
|
data = format_image_import (path, & width, & height);
|
|
|
|
return (raptor_sprite_raw_import (raptor, data, width, height));
|
|
}
|
|
|
|
static uint raptor_font_import (raptor_structure * raptor, char * path, char begin, char end, uint colour) {
|
|
uint width = 0;
|
|
uint height = 0;
|
|
uint result = 0;
|
|
uint * data = null;
|
|
|
|
data = format_image_import (path, & width, & height);
|
|
|
|
result = raptor_font_raw_import (raptor, data, width, begin, end, colour);
|
|
|
|
data = deallocate (data);
|
|
|
|
return (result);
|
|
}
|
|
|
|
static uint raptor_sprite_width (raptor_structure * raptor, uint sprite) {
|
|
return (raptor->sprite_width [sprite]);
|
|
}
|
|
|
|
static uint raptor_sprite_height (raptor_structure * raptor, uint sprite) {
|
|
return (raptor->sprite_height [sprite]);
|
|
}
|
|
|
|
static uint raptor_character_width (raptor_structure * raptor, char character, uint font, float scale) {
|
|
if ((character < raptor->font_begin [font]) || (character > raptor->font_end [font])) {
|
|
return (0);
|
|
} else {
|
|
uint index = raptor->font_index [font] [character - raptor->font_begin [font]];
|
|
|
|
return ((uint) (scale * (float) raptor->sprite_width [index]));
|
|
}
|
|
}
|
|
|
|
static uint raptor_character_height (raptor_structure * raptor, char character, uint font, float scale) {
|
|
if ((character < raptor->font_begin [font]) || (character > raptor->font_end [font])) {
|
|
return (0);
|
|
} else {
|
|
uint index = raptor->font_index [font] [character - raptor->font_begin [font]];
|
|
|
|
return ((uint) (scale * (float) raptor->sprite_height [index]));
|
|
}
|
|
}
|
|
|
|
static uint raptor_string_width (raptor_structure * raptor, char * string, uint font, float scale) {
|
|
uint width = 0;
|
|
uint match = 0;
|
|
|
|
if (string == null) {
|
|
return (0);
|
|
}
|
|
|
|
for (uint index = 0; string [index] != '\0'; ++index) {
|
|
if (string [index] == '\t') {
|
|
width += raptor->tab_width * raptor_character_width (raptor, ' ', font, scale);
|
|
} else if (string [index] == '\n') {
|
|
match = maximum (width, match);
|
|
width = 0;
|
|
} else {
|
|
width += raptor_character_width (raptor, string [index], font, scale);
|
|
}
|
|
}
|
|
|
|
return (maximum (width, match));
|
|
}
|
|
|
|
static uint raptor_string_height (raptor_structure * raptor, char * string, uint font, float scale) {
|
|
uint height = raptor_character_height (raptor, ' ', font, scale);
|
|
|
|
if ((string == null) || (string [0] == '\0')) {
|
|
return (0);
|
|
}
|
|
|
|
for (uint index = 0; string [index] != '\0'; ++index) {
|
|
if (string [index] == '\n') {
|
|
height += raptor_character_height (raptor, ' ', font, scale);
|
|
}
|
|
}
|
|
|
|
return (height);
|
|
}
|
|
|
|
static uint raptor_center_x (raptor_structure * raptor, uint size) {
|
|
return ((raptor->window_width - size) / 2);
|
|
}
|
|
|
|
static uint raptor_center_y (raptor_structure * raptor, uint size) {
|
|
return ((raptor->window_height - size) / 2);
|
|
}
|
|
|
|
static bool raptor_cursor_inside (raptor_structure * raptor, int x, int y, uint width, uint height) {
|
|
return ((raptor->cursor_x > x)
|
|
&& (raptor->cursor_y > y)
|
|
&& (raptor->cursor_x < x + (int) width)
|
|
&& (raptor->cursor_y < y + (int) height));
|
|
}
|
|
|
|
static bool raptor_cursor_left_click (raptor_structure * raptor, int x, int y, uint width, uint height) {
|
|
if (raptor->cursor [cursor_left] == true) {
|
|
return (raptor_cursor_inside (raptor, x, y, width, height) == true);
|
|
}
|
|
|
|
return (false);
|
|
}
|
|
|
|
static bool raptor_cursor_right_click (raptor_structure * raptor, int x, int y, uint width, uint height) {
|
|
if (raptor->cursor [cursor_right] == true) {
|
|
return (raptor_cursor_inside (raptor, x, y, width, height));
|
|
}
|
|
|
|
return (false);
|
|
}
|
|
|
|
static void raptor_configure (raptor_structure * raptor, uint window_width, uint window_height, char * window_title) {
|
|
ulong font_bitmap [2 * 95] = {
|
|
0x0000000000000000, 0x0000000000000000, 0x0000101010101010, 0x1000101000000000, 0x0024242400000000, 0x0000000000000000,
|
|
0x00002424247e2424, 0x7e24242400000000, 0x0010107c9290907c, 0x1212927c10100000, 0x0000649468081010, 0x202c524c00000000,
|
|
0x000018242418304a, 0x4444443a00000000, 0x0010101000000000, 0x0000000000000000, 0x0000081020202020, 0x2020100800000000,
|
|
0x0000201008080808, 0x0808102000000000, 0x000000000024187e, 0x1824000000000000, 0x000000000010107c, 0x1010000000000000,
|
|
0x0000000000000000, 0x0000101020000000, 0x000000000000007e, 0x0000000000000000, 0x0000000000000000, 0x0000101000000000,
|
|
0x0000040408081010, 0x2020404000000000, 0x00003c4242464a52, 0x6242423c00000000, 0x0000081828080808, 0x0808083e00000000,
|
|
0x00003c4242020408, 0x1020407e00000000, 0x00003c4242021c02, 0x0242423c00000000, 0x000002060a122242, 0x7e02020200000000,
|
|
0x00007e4040407c02, 0x0202423c00000000, 0x00001c2040407c42, 0x4242423c00000000, 0x00007e0202040408, 0x0810101000000000,
|
|
0x00003c4242423c42, 0x4242423c00000000, 0x00003c424242423e, 0x0202043800000000, 0x0000000000101000, 0x0000101000000000,
|
|
0x0000000000101000, 0x0000101020000000, 0x0000000408102040, 0x2010080400000000, 0x00000000007e0000, 0x7e00000000000000,
|
|
0x0000004020100804, 0x0810204000000000, 0x00003c4242420408, 0x0800080800000000, 0x00007c829ea2a2a2, 0xa69a807e00000000,
|
|
0x00003c424242427e, 0x4242424200000000, 0x00007c4242427c42, 0x4242427c00000000, 0x00003c4242404040, 0x4042423c00000000,
|
|
0x0000784442424242, 0x4242447800000000, 0x00007e4040407840, 0x4040407e00000000, 0x00007e4040407840, 0x4040404000000000,
|
|
0x00003c424240404e, 0x4242423c00000000, 0x0000424242427e42, 0x4242424200000000, 0x0000381010101010, 0x1010103800000000,
|
|
0x00000e0404040404, 0x0444443800000000, 0x0000424448506060, 0x5048444200000000, 0x0000404040404040, 0x4040407e00000000,
|
|
0x000082c6aa929282, 0x8282828200000000, 0x000042424262524a, 0x4642424200000000, 0x00003c4242424242, 0x4242423c00000000,
|
|
0x00007c424242427c, 0x4040404000000000, 0x00003c4242424242, 0x42424a3c02000000, 0x00007c424242427c, 0x5048444200000000,
|
|
0x00003c4240403c02, 0x0242423c00000000, 0x0000fe1010101010, 0x1010101000000000, 0x0000424242424242, 0x4242423c00000000,
|
|
0x0000424242424224, 0x2424181800000000, 0x0000828282828292, 0x92aac68200000000, 0x0000424224241818, 0x2424424200000000,
|
|
0x0000828244442810, 0x1010101000000000, 0x00007e0202040810, 0x2040407e00000000, 0x0000382020202020, 0x2020203800000000,
|
|
0x0000404020201010, 0x0808040400000000, 0x0000380808080808, 0x0808083800000000, 0x0000102844000000, 0x0000000000000000,
|
|
0x0000000000000000, 0x0000007e00000000, 0x1008000000000000, 0x0000000000000000, 0x00000000003c023e, 0x4242423e00000000,
|
|
0x00004040407c4242, 0x4242427c00000000, 0x00000000003c4240, 0x4040423c00000000, 0x00000202023e4242, 0x4242423e00000000,
|
|
0x00000000003c4242, 0x7e40403c00000000, 0x00000e10107c1010, 0x1010101000000000, 0x00000000003e4242, 0x4242423e02023c00,
|
|
0x00004040407c4242, 0x4242424200000000, 0x0000101000301010, 0x1010103800000000, 0x00000404000c0404, 0x0404040444443800,
|
|
0x0000404040424448, 0x7048444200000000, 0x0000301010101010, 0x1010103800000000, 0x0000000000fc9292, 0x9292929200000000,
|
|
0x00000000007c4242, 0x4242424200000000, 0x00000000003c4242, 0x4242423c00000000, 0x00000000007c4242, 0x4242427c40404000,
|
|
0x00000000003e4242, 0x4242423e02020200, 0x00000000005e6040, 0x4040404000000000, 0x00000000003e4040, 0x3c02027c00000000,
|
|
0x00001010107c1010, 0x1010100e00000000, 0x0000000000424242, 0x4242423e00000000, 0x0000000000424242, 0x2424181800000000,
|
|
0x0000000000828292, 0x9292927c00000000, 0x0000000000424224, 0x1824424200000000, 0x0000000000424242, 0x4242423e02023c00,
|
|
0x00000000007e0408, 0x1020407e00000000, 0x00000c1010102010, 0x1010100c00000000, 0x0000101010101010, 0x1010101000000000,
|
|
0x0000300808080408, 0x0808083000000000, 0x000000000062928c, 0x0000000000000000
|
|
};
|
|
|
|
XSetWindowAttributes window_attributes;
|
|
|
|
uint * dumb_buffer = allocate (256 * sizeof (* dumb_buffer));
|
|
|
|
for (uint index = 0; index < 256; ++index) {
|
|
dumb_buffer [index] = 0xffffffff;
|
|
}
|
|
|
|
++raptor->font_count;
|
|
|
|
raptor->font_index = reallocate (raptor->font_index, raptor->font_count * sizeof (* raptor->font_index));
|
|
raptor->font_width = reallocate (raptor->font_width, raptor->font_count * sizeof (* raptor->font_width));
|
|
raptor->font_height = reallocate (raptor->font_height, raptor->font_count * sizeof (* raptor->font_height));
|
|
raptor->font_begin = reallocate (raptor->font_begin, raptor->font_count * sizeof (* raptor->font_begin));
|
|
raptor->font_end = reallocate (raptor->font_end, raptor->font_count * sizeof (* raptor->font_end));
|
|
|
|
raptor->font_begin [raptor->font_count - 1] = ' ';
|
|
raptor->font_end [raptor->font_count - 1] = '~';
|
|
|
|
raptor->font_index [raptor->font_count - 1] = allocate (95 * sizeof (* * raptor->font_index));
|
|
raptor->font_width [raptor->font_count - 1] = allocate (95 * sizeof (* * raptor->font_width));
|
|
raptor->font_height [raptor->font_count - 1] = allocate (95 * sizeof (* * raptor->font_height));
|
|
|
|
for (uint index = 0; index < 95; ++index) {
|
|
uint * buffer = allocate (8 * 16 * sizeof (* buffer));
|
|
|
|
for (uint value = 0; value < 2; ++value) {
|
|
for (uint bit = 64; bit > 0; --bit) {
|
|
uint destination = ((value << 3) - ((bit - 1) >> 3) + 7) * 8 - ((bit - 1) & 7) + 7;
|
|
uint source = (font_bitmap [2 * index + value] >> (bit - 1)) & 1;
|
|
|
|
buffer [destination] = (source) ? 0xffffffff : 0x00000000;
|
|
}
|
|
}
|
|
|
|
raptor->font_index [raptor->font_count - 1] [index] = raptor_sprite_raw_import (raptor, buffer, 8, 16);
|
|
raptor->font_width [raptor->font_count - 1] [index] = 8;
|
|
raptor->font_height [raptor->font_count - 1] [index] = 16;
|
|
}
|
|
|
|
raptor_sprite_raw_import (raptor, dumb_buffer, 16, 16);
|
|
|
|
raptor->window_width = window_width;
|
|
raptor->window_height = window_height;
|
|
|
|
raptor->display = XOpenDisplay (null);
|
|
|
|
int screen = DefaultScreen (raptor->display);
|
|
|
|
XMatchVisualInfo (raptor->display, screen, 32, TrueColor, & raptor->visual);
|
|
|
|
window_attributes.colormap = XCreateColormap (raptor->display, DefaultRootWindow (raptor->display), raptor->visual.visual, AllocNone);
|
|
|
|
window_attributes.border_pixel = 0x00000000;
|
|
window_attributes.background_pixel = 0x00000000;
|
|
|
|
raptor->window = XCreateWindow (raptor->display, DefaultRootWindow (raptor->display), 0, 0, window_width, window_height, 0,
|
|
raptor->visual.depth, InputOutput, raptor->visual.visual, CWColormap | CWBorderPixel | CWBackPixel,
|
|
& window_attributes);
|
|
|
|
XStoreName (raptor->display, raptor->window, window_title);
|
|
|
|
XSelectInput (raptor->display, raptor->window, ExposureMask | KeyPressMask | ButtonPressMask | StructureNotifyMask);
|
|
|
|
raptor->pixmap = XCreatePixmap (raptor->display, raptor->window, raptor->window_width, raptor->window_height, raptor->visual.depth);
|
|
|
|
raptor->context = XCreateGC (raptor->display, raptor->window, 0, null);
|
|
|
|
XSetForeground (raptor->display, raptor->context, BlackPixel (raptor->display, screen));
|
|
|
|
raptor->atom_close_button = XInternAtom (raptor->display, "WM_DELETE_WINDOW", false);
|
|
|
|
XSetWMProtocols (raptor->display, raptor->window, & raptor->atom_close_button, 1);
|
|
|
|
//~XGrabPointer(raptor->display, DefaultRootWindow (raptor->display), False, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None,
|
|
//~CurrentTime);
|
|
|
|
XMapWindow (raptor->display, raptor->window);
|
|
|
|
XFlush (raptor->display);
|
|
|
|
raptor->framebuffer = allocate (window_width * window_height * sizeof (* raptor->framebuffer));
|
|
|
|
raptor->active = true;
|
|
|
|
raptor->frame_begin = nano_time ();
|
|
}
|
|
|
|
static void raptor_render_base (raptor_structure * raptor, uint sprite, int x, int y, uint u, uint v, uint width, uint height, float scale_x,
|
|
float scale_y, int flip_x, int flip_y, uint upper_left, uint upper_right, uint lower_left, uint lower_right) {
|
|
(void) scale_x;
|
|
(void) scale_y;
|
|
(void) flip_x;
|
|
(void) flip_y;
|
|
/// FIX TO INTERPOLATE ALL 4 COLOURS
|
|
//~(void) upper_left;
|
|
(void) upper_right;
|
|
(void) lower_left;
|
|
(void) lower_right;
|
|
|
|
uint interpolate_pixels (uint pixel, uint modifier) {
|
|
uint r = (((pixel & 0xff000000) >> 24) * ((modifier & 0x000000ff) >> 0)) / 0xff;
|
|
uint g = (((pixel & 0x00ff0000) >> 16) * ((modifier & 0x0000ff00) >> 8)) / 0xff;
|
|
uint b = (((pixel & 0x0000ff00) >> 8) * ((modifier & 0x00ff0000) >> 16)) / 0xff;
|
|
uint a = (((pixel & 0x000000ff) >> 0) * ((modifier & 0xff000000) >> 24)) / 0xff;
|
|
|
|
return ((r << 24) | (g << 16) | (b << 8) | a);
|
|
}
|
|
|
|
if ((x + (int) width < 0) || (y + (int) height < 0) || (x > (int) raptor->window_width) || (y > (int) raptor->window_height)) return;
|
|
|
|
for (uint vertical = 0; vertical < height; ++vertical) {
|
|
if (vertical + y >= raptor->window_height) break;
|
|
if (vertical + v >= raptor->sprite_height [sprite]) break;
|
|
|
|
for (uint horizontal = 0; horizontal < width; ++horizontal) {
|
|
if (horizontal + x >= raptor->window_width) break;
|
|
if (horizontal + u >= raptor->sprite_width [sprite]) break;
|
|
|
|
uint pixel = raptor->sprite_data [sprite] [(vertical + v) * raptor->sprite_width [sprite] + horizontal + u];
|
|
uint at = (y + vertical) * raptor->window_width + (x + horizontal);
|
|
|
|
raptor->framebuffer [at] = (((pixel & 0xff000000) >> 24) > 0x77)
|
|
? interpolate_pixels (pixel, upper_left)
|
|
: raptor->framebuffer [at];
|
|
}
|
|
}
|
|
}
|
|
|
|
static void raptor_render_rectangle (raptor_structure * raptor, int x, int y, uint width, uint height, uint colour) {
|
|
raptor_render_base (raptor, raptor->sprite_count - 1, x, y, 0, 0, 16, 16, (float) width / 16, (float) height / 16, 0, 0, colour, colour,
|
|
colour, colour);
|
|
}
|
|
|
|
static void raptor_render_sprite (raptor_structure * raptor, uint sprite, int x, int y) {
|
|
uint width = raptor->sprite_width [sprite];
|
|
uint height = raptor->sprite_height [sprite];
|
|
|
|
raptor_render_base (raptor, sprite, x, y, 0, 0, width, height, 1.0f, 1.0f, 0, 0, 0xffffffffu, 0xffffffffu, 0xffffffffu, 0xffffffffu);
|
|
}
|
|
|
|
static void raptor_render_sprite_scale (raptor_structure * raptor, uint sprite, int x, int y, float scale_x, float scale_y) {
|
|
uint width = raptor->sprite_width [sprite];
|
|
uint height = raptor->sprite_height [sprite];
|
|
|
|
raptor_render_base (raptor, sprite, x, y, 0, 0, width, height, scale_x, scale_y, 0, 0, 0xffffffffu, 0xffffffffu, 0xffffffffu,
|
|
0xffffffffu);
|
|
}
|
|
|
|
static void raptor_render_sprite_crop (raptor_structure * raptor, uint sprite, int x, int y, uint u, uint v, uint width, uint height) {
|
|
raptor_render_base (raptor, sprite, x, y, u, v, width, height, 1.0f, 1.0f, 0, 0, 0xffffffffu, 0xffffffffu, 0xffffffffu, 0xffffffffu);
|
|
}
|
|
|
|
static void raptor_render_sprite_colour (raptor_structure * raptor, uint sprite, uint colour, int x, int y) {
|
|
uint width = raptor->sprite_width [sprite];
|
|
uint height = raptor->sprite_height [sprite];
|
|
|
|
raptor_render_base (raptor, sprite, x, y, 0, 0, width, height, 1.0f, 1.0f, 0, 0, colour, colour, colour, colour);
|
|
}
|
|
|
|
static void raptor_render_sprite_crop_colour (raptor_structure * raptor, uint sprite, uint colour, int x, int y, uint u, uint v, uint width, uint height) {
|
|
raptor_render_base (raptor, sprite, x, y, u, v, width, height, 1.0f, 1.0f, 0, 0, colour, colour, colour, colour);
|
|
}
|
|
|
|
static void raptor_render_sprite_flip (raptor_structure * raptor, uint sprite, int x, int y, int flip_x, int flip_y) {
|
|
uint width = raptor->sprite_width [sprite];
|
|
uint height = raptor->sprite_height [sprite];
|
|
|
|
raptor_render_base (raptor, sprite, x, y, 0, 0, width, height, 1.0f, 1.0f, flip_x, flip_y, 0xffffffffu, 0xffffffffu, 0xffffffffu,
|
|
0xffffffffu);
|
|
}
|
|
|
|
static void raptor_render_sprite_animate (raptor_structure * raptor, uint sprite, int x, int y, uint frames, uint state, uint states) {
|
|
uint width = raptor->sprite_width [sprite] / states;
|
|
uint height = raptor->sprite_height [sprite] / frames;
|
|
|
|
uint u = width * (state % states);
|
|
uint v = height * (raptor->animation_tick % frames);
|
|
|
|
raptor_render_sprite_crop (raptor, sprite, x, y, u, v, width, height);
|
|
}
|
|
|
|
static void raptor_render_character (raptor_structure * raptor, char character, uint font, int x, int y, float scale, uint colour) {
|
|
if ((character < raptor->font_begin [font]) || (character > raptor->font_end [font])) return;
|
|
|
|
uint index = raptor->font_index [font] [character - raptor->font_begin [font]];
|
|
|
|
uint width = raptor->sprite_width [index];
|
|
uint height = raptor->sprite_height [index];
|
|
|
|
raptor_render_base (raptor, index, x, y, 0, 0, width, height, scale, scale, 0, 0, colour, colour, colour, colour);
|
|
}
|
|
|
|
static void raptor_render_string (raptor_structure * raptor, char * string, uint font, int x, int y, float scale, uint colour) {
|
|
int offset = x;
|
|
|
|
if (string == null) return;
|
|
|
|
for (uint index = 0; string [index] != '\0'; ++index) {
|
|
if (string [index] == '\t') {
|
|
x += raptor->tab_width * raptor_character_width (raptor, ' ', font, scale);
|
|
continue;
|
|
} else if (string [index] == '\n') {
|
|
x = offset;
|
|
y += raptor_character_height (raptor, ' ', font, scale);
|
|
continue;
|
|
} else {
|
|
raptor_render_character (raptor, string [index], font, x, y, scale, colour);
|
|
|
|
x += raptor_character_width (raptor, string [index], font, scale);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void raptor_render_framerate (raptor_structure * raptor, uint font, int x, int y, float scale, uint colour) {
|
|
raptor_render_string (raptor, number_to_string (raptor->framerate), font, x, y, scale, colour);
|
|
}
|
|
|
|
static void raptor_synchronize (raptor_structure * raptor, uint clear_colour) {
|
|
uint signal_code [signal_count] = {
|
|
0,
|
|
38, 56, 54, 40, 26, 41, 42, 43, 31, 44, 45, 46, 58, 57, 32, 33,
|
|
24, 27, 39, 28, 30, 55, 25, 53, 29, 52, 19, 10, 11, 12, 13, 14,
|
|
15, 16, 17, 18, 9, 23, 36, 36, 61, 51, 47, 49, 65, 22, 60, 59,
|
|
48, 66, 20, 21, 34, 35, 37, 105, 50, 62, 64, 108, 67, 68, 69, 70,
|
|
71, 72, 73, 74, 75, 76, 95, 96, 111, 116, 113, 114, 77, 127, 118, 110,
|
|
112, 119, 115, 117, 86, 82, 63, 106, 104, 91, 90, 87, 88, 89, 83, 84,
|
|
85, 79, 80, 81
|
|
};
|
|
|
|
uint new_window_width = raptor->window_width;
|
|
uint new_window_height = raptor->window_height;
|
|
|
|
XEvent event = { 0 };
|
|
//~Window root_window = { 0 };
|
|
|
|
//~int root_x = 0;
|
|
//~int root_y = 0;
|
|
//~uint mask = 0;
|
|
|
|
for (uint index = 0; index < cursor_count; ++index) {
|
|
raptor->cursor [index] = false;
|
|
}
|
|
|
|
for (uint index = 0; index < signal_count; ++index) {
|
|
raptor->signal [index] = false;
|
|
}
|
|
|
|
//~XQueryPointer (raptor->display, raptor->window, & root_window, & root_window, & root_x, & root_y, & root_x, & root_y, & mask);
|
|
|
|
XNextEvent (raptor->display, & event);
|
|
|
|
switch (event.type) {
|
|
case (Expose): {
|
|
XFlush (raptor->display);
|
|
} break;
|
|
case (ClientMessage): {
|
|
if ((Atom) event.xclient.data.l [0] == raptor->atom_close_button) {
|
|
raptor->active = false;
|
|
return;
|
|
}
|
|
} break;
|
|
case (ConfigureNotify): {
|
|
new_window_width = event.xconfigure.width;
|
|
new_window_height = event.xconfigure.height;
|
|
} break;
|
|
case (ButtonPress): {
|
|
if (event.xbutton.button == Button1) raptor->cursor [cursor_left] = true;
|
|
if (event.xbutton.button == Button2) raptor->cursor [cursor_middle] = true;
|
|
if (event.xbutton.button == Button3) raptor->cursor [cursor_right] = true;
|
|
raptor->cursor_x = event.xbutton.x;
|
|
raptor->cursor_y = event.xbutton.y;
|
|
} break;
|
|
case (KeyPress): {
|
|
for (uint index = 0; index < signal_count; ++index) {
|
|
if (event.xkey.keycode == signal_code [index]) {
|
|
raptor->signal [index] = true;
|
|
}
|
|
}
|
|
} break;
|
|
default: {
|
|
//~XFlush (raptor->display);
|
|
return;
|
|
} break;
|
|
}
|
|
|
|
for (uint pixel = 0; pixel < raptor->window_width * raptor->window_height; ++pixel) {
|
|
uint r = (raptor->framebuffer [pixel] & 0x00ff0000) >> 16;
|
|
uint b = (raptor->framebuffer [pixel] & 0x000000ff) << 16;
|
|
|
|
raptor->framebuffer [pixel] = (raptor->framebuffer [pixel] & 0xff00ff00) | b | r;
|
|
}
|
|
|
|
raptor->image = XCreateImage (raptor->display, raptor->visual.visual, raptor->visual.depth, ZPixmap, 0, (char *) raptor->framebuffer,
|
|
raptor->window_width, raptor->window_height, 32, 0);
|
|
|
|
XPutImage (raptor->display, raptor->pixmap, raptor->context, raptor->image, 0, 0, 0, 0, raptor->window_width, raptor->window_height);
|
|
|
|
XCopyArea (raptor->display, raptor->pixmap, raptor->window, raptor->context, 0, 0, raptor->window_width, raptor->window_height, 0, 0);
|
|
|
|
XDestroyImage (raptor->image);
|
|
|
|
if ((new_window_width != raptor->window_width) || (new_window_height != raptor->window_height)) {
|
|
XFreePixmap (raptor->display, raptor->pixmap);
|
|
|
|
raptor->pixmap = XCreatePixmap (raptor->display, raptor->window, new_window_width, new_window_height, raptor->visual.depth);
|
|
|
|
raptor->window_width = new_window_width;
|
|
raptor->window_height = new_window_height;
|
|
}
|
|
|
|
raptor->framebuffer = allocate (raptor->window_width * raptor->window_height * sizeof (* raptor->framebuffer));
|
|
|
|
clear_colour = colour_channel_reverse (clear_colour);
|
|
|
|
for (uint pixel = 0; pixel < raptor->window_width * raptor->window_height; ++pixel) {
|
|
raptor->framebuffer [pixel] = clear_colour;
|
|
}
|
|
|
|
raptor->frame_end = nano_time ();
|
|
|
|
raptor->frame_time = raptor->frame_end - raptor->frame_begin;
|
|
|
|
if (raptor->frame_time < 1000000000ul / raptor->gameplay_framerate) {
|
|
nano_wait (1000000000ul / raptor->gameplay_framerate - raptor->frame_time);
|
|
}
|
|
|
|
if (raptor->global_tick % raptor->gameplay_framerate == 0) {
|
|
raptor->framerate = (uint) (1000000000ul / raptor->frame_time);
|
|
}
|
|
|
|
++raptor->global_tick;
|
|
|
|
raptor->global_tick = raptor->global_tick % (raptor->gameplay_framerate * raptor->animation_framerate);
|
|
|
|
raptor->gameplay_tick = raptor->global_tick / raptor->animation_framerate;
|
|
raptor->animation_tick = raptor->global_tick / raptor->gameplay_framerate;
|
|
|
|
raptor->frame_begin = nano_time ();
|
|
}
|
|
|
|
////////////// MOVE ME PLEASE
|
|
|
|
static void raptor_render_rectangle_vertical_gradient (raptor_structure * raptor, int x, int y, uint width, uint height, uint colour_up,
|
|
uint colour_down) {
|
|
raptor_render_base (raptor, raptor->sprite_count - 1, x, y, 0, 0, 16, 16, (float) width / 16.0f, (float) height / 16.0f, 0, 0,
|
|
colour_up, colour_up, colour_down, colour_down);
|
|
}
|