Game Development Community

Trouble Getting Multiple Objects To Collide Properly

by David Taylor · in Torque Game Builder · 04/18/2006 (9:23 pm) · 5 replies

Okay, here's my problem. I've got several marbles being thrown, one at a time, into the screen. I want them to be able to collide with each other, but only when the spirtes are of a certain size. I have them growing and shrinking as they move to mimick being thrown.

1. I'm altering their collision layers in an attempt to make this happen. At the moment, however, they seem to collide regardless of the size of the newly thrown marble. Can anyone suggest to me a better way to go about this?

function throwMarble()
{
    echo("throwMarble() start");

    createMarbleSprite();

    moveMarbleUp();
    moveMarbleSideways();

    enlargeMarbleSize();

    echo("throwMarble() finish");
}

function createMarbleSprite()
{
    $marble = new t2dStaticSprite() {    scenegraph = t2dScene; };
    $marble.setPosition("0 30");
    $marble.setSize(1);
    $marble.setImageMap(spriteMarbleImageMap);

    // Set the marble collision info
    $marble.setGraphGroup(1);
    $marble.setLayer(1);
    $marble.setCollisionActive( true, true );
    $marble.setCollisionPolyCustom( 4, "-1 0 -0.1 -0.6 0.98 0.15 -0.1 0.7" );
    $marble.setCollisionMasks( BIT(2), BIT(2) );
    $marble.setCollisionCallback( true );
}

function enlargeMarbleSize()
{
//    echo("enlargeMarbleSize() start");

    %currentsize = $marble.getSize();

    if(%currentsize < 5)
    {
        $marble.setSize(%currentsize * 1.01);
        %currentsize = $marble.getSize();

        schedule(10, 0, enlargeMarbleSize);

    }
    else
    {
        $marble.setSize(5);
        reduceMarbleSize();
    }

//    echo("enlargeMarbleSize() finish");
}

function reduceMarbleSize()
{
//    echo("reduceMarbleSize() start");

    %currentsize = $marble.getSize();

    if(%currentsize > 1)
    {
        $marble.setSize(%currentsize / 1.01);
        %currentsize = $marble.getSize();

        schedule(10, 0, reduceMarbleSize);
    }
    else
    {
        $marble.setSize(1);
        stopMoveMarbleUp();
        stopMoveMarbleSideways();
        [b][i]// Change the marble's collision masks to allow it to collide with other marbles once it has landed
        $marble.setCollisionMasks( BIT(1), BIT(1) );[/i][/b]
    }

//    echo("reduceMarbleSize() finish");
}

function moveMarbleUp()
{
    %random = getRandom(5, 15);
    // Set the marble moving up.
    $marble.setLinearVelocityY(-%random);
}

function stopMoveMarbleUp()
{
    // Stop the marble moving up.
    $marble.setLinearVelocityY(0);
}

function moveMarbleSideways()
{
    %random = getRandom(-5, 5);
    // Set the marble moving sideways.
    $marble.setLinearVelocityX(%random);
}

function stopMoveMarbleSideways()
{
    // Stop the marble moving sideways.
    $marble.setLinearVelocityX(0);
}

2. The marbles are circular in appearance, but the sprite itself is a square, and the collisions are bouncingon angles reminiscent of squares. Is there any way to make the collisions circular in nature?

#1
04/18/2006 (11:42 pm)
For #1, If you don't want the marbles to collide until they 'reach' the game board, why not disable collisions on it entirely with setCollisionPolyActive(false, false) until you get to that point? If you still need it to collide off other objects as it falls into the game board, then you are on the right track, but you probably want to adjust the layer the object is on instead of (or in addition to, depending on the composition of the rest of the scene) changing the collision masks.

