steed/src/sdl-instead/game.c
2009-02-21 10:52:44 +00:00

1904 lines
40 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <unistd.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <dirent.h>
#include <errno.h>
#include <pwd.h>
#include <sys/stat.h>
#include "graphics.h"
#include "sound.h"
#include "game.h"
#include "input.h"
#include "instead.h"
int opt_fs = 0;
int opt_hl = 1;
int opt_hz = 22050;
int opt_vol = 127;
int opt_autosave = 0;
char *opt_game = NULL;
char game_cwd[PATH_MAX];
char *curgame;
int cfg_parse(const char *path);
char *game_cfg_path(void);
int game_save(void);
int cfg_load(void)
{
char *p = game_cfg_path();
if (!p)
return -1;
if (access(p, R_OK))
return 0;
return cfg_parse(p);
}
int cfg_save(void)
{
FILE *fp;
char *p = game_cfg_path();
if (!p)
return -1;
fp = fopen(p, "w");
if (!fp)
return -1;
fprintf(fp, "fs = %d\nhl = %d\nhz = %d\nvol = %d\nautosave = %d\ngame = %s", opt_fs, opt_hl, opt_hz, opt_vol, opt_autosave, curgame?curgame:"");
fclose(fp);
return 0;
}
void game_menu_box(int show, const char *txt);
void game_cursor(int on);
#ifndef THEMES_PATH
#define THEMES_PATH "./themes"
#endif
struct theme {
int w;
int h;
color_t bgcol;
char *bg_name;
img_t bg;
char *use_name;
img_t use;
int pad;
int win_x;
int win_y;
int win_w;
int win_h;
char *font_name;
int font_size;
fnt_t font;
int max_scene_h;
char *a_up_name;
char *a_down_name;
img_t a_up;
img_t a_down;
color_t fgcol;
color_t lcol;
color_t acol;
int inv_x;
int inv_y;
int inv_w;
int inv_h;
color_t icol;
color_t ilcol;
color_t iacol;
char *inv_font_name;
int inv_font_size;
fnt_t inv_font;
char *inv_a_up_name;
char *inv_a_down_name;
img_t inv_a_up;
img_t inv_a_down;
// int lstyle;
// int ilstyle;
color_t menu_bg;
color_t menu_fg;
color_t border_col;
color_t menu_link;
color_t menu_alink;
int menu_alpha;
int border_w;
char *menu_font_name;
int menu_font_size;
fnt_t menu_font;
char *menu_button_name;
img_t menu_button;
int menu_button_x;
int menu_button_y;
} game_theme = {
.w = 800,
.h = 480,
.bg_name = NULL,
.bg = NULL,
.use_name = NULL,
.use = NULL,
.font_name = NULL,
.font = NULL,
.a_up_name = NULL,
.a_down_name = NULL,
.a_up = NULL,
.a_down = NULL,
.inv_font_name = NULL,
.inv_font = NULL,
.inv_a_up_name = NULL,
.inv_a_down_name = NULL,
.inv_a_up = NULL,
.inv_a_down = NULL,
.menu_font_name = NULL,
.menu_font = NULL,
.menu_button_name = NULL,
.menu_button = NULL,
};
#define FREE(v) do { if ((v)) free((v)); v = NULL; } while(0)
void free_theme_strings()
{
struct theme *t = &game_theme;
FREE(t->use_name);
FREE(t->bg_name);
FREE(t->inv_a_up_name);
FREE(t->inv_a_down_name);
FREE(t->a_down_name);
FREE(t->a_up_name);
FREE(t->font_name);
FREE(t->inv_font_name);
FREE(t->menu_font_name);
FREE(t->menu_button_name);
}
int game_theme_free(void)
{
free_theme_strings();
if (game_theme.font)
fnt_free(game_theme.font);
if (game_theme.inv_font)
fnt_free(game_theme.inv_font);
if (game_theme.menu_font)
fnt_free(game_theme.menu_font);
if (game_theme.a_up)
gfx_free_image(game_theme.a_up);
if (game_theme.a_down)
gfx_free_image(game_theme.a_down);
if (game_theme.inv_a_up)
gfx_free_image(game_theme.inv_a_up);
if (game_theme.inv_a_down)
gfx_free_image(game_theme.inv_a_down);
if (game_theme.use)
gfx_free_image(game_theme.use);
if (game_theme.bg)
gfx_free_image(game_theme.bg);
if (game_theme.menu_button)
gfx_free_image(game_theme.menu_button);
game_theme.font = game_theme.inv_font = game_theme.menu_font = NULL;
game_theme.a_up = game_theme.a_down = game_theme.use = NULL;
game_theme.inv_a_up = game_theme.inv_a_down = NULL;
game_theme.menu_button = NULL;
game_theme.bg = NULL;
// game_theme.slide = gfx_load_image("slide.png", 1);
return 0;
}
int game_theme_init(void)
{
struct theme *t = &game_theme;
if (t->font_name) {
fnt_free(t->font);
if (!(t->font = fnt_load(t->font_name, t->font_size)))
goto err;
}
if (t->inv_font_name) {
fnt_free(t->inv_font);
if (!(t->inv_font = fnt_load(t->inv_font_name, t->inv_font_size)))
goto err;;
}
if (t->menu_font_name) {
fnt_free(t->menu_font);
if (!(t->menu_font = fnt_load(t->menu_font_name, t->menu_font_size)))
goto err;
}
if (t->a_up_name) {
gfx_free_image(t->a_up);
if (!(t->a_up = gfx_load_image(t->a_up_name, 1)))
goto err;
}
if (t->a_down_name) {
gfx_free_image(t->a_down);
if (!(t->a_down = gfx_load_image(t->a_down_name, 1)))
goto err;
}
if (t->inv_a_up_name) {
gfx_free_image(t->inv_a_up);
if (!(t->inv_a_up = gfx_load_image(t->inv_a_up_name, 1)))
goto err;
}
if (t->inv_a_down_name) {
gfx_free_image(t->inv_a_down);
if (!(t->inv_a_down = gfx_load_image(t->inv_a_down_name, 1)))
goto err;
}
if (t->bg_name) {
gfx_free_image(t->bg);
t->bg = NULL;
if (t->bg_name[0] && !(t->bg = gfx_load_image(t->bg_name, 0)))
goto err;
}
if (t->use_name) {
gfx_free_image(t->use);
if (!(t->use = gfx_load_image(t->use_name, 1)))
goto err;
}
if (t->menu_button_name) {
gfx_free_image(t->menu_button);
if (!(t->menu_button = gfx_load_image(t->menu_button_name, 1)))
goto err;
}
free_theme_strings();
if (!t->use || !t->inv_a_up || !t->inv_a_down || !t->a_down || !t->a_up ||
!t->font || !t->inv_font || !t->menu_font || !t->menu_button) {
fprintf(stderr,"Can't init theme.\n");
return -1;
}
return 0;
err:
game_theme_free();
return -1;
}
int theme_load(const char *name);
int game_theme_load(const char *name)
{
char cwd[PATH_MAX];
getcwd(cwd, sizeof(cwd));
if (chdir(THEMES_PATH) || chdir(name) || theme_load("theme.ini")) {
chdir(cwd);
return -1;
}
chdir(cwd);
return 0;
}
int game_default_theme(void)
{
return game_theme_load("default");
}
typedef int (*parser_fn)(const char *v, void *data);
int parse_string(const char *v, void *data)
{
char **p = ((char **)data);
if (*p)
free(*p);
*p = strdup(v);
if (!*p)
return -1;
return 0;
}
int parse_int(const char *v, void *data)
{
int *i = (int *)data;
char *eptr = NULL;
*i = strtol(v, &eptr, 0);
if (!eptr || *eptr)
return -1;
return 0;
}
int parse_color(const char *v, void *data)
{
color_t *c = (color_t *)data;
return gfx_parse_color(v, c);
}
int parse_include(const char *v, void *data)
{
int rc;
char cwd[PATH_MAX];
getcwd(cwd, sizeof(cwd));
chdir(game_cwd);
rc = game_theme_load(v);
chdir(cwd);
return rc;
}
struct parser {
const char *cmd;
parser_fn fn;
void *p;
};
struct parser cfg_parser[] = {
{ "hz", parse_int, &opt_hz },
{ "fs", parse_int, &opt_fs },
{ "vol", parse_int, &opt_vol },
{ "hl", parse_int, &opt_hl },
{ "game", parse_string, &opt_game },
{ "autosave", parse_int, &opt_autosave },
{ NULL, },
};
struct parser cmd_parser[] = {
{ "scr.w", parse_int, &game_theme.w },
{ "scr.h", parse_int, &game_theme.h },
{ "scr.col.bg", parse_color, &game_theme.bgcol },
{ "scr.gfx.bg", parse_string, &game_theme.bg_name },
{ "scr.gfx.use", parse_string, &game_theme.use_name },
{ "scr.gfx.pad", parse_int, &game_theme.pad },
{ "win.x", parse_int, &game_theme.win_x },
{ "win.y", parse_int, &game_theme.win_y },
{ "win.w", parse_int, &game_theme.win_w },
{ "win.h", parse_int, &game_theme.win_h },
{ "win.fnt.name", parse_string, &game_theme.font_name },
{ "win.fnt.size", parse_int, &game_theme.font_size },
{ "win.gfx.h", parse_int, &game_theme.max_scene_h },
{ "win.gfx.up", parse_string, &game_theme.a_up_name },
{ "win.gfx.down", parse_string, &game_theme.a_down_name },
{ "win.col.fg", parse_color, &game_theme.fgcol },
{ "win.col.link", parse_color, &game_theme.lcol },
{ "win.col.alink", parse_color, &game_theme.acol },
{ "inv.x", parse_int, &game_theme.inv_x },
{ "inv.y", parse_int, &game_theme.inv_y },
{ "inv.w", parse_int, &game_theme.inv_w },
{ "inv.h", parse_int, &game_theme.inv_h },
{ "inv.col.fg", parse_color, &game_theme.icol },
{ "inv.col.link", parse_color, &game_theme.ilcol },
{ "inv.col.alink", parse_color, &game_theme.iacol },
{ "inv.fnt.name", parse_string, &game_theme.inv_font_name },
{ "inv.fnt.size", parse_int, &game_theme.inv_font_size },
{ "inv.gfx.up", parse_string, &game_theme.inv_a_up_name },
{ "inv.gfx.down", parse_string, &game_theme.inv_a_down_name },
{ "menu.col.bg", parse_color, &game_theme.menu_bg },
{ "menu.col.fg", parse_color, &game_theme.menu_fg },
{ "menu.col.link", parse_color, &game_theme.menu_link },
{ "menu.col.alink", parse_color, &game_theme.menu_alink },
{ "menu.col.alpha", parse_int, &game_theme.menu_alpha },
{ "menu.col.border", parse_color, &game_theme.border_col },
{ "menu.bw", parse_int, &game_theme.border_w },
{ "menu.fnt.name", parse_string, &game_theme.menu_font_name },
{ "menu.fnt.size", parse_int, &game_theme.menu_font_size },
{ "menu.gfx.button", parse_string, &game_theme.menu_button_name },
{ "menu.buttonx", parse_int, &game_theme.menu_button_x },
{ "menu.buttony", parse_int, &game_theme.menu_button_y },
{ "include", parse_include, NULL },
{ NULL, },
};
char *strip(char *s)
{
char *e;
while (isspace(*s))
s ++;
if (!*s)
return s;
e = s + strlen(s) - 1;
while (e != s && isspace(*e)) {
*e = 0;
e --;
}
return s;
}
int process_cmd(char *n, char *v, struct parser *cmd_parser)
{
int i;
n = strip(n);
v = strip(v);
for (i = 0; cmd_parser[i].cmd; i++) {
if (!strcmp(cmd_parser[i].cmd, n)) {
return cmd_parser[i].fn(v, cmd_parser[i].p);
}
}
return -1;
}
int parse_ini(const char *path, struct parser *cmd_parser)
{
int rc = 0;
int line_nr = 0;
FILE *fp;
char line[1024];
fp = fopen(path, "r");
if (!fp)
return -1;
while (fgets(line, sizeof(line), fp)) {
char *p = line;
char *val;
int len;
line_nr ++;
p += strspn(p, " \t");
if (*p == ';')
continue;
len = strcspn(p, "=");
if (p[len] != '=')
continue;
p[len] = 0;
val = p + len + 1;
len = strcspn(p, " \t");
p[len] = 0;
// printf("%s\n", p);
val += strspn(val, " \t");
val[strcspn(val, "\n")] = 0;
if (process_cmd(p, val, cmd_parser)) {
rc = -1;
fprintf(stderr, "Can't process cmd '%s' on line %d : %s\n", p, line_nr, strerror(errno));
}
}
fclose(fp);
return rc;
}
int theme_parse(const char *path)
{
if (parse_ini(path, cmd_parser)) {
game_theme_free();
return -1;
}
return 0;
}
int theme_load(const char *name)
{
if (theme_parse(name))
return -1;
if (game_theme_init())
return -1;
return 0;
}
int cfg_parse(const char *path)
{
return parse_ini(path, cfg_parser);
}
#ifndef GAMES_PATH
#define GAMES_PATH "./games"
#endif
char *getpath(const char *d, const char *n)
{
int i = strlen(d) + strlen(n) + 3;
char *p = malloc(i);
if (p) {
strcpy(p, d);
strcat(p, "/");
strcat(p, n);
strcat(p, "/");
}
return p;
}
#define MAIN_FILE "main.lua"
int is_game(const char *n)
{
int rc = 0;
char *p = getpath(GAMES_PATH, n);
char *pp;
if (!p)
return 0;
pp = malloc(strlen(p) + strlen(MAIN_FILE) + 1);
if (pp) {
strcpy(pp, p);
strcat(pp, MAIN_FILE);
if (!access(pp, R_OK))
rc = 1;
free(pp);
}
free(p);
return rc;
}
struct game {
char *path;
char *name;
};
struct game *games;
int games_nr = 0;
int game_select(const char *name)
{
int i;
if (!name || !*name) {
if (games_nr == 1)
name = games[0].name;
else
return 0;
}
chdir(game_cwd);
for (i = 0; i<games_nr; i ++) {
if (!strcmp(games[i].name, name)) {
instead_done();
if (instead_init())
return -1;
if (chdir(games[i].path))
return -1;
if (instead_load(MAIN_FILE))
return -1;
curgame = games[i].name;
return 0;
}
}
return 0;
}
static char save_path[PATH_MAX];
char *game_cfg_path(void)
{
struct passwd *pw;
pw = getpwuid(getuid());
if (!pw)
return NULL;
snprintf(save_path, sizeof(save_path) - 1 , "%s/.insteadrc", pw->pw_dir);
return save_path;
}
char *game_save_path(int cr)
{
struct passwd *pw;
if (!curgame)
return NULL;
pw = getpwuid(getuid());
if (!pw)
return NULL;
snprintf(save_path, sizeof(save_path) - 1 , "%s/.instead/", pw->pw_dir);
if (cr && mkdir(save_path, S_IRWXU) && errno != EEXIST)
return NULL;
snprintf(save_path, sizeof(save_path) - 1 , "%s/.instead/saves", pw->pw_dir);
if (cr && mkdir(save_path, S_IRWXU) && errno != EEXIST)
return NULL;
snprintf(save_path, sizeof(save_path) - 1, "%s/.instead/saves/%s/", pw->pw_dir, curgame);
if (cr && mkdir(save_path, S_IRWXU) && errno != EEXIST)
return NULL;
snprintf(save_path, sizeof(save_path) - 1, "%s/.instead/saves/%s/autosave", pw->pw_dir, curgame);
return save_path;
}
int games_lookup(void)
{
char *p;
int n = 0;
DIR *d;
struct dirent *de;
d = opendir(GAMES_PATH);
if (!d)
return -1;
while ((de = readdir(d))) {
if (de->d_type != DT_DIR)
continue;
if (!is_game(de->d_name))
continue;
n ++;
}
rewinddir(d);
if (!n)
return 0;
games = malloc(sizeof(struct game) * n);
while ((de = readdir(d)) && games_nr < n) {
if (de->d_type != DT_DIR)
continue;
if (!is_game(de->d_name))
continue;
p = getpath(GAMES_PATH, de->d_name);
games[games_nr].path = p;
games[games_nr].name = strdup(de->d_name);
games_nr ++;
}
closedir(d);
return 0;
}
static char *last_pict = NULL;
static char *last_title = NULL;
static char *last_music = NULL;
static int mx, my;
static img_t menubg = NULL;
static img_t menu = NULL;
static int cur_menu = 0;
static int menu_shown = 0;
enum {
menu_main = 0,
menu_about,
menu_settings,
menu_quit,
menu_askquit,
menu_saved,
menu_games,
};
int game_cmd(char *cmd);
int change_vol(int d, int val);
void game_clear(int x, int y, int w, int h)
{
if (game_theme.bg)
gfx_draw_bg(game_theme.bg, x, y, w, h);
else
gfx_clear(x, y, w, h);
if (menu_shown) {
int xx = x - mx;
int yy = y - my;
gfx_draw_from(menubg, xx, yy, x, y, w, h);
gfx_draw_from(menu, xx, yy, x, y, w, h);
// gfx_update(mx, my, ww, hh);
return;
}
}
void game_clear(int x, int y, int w, int h);
struct el {
int id;
int x;
int y;
int type;
int drawn;
// int clone;
union {
layout_t lay;
textbox_t box;
img_t img;
void *p;
} p;
};
enum {
elt_box,
elt_layout,
elt_image,
};
enum {
el_menu = 0,
el_title,
el_ways,
el_inv,
el_scene,
el_sup,
el_sdown,
// el_sslide,
el_iup,
el_idown,
// el_islide,
el_spic,
el_menu_button,
el_max,
};
struct el objs[el_max];
void el_set(int i, int t, int x, int y, void *p)
{
objs[i].id = i;
objs[i].x = x;
objs[i].y = y;
objs[i].p.p = p;
objs[i].type = t;
objs[i].drawn = 0;
// objs[i].clone = 0;
}
void el_set_clone(int i, int t, int x, int y, void *p)
{
el_set(i, t, x, y, p);
// objs[i].clone = 1;
}
struct el *el(int num)
{
return &objs[num];
}
textbox_t el_box(int num)
{
return objs[num].p.box;
}
layout_t el_layout(int num)
{
return objs[num].p.lay;
}
img_t el_img(int num)
{
return objs[num].p.img;
}
char *game_menu_gen(void);
void el_draw(int n);
int game_init(const char *name)
{
char *s;
layout_t lay;
textbox_t box;
getcwd(game_cwd, sizeof(game_cwd));
cfg_load();
if (!name && opt_game)
name = opt_game;
if (gfx_init(game_theme.w, game_theme.h, opt_fs))
return -1;
snd_init(opt_hz);
change_vol(0, opt_vol);
if (game_default_theme())
return -1;
if (game_select(name)) {
name = NULL;
}
if (!access("theme.ini", R_OK)) {
if (theme_load("theme.ini"))
return -1;
}
gfx_bg(game_theme.bgcol);
game_clear(0, 0, game_theme.w, game_theme.h);
// if (instead_init("cat.lua"))
// return -1;
// gfx_update(0, 0, game_theme.w, game_theme.h);
lay = txt_layout(game_theme.font, ALIGN_JUSTIFY, game_theme.win_w, game_theme.win_h);
if (!lay)
return -1;
box = txt_box(game_theme.win_w, game_theme.win_h);
if (!box)
return -1;
txt_layout_color(lay, game_theme.fgcol);
txt_layout_link_color(lay, game_theme.lcol);
txt_layout_active_color(lay, game_theme.acol);
// txt_layout_link_style(lay, game_theme.lstyle);
txt_box_set(box, lay);
el_set(el_scene, elt_box, game_theme.win_x, 0, box);
lay = txt_layout(game_theme.inv_font, ALIGN_LEFT, game_theme.inv_w, game_theme.inv_h);
if (!lay)
return -1;
txt_layout_link_color(lay, game_theme.ilcol);
txt_layout_active_color(lay, game_theme.iacol);
// txt_layout_link_style(lay, game_theme.ilstyle);
box = txt_box(game_theme.inv_w, game_theme.inv_h);
if (!box)
return -1;
txt_box_set(box, lay);
el_set(el_inv, elt_box, game_theme.inv_x, game_theme.inv_y, box);
lay = txt_layout(game_theme.font, ALIGN_CENTER, game_theme.win_w, 0);
if (!lay)
return -1;
el_set(el_title, elt_layout, game_theme.win_x, game_theme.win_y, lay);
lay = txt_layout(game_theme.font, ALIGN_CENTER, game_theme.win_w, 0);
if (!lay)
return -1;
el_set(el_ways, elt_layout, game_theme.win_x, 0, lay);
el_set(el_sdown, elt_image, 0, 0, game_theme.a_down);
el_set(el_sup, elt_image, 0, 0, game_theme.a_up);
// el_set(el_sslide, elt_image, 0, 0, game_theme.slide);
el_set(el_idown, elt_image, 0, 0, game_theme.inv_a_down);
el_set(el_iup, elt_image, 0, 0, game_theme.inv_a_up);
// el_set(el_islide, elt_image, 0, 0, game_theme.slide);
el_set(el_spic, elt_image, game_theme.win_x, game_theme.win_y, NULL);
el_set(el_menu, elt_layout, 0, 0, NULL);
el_set(el_menu_button, elt_image, game_theme.menu_button_x, game_theme.menu_button_y, game_theme.menu_button);
el_draw(el_menu_button);
s = game_save_path(0);
if (s && !access(s, R_OK)) {
char cmd[256];
snprintf(cmd, sizeof(cmd) - 1, "load %s", s);
game_cmd(cmd);
return 0;
}
if (!curgame) {
menu_shown = 1;
cur_menu = menu_games;
game_menu_box(menu_shown, game_menu_gen());
gfx_flip();
} else
game_cmd("look");
return 0;
}
void free_last(void)
{
if (last_pict)
free(last_pict);
if (last_title)
free(last_title);
if (last_music)
free(last_music);
last_pict = last_title = last_music = NULL;
}
void game_done(void)
{
int i;
if (opt_autosave)
game_save();
chdir(game_cwd);
cfg_save();
menu_shown = 0;
game_menu_box(0, NULL);
cur_menu = menu_main;
if (el_img(el_spic))
gfx_free_image(el_img(el_spic));
for (i = 0; i < el_max; i++) {
struct el *o;
o = el(i);
// if (o->type == elt_image && o->p.p) {
// if (!o->clone)
// gfx_free_image(o->p.img);
// } else
if (o->type == elt_layout && o->p.p) {
txt_layout_free(o->p.lay);
} else if (o->type == elt_box && o->p.p) {
txt_layout_free(txt_box_layout(o->p.box));
txt_box_free(o->p.box);
}
o->p.p = NULL;
o->drawn = 0;
}
free_last();
if (menu)
gfx_free_image(menu);
if (menubg)
gfx_free_image(menubg);
menu = menubg = NULL;
game_theme_free();
instead_done();
snd_done();
gfx_done();
curgame = NULL;
}
void el_size(int i, int *w, int *h)
{
int type;
type = el(i)->type;
if (type == elt_layout)
txt_layout_size(el_layout(i), w, h);
else if (type == elt_box)
txt_box_size(el_box(i), w, h);
else if (type == elt_image) {
if (w)
*w = gfx_img_w(el_img(i));
if (h)
*h = gfx_img_h(el_img(i));
}
}
int el_clear(int n)
{
int x, y, w, h;
struct el *o;
o = el(n);
if (!o || !o->drawn)
return 0;
x = o->x;
y = o->y;
el_size(n, &w, &h);
o->drawn = 0;
game_clear(x, y, w, h);
return 1;
}
void el_update(int n)
{
int x, y, w, h;
struct el *o;
o = el(n);
// if (!o->drawn)
// return;
x = o->x;
y = o->y;
el_size(n, &w, &h);
gfx_update(x, y, w, h);
return;
}
void box_update_scrollbar(int n)
{
struct el *elup;
struct el *eldown;
// struct el *elslide;
layout_t l;
int x1, y1;
int x2, y2;
int off;
int w, h, hh;
el_size(n, &w, &h);
x1 = el(n)->x + w + game_theme.pad;
y1 = el(n)->y;
x2 = x1;
y2 = y1 + h - gfx_img_h(game_theme.a_down);
l = txt_box_layout(el_box(n));
txt_layout_size(l, NULL, &hh);
off = txt_box_off(el_box(n));
if (n == el_scene) {
elup = el(el_sup);
eldown = el(el_sdown);
// elslide = el(el_sslide);
} else if (n == el_inv) {
elup = el(el_iup);
eldown = el(el_idown);
// elslide = el(el_islide);
}
if (!elup || !eldown)
return;
if (el_clear(elup->id)) {
if (elup->x != x1 || elup->y != y1)
el_update(elup->id);
}
if (el_clear(eldown->id)) {
if (eldown->x != x2 || eldown->y != y2)
el_update(eldown->id);
}
elup->x = x1;
elup->y = y1;
eldown->x = x2;
eldown->y = y2;
el_clear(elup->id);
el_clear(eldown->id);
if (hh - off >= h)
el_draw(eldown->id);
if (off)
el_draw(elup->id);
el_update(elup->id);
el_update(eldown->id);
}
void el_draw(int n)
{
int x, y;
struct el *o;
o = el(n);
x = o->x;
y = o->y;
if (!o->p.p)
return;
if (o->type == elt_image)
gfx_draw(o->p.img, x, y);
else if (o->type == elt_layout)
txt_layout_draw(o->p.lay, x, y);
else if (o->type == elt_box) {
txt_box_draw(o->p.box, x, y);
box_update_scrollbar(o->id);
}
o->drawn = 1;
return;
}
img_t game_pict_scale(img_t img, int ww, int hh)
{
img_t img2 = img;
int w, h;
float scale1, scale2, scale;
w = gfx_img_w(img);
h = gfx_img_h(img);
if (w <= ww && h <= hh)
return img;
scale1 = (float)ww / (float)w;
scale2 = (float)hh / (float)h;
scale = (scale1<scale2)?scale1:scale2;
img2 = gfx_scale(img, scale, scale);
gfx_free_image(img);
return img2;
}
int vol_from_pcn(int v)
{
return (v * 127) / 100;
}
int vol_to_pcn(int v)
{
return (v * 100) / 127;
}
void music_player(void);
int static old_vol = 0;
int static cur_vol = 0;
int change_vol(int d, int val)
{
int v = snd_volume_mus(-1);
int pc = vol_to_pcn(v);
int opc = pc;
if (d) {
pc += d;
if (pc < 0)
pc = 0;
if (pc > 100)
pc = 100;
while (vol_to_pcn(v) != pc)
v += (d<0)?-1:1;
} else {
v = val;
pc = vol_to_pcn(v);
}
if (!pc)
v = 0;
snd_volume_mus(v);
if (opc && !pc) {
snd_stop_mus(0);
if (last_music)
free(last_music);
last_music = NULL;
}
if (!opc && pc) {
music_player();
}
cur_vol = snd_volume_mus(-1);
opt_vol = cur_vol;
return 0;
}
int change_hz(int hz)
{
if (!hz)
return -1;
snd_done();
if (last_music)
free(last_music);
last_music = NULL;
snd_init(hz);
snd_volume_mus(cur_vol);
music_player();
opt_hz = snd_hz();
return 0;
}
#define MENU_GAMES_MAX 4
static int games_menu_from = 0;
int game_save(void)
{
char *s = game_save_path(1);
char cmd[256];
char *p;
if (s) {
snprintf(cmd, sizeof(cmd) - 1, "save %s", s);
p = instead_cmd(cmd);
if (p)
free(p);
return 0;
}
return -1;
}
int game_menu_act(const char *a)
{
if (!strcmp(a, "/autosave")) {
opt_autosave ^= 1;
} else if (!strcmp(a, "/hl")) {
opt_hl ^= 1;
} else if (!strcmp(a, "/fs")) {
char *og = curgame;
opt_fs ^= 1;
game_save();
game_done();
game_init(og);
} else if (!strcmp(a, "/games_prev")) {
games_menu_from -= MENU_GAMES_MAX;
if (games_menu_from < 0)
games_menu_from = 0;
} else if (!strcmp(a, "/games_next")) {
if (games_menu_from + MENU_GAMES_MAX < games_nr)
games_menu_from += MENU_GAMES_MAX;
} else if (!strcmp(a, "/select")) {
cur_menu = menu_games;
} else if (!strcmp(a, "/save")) {
if (!game_save()) {
cur_menu = menu_saved;
}
}
else if (!strcmp(a, "/new")) {
if (!curgame)
return 0;
free_last();
game_select(curgame);
// instead_done();
// instead_init();
// instead_load(MAIN_FILE);
menu_shown = 0;
game_menu_box(0, NULL);
game_cmd("look");
game_save();
// game_done();
// game_init();
// game_cmd("look");
}
else if (!strcmp(a,"/main")) {
cur_menu = menu_main;
}
else if (!strcmp(a,"/ask_quit")) {
cur_menu = menu_askquit;
}
else if (!strcmp(a,"/about")) {
cur_menu = menu_about;
}
else if (!strcmp(a,"/mtoggle")) {
if (!old_vol) {
old_vol = snd_volume_mus(-1);
change_vol(0, 0);
} else {
change_vol(0, old_vol);
old_vol = 0;
}
}
else if (!strcmp(a,"/resume")) {
menu_shown = 0;
game_menu_box(0, NULL);
}
else if (!strcmp(a, "/settings")) {
cur_menu = menu_settings;
}
else if (!strcmp(a, "/vol--")) {
change_vol(-10, 0);
}
else if (!strcmp(a, "/vol++")) {
change_vol(+10, 0);
}
else if (!strcmp(a, "/vol-")) {
change_vol(-1, 0);
}
else if (!strcmp(a, "/vol+")) {
change_vol(+1, 0);
}
else if (!strcmp(a, "/hz-")) {
int hz = snd_hz();
if (hz == 44100)
hz = 22050;
else if (hz == 22050)
hz = 11025;
else
hz = 0;
change_hz(hz);
}
else if (!strcmp(a, "/hz+")) {
int hz = snd_hz();
if (hz == 11025)
hz = 22050;
else if (hz == 22050)
hz = 44100;
else
hz = 0;
change_hz(hz);
}
else if (!strcmp(a,"/quit")) {
return -1;
} else if (cur_menu == menu_games) {
char *p;
p = strdup(a);
if (p) {
char *og = curgame;
game_done();
if (game_init(p)) {
fprintf(stderr, "Can't init game:%s:%s\n", p, strerror(errno));
// exit(1);
game_done();
game_init(og);
}
free(p);
}
}
return 0;
}
#ifdef RUSSIAN
#define MAIN_MENU "<a:/resume>Вернуться в игру</a>\n<a:/select>Выбор игры</a>\n<a:/new>Новая игра</a>\n<a:/save>Сохранить игру</a>\n<a:/about>Информация</a>\n<a:/settings>Настройки</a>\n<a:/ask_quit>Выход</a>"
#define ABOUT_MENU "IN S.T.E.A.D SDL - "VERSION"\n\nИнтерпретатор простых\nтекстовых приключений.\n\nКосых П.А. '2009\n\n<a:/main>Назад</a>"
#define BACK_MENU "<a:/main>Назад</a>"
#define ON "Да"
#define OFF "Нет"
#define SETTINGS_MENU "Громкость\n<a:/vol--><<</a><a:/vol-><</a> <a:/mtoggle>%d%%</a> <a:/vol+>></a><a:/vol++>>></a>\n\n\
Качество звука\n<a:/hz-><<</a> %dГц <a:/hz+>>></a>\n\nПодсветка ссылок: <a:/hl>%s</a>\n\nПолный экран: <a:/fs>%s</a>\n\n\
Автосохранение: <a:/autosave>%s</a>\n\n\
<a:/main>Назад</a>"
#define QUIT_MENU "На самом деле выйти?\n\n<a:/quit>Да</a> | <a:/main>Нет</a>"
#define SELECT_GAME_MENU "Выбор игры\n\n"
#define SAVED_MENU "Игра сохранена!\n\n<a:/main>Ок</a>"
#define NOGAMES_MENU "Не найдена ни одна игра. \nПожалуйста, скопируйте хотя бы одну игру в каталог:\n'%s'"
#else
#define MAIN_MENU "<a:/resume>Resume</a>\n<a:/select>Select Game</a>\n<a:/new>New</a>\n<a:/save>Save</a>\n<a:/about>About</a>\n<a:/settings>Settings</a>\n<a:/ask_quit>Quit</a>"
#define ABOUT_MENU "Written by Peter Kosyh '2009\n\n<a:/main>Back</a>"
#define BACK_MENU "<a:/main>Back</a>"
#define ON "on"
#define OFF "off"
#define SELECT_GAME_MENU "Select game to play\n\n"
#define SETTINGS_MENU "Volume\n<a:/vol--><<</a><a:/vol-><</a> <a:/mtoggle>%d%%</a> <a:/vol+>></a><a:/vol++>>></a>\n\n\
Quality\n<a:/hz-><<</a> %dHz <a:/hz+>>></a>Refs highlighting: <a:/hl>%s</a>\n\nFull Screen: <a:/fs>%s</a>\n\n\
Autosave: <a:/autosave>%s</a>\n\n\
<a:/main>Back</a>"
#define QUIT_MENU "Really quit?\n\n<a:/quit>Yes</a> | <a:/main>No</a>"
#define SAVED_MENU "Current Game saved!\n\n<a:/main>Ok</a>"
#define NOGAMES_MENU "No games found. \nPlease, write any game in the this directory:\n'%s'"
#endif
char menu_buff[4096];
void games_menu(void)
{
int i;
*menu_buff = 0;
sprintf(menu_buff, SELECT_GAME_MENU);
for (i = games_menu_from; i < games_nr && i - games_menu_from < MENU_GAMES_MAX; i ++) {
char tmp[PATH_MAX];
if (curgame && !strcmp(games[i].name, curgame))
snprintf(tmp, sizeof(tmp), "<a:/resume><b>%s</b></a>\n", games[i].name);
else
snprintf(tmp, sizeof(tmp), "<a:%s>%s</a>\n", games[i].name, games[i].name);
strcat(menu_buff, tmp);
}
if (!games_nr)
sprintf(menu_buff, NOGAMES_MENU, GAMES_PATH);
strcat(menu_buff,"\n");
if (games_menu_from)
strcat(menu_buff,"<a:/games_prev><<</a> ");
strcat(menu_buff, BACK_MENU);
if (games_menu_from + MENU_GAMES_MAX < games_nr)
strcat(menu_buff," <a:/games_next>>></a>");
}
char *game_menu_gen(void)
{
if (cur_menu == menu_main) {
snprintf(menu_buff, sizeof(menu_buff), MAIN_MENU);
} else if (cur_menu == menu_about) {
snprintf(menu_buff, sizeof(menu_buff), ABOUT_MENU);
} else if (cur_menu == menu_settings) {
snprintf(menu_buff, sizeof(menu_buff),
SETTINGS_MENU, vol_to_pcn(snd_volume_mus(-1)), snd_hz(), opt_hl?ON:OFF, opt_fs?ON:OFF, opt_autosave?ON:OFF);
} else if (cur_menu == menu_askquit) {
snprintf(menu_buff, sizeof(menu_buff), QUIT_MENU);
} else if (cur_menu == menu_saved) {
snprintf(menu_buff, sizeof(menu_buff),
SAVED_MENU);
} else if (cur_menu == menu_games) {
games_menu();
}
return menu_buff;
}
void game_menu_box(int show, const char *txt)
{
// img_t menu;
int w, h, mw, mh;
int x, y;
int b = game_theme.border_w;
int pad = game_theme.pad;
layout_t lay;
el(el_menu)->drawn = 0;
if (el_layout(el_menu)) {
txt_layout_free(el_layout(el_menu));
el(el_menu)->p.p = NULL;
}
if (menubg) {
gfx_draw(menubg, mx, my);
gfx_free_image(menubg);
menubg = NULL;
}
el_clear(el_menu_button);
if (!show)
el_draw(el_menu_button);
el_update(el_menu_button);
if (!show) {
gfx_flip();
return;
}
lay = txt_layout(game_theme.menu_font, ALIGN_CENTER, game_theme.win_w, 0);
txt_layout_color(lay, game_theme.menu_fg);
txt_layout_link_color(lay, game_theme.menu_link);
txt_layout_active_color(lay, game_theme.menu_alink);
txt_layout_set(lay, (char*)txt);
txt_layout_real_size(lay, &w, &h);
if (menu) {
gfx_free_image(menu);
menu = NULL;
}
menu = gfx_new(w + (b + pad)*2, h + (b + pad)*2);
gfx_img_fill(menu, 0, 0, w + (b + pad)*2, h + (b + pad)*2, game_theme.border_col);
gfx_img_fill(menu, b, b, w + pad*2, h + pad*2, game_theme.menu_bg);
gfx_set_alpha(menu, game_theme.menu_alpha);
x = (game_theme.win_w - w)/2 + game_theme.win_x; // (game_theme.w - w)/2;
y = (game_theme.win_h - h)/2 + game_theme.win_y; //(game_theme.h - h)/2;
mx = x - b - pad;
my = y - b - pad;
mw = w + (b + pad) * 2;
mh = h + (b + pad) * 2;
menubg = gfx_grab_screen(mx, my, mw, mh);
gfx_draw(menu, mx, my);
el_set(el_menu, elt_layout, game_theme.win_x, y, lay);
el_draw(el_menu);
gfx_flip();
}
int check_new_place(char *title)
{
int rc = 0;
if (!title && !last_title)
return 0;
if (!title && last_title) {
rc = 1;
} else if (!last_title || strcmp(title, last_title)) {
rc = 1;
}
if (last_title) {
free(last_title);
}
last_title = title;
return rc;
}
int check_new_pict(char *pict)
{
int rc = 0;
if (!pict && !last_pict)
return 0;
if (!pict && last_pict) {
rc = 1;
} else if (!last_pict || strcmp(pict, last_pict)) {
rc = 1;
}
if (last_pict) {
free(last_pict);
}
last_pict = pict;
return rc;
}
void scene_scrollbar(void)
{
layout_t l;
int h, off;
int hh;
el_clear(el_sdown);
el_clear(el_sup);
el_size(el_scene, NULL, &hh);
el(el_sup)->y = el(el_scene)->y;
l = txt_box_layout(el_box(el_scene));
txt_layout_size(l, NULL, &h);
off = txt_box_off(el_box(el_scene));
if (h - off >= hh)
el_draw(el_sdown);
if (off)
el_draw(el_sup);
}
void music_player(void)
{
char *mus;
if (!snd_volume_mus(-1))
return;
mus = instead_eval("return get_music()");
if (mus) {
if (!last_music && mus) {
last_music = mus;
snd_stop_mus(500);
snd_play_mus(mus, 0);
} else if (strcmp(last_music, mus)) {
free(last_music);
last_music = mus;
snd_stop_mus(500);
snd_play_mus(mus, 0);
} else
free(mus);
}
}
int game_cmd(char *cmd)
{
int new_pict = 0, new_place = 0;
int title_h = 0, ways_h = 0, pict_h = 0;
char buf[256];
char *cmdstr;
char *invstr;
char *waystr;
char *title;
char *pict;
img_t oldscreen;
cmdstr = instead_cmd(cmd);
if (!cmdstr) {
return -1;
}
music_player();
title = instead_eval("return get_title();");
if (title) {
snprintf(buf, sizeof(buf), "<b><c><a:look>%s</a></c></b>", title);
txt_layout_set(el_layout(el_title), buf);
} else
txt_layout_set(el_layout(el_title), NULL);
new_place = check_new_place(title);
txt_layout_size(el_layout(el_title), NULL, &title_h);
// title_h += 12; // todo
pict = instead_eval("return get_picture();");
new_pict = check_new_pict(pict);
if (pict) {
int w, h, x;
img_t img;
if (new_pict) {
img = gfx_load_image(pict, 1);
if (el_img(el_spic))
gfx_free_image(el_img(el_spic));
el(el_spic)->p.p = NULL;
img = game_pict_scale(img, game_theme.win_w, game_theme.max_scene_h);
} else
img = el_img(el_spic);
if (img) {
w = gfx_img_w(img);
h = gfx_img_h(img);
x = (game_theme.win_w - w)/2 + game_theme.win_x;
el_set(el_spic, elt_image, x, game_theme.win_y + title_h, img);
pict_h = h;
}
} else if (el_img(el_spic)) {
el_clear(el_spic);
gfx_free_image(el_img(el_spic));
el(el_spic)->p.p = NULL;
}
waystr = instead_cmd("way");
invstr = instead_cmd("inv");
if (waystr) {
waystr[strcspn(waystr,"\n")] = 0;
}
txt_layout_set(el_layout(el_ways), waystr);
if (waystr)
free(waystr);
txt_layout_size(el_layout(el_ways), NULL, &ways_h);
el(el_ways)->y = el(el_title)->y + title_h + pict_h;
txt_layout_set(txt_box_layout(el_box(el_scene)), cmdstr);
txt_box_set(el_box(el_scene), txt_box_layout(el_box(el_scene)));
free(cmdstr);
el(el_scene)->y = el(el_ways)->y + ways_h;
/* draw title and ways */
if (new_pict || new_place) {
img_t offscreen = gfx_new(game_theme.w, game_theme.h);
oldscreen = gfx_screen(offscreen);
gfx_draw(oldscreen, 0, 0);
}
if (new_pict || new_place) {
game_clear(game_theme.win_x, game_theme.win_y, game_theme.win_w, game_theme.win_h);
// el_draw(el_title);
} else {
game_clear(game_theme.win_x, game_theme.win_y + pict_h + title_h,
game_theme.win_w, game_theme.win_h - pict_h - title_h);
}
el_clear(el_title);
el_draw(el_title);
el_draw(el_ways);
if (new_pict || new_place)
el_draw(el_spic);
txt_box_resize(el_box(el_scene), game_theme.win_w, game_theme.win_h - title_h - ways_h - pict_h);
el_draw(el_scene);
txt_layout_set(txt_box_layout(el_box(el_inv)), invstr);
txt_box_set(el_box(el_inv), txt_box_layout(el_box(el_inv)));
if (invstr)
free(invstr);
el_clear(el_inv);
el_draw(el_inv);
// scene_scrollbar();
if (new_pict || new_place) {
img_t offscreen;
offscreen = gfx_screen(oldscreen);
gfx_change_screen(offscreen);
gfx_free_image(offscreen);
return 0;
}
gfx_flip();
return 0;
}
xref_t inv_xref = NULL;
int disable_inv(void)
{
if (inv_xref) {
xref_set_active(inv_xref, 0);
xref_update(inv_xref, el(el_inv)->x, el(el_inv)->y, game_clear);
// txt_box_update_links(el_box(el_inv), el(el_inv)->x, el(el_inv)->y, game_clear);
inv_xref = NULL;
return 1;
}
return 0;
}
void enable_inv(xref_t xref)
{
inv_xref = xref;
xref_set_active(xref, 1);
//txt_box_update_links(el_box(el_inv), el(el_inv)->x, el(el_inv)->y, game_clear);
xref_update(inv_xref, el(el_inv)->x, el(el_inv)->y, game_clear);
}
struct el *look_obj(int x, int y)
{
int i;
for (i = 0; i < el_max; i++) {
int w, h;
if (el(i)->drawn && el(i)->id == el_menu) {
return el(i);
}
if (x < el(i)->x || y < el(i)->y || !el(i)->drawn)
continue;
el_size(i, &w, &h);
if (x >= el(i)->x && y >= el(i)->y && x <= el(i)->x + w && y <= el(i)->y + h)
return el(i);
}
return NULL;
}
xref_t look_xref(int x, int y, struct el **elem)
{
struct el *o;
int type;
xref_t xref = NULL;
o = look_obj(x, y);
if (elem)
*elem = o;
if (!o)
return NULL;
type = o->type;
if (type == elt_layout)
xref = txt_layout_xref(o->p.lay, x - o->x, y - o->y);
else if (type == elt_box)
xref = txt_box_xref(o->p.box, x - o->x, y - o->y);
return xref;
}
static xref_t old_xref = NULL;
static struct el *old_el = NULL;
void menu_update(struct el *elem)
{
gfx_draw(menubg, mx, my);
gfx_draw(menu, mx, my);
txt_layout_draw(elem->p.lay, elem->x, elem->y);
gfx_update(mx, my, gfx_img_w(menu), gfx_img_h(menu));
// gfx_fill(x, y, w, h, game_theme.menu_bg);
}
int game_highlight(int x, int y, int on)
{
struct el *elem = NULL;
static struct el *oel = NULL;
static xref_t hxref = NULL;
xref_t xref = NULL;
int up = 0;
if (!opt_hl)
return 0;
if (on) {
xref = look_xref(x, y, &elem);
if (xref) {
game_cursor(-1);
xref_set_active(xref, 1);
xref_update(xref, elem->x, elem->y, game_clear);
}
}
if (hxref != xref && oel) {
if (hxref != inv_xref) {
xref_set_active(hxref, 0);
game_cursor(-1);
xref_update(hxref, oel->x, oel->y, game_clear);
up = 1;
}
hxref = NULL;
}
hxref = xref;
// if (!up || !elem)
// return 0;
// xref_update(hxref, elem->x, elem->y, game_clear);
// game_cursor(2);
// game_cursor(0);
// if (elem->id == el_menu) {
// menu_update(elem);
// }
// else if (elem->type == elt_layout)
// txt_layout_update_links(elem->p.lay, elem->x, elem->y, game_clear);
// else if (elem->type == elt_box)
// txt_box_update_links(elem->p.box, elem->x, elem->y, game_clear);
// el_update(elem->id);
oel = elem;
return 0;
}
void menu_toggle(void)
{
game_cursor(0);
game_highlight(-1, -1, 0);
disable_inv();
menu_shown ^= 1;
if (!menu_shown)
cur_menu = menu_main;
game_menu_box(menu_shown, game_menu_gen());
}
int game_click(int x, int y, int action)
{
struct el *elem = NULL;
char buf[256];
xref_t xref;
if (old_xref) {
xref = old_xref;
elem = old_el;
} else {
xref = look_xref(x, y, &elem);
}
if (!xref) {
if (action && elem) {
if (elem->id == el_menu_button) {
menu_toggle();
} else if (elem->id == el_sdown) {
txt_box_next(el_box(el_scene));
el_clear(el_scene);
el_draw(el_scene);
el_update(el_scene);
}
else if (elem->id == el_sup) {
txt_box_prev(el_box(el_scene));
el_clear(el_scene);
el_draw(el_scene);
el_update(el_scene);
}
else if (elem->id == el_idown) {
txt_box_next(el_box(el_inv));
el_clear(el_inv);
el_draw(el_inv);
el_update(el_inv);
}
else if (elem->id == el_iup) {
txt_box_prev(el_box(el_inv));
el_clear(el_inv);
el_draw(el_inv);
el_update(el_inv);
}
}
if (disable_inv()) {
el_update(el_inv);
// gfx_flip();
}
return 0;
}
if (!action) {
xref_set_active(xref, 1);
xref_update(xref, elem->x, elem->y, game_clear);
/*
if (elem->id == el_menu) {
menu_update(elem);
} else if (elem->type == elt_layout)
txt_layout_update_links(elem->p.lay, elem->x, elem->y, game_clear);
else if (elem->type == elt_box)
txt_box_update_links(elem->p.box, elem->x, elem->y, game_clear);
el_update(elem->id); */
old_xref = xref;
old_el = elem;
return 0;
}
old_el = NULL;
old_xref = NULL;
if (elem->id == el_menu) {
// xref_set_active(xref, 0);
// txt_layout_update_links(elem->p.lay, elem->x, elem->y, game_clear);
if (game_menu_act(xref_get_text(xref))) {
return -1;
}
game_menu_box(menu_shown, game_menu_gen());
// gfx_flip();
return 1;
}
if (elem->id == el_ways ||
elem->id == el_title) {
strcpy(buf, xref_get_text(xref));
disable_inv();
game_cmd(buf);
return 1;
}
if (elem->id == el_scene) {
if (inv_xref) {
snprintf(buf,sizeof(buf), "use %s,%s", xref_get_text(inv_xref), xref_get_text(xref));
disable_inv();
} else
strcpy(buf, xref_get_text(xref));
game_cmd(buf);
return 1;
}
if (elem->id == el_inv) {
if (!inv_xref) {
enable_inv(xref);
el_update(el_inv);
return 0;
}
if (xref == inv_xref)
snprintf(buf,sizeof(buf), "use %s", xref_get_text(xref));
else
snprintf(buf,sizeof(buf), "use %s,%s", xref_get_text(inv_xref), xref_get_text(xref));
disable_inv();
game_cmd(buf);
return 1;
}
return 0;
}
void game_cursor(int on)
{
static img_t grab = NULL;
static int xc, yc, w, h;
if (grab) {
gfx_draw(grab, xc, yc);
gfx_free_image(grab);
grab = NULL;
}
if (!on) {
gfx_update(xc, yc, gfx_img_w(game_theme.use), gfx_img_h(game_theme.use));
return;
}
if (on == -1)
return;
if (inv_xref) {
int ox = xc;
int oy = yc;
gfx_cursor(&xc, &yc, &w, &h);
xc += w/2;
yc += h/2;
grab = gfx_grab_screen(xc, yc, gfx_img_w(game_theme.use), gfx_img_h(game_theme.use));
gfx_draw(game_theme.use, xc, yc);
gfx_update(xc, yc, gfx_img_w(game_theme.use), gfx_img_h(game_theme.use));
gfx_update(ox, oy, gfx_img_w(game_theme.use), gfx_img_h(game_theme.use));
}
}
int game_loop(void)
{
static int x = 0, y = 0;
struct inp_event ev;
while (1) {
if (input(&ev, 1) == -1) /* close */
break;
if (ev.type == KEY_DOWN && ev.sym && !strcmp(ev.sym,"escape")) {
menu_toggle();
} else if (ev.type == MOUSE_DOWN) {
game_cursor(0);
game_highlight(-1, -1, 0);
game_click(ev.x, ev.y, 0);
x = ev.x;
y = ev.y;
} else if (ev.type == MOUSE_UP) {
game_cursor(0);
game_highlight(-1, -1, 0);
if (game_click(x, y, 1) == -1)
break;
} else if (ev.type == MOUSE_WHEEL_UP && !menu_shown) {
int xm, ym;
struct el *o;
gfx_cursor(&xm, &ym, NULL, NULL);
o = look_obj(xm, ym);
if (o && (o->id == el_scene || o->id == el_inv)) {
game_cursor(0);
game_highlight(-1, -1, 0);
txt_box_prev_line(el_box(o->id));
el_clear(o->id);
el_draw(o->id);
el_update(o->id);
}
} else if (ev.type == MOUSE_WHEEL_DOWN && !menu_shown) {
int xm, ym;
struct el *o;
gfx_cursor(&xm, &ym, NULL, NULL);
o = look_obj(xm, ym);
if (o && (o->id == el_scene || o->id == el_inv)) {
game_cursor(0);
game_highlight(-1, -1, 0);
txt_box_next_line(el_box(o->id));
el_clear(o->id);
el_draw(o->id);
el_update(o->id);
}
} else if (ev.type == MOUSE_MOTION) {
// game_highlight(ev.x, ev.y, 1);
}
game_highlight(ev.x, ev.y, 1);
game_cursor(1);
}
return 0;
}