Archived

This topic is now archived and is closed to further replies.

endasil

Circle collision and new direction

Recommended Posts

I''m making a simple game with two circular boats that can move around on the screen and collide with eachother. The boats can move in a chosen angle, and the game can detect if the boats collide. The problem i need help with is that when two boats collide, they should instead of just stopping, "bounce" in the right direction depending on in what direction they collide, speed and such. But i can not figure out how to do this. Please help me. The variables i use for the boats right now are speed[BoatNr] How fast the boat moves in the current direction angle[BoatNr] What direction the boat moves in x[BoatNr] x position of the boat y[BoatNr] y position of the boat radius[BoatNr] radius of the circle for collision detection.

Share this post


Link to post
Share on other sites
you'll be better off with simple vector maths.


Vector Vel0(cos(Boat0.angle) * Boat0.speed, sin(Boat0.angle) * Boat0.speed);

Vector Vel1(cos(Boat1.angle) * Boat1.speed, sin(Boat1.angle) * Boat1.speed);

Vector Pos0(Boat0.x, Boat0.y);
Vector Pos1(Boat1.x, Boat1.y);

float r0 = Boat0.radius;
float r1 = Boat1.radius;
float r = r0 + r1;

Vector D(Pos1 - Pos0);
Vector V(Vel1 - Vel0);

float DdotV = D.Dot(V);

//------------------------------

// collision test

//------------------------------

if (DdotV > 0.0f) // if boats not moving towards each other, no collision/impulse

return false;

float DdotD = D.Dot(D); // relative distance,squared


if (DdotD > r*r) // boat didn't collide

return false;

float dlength = sqrt(DdotD);

//------------------------------

// collision parameters

//------------------------------

Vector Normal = D / dlength; // normal of collision

float depth = r - dlength; // depth of collision


//------------------------------

// separate the boats a bit because they are overlapping

//------------------------------

float sep_damping = 0.25f;
Pos0 -= Normal * depth * sep_damping;
Pos1 += Normal * depth * sep_damping;

//------------------------------

// collision impulse

//------------------------------

float elasticity = 0.05f; // very squishy collision

float friction = 0.05f; // very little friction


//------------------------------

// collision impact stuff

//------------------------------

// first boat

float V0dotN = Vel0.Dot(Normal);

Vector V0n = V0dotN * Normal; // velocity along normal of collision

Vector V0t = Vel0 - V0n; // velocity along plane of collision

Vel0 = -(elasticity) * V0n + (1.0f - friction) * V0t; // new velocity, after friction and bounce


// second boat

float V1dotN = Vel1.Dot(Normal);

Vector V1n = V1dotN * Normal; // velocity along normal of collision

Vector V1t = Vel1 - V1n; // velocity along plane of collision

Vel1 = -(elasticity) * V1n + (1.0f - friction) * V1t; // new velocity, after friction and bounce



// reset the boat

Boat0.speed = sqrt(Vel0.Dot(Vel0));
Boat1.speed = sqrt(Vel1.Dot(Vel1));

// set the angle only if the speed is large enough

if (Boat0.speed > 0.001f)
Boat0.angle = atan2(Vel0.y, Vel0.x);

// set the angle only if the speed is large enough

if (Boat1.speed > 0.001f)
Boat1.angle = atan2(Vel1.y, Vel1.x);

Boat0.x = Pos0.x;
Boat0.y = Pos0.y;

Boat1.x = Pos1.x;
Boat1.y = Pos1.y;


and also, I hope you don't set the boat's orientation directly from the boat's velocity direction. When they will collide, the direction is gonna flip. This is why I check if the new velocity is sufficient. YOu should get rid of the angle for the boat velocity, and use vectors, much simpler. However, for the boat orientation (the way it is rendered), you can keep an angle.

[edited by - oliii on November 17, 2003 8:29:42 AM]

Share this post


Link to post
Share on other sites
Thank you very much for responding.

Could you explain vectors to me please? Learned some about it in school 2000 years ago, but now i don't remember much.

[edited by - endasil on November 17, 2003 8:44:00 AM]

Share this post


Link to post
Share on other sites
vectors are positions or directions in space (3D), or in a plane (2D). They contains three coordinates (for 3D) or 2 (for 2D), which are references along the axes of an orthogonal coordinate system. in 2D, the display, for example, is a 2D orthogonal system, the horizontal lines (the X axis) are perpendicular to the vertical lines (the Y axis). There is also a point called the origin, the top left (or bottom left depending on which way you want it) corner, and the origin as coordinates (0, 0).

the vector (x, y) defines a point on the display, where the point is x amount along the horizontal line from the origin, and y amount along the vertical line from the origin. That's the basics of a vector.

There are 2 types of vectors though. Directional (pointing towards a direction), and positions (a point in space). It is better to remember to keep those two types in mind, as they are fundamentaly different (one points towards, with no sense of position, the other is just a position in space).

For example, the direction vector D from a position A to a position B is D = (B - A).

And the position B can be found by adding a direction to the position A. B = A + D.

you can perform operations on vectors, such as multiplications, substractions, additions, and products.

products
--------
A.Dot (B) = B.Dot (A) = (A.x * B.x) + (A.y * B.y);
A.Cross(B) = -A.Cross(B) = (A.x * B.y) - (A.y * B.x);
A * k = k * A = (A.x * k, A.y * k)
A / k = 1/k * A = (A.x / k, A.y / k)

A *= k = A.x *= k; A.y *= k;
A /= k = A.x /= k; A.y /= k;

