4c67b5da84
The compositor itself still needs work, but the compositing engine within now does full blitting and is faster than the old method. Transparency is now supported properly, though telling the compositor to use it on a window will degrade performance. One terminal is usually okay, and everything runs faster than it did before; two terminals is pushing it; three will make you very sad. The stacking logic has also been updated. Presumably, alpha blitting for transparent windows could be done with SIMD instructions and be extremely fast. All graphics libraries have also been updated to (hopefully) work properly with alpha bits.
272 lines
5.0 KiB
C
272 lines
5.0 KiB
C
/*
|
|
* The ToAru Sample Game
|
|
*
|
|
* This is the updated, windowed version of the sample RPG
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdint.h>
|
|
#include <syscall.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <time.h>
|
|
|
|
#include "lib/window.h"
|
|
#include "lib/graphics.h"
|
|
#include "lib/decorations.h"
|
|
|
|
sprite_t * sprites[128];
|
|
window_t * window;
|
|
|
|
gfx_context_t * ctx;
|
|
|
|
#define WINDOW_SIZE 224
|
|
int out_of_bounds(int x, int y) {
|
|
if (x < ctx->width / 2 - WINDOW_SIZE)
|
|
return 1;
|
|
if (x >= ctx->width / 2 + WINDOW_SIZE)
|
|
return 1;
|
|
if (y < ctx->height / 2 - WINDOW_SIZE)
|
|
return 1;
|
|
if (y >= ctx->height / 2 + WINDOW_SIZE)
|
|
return 1;
|
|
return 0;
|
|
}
|
|
|
|
/* RPG Mapping Bits */
|
|
struct {
|
|
int width;
|
|
int height;
|
|
char * buffer;
|
|
int size;
|
|
} map;
|
|
|
|
void load_map(char * filename) {
|
|
FILE * f = fopen(filename, "r");
|
|
char tmp[256];
|
|
fgets(tmp, 255, f);
|
|
map.width = atoi(tmp);
|
|
fgets(tmp, 256, f);
|
|
map.height = atoi(tmp);
|
|
map.size = map.height * map.width;
|
|
map.buffer = malloc(map.size);
|
|
fread(map.buffer, map.size, 1, f);
|
|
fclose(f);
|
|
}
|
|
|
|
char cell(int x, int y) {
|
|
if (x < 0 || y < 0 || x >= map.width || y >= map.height) {
|
|
return 'A'; /* The abyss is trees! */
|
|
}
|
|
return (map.buffer[y * map.width + x]);
|
|
}
|
|
|
|
#define VIEW_SIZE 4
|
|
#define CELL_SIZE 64
|
|
|
|
int my_x = 2;
|
|
int my_y = 2;
|
|
int direction = 0;
|
|
int offset_x = 0;
|
|
int offset_y = 0;
|
|
int offset_iter = 0;
|
|
int map_x;
|
|
int map_y;
|
|
|
|
void render_map(int x, int y) {
|
|
int i = 0;
|
|
for (int _y = y - VIEW_SIZE; _y <= y + VIEW_SIZE; ++_y) {
|
|
int j = 0;
|
|
for (int _x = x - VIEW_SIZE; _x <= x + VIEW_SIZE; ++_x) {
|
|
char c = cell(_x,_y);
|
|
int sprite;
|
|
switch (c) {
|
|
case '\n':
|
|
case 'A':
|
|
sprite = 1;
|
|
break;
|
|
case '.':
|
|
sprite = 2;
|
|
break;
|
|
case 'W':
|
|
sprite = 3;
|
|
break;
|
|
default:
|
|
sprite = 0;
|
|
break;
|
|
}
|
|
draw_sprite(ctx, sprites[sprite],
|
|
decor_left_width + map_x + offset_x * offset_iter + j * CELL_SIZE,
|
|
decor_top_height + map_y + offset_y * offset_iter + i * CELL_SIZE);
|
|
++j;
|
|
}
|
|
++i;
|
|
}
|
|
}
|
|
|
|
|
|
void display() {
|
|
render_map(my_x,my_y);
|
|
draw_sprite(ctx, sprites[124 + direction], decor_left_width + map_x + CELL_SIZE * 4, decor_top_height + map_y + CELL_SIZE * 4);
|
|
render_decorations(window, ctx->backbuffer, "RPG Demo");
|
|
flip(ctx);
|
|
}
|
|
|
|
void transition(int nx, int ny) {
|
|
if (nx < my_x) {
|
|
offset_x = 1;
|
|
offset_y = 0;
|
|
} else if (ny < my_y) {
|
|
offset_x = 0;
|
|
offset_y = 1;
|
|
} else if (nx > my_x) {
|
|
offset_x = -1;
|
|
offset_y = 0;
|
|
} else if (ny > my_y) {
|
|
offset_x = 0;
|
|
offset_y = -1;
|
|
}
|
|
for (int i = 0; i < 64; i += 2) {
|
|
offset_iter = i;
|
|
display();
|
|
}
|
|
offset_iter = 0;
|
|
offset_x = 0;
|
|
offset_y = 0;
|
|
my_x = nx;
|
|
my_y = ny;
|
|
display();
|
|
}
|
|
|
|
void move(int cx, int cy) {
|
|
int nx = my_x + cx;
|
|
int ny = my_y + cy;
|
|
|
|
if (cx == 1) {
|
|
if (direction != 1) {
|
|
direction = 1;
|
|
display();
|
|
return;
|
|
}
|
|
} else if (cx == -1) {
|
|
if (direction != 2) {
|
|
direction = 2;
|
|
display();
|
|
return;
|
|
}
|
|
} else if (cy == 1) {
|
|
if (direction != 0) {
|
|
direction = 0;
|
|
display();
|
|
return;
|
|
}
|
|
} else if (cy == -1) {
|
|
if (direction != 3) {
|
|
direction = 3;
|
|
display();
|
|
return;
|
|
}
|
|
}
|
|
|
|
switch (cell(nx,ny)) {
|
|
case '_':
|
|
case '.':
|
|
transition(nx,ny);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
display();
|
|
}
|
|
|
|
/* woah */
|
|
char font_buffer[400000];
|
|
sprite_t alpha_tmp;
|
|
|
|
void init_sprite(int i, char * filename, char * alpha) {
|
|
sprites[i] = malloc(sizeof(sprite_t));
|
|
load_sprite(sprites[i], filename);
|
|
if (alpha) {
|
|
sprites[i]->alpha = ALPHA_MASK;
|
|
load_sprite(&alpha_tmp, alpha);
|
|
sprites[i]->masks = alpha_tmp.bitmap;
|
|
} else {
|
|
sprites[i]->alpha = ALPHA_INDEXED;
|
|
}
|
|
sprites[i]->blank = 0x0;
|
|
}
|
|
|
|
int main(int argc, char ** argv) {
|
|
setup_windowing();
|
|
|
|
window = window_create(10,10, 2 * WINDOW_SIZE, 2 * WINDOW_SIZE);
|
|
ctx = init_graphics_window_double_buffer(window);
|
|
draw_fill(ctx,rgb(0,0,0));
|
|
|
|
init_decorations();
|
|
|
|
map_x = WINDOW_SIZE - (64 * 9) / 2;
|
|
map_y = WINDOW_SIZE - (64 * 9) / 2;
|
|
|
|
printf("Loading sprites...\n");
|
|
init_sprite(0, "/etc/game/0.bmp", NULL);
|
|
init_sprite(1, "/etc/game/1.bmp", NULL);
|
|
init_sprite(2, "/etc/game/2.bmp", NULL);
|
|
init_sprite(3, "/etc/game/3.bmp", NULL);
|
|
init_sprite(4, "/etc/game/4.bmp", NULL);
|
|
init_sprite(5, "/etc/game/5.bmp", NULL);
|
|
init_sprite(6, "/etc/game/6.bmp", NULL);
|
|
init_sprite(7, "/etc/game/7.bmp", NULL);
|
|
init_sprite(124, "/etc/game/remilia.bmp", NULL);
|
|
init_sprite(125, "/etc/game/remilia_r.bmp", NULL);
|
|
init_sprite(126, "/etc/game/remilia_l.bmp", NULL);
|
|
init_sprite(127, "/etc/game/remilia_f.bmp", NULL);
|
|
load_map("/etc/game/map");
|
|
printf("%d x %d\n", map.width, map.height);
|
|
|
|
display();
|
|
|
|
|
|
int playing = 1;
|
|
while (playing) {
|
|
|
|
char ch = 0;
|
|
w_keyboard_t * kbd;
|
|
do {
|
|
kbd = poll_keyboard();
|
|
if (kbd != NULL) {
|
|
ch = kbd->key;
|
|
free(kbd);
|
|
}
|
|
} while (kbd != NULL);
|
|
|
|
switch (ch) {
|
|
case 'q':
|
|
playing = 0;
|
|
break;
|
|
case 'a':
|
|
move(-1,0);
|
|
/* left */
|
|
break;
|
|
case 'd':
|
|
move(1,0);
|
|
/* right */
|
|
break;
|
|
case 's':
|
|
move(0,1);
|
|
/* Down */
|
|
break;
|
|
case 'w':
|
|
move(0,-1);
|
|
/* Up */
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
teardown_windowing();
|
|
|
|
return 0;
|
|
}
|