6 static SlopeTable slopetable
[SLOPE_LAST
+1];
8 // creates the slope tables
9 bool initslopetable(void)
12 int curtable
, opposing_table
;
13 int inverttable
, invertfliptable
;
16 stat("initslopetable: generating slopetables.");
17 memset(slopetable
, 0, sizeof(slopetable
));
20 for(x
=0;x
<TILE_W
*2;x
++)
25 curtable
= SLOPE_FWD1
;
26 opposing_table
= SLOPE_BACK2
;
27 inverttable
= SLOPE_CEIL_BACK1
;
28 invertfliptable
= SLOPE_CEIL_FWD2
;
33 curtable
= SLOPE_FWD2
;
34 opposing_table
= SLOPE_BACK1
;
35 inverttable
= SLOPE_CEIL_BACK2
;
36 invertfliptable
= SLOPE_CEIL_FWD1
;
39 for(y
=ya
;y
<TILE_H
;y
++)
44 slopetable
[curtable
].table
[mx
][y
] = 1;
45 slopetable
[opposing_table
].table
[flipmx
][y
] = 1;
46 slopetable
[inverttable
].table
[mx
][flipy
] = 1;
47 slopetable
[invertfliptable
].table
[flipmx
][flipy
] = 1;
57 void c------------------------------() {}
60 // X and Y are non-CSFd pixel coordinates relative to the upper-left of the map.
61 // if the given pixel is inside of a slope, returns the slope type 1-8. else, returns 0.
62 uint8_t ReadSlopeTable(int x
, int y
)
69 DrawSlopeTablesOnTiles();
72 // convert coordinates into a tile and check if the tile is a slope tile
76 if (mx
< 0 || my
< 0 || mx
>= map
.xsize
|| my
>= map
.ysize
)
79 t
= map
.tiles
[mx
][my
];
81 if (tileattr
[t
] & TA_SLOPE
)
83 slopetype
= (tilecode
[t
] & 0x07) + 1; // extract slope type from tile code
85 // get offset from the tile
86 x
%= TILE_W
; y
%= TILE_H
;
88 if (slopetable
[slopetype
].table
[x
][y
])
95 // returns true if any of the points in the given point list
96 // are on the solid portion of a slope tile.
97 bool IsSlopeAtPointList(Object
*o
, SIFPointList
*points
)
101 for(i
=0;i
<points
->count
;i
++)
103 x
= (o
->x
>> CSF
) + points
->point
[i
].x
;
104 y
= (o
->y
>> CSF
) + points
->point
[i
].y
;
105 if (ReadSlopeTable(x
, y
)) return 1;
112 void c------------------------------() {}
115 // returns nonzero (the slope type) if the object is standing on a slope.
116 int CheckStandOnSlope(Object
*o
)
120 y
= (o
->y
>> CSF
) + sprites
[o
->sprite
].slopebox
.y2
+ 1;
123 if ((st
= ReadSlopeTable(x
+ sprites
[o
->sprite
].slopebox
.x1
, y
))) return st
;
124 if ((st
= ReadSlopeTable(x
+ sprites
[o
->sprite
].slopebox
.x2
, y
))) return st
;
129 // returns nonzero (the slope type) if the objects blocku should be set
130 // because of a ceiling slope.
131 int CheckBoppedHeadOnSlope(Object
*o
)
135 y
= (o
->y
>> CSF
) + sprites
[o
->sprite
].slopebox
.y1
- 1;
138 // without this, you get stuck in the save area below Gum Door in Grasstown
139 //if (o == player) y += 4;
141 if ((st
= ReadSlopeTable(x
+ sprites
[o
->sprite
].slopebox
.x1
, y
))) return st
;
142 if ((st
= ReadSlopeTable(x
+ sprites
[o
->sprite
].slopebox
.x2
, y
))) return st
;
148 // move an object laterally, and have it climb slopes as it approaches them.
149 // We also have to move the object down as it goes down the slope.
150 // Otherwise, it would "skip" down the slope ungracefully.
151 // returns 1 if the object was blocked by a wall.
152 bool movehandleslope(Object
*o
, int xinertia
)
154 int xoff
, opposing_x
;
155 int newx
, newy
, oldy
;
158 if (!xinertia
) return 0;
160 // for objects which don't follow slope, just treat the slope as a blockl/r
161 if (!(o
->nxflags
& NXFLAG_FOLLOW_SLOPE
))
165 if (o
->blockr
) return 1;
169 if (o
->blockl
) return 1;
179 // determine which side of the bounding box to use based on which way
182 { // moving right (right side of slopebox hits slopes first)
183 opposing_x
= sprites
[o
->sprite
].slopebox
.x1
;
184 xoff
= sprites
[o
->sprite
].slopebox
.x2
;
187 { // move left (left side of slopebox hits slopes first)
188 opposing_x
= sprites
[o
->sprite
].slopebox
.x2
;
189 xoff
= sprites
[o
->sprite
].slopebox
.x1
;
192 // check the opposing side at y+1 to see if we were standing on a slope before the move.
193 uint8_t old_floor_slope
, old_ceil_slope
;
194 old_floor_slope
= ReadSlopeTable((newx
>>CSF
) + opposing_x
, \
195 (newy
>>CSF
) + sprites
[o
->sprite
].slopebox
.y2
+ 1);
197 old_ceil_slope
= ReadSlopeTable((newx
>>CSF
) + opposing_x
, \
198 (newy
>>CSF
) + sprites
[o
->sprite
].slopebox
.y1
- 1);
203 // check the opposing side again and if now we're not standing any more,
204 // we moved down the slope, so add +1 to the object's Y coordinate.
205 if (old_floor_slope
&& !ReadSlopeTable((newx
>>CSF
) + opposing_x
, \
206 (newy
>>CSF
) + sprites
[o
->sprite
].slopebox
.y2
+ 1))
208 bool walking_down
= false;
210 // only trigger if it's the correct slope type so that we would be walking down it if
211 // we were going in the direction we're going. prevents being shoved down 1px when
212 // exiting the top of a slope.
215 if (old_floor_slope
== SLOPE_FWD1
|| \
216 old_floor_slope
== SLOPE_FWD2
)
221 else if (xinertia
> 0)
223 if (old_floor_slope
== SLOPE_BACK1
|| \
224 old_floor_slope
== SLOPE_BACK2
)
236 // the same for ceiling slopes
237 if (old_ceil_slope
&& !ReadSlopeTable((newx
>>CSF
) + opposing_x
, \
238 (newy
>>CSF
) + sprites
[o
->sprite
].slopebox
.y1
- 1))
244 if (old_ceil_slope
== SLOPE_CEIL_BACK1
|| \
245 old_ceil_slope
== SLOPE_CEIL_BACK2
)
250 else if (xinertia
> 0)
252 if (old_ceil_slope
== SLOPE_CEIL_FWD1
|| \
253 old_ceil_slope
== SLOPE_CEIL_FWD2
)
260 { // moving down (actually up) the "descending" (closer to real ceil) portion
261 // of a ceiling slope tile. Reverse of floor slope thingy above.
266 // check the coordinate and see if it's inside a slope tile.
267 // if so, move the object up 1 Y pixel.
268 uint8_t moved_into_ceil_slope
= ReadSlopeTable((newx
>>CSF
) + xoff
, \
269 (newy
>>CSF
) + sprites
[o
->sprite
].slopebox
.y1
);
270 if (moved_into_ceil_slope
)
275 uint8_t moved_into_floor_slope
= ReadSlopeTable((newx
>>CSF
) + xoff
, \
276 (newy
>>CSF
) + sprites
[o
->sprite
].slopebox
.y2
);
277 if (moved_into_floor_slope
)
282 // can't move if blocked by a wall. but if we've moved up or down 1px, be sure and update
283 // the blockr/l state before declaring we can't move--otherwise we can get stuck at the
284 // top of a slope with the bottom blockr/l stuck at the top px of the adjacent solid tile.
291 o
->UpdateBlockStates(RIGHTMASK
);
293 blocked_wall
= o
->blockr
;
298 o
->UpdateBlockStates(LEFTMASK
);
300 blocked_wall
= o
->blockl
;
304 { // we can't actually move...so reset Y position
308 { // can move...complete the move by setting the X position too
317 void c------------------------------() {}
323 void DrawSlopeTablesOnTiles()
325 static int lastmap
= -1;
327 if (game
.curmap
!= lastmap
)
329 lastmap
= game
.curmap
;
330 for(int i
=0;i
<256;i
++)
332 if (tileattr
[i
] & TA_SLOPE
)
334 DrawSlopeTableOnTile((tilecode
[i
]&7)+1, i
);
340 void DrawSlopeTableOnTile(int table
, int tile
)
344 extern SDL_Surface
*tileset
;
346 for(y
=0;y
<TILE_H
;y
++)
348 for(x
=0;x
<TILE_W
;x
++)
350 dstrect
.x
= (tile
& 15) << 5;
351 dstrect
.y
= (tile
>> 4) << 5;
358 if (slopetable
[table
].table
[x
][y
])
360 if (table
> 4) // floor slopes
361 SDL_FillRect(tileset
, &dstrect
, SDL_MapRGB(tileset
->format
, 0, 255, 0));
363 SDL_FillRect(tileset
, &dstrect
, SDL_MapRGB(tileset
->format
, 255, 0, 0));
369 void dumpslopetable(int t
)
374 stat("\nDumping slope table %d:", t
);
375 for(y
=0;y
<TILE_H
;y
++)
377 for(x
=0;x
<TILE_W
;x
++)
379 buffer
[x
] = slopetable
[t
].table
[x
][y
] + '0';