Tux can peek to the left and to the right as far as the camera would move in best...
[supertux.git] / src / collision_grid_iterator.hpp
1 //  $Id$
2 //
3 //  SuperTux
4 //  Copyright (C) 2006 Matthias Braun <matze@braunis.de>
5 //
6 //  This program is free software; you can redistribute it and/or
7 //  modify it under the terms of the GNU General Public License
8 //  as published by the Free Software Foundation; either version 2
9 //  of the License, or (at your option) any later version.
10 //
11 //  This program is distributed in the hope that it will be useful,
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 //  GNU General Public License for more details.
15 //
16 //  You should have received a copy of the GNU General Public License
17 //  along with this program; if not, write to the Free Software
18 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19 //  02111-1307, USA.
20 #ifndef __COLLISION_GRID_ITERATOR_H__
21 #define __COLLISION_GRID_ITERATOR_H__
22
23 #include "math/rect.hpp"
24 #include "log.hpp"
25
26 class CollisionGrid;
27
28 class CollisionGridIterator
29 {
30 public:
31   CollisionGridIterator(CollisionGrid& newgrid, const Rect& bbox)
32     : grid(newgrid)
33   {
34     start_x = int(bbox.p1.x / grid.cell_width) - 2;
35     if(start_x < 0)
36       start_x = 0;
37     x = start_x;
38         
39     y = int(bbox.p1.y / grid.cell_height) - 2;
40     if(y < 0)
41       y = 0;
42     
43     end_x = int(bbox.p2.x / grid.cell_width) + 2;
44     if(end_x > (int) grid.cells_x)
45       end_x = grid.cells_x;
46     
47     end_y = int(bbox.p2.y / grid.cell_height) + 2;
48     if(end_y > (int) grid.cells_y)
49       end_y = grid.cells_y;
50     
51     timestamp = grid.iterator_timestamp++;
52     entry = 0;
53
54     if(start_x >= end_x) {
55       log_debug << "bad region" << std::endl;
56       y = 0;
57       end_y = 0;
58       return;
59     }
60   }
61
62   MovingObject* next()
63   {
64     CollisionGrid::ObjectWrapper* wrapper = next_wrapper();
65     if(wrapper == 0)
66       return 0;
67         
68     return wrapper->object;
69   }
70
71 private:
72   friend class CollisionGrid;
73
74   CollisionGrid::ObjectWrapper* next_wrapper() 
75   {
76     CollisionGrid::ObjectWrapper* wrapper;
77     
78     do {
79       while(entry == 0) {
80         if(y >= end_y)
81           return 0;
82         
83         entry = grid.grid[y*grid.cells_x + x];
84         x++;
85         if(x >= end_x) {
86           x = start_x;
87           y++;
88         }
89       }
90       
91       wrapper = entry->object_wrapper;
92       entry = entry->next;
93     } while(wrapper->timestamp == timestamp);
94     
95     wrapper->timestamp = timestamp;
96     
97     return wrapper;
98   }
99     
100   CollisionGrid& grid;
101   CollisionGrid::GridEntry* entry;
102   int x, y;
103   int start_x, end_x, end_y;
104   int timestamp;
105 };
106
107 #endif
108