mkxp-sunshine/journal/linux/niko.c
Mathew Velasquez aa7818847c Lots of stuff
2016-12-06 23:49:37 -05:00

114 lines
3.5 KiB
C

#include <sys/time.h>
#include "display.h"
#include "image.h"
static uint64_t getticks()
{
struct timeval tv;
gettimeofday(&tv, NULL);
return (uint64_t)tv.tv_sec * 1000 + (uint64_t)tv.tv_usec / 1000;
}
static void draw_niko(xcb_connection_t *c,
xcb_window_t win,
xcb_gcontext_t gc,
xcb_pixmap_t masks[3],
xcb_pixmap_t images[3],
int x, int y, int w, int h,
int offset)
{
int frame;
if (offset % 32 >= 16) {
frame = 1;
} else {
if ((offset / 32) % 2)
frame = 0;
else
frame = 2;
}
xcb_shape_mask(c, ShapeSet, ShapeBounding, win, 0, 0, masks[frame]);
xcb_copy_area(c, images[frame], win, gc, x, y, x, y, w, h);
}
int do_niko(struct Display *dpy, int x, int y)
{
// Create window
uint32_t values[] = {
true, // override_redirect
XCB_EVENT_MASK_EXPOSURE, // event mask
};
xcb_window_t window = xcb_generate_id(dpy->c);
xcb_create_window(dpy->c, XCB_COPY_FROM_PARENT, window, dpy->screen->root,
x, y, NIKO_WIDTH, NIKO_HEIGHT,
0, XCB_WINDOW_CLASS_INPUT_OUTPUT, dpy->screen->root_visual,
XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK, &values);
// Stick window on top
xcb_stack_mode_t stack = XCB_STACK_MODE_ABOVE;
xcb_configure_window(dpy->c, window, XCB_CONFIG_WINDOW_STACK_MODE, &stack);
// Create pixmaps
xcb_pixmap_t niko_masks[] = {
create_mask(dpy->c, window, niko1_mask, NIKO_WIDTH, NIKO_HEIGHT),
create_mask(dpy->c, window, niko2_mask, NIKO_WIDTH, NIKO_HEIGHT),
create_mask(dpy->c, window, niko3_mask, NIKO_WIDTH, NIKO_HEIGHT),
};
xcb_pixmap_t niko_images[] = {
create_image(dpy->c, window, niko1_rgb, NIKO_WIDTH, NIKO_HEIGHT),
create_image(dpy->c, window, niko2_rgb, NIKO_WIDTH, NIKO_HEIGHT),
create_image(dpy->c, window, niko3_rgb, NIKO_WIDTH, NIKO_HEIGHT),
};
// Create graphics context
xcb_gcontext_t gc = xcb_generate_id(dpy->c);
xcb_create_gc(dpy->c, gc, window, 0, NULL);
// Map!
xcb_map_window(dpy->c, window);
xcb_flush(dpy->c);
// Niko movement info
int niko_offset = 0;
uint64_t ticks = getticks();
for (;;) {
// Handle events
for (;;) {
xcb_generic_event_t *e = xcb_poll_for_event(dpy->c);
if (e) {
switch (e->response_type) {
case XCB_EXPOSE: {
xcb_expose_event_t *ee = (xcb_expose_event_t*)e;
draw_niko(dpy->c, window, gc, niko_masks, niko_images,
ee->x, ee->y, ee->width, ee->height, niko_offset);
xcb_flush(dpy->c);
} break;
}
free(e);
} else if (getticks() - ticks >= 1000 / 60) {
break;
}
}
// Move niko
niko_offset += 2;
int new_y = y + niko_offset;
if (new_y > dpy->screen->height_in_pixels)
break;
xcb_configure_window(dpy->c, window, XCB_CONFIG_WINDOW_Y, &new_y);
draw_niko(dpy->c, window, gc, niko_masks, niko_images, 0, 0, NIKO_WIDTH, NIKO_HEIGHT, niko_offset);
xcb_flush(dpy->c);
ticks = getticks();
}
// Free up stuff
xcb_free_gc(dpy->c, gc);
for (int i = 0; i < 3; ++i) {
xcb_free_pixmap(dpy->c, niko_masks[i]);
xcb_free_pixmap(dpy->c, niko_images[i]);
}
return 0;
}