Adonthell  0.4
mapsquare.cc
Go to the documentation of this file.
1 /*
2  $Id: mapsquare.cc,v 1.8 2001/08/29 07:40:33 gnurou Exp $
3 
4  Copyright (C) 2001 Alexandre Courbot
5  Part of the Adonthell Project http://adonthell.linuxgames.com
6 
7  This program is free software; you can redistribute it and/or modify
8  it under the terms of the GNU General Public License.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
15 
16 /**
17  * @file mapsquare.cc
18  * @author Alexandre Courbot <alexandrecourbot@linuxgames.com>
19  *
20  * @brief Defines the mapsquare and mapsquare_area classes.
21  *
22  *
23  */
24 
25 
26 #include "mapsquare.h"
27 #include "mapobject.h"
28 #include "mapcharacter.h"
29 
31 {
32  mapobj = NULL;
33  is_base = false;
34 }
35 
37 {
38 }
39 
41 {
42  mchar = NULL;
43  is_base = false;
44 }
45 
47 {
48 }
49 
51 {
52  base_begin = tiles.end ();
54 }
55 
57 {
58  tiles = src.tiles;
59  mapchars = src.mapchars;
60 
61  // Correctly place the base tile square's base tile pointer.
62  list <mapsquare_tile>::iterator it;
63  for (it = tiles.begin ();
64  it != tiles.end () && *(it->base_tile) < *it; it++);
65  base_begin = it;
67 }
68 
70 {
71 }
72 
74 {
75  list <mapsquare_char>::iterator i;
76  for (i = mapchars.begin (); i != mapchars.end (); i++)
77  if (i->is_base)
78  return false;
79  return true;
80 }
81 
83 {
84  list <mapsquare_char>::iterator i;
85  for (i = mapchars.begin (); i != mapchars.end (); i++)
86  if (i->is_base)
87  return i->mchar;
88  return NULL;
89 }
90 
92 {
93 }
94 
96 {
97 }
98 
100 {
101  area.clear ();
102 }
103 
104 s_int8 mapsquare_area::put_mapobject (u_int16 px, u_int16 py, mapobject * mobj)
105 {
106  u_int16 i, j;
107  mapsquare_tile t;
108  list <mapsquare_tile>::iterator it;
109 
110  // Calculating where the object will start and end on the map.
111  u_int16 i0 = px - mobj->base_x () < 0 ? 0 : px - mobj->base_x ();
112  u_int16 j0 = py - mobj->base_y () < 0 ? 0 : py - mobj->base_y ();
113 
114  u_int16 ie = px + (mobj->area_length ()) - mobj->base_x () > area_length () ?
115  area_length () : px + (mobj->area_length ()) - mobj->base_x ();
116  u_int16 je = py + (mobj->area_height ()) - mobj->base_y () > area_height () ?
117  area_height () : py + (mobj->area_height ()) - mobj->base_y ();
118 
119  // Offset between square's position on the map and on the object.
120  s_int16 xoff = mobj->base_x () - px;
121  s_int16 yoff = mobj->base_y () - py;
122 
123 
124  // First place the base tile, as others refers to it...
125  t.mapobj = mobj;
126  t.is_base = true;
127  t.x = px;
128  t.y = py;
129 
130  // The iterator will be inserted AFTER all the others base tiles.
131  // Doing so, this object will be drawn last on this square.
132  for (it = area[px][py].tiles.begin ();
133  it != area[px][py].tiles.end () && *(it->base_tile) <= t; it++);
134  area[px][py].tiles.insert (it, t);
135  it--;
136  it->base_tile = it;
137 
138  // Update t so it refers to the base tile
139  t.base_tile = it;
140  t.is_base = false;
141 
142  // Now place the others tiles.
143  for (j = j0; j < je; j++)
144  for (i = i0; i < ie; i++)
145  {
146  mapsquare & s = area[i][j];
147  t.x = i;
148  t.y = j;
149  s.set_walkable (s.get_walkable () &
150  mobj->get_square (i + xoff, j + yoff)->get_walkable ());
151 
152  if (i != px || j != py)
153  {
154  for (it = s.tiles.begin ();
155  it != s.tiles.end () &&
156  *(it->base_tile) <= *(t.base_tile); it++);
157  s.tiles.insert (it, t);
158  }
159  }
160 
161  // Correctly place the base tile square's base tile pointer.
162  for (it = area[px][py].tiles.begin ();
163  it != area[px][py].tiles.end () && *(it->base_tile) < *it; it++);
164  area[px][py].base_begin = it;
165 
166  return 0;
167 }
168 
169 void mapsquare_area::remove_mapobject (u_int16 px, u_int16 py, mapobject * mobj)
170 {
171  u_int16 i, j;
172  list <mapsquare_tile>::iterator it;
173 
174  // Calculating where the object will start and end on the map.
175  u_int16 i0 = px - mobj->base_x () < 0 ? 0 : px - mobj->base_x ();
176  u_int16 j0 = py - mobj->base_y () < 0 ? 0 : py - mobj->base_y ();
177 
178  u_int16 ie = px + (mobj->area_length ()) - mobj->base_x () > area_length () ?
179  area_length () : px + (mobj->area_length ()) - mobj->base_x ();
180  u_int16 je = py + (mobj->area_height ()) - mobj->base_y () > area_height () ?
181  area_height () : py + (mobj->area_height ()) - mobj->base_y ();
182 
183  // Find the base tile, get it's reference (to remove others).
184  for (it = area[px][py].tiles.begin (); it != area[px][py].tiles.end () &&
185  !(it->is_base == true && it->mapobj == mobj); it++);
186 
187  // Base tile not found - better to return now...
188  if (it == area[px][py].tiles.end ()) return;
189 
190  // Keep the iterator available for further comparison
191  list <mapsquare_tile>::iterator the_base = it;
192 
193  // And now erase all the others tiles of this object.
194  for (j = j0; j < je; j++)
195  for (i = i0; i < ie; i++)
196  {
197  if (i != px || j != py)
198  {
199  mapsquare & s = area[i][j];
200 
201  for (it = s.tiles.begin (); it != s.tiles.end () && it->base_tile != the_base; it++);
202 
203  // Not found?? Weird - let's not mess with it then!
204  if (it == s.tiles.end ()) continue;
205 
206  s.tiles.erase (it);
207 
208  // Recalculate the walkability of this square.
210  for (it = s.tiles.begin (); it != s.tiles.end (); it++)
211  {
212  u_int16 wx = it->x - (it->base_tile->x - it->mapobj->base_x ());
213  u_int16 wy = it->y - (it->base_tile->y - it->mapobj->base_y ());
214  s.set_walkable (s.get_walkable () &
215  it->mapobj->get_square (wx, wy)->get_walkable ());
216  }
217  }
218  }
219  mapsquare & s = area[px][py];
220  // Erase the base tile
221  s.tiles.erase (the_base);
222  // Recalculate the walkability of this square.
224  for (it = s.tiles.begin (); it != s.tiles.end (); it++)
225  {
226  u_int16 wx = it->x - (it->base_tile->x - it->mapobj->base_x ());
227  u_int16 wy = it->y - (it->base_tile->y - it->mapobj->base_y ());
228  s.set_walkable (s.get_walkable () &
229  it->mapobj->get_square (wx, wy)->get_walkable ());
230  }
231 }
232 
234 {
235  vector <vector<mapsquare> >::iterator i;
236 
237  area.resize (nl);
238  for (i = area.begin (); i != area.end (); i++)
239  i->resize (nh);
240 
241  u_int16 j, k;
242  for (j = 0; j < nl; j++)
243  for (k = 0; k < nh; k++)
244  {
245  area[j][k].x_ = j;
246  area[j][k].y_ = k;
247  }
248 }