DANGEROUS. working tech demo of sprites

This commit is contained in:
p.kosyh 2011-04-11 09:12:57 +00:00
parent 8d4dc02cef
commit 2b7b025456
15 changed files with 892 additions and 98 deletions

1
debian/changelog vendored
View file

@ -5,6 +5,7 @@ instead (1.3.5) unstable; urgency=low
* bug fix in jump to pos logic;
* bug fix lags in sound;
* bug fix with wince/windows with themes load;
* experemental sprites technology;
* global dir is now readdir;
* multichannal sound system (add_sound, stop_sound);
* -appdata parameter;

View file

@ -59,6 +59,7 @@
".\symbian_gamedata\stead\para.lua" -"!:\data\instead\stead\para.lua"
".\symbian_gamedata\stead\theme.lua" -"!:\data\instead\stead\theme.lua"
".\symbian_gamedata\stead\prefs.lua" -"!:\data\instead\stead\prefs.lua"
".\symbian_gamedata\stead\sprites.lua" -"!:\data\instead\stead\sprites.lua"
".\symbian_gamedata\lang\ru.ini" -"!:\data\instead\lang\ru.ini"
".\symbian_gamedata\lang\en.ini" -"!:\data\instead\lang\en.ini"
".\symbian_gamedata\themes\fantasy\down.png" -"!:\data\instead\themes\fantasy\down.png"

View file

