Skip to content

Commit 04784f0

Browse files
Dmytro Lysaipingw33n
authored andcommitted
[object] Fix hit_test for outlined objects
For now hitting outline doesn't pass the hit_test. (Seems to be the original behavior too.)
1 parent 3f260d5 commit 04784f0

File tree

4 files changed

+43
-27
lines changed

4 files changed

+43
-27
lines changed

src/game/fidget.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ impl Fidget {
4949
if obj.flags.contains(Flag::TurnedOff) ||
5050
obj.fid.kind() != EntityKind::Critter ||
5151
obj.is_critter_dead() ||
52-
!world.object_bounds(objh).intersects(world.camera().viewport)
52+
!world.object_bounds(objh, true).intersects(world.camera().viewport)
5353
// FIXME
5454
// g_map_header.map_id == MAP_ID_WOODSMAN_ENCOUNTER && obj.pid == Some(Pid::ENCLAVE_PATROL)
5555
{

src/game/object.rs

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ impl Egg {
9494
return false;
9595
}
9696
let p = p - bounds.top_left();
97-
frm.mask.test(p)
97+
frm.mask.test(p).unwrap()
9898
}
9999
}
100100

@@ -235,9 +235,11 @@ impl Object {
235235
}
236236

237237
// obj_bound()
238-
pub fn bounds(&self, frm_db: &FrameDb, tile_grid: &impl TileGridView) -> Rect {
238+
pub fn bounds(&self, frm_db: &FrameDb, tile_grid: &impl TileGridView,
239+
include_outline: bool,
240+
) -> Rect {
239241
self.do_with_frame_list(frm_db, |frml, frm|
240-
self.bounds0(frml.center, frm.size(), tile_grid))
242+
self.bounds0(frml.center, frm.size(), tile_grid, include_outline))
241243
}
242244

243245
// critter_is_dead()
@@ -274,13 +276,15 @@ impl Object {
274276
return None;
275277
}
276278

277-
let bounds = self.bounds(frm_db, tile_grid);
279+
// TODO The test may return None for outlined objects.
280+
// Need to have mask for outlined object.
281+
let bounds = self.bounds(frm_db, tile_grid, false);
278282
if !bounds.contains(p) {
279283
return None;
280284
}
281285

282286
let p = p - bounds.top_left();
283-
if !self.do_with_frame(frm_db, |frm| frm.mask.test(p)) {
287+
if !self.do_with_frame(frm_db, |frm| frm.mask.test(p).unwrap()) {
284288
return None;
285289
}
286290

@@ -303,7 +307,9 @@ impl Object {
303307
Some(r)
304308
}
305309

306-
fn bounds0(&self, frame_center: Point, frame_size: Point, tile_grid: &impl TileGridView) -> Rect {
310+
fn bounds0(&self, frame_center: Point, frame_size: Point, tile_grid: &impl TileGridView,
311+
include_outline: bool,
312+
) -> Rect {
307313
let mut r = if let Some(pos) = self.pos {
308314
let top_left =
309315
tile_grid.center_to_screen(pos.point)
@@ -316,13 +322,15 @@ impl Object {
316322
Rect::with_points(self.screen_pos, self.screen_pos + frame_size)
317323
};
318324

319-
let has_outline = self.outline.map(|o| !o.disabled).unwrap_or(false);
320-
if has_outline {
321-
// Include 1-pixel outline.
322-
r.left -= 1;
323-
r.top -= 1;
324-
r.right += 1;
325-
r.bottom += 1;
325+
if include_outline {
326+
let has_outline = self.outline.map(|o| !o.disabled).unwrap_or(false);
327+
if has_outline {
328+
// Include 1-pixel outline.
329+
r.left -= 1;
330+
r.top -= 1;
331+
r.right += 1;
332+
r.bottom += 1;
333+
}
326334
}
327335

328336
r
@@ -1021,8 +1029,10 @@ impl Objects {
10211029
r
10221030
}
10231031

1024-
pub fn bounds(&self, obj: Handle, tile_grid: &impl TileGridView) -> Rect {
1025-
self.get(obj).bounds(&self.frm_db, tile_grid)
1032+
pub fn bounds(&self, obj: Handle, tile_grid: &impl TileGridView,
1033+
include_outline: bool,
1034+
) -> Rect {
1035+
self.get(obj).bounds(&self.frm_db, tile_grid, include_outline)
10261036
}
10271037

10281038
pub fn hit_test(&self, p: EPoint, screen_rect: Rect, tile_grid: &impl TileGridView,
@@ -1360,7 +1370,7 @@ mod test {
13601370

13611371
let mut obj = Object::new(FrameId::BLANK, None, Some((0, (55, 66)).into()), SubObject::None);
13621372
obj.screen_shift = screen_shift;
1363-
assert_eq!(obj.bounds0(Point::new(-1, 3), Point::new(29, 63), &View::default()),
1373+
assert_eq!(obj.bounds0(Point::new(-1, 3), Point::new(29, 63), &View::default(), true),
13641374
Rect::with_points(Point::new(1, -51), Point::new(30, 12))
13651375
.translate(base));
13661376
}

src/game/world.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -232,12 +232,12 @@ impl World {
232232
}
233233
}
234234

235-
pub fn object_bounds(&self, obj: object::Handle) -> Rect {
236-
self.objects.bounds(obj, &self.camera.hex())
235+
pub fn object_bounds(&self, obj: object::Handle, include_outline: bool) -> Rect {
236+
self.objects.bounds(obj, &self.camera.hex(), include_outline)
237237
}
238238

239239
pub fn is_object_in_camera(&self, obj: object::Handle) -> bool {
240-
let bounds = self.object_bounds(obj);
240+
let bounds = self.object_bounds(obj, true);
241241
self.camera.viewport.intersects(bounds)
242242
}
243243

src/graphics/sprite.rs

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -120,12 +120,15 @@ impl Mask {
120120
}
121121

122122
#[must_use]
123-
pub fn test(&self, point: Point) -> bool {
123+
pub fn test(&self, point: Point) -> Option<bool> {
124+
if point.x >= self.width {
125+
return None;
126+
}
124127
let Point { x, y } = point;
125128
let i = x + y * self.width;
129+
let b = self.bitmask.get(i as usize / 8)?;
126130
let bit = i % 8;
127-
let i = i as usize / 8;
128-
self.bitmask[i] & (1 << bit) != 0
131+
Some(b & (1 << bit) != 0)
129132
}
130133
}
131134

@@ -272,10 +275,13 @@ mod test {
272275
fn test() {
273276
let mask = Mask::new(3, &[0, 1, 0, 2, 0, 100]);
274277
assert_eq!(&*mask.bitmask, &[0b101010]);
275-
assert_eq!(mask.test((0, 0).into()), false);
276-
assert_eq!(mask.test((1, 0).into()), true);
277-
assert_eq!(mask.test((0, 1).into()), true);
278-
assert_eq!(mask.test((1, 1).into()), false);
278+
assert_eq!(mask.test((0, 0).into()), Some(false));
279+
assert_eq!(mask.test((1, 0).into()), Some(true));
280+
assert_eq!(mask.test((0, 1).into()), Some(true));
281+
assert_eq!(mask.test((1, 1).into()), Some(false));
282+
assert_eq!(mask.test((2, 1).into()), Some(true));
283+
assert_eq!(mask.test((3, 1).into()), None);
284+
assert_eq!(mask.test((2, 2).into()), None);
279285
}
280286
}
281287
}

0 commit comments

Comments
 (0)