/// _ /// __ ____ _ _ __ | |_ ___ _ __ /// \ \/ / _` | '_ \| __/ _ \| '__| /// > < (_| | |_) | || (_) | | /// /_/\_\__,_| .__/ \__\___/|_| /// |_| /// /// 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 #include typedef struct { Display * display; Window window; XVisualInfo visual; GC context; Pixmap pixmap; XImage * image; Atom atom_close_button; Atom atom_transparency; boolean signal [signal_count]; boolean cursor [cursor_count]; integer cursor_x; integer cursor_y; natural gameplay_framerate; natural animation_framerate; natural window_width; natural window_height; boolean active; natural framerate; natural_64 frame_time; natural_64 frame_begin; natural_64 frame_end; natural * framebuffer; natural global_tick; natural gameplay_tick; natural animation_tick; natural tab_width; natural sprite_count; natural font_count; natural * * sprite_data; natural * sprite_width; natural * sprite_height; natural * * font_index; natural * * font_width; natural * * font_height; character * font_begin; character * font_end; } raptor_structure; static raptor_structure * raptor_initialize (natural gameplay_framerate, natural 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 (natural index = 0; index < raptor->sprite_count; ++index) { raptor->sprite_data [index] = deallocate (raptor->sprite_data [index]); } for (natural 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 natural raptor_sprite_raw_import (raptor_structure * raptor, natural * data, natural width, natural 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 natural raptor_font_raw_import (raptor_structure * raptor, natural * data, natural image_width, natural image_height, character begin, character end, natural empty) { natural current = ++raptor->font_count - 1; natural pointer = 0; natural width = 0; natural height = 0; natural point_count = 0; natural * point_array = null; fatal_failure (raptor->active == true, "raptor_font_raw_import: Raptor renderer is already initialized."); fatal_failure (data == null, "raptor_font_raw_import: Data is null pointer."); fatal_failure (image_width == 0, "raptor_font_raw_import: Font image width is zero."); fatal_failure (image_height == 0, "raptor_font_raw_import: Font image height is zero."); fatal_failure (begin >= end, "raptor_font_raw_import: Font character range is inverted."); 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 ((caliber) (end - begin + 1) * sizeof (* * raptor->font_index)); raptor->font_width [current] = allocate ((caliber) (end - begin + 1) * sizeof (* * raptor->font_width)); raptor->font_height [current] = allocate ((caliber) (end - begin + 1) * sizeof (* * raptor->font_height)); point_array = allocate ((caliber) (end - begin + 1) * sizeof (* point_array)); if (empty == 0x00000000u) { empty = data [0]; } for (natural y = 0; y < image_height - 1; ++y) { for (natural x = 0; x < image_width - 1; ++x) { if ((data [(y + 0) * image_width + (x + 0)] == empty) && (data [(y + 1) * image_width + (x + 0)] == empty) && (data [(y + 0) * image_width + (x + 1)] == empty) && (data [(y + 1) * image_width + (x + 1)] == 0x00000000u)) { ++point_count; point_array [point_count - 1] = (y + 1) * image_width + (x + 1); } } } if (point_count != end - begin + 1) { print ("/w Mismatch between font character points:\n"); print ("/c --- Hardcoded expected number of character points: %i\n", end - begin + 1); print ("/c --- Algorithm found number of character points: %i\n", point_count); } for (natural index = 0; index < end - begin + 1; ++index) { for (width = 0; data [point_array [index] + width] != empty; ++width); for (height = 0; data [point_array [index] + height * image_width] != empty; ++height); fatal_failure (width == 0, "raptor_font_raw_import: Font width is zero."); fatal_failure (height == 0, "raptor_font_raw_import: Font height is zero."); natural * buffer = allocate (width * height * sizeof (* buffer)); for (natural y = 0; y < height; ++y) { for (natural x = 0; x < width; ++x) { buffer [y * width + x] = data [point_array [index] + y * image_width + x]; } } raptor->font_index [current] [index] = raptor_sprite_raw_import (raptor, buffer, width, height); raptor->font_width [current] [index] = width; raptor->font_height [current] [index] = height; } point_array = deallocate (point_array); return (current); } static natural raptor_sprite_import (raptor_structure * raptor, character * path) { natural width = 0; natural height = 0; natural * data = null; data = format_image_import (path, & width, & height); return (raptor_sprite_raw_import (raptor, data, width, height)); } static natural raptor_font_import (raptor_structure * raptor, character * path, character begin, character end, natural colour) { natural width = 0; natural height = 0; natural result = 0; natural * data = null; data = format_image_import (path, & width, & height); result = raptor_font_raw_import (raptor, data, width, height, begin, end, colour); data = deallocate (data); return (result); } static natural raptor_sprite_width (raptor_structure * raptor, natural sprite) { return (raptor->sprite_width [sprite]); } static natural raptor_sprite_height (raptor_structure * raptor, natural sprite) { return (raptor->sprite_height [sprite]); } static natural raptor_character_width (raptor_structure * raptor, character data, natural font, real scale) { if ((data < raptor->font_begin [font]) || (data > raptor->font_end [font])) { return (0); } else { natural index = raptor->font_index [font] [data - raptor->font_begin [font]]; return ((natural) (scale * (real) raptor->sprite_width [index])); } } static natural raptor_character_height (raptor_structure * raptor, character data, natural font, real scale) { if ((data < raptor->font_begin [font]) || (data > raptor->font_end [font])) { return (0); } else { natural index = raptor->font_index [font] [data - raptor->font_begin [font]]; return ((natural) (scale * (real) raptor->sprite_height [index])); } } static natural raptor_string_width (raptor_structure * raptor, character * string, natural font, real scale) { natural width = 0; natural match = 0; if (string == null) { return (0); } for (natural 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 natural raptor_string_height (raptor_structure * raptor, character * string, natural font, real scale) { natural height = raptor_character_height (raptor, ' ', font, scale); if ((string == null) || (string [0] == '\0')) { return (0); } for (natural index = 0; string [index] != '\0'; ++index) { if (string [index] == '\n') { height += raptor_character_height (raptor, ' ', font, scale); } } return (height); } static natural raptor_center_x (raptor_structure * raptor, natural size) { return ((raptor->window_width - size) / 2); } static natural raptor_center_y (raptor_structure * raptor, natural size) { return ((raptor->window_height - size) / 2); } static boolean raptor_cursor_inside (raptor_structure * raptor, integer x, integer y, natural width, natural height) { return ((raptor->cursor_x > x) && (raptor->cursor_y > y) && (raptor->cursor_x < x + (integer) width) && (raptor->cursor_y < y + (integer) height)); } static boolean raptor_cursor_left_click (raptor_structure * raptor, integer x, integer y, natural width, natural height) { if (raptor->cursor [cursor_left] == true) { return (raptor_cursor_inside (raptor, x, y, width, height) == true); } return (false); } static boolean raptor_cursor_right_click (raptor_structure * raptor, integer x, integer y, natural width, natural height) { if (raptor->cursor [cursor_right] == true) { return (raptor_cursor_inside (raptor, x, y, width, height)); } return (false); } static procedure raptor_configure (raptor_structure * raptor, natural window_width, natural window_height, character * window_title) { natural_64 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; natural * dumb_buffer = allocate (256 * sizeof (* dumb_buffer)); for (natural 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 (natural index = 0; index < 95; ++index) { natural * buffer = allocate (8 * 16 * sizeof (* buffer)); for (natural value = 0; value < 2; ++value) { for (natural bit = 64; bit > 0; --bit) { natural destination = ((value << 3) - ((bit - 1) >> 3) + 7) * 8 - ((bit - 1) & 7) + 7; natural 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); integer 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 procedure raptor_render_base (raptor_structure * raptor, natural sprite, integer x, integer y, natural u, natural v, natural width, natural height, real scale_x, real scale_y, integer flip_x, integer flip_y, natural upper_left, natural upper_right, natural lower_left, natural lower_right) { (none) scale_x; (none) scale_y; (none) flip_x; (none) flip_y; /// FIX TO INTERPOLATE ALL 4 COLOURS //~(none) upper_left; (none) upper_right; (none) lower_left; (none) lower_right; natural interpolate_pixels (natural pixel, natural modifier) { natural r = (((pixel & 0xff000000) >> 24) * ((modifier & 0x000000ff) >> 0)) / 0xff; natural g = (((pixel & 0x00ff0000) >> 16) * ((modifier & 0x0000ff00) >> 8)) / 0xff; natural b = (((pixel & 0x0000ff00) >> 8) * ((modifier & 0x00ff0000) >> 16)) / 0xff; natural a = (((pixel & 0x000000ff) >> 0) * ((modifier & 0xff000000) >> 24)) / 0xff; return ((r << 24) | (g << 16) | (b << 8) | a); } if ((x + (integer) width < 0) || (y + (integer) height < 0) || (x > (integer) raptor->window_width) || (y > (integer) raptor->window_height)) return; for (natural vertical = 0; vertical < height; ++vertical) { if (vertical + y >= raptor->window_height) break; if (vertical + v >= raptor->sprite_height [sprite]) break; for (natural horizontal = 0; horizontal < width; ++horizontal) { if (horizontal + x >= raptor->window_width) break; if (horizontal + u >= raptor->sprite_width [sprite]) break; natural pixel = raptor->sprite_data [sprite] [(vertical + v) * raptor->sprite_width [sprite] + horizontal + u]; natural at = (y + vertical) * raptor->window_width + (x + horizontal); raptor->framebuffer [at] = (((pixel & 0xff000000) >> 24) > 0x77) ? interpolate_pixels (pixel, upper_left) : raptor->framebuffer [at]; } } } static procedure raptor_render_rectangle (raptor_structure * raptor, integer x, integer y, natural width, natural height, natural colour) { raptor_render_base (raptor, raptor->sprite_count - 1, x, y, 0, 0, 16, 16, (real) width / 16, (real) height / 16, 0, 0, colour, colour, colour, colour); } static procedure raptor_render_sprite (raptor_structure * raptor, natural sprite, integer x, integer y) { natural width = raptor->sprite_width [sprite]; natural 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 procedure raptor_render_sprite_scale (raptor_structure * raptor, natural sprite, integer x, integer y, real scale_x, real scale_y) { natural width = raptor->sprite_width [sprite]; natural 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 procedure raptor_render_sprite_crop (raptor_structure * raptor, natural sprite, integer x, integer y, natural u, natural v, natural width, natural height) { raptor_render_base (raptor, sprite, x, y, u, v, width, height, 1.0f, 1.0f, 0, 0, 0xffffffffu, 0xffffffffu, 0xffffffffu, 0xffffffffu); } static procedure raptor_render_sprite_colour (raptor_structure * raptor, natural sprite, natural colour, integer x, integer y) { natural width = raptor->sprite_width [sprite]; natural 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 procedure raptor_render_sprite_flip (raptor_structure * raptor, natural sprite, integer x, integer y, integer flip_x, integer flip_y) { natural width = raptor->sprite_width [sprite]; natural 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 procedure raptor_render_sprite_animation (raptor_structure * raptor, natural sprite, integer x, integer y, natural frames, natural state, natural states) { natural width = raptor->sprite_width [sprite] / states; natural height = raptor->sprite_height [sprite] / frames; natural u = width * (state % states); natural v = height * (raptor->animation_tick % frames); raptor_render_sprite_crop (raptor, sprite, x, y, u, v, width, height); } static procedure raptor_render_sprite_crop_colour (raptor_structure * raptor, natural sprite, natural colour, integer x, integer y, natural u, natural v, natural width, natural height) { raptor_render_base (raptor, sprite, x, y, u, v, width, height, 1.0f, 1.0f, 0, 0, colour, colour, colour, colour); } static procedure raptor_render_character (raptor_structure * raptor, character data, natural font, integer x, integer y, real scale, natural colour) { if ((data < raptor->font_begin [font]) || (data > raptor->font_end [font])) return; natural index = raptor->font_index [font] [data - raptor->font_begin [font]]; natural width = raptor->sprite_width [index]; natural 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 procedure raptor_render_string (raptor_structure * raptor, character * string, natural font, integer x, integer y, real scale, natural colour) { integer offset = x; if (string == null) return; for (natural 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 procedure raptor_render_framerate (raptor_structure * raptor, natural font, integer x, integer y, real scale, natural colour) { raptor_render_string (raptor, number_to_string (raptor->framerate), font, x, y, scale, colour); } static procedure raptor_synchronize (raptor_structure * raptor, natural clear_colour) { natural 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 }; natural new_window_width = raptor->window_width; natural new_window_height = raptor->window_height; XEvent event = { 0 }; //~Window root_window = { 0 }; //~integer root_x = 0; //~integer root_y = 0; //~natural mask = 0; for (natural index = 0; index < cursor_count; ++index) { raptor->cursor [index] = false; } for (natural 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 (natural 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 (natural pixel = 0; pixel < raptor->window_width * raptor->window_height; ++pixel) { natural r = (raptor->framebuffer [pixel] & 0x00ff0000) >> 16; natural 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, (character *) 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 (natural 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 = (natural) (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 procedure raptor_render_rectangle_vertical_gradient (raptor_structure * raptor, integer x, integer y, natural width, natural height, natural colour_up, natural colour_down) { raptor_render_base (raptor, raptor->sprite_count - 1, x, y, 0, 0, 16, 16, (real) width / 16.0f, (real) height / 16.0f, 0, 0, colour_up, colour_up, colour_down, colour_down); }