@ -2,11 +2,13 @@
#include <string.h>
#include "list.h"
#include "cache.h"
extern unsigned long hash_string(const char *str);
#define HASH_SIZE 511
typedef struct {
struct list_head list;
struct list_head unused;
int auto_grow;
int size;
int max_size;
@ -56,14 +58,14 @@ static unsigned long hash_long64(unsigned long key)
return key;
}
static unsigned long hash_addr(void *p)
unsigned long hash_addr(void *p)
{
if (sizeof(long) == 8)
return hash_long64((unsigned long)p);
return hash_long32((unsigned long)p);
}
static unsigned long hash_string(const char *str)
unsigned long hash_string(const char *str)
{
unsigned long hash = 0;
int c;
@ -79,6 +81,7 @@ cache_t cache_init(int size, cache_free_fn free_fn)
if (!c)
return NULL;
INIT_LIST_HEAD(&c->list);
INIT_LIST_HEAD(&c->unused);
c->auto_grow = 0;
c->size = 0;
c->used = 0;
@ -98,14 +101,17 @@ static void cache_e_free(cache_t cache, __cache_e_t *cc)
__cache_t *c = cache;
if (!c)
return;
free(cc->name);
if (c->free_fn && !cc->used)
c->free_fn(cc->data);
list_del(cc->hash);
free(cc->hash);
list_del(cc->vhash);
list_del(&cc->list);
if (c->free_fn && !cc->used) {
c->free_fn(cc->data);
}
free(cc->name);
free(cc->hash);
free(cc->vhash);
list_del((struct list_head*)cc);
free(cc);
}
@ -116,6 +122,8 @@ void cache_zap(cache_t cache)
return;
while (!list_empty(&c->list))
cache_e_free(cache, (__cache_e_t *)(c->list.next));
while (!list_empty(&c->unused))
cache_e_free(cache, (__cache_e_t *)(c->unused.next));
c->size = 0;
c->used = 0;
}
@ -128,7 +136,7 @@ void cache_free(cache_t cache)
free(cache);
}
static __cache_e_t *cache_lookup(cache_t cache, const char *name)
static __cache_e_t *_cache_lookup(cache_t cache, const char *name)
{
struct list_head *pos;
struct list_head *list;
@ -165,11 +173,16 @@ static __cache_e_t *cache_data(cache_t cache, void *p)
int cache_forget(cache_t cache, void *p)
{
__cache_t *c = cache;
__cache_e_t *cc = cache_data(cache, p);
// if (cc)
// fprintf(stderr, "Forget %p at %d\n", p, cc->used);
if (cc && cc->used) {
cc->used --;
if (!cc->used)
if (!cc->used) {
((__cache_t*)cache)->used --;
list_move_tail(&cc->list, &c->unused);
}
return 0;
}
return -1;
@ -181,14 +194,26 @@ void *cache_get(cache_t cache, const char *name)
__cache_t *c = cache;
if (!c || !name)
return NULL;
cc = cache_lookup(cache, name);
cc = _cache_lookup(cache, name);
if (!cc)
return NULL;
cc->used ++; /* need again! */
if (cc->used == 1)
((__cache_t*)cache)->used ++;
list_move((struct list_head*)cc, &c->list); /* first place */
// printf("%p\n", cc->data);
list_move(&cc->list, &c->list); /* first place */
// printf("cache_get %s:%p %d\n", name, cc->data, cc->used);
return cc->data;
}
void *cache_lookup(cache_t cache, const char *name)
{
__cache_e_t *cc;
__cache_t *c = cache;
if (!c || !name)
return NULL;
cc = _cache_lookup(cache, name);
if (!cc)
return NULL;
return cc->data;
}
@ -206,14 +231,10 @@ int cache_have(cache_t cache, void *p)
static void __cache_shrink(__cache_t *c)
{
while (c->size > c->max_size) {
__cache_e_t *cc;
cc = (__cache_e_t *)c->list.prev;
if (!cc->used) {
c->size --;
cache_e_free(c, (__cache_e_t *)c->list.prev);
} else
break;
while (c->size && c->size > c->max_size && !list_empty(&c->unused)) {
__cache_e_t *cc = (__cache_e_t *)(c->unused.next);
c->size --;
cache_e_free(c, cc);
}
// fprintf(stderr,"%d/%d\n", c->size, c->used);
}
@ -227,7 +248,7 @@ int cache_add(cache_t cache, const char *name, void *p)
struct list_head *list;
if (!c || !name)
return -1;
cc = cache_lookup(cache, name);
cc = _cache_lookup(cache, name);
if (cc)
return 0;
cc = malloc(sizeof(__cache_e_t));
@ -271,6 +292,7 @@ int cache_add(cache_t cache, const char *name, void *p)
c->used ++;
if (c->auto_grow && c->used > c->max_size)
c->max_size = c->used;
// printf("cache_add %s:%p %d\n", name, cc->data, cc->used);
// __cache_shrink(c);
return 0;
}

View file

@ -10,7 +10,10 @@ extern int cache_forget(cache_t cache, void *p);
extern void cache_zap(cache_t cache);
extern void cache_shrink(cache_t cache);
extern void *cache_get(cache_t cache, const char *name);
extern void *cache_lookup(cache_t cache, const char *name);
extern int cache_add(cache_t cache, const char *name, void *p);
extern int cache_have(cache_t cache, void *p);
extern unsigned long hash_addr(void *p);
extern unsigned long hash_string(const char *str);
#endif

View file

@ -311,8 +311,8 @@ void game_clear(int x, int y, int w, int 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_draw_from(menubg, xx, yy, w, h, NULL, x, y);
gfx_draw_from(menu, xx, yy, w, h, NULL, x, y);
}
}
@ -358,9 +358,9 @@ enum {
el_max,
};
struct el objs[el_max];
static struct el objs[el_max];
void el_set(int i, int t, int x, int y, void *p)
static void el_set(int i, int t, int x, int y, void *p)
{
objs[i].id = i;
objs[i].x = x;
@ -370,27 +370,22 @@ void el_set(int i, int t, int x, int y, void *p)
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)
static struct el *el(int num)
{
return &objs[num];
}
textbox_t el_box(int num)
static textbox_t el_box(int num)
{
return objs[num].p.box;
}
layout_t el_layout(int num)
static layout_t el_layout(int num)
{
return objs[num].p.lay;
}
img_t el_img(int num)
static img_t el_img(int num)
{
return objs[num].p.img;
}
@ -414,7 +409,7 @@ int game_error(const char *name)
return 0;
}
void el_draw(int n);
static void el_draw(int n);
int window_sw = 0;
int fullscreen_sw = 0;
@ -645,6 +640,7 @@ int game_change_hz(int hz)
}
unsigned int timer_counter = 0;
gtimer_t timer_han = NULL_TIMER;
static void anigif_do(void *data)
@ -847,7 +843,7 @@ void game_done(int err)
// SDL_Quit();
}
void el_size(int i, int *w, int *h)
static void el_size(int i, int *w, int *h)
{
int type;
type = el(i)->type;
@ -863,7 +859,10 @@ void el_size(int i, int *w, int *h)
}
}
int el_clear(int n)
#define el_clear(n) _el_clear(n, game_clear)
#define el_clear_nobg(n) _el_clear(n, NULL)
static int _el_clear(int n, clear_fn clear)
{
void *v;
img_t img;
@ -876,7 +875,8 @@ int el_clear(int n)
y = o->y;
el_size(n, &w, &h);
o->drawn = 0;
game_clear(x, y, w, h);
if (clear)
clear(x, y, w, h);
if (o->type == elt_box) {
for (v = NULL; (img = txt_layout_images(txt_box_layout(el_box(n)), &v)); )
gfx_dispose_gif(img);
@ -889,7 +889,7 @@ int el_clear(int n)
return 1;
}
void el_update(int n)
static void el_update(int n)
{
int x, y, w, h;
struct el *o;
@ -904,6 +904,18 @@ void el_update(int n)
return;
}
static void el_clip(int n)
{
int x, y, w, h;
struct el *o;
o = el(n);
x = o->x;
y = o->y;
el_size(n, &w, &h);
gfx_clip(x, y, w, h);
return;
}
int box_isscroll_up(int n)
{
if (el(n)->type != elt_box)
@ -1017,6 +1029,7 @@ void el_draw(int n)
y = o->y;
if (!o->p.p)
return;
game_cursor(CURSOR_CLEAR);
if (o->type == elt_image)
gfx_draw(o->p.img, x, y);
@ -1039,6 +1052,9 @@ img_t game_pict_scale(img_t img, int ww, int hh)
game_pic_w = gfx_img_w(img);
game_pic_h = gfx_img_h(img);
if (!cache_have(gfx_image_cache(), img))
return img; /* do not scale sprites! */
if (game_theme.scale > 1.0f)
theme_img_scale(&img);
@ -1205,6 +1221,7 @@ int check_new_place(char *title)
int check_new_pict(char *pict)
{
int rc = 0;
if (!pict && !last_pict)
return 0;
@ -1500,6 +1517,65 @@ static void scroll_to_diff(const char *cmdstr, int cur_off)
int game_highlight(int x, int y, int on);
int game_pict_modify(img_t p)
{
static int modify = 0;
int last = modify;
if (p && (el_img(el_spic) == p))
modify = 1;
else
modify = 0;
return last;
}
static void game_pict_clip(void)
{
int x, y, w, h;
if (game_theme.gfx_mode == GFX_MODE_EMBEDDED) {
el_clip(el_scene);
return;
}
if (game_theme.gfx_mode != GFX_MODE_FLOAT) {
x = game_theme.win_x;
y = game_theme.win_y;
w = game_theme.win_w;
h = game_theme.win_h;
if (game_theme.max_scene_h >=0)
h = game_theme.max_scene_h;
} else {
x = game_theme.gfx_x;
y = game_theme.gfx_y;
w = game_theme.max_scene_w;
h = game_theme.max_scene_h;
}
gfx_clip(x, y, w, h);
}
static void game_redraw_pic(void)
{
int x, y, ox, oy;
if (game_pict_coord(&x, &y, NULL, NULL))
return;
game_pict_clip();
ox = el(el_spic)->x;
oy = el(el_spic)->y;
el(el_spic)->x = x;
el(el_spic)->y = y;
el_clear(el_spic);
el_draw(el_spic);
gfx_noclip();
el_update(el_spic);
el(el_spic)->x = ox;
el(el_spic)->y = oy;
}
int game_cmd(char *cmd)
{
int old_off;
@ -1515,16 +1591,32 @@ int game_cmd(char *cmd)
char *title = NULL;
char *pict = NULL;
img_t oldscreen = NULL;
int dd = (game_theme.gfx_mode == GFX_MODE_DIRECT);
if (menu_shown)
return -1;
if (dd)
game_cursor(CURSOR_CLEAR);
cmdstr = instead_cmd(cmd); instead_clear();
game_music_player();
game_sound_player();
if (!cmdstr)
if (game_theme.gfx_mode == GFX_MODE_DIRECT) {
if (cmdstr)
free(cmdstr);
goto out;
} else if (dd) { /* disable direct mode on the fly */
game_theme_changed = 2; /* force redraw */
game_cursor(CURSOR_DRAW);
}
if (!cmdstr) {
if (game_pict_modify(NULL)) /* redraw pic only */
game_redraw_pic();
goto inv; /* hackish? ok, yes it is... */
}
fading = check_fading();
@ -1541,7 +1633,7 @@ int game_cmd(char *cmd)
unix_path(pict);
new_pict = check_new_pict(pict);
if (game_theme_changed == 2 && opt_owntheme && !fading)
fading = 1; /* one frame at least */
@ -1571,14 +1663,18 @@ int game_cmd(char *cmd)
} else
txt_layout_set(el_layout(el_title), NULL);
if (new_pict || fading ||
if (new_pict || fading || game_pict_modify(NULL) ||
(new_place && (game_theme.gfx_mode == GFX_MODE_FIXED))) {
redraw_pict = 1;
}
game_pict_clip();
if (redraw_pict) {
if (el_img(el_spic)) {
el_clear(el_spic);
if (game_theme.gfx_mode == GFX_MODE_EMBEDDED)
el_clear_nobg(el_spic);
else
el_clear(el_spic);
if (new_pict) {
gfx_free_image(el_img(el_spic));
el(el_spic)->p.p = NULL;
@ -1617,6 +1713,9 @@ int game_cmd(char *cmd)
pict_h = h;
}
}
gfx_noclip();
/* clear area */
el_clear(el_ways);
el_clear(el_scene);
@ -1689,11 +1788,15 @@ int game_cmd(char *cmd)
if (game_theme.gfx_mode != GFX_MODE_EMBEDDED) {
el_draw(el_ways);
if (redraw_pict)
if (redraw_pict) {
game_pict_clip();
el_draw(el_spic);
gfx_noclip();
}
}
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);
inv:
@ -1730,6 +1833,7 @@ inv:
gfx_cursor(&x, &y);
game_highlight(x, y, 1);
}
out:
game_cursor(CURSOR_DRAW);
gfx_flip();
// input_clear();
@ -1844,6 +1948,9 @@ xref_t look_xref(int x, int y, struct el **elem)
static xref_t old_xref = NULL;
static struct el *old_el = NULL;
static int click_x = -1;
static int click_y = -1;
int game_paused(void)
{
return browse_dialog || menu_shown || use_xref || old_xref || gfx_fading() || minimized();
@ -1891,11 +1998,20 @@ void mouse_reset(int hl)
game_highlight(-1, -1, 0);
else
game_highlight(-1, -1, -1);
disable_use();
motion_mode = 0;
if (motion_mode) {
click_x = -1;
click_y = -1;
}
if (hl)
motion_mode = 0;
old_xref = old_el = NULL;
}
static void menu_toggle(void)
{
mouse_reset(1);
@ -1959,7 +2075,15 @@ int game_click(int x, int y, int action, int filter)
char buf[1024];
xref_t xref = NULL;
char *xref_txt;
if (!action) {
click_x = x;
click_y = y;
} else {
click_x = -1;
click_y = -1;
}
if (action)
motion_mode = 0;
@ -2092,6 +2216,12 @@ int game_click(int x, int y, int action, int filter)
return 1;
}
void mouse_restore(void)
{
if (click_x != -1 && click_y != -1)
game_click(click_x, click_y, 0, 0);
}
void game_cursor(int on)
{
static img_t grab = NULL;
@ -2471,12 +2601,13 @@ static int is_key(struct inp_event *ev, const char *name)
{
return strcmp(ev->sym, name);
}
static int game_pic_coord(int x, int y, int *ox, int *oy)
int game_pict_coord(int *x, int *y, int *w, int *h)
{
int xx, yy, ww, hh;
img_t img;
int ww, hh;
int xx, yy;
word_t word;
img = el_img(el_spic);
if (!img)
return -1;
@ -2488,23 +2619,40 @@ static int game_pic_coord(int x, int y, int *ox, int *oy)
goto out;
}
el_size(el_scene, &ww, &hh);
if (x < el(el_scene)->x || y < el(el_scene)->y || x >= el(el_scene)->x + ww ||
y >= el(el_scene)->y + hh)
return -1; /* no scene layout */
for (word = NULL; (word = txt_layout_words(txt_box_layout(el_box(el_scene)), word)); ) { /* scene */
if (word_image(word) != el_img(el_spic))
continue;
if (word_image(word) != img) {
word = NULL;
/* first word is always pic */
break;
// continue;
}
word_geom(word, &xx, &yy, &ww, &hh);
yy -= txt_box_off(el_box(el_scene));
xx += el(el_scene)->x;
yy += el(el_scene)->y;
goto out;
break;
}
if (!word)
return -1;
out:
if (x)
*x = xx;
if (y)
*y = yy;
if (w)
*w = ww;
if (h)
*h = hh;
return 0;
}
static int game_pic_click(int x, int y, int *ox, int *oy)
{
int xx, yy, ww, hh;
if (game_pict_coord(&xx, &yy, &ww, &hh))
return -1;
if (x >= xx && y >= yy && x < (xx + ww) && y < (yy + hh)) {
*ox = x - xx;
*oy = y - yy;
@ -2521,7 +2669,7 @@ out:
return -1;
}
static int game_bg_coord(int x, int y, int *ox, int *oy)
static int game_bg_click(int x, int y, int *ox, int *oy)
{
struct el *o;
struct game_theme *t = &game_theme;
@ -2563,8 +2711,8 @@ static int game_input(int down, const char *key, int x, int y, int mb)
} else {
int px = -1;
int py = -1;
game_pic_coord(x, y, &px, &py); /* got picture coord */
if (game_bg_coord(x, y, &x, &y)) /* no click on bg */
game_pic_click(x, y, &px, &py); /* got picture coord */
if (game_bg_click(x, y, &x, &y)) /* no click on bg */
return -1;
snprintf(tx, sizeof(tx), "%d", x);
snprintf(ty, sizeof(ty), "%d", y);
@ -2595,6 +2743,7 @@ static int game_input(int down, const char *key, int x, int y, int mb)
if (opt_click && mb != -1)
snd_play(game_theme.click, -1, 0);
game_cmd(p); free(p);
mouse_restore();
return 0;
}
@ -2763,6 +2912,18 @@ int game_loop(void)
mouse_reset(1);
game_menu(menu_askquit);
#endif
} else if (alt_pressed && (!is_key(&ev, "q") || !is_key(&ev, "f4"))) {
break;
} else if (alt_pressed &&
(!is_key(&ev, "enter") || !is_key(&ev, "return"))) {
int old_menu = (menu_shown) ? cur_menu: -1;
shift_pressed = alt_pressed = 0;
opt_fs ^= 1;
game_restart();
if (old_menu != -1)
game_menu(old_menu);
} else if (game_theme.gfx_mode == GFX_MODE_DIRECT) {
; // nothing todo
} else if (!alt_pressed && (!is_key(&ev, "return") || !is_key(&ev, "enter")
#ifdef S60
|| !is_key(&ev, ".")
@ -2854,17 +3015,9 @@ int game_loop(void)
else
select_frame(0);
#endif
} else if (alt_pressed && (!is_key(&ev, "q") || !is_key(&ev, "f4"))) {
break;
} else if (alt_pressed &&
(!is_key(&ev, "enter") || !is_key(&ev, "return"))) {
int old_menu = (menu_shown) ? cur_menu: -1;
shift_pressed = alt_pressed = 0;
opt_fs ^= 1;
game_restart();
if (old_menu != -1)
game_menu(old_menu);
}
} else if (game_theme.gfx_mode == GFX_MODE_DIRECT) {
; // nothing todo
} else if (ev.type == MOUSE_DOWN) {
if (ev.code != 1)
disable_use();

View file

@ -78,6 +78,9 @@ extern char *open_file_dialog(void);
extern int game_from_disk(void);
extern int game_pict_modify(img_t p);
extern int game_pict_coord(int *x, int *y, int *w, int *h);
#define CURSOR_CLEAR -1
#define CURSOR_OFF 0
#define CURSOR_ON 1

View file

@ -12,6 +12,7 @@
#define Surf(p) ((SDL_Surface *)p)
static SDL_Surface *screen = NULL;
static cache_t images = NULL;
static struct {
const char *name;
@ -249,6 +250,7 @@ struct _anigif_t {
};
typedef struct _anigif_t *anigif_t;
extern int timer_counter;
static int anigif_spawn(anigif_t ag, int x, int y, int w, int h)
{
@ -287,7 +289,6 @@ static anigif_t anigif_find(anigif_t g)
}
return NULL;
}
extern int timer_counter;
static void anigif_disposal(anigif_t g)
{
@ -429,6 +430,8 @@ void gfx_free_image(img_t p)
anigif_t ag;
if (!p)
return;
if (!cache_forget(images, p))
return; /* cached sprite */
if ((ag = is_anigif(p))) {
if (ag->drawn)
anigif_drawn_nr --;
@ -669,7 +672,7 @@ static img_t img_pad(char *fname)
static img_t _gfx_load_combined_image(char *filename);
/* blank:WxH */
static img_t _gfx_load_special_image(char *f)
static img_t _gfx_load_special_image(char *f, int combined)
{
int alpha = 0;
int blank = 0;
@ -680,13 +683,17 @@ static img_t _gfx_load_special_image(char *f)
if (!f)
return NULL;
if (!(f = filename = strdup(f)))
return NULL;
if (!strncmp(filename, "blank:", 6)) {
filename += 6;
blank = 1;
} else if (!strncmp(filename, "spr:", 4) && !combined) {
// filename += 4;
img2 = cache_get(images, filename);
// fprintf(stderr, "get:%s %p\n", filename, img2);
goto out;
} else if (!strncmp(filename, "box:", 4)) {
filename += 4;
alpha = 255;
@ -726,6 +733,7 @@ skip:
img = gfx_new(wh[0], wh[1]);
if (!img)
goto err;
if (pc) {
color_t col = { .r = 255, .g = 255, .b = 255 };
gfx_parse_color(pc, &col);
@ -733,6 +741,7 @@ skip:
}
if (pt)
alpha = atoi(pt);
img2 = gfx_alpha_img(img, alpha);
gfx_free_image(img);
out:
@ -743,12 +752,17 @@ err:
return NULL;
}
static img_t _gfx_load_image(char *filename)
cache_t gfx_image_cache(void)
{
return images;
}
static img_t _gfx_load_image(char *filename, int combined)
{
SDL_Surface *img;
int nr = 0;
filename = strip(filename);
img = _gfx_load_special_image(filename);
img = _gfx_load_special_image(filename, combined);
if (img)
return img;
filename = dirpath(filename);
@ -802,7 +816,7 @@ static img_t _gfx_load_combined_image(char *filename)
goto err; /* first image is a base image */
*ep = 0;
base = _gfx_load_image(strip(p));
base = _gfx_load_image(strip(p), 1);
if (!base)
goto err;
p = ep + 1;
@ -825,7 +839,7 @@ static img_t _gfx_load_combined_image(char *filename)
} else if (*ep) {
goto err;
}
img = _gfx_load_image(strip(p));
img = _gfx_load_image(strip(p), 1);
if (img) {
to.x = x; to.y = y;
if (c) {
@ -852,7 +866,7 @@ img_t gfx_load_image(char *filename)
if (!filename)
return NULL;
/* if (!access(filename, R_OK)) */
img = _gfx_load_image(filename);
img = _gfx_load_image(filename, 0);
if (!img)
img = _gfx_load_combined_image(filename);
if (!img)
@ -875,10 +889,13 @@ void gfx_draw_bg(img_t p, int x, int y, int width, int height)
SDL_BlitSurface(pixbuf, &src, screen, &dest);
}
void gfx_draw_from(img_t p, int x, int y, int xx, int yy, int width, int height)
void gfx_draw_from(img_t p, int x, int y, int width, int height, img_t to, int xx, int yy)
{
SDL_Surface *pixbuf = (SDL_Surface *)p;
SDL_Surface *scr = (SDL_Surface *)to;
SDL_Rect dest, src;
if (!scr)
scr = screen;
src.x = x;
src.y = y;
src.w = width;
@ -887,7 +904,7 @@ void gfx_draw_from(img_t p, int x, int y, int xx, int yy, int width, int height)
dest.y = yy;
dest.w = width;
dest.h = height;
SDL_BlitSurface(pixbuf, &src, screen, &dest);
SDL_BlitSurface(pixbuf, &src, scr, &dest);
}
void gfx_draw(img_t p, int x, int y)
@ -945,19 +962,18 @@ int gfx_frame_gif(img_t img)
{
anigif_t ag;
ag = is_anigif(img);
if (!ag)
return 0;
if (!ag->drawn || !ag->active)
return 0;
if (ag->loop == -1)
return 0;
if ((timer_counter - ag->delay) < (ag->frames[ag->cur_frame].delay / HZ))
return 0;
if (ag->cur_frame != ag->nr_frames - 1 || ag->loop > 1 || !ag->loop)
anigif_disposal(ag);
@ -977,6 +993,7 @@ int gfx_frame_gif(img_t img)
}
if (ag->loop != -1)
anigif_frame(ag);
return 1;
}
@ -2150,24 +2167,38 @@ void _txt_layout_free(layout_t lay)
layout->vcnt = 0;
}
word_t txt_layout_words(layout_t lay, word_t v)
word_t txt_layout_words_ex(layout_t lay, struct line *line, word_t v, int off, int height)
{
struct layout *layout = (struct layout*)lay;
struct word *w = (struct word*)v;
struct layout *layout = (struct layout *)lay;
struct line *line;
if (!layout)
if (!lay)
return NULL;
if (!w) {
if (!(line = layout->lines))
if (!line)
line = layout->lines;
if (!line)
return NULL;
w = line->words;
} else {
line = w->line;
w = w->next;
}
for (; !w && line->next; line = line->next, w = line->words);
return w;
for (; (!w || (line->y + line->h) < off) && line->next; line = line->next, w = line->words);
if ((line->y + line->h) < off)
w = NULL;
else if (height >= 0 && line->y - off > height)
w = NULL;
return w;
}
word_t txt_layout_words(layout_t lay, word_t v)
{
return txt_layout_words_ex(lay, NULL, v, 0, -1);
}
void txt_layout_free(layout_t lay)
{
struct layout *layout = (struct layout *)lay;
@ -2724,7 +2755,6 @@ void xref_update(xref_t pxref, int x, int y, clear_fn clear, update_fn update)
gfx_noclip();
}
void txt_layout_draw_ex(layout_t lay, struct line *line, int x, int y, int off, int height, clear_fn clear)
{
void *v;
@ -3891,11 +3921,18 @@ int gfx_init(void)
fprintf(stderr, "Couldn't initialize SDL: %s\n", SDL_GetError());
return -1;
}
if (!(images = cache_init(-1, gfx_free_image))) {
fprintf(stderr, "Can't init cache subsystem.\n");
gfx_done();
return -1;
}
return 0;
}
void gfx_done(void)
{
cache_free(images);
images = NULL;
SDL_Quit();
}

View file

@ -55,6 +55,7 @@ extern void gfx_done(void);
extern int gfx_parse_color (const char *spec, color_t *def);
extern void gfx_flip(void);
extern cache_t gfx_image_cache(void);
extern img_t gfx_screen(img_t nscreen);
extern void gfx_bg(color_t col);
extern void gfx_noclip(void);
@ -86,7 +87,7 @@ extern img_t gfx_alpha_img(img_t src, int alpha);
extern img_t gfx_display_alpha(img_t src);
extern img_t gfx_scale(img_t src, float xscale, float yscale);
extern void gfx_draw_bg(img_t p, int x, int y, int width, int height);
extern void gfx_draw_from(img_t p, int x, int y, int xx, int yy, int width, int height);
extern void gfx_draw_from(img_t p, int x, int y, int width, int height, img_t to, int xx, int yy);
extern void gfx_cursor(int *xp, int *yp);
extern void gfx_warp_cursor(int x, int y);
extern void gfx_change_screen(img_t src, int steps);
@ -98,6 +99,7 @@ extern fnt_t fnt_load(const char *fname, int size);
extern void fnt_free(fnt_t);
extern int fnt_height(fnt_t fn);
extern void fnt_style(fnt_t fn, int style);
extern img_t fnt_render(fnt_t fn, const char *p, color_t col);
extern void txt_draw(fnt_t fnt, const char *txt, int x, int y, color_t col);
extern void txt_size(fnt_t fnt, const char *txt, int *w, int *h);

View file

@ -1,5 +1,6 @@
#include "externals.h"
#include "internals.h"
#include "list.h"
#ifndef STEAD_PATH
#define STEAD_PATH "./stead"
@ -458,6 +459,7 @@ static int luaB_get_steadpath(lua_State *L) {
extern void mouse_reset(int hl); /* too bad */
extern void mouse_restore(void);
static void instead_timer_do(void *data)
{
@ -472,7 +474,9 @@ static void instead_timer_do(void *data)
if (!p)
goto out;
mouse_reset(0);
// fprintf(stderr, "cmd =%s\n", p);
game_cmd(p); free(p);
mouse_restore();
game_cursor(CURSOR_ON);
out:
instead_timer_nr = 0;
@ -531,6 +535,489 @@ static int luaB_theme_var(lua_State *L) {
extern int dir_iter_factory (lua_State *L);
extern int luaopen_lfs (lua_State *L);
static LIST_HEAD(sprites);
static LIST_HEAD(fonts);
typedef struct {
struct list_head list;
char *name;
fnt_t fnt;
} _fnt_t;
typedef struct {
struct list_head list;
char *name;
img_t img;
} _spr_t;
static void sprites_free(void)
{
// fprintf(stderr, "sprites free \n");
while (!list_empty(&sprites)) {
_spr_t *sp = (_spr_t*)(sprites.next);
free(sp->name);
cache_forget(gfx_image_cache(), sp->img);
list_del(&sp->list);
free(sp);
}
while (!list_empty(&fonts)) {
_fnt_t *fn = (_fnt_t*)(fonts.next);
fnt_free(fn->fnt);
free(fn->name);
list_del(&fn->list);
free(fn);
}
game_pict_modify(NULL);
cache_shrink(gfx_image_cache());
}
static _spr_t *sprite_lookup(const char *name)
{
struct list_head *pos;
_spr_t *sp;
list_for_each(pos, &sprites) {
sp = (_spr_t*)pos;
if (!strcmp(name, sp->name)) {
list_move(&sp->list, &sprites); // move it on head
return sp;
}
}
return NULL;
}
static _fnt_t *font_lookup(const char *name)
{
struct list_head *pos;
_fnt_t *fn;
list_for_each(pos, &fonts) {
fn = (_fnt_t*)pos;
if (!strcmp(name, fn->name)) {
list_move(&fn->list, &fonts); // move it on head
return fn;
}
}
return NULL;
}
static _spr_t *sprite_new(const char *name, img_t img)
{
_spr_t *sp;
sp = malloc(sizeof(_spr_t));
if (!sp)
return NULL;
INIT_LIST_HEAD(&sp->list);
sp->name = strdup(name);
if (!sp->name) {
free(sp);
return NULL;
}
sp->img = img;
if (cache_add(gfx_image_cache(), name, img)) {
free(sp->name);
free(sp);
return NULL;
}
// fprintf(stderr, "added: %s\n", name);
list_add(&sp->list, &sprites);
return sp;
}
static _fnt_t *font_new(const char *name, fnt_t fnt)
{
_fnt_t *fn;
fn = malloc(sizeof(_fnt_t));
if (!fn)
return NULL;
INIT_LIST_HEAD(&fn->list);
fn->name = strdup(name);
if (!fn->name) {
free(fn);
return NULL;
}
fn->fnt = fnt;
list_add(&fn->list, &fonts);
return fn;
}
static void sprite_name(const char *name, char *sname, int size)
{
unsigned long h = 0;
if (!sname || !size)
return;
h = hash_string(name);
do { /* new uniq name */
snprintf(sname, size, "spr:%lx", h);
h ++;
} while (sprite_lookup(sname) || cache_lookup(gfx_image_cache(), sname));
sname[size - 1] = 0;
}
static void font_name(const char *name, char *sname, int size)
{
unsigned long h = 0;
if (!sname || !size)
return;
h = hash_string(name);
do { /* new uniq name */
snprintf(sname, size, "fnt:%lx", h);
h ++;
} while (font_lookup(sname));
sname[size - 1] = 0;
}
static int luaB_free_sprites(lua_State *L) {
sprites_free();
return 0;
}
static int luaB_load_sprite(lua_State *L) {
img_t img = NULL;
_spr_t *sp;
const char *key;
char sname[sizeof(unsigned long) * 2 + 16];
const char *fname = luaL_optstring(L, 1, NULL);
const char *desc = luaL_optstring(L, 2, NULL);
if (!fname)
return 0;
img = gfx_load_image((char*)fname);
if (img)
theme_img_scale(&img);
if (!img)
goto err;
if (!desc || sprite_lookup(desc)) {
key = sname;
sprite_name(fname, sname, sizeof(sname));
} else
key = desc;
sp = sprite_new(key, img);
if (!sp)
goto err;
lua_pushstring(L, key);
return 1;
err:
gfx_free_image(img);
return 0;
}
static int luaB_load_font(lua_State *L) {
fnt_t fnt = NULL;
_fnt_t *fn;
const char *key;
char sname[sizeof(unsigned long) * 2 + 16];
struct game_theme *t = &game_theme;
const char *fname = luaL_optstring(L, 1, NULL);
int sz = luaL_optnumber(L, 2, t->font_size) * game_theme.scale;
const char *desc = luaL_optstring(L, 3, NULL);
if (!fname)
return 0;
fnt = fnt_load((char*)fname, sz);
if (!fnt)
return 0;
if (!desc || font_lookup(desc)) {
key = sname;
font_name(fname, sname, sizeof(sname));
} else
key = desc;
fn = font_new(key, fnt);
if (!fn)
goto err;
lua_pushstring(L, key);
return 1;
err:
fnt_free(fnt);
return 0;
}
static int luaB_text_size(lua_State *L) {
_fnt_t *fn;
int w = 0, h = 0;
const char *font = luaL_optstring(L, 1, NULL);
const char *text = luaL_optstring(L, 2, NULL);
if (!font)
return 0;
fn = font_lookup(font);
if (!fn)
return 0;
if (!text) {
w = 0;
h = fnt_height(fn->fnt);
} else
txt_size(fn->fnt, text, &w, &h);
lua_pushnumber(L, w);
lua_pushnumber(L, h);
return 2;
}
static int luaB_text_sprite(lua_State *L) {
img_t img = NULL;
_spr_t *sp;
_fnt_t *fn;
const char *key;
char sname[sizeof(unsigned long) * 2 + 16];
const char *font = luaL_optstring(L, 1, NULL);
const char *text = luaL_optstring(L, 2, NULL);
char txtkey[8];
const char *color = luaL_optstring(L, 3, NULL);
int style = luaL_optnumber(L, 4, 0);
color_t col = { .r = game_theme.fgcol.r, .g = game_theme.fgcol.g, .b = game_theme.fgcol.b };
if (!font)
return 0;
if (color)
gfx_parse_color (color, &col);
if (!text)
text = "";
fn = font_lookup(font);
if (!fn)
return 0;
fnt_style(fn->fnt, style);
img = fnt_render(fn->fnt, text, col);
if (!img)
return 0;
key = sname;
strncpy(txtkey, text, sizeof(txtkey));
txtkey[sizeof(txtkey) - 1] = 0;
sprite_name(text, sname, sizeof(sname));
sp = sprite_new(key, img);
if (!sp)
goto err;
lua_pushstring(L, key);
return 1;
err:
gfx_free_image(img);
return 0;
}
static int luaB_sprite_size(lua_State *L) {
img_t s = NULL;
float v;
int w, h;
const char *src = luaL_optstring(L, 1, NULL);
if (!src)
return 0;
s = cache_lookup(gfx_image_cache(), src);
if (!s)
return 0;
v = game_theme.scale;
w = gfx_img_w(s) / v;
h = gfx_img_h(s) / v;
lua_pushnumber(L, w);
lua_pushnumber(L, h);
return 2;
}
static img_t grab_sprite(const char *dst, int *xoff, int *yoff)
{
img_t d;
if (game_theme.gfx_mode == GFX_MODE_DIRECT && !strcmp(dst, "screen")) {
d = gfx_screen(NULL);
*xoff = game_theme.xoff;
*yoff = game_theme.yoff;
} else
d = cache_lookup(gfx_image_cache(), dst);
return d;
}
static int luaB_draw_sprite(lua_State *L) {
img_t s, d;
img_t img2 = NULL;
float v;
const char *src = luaL_optstring(L, 1, NULL);
int x = luaL_optnumber(L, 2, 0);
int y = luaL_optnumber(L, 3, 0);
int w = luaL_optnumber(L, 4, 0);
int h = luaL_optnumber(L, 5, 0);
const char *dst = luaL_optstring(L, 6, NULL);
int xx = luaL_optnumber(L, 7, 0);
int yy = luaL_optnumber(L, 8, 0);
int alpha = luaL_optnumber(L, 9, 255);
int xoff = 0, yoff = 0;
int xoff0 = 0, yoff0 = 0;
if (!src || !dst)
return 0;
s = grab_sprite(src, &xoff0, &yoff0);
d = grab_sprite(dst, &xoff, &yoff);
if (!s || !d)
return 0;
v = game_theme.scale;
if (v != 1.0f) {
x *= v;
y *= v;
w *= v;
h *= v;
xx *= v;
yy *= v;
}
if (!w)
w = gfx_img_w(s) - 2 * xoff0;
if (!h)
h = gfx_img_h(s) - 2 * yoff0;
game_pict_modify(d);
if (alpha != 255) {
img2 = gfx_alpha_img(s, alpha);
if (img2)
s = img2;
}
gfx_draw_from(s, x + xoff0, y + yoff0, w, h, d, xx + xoff, yy + yoff);
gfx_free_image(img2);
lua_pushboolean(L, 1);
return 1;
}
static int luaB_alpha_sprite(lua_State *L) {
_spr_t *sp;
img_t s;
img_t img2 = NULL;
const char *key;
char sname[sizeof(unsigned long) * 2 + 16];
const char *src = luaL_optstring(L, 1, NULL);
int alpha = luaL_optnumber(L, 2, 255);
const char *desc = luaL_optstring(L, 3, NULL);
if (!src)
return 0;
s = cache_lookup(gfx_image_cache(), src);
if (!s)
return 0;
img2 = gfx_alpha_img(s, alpha);
if (!img2)
return 0;
if (!desc || sprite_lookup(desc)) {
key = sname;
sprite_name(src, sname, sizeof(sname));
} else
key = desc;
sp = sprite_new(key, img2);
if (!sp)
goto err;
lua_pushstring(L, sname);
return 1;
err:
gfx_free_image(img2);
return 0;
}
static int luaB_fill_sprite(lua_State *L) {
img_t d;
float v;
const char *dst = luaL_optstring(L, 1, NULL);
int x = luaL_optnumber(L, 2, 0);
int y = luaL_optnumber(L, 3, 0);
int w = luaL_optnumber(L, 4, 0);
int h = luaL_optnumber(L, 5, 0);
const char *color = luaL_optstring(L, 6, 0);
int xoff = 0, yoff = 0;
color_t col = { .r = game_theme.bgcol.r, .g = game_theme.bgcol.g, .b = game_theme.bgcol.b };
if (!dst)
return 0;
d = grab_sprite(dst, &xoff, &yoff);
if (color)
gfx_parse_color(color, &col);
if (!d)
return 0;
v = game_theme.scale;
if (v != 1.0f) {
x *= v;
y *= v;
w *= v;
h *= v;
}
if (!w)
w = gfx_img_w(d) - 2 * xoff;
if (!h)
h = gfx_img_h(d) - 2 * yoff;
game_pict_modify(d);
gfx_img_fill(d, x + xoff, y + yoff, w, h, col);
lua_pushboolean(L, 1);
return 1;
}
static int luaB_free_sprite(lua_State *L) {
const char *key = luaL_optstring(L, 1, NULL);
_spr_t *sp;
if (!key)
return 0;
sp = sprite_lookup(key);
if (!sp)
return 0;
cache_forget(gfx_image_cache(), sp->img);
cache_shrink(gfx_image_cache());
list_del(&sp->list);
free(sp->name); free(sp);
lua_pushboolean(L, 1);
return 1;
}
static int luaB_free_font(lua_State *L) {
const char *key = luaL_optstring(L, 1, NULL);
_fnt_t *fn;
if (!key)
return 0;
fn = font_lookup(key);
if (!fn)
return 0;
list_del(&fn->list);
free(fn->name); free(fn);
lua_pushboolean(L, 1);
return 1;
}
static const luaL_Reg base_funcs[] = {
{"doencfile", luaB_doencfile},
{"dofile", luaB_dofile},
@ -542,6 +1029,19 @@ static const luaL_Reg base_funcs[] = {
{"set_timer", luaB_set_timer},
{"theme_var", luaB_theme_var},
{"readdir", dir_iter_factory},
{"font_load", luaB_load_font},
{"font_free", luaB_free_font},
{"sprite_load", luaB_load_sprite},
{"sprite_text", luaB_text_sprite},
{"sprite_free", luaB_free_sprite},
{"sprites_free", luaB_free_sprites},
{"sprite_draw", luaB_draw_sprite},
{"sprite_fill", luaB_fill_sprite},
{"sprite_alpha", luaB_alpha_sprite},
{"sprite_size", luaB_sprite_size},
{"sprite_text_size", luaB_text_size},
{NULL, NULL}
};
@ -612,6 +1112,7 @@ int instead_init(void)
}
/* cleanup Lua */
instead_clear();
srand(time(NULL));
return 0;
}
@ -629,6 +1130,7 @@ void instead_done(void)
#ifdef _HAVE_ICONV
fromcp = NULL;
#endif
sprites_free();
}
int instead_encode(const char *s, const char *d)
@ -665,4 +1167,3 @@ int instead_encode(const char *s, const char *d)
fclose(dst);
return 0;
}

View file

@ -15,6 +15,8 @@ static int parse_gfx_mode(const char *v, void *data)
*i = GFX_MODE_EMBEDDED;
else if (!strcmp(v, "float"))
*i = GFX_MODE_FLOAT;
else if (!strcmp(v, "direct"))
*i = GFX_MODE_DIRECT;
else
return -1;
return 0;
@ -33,6 +35,9 @@ static int out_gfx_mode(const void *v, char **out)
case GFX_MODE_FLOAT:
o = strdup("float");
break;
case GFX_MODE_DIRECT:
o = strdup("direct");
break;
default:
o = strdup("");
break;
@ -364,6 +369,10 @@ int theme_img_scale(img_t *p)
float v = game_theme.scale;
if (!p || !*p || v == 1.0f)
return 0;
if (!cache_have(gfx_image_cache(), p))
return 0; /* do not scale sprites! */
pic = gfx_scale(*p, v, v);
if (!pic)
return -1;

View file

@ -147,6 +147,7 @@ extern int theme_relative;
#define GFX_MODE_FLOAT 0
#define GFX_MODE_FIXED 1
#define GFX_MODE_EMBEDDED 2
#define GFX_MODE_DIRECT 3
#define INV_MODE_DISABLED -1
#define INV_MODE_VERT 0

View file

@ -26,6 +26,7 @@ install:
$(INSTALL) hotkeys.lua $(STEADPATH)/hotkeys.lua
$(INSTALL) hideinv.lua $(STEADPATH)/hideinv.lua
$(INSTALL) theme.lua $(STEADPATH)/theme.lua
$(INSTALL) sprites.lua $(STEADPATH)/sprites.lua
uninstall:
$(RM) $(STEADPATH)/stead.lua

View file

@ -23,3 +23,4 @@ install:
copy hotkeys.lua ..\bin\stead
copy hideinv.lua ..\bin\stead
copy theme.lua ..\bin\stead
copy sprites.lua ..\bin\stead

60
stead/sprites.lua Normal file
View file

@ -0,0 +1,60 @@
require "theme"
sprite = {
nam = 'sprites';
object_type = true;
system_type = true;
ini = function(s)
if type(s.load) == 'function' then
sprites_free();
sprite.init();
end
end;
screen = function(s)
if theme.get 'scr.gfx.mode' ~= 'direct' then
return
end
return 'screen'
end;
font = function(font, size)
return font_load(font, size);
end;
free_font = function(font)
return font_free(key);
end;
alpha = function(name, alpha)
return sprite_alpha(name, alpha);
end;
text = function(font, text, col, style)
return sprite_text(font, text, col, style);
end;
size = function(spr)
return sprite_size(spr);
end;
text_size = function(spr)
return sprite_text_size(spr);
end;
draw = function(s, fx, fy, fw, fh, d, x, y, alpha)
if d == nil and x == nil and y == nil then
return sprite_draw(s, 0, 0, 0, 0, fx, fy, fw, fh);
end
return sprite_draw(s, fx, fy, fw, fh, d, x, y, alpha);
end;
fill = function(d, x, y, w, h, col)
if h == nil and col == nil then
return sprite_fill(d, 0, 0, 0, 0, x, y, w);
end
return sprite_fill(d, x, y, w, h, col);
end;
load = function(fname)
return sprite_load(fname);
end;
free = function(key)
return sprite_free(key);
end;
}
stead.module_init(function()
sprites_free();
end)

View file

@ -1540,9 +1540,8 @@ function do_ini(self, load)
local function call_ini(k, o, ...)
v = stead.par('', v, call(o, 'ini'), ...);
end
math.randomseed(tonumber(os.date("%m%d%H%M%S")))
rnd(1); rnd(1); rnd(1); -- Lua bug?
math.randomseed(os.time(os.date("*t")))
rnd(1); rnd(2); rnd(3); -- Lua bug?
game.pl = deref(game.pl);
game.where = deref(game.where);