Search code examples
rubylibgosu

Unusual behavior of collision detection using Chingu


I'm trying various ways of colliding the player with an item:

Coin.each_bounding_circle_collision(@player) do |coin, player|
    puts "coin collides with player"
end

Item.each_bounding_circle_collision(@player) do |item, player|
    puts "item collides with player"
end

@player.each_bounding_circle_collision(Item) do |player, item|
    puts "player collides with item"
end

@player.each_bounding_circle_collision(Coin) do |player, coin|
    puts "player collides with coin"
end

Of these, only the first and the last one works (i.e. the ones where I check against Coin), despite Item being the parent class of Coin:

class Item < Chingu::GameObject
    trait :timer
    trait :velocity
    trait :collision_detection
    trait :bounding_circle, :scale => 0.8

    attr_reader :score

    def initialize(options = {})
        super(options)

        self.zorder = Z::Item
    end
end

class Coin < Item
    def setup
        @animation = Chingu::Animation.new(:file => "media/coin.png", :delay => 100, :size => [14, 18])
        @image = @animation.first

        cache_bounding_circle
    end

    def update
        @image = @animation.next
    end
end

Due to my lowly knowledge of Ruby in general, I'm failing to see why this isn't working, maybe I'm missing something obvious. Any help would be greatly appreciated.

(Due to low reputation I can't tag this with 'chingu', so it's going under the next closest thing, 'libgosu')

Thanks.

(Source: Rubyroids)


Solution

  • Unfortunately, Chingu only keeps a record of all GameObject instances and GameObject instances by class, not by inheritance. What Chingu does here is checks collisions against Item.all, which is an array of purely Item instances, not its subclasses. The way to check all Item instances is:

    @player.each_bounding_circle_collision(game_objects.of_class(Item)) do |player, item|
        puts "player collides with item"
    end
    

    Be aware, however, that that is quite slow, because game_objects#of_class goes through ALL game objects, picking out the ones that are kind_of? the class you want (same as Array#grep in newer Ruby version really, but presumably slower). You might want to record the list of Item instances every so often, not every time you want to check collisions, depending on how many objects you have in your game.