Sign in to follow this  
Followers 0
matwachich

2D Collision, Objet mass

5 posts in this topic

I'm making a 2D games engin, which includes a small physics engin

here is the code that controls the ellastic collision between 2 objects ($hSprite1, $hSprite2) inspired from This link

Local $dist = _GEng_SpriteToSprite_Dist($hSprite1, $hSprite2) ; the distance between the 2 objects
    Local $nx, $ny, $gx, $gy
    $nx = ($hSprite2[$_gSpr_PosX] - $hSprite1[$_gSpr_PosX]) / $dist
    $ny = ($hSprite2[$_gSpr_PosY] - $hSprite1[$_gSpr_PosY]) / $dist
    $gx = -1 * $ny
    $gy = $nx
    ; ---
    Local $v1n, $v1g, $v2n, $v2g
    $v1n = $nx * $hSprite1[$_gSpr_SpeedX] + $ny * $hSprite1[$_gSpr_SpeedY]
    $v1g = $gx * $hSprite1[$_gSpr_SpeedX] + $gy * $hSprite1[$_gSpr_SpeedY]
    $v2n = $nx * $hSprite2[$_gSpr_SpeedX] + $ny * $hSprite2[$_gSpr_SpeedY]
    $v2g = $gx * $hSprite2[$_gSpr_SpeedX] + $gy * $hSprite2[$_gSpr_SpeedY]
    ; ---
    If $hSprite1[$_gSpr_Masse] > 0 Then
        $hSprite1[$_gSpr_SpeedX] = $nx * $v2n + $gx * $v1g
        $hSprite1[$_gSpr_SpeedY] = $ny * $v2n + $gy * $v1g
    EndIf
    If $hSprite2[$_gSpr_Masse] > 0 Then
        $hSprite2[$_gSpr_SpeedX] = $nx * $v1n + $gx * $v2g
        $hSprite2[$_gSpr_SpeedY] = $ny * $v1n + $gy * $v2g
    EndIf

this code conciders that the 2 objects have the same mass, but i want to be able to compute collisions between object of different mass, and i don't know where to insert the mass variable ($hSpriteX[$_gSpr_Masse]) in the equations

Need help please!

Share this post


Link to post
Share on other sites



#2 ·  Posted (edited)

Look at the code in where you can enable mass on the balls.

Btw, there are plenty tutorial for collision detection in the web - just ask Google...

Br,

UEZ

Edited by UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Share this post


Link to post
Share on other sites

I advise you get physics textbook :huh2:

Momentum = mass * velocity

Total momentum before is the same as after.

Share this post


Link to post
Share on other sites

#4 ·  Posted (edited)

I'm making a 2D games engin, which includes a small physics engin

here is the code that controls the ellastic collision between 2 objects ($hSprite1, $hSprite2) inspired from This link

Local $dist = _GEng_SpriteToSprite_Dist($hSprite1, $hSprite2) ; the distance between the 2 objects
    Local $nx, $ny, $gx, $gy
    $nx = ($hSprite2[$_gSpr_PosX] - $hSprite1[$_gSpr_PosX]) / $dist
    $ny = ($hSprite2[$_gSpr_PosY] - $hSprite1[$_gSpr_PosY]) / $dist
    $gx = -1 * $ny
    $gy = $nx
    ; ---
    Local $v1n, $v1g, $v2n, $v2g
    $v1n = $nx * $hSprite1[$_gSpr_SpeedX] + $ny * $hSprite1[$_gSpr_SpeedY]
    $v1g = $gx * $hSprite1[$_gSpr_SpeedX] + $gy * $hSprite1[$_gSpr_SpeedY]
    $v2n = $nx * $hSprite2[$_gSpr_SpeedX] + $ny * $hSprite2[$_gSpr_SpeedY]
    $v2g = $gx * $hSprite2[$_gSpr_SpeedX] + $gy * $hSprite2[$_gSpr_SpeedY]
    ; ---
    If $hSprite1[$_gSpr_Masse] > 0 Then
        $hSprite1[$_gSpr_SpeedX] = $nx * $v2n + $gx * $v1g
        $hSprite1[$_gSpr_SpeedY] = $ny * $v2n + $gy * $v1g
    EndIf
    If $hSprite2[$_gSpr_Masse] > 0 Then
        $hSprite2[$_gSpr_SpeedX] = $nx * $v1n + $gx * $v2g
        $hSprite2[$_gSpr_SpeedY] = $ny * $v1n + $gy * $v2g
    EndIf

