1 /*
2 * Abuse - dark 2D side-scrolling platform game
3 * Copyright (c) 1995 Crack dot Com
4 * Copyright (c) 2005-2011 Sam Hocevar <sam@hocevar.net>
5 *
6 * This software was released into the Public Domain. As with most public
7 * domain software, no warranty is made or implied by Crack dot Com, by
8 * Jonathan Clark, or by Sam Hocevar.
9 */
10
11 #if defined HAVE_CONFIG_H
12 # include "config.h"
13 #endif
14
15 #include "common.h"
16
17 #include "automap.h"
18 #include "game.h"
19
20 automap *current_automap=0;
21
draw()22 void automap::draw()
23 {
24 if (!automap_window) return ;
25 image *screen=automap_window->screen;
26
27 long sx,ex,sy,ey,x,y,window_xstart,window_ystart,
28 window_xend,window_yend,centerx,centery,
29 draw_xstart,draw_ystart,
30 i,j;
31
32 x=the_game->first_view->x_center();
33 y=the_game->first_view->y_center();
34
35
36 window_xstart=automap_window->x1();
37 window_ystart=automap_window->y1();
38 window_xend=automap_window->x2();
39 window_yend=automap_window->y2();
40 centerx=(window_xstart+window_xend)/2;
41 centery=(window_ystart+window_yend)/2;
42
43 sx=x/f_wid-w/2; // start drawing with this foretile
44 sy=y/f_hi-h/2;
45 ex=sx+w;
46 ey=sy+h;
47
48 if (sx<0) // does the map scroll past the left side ?
49 { sx=0; // yes, start drawing at 0
50 draw_xstart=centerx-(x*AUTOTILE_WIDTH/f_wid);
51 }
52 else
53 draw_xstart=centerx-(x*AUTOTILE_WIDTH/f_wid-sx*AUTOTILE_WIDTH);
54
55 if (sy<0)
56 {
57 sy=0;
58 draw_ystart=centery-(y*AUTOTILE_HEIGHT/f_hi);
59 }
60 else
61 draw_ystart=centery-(y*AUTOTILE_HEIGHT/f_hi-sy*AUTOTILE_HEIGHT);
62
63 // if view position hasn't changed, only update the blinking dot and return
64 if (draw_xstart==old_dx && draw_ystart==old_dy)
65 {
66 automap_window->screen->Lock();
67 automap_window->screen->AddDirty(centerx,centery,centerx + 1,centery + 1);
68 if ((tick++)&4)
69 automap_window->screen->PutPixel(vec2i(centerx,centery),255);
70 else
71 automap_window->screen->PutPixel(vec2i(centerx,centery),27);
72 automap_window->screen->Unlock();
73 return ;
74 }
75
76 old_dx=draw_xstart;
77 old_dy=draw_ystart;
78
79
80 if (ex>=cur_lev->foreground_width())
81 ex=cur_lev->foreground_width()-1;
82 if (ey>=cur_lev->foreground_height())
83 ey=cur_lev->foreground_height()-1;
84
85
86 screen->bar(window_xstart,window_ystart,draw_xstart,window_yend,0);
87 screen->bar(window_xstart,window_ystart,window_xend,draw_ystart,0);
88
89
90 /* if (ex>=cur_lev->foreground_width())
91 {
92 draw_xend=center
93 ex=foreground_width()-1; */
94
95
96
97
98 // we are going to redraw the whole map, so make the dirty rect work easier by marking
99 // everything dirty
100 screen->AddDirty(window_xstart,window_ystart,window_xend+1,window_yend+1);
101
102
103
104
105 // draw the tiles that will be around the border of the automap with put_image
106 // because it handles clipping, but for ths reason is slower, the rest
107 // we will slam on as fast as possible
108
109 screen->SetClip(window_xstart,window_ystart,window_xend+1,window_yend+1);
110 /* for (i=draw_xstart,j=draw_ystart,x=sx,y=sy; y<=ey; j+=AUTOTILE_HEIGHT,y++)
111 foretiles[cur_lev->get_fg(x,y)]->micro_image->put_image(screen,i,j,0);
112
113 for (i=draw_xstart+ex*AUTOTILE_WIDTH,j=draw_ystart,y=sy,x=ex; y<=ey; j+=AUTOTILE_HEIGHT,y++)
114 foretiles[cur_lev->get_fg(x,y)]->micro_image->put_image(screen,i,j,0);
115
116 for (i=draw_xstart,j=draw_ystart,x=sx,y=sy; x<=ex; i+=AUTOTILE_WIDTH,x++)
117 foretiles[cur_lev->get_fg(x,y)]->micro_image->put_image(screen,i,j,0);
118
119 for (i=draw_xstart,j=draw_ystart+ey*AUTOTILE_HEIGHT,x=sx,y=ex; x<=ex; i+=AUTOTILE_WIDTH,x++)
120 foretiles[cur_lev->get_fg(x,y)]->micro_image->put_image(screen,i,j,0); */
121
122
123
124 unsigned short *fgline;
125 for (j=draw_ystart,y=sy; y<=ey; j+=AUTOTILE_HEIGHT,y++)
126 {
127 fgline=cur_lev->get_fgline(y)+sx;
128 for (i=draw_xstart,x=sx; x<=ex; i+=AUTOTILE_WIDTH,x++,fgline++)
129 {
130 if ((*fgline)&0x8000)
131 {
132 int id=foretiles[ (*fgline)&0x7fff];
133 if (id>=0)
134 cache.foret(id)->micro_image->put_image(screen,i,j,0);
135 else
136 cache.foret(foretiles[0])->micro_image->put_image(screen,i,j,0);
137 }
138 else
139 screen->bar(i,j,i+AUTOTILE_WIDTH-1,j+AUTOTILE_HEIGHT-1,0);
140 }
141 }
142
143 // draw the person as a dot, no need to add a dirty because we marked the
144 // whole screen already
145 automap_window->screen->Lock();
146 if ((tick++)&4)
147 automap_window->screen->PutPixel(vec2i(centerx,centery),255);
148 else
149 automap_window->screen->PutPixel(vec2i(centerx,centery),27);
150 automap_window->screen->Unlock();
151
152 // set the clip back to full window size because soemthing else could mess with the area
153 automap_window->screen->SetClip(0,0,screen->Size().x,screen->Size().y);
154 }
155
toggle_window()156 void automap::toggle_window()
157 {
158 if (automap_window)
159 {
160 wm->close_window(automap_window);
161 automap_window = NULL;
162 }
163 else
164 {
165 old_dx = -1000; // make sure the map gets drawn the first time
166 old_dy = -1000;
167
168 automap_window = wm->new_window(0, 0, w * AUTOTILE_WIDTH,
169 h * AUTOTILE_HEIGHT, NULL, "Map");
170 automap_window->screen->bar(17, 1, 17 + 8 * 6 + 3, 6,
171 wm->medium_color());
172 wm->font()->put_string(automap_window->screen, 20, 2, "Automap",
173 wm->dark_color());
174 draw();
175 }
176 }
177
178
automap(level * l,int width,int height)179 automap::automap(level *l, int width, int height)
180 {
181 w=width;
182 h=height;
183
184 tick=0;
185 cur_lev=l;
186 automap_window=NULL;
187 toggle_window();
188 }
189
handle_event(event & ev)190 void automap::handle_event(event &ev)
191 {
192
193 //only respond to stuff in our window or on the main screen
194 if (ev.window==NULL || ev.window==automap_window)
195 {
196 switch (ev.type)
197 {
198 case EV_KEY :
199 switch(ev.key)
200 {
201 case 'A' :
202 case 'a' :
203 toggle_window();
204 break;
205 }
206 break;
207 case EV_CLOSE_WINDOW :
208 wm->close_window(automap_window);
209 automap_window=NULL;
210 break;
211 }
212 }
213 }
214
215
216
217
218
219
220
221