Name: Anonymous 2013-09-13 22:49
Translated this over from Ruby to Racket. It's a class for storing hitboxes in 2d games and providing methods for checking for collision detection (for both moving and still boxes). Let me know if there's a way to shorten this in some areas so it's not so freakishly long...
#lang racket
(define Box
(class object%
(init-field x)
(init-field y)
(init-field width)
(init-field height)
;; 2D Collision detection between boxes is defined
;; as whether or not they overlap on both the
;; X-Axis and Y-Axis
(define/public (collides-with? other)
(and (overlap? other 'x)
(overlap? other 'y)))
;; Private method to determine whether or not
;; two boxes will overlap on a particular axis
(define (overlap? other axis)
(let ((arg-list
(map (lambda (p)
(cond ((equal? axis 'x) (car p))
((equal? axis 'y) (cdr p))))
(list (cons x y)
(cons width height)
(cons (get-field x other) (get-field y other))
(cons (get-field width other) (get-field height other))))))
(apply (lambda (ap ad bp bd)
(or (and (>= (+ ap ad) bp)
(>= bp ap))
(and (>= (+ bp bd) ap)
(>= ap bp)))) arg-list)))
;; Determines whether this box will be hit by another box
;; moving with given velocity vectors vx and vy
(define/public (in-path-of? other vx vy)
(let (
(other-x (get-field x other))
(other-y (get-field y other))
(other-width (get-field width other))
(other-height (get-field height other)))
(cond
;; Collision detection with boxes moving in one direction
((zero? vx)
(collides-with? (new Box
(x other-x) (y other-y)
(width other-width) (height (+ other-height vy)))))
((zero? vy)
(collides-with? (new Box
(x other-x) (y other-y)
(width (+ other-width vx)) (height other-height))))
;; Collision detection at beginning or end of box's trajectory
((collides-with? other) #t)
((collides-with? (new Box
(x (+ other-x vx)) (y (+ other-y vy))
(width other-width) (height other-height))) #t)
;; Collision detection with boxes in path
(else
(let (
;; Distances to enter and exit a collision on an axis
;; En = distance between closest points, Ex = between farthest
(xInvEn (if (> vx 0)
(- x (+ other-x other-width))
(- (+ x width) other-x)))
(xInvEx (if (> vx 0)
(- (+ x width) other-x)
(- x (+ other-x other-width))))
(yInvEn (if (> vy 0)
(- y (+ other-y other-height))
(- (+ y height) other-y)))
(yInvEx (if (> vy 0)
(- (+ y height) other-y)
(- y (+ other-y other-height)))))
(let (
;; Collision times relative to entry and exit
;; 0 = collision at start of movement,
;; 1 = collision at end, 0.5 = halfway, etc...
(xEntry (/ xInvEn vx)) (xExit (/ xInvEx vx))
(yEntry (/ yInvEn vy)) (yExit (/ yInvEx vy)))
(let (
(entryTime (max xEntry yEntry))
(exitTime (min xExit yExit)))
(not (or
(> entryTime exitTime)
(and (< xEntry 0.0) (< yEntry 0.0))
(> xEntry 1.0)
(> yEntry 1.0))))))))))
(super-new)))