As for #2, you're setting a custom collision polygon in your marble creation function. You can either manually adjust that creation to have more than four sides, or for perfectly circular objects, just use the 'setCollisionPolyPrimitive()' function and pass in a fairly high count as the parameter, say 16, to approximate a circle, then use setCollisionScale() to adjust the size of this poly to match the sprite.
#2
04/19/2006 (5:31 am)
Thanks, Luke. (Again, lol.) The marbles are colliding only when the thrown marble is either on the ground or just about to land. :) (Although I'm not yet able to tell any difference when I change the collision scale... *shrugs*)

Here's my new code:
function throwMarble()
{
    echo("throwMarble() start");

    createMarbleSprite();

    moveMarbleUp();
    moveMarbleSideways();

    enlargeMarbleSize();

    echo("throwMarble() finish");
}

function createHandSprite()
{
    $hand = new t2dStaticSprite() {    scenegraph = t2dScene; };
    $hand.setPosition("0 30");
    $hand.setSize(10);
    $hand.setImageMap(spriteHandImageMap);
}

function createMarbleSprite()
{
    $marble = new t2dStaticSprite() {    scenegraph = t2dScene; };
    $marble.setPosition($hand.getPosition());
    $marble.setSize(1);
    $marble.setImageMap(spriteMarbleImageMap);

    // Set the marble collision info
    $marble.setGraphGroup(1);
    $marble.setLayer(1);
    $marble.setCollisionActive( false, false );
    $marble.setCollisionPolyPrimitive( 64 );
    $marble.setCollisionScale(10);
    $marble.setCollisionMasks( BIT(1), BIT(1) );
    $marble.setCollisionCallback( true );
}

function enlargeMarbleSize()
{
//    echo("enlargeMarbleSize() start");

    %currentsize = $marble.getSize();

    if(%currentsize < 5)
    {
        $marble.setSize(%currentsize * 1.01);
        %currentsize = $marble.getSize();

        schedule(10, 0, enlargeMarbleSize);
    }
    else
    {
        $marble.setSize(5);
        reduceMarbleSize();
    }

//    echo("enlargeMarbleSize() finish");
}

function reduceMarbleSize()
{
//    echo("reduceMarbleSize() start");

    %currentsize = $marble.getSize();

    if(%currentsize > 1)
    {
        $marble.setSize(%currentsize / 1.01);
        %currentsize = $marble.getSize();

        schedule(10, 0, reduceMarbleSize);

        if(%currentsize < 2)
        {
            $marble.setCollisionActive( true, true ); 
        }
    }
    else
    {
        $marble.setSize(1);
        stopMoveMarbleUp();
        stopMoveMarbleSideways();
    }

//    echo("reduceMarbleSize() finish");
}

function moveMarbleUp()
{
    %random = getRandom(5, 15);
    // Set the marble moving up.
    $marble.setLinearVelocityY(-%random);
}

function stopMoveMarbleUp()
{
    // Stop the marble moving up.
    $marble.setLinearVelocityY(0);
}

function moveMarbleSideways()
{
    %random = getRandom(-5, 5);
    // Set the marble moving sideways.
    $marble.setLinearVelocityX(%random);
}

function stopMoveMarbleSideways()
{
    // Stop the marble moving sideways.
    $marble.setLinearVelocityX(0);
}

My problem now is that nine times out of ten, if there is a collision, it is only the thrown marble that moves. The other one, (the one that is already on the ground), just sits there and doesn't react at all. How can I get it to respond? I thought of putting in the OnCollision function something where the grounded marble checked for what part of the sprite was hit and somehow chose which direction for it to move in, etc, but I have no idea as to where I would start with that, and I'm hoping there's a simpler way by making a call with the TGB engine.
#3
04/19/2006 (5:39 am)
Not sure if this would do anything, but you might need to set the responce mode of your marbles to something other than the default.
For example, you might need to set your marbles to bounce or similar.

Another suggestion is that, when you hit your stationary marble, you apply a force or impulse to the marble, to get it to move, and apply it from where the colliding marble just hit it.

Hope that helps,
Tom.
#4
04/19/2006 (11:56 am)
Thanks Tom. How would I go about that? (Both suggestions.) My code is based off the basic tutorial, so I'm still trying to work out how a lot of this works. Where have I declared the response mode to be the default method, and how do I change it to make it bounce?
#5
04/19/2006 (12:03 pm)
obj.setCollisionResponse(Your new response.);
I think that is what you need for the first part, where 'your new response' is bounce.

As for the second, I'm not sure to be honest. It would need some researching.
You can apply a force/impluse/velocity with
obj.setLinearVelocity("0 0");
Where "0 0" is your X Y Linear velocity. :)

Hope that helps,
Tom.