Example 4 demonstrates fast drawing routines and putting slabs with mouse. Also, shows how to draw ADiKtEd messages using DK font. Use left/right arrows to switch levels, numpad +/- to zoom, LMB to move, RMB to put temple tiles.
#include <stdlib.h>
#include <string.h>
#include <SDL/SDL.h>
#include "../libadikted/adikted.h"
#define ONE_LOOP_DELAY 20
SDL_Surface *screen = NULL;
struct MAPDRAW_DATA *draw_data=NULL;
SDL_Surface *bitmap=NULL;
struct IPOINT_2D startpt;
struct IPOINT_2D map_size;
struct LEVEL *lvl;
static int lvl_idx=11;
static short done=0;
short prepare_map_drawing(struct LEVEL *lvl, int width, int height)
{
short result;
struct MAPDRAW_OPTIONS *opts=level_get_mapdraw_options(lvl);
free_draw_data(draw_data);
SDL_FreeSurface(bitmap);
struct IPOINT_2D bmp_size;
get_full_draw_dimensions_opt(&map_size,&(lvl->subsize),opts);
message_log("Map dimensions %d,%d.",map_size.x,map_size.y);
if (map_size.x>width)
bmp_size.x=width+1;
else
bmp_size.x=map_size.x;
if (map_size.y>height)
bmp_size.y=height+1;
else
bmp_size.y=map_size.y;
message_log("Bitmap dimensions %d,%d.",bmp_size.x,bmp_size.y);
result=load_draw_data(&draw_data,opts,&(lvl->subsize),bmp_size,get_lvl_inf(lvl));
if (result==ERR_NONE)
{
bitmap=SDL_CreateRGBSurface(SDL_SWSURFACE,bmp_size.x,bmp_size.y,24,0x00ff0000,0x000000ff,0x0000ff00,0);
if (bitmap==NULL)
{
message_error("prepare_map_drawing: Cannot create bitmap surface.");
free_draw_data(draw_data);
result=2;
}
set_draw_data_rect(draw_data,startpt.x,startpt.y,
startpt.x+bmp_size.x-1,startpt.y+bmp_size.y-1,bitmap->pitch,opts->rescale);
}
return result;
}
static void draw_screen()
{
if (screen->w > bitmap->w)
SDL_FillRect(screen,NULL,0);
SDL_BlitSurface(bitmap, NULL, screen, NULL);
SDL_Flip (screen);
}
static void process_events()
{
static struct IPOINT_2D viewmove={0,0};
static short clip_view=0;
static short reload_data=1;
static short reload_lvl=1;
static short level_redraw=1;
static short slab_drawing = -1;
static struct IPOINT_2D mouse_movestart={-1,0};
SDL_Event event;
while (SDL_PollEvent(&event))
{
switch (event.type)
{
case SDL_KEYDOWN:
switch (event.key.keysym.sym)
{
case SDLK_PLUS:
case SDLK_KP_PLUS:
{
struct MAPDRAW_OPTIONS *opts=level_get_mapdraw_options(lvl);
if (opts->rescale > 0)
{
opts->rescale--;
startpt.x = (startpt.x<<1) + (bitmap->w/2);
startpt.y = (startpt.y<<1) + (bitmap->h/2);
clip_view=1;
reload_data=1;
} else
{
message_error("Scale factor minimum reached");
level_redraw=1;
}
};break;
case SDLK_MINUS:
case SDLK_KP_MINUS:
{
struct MAPDRAW_OPTIONS *opts=level_get_mapdraw_options(lvl);
if (opts->rescale < 5)
{
opts->rescale++;
startpt.x = (startpt.x>>1) - (bitmap->w/4);
startpt.y = (startpt.y>>1) - (bitmap->h/4);
clip_view=1;
reload_data=1;
} else
{
message_error("Maxumum scale factor reached");
level_redraw=1;
}
};break;
case SDLK_RIGHT:
lvl_idx%=20;
lvl_idx+=1;
reload_lvl=1;
break;
case SDLK_LEFT:
lvl_idx--;
if (lvl_idx<=0) lvl_idx=20;
reload_lvl=1;
break;
case SDLK_DOWN:
viewmove.y=1;
break;
case SDLK_UP:
viewmove.y=-1;
break;
case SDLK_END:
viewmove.x=16;
break;
case SDLK_HOME:
viewmove.x=-16;
break;
case SDLK_PAGEDOWN:
viewmove.y=16;
break;
case SDLK_PAGEUP:
viewmove.y=-16;
break;
case SDLK_ESCAPE:
done = 1;
break;
}
break;
case SDL_KEYUP:
switch (event.key.keysym.sym)
{
case SDLK_LEFT:
case SDLK_RIGHT:
case SDLK_END:
case SDLK_HOME:
viewmove.x=0;
break;
case SDLK_DOWN:
case SDLK_UP:
case SDLK_PAGEDOWN:
case SDLK_PAGEUP:
viewmove.y=0;
break;
}
break;
case SDL_MOUSEBUTTONDOWN:
switch (event.button.button)
{
case SDL_BUTTON_LEFT:
{
short obj_reslt;
unsigned int sx,sy,z;
obj_reslt=get_object_with_circle_at(&sx,&sy,&z,draw_data,lvl,
event.button.x,event.button.y);
if (obj_reslt==ERR_NONE)
{
unsigned char *obj=get_object(lvl,sx,sy,z);
char *obj_name;
switch (get_object_type(lvl,sx,sy,z))
{
case OBJECT_TYPE_THING:
obj_name=get_thing_subtype_fullname(get_thing_type(obj),get_thing_subtype(obj));
break;
case OBJECT_TYPE_ACTNPT:
obj_name="Action point";
break;
case OBJECT_TYPE_STLIGHT:
obj_name="Static light";
break;
default:
obj_name="Unknown object";
break;
}
message_info("%s at (%d,%d)",obj_name,sx,sy);
level_redraw=1;
} else
{
mouse_movestart.x=event.button.x;
mouse_movestart.y=event.button.y;
}
}
break;
case SDL_BUTTON_RIGHT:
{
slab_drawing=SLAB_TYPE_TEMPLE;
unsigned int sx,sy;
get_subtile_from_draw_coords(&sx,&sy,draw_data,
event.button.x,event.button.y);
unsigned int tx,ty;
tx=sx/MAP_SUBNUM_X;ty=sy/MAP_SUBNUM_Y;
if (get_tile_slab(lvl,tx,ty)!=slab_drawing)
{
user_set_slab(lvl,tx,ty,slab_drawing);
user_set_tile_owner(lvl,tx,ty,PLAYER0);
}
message_info("New %s put at (%d,%d)",
get_slab_fullname(get_tile_slab(lvl,tx,ty)),tx,ty);
level_redraw=1;
}
break;
}
break;
case SDL_MOUSEBUTTONUP:
switch (event.button.button)
{
case SDL_BUTTON_LEFT:
mouse_movestart.x=-1;
break;
case SDL_BUTTON_RIGHT:
slab_drawing=-1;
break;
}
break;
case SDL_MOUSEMOTION:
if (mouse_movestart.x>=0)
{
startpt.x+=mouse_movestart.x-event.motion.x;
startpt.y+=mouse_movestart.y-event.motion.y;
mouse_movestart.x=event.motion.x;
mouse_movestart.y=event.motion.y;
clip_view=1;
}
if (slab_drawing>=0)
{
unsigned int sx,sy;
get_subtile_from_draw_coords(&sx,&sy,draw_data,
event.motion.x-event.motion.xrel,event.motion.y-event.motion.yrel);
struct IPOINT_2D tile_prv;
tile_prv.x=sx/MAP_SUBNUM_X;
tile_prv.y=sy/MAP_SUBNUM_Y;
get_subtile_from_draw_coords(&sx,&sy,draw_data,
event.motion.x,event.motion.y);
struct IPOINT_2D tile_cur;
tile_cur.x=sx/MAP_SUBNUM_X;
tile_cur.y=sy/MAP_SUBNUM_Y;
int dist_x=(tile_prv.x-tile_cur.x);
int dist_y=(tile_prv.y-tile_cur.y);
int max_dist=max(abs(dist_x),abs(dist_y));
max_dist++;
int i;
int tx,ty;
for (i=0;i<max_dist;i++)
{
tx=tile_cur.x+(dist_x*i/max_dist);
ty=tile_cur.y+(dist_y*i/max_dist);
if (get_tile_slab(lvl,tx,ty)!=slab_drawing)
{
user_set_slab(lvl,tx,ty,slab_drawing);
user_set_tile_owner(lvl,tx,ty,PLAYER0);
}
}
if (max_dist==1)
message_info("New %s put at (%d,%d)",
get_slab_fullname(get_tile_slab(lvl,tx,ty)),tx,ty);
else
message_info("Changed %d slabs, last at (%d,%d)",max_dist,tx,ty);
level_redraw=1;
}
break;
case SDL_VIDEORESIZE:
screen = SDL_SetVideoMode(event.resize.w, event.resize.h, 24, SDL_SWSURFACE|SDL_RESIZABLE);
if (screen == NULL)
{
message_error("Couldn't change video mode: %s\n", SDL_GetError());
reload_data=0;
level_redraw=0;
clip_view=0;
done = 1;
return;
}
clip_view=1;
reload_data=1;
break;
case SDL_QUIT:
done = 1;
break;
default:
break;
}
}
if (viewmove.x)
{
startpt.x+=viewmove.x;
clip_view=1;
}
if (viewmove.y)
{
startpt.y+=viewmove.y;
clip_view=1;
}
if (reload_lvl)
{
char level_fname[16];
sprintf(level_fname,"MAP%05d",lvl_idx);
format_lvl_fname(lvl,level_fname);
message_info("loading map file...");
short result;
result=user_load_map(lvl,0);
if (result!=ERR_NONE)
{
message_release();
message_info("example4 finished with map load error");
reload_data=0;
level_redraw=0;
clip_view=0;
done = 1;
return;
}
message_info("%s loaded successfully",level_fname);
reload_lvl=0;
reload_data=1;
level_redraw=1;
}
if (reload_data)
{
short result;
result=prepare_map_drawing(lvl, screen->w, screen->h);
if (result!=ERR_NONE)
{
message_release();
message_info("example4 finished with data files load error");
level_redraw=0;
clip_view=0;
done = 1;
return;
}
message_info("Data reloaded for rescale %d",draw_data->rescale);
reload_data=0;
level_redraw=1;
}
if (clip_view)
{
if (startpt.x>map_size.x-screen->w)
startpt.x=map_size.x-screen->w;
if (startpt.y>map_size.y-screen->h)
startpt.y=map_size.y-screen->h;
if (startpt.x<0) startpt.x=0;
if (startpt.y<0) startpt.y=0;
struct MAPDRAW_OPTIONS *opts=level_get_mapdraw_options(lvl);
set_draw_data_rect(draw_data,startpt.x,startpt.y,
startpt.x+bitmap->w-1,startpt.y+bitmap->h-1,bitmap->pitch,opts->rescale);
clip_view=0;
level_redraw=1;
}
if (level_redraw)
{
struct MAPDRAW_OPTIONS *opts=level_get_mapdraw_options(lvl);
SDL_LockSurface(bitmap);
draw_map_on_buffer_fast(bitmap->pixels,lvl,draw_data,0);
if ((opts->rescale)<5)
draw_things_on_buffer(bitmap->pixels,lvl,draw_data);
draw_text_on_buffer(bitmap->pixels,16,bitmap->h-18,message_get(),draw_data,1);
draw_text_on_buffer(bitmap->pixels,16,bitmap->h-32,message_get_prev(),draw_data,0);
message_release();
SDL_UnlockSurface(bitmap);
level_redraw=0;
}
}
int main (int argc, char *argv[])
{
init_messages();
set_msglog_fname("putemple.log");
message_log("Initializing SDL");
if (SDL_Init (SDL_INIT_VIDEO) < 0)
{
message_error("Couldn't initialize SDL: %s\n", SDL_GetError());
free_messages();
return 1;
}
atexit (SDL_Quit);
screen = SDL_SetVideoMode (512, 512, 24, SDL_SWSURFACE | SDL_RESIZABLE);
if (screen == NULL)
{
message_error("Couldn't set video mode: %s\n", SDL_GetError());
free_messages();
return 2;
}
SDL_WM_SetCaption ("ADiKtEd Libray example 4", NULL);
message_log("Preparing data structures");
level_init(&lvl,MFV_DKGOLD,NULL);
set_levels_path(lvl,"./Levels");
set_data_path(lvl,"./data");
struct MAPDRAW_OPTIONS *opts=level_get_mapdraw_options(lvl);
opts->rescale = 3;
opts->bmfonts |= BMFONT_LOAD_SMALL|BMFONT_LOAD_LARGE;
opts->tngflags |= TNGFLG_SHOW_CIRCLES;
message_info("entering application loop");
while (!done)
{
time_t begin_tm;
time_t end_tm;
time(&begin_tm);
process_events();
draw_screen();
time(&end_tm);
int delay=(end_tm-begin_tm);
if (delay<ONE_LOOP_DELAY)
SDL_Delay(ONE_LOOP_DELAY-delay);
}
message_info("application loop terminated");
free_draw_data(draw_data);
level_free(lvl);
level_deinit(&lvl);
free_messages();
return 0;
}