Forum > Games
Simple ball bounce
lazboy10:
Hi!
So my problem is that i have been trying to get a ball to hit another ball and then bounce in the correct angle.
i have working code for the actual collision part, but for the life of me i just cant get the other ball to bounce correctly in the right angle.
My math skills are terrible so im hoping someone could help me with some working code... what i need is the bounce code only, i don't need any velocity or optimized code. just the basic bounce part.
here is my collision code that works:
--- Code: Pascal [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---function TestCollision: boolean;var CentreAX, CentreAY, CentreBX, CentreBY, vDx, vDy, fDist: Single;begin {red ball} CentreAX := (Balls[1].Position.X + 24) / 2; CentreAY := (Balls[1].Position.Y + 24) / 2; {white ball} CentreBX := (Balls[0].Position.X + 24) / 2; CentreBY := (Balls[0].Position.Y + 24) / 2; vDx := CentreBX - CentreAX; vDy := CentreBY - CentreAY; fDist := Sqrt((vDx * vDx) + (vDy * vDy)); if fDist<12 then Result := True else Result := False;end;
Mr.Madguy:
It's simple conservation of momentum. In case of equal masses velocities are simply swapped and mirrored against plane, that is perpendicular to line between two ball centers. Collision point also lies in a middle of that line. Hit detection - is simple distance measurement between centers. If distance <= 2 radius, then it's hit.
Looks like simple googling gives proper result.
BobDog:
You can look at this.
(simple console graphics only)
Tested win 10, 32 and 64 bit fp.
--- Code: Pascal [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} --- program balls; uses windows; const DC_BRUSH=18; const DC_PEN=19; Type V2=object x,y,dx,dy:single; radius:integer; c:longword; End; type aov=array[1..4] of v2; function SetDCBrushColor(p:hdc;colour:COLORREF): COLORREF; stdcall external 'gdi32.dll' name 'SetDCBrushColor'; function SetDCPenColor(p:hdc;colour:COLORREF): COLORREF; stdcall external 'gdi32.dll' name 'SetDCPenColor'; function rgb(r:word;g:word;b:word) :longword; begin exit(((b Shl 16) Or ((g) Shl 8) Or (r) Or $FF000000)- $FF000000) end; procedure hidecursor(); var consoleHandle:handle; info:CONSOLE_CURSOR_INFO ; begin consolehandle := GetStdHandle(STD_OUTPUT_HANDLE); info.dwSize := 100; info.bVisible := FALSE ; SetConsoleCursorInfo(consoleHandle, @info); End; procedure MoveAndDraw(wh:hdc;var b:aov); var lx,ly:single;i,r,j:integer; begin for i:=low(b) to high(b) do begin lx:=b[i].x;ly:=b[i].y; r:=b[i].radius; SetDCBrushColor(wh,rgb(0,0,0)); SetDCPenColor(wh,rgb(0,0,0)); ellipse(wh,trunc(lx-r),trunc(ly-r),trunc(lx+r),trunc(ly+r)); b[i].x:=b[i].x+b[i].dx; b[i].y:=b[i].y+b[i].dy; SetDCBrushColor(wh,b[i].c); SetDCPenColor(wh,b[i].c); for j:=0 to 5 do ellipse(wh,trunc(b[i].x-r),trunc(b[i].y-r),trunc(b[i].x+r),trunc(b[i].y+r)); end; end; procedure HandleEdges(var b:aov); var i,r:integer; begin for i:=low(b) to high(b) do begin r:=b[i].radius; if (b[i].x<r) then begin b[i].x:=r;b[i].dx:=-b[i].dx; end; if (b[i].x>(800-r)) then begin b[i].x:=800-r;b[i].dx:=-b[i].dx; end; if (b[i].y<r) then begin b[i].y:=r;b[i].dy:=-b[i].dy; end; if (b[i].y>(600-r)) then begin b[i].y:=600-r;b[i].dy:=-b[i].dy; end end; end; function HandleBallCollisions(Var b:aov):boolean ;Var L,impulsex,impulsey,dot,impactx,impacty: single; ma,mb,f1,f2: single; n1,n2: Integer; flag:boolean=false;Begin For n1 :=low(b) To high(b) -1 Do Begin For n2 :=n1+1 To high(b) Do Begin L := Sqrt( (b[n1].x-b[n2].x)*(b[n1].x-b[n2].x) + (b[n1].y-b[n2].y)*(b[n1].y-b[n2].y)); If L< (b[n1].radius+b[n2].radius) Then Begin flag:=true; impulsex := (b[n1].x-b[n2].x)/L ; impulsey := (b[n1].y-b[n2].y)/L ; // in case of large overlap (non analogue motion) b[n1].x := b[n2].x+(b[n1].radius+b[n2].radius)*impulsex ; b[n1].y := b[n2].y+(b[n1].radius+b[n2].radius)*impulsey ; impactx := b[n1].dx-b[n2].dx ; impacty := b[n1].dy-b[n2].dy ; dot := impactx*impulsex+impacty*impulsey ; ma := b[n1].radius; mb := b[n2].radius; ma := ma*ma; // weigh by area (radius squared) mb := mb*mb; f1 := 2*mb/(ma+mb); // ball weight factors f2 := 2*ma/(ma+mb); b[n1].dx:= b[n1].dx-dot*impulsex *f1; b[n1].dy:= b[n1].dy-dot*impulsey *f1; b[n2].dx:=b[n2].dx+ dot*impulsex *f2 ; b[n2].dy:= b[n2].dy+dot*impulsey *f2 ; End; End; // n2 End; // n1 exit(flag);End; Var p:hwnd; wh:hdc; b:aov; beginb[1].x:=100;b[1].y:=200;b[1].dx:=0.06;b[1].dy:=0.04;b[1].radius:=45;b[1].c:=rgb(255,100,0); b[2].x:=500;b[2].y:=300;b[2].dx:=-0.06;b[2].dy:=-0.08;b[2].radius:=40;b[2].c:=rgb(0,255,0); b[3].x:=200;b[3].y:=500;b[3].dx:=0.06;b[3].dy:=-0.07;b[3].radius:=35;b[3].c:=rgb(0,0,255); b[4].x:=300;b[4].y:=400;b[4].dx:=-0.06;b[4].dy:=0.07;b[4].radius:=30;b[4].c:=rgb(0,100,255); p := GetConsoleWindow();setwindowpos(p, HWND_TOPMOST, 100, 100, 810, 630,SWP_SHOWWINDOW); wh:=GetDC(p); SelectObject(wh,GetStockObject(DC_BRUSH)); SelectObject(wh,GetStockObject(DC_PEN)); hidecursor; ShowScrollBar(p, SB_BOTH, FALSE); while true do beginMoveAndDraw(wh,b);HandleEdges(b);if HandleBallCollisions(b) then //clearscreen- optionalbegin SetDCBrushColor(wh,rgb(0,0,0)); SetDCPenColor(wh,rgb(0,0,0)); rectangle(wh,0,0,810,630);end; end; end.
speter:
In case anyone is interested, here is a GUI version of BobDog's code.
cheers
S.
loaded:
--- Quote from: speter on February 01, 2022, 08:30:56 am ---In case anyone is interested, here is a GUI version of BobDog's code.
--- End quote ---
I am one of those who are interested.
Many thanks for the code, BobDog and speter
Navigation
[0] Message Index
[#] Next page