Products are performed on directional vectors. They are linked to the angles between the two directions A and B. For example, you can find the angle between A and B by doing angle = atan2(A.Cross(B), A.Dot(B)). Dot returns a float, the cross, in 2D, returns a float too, the other products return a vector.

Additions
---------
A + B = (B + A) = (A.x + B.x, A.y + B.y)
A - B = -(B - A) = (A.x - B.x, A.y - B.y)

A += B => A.x += B.x; A.y += B.y;
A -= B => A.x -= B.x; A.y -= B.y;

there is no defined operation for adding a float to a vector.

other things
------------

k * (A + B) = k*A + k*B
A + (B + C) = (A + B) + C

-A = A * -1 = (-A.x, -A.y)

the length of a vector is

length(A) = sqrt(A.x*A.x + A.y*A.y) = sqrt(A.Dot(A))

a normalised vector is a vector with length = 1. It is a direction vector, with no specified 'strenght'.

Length(A) = sqrt(A.x*A.x + A.y*A.y) = sqrt(A.Dot(A))

Unit_Vector(A) = A / length(A)


[edited by - oliii on November 17, 2003 2:14:50 PM]

Share this post


Link to post
Share on other sites
if you're lazy, here is a 2D vector class


#ifndef OLI_VECTOR2_H
#define OLI_VECTOR2_H


/*
#include "Engine\Maths\Vector2.h"
*/


/*
------------------------------------------------------------------
File: Vector2.h
Started: 17/11/2003 22:50:17

$Header: $
$Revision: $
$Locker: $
$Date: $

Author: Olivier renault
------------------------------------------------------------------
Module:
Description:
------------------------------------------------------------------
$History: $
------------------------------------------------------------------
*/


#pragma once

#include <Math.h>

float PI()
{
static const float pi = atan(1.0f) * 4.0f;

return pi;
}

float RadiansToDegrees(float rads)
{
return rads * (180.0f / PI());
}

float DegreesToRadians(float degs)
{
return degs * (PI() / 180.0f);
}


class Vector2
{
public:
float x, y;

Vector2()
{}

Vector2(float _x, float _y)
: x(_x)
, y(_y)
{}

Vector2(const Vector2& vec)
: x(vec.x)
, y(vec.y)
{}

//------------------------------------

// operators

//------------------------------------

Vector2& operator += (const Vector2& vec) { x += vec.x; y += vec.y; return *this; }
Vector2& operator -= (const Vector2& vec) { x -= vec.x; y -= vec.y; return *this; }
Vector2& operator *= (float k) { x *= k; y *= k; return *this; }
Vector2& operator /= (float k) { return (*this) *= 1.0f/k; }

Vector2 operator + (const Vector2& vec) const { Vector2 Temp(*this); return Temp += vec; }
Vector2 operator - (const Vector2& vec) const { Vector2 Temp(*this); return Temp -= vec; }
Vector2 operator * (float k) const { Vector2 Temp(*this); return Temp *= k; }
Vector2 operator / (float k) const { Vector2 Temp(*this); return Temp /= k; }

float operator * (const Vector2& vec) const { return x * vec.x + y * vec.y; } // dot product

float operator ^ (const Vector2& vec) const { return x * vec.y - y * vec.x; } // cross product


friend Vector2 operator * (float k, const Vector2& seg) { return seg*k; }

float GetLengthSquared() const { return (*this) * (*this); }
float GetLength() const { return sqrt(GetLengthSquared()); }
float Normalise(void) { float d = GetLength(); if (d < 0.0000001f) return 0.0f; (*this) /= d; return d; }

Vector2 UnitVector(void) const { Vector2 Temp(*this); Temp.Normalise(); return Temp; }

//-------------------------------------------------------

// calculate the angle in degrees between two segments

//

//-------------------------------------------------------

float GetDegrees(const Vector2& vec)
{
float co = (*this) * vec;
float si = (*this) ^ vec;

return RadiansToDegrees(atan2(si, co));
}

Vector2& Rotate(float degrees)
{
float rads = DegreesToRadians(degrees);

float cos_angle = cos(rads);
float sin_angle = sin(rads);

float t = x;
x = x * cos_angle - y * sin_angle;
y = t * sin_angle + y * cos_angle;

return *this;
}

Vector2 FromRotation(float degrees) const
{
Vector2 Temp(*this);

return Temp.Rotate(degrees);
}


Vector2& Rotate(const Vector2& CentreOfRotation, float degrees)
{
Vector2 Seg(*this - CentreOfRotation);

Seg.Rotate(degrees);

*this = CentreOfRotation + Seg;

return *this;
}

Vector2& BoundMin(const Vector2& vec)
{
if (vec.x < x) x = vec.x;
if (vec.y < y) y = vec.y;

return *this;
}

Vector2& BoundMax(const Vector2& vec)
{
if (vec.x > x) x = vec.x;
if (vec.y > y) y = vec.y;

return *this;
}
};
#endif



I haven't tested it fully, but it should be perfectly fine .

[edited by - oliii on November 17, 2003 5:59:27 PM]

[edited by - oliii on November 17, 2003 6:04:36 PM]

Share this post


Link to post
Share on other sites
Thank you for your help. There are still alot i don''t fully understand and i don''t just want to pick a bunch of finished stuff and use, i want to learn everything!

I have send a request to add you to my icq list. It would be a bit easier to learn if we can have a direct conversation.

Share this post


Link to post
Share on other sites
Yay, had a similar problem on a lil'' thing i was working on.. had pseudo-solution happening but it just didnt work well enough, havent touched it since, now i can work on it with renewed vigour, nice one

Share this post


Link to post
Share on other sites