toaruos/userspace/gui/basic/game.c

344 lines
6.9 KiB
C
Raw Normal View History

/* This file is part of ToaruOS and is released under the terms
* of the NCSA / University of Illinois License - see LICENSE.md
* Copyright (C) 2013-2014 Kevin Lange
*/
2011-04-30 04:54:07 +04:00
/*
* The ToAru Sample Game
*
* This is the updated, windowed version of the sample RPG
2011-04-30 04:54:07 +04:00
*/
#include <stdio.h>
#include <stdint.h>
#include <syscall.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
2014-04-16 08:16:46 +04:00
#include "lib/yutani.h"
#include "lib/graphics.h"
#include "lib/decorations.h"
2011-04-30 04:54:07 +04:00
2014-04-16 08:16:46 +04:00
static sprite_t * sprites[128];
static yutani_t * yctx;
static yutani_window_t * window;
static gfx_context_t * ctx;
2011-05-01 07:30:57 +04:00
2012-02-09 07:22:30 +04:00
#define WINDOW_SIZE 224
int out_of_bounds(int x, int y) {
if (x < ctx->width / 2 - WINDOW_SIZE)
2012-02-09 07:22:30 +04:00
return 1;
if (x >= ctx->width / 2 + WINDOW_SIZE)
2012-02-09 07:22:30 +04:00
return 1;
if (y < ctx->height / 2 - WINDOW_SIZE)
2012-02-09 07:22:30 +04:00
return 1;
if (y >= ctx->height / 2 + WINDOW_SIZE)
2012-02-09 07:22:30 +04:00
return 1;
return 0;
}
2011-05-01 10:51:48 +04:00
/* 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);
2011-05-01 10:51:48 +04:00
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;
2011-05-01 10:51:48 +04:00
int raw_x_offset = 0;
int raw_y_offset = 0;
2011-05-01 10:51:48 +04:00
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) {
2011-05-02 04:20:45 +04:00
case '\n':
2011-05-01 10:51:48 +04:00
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 + raw_x_offset + map_x + offset_x * offset_iter + j * CELL_SIZE,
decor_top_height + raw_y_offset + map_y + offset_y * offset_iter + i * CELL_SIZE);
2011-05-01 10:51:48 +04:00
++j;
}
++i;
}
}
void display() {
render_map(my_x,my_y);
draw_sprite(ctx, sprites[124 + direction], decor_left_width + raw_x_offset + map_x + CELL_SIZE * 4, decor_top_height + raw_y_offset + map_y + CELL_SIZE * 4);
render_decorations(window, ctx, "RPG Demo");
flip(ctx);
2014-04-16 08:16:46 +04:00
yutani_flip(yctx, window);
2011-05-01 10:51:48 +04:00
}
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) {
2011-05-01 10:51:48 +04:00
offset_iter = i;
display();
}
offset_iter = 0;
offset_x = 0;
offset_y = 0;
my_x = nx;
my_y = ny;
display();
2011-05-01 10:51:48 +04:00
}
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();
2011-05-01 10:51:48 +04:00
return;
}
} else if (cx == -1) {
if (direction != 2) {
direction = 2;
display();
2011-05-01 10:51:48 +04:00
return;
}
} else if (cy == 1) {
if (direction != 0) {
direction = 0;
display();
2011-05-01 10:51:48 +04:00
return;
}
} else if (cy == -1) {
if (direction != 3) {
direction = 3;
display();
2011-05-01 10:51:48 +04:00
return;
}
}
switch (cell(nx,ny)) {
case '_':
case '.':
transition(nx,ny);
break;
default:
break;
}
display();
2011-05-01 10:51:48 +04:00
}
2011-05-01 07:30:57 +04:00
/* woah */
char font_buffer[400000];
sprite_t alpha_tmp;
void init_sprite(int i, char * filename, char * alpha) {
sprites[i] = malloc(sizeof(sprite_t));
2011-05-01 07:30:57 +04:00
load_sprite(sprites[i], filename);
if (alpha) {
sprites[i]->alpha = ALPHA_MASK;
2011-05-01 07:30:57 +04:00
load_sprite(&alpha_tmp, alpha);
sprites[i]->masks = alpha_tmp.bitmap;
} else {
sprites[i]->alpha = ALPHA_INDEXED;
2011-05-01 07:30:57 +04:00
}
sprites[i]->blank = 0x0;
}
2014-04-16 08:16:46 +04:00
#if 0
void resize_callback(window_t * win) {
int _width = win->width - decor_left_width - decor_right_width;
int _height = win->height - decor_top_height - decor_bottom_height;
raw_x_offset = _width / 2 - WINDOW_SIZE;
raw_y_offset = _height / 2 - WINDOW_SIZE;
reinit_graphics_window(ctx, window);
draw_fill(ctx, rgb(0,0,0));
display();
}
2014-04-16 08:16:46 +04:00
#endif
char handle_event(yutani_msg_t * m) {
if (m) {
switch (m->type) {
case YUTANI_MSG_KEY_EVENT:
{
struct yutani_msg_key_event * ke = (void*)m->data;
if (ke->event.action == KEY_ACTION_DOWN) {
return ke->event.keycode;
}
}
break;
case YUTANI_MSG_WINDOW_FOCUS_CHANGE:
{
struct yutani_msg_window_focus_change * wf = (void*)m->data;
yutani_window_t * win = hashmap_get(yctx->windows, (void*)wf->wid);
if (win) {
win->focused = wf->focused;
display();
}
}
2014-04-20 04:08:14 +04:00
break;
case YUTANI_MSG_WINDOW_MOUSE_EVENT:
{
struct yutani_msg_window_mouse_event * me = (void*)m->data;
if (me->command == YUTANI_MOUSE_EVENT_DOWN && me->buttons & YUTANI_MOUSE_BUTTON_LEFT) {
if (me->new_y < decor_top_height) {
yutani_window_drag_start(yctx, window);
}
}
}
break;
case YUTANI_MSG_SESSION_END:
return 'q';
default:
break;
}
free(m);
}
return 0;
}
2011-04-30 04:54:07 +04:00
int main(int argc, char ** argv) {
2014-04-16 08:16:46 +04:00
yctx = yutani_init();
window = yutani_window_create(yctx, 2 * WINDOW_SIZE, 2 * WINDOW_SIZE);
yutani_window_move(yctx, window, 10, 10);
ctx = init_graphics_yutani_double_buffer(window);
draw_fill(ctx,rgb(0,0,0));
2012-12-10 12:29:04 +04:00
flip(ctx);
2014-04-16 08:16:46 +04:00
yutani_flip(yctx, window);
yutani_window_advertise_icon(yctx, window, "RPG Demo", "applications-simulation");
init_decorations();
2011-05-01 07:30:57 +04:00
map_x = WINDOW_SIZE - (64 * 9) / 2;
map_y = WINDOW_SIZE - (64 * 9) / 2;
2011-04-30 04:54:07 +04:00
printf("Loading sprites...\n");
2014-05-07 11:10:34 +04:00
#define GAME_PATH "/usr/share/game/"
init_sprite(0, GAME_PATH "0.bmp", NULL);
init_sprite(1, GAME_PATH "1.bmp", NULL);
init_sprite(2, GAME_PATH "2.bmp", NULL);
init_sprite(3, GAME_PATH "3.bmp", NULL);
init_sprite(4, GAME_PATH "4.bmp", NULL);
init_sprite(5, GAME_PATH "5.bmp", NULL);
init_sprite(6, GAME_PATH "6.bmp", NULL);
init_sprite(7, GAME_PATH "7.bmp", NULL);
init_sprite(124, GAME_PATH "remilia.bmp", NULL);
init_sprite(125, GAME_PATH "remilia_r.bmp", NULL);
init_sprite(126, GAME_PATH "remilia_l.bmp", NULL);
init_sprite(127, GAME_PATH "remilia_f.bmp", NULL);
load_map(GAME_PATH "map");
2011-05-01 10:51:48 +04:00
printf("%d x %d\n", map.width, map.height);
2011-04-30 04:54:07 +04:00
display();
2011-04-30 04:54:07 +04:00
int playing = 1;
while (playing) {
2011-04-30 06:41:29 +04:00
2014-04-16 08:16:46 +04:00
char ch = '\0';
yutani_msg_t * m = NULL;
do {
m = yutani_poll_async(yctx);
handle_event(m);
} while (m);
m = yutani_poll(yctx);
ch = handle_event(m);
switch (ch) {
case 'q':
playing = 0;
break;
case 'a':
2011-05-01 10:51:48 +04:00
move(-1,0);
2011-05-01 07:30:57 +04:00
/* left */
break;
case 'd':
2011-05-01 10:51:48 +04:00
move(1,0);
2011-05-01 07:30:57 +04:00
/* right */
break;
case 's':
2011-05-01 10:51:48 +04:00
move(0,1);
/* Down */
2011-05-01 07:30:57 +04:00
break;
case 'w':
2011-05-01 10:51:48 +04:00
move(0,-1);
/* Up */
2011-05-01 07:30:57 +04:00
break;
default:
break;
2011-04-30 04:54:07 +04:00
}
}
2014-04-16 08:16:46 +04:00
yutani_close(yctx, window);
2011-04-30 04:54:07 +04:00
return 0;
}