01 March, 2015 edit: I recently re-did this code to be less redundant and generally much cleaner. The snippet has been updated. Also, made some tweaks:
- The pixel collider's proxy supports lists as well now.
- The pixel collider no longer executes the default movable behavior for Cross()/Uncross() respectively.
// defines we need
#define COLLIDE_AREAS 1
#define COLLIDE_TURFS 2
#define COLLIDE_OBJS 4
#define COLLIDE_MOBS 8
#define COLLIDE_ALL 15
#define ispixelcollider(c) istype(c, /pixel_collider)
#ifndef islist
#define islist(l) istype(l, /list)
#endif
// pixel collider
var/pixel_collider/pixel_collider = new
pixel_collider
parent_type = /atom/movable
density = 0
bounds = 0
var/tmp/proxy // can be a reference to an atom or a list of atoms.
var/tmp/collision_mask = COLLIDE_ALL
var/tmp/list/collisions
proc/is_proxy(atom/collided)
if(islist(proxy))
if(collided in proxy)
return 1
else
if(collided == proxy)
return 1
proc/collide(atom/collided)
if(!is_proxy(collided))
if(collision_mask & collided.collision_layer)
if(!collisions)
collisions = list()
collisions += src
return 1
proc/unload()
bounds = 0
step_x = 0
step_y = 0
collision_mask = COLLIDE_ALL
proxy = null
if(collisions)
collisions = null
loc = null
proc/can_move_to(atom/movable/ref, turf/loc, mask, proxy)
if(!ref || !loc) return
var/pixel_collider/p = pixel_collider
p.step_x = ref.step_x
p.step_y = ref.step_y
p.bounds = ref.bounds
if(mask) p.collision_mask = mask
p.proxy = proxy || ref
p.loc = ref.loc
. = p.Move(loc)
p.unload()
proc/can_step(atom/movable/ref, dir, speed, mask, proxy)
if(!ref) return
var/pixel_collider/p = pixel_collider
p.step_x = ref.step_x
p.step_y = ref.step_y
p.bounds = ref.bounds
if(mask) p.collision_mask = mask
p.proxy = proxy || ref
p.loc = ref.loc
. = step(p, dir, speed || ref.step_size)
p.unload()
proc/can_set_loc(turf/loc, step_x, step_y, atom/movable/ref, mask, proxy)
if(!ref) return
var/pixel_collider/p = pixel_collider
p.step_x = step_x
p.step_y = step_y
p.bounds = ref.bounds
if(mask) p.collision_mask = mask
p.proxy = proxy || ref
. = p.Move(loc, 0, step_x, step_y)
p.unload()
proc/get_collisions(atom/movable/ref, turf/loc, width, height, mask, proxy)
if(!ref || !loc)
return
var/pixel_collider/p = pixel_collider
p.proxy = proxy || ref
p.bound_width = width
p.bound_height = height
p.step_x = ref.step_x
p.step_y = ref.step_y
if(mask) p.collision_mask = mask
p.Move(loc)
. = p.collisions
p.unload()
// collision handling
atom
var/tmp/collision_layer = 0
area
collision_layer = COLLIDE_AREAS
turf
collision_layer = COLLIDE_TURFS
obj
collision_layer = COLLIDE_OBJS
mob
collision_layer = COLLIDE_MOBS
// handle collisions with turfs.
atom
Enter(pixel_collider/pixel_collider)
if(!istype(pixel_collider) || !density)
return ..()
if(pixel_collider.collide(src))
return 0
return 1
Exit(pixel_collider/pixel_collider)
if(!istype(pixel_collider) || !density)
return ..()
if(pixel_collider.collide(src))
return 0
return 1
// handle collisions with movable objects.
atom/movable
Cross(pixel_collider/pixel_collider)
if(!istype(pixel_collider) || !density)
return ..()
if(pixel_collider.collide(src))
return 0
return 1
Uncross(pixel_collider/pixel_collider)
if(!istype(pixel_collider) || !density)
return ..()
if(pixel_collider.collide(src))
return 0
return 1