this code conciders that the 2 objects have the same mass, but i want to be able to compute collisions between object of different mass, and i don't know where to insert the mass variable ($hSpriteX[$_gSpr_Masse]) in the equations

Need help please!

I assume you mean how do you allow for the different masses in your calculations of the resulting speeds. Based on that here are my meandering thoughts, and there might be others who can give better answers as always.

The first thing I would think about is that enery and momentum must be conserved. So I would work out the momentum in x and y before the collision and make sure that the momentum was the same after the collision.

I would assume a perfectly elestic collision; ie no energy given upo to friction in the collision.

I don't actually know how 2 bodies respond to collisions so let's try a straight line collision.

Say the small one is S and the big one is G, velocity of S is Vs and for B it's Vb. Mass of S is Ws and of B is Wb. so

Initial total momentum is

Mt = Ms + Mb

= Wb * Vb + Ws * Vs

After the collision each some momentum will be transferred from one to the other, and what's lost by one is gained by the other.

The velocities after collision are say Rs and Rb for (rebound vel)

so

Ms * Rs + Mb * Rb = Ms * Vs + Mb * Vb (i)

Say the change in velocity for S is J. Then the change in velocity for B will be K given by

K*Mb = -J * Ms (ii)

Since

Rs = Vs + J

and

Rb = Vb - J * Ms/Mb

we can write (i) again lik ethis

Ms * (Vs + J) + Mb *(Vb - J * Ms/Mb) = Ms * Vs + Mb * Vb

which only has J as an unknown so we can work it out.

Now treat the X and Y components as I did the in-line example and I think you should be able to calculate the changes in velocity depending on the initial velocities and the relative masses.

Since this is written as I think it up it neds to be treated with sceptism, but so far it sounds reasonable to me.

EDIT: Typos

Edited by martin

Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.

Share this post


Link to post
Share on other sites

Ok! thanks!

I inspired from the UEZ example and here is the result

If Not __GEng_Sprite_IsSprite($hSprite2) Then Return SetError(1, 0, 0)
    ; ---
    Local $dist = _GEng_SpriteToSprite_Dist($hSprite1, $hSprite2)
    Local $mass_tot = $hSprite1[$_gSpr_Masse] + $hSprite2[$_gSpr_Masse]
    Local $nx, $ny, $gx, $gy
    $nx = ($hSprite2[$_gSpr_PosX] - $hSprite1[$_gSpr_PosX]) / $dist
    $ny = ($hSprite2[$_gSpr_PosY] - $hSprite1[$_gSpr_PosY]) / $dist
    $gx = -1 * $ny
    $gy = $nx
    ; ---
    Local $v1n, $v1g, $v2n, $v2g
    $v1n = $nx * $hSprite1[$_gSpr_SpeedX] + $ny * $hSprite1[$_gSpr_SpeedY]
    $v1g = $gx * $hSprite1[$_gSpr_SpeedX] + $gy * $hSprite1[$_gSpr_SpeedY]
    $v2n = $nx * $hSprite2[$_gSpr_SpeedX] + $ny * $hSprite2[$_gSpr_SpeedY]
    $v2g = $gx * $hSprite2[$_gSpr_SpeedX] + $gy * $hSprite2[$_gSpr_SpeedY]
    ; ---
    ;calculate new vectors according to mass
    $v_p1 = ($hSprite1[$_gSpr_Masse] - $hSprite2[$_gSpr_Masse]) / $mass_tot * $v1n + 2 * $hSprite2[$_gSpr_Masse] / $mass_tot * $v2n
    $v_p2 = ($hSprite2[$_gSpr_Masse] - $hSprite1[$_gSpr_Masse]) / $mass_tot * $v2n + 2 * $hSprite1[$_gSpr_Masse] / $mass_tot * $v1n
    ; ---
    If $hSprite1[$_gSpr_Masse] > 0 Then
        $hSprite1[$_gSpr_SpeedX] = $nx * $v_p1 + $gx * $v1g
        $hSprite1[$_gSpr_SpeedY] = $ny * $v_p1 + $gy * $v1g
    EndIf
    If $hSprite2[$_gSpr_Masse] > 0 Then
        $hSprite2[$_gSpr_SpeedX] = $nx * $v_p2 + $gx * $v2g
        $hSprite2[$_gSpr_SpeedY] = $ny * $v_p2 + $gy * $v2g
    EndIf

It works just as i need.

The very big problem is the 'orbiting effect', here is how i solved it (partially, failing at high speed moving objects)

Local $rat1x, $rat1y ; ratio de vitesse x/y
    Local $rat2x, $rat2y ; ratio de vitesse x/y
    ; ---
    If $hSprite1[$_gSpr_SpeedX] = 0 Then
        $rat1x = 0
        $rat1y = 1
    ElseIf $hSprite1[$_gSpr_SpeedY] = 0 Then
        $rat1x = 1
        $rat1y = 0
    Else
        $rat1x = $hSprite1[$_gSpr_SpeedX] / (Abs($hSprite1[$_gSpr_SpeedY]) + Abs($hSprite1[$_gSpr_SpeedX]))
        $rat1y = $hSprite1[$_gSpr_SpeedY] / (Abs($hSprite1[$_gSpr_SpeedY]) + Abs($hSprite1[$_gSpr_SpeedX]))
    EndIf
    ;ConsoleWrite($rat1x & " , " & $rat1y & @CRLF)
    ; ---
    If $hSprite1[$_gSpr_SpeedX] < 0 Then
        $rat1x = -1 * Abs($rat1x)
    Else
        $rat1x = Abs($rat1x)
    EndIf
    If $hSprite1[$_gSpr_SpeedY] < 0 Then
        $rat1y = -1 * Abs($rat1y)
    Else
        $rat1y = Abs($rat1y)
    EndIf
    ; ---
    ; ---
    If $hSprite2[$_gSpr_SpeedX] = 0 Then
        $rat2x = 0
        $rat2y = 1
    ElseIf $hSprite2[$_gSpr_SpeedY] = 0 Then
        $rat2x = 1
        $rat2y = 0
    Else
        $rat2x = $hSprite2[$_gSpr_SpeedX] / (Abs($hSprite2[$_gSpr_SpeedY]) + Abs($hSprite2[$_gSpr_SpeedX]))
        $rat2y = $hSprite2[$_gSpr_SpeedY] / (Abs($hSprite2[$_gSpr_SpeedY]) + Abs($hSprite2[$_gSpr_SpeedX]))
    EndIf
    ;ConsoleWrite($rat2x & " , " & $rat2y & @CRLF)
    ; ---
    If $hSprite2[$_gSpr_SpeedX] < 0 Then
        $rat2x = -1 * Abs($rat2x)
    Else
        $rat2x = Abs($rat2x)
    EndIf
    If $hSprite2[$_gSpr_SpeedY] < 0 Then
        $rat2y = -1 * Abs($rat2y)
    Else
        $rat2y = Abs($rat2y)
    EndIf
    ; ---
    Local $x = 0
    Do
        If $hSprite1[$_gSpr_Masse] > 0 Then
            If $hSprite1[$_gSpr_PosX] > $hSprite1[$_gSpr_OriX] And _
                $hSprite1[$_gSpr_PosY] > $hSprite1[$_gSpr_OriY] And _
                $hSprite1[$_gSpr_PosX] < $__GEng_WinW - $hSprite1[$_gSpr_OriX] And _
                $hSprite1[$_gSpr_PosY] < $__GEng_WinH - $hSprite1[$_gSpr_OriY] Then
                    $hSprite1[$_gSpr_PosX] += $rat1x
                    $hSprite1[$_gSpr_PosY] += $rat1y
            EndIf
        EndIf
        If $hSprite2[$_gSpr_Masse] > 0 Then
            If $hSprite2[$_gSpr_PosX] > $hSprite2[$_gSpr_OriX] And _
                $hSprite2[$_gSpr_PosY] > $hSprite2[$_gSpr_OriY] And _
                $hSprite2[$_gSpr_PosX] < $__GEng_WinW - $hSprite2[$_gSpr_OriX] And _
                $hSprite2[$_gSpr_PosY] < $__GEng_WinH - $hSprite2[$_gSpr_OriY] Then
                    $hSprite2[$_gSpr_PosX] += $rat2x
                    $hSprite2[$_gSpr_PosY] += $rat2y
            EndIf
        EndIf
        ;ConsoleWrite($rat1x & " , " & $rat1y & @CRLF)
        ;ConsoleWrite($rat2x & " , " & $rat2y & @CRLF)
        $x += 1
        ;ConsoleWrite(" >>> " & $x & @CRLF)
        If $x = 10 Then
            ;ConsoleWrite("Max!" & @CRLF)
            ExitLoop
        EndIf
    Until Not _GEng_Sprite_Collision($hSprite1, $hSprite2, 0) ; check collision between the sprites (recursive call)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0