Dark Bit Factory & Gravity
PROGRAMMING => Other languages => Yabasic => Topic started by: Clanky on February 10, 2007
-
Wow.. I just needa finish Green Boxcopter - then I have finished a game...
I will do this later, because'a I'm'a tryin' ta mak'a pool game'a.
Basic information:
There are 15 balls (one black, 7 red, 7 yellow) with one white ball;
I have the visuals of the table;
I have set up a check system to see what each balls status is (current position, direction, etc.);
Hopefully I can be taught how to make circlular collisions with defractions of the balls to the angle where the white ball has hit them.
I have the visuals - like normal I code the easy stuff. I just need to make it so the balls collide and rebound of of each other and stuff like that.
I won't be able to put the code up for awhile because I have it on the other - non internet connected computer.
When I get it on this computer, I will post it. But in the mean time, hopefully someone can give me a low down on making balls collide and rebound and stuff. And to make it so the balls go off on angles porportional to where they have been hit? Dig it??? (Hope so!)
Also, I am having real trouble with the white ball collisions... when I hit it (I have coded a little bit on breaking, with the power of the hit decreasing as it rolls, and decreasing more if it hits a wall), it is hitting the top of the table and turning right? Not suppose to happen as it hasn't hit a side wall yet?
Also, if someone would be kind enough to teach me how to make it so that you can more you 'cue' (I think that's the stick?) around in a circle, and to hit the ball of on an angle?
I will try and get the code up here as soon as I can... most probably tomorrow (hopefully)
Thanks.
-
Fryer put quite a bit of work into this problem a few years ago. I don't think we were particularly satisfied with the results. It's not too bad colliding one ball against another, but when you have a pack of balls it can be very difficult.
Post it up and we can all have a look.
Jim
-
If you can solve the problems of a game like this Clanky, I will personally give you a +50 Karma boost! Whatever happens, you'll learn a lot from it!! If you manage to impliment top and backspin and sidespin properly I'll boost your Karma by 100.
A great project. I can forsee problems of balls geting stuck inside each other etc... *shudders*
-
This might be of some help:
http://freespace.virgin.net/hugo.elias/models/m_snokr.htm
-
I would be delighted to help you on this one, in fact if you dont mind it being a team effort I would be happy to take on half the burden. I have already attempted a pool game not as far as putting backspin on the cue but got all the balls bouncing around correctly things went to pot for me when I thought it would be nice to make it 3D. Anyway I will type my old one out on the PC (its on my memory card atm) if you want a look at the code. I will post it here if you do.
Edit: Pool game attached at last. Graphics are a little modified from Clankys, It was the swept collision between the balls and the walls that held the whole show up, Sorry for the long wait. Thanks to everyone who had helped to make this happen.
Better late than never ;D
-
Nice link rdc - in snooker it can be simplified a bit because all the balls are the same size and you can just set both ball masses to 1 and ignore them.
Jim
-
Ok, heres the visual side of the game... I had to make the power and shot code just for this demo - it only goes straight ahead. but, it isn't really calculated at all... it's only the visuals.
Thanx for everything guys.
And I agree, this will be heaps hard... and I did think about having spin and stuff - I will see if i can make it so you have a ball with the position of where the cue will hit the ball on a side panel.
Hopefully this can be a DBF Team Game.
-
Thanx rcd... that page has really inspired me to make this game!
I did year 12 physics, so the momentum aspects of the collisions were a flash back *cries in happyness*... good Mr. Newton with his fundemental law for momentum - "after collision: both balls will have equal magnitude with opposite direction..." or something (and hopefully Mr. Newton's law)
I actually had two books complete on physics - with loads of information about collisions and momenta... but, there gone - bummer!!!
I guess this will be hard...
-
This was as far as I got with this, exe and source for b3d but it doesn't use b3d collisions or anything like that. I never quite worked out the right way of calculating the results of the sphere-sphere collisions but it works fairly well.
http://www.stonemonkie.pwp.blueyonder.co.uk/pool3d_3.zip
-
Holy shit Fryer! That's mentally good! Check your Karma.
-
I did a simple ball bounce code for a fire demo(haven't posted it because i haven't got any music to go with it). but it doesn't work to well, probably not well enough at all. :(
the .exe is really nice and works perfectly but the sourcecode freezes
-
Sorry about that Paul. atm I don't have b3d installed so i'd probably been messing around with something at the time of working on it. I'll look out something that works.
-
installed b3d but can't work out why it's freezing atm but here's an earlier source, it doesn't have the pockets.
-
pool3d3 is amazing but I couldnt get pool3d2 to run its says error texture not found or something to that effect but the routines should prove invaluable looks like this little project has generated quite a bit of interest
-
Sorry again, I've added the texture to the above attachment.
-
its workin perfect now I love the shadows
-
Very nice pool program Stonemonkey! Beautiful... just you can't sink the balls :( lol
I've got a cue in my program now - copied Jim Shaw's rotation bit out of his Physics Sample. It rotates, but I need some help with creating an angle so the ball moves in the direction the cue is pointing.
Then, some help with making collisions... I tried using the information from the site rdc gave, but it seems YaBASIC doesn't allow normalise() or dotpoint() **or something**
I added really nice shadow effects to the balls today. This was really a nice addition because it gave it a 3D feel to the balls. I also added a spin factor... g2g - lightning comming!! eeee
-
Moving a ball in the direction of an arrow:
If a ball is going in direction 'angle' then if you say
xpos = xpos + cos(angle) * speed
ypos = ypos + sin(angle) * speed
that will move it the right way. In yabasic, angles are in radians.
radians = degrees/180*3.14159
and
degrees = radians*3.14159/180
Normalising a vector:
If you want to make a vector have length 1 (that is, if you apply Pythagoras' Theorem to the x,y,z of the vector it comes out as 1) then you need to say
length = sqr(x*x + y*y + z*z) : rem Pythagoras
x = x / length
y = y / length
z = z / length
Vector dot product:
This calculates the amount of one vector that lies in the direction of another vector. It's also useful for finding out the angle between two vectors. If you have two vectors x1,y1,z1 and x2,y2,z2 then
dot = x1 * x2 + y1 * y2 + z1 * z2
If you're working in 2d (like in this pool game) just remove all the z terms from the last 2 equations, ie
length = sqr(x*x + y*y) : rem Pythagoras
x = x / length
y = y / length
dot = x1 * x2 + y1 * y2
Jim
-
Useful stuff, Jim.
-
the code is working for me now, wonder why it freezed instead of MAV'ing
-
A MAV is usually due to reading or writing to an address that you're not supposed to such as out of the range of an array or reading/writing fast pixels outside of the screen. I've not looked into this yet but the freeze is probably due to it getting stuck in some loop somewhere.
-
First I would suggest abandoning the traditional 2d movement of x+dirx / y+diry with a pool game it would be far more efficient imho to work with angles and momentum you can then obtain the dirx as cos(angle)*momentum and diry as sin(angle)*momentum you could of course keep things the way they are and obtain the angle by using the atan(adjacent,opposite) command but that would mean switching between one form to the other just to revert to the original form. better to just work in angles alone. if you post the code as it is now I would incorporate this feature. also I was thinking that when the setup routine is running that if you include a tiny amount of random displacement to the ball positions it would result in a totally unique break each time. the amount of displacement should be so small that it doesnt show up on a pixel basis but large enough to have a dramatic effect on the collisions. :)
-
Thanx guys. I did do abit of the angle last night, got it working - with the exception of the spin and power... but I did it before I read these.
How could I make spin? I got it working before without having cue angles, but now it has cue angles it hits it funny.
I will see where I can get too...
@ Rain_Storm: How far have you got with your pool? Have you started writting it up yet?
@ Jim: Thanx for the codes, much appreciated.
-
Here's the newest add... it has got Jim's help code, with Rain_Storm's too... but it is still hitting funny. I know why this is:
if dirx=0 wx=wx+cos(dx)*((power/1.2)+(wbdirx/45))
**where**
'wx' is the white ball's X position;
'dx' is the angle hit;
'power' is the total power hit - decreases;
'wbdirx' is the spin.
** **
Hope this can clear things up... I really want to finish this game. It's been a real knowledge booster. Thanks Guys! :clap:
-
Im am workin on typin it but its takin awhile its over 200 lines but its just really what you already have but with collisions (balls and pockets are the same but one scores the other bounces) and thats about it. Alright heres how spin works
1) topspin - add cos(topspin_angle) to foward momentum if this value is negative its called backspin
topspin will make a ball travel foward faster or slower but will have the opposite effect when the ball collides
with something backspin slow before collision fast after topspin fast before slow after
2) sidespin does this for sideways momentum and will make the ball travel along a curve to the left or right but it is
different when the ball collides with something it changes the angle of the bounce effect slightly
whilst traveling between collisions -
dirx = cos(ball_ang)*foward_momentum + cos(ball_ang+pi/2)*side_momentum
diry = sin(ball_ang)*foward_momentum + sin(ball_ang+pi/2)*side_momentum
new_posx = posx + dirx
new_posy = posy + diry
this should help you with the collisions with other balls and walls -
open window 640,512
window origin "cc"
degree = pi/180
doubpi = pi*2
halfpi = pi/2
kg = 1
m = 30
secs = 30
mins = 60*secs
mps = m/secs
rpm = doubpi/mins
rem initialise balls -
balls = 4
radius = 30
dim posx(balls), posy(balls), posz(balls)
dim dirx(balls), diry(balls), dirz(balls)
dim rotx(balls), roty(balls), rotz(balls)
dim r(balls), g(balls), b(balls)
for b = 0 to balls
repeat
rem randomise ball location -
posx(b) = ran(200) - ran(200)
posy(b) = ran(200) - ran(200)
posz(b) = ran(200) - ran(200)
rem ensure initial positions are clear of other balls -
h = radius*3
for a = 0 to balls
if (a <> b) then
rem check if location is already occupied -
adj = posx(b) - posx(a)
opp = posy(b) - posy(a)
hyp = sqrt(adj*adj + opp*opp)
if (hyp < h) h = hyp
fi
next
until (h>radius*2)
rem initialise other properties -
dirx(b) = ran(mps)*5 : rem only positive values are allowed
diry(b) = ran(mps)*5 : rem only positive values are allowed
dirz(b) = ran(mps)*5 : rem only positive values are allowed
rotx(b) = ran(doubpi)
roty(b) = ran(doubpi)
rotz(b) = ran(doubpi)
r(b) = ran(100)+ran(100)+ran(55) : rem balanced random colours
g(b) = ran(100)+ran(100)+ran(55) : rem balanced random colours
b(b) = ran(100)+ran(100)+ran(55) : rem balanced random colours
next
diry(0) = diry(0)*3
rem draw fake phong shaded balls -
sub pcircle(a,b,c) x = a+c/3 : y = b+c/3 : f = pi/8
for e = 0 to doubpi step f
gtriangle x,y to a+cos(e)*c,b+sin(e)*c to a+cos(e+f)*c,b+sin(e+f)*c
next
end sub
repeat
setdispbuf draw
draw = 1 - draw
setdrawbuf draw
clear window
rem draw balls
for b = 0 to balls
red = r(b)
grn = g(b)
blu = b(b)
setrgb 1, red, grn, blu
setrgb 2, red/10, grn/10, blu/10
setrgb 3, red/10, grn/10, blu/10
pcircle(posx(b),posy(b),radius)
setrgb 1, red*2, grn*2, blu*2
fill circle posx(b)+radius/3,posy(b)+radius/3,3
next
rem collision detection
for b = 0 to balls
rem update current ball position -
posx(b) = posx(b) + cos(rotz(b))*diry(b)
posy(b) = posy(b) + sin(rotz(b))*diry(b)
rem check new position against other balls
for a = 0 to balls
if (a <> b) then
rem calculate the distance between both balls
adj = posx(b) - posx(a)
opp = posy(b) - posy(a)
hyp = sqrt(adj*adj + opp*opp)
rem check if both balls overlap -
if (hyp < radius*2) then
rem find out how much they are overlapping by -
penetration = (radius*2) - hyp
rem rewind the current ball to the point of collision -
posx(b) = posx(b) - cos(rotz(b))*penetration
posy(b) = posy(b) - sin(rotz(b))*penetration
rem calculate new trajectories for the both balls -
rotz(b) = atan(-adj, opp) + halfpi
rotz(a) = atan(-adj, opp) - halfpi
rem energy is transferred between both balls and
rem each ball will lose energy as a result -
dx = dirx(b)/4 + dirx(a)/4 : rem relative velocity x
dy = diry(b)/4 + diry(a)/4 : rem relative velocity y
dx = dx*0.8 : rem coefficient of restitution
dy = dy*0.8 : rem coefficient of restitution
dirx(a) = dirx(a)/2 + dx
diry(a) = diry(a)/2 + dy
dirx(b) = dirx(b)/2 + dx
diry(b) = diry(b)/2 + dy
else
dirx(b) = dirx(b)*0.9999 : rem coefficient of friction
diry(b) = diry(b)*0.9999 : rem coefficient of friction
fi
fi
next
rem ensure that current ball doesn't leave the screen -
if (posx(b) < -320+radius) then
rotz(b) = pi - rotz(b)
posx(b) = -320 + radius
elsif (posx(b) > 320-radius) then
rotz(b) = pi - rotz(b)
posx(b) = 320 - radius
fi
if (posy(b) < -256+radius) then
rotz(b) = -rotz(b)
posy(b) = -256 + radius
elsif (posy(b) > 256-radius) then
rotz(b) = -rotz(b)
posy(b) = 256 - radius
fi
next
until (1 = 0)
-
Thanks, I will take this into account.
-
I will include the angular movement and collisions in the last version of pool you posted tomarrow and will put it on the forum its far too late now ;)
-
Guese what I'm takin the day off today I should've been sleepin last night but I just couldn't help it and threw this together its fairly bug free and commented too
###############################
# Comments that look like this are important #
###############################
enjoy
-
That's a lot of progress for one night! K++!
The collisions look pretty inelastic at the moment - is it possible to reduce the total enery at the time of the collision? That would model real life where some kinetic energy is lost as sound and heat, and might make it look a little more realistic.
How well does it handle smashing a pack? How well does it handle a very fast cue ball hitting (or not!) a stationary ball?
Jim
-
Aha well spotted you're exactly right the balls are alot harder than the code above implies since I set the coefficient of restitution to around 0.8 when it should be above 0.9 for balls that hard but this is because all the balls momentum is randomised so there is far more energy on the table at the moment then there would be from the break with all balls stationary also I have set the coefficient of restitution for the bunkers stlightly lower 0.78 i think to reflect the softer surface, the coefficient of friction is 0.999 preatty smooth slowdown and the coefficient for angular momentum is 0.99 so balls will stay spinnin for quite a bit these values must be played with to suit a static layout with only the cue ball having momentum and I have left notes in the code of how to play with them and what ranges are good.
From my own observations the maximum speed you can get away with before collisions begin to suffer is about 10 meters per second since the screen is updated 100 times per second, one meter is also 100 this means that at 1*mps a ball will travel one pixel each frame so at 10*mps a ball will move exactly one radius (radius = 10) each frame I have included a feature that forbids overlapping balls by rewinding the moving ball to the point of collision but if the ball moves more than one radius that feature may move the ball to the opposite side of the other ball and generate incorrect collisions also the bunkers are a bounding box with the balls inside it there is the possibility that a ball may get stuck outside those bounds and start vibrating. this is also stated in the code but again well spotted as this is an important part in a pool game the physics have got to be right in fact the only thing you can really cheat is the balls mass which is the same for all balls so it can be assumed to be one and ignored. phew that was a long post
-
if the ball moves more than one radius that feature may move the ball to the opposite side of the other ball
If you limit it to < half a ball radius that can't happen.
Jim
-
thats gonna have to be the road to take
I've noticed a bug in the way I was rewinding the moving ball back to the point of collision thats messin things up in the pack.
At the destination point ball A is overlapping ball B. so we rewind ball A to the point of collision, but at this point in time ball A's new position overlaps ball C, collisions are not detected between ball A and ball C. by right we should collide with ball C, ignore ball A and let that be that. but we are in the middle of a for next loop so it will also require a goto statement to break out of it. but what if there are two balls occupying a part of that new space. Its gonna be a real problem if at any point an overlap is missed and two ball become glued together. The best solution I can think of is to simply detect collisions in one loop then find the closest of those in another loop. complex or what?
-
:) I'm pretty sure there are some good articles on the web about this.
-
I have this code I downloaded a while back when I was still using Blitzbasic. It may not be exactly what you are looking for but, maybe it is helpfull to somebody.
;------------------------------------------
;2D COLLISION DEMO CODE
;------------------------------------------
; By Joseph 'Phish' Humfrey
; This type of collision response isn't
; just useful for pool and billiard style
; games, and in fact, I didn't write it for
; that reason at all. I wrote it because I
; needed to have collision for the space
; ships in my game 'Unity'. When their
; shields are up, they use this relatively
; simple method. It can be used for almost
; anything - player character bouncing off
; enemies in a platform game, to space
; ship collision, to a game which does
; actually involve balls. The basic
; algorithm which I used would work for
; both 2d and 3d, so if you would like to
; see it, email me at phish@aelius.com
;------------------------------------------
; The actual code which works out what
; happens after a collision is in the
; UpdateCirclePhysics() function.
;------------------------------------------
; Enjoy!
;------------------------------------------
;------------------------------------------
Graphics 800, 600, 16, 2
SetBuffer BackBuffer()
SeedRnd MilliSecs()
;------------------------------------------
; MAIN DATA TYPE
;------------------------------------------
; This exact type isn't supposed to be used
; Instead, you should use some of the fields
; in your own type, or just use this one
; for reference, to see what each field does
Type circle
Field x#, y#;position
Field dx#, dy#;x and y speeds
Field radius#;radius of circle
Field mass#;mass of circle
End Type
;------------------------------------------
;------------------------------------------
;------------------------------------------
; SET UP BALLS INTO A POOL STYLE ARRANGEMENT
; FOR DEMO
;------------------------------------------
.Setup
ballTriangleSize=5
For xloop = ballTriangleSize To 1 Step -1
For yloop = 1 To xloop
c.circle = New circle
c\x = (5-xloop)*27 + 200
c\y = yloop*31-(xloop*31)/2.0 + 300
c\dx=0
c\dy=0
c\radius = 15
c\mass = 50
Next
Next
;Cue ball (smaller so you know which it is :)
cue.circle = New circle
cue\x = 800
cue\y = 300 +20
cue\dx = -20
cue\dy = Rnd(4)-2
cue\radius = 14
cue\mass = 50
;------------------------------------------
;------------------------------------------
;------------------------------------------
;MAIN LOOP
;------------------------------------------
; This is the main While..Wend game loop
While Not KeyDown(1)
Cls
UpdateCirclePhysics()
RenderCircles()
;------------
; Reset button
Text 10, 10, "Press a mouse button to reset."
Text 10, 25, "Press Esc to exit."
If GetMouse() Then
For c.circle = Each circle
Delete c
Next
Goto setup
End If
;------------
Flip
Wend
;------------------------------------------
;------------------------------------------
End
;------------------------------------------
Function UpdateCirclePhysics()
;------------------------------------------
; This is the main physics function for the
; circles. It contains the very basic
; movement physics as well as the collision
; response code.
;------------------------------------------
For c.circle = Each circle
;update positions
c\x=c\x+c\dx
c\y=c\y+c\dy
;gradually slow down
c\dx=c\dx*0.991
c\dy=c\dy*0.991
;------------------------------------------
;COLLISION CHECKING
;------------------------------------------
; Check each circle in the loop against
; every other (c against c2)
For c2.circle = Each circle
collisionDistance# = c\radius+c2\radius
actualDistance# = Sqr((c2\x-c\x)^2+(c2\y-c\y)^2)
;Collided or not?
If actualDistance<collisionDistance Then
collNormalAngle#=ATan2(c2\y-c\y, c2\x-c\x)
;Position exactly touching, no intersection
moveDist1#=(collisionDistance-actualDistance)*(c2\mass/Float((c\mass+c2\mass)))
moveDist2#=(collisionDistance-actualDistance)*(c\mass/Float((c\mass+c2\mass)))
c\x=c\x + moveDist1*Cos(collNormalAngle+180)
c\y=c\y + moveDist1*Sin(collNormalAngle+180)
c2\x=c2\x + moveDist2*Cos(collNormalAngle)
c2\y=c2\y + moveDist2*Sin(collNormalAngle)
;------------------------------------------
;COLLISION RESPONSE
;------------------------------------------
;n = vector connecting the centers of the circles.
;we are finding the components of the normalised vector n
nX#=Cos(collNormalAngle)
nY#=Sin(collNormalAngle)
;now find the length of the components of each movement vectors
;along n, by using dot product.
a1# = c\dx*nX + c\dy*nY
a2# = c2\dx*nX + c2\dy*nY
;optimisedP = 2(a1 - a2)
; ----------
; m1 + m2
optimisedP# = (2.0 * (a1-a2)) / (c\mass + c2\mass)
;now find out the resultant vectors
;r1 = c1\v - optimisedP * mass2 * n
c\dx = c\dx - (optimisedP*c2\mass*nX)
c\dy = c\dy - (optimisedP*c2\mass*nY)
;r2 = c2\v - optimisedP * mass1 * n
c2\dx = c2\dx + (optimisedP*c\mass*nX)
c2\dy = c2\dy + (optimisedP*c\mass*nY)
End If
Next
;------------------------------------------
;------------------------------------------
;Simple Bouncing off walls.
If c\x<c\radius Then
c\x=c\radius
c\dx=c\dx*-0.9
End If
If c\x>GraphicsWidth()-c\radius Then
c\x=GraphicsWidth()-c\radius
c\dx=c\dx*-0.9
End If
If c\y<c\radius Then
c\y=c\radius
c\dy=c\dy*-0.9
End If
If c\y>GraphicsHeight()-c\radius Then
c\y=GraphicsHeight()-c\radius
c\dy=c\dy*-0.9
End If
Next
End Function
;------------------------------------------
Function RenderCircles()
;------------------------------------------
; Simple function draws all the circles
; on the screen.
;------------------------------------------
For c.circle = Each circle
If c\radius=15 Then Color 200, 50, 50 Else Color 255, 255, 255
Oval c\x-c\radius, c\y-c\radius, c\radius*2, c\radius*2
Next
End Function
;------------------------------------------
;------------------------------------------
-
I've done some great graphics for this game now...
I had a look at your collisions Rain, but it was too complex for my simple mind - great though!
I have done all the rules, and have pause & restart options. All I need now is the collisions and to fix the spin (can't get it to work even with your codes Rain?... don't know whats going on there) and it's finished.
For the spin, I have said (along the line of):
side_momentum = (power + spin_x)
forward_momentum = (power + spin_y)
I did this because the side spin will be affected by the x-spin value, and the forward the y-spin value??? Correct?
I can get back spin, but not top or either side spin?
I also need to find a way to make it so when the white ball hits something else - wall(s) or ball(s) - it changes it's spin... if I read correctly in one of your post's Rain?
Great help you guys... this is the most inspiring game out I have tried to make!!!
Oh... and to Stonemonkey: I showed a friend your pool clone program and he was impressed! I think that maybe, if you would like - maybe look at completing it with rules and stuff... because that would be a great game!!!
-
hypotenuse as you know must be less than 2*radius for a collision to occur after that you can use adj and opp to determine the angle of the line of action. the trajectories will change according to this angle its the angle of the line between both center points. Its easier to use atan because this will return the tan of that angle. so the value in line_of_action isnt the true line of action but rather a line perpendicular to it, this is in effect a wall angled correctly that both balls simply bounce away from. once we have that angle we either add or subtract 90 degrees (pi/2) for each ball
adj = ballx(a) - ballx(b) : rem (distance between centters along x axis)
opp = bally(a) - bally(b) : rem (distance along y axis)
hyp = sqrt(adj*adj + opp*opp) : rem (true distance between points)
if (hyp < radius*2) then
line_of_action = atan(-adj, opp)
trajectory(a) = line_of_action + pi/2 : rem new angle for ball a
trajectory(b) = line_of_action - pi/2 : rem new angle for ball b
fi
this will send the both balls heading off in the correct direction. Once you got it you will see that circle to circle collisions are far more easy and much faster than box to box collisions ;D
-
Sorry Clanky, I misread what you were asking.
"side_momentum = (power + spin_x)
forward_momentum = (power + spin_y)"
(side_momentum = (power + spin_x) <- is spin_x the current rotation value or the increment? You need to find the increment its the rate of rotation that is effecting side momentum not the current angle. should be more like this)
side_momentum = cos(spin_x_increment) <- no power added here power effects foward momentum
forward_momentum = power + cos(spin_y_increment)
(if cos isnt workin try sin its the same principal though)
"I did this because the side spin will be affected by the x-spin value, and the forward the y-spin value??? Correct?
I can get back spin, but not top or either side spin?
I also need to find a way to make it so when the white ball hits something else - wall(s) or ball(s) - it changes it's spin... if I read correctly in one of your post's Rain?"
now you have backspin workin thats a sign that you are on the right road with foward momentum. sidespin should be one of the last things you add in you need to get the collisions running perfectly or else you will not be able to observe how sidespin is effecting things. it should only have a slight effect on the balls motion until the ball hits something then sidespin becomes really noticeable as the ball shoots off in a direction you would not have expected it should be a lot easier once the collisions are up and runnin
-
K, that makes it abit clearier... i will try the collisions again, and wait till i get that working - then try the spins haha!
Can't wait for this sucker to be complete!!! YAYz
Thanks for your help 'again' Rain... been a pleasure working on this with you.
-
You're gonna get a ton of karma when its done I'll see to that
-
Ok, here's the problem...
My old computer which I used to make the pool game can't burn CD's, and my new computer doesn't have a floppy disc drive... and, to top that off, my brothers' MP3 is stuffing up - like normal - so I am not able to put it up here Rain... gawd annoying things like this get too me real bad!
I have no way in knowing when I can get it up here for you Rain if you want to fix it, so I guess I will have to keep trying... bare with me. :telloff:
-
damn thats a kick in the stones do you know how to install a flappy drive you would be able to slot the floppy drive in the other pc the only thing is that floppy cables can go in the wrong way around unlike all other cables in a modern pc it would take about five minutes tops if you get the cable the right way around first time and if its the wrong way it wont break your pc at all
-
Ok, finally got it working... had to use 'my' old cord instead of my brothers.
It just needs the collisions added and I'm sure it's all working properly with rules and stuff.
-
I'll put in the collisions a.s.a.p ;) I cant wait til this is a finished game :D Its looking ace at the moment Clanky this is gonna be brill
-
Just realised... there are some rules missing... and I also need to fix the spin stuff. So, when you finish and post it - I will edit it so it has the other missing rules and spin (hopefully I can code the spin).
Thanks for this Rain.
I'll give you karma!
-
You deserve k+ too man like the pause and stuff hope to have the collisions up and runnin by tomarrow then we can tackle the finishing touches
-
Man this is proving to be a challenge for me I am not use to workin in someone elses code but I always loved a challenge :D I may have to rework some parts but where ever I make a change I will try to have my adjustments runnin alongside you own code and not effect things for your code. that will help me and make it so that things are not messed up elsewhere so if you see something being done twice but with different variables thats why
-
Haha, I see your point!
Good luck with this... glad you took over to finish it because it was just sitting on my computer without collisions...
Thanks again Rain. :buddies:
-
I've been looking into these collisions again, not with the intentions of being used in this project but feel free to use anything if you want (although it's still not working).
For this I've made some assumptions so please tell me if anything at all here is wrong.
1. The velocities of the balls along the tangent to the collision normal do not change.
2. The speed and direction of the combined centre of mass of both balls is the same before and after the collision
3. The speed at which the balls travel away from each other after the collision is equal to the speed at which they travelled towards each other before the collision.
I'm pretty certain about 1 and 2 but not so sure about 3.
from that, I've come up with this test in blitz.
Graphics 800,600,32,2
x1#=300:y1#=300
vx1#=40:vy1#=20
x2#=310:y2#=295
vx2#=-20:vy2#=40
Repeat
;read start position of ball1 from mouse coords
vx1#=300.0-MouseX()
vy1#=300.0-MouseY()
;get the collision normal and tangent
nx#=x2-x1
ny#=y2-y1
l#=1.0/Sqr(nx*nx+ny*ny)
nx#=nx*l
ny#=ny*l
tx#=ny
ty#=-nx
;get the tangent component of each balls vector
vp1#=vx1*tx+vy1*ty
vp2#=vx2*tx+vy2*ty
;write the tangent component into variables for the result
rx1#=vp1*tx
ry1#=vp1*ty
rx2#=vp2*tx
ry2#=vp2*ty
;find the centre of gravity of both balls combined
;the direction and speed of the centre of gravity should be constant before and after the collision
cx#=((vx1)+(vx2))*.5
cy#=((vy1)+(vy2))*.5
;get the initial distance apart
;they should be travelling apart After the collision at the same rate they travelled towards each other before
rad#=Sqr(((vx1)-(vx2))^2.0+((vy1)-(vy2))^2.0)*.5
;calculate where on the circle edge (radius from centre of gravity) the line is for v1
dot#=tx*(rx1-cx)+ty*(ry1-cy)
dis#=-Sqr(rad*rad-dot*dot)-(nx*(rx1-cx)+ny*(ry1-cy))
rx1#=rx1+nx*dis
ry1#=ry1+ny*dis
;and same for v2
dot#=tx*(rx2-cx)+ty*(ry2-cy)
dis#=Sqr(rad*rad-dot*dot)-(nx*(rx2-cx)+ny*(ry2-cy))
rx2#=rx2+nx*dis
ry2#=ry2+ny*dis
;draw test
Color $ff,$ff,$ff
Line x1,y1,x1-vx1,y1-vy1
Line x2,y2,x2-vx2,y2-vy2
Text 50,50,"total v before:"+(Sqr(vx1^2+vy1^2)+Sqr(vx2^2+vy2^2))
Color 0,0,$ff
Line x1,y1,x1+rx1,y1+ry1
Line x2,y2,x2+rx2,y2+ry2
Text 50,70,"total v after:"+(Sqr(rx1^2+ry1^2)+Sqr(rx2^2+ry2^2))
Flip
Cls
Until KeyDown(1)
End
But the sum of the velocities before and after the collision vary quite a lot and I have no idea what else to try as this all fits with the assumptions I've made.
-
3 is true but its true of the speed at which they are traveling relative to each other not the table so if ball one moves at 1 meter per second and ball two is not moving both balls will end up traveling at 1/2 meter per second after collision. This will be useful thanks for including it here Stonemonkey. This is a really tough game to get right even though its just a game based on collisions.
-
For 3. I mean (ignoring any other forces) if they are 1m apart 1 second before the collision then they will be 1m apart 1 second after the collision.
EDIT:
My calculations even though not working properly have a very surprising result, if the balls are placed and given velocity vectors in such a way that separate them instead of colliding them, the collision calculations seem to be able to handle that and the calculated vectors are the same as the initial vectors.
-
I thought there was friction applied to the balls through the table? This would make 3 not true for this game?
But, I don't know haha lol
-
Heh, there should be but I'm wanting to work out the collision calcs without worrying about any other forces like that for now.
-
Not necessary to include friction at the moment of impact because the force of the collisions is so great that it will overshadow all other forces acting on the balls at the moment of impact at least. friction can easily be applied after collisions in a separate process
-
Ok! Sounds like a plan! :inspired:
Looks like your :stirrer: something really good up Rain... all the best
-
Hey guys I have come accross the perfect algorithm (https://www.gamasutra.com/php-bin/login.php?from=http://www.gamasutra.com/features/20020118/vandenhuevel_01.htm) ( you have to register an account) that addresses all of the short comings that my own collisions fail to incorporate. But there is one thing that I cant figure out. I need to calculate the angle between two vectors by using the dot product and I am not familiar with the process involved. This is the best I can come up with ...
dot_product = (cosine_a*cosine_b + sine_a*sine_b)
angle = acos(dot_product)
if (cos(angle > 0) then
rem both balls are heading towards each other
fi
is that right? I cant get the angle returned to tell me if the balls are heading towards each other. this algorithm is far superior in that balls can travel at any speed and this is the only part that I cant understand. all the rest makes perfect sense to me. also this algorithm will always strike the nearest ball at the correct place and time something my own collisions can only achieve through trial and error (and a lot of rewinding)
-
Looks ok but you don't need to change to the angle and back again and i think it should be < 0
dot_product = (cosine_a*cosine_b + sine_a*sine_b)
if (dot_product < 0) then
rem both balls are heading towards each other
fi
-
Her is a good explanation of a dot product:
http://freespace.virgin.net/hugo.elias/routines/r_dot.htm
-
Thanks rdc thats gettin bookmarked really clear and shows how to do it in 3D as well :D
-
Sounds like this project just got a kick in the butt!
Hope all is going well Rain, I'm looking forward to seeing this project complete, your name has 30+ karma written on it haha
:updance: :2funny:
-
Hope it works out like it should and nothin goes against us, I have also been lookin into A.I. routine based on calculating distance and the angle between white ball, colour ball and pocket but I think that kind of thing may be too hard to get workin, but who knows at this stage. thank god there has been a lot of help with this game. Big thanks guys :cheers:
-
AI as in, opponent AI - so you can choose 1 or 2 player?
Well, if that's it, that would be an awesome addition!!!
Cheers
-
I'm not totally certain but I think I've solved it for the way i've been working on the collisions.
The maths is the same as what I'd come up with before except I'm using it on the square root of the vectors now.
Freebasic code:
-
Time to plug it in to the yabasic code and see what it looks like! But the conservation of momentum makes it look hopeful.
Jim
-
I'm having some problems with it like that, but seems ok if I go back to the method of just transferring the velocities along the normal but with the square root of the velocity vectors.
EDIT:
my mistake, works pretty well after all.
-
I've just been thinking about thi rainstorm:
dot_product = (cosine_a*cosine_b + sine_a*sine_b)
angle = acos(dot_product)
if (cos(angle < 0) then
rem both balls are heading towards each other
fi
and it's not quite right, both balls could be traveling in the same direction but at different speeds and still collide so it doesn't quite work out. What you have to do is find the speed of 1 ball relative to the other and then do the dot product with that and the vector between the 2 balls
dot_product=(cosine_b-cosine_a)*(ball_b_x-ball_a_x)+(sine_b-sine_a)*(ball_b_y-ball_a_y)
-
Thanks stonemonkey but I already spotted that I am now working out how to collide balls so that both can be considered in motion (not by moving them one at a time which was the old way I did it) the trick is to translate one of the balls vector against the others vector so that the other ball can be considered stationary (but its motion is still being considered as a subtraction to the moving balls vector) still workin that part out but this is what I have so far for the collisions (only one moving atm) speed of travel is irrelevant and collisions are still accurate : )
controls - move balls vector with up/down/left/right (both controllers)
the red balls are the destinations the unfilled circle is ball a's vector minus ball b's vector
sub distance(px,py, x1,y1, x2,y2)
local dx,dy,clip_line
dx = x2 - x1
dy = y2 - y1
clip_line = ((px-x1)*dx + (py-y1)*dy) / (dx*dx + dy*dy)
closest_point_x = (x1 + clip_line*dx)
closest_point_y = (y1 + clip_line*dy)
dx = px - closest_point_x
dy = py - closest_point_y
return sqrt(dx*dx + dy*dy)
end sub
sub rnd(range)
rnd$ = time$
length = len(rnd$)
local rnd$(length)
static rnd, seed
for l = 1 to length
if (mid$(rnd$,l,1) = "-") then
rnd$ = left$(rnd$,l-1) + " " + right$(rnd$,length-l)
else
rnd$ = left$(rnd$,l-1) + str$(9-val(mid$(rnd$,l,1))) + right$(rnd$,length-l)
fi
next l
seed = ran(rnd)
if (seed < 1) seed = range + 1
random = token(rnd$, rnd$())
for r = 1 to random rnd = val(rnd$(r)) + rnd next
rnd = ran(rnd) / ran(seed)
return range*frac(rnd)
end sub
open window 640, 512
window origin "cc"
ball_radius = 30
sum_radii = ball_radius + ball_radius
balls = 1
dim posx(balls), posy(balls)
dim momx(balls), momy(balls)
dim rotx(balls), roty(balls), rotz(balls)
dim newx(balls), newy(balls)
label start
for a = 0 to balls
0 x = rnd(200) - rnd(200)
y = rnd(200) - rnd(200)
for b = 0 to a
if (a <> b) then
adjacent = posx(b) - x
opposite = posy(b) - y
distance = sqrt(adjacent*adjacent + opposite*opposite)
if (distance <= sum_radii) goto 0
fi
next b
posx(a) = x
posy(a) = y
next a
wait 0.1
label loop
setdispbuf draw
draw = 1 - draw
setdrawbuf draw
clear window
for a = 0 to balls
setrgb 1, 000, 000, 255
fill circle posx(a), posy(a), ball_radius
setrgb 1, 255, 000, 000
fill circle newx(a), newy(a), ball_radius
setrgb 1, 255, 255, 000
line posx(a), posy(a) to newx(a), newy(a)
next a
for a = 0 to balls
posx_a = posx(a)
posy_a = posy(a)
momy_a = momy(a)
rotz_a = rotz(a)
dirx_a = cos(rotz_a)*momy_a
diry_a = sin(rotz_a)*momy_a
newx_a = posx_a + dirx_a
newy_a = posy_a + diry_a
travel = sqrt(dirx_a*dirx_a + diry_a*diry_a)
hyp = travel
for b = 0 to balls
if (a <> b) then
posx_b = posx(b)
posy_b = posy(b)
' find the distance and check if a collision is possible
adjacent = posx_b - posx_a
opposite = posy_b - posy_a
distance = sqrt(adjacent*adjacent + opposite*opposite)
if (travel < distance-sum_radii) goto 1
' check if the balls are heading towards each other
dot_product = dirx_a*adjacent + diry_a*opposite
if (dot_product <= 0) goto 1
' find the closest point along vector to the center of ball
closest = distance(posx_b,posy_b,posx_a,posy_a,newx_a,newy_a)
if (closest > sum_radii) goto 1
nx = closest_point_x
ny = closest_point_y
' find the point at which both surfaces just begin to touch
contact = sqrt(sum_radii*sum_radii - closest*closest)
minx_a = nx - cos(rotz_a)*contact
miny_a = ny - sin(rotz_a)*contact
' check that this is closer than any other collisions
mx = minx_a - posx_a
my = miny_a - posy_a
min_dist = sqrt(mx*mx + my*my)
if (min_dist < hyp) then
newx_a = minx_a
newy_a = miny_a
hyp = min_dist
fi
fi
1 next b
newx(a) = newx_a
newy(a) = newy_a
next a
newx_a = newx(0) - (newx(1) - posx(1))
newy_a = newy(0) - (newy(1) - posy(1))
circle newx_a, newy_a, ball_radius
' controls
p = peek("port1")
if (and(p, 16) <> 0) then momy(0) = momy(0) + 1
elsif (and(p, 32) <> 0) then rotz(0) = rotz(0) + pi/360
elsif (and(p, 64) <> 0) then momy(0) = momy(0) - 1
elsif (and(p, 128) <> 0) then rotz(0) = rotz(0) - pi/360
elsif (and(p,65535) <> 0) then goto start
fi
p = peek("port2")
if (and(p, 16) <> 0) then momy(balls) = momy(balls) + 1
elsif (and(p, 32) <> 0) then rotz(balls) = rotz(balls) + pi/360
elsif (and(p, 64) <> 0) then momy(balls) = momy(balls) - 1
elsif (and(p, 128) <> 0) then rotz(balls) = rotz(balls) - pi/360
elsif (and(p,65535) <> 0) then goto start
fi
goto loop
Edit :
Position the red balls so that they overlap and you can see that the unfilled circle will also overlap the other ball
-
here is a better example nearly have these collisions perfected just that I have to remove the final overlap between both balls. I still dont know why this is happening the distance should have been corrected to bring both balls up to the position where the touch for the first time. Nearly there though ; )
sub distance(px,py, x1,y1, x2,y2)
local dx,dy,clip_line
dx = x2 - x1
dy = y2 - y1
clip_line = ((px-x1)*dx + (py-y1)*dy) / (dx*dx + dy*dy)
closest_point_x = (x1 + clip_line*dx)
closest_point_y = (y1 + clip_line*dy)
dx = px - closest_point_x
dy = py - closest_point_y
return sqrt(dx*dx + dy*dy)
end sub
sub rnd(range)
rnd$ = time$
length = len(rnd$)
local rnd$(length)
static rnd, seed
for l = 1 to length
if (mid$(rnd$,l,1) = "-") then
rnd$ = left$(rnd$,l-1) + " " + right$(rnd$,length-l)
else
rnd$ = left$(rnd$,l-1) + str$(9-val(mid$(rnd$,l,1))) + right$(rnd$,length-l)
fi
next l
seed = ran(rnd)
if (seed < 1) seed = range + 1
random = token(rnd$, rnd$())
for r = 1 to random rnd = val(rnd$(r)) + rnd next
rnd = ran(rnd) / ran(seed)
return range*frac(rnd)
end sub
open window 640, 512
window origin "cc"
ball_radius = 30
sum_radii = ball_radius + ball_radius
balls = 1
dim posx(balls), posy(balls)
dim momx(balls), momy(balls)
dim rotx(balls), roty(balls), rotz(balls)
dim newx(balls), newy(balls)
label start
for a = 0 to balls
0 x = rnd(200) - rnd(200)
y = rnd(200) - rnd(200)
for b = 0 to a
if (a <> b) then
adjacent = posx(b) - x
opposite = posy(b) - y
distance = sqrt(adjacent*adjacent + opposite*opposite)
if (distance <= sum_radii) goto 0
fi
next b
posx(a) = x
posy(a) = y
next a
wait 0.1
label loop
setdispbuf draw
draw = 1 - draw
setdrawbuf draw
clear window
for a = 0 to balls
setrgb 1, 000, 000, 255
fill circle posx(a), posy(a), ball_radius
setrgb 1, 255, 000, 000
fill circle newx(a), newy(a), ball_radius
setrgb 1, 255, 255, 000
line posx(a), posy(a) to newx(a), newy(a)
next a
for a = 0 to balls
posx_a = posx(a)
posy_a = posy(a)
momy_a = momy(a)
rotz_a = rotz(a)
dirxa = cos(rotz_a)*momy_a
dirya = sin(rotz_a)*momy_a
newxa = posx_a + dirxa
newya = posy_a + dirya
travela = sqrt(dirxa*dirxa + dirya*dirya)
hyp = travela
for b = 0 to balls
if (a <> b) then
posx_b = posx(b)
posy_b = posy(b)
momy_b = momy(b)
rotz_b = rotz(b)
dirx_b = cos(rotz_b)*momy_b
diry_b = sin(rotz_b)*momy_b
dirx_a = dirxa - dirx_b
diry_a = dirya - diry_b
newx_a = posx_a + dirx_a
newy_a = posy_a + diry_a
travel_a = sqrt(dirx_a*dirx_a + diry_a*diry_a)
' find the distance and check if a collision is possible
adjacent = posx_b - posx_a
opposite = posy_b - posy_a
distance = sqrt(adjacent*adjacent + opposite*opposite)
if (travel_a < distance-sum_radii) goto 1
' check if the balls are heading towards each other
dot_product = dirx_a*adjacent + diry_a*opposite
if (dot_product <= 0) goto 1
' find the closest point along vector to the center of ball
closest = distance(posx_b,posy_b,posx_a,posy_a,newx_a,newy_a)
if (closest > sum_radii) goto 1
nx = closest_point_x
ny = closest_point_y
' find the point at which both surfaces just begin to touch
contact = sqrt(sum_radii*sum_radii - closest*closest)
minx_a = nx - cos(rotz_a)*contact
miny_a = ny - sin(rotz_a)*contact
' check that this is closer than any other collisions
mx = minx_a - posx_a
my = miny_a - posy_a
min_dist = sqrt(mx*mx + my*my)
if (min_dist < hyp) then
dist = min_dist/travel_a
newxa = posx_a + cos(rotz_a)*momy_a*dist
newya = posy_a + sin(rotz_a)*momy_a*dist
hyp = min_dist
fi
fi
1 next b
newx(a) = newxa
newy(a) = newya
next a
newx_a = newx(0) - (newx(1) - posx(1))
newy_a = newy(0) - (newy(1) - posy(1))
circle newx_a, newy_a, ball_radius
' controls
p = peek("port1")
if (and(p, 16) <> 0) then momy(0) = momy(0) + 1
elsif (and(p, 32) <> 0) then rotz(0) = rotz(0) + pi/360
elsif (and(p, 64) <> 0) then momy(0) = momy(0) - 1
elsif (and(p, 128) <> 0) then rotz(0) = rotz(0) - pi/360
elsif (and(p,65535) <> 0) then goto start
fi
p = peek("port2")
if (and(p, 16) <> 0) then momy(balls) = momy(balls) + 1
elsif (and(p, 32) <> 0) then rotz(balls) = rotz(balls) + pi/360
elsif (and(p, 64) <> 0) then momy(balls) = momy(balls) - 1
elsif (and(p, 128) <> 0) then rotz(balls) = rotz(balls) - pi/360
elsif (and(p,65535) <> 0) then goto start
fi
goto loop
-
I have to abandon the above technique there is a glitch in my interpretation of the algorithm and I simply cannot root it out and it has taken up too much time (I got other proggys on the go including 20 secs compo). It's a major bummer because my own technique will require that the balls all be moved by an amount that is less than the radius where as the above could handle anything (if it were done right) I really can't get it workin so there is no other option left >:(
I feel disappointed but its the best choice, at least things will be moving foward instead of hitting the same brick wall time and again. I think I was a bit too ambitious and the new technique was very much over my head :whack: at least I can understand my own solution if things get buggy
-
I felt a bit like that when I was converting Battlezone to Yabasic sometimes, but I have a feeling that you will crack this problem sooner or later. Remember that it's not always possible to get it right first time, you'll find a way.
-
I've written a full pool game, and you are certanly going about it in the correct way for collision.
Part of the secret to this (and sorry if someone else has talked about it, I've not been through the full thread), is down to slicing the time up.
one way is to break the calculation into very small time spans, recalculate the ball positions, collision check then repeat, this means the balls move in very small steps (so you end up with movements which would be less than the radius). This can then be optimised, because it's only important for the collision part. So, if you can calculate how long it would take for the first collision to take place, you can jump that many slices and continue from there.
While you are working on your 20second intro, I'll see if I can dig out some code/links for you. Afraid it won't be in yabasic, but I can see what I can come up with if it helps.
-
Are the vectors shortened for all moving balls? Such that only one collision happens at a time unless two collisions occur simultaeniously? Also are collisions with the bunkers treated in the same fashion. This is an interesting approach and cleans up the whole bussiness of a ball being overlapped by another ball just because it happened to be too close to the collision (like in the pack) I dont mind that the code isn't Yabasic as long as it is in some form basic I should be able to makeuse of it?
-
yeah, generally consider all collisions as the same, ball-ball and ball-sides.
If something is moving at 10 units per second, you would just consider it as 1 unit per 10th so everything would be divided by 10. It may need a smaller step but you have to balance that against how many calculations you perform. The smaller the step, the less chance of simultanious collisions (which is the perfect situation).
If you do happen to have multiple collisions, I did something like this.
1) Loop through balls finding first collision,
2) resolve that collision
3) go back and loop through the balls from the beginning again.
It can get a bit deadlooped there, which you can usually check for (and for example, ignore something that's already been resolved once).
If you get it working well with these timesteps, you can put in the optimization, which is along the lines of
1) Loop through each ball
2) see if it's possible for this to collide with edges (speed vector line/ edge line intersection), add collision point / distance to a list of collisions
3) compare with all other balls (speed vector line / speed vector line intersection), add collision point / distance to a list of collisions
4) distance between current position and collision position indicates how long it would take for that collision to take place
5) repeat for each ball
6) List of collisions should show which one is first, and therefore how long the step needs to be (instead of the fixed time above)
7) resolve this first collision, and go back to 1 (although this can be optimized to say only recalculate the balls effected in the collision)
This is obviously using lines for simplicity, but it's not too much work to make it a little more fuzzy to include the ball radius.
-
Thanks GrahamK thats sounds solid i think I will do the loop once to detect collisions and just determine which happens first. then once the loop completes start a new loop to update all positions
Well this is what I have to work with, my own solution where only one ball moves at a time movement is limited to less than radius but momentum is conserved and trajectories look good. I will include you're suggestions asap. And thanks for the help really good idea and well explained :cheers:
open window 640, 512
window origin "cc"
holes = 5
dim hx(holes), hy(holes)
data -280,-140, 000,-140, 280,-140
data -280, 140, 000, 140, 280, 140
for a = 0 to holes read hx(a), hy(a) next
colrs = 3
dim red(colrs), grn(colrs), blu(colrs)
data 255,255,255, 255,255,000, 255,000,000, 100,100,100
for a = 0 to colrs read red(a), grn(a), blu(a) next
fric = 0.999
damp = 0.990
bump = 0.900
radi = 10
hradi = radi*1.5
sum_radi = (radi+radi)^2
sum_hradi = hradi^2
minx = -270
miny = -130
maxx = 270
maxy = 130
label setup
balls = 15
redim posx(balls), posy(balls)
redim dirx(balls), diry(balls)
redim colr(balls)
for a = 0 to balls
colr(a) = mod(a,2)+1
dirx(a) = ran(5) - ran(5)
diry(a) = ran(5) - ran(5)
00 posx(a) = ran(200) - ran(200)
posy(a) = ran(100) - ran(100)
for b = 0 to a
if (a <> b) then
adj = posx(b) - posx(a)
opp = posy(b) - posy(a)
hyp = adj^2 + opp^2
if (hyp < sum_radi) goto 00
fi
next
next
colr(0) = 0
colr(balls) = 3
motionless = 0
label main
setdispbuf draw
draw = 1 - draw
setdrawbuf draw
clear window
if (and(peek("port1"),16384) <> 0) goto setup
setrgb 1, 000, 100, 000
fill box minx-radi, miny-radi to maxx+radi, maxy+radi
setrgb 1, 255,255,255
for a = 0 to holes circle hx(a), hy(a), hradi next
for a = 0 to balls
for b = 1.0 to 0.1 step -0.1
setrgb 1, red(colr(a))*(1-b), grn(colr(a))*(1-b), blu(colr(a))*(1-b)
fill circle posx(a), posy(a), radi*b
next
next
if (motionless = balls) goto setup
motionless = 0
for a = 0 to balls
if (dirx(a)^2 + diry(a)^2 > 0.00001) then
dxa = dirx(a)*fric
dya = diry(a)*fric
pxa = posx(a)
pya = posy(a)
for b = a+1 to balls
adj = posx(b) - pxa
opp = posy(b) - pya
dist = adj^2 + opp^2
if (dist < sum_radi) then
dist = sqrt(dist)
nx = adj / dist
ny = opp / dist
cx = (pxa+posx(b))/2
cy = (pya+posy(b))/2
pxa = cx - nx*radi
pya = cy - ny*radi
posx(b) = cx + nx*radi
posy(b) = cy + ny*radi
product = ((dirx(b)-dxa)*nx + (diry(b)-dya)*ny) * damp
sx = nx * product
sy = ny * product
dxa = dxa + sx
dya = dya + sy
dirx(b) = dirx(b) - sx
diry(b) = diry(b) - sy
fi
next
pxa = pxa + dxa
pya = pya + dya
if (pxa < minx) then
pxa = minx
dxa = -dxa*bump
dya = dya*bump
elsif (pxa > maxx) then
pxa = maxx
dxa = -dxa*bump
dya = dya*bump
fi
if (pya < miny) then
pya = miny
dxa = dxa*bump
dya = -dya*bump
elsif (pya > maxy) then
pya = maxy
dxa = dxa*bump
dya = -dya*bump
fi
posx(a) = pxa
posy(a) = pya
dirx(a) = dxa
diry(a) = dya
for b = 0 to holes
adj = pxa - hx(b)
opp = pya - hy(b)
if (adj^2 + opp^2 < sum_hradi) then
for c = a to balls-1
posx(c) = posx(c+1)
posy(c) = posy(c+1)
dirx(c) = dirx(c+1)
diry(c) = diry(c+1)
colr(c) = colr(c+1)
next
balls = balls - 1
fi
next
else motionless = motionless + 1
fi
next
goto main
-
Glad I can be of some help.
I've done a bit of code, I may be able to post it tomorrow.
-
I've made a picture to aid what Graham had to say.
Heres my interpritation.
The red ball has moved a certain amount (say 100 units) from frame 1 to frame 2. a certain amount of time has aslo passed between frame 1 and frame 2 ( t1 + t2 say 0.1s). At somepoint between frame 1 and frame 2 the red ball has hit the black ball.
So in the calculation, you loop through from frame 1 to frame 2 by 1 unit at a time until you find the point the red ball touches the black ball. That means, it takes a total time of t1 before the ball hits the black ball. the remaining time is t2 and thats how long the black ball has to travel before being in the correct place at frame 2,
Heres the pic to go with the text. Its not very accurate, but it shows the principal of what should happen :)
-
Yep, that's about it.
I've managed to get some code working which shows collision response etc. I'll post it later on (In Cobra I'm afraid, but reasonably readable... I'm biased tho ;) )
-
here is a pool game with source in c and ogl. Maybe it can help.
another pool game (http://planetjahn.de/apool/download.php)
-
ok, here you go... Not as well commented as I'd hoped, but I'll try and answer any questions.
I've included an exe and the source here (http://www.squeakyduck.co.uk/downloads/pooldemo.zip) as this won't compile under the demo of cobra.
It's not perfect, as there are a few niggles in the collision response (no comments about sticky balls!), but I hope it helps.
Only thing which isn't described, is that Cobra has a command LineIntersectPt, which takes two lines (4 coordinates) and tells you if they intersect, and where. The other helpful command is pointdistance, which just returns the distance between two points. Other than that, most of the rest should convert reasonably simply.
Main bits of handy code are in Iteration, and ballballcollision.
program
uses pure2d,keyset
const
rad=10
preserve=0.9 // amount of energy preserved after collision
type aball=record
x,y:real
dx,dy:real
col:integer
endtype
type intersect=record
b1,b2:^aball
wall:integer
x,y:real
count:integer=255
endtype
procedure ReDrawScreen
var
ball:^aball
coll:^intersect
begin
////writelog('Redraw')
Rectc(100,50,700,550,ToRGBA(255,255,255),FALSE)
Rectc(100+rad,50+rad,700-rad,550-rad,ToRGBA(100,100,100),FALSE)
loop ball through balls
ellipse(ball.x,ball.y,rad,rad,ball.col,false)
endloop
loop ball through balls
Line(ball.x,ball.y,ball.x+ball.dx,ball.y+ball.dy,ToRGBA(0,255,255))
endloop
loop coll through collisions
Rect(coll.x-4,coll.y-4,9,9,ToRGBA(0,coll.count,0),FALSE)
coll.count = coll.count-1
if coll.count<0 then free(coll)
endloop
end
procedure Init
var
ball:^aball
begin
ball = newitem(balls)
ball.x = Rand(120,680)
ball.y = Rand(70,530)
ball.dx = Rnd(-50,50)
ball.dy = Rnd(-50,50)
ball.col = ToRGBA(255,255,255)
end
procedure CreateBalls(count:integer=10)
var
ball,b2:^aball
ok : boolean
x,y:real
begin
while count >0
ok = false
while not ok
x = Rand(120,680)
y = Rand(70,530)
ok = true
// keep balls apart no overlap
loop b2 through balls
if sqrt((b2.x-x)*(b2.x-x)+(b2.y-y)*(b2.y-y)) < 50 then ok = false
endloop
wend
ball = newitem(balls)
ball.col = ToRGBA(255,0,0)
ball.x=x
ball.y=y
ball.dx = Rnd(-10,10)
ball.dy = Rnd(-10,10)
dec(count)
wend
end
procedure BallWallCollision(b:^aball,wall:integer,cx,cy:real,tstep:real=0.1)
var
cdist,tdist,prop:real
dx,dy:real
begin
// walls are easy as they act purely mirrors, and don't react to the impact
// should really do sphere to plane collision, but too lazy in this version
////writelog('Collision: in ('+b.dx+','+b.dy+')')
// first work out how far into the move the collision occured, needed to calc new position
tdist = Sqrt((b.dx*b.dx)+(b.dy*b.dy))*tstep
dx = cx-b.x
dy = cy-b.y
cdist = Sqrt((dx*dx)+(dy*dy))
if tdist = cdist then
prop = 0
else
prop = 1-(cdist/tdist)
endif
if (wall <2) then // horizontal walls
b.dy=-(b.dy*preserve)
else
b.dx=-(b.dx*preserve)
endif
//writelog('Collision: tdist ('+tdist+') cdist('+cdist+') prop('+(prop)+')')
// reposition ball at collision point, then move it out by amount Left after the collision
b.x = cx + (b.dx * prop)
b.y = cy + (b.dy * prop)
end
procedure BallBallCollision(b1,b2:^aball,substep:real)
var
b1sx,b1sy,b2sx,b2sy,mb1,mb2,mt:real // speeds
vel1,vel2:real
mv,vm,mt2,ep,fac:real;
b1tob2vx,b1tob2vy:real // vector between balls
b1uvectorX,b1uvectory:real // normal speed vector
cosine,mvcosine:real
begin
// calculate ball/ball collision
// Move balls to collision positions,
b1.x = b1.x+(b1.dx*substep)
b1.y = b1.y+(b1.dy*substep)
b2.x = b2.x+(b2.dx*substep)
b2.y = b2.y+(b2.dy*substep)
//calculate the new speeds for both
b1SX = b1.dx
b1Sy =b1.dy
b2SX = b2.dx
b2Sy = b2.dy
vel1 = Sqrt((b1sx*b1sx)+(b1sy*b1sy))
vel2 = Sqrt((b2sx*b2sx)+(b2sy*b2sy))
mb1=vel1
mb2=vel2
mt = mb1+mb2
// subtract second ball speed from first
b1sx = b1sx - b2sx
b1sy = b1sy - b2sy
// calculate magnitude
mv = Sqrt((b1sx*b1sx)+(b1sy*b1sy))
if mv = 0 then mv = 0.00001 // trap for div 0 case
// calculate vector between balls
b1tob2vX = b2.x - b1.x
b1tob2vy = b2.y - b1.y
//normalise vector between balls
vm = Sqrt((b1tob2vx*b1tob2vx)+(b1tob2vy*b1tob2vy))
if vm = 0 then vm = 0.00001
b1tob2vX = b1tob2vx / vm
b1tob2vy = b1tob2vy / vm
// create a normal of the speed vector
b1uvectorX = b1sx / mv
b1uvectory = b1sy / mv
// create dot product
cosine = (b1uvectorx*b1tob2vx)+(b1uvectory*b1tob2vy)
mvcosine = cosine * mv
//multiply interball vector
b1tob2vx=b1tob2vx*mv
b1tob2vy=b1tob2vy*mv
//subtract from speed vector
b1sx = b1sx - b1tob2vx
b1sy = b1sy - b1tob2vy
//add ball 2's speed back to 1
b1sx = b1sx + b2sx
b1sy = b1sy + b2sy
//and add new speed to ball 2's
b2sx = b2sx + b1tob2vx
b2sy = b2sy + b1tob2vy
vel1 = Sqrt((b1sx*b1sx)+(b1sy*b1sy))
Vel2 = Sqrt((b2sx*b2sx)+(b2sy*b2sy))
mt2 = vel1 + vel2
If mt2 <> mt Then
//rescale momentum to correct rounding errors
ep=preserve // amount of energy preserved
fac = ((mt*ep)/mt2)
fac = fac * fac
b1sx = b1sx * fac
b1sy = b1sy * fac
b2sx = b2sx * fac
b2sy = b2sy * fac
// now reset internal vectors
b1.dx = b1sx
b1.dy = b1sy
b2.dx = b2sx
b2.dy = b2sy
end
procedure Iteration(timestep:real=0.1)
var
b1,b2:^aball
x1,x2,y1,y2,dx,dy:real
x1c,x2c,y1c,y2c,dxc,dyc:real
ix,iy:real
coll:boolean
ccount:integer
substep:real
begin
b1 = firstitem(balls)
////writelog('In Collision: ('+b1.dx+','+b1.dy+')')
loop b1 through balls
if ((b1.dx*b1.dx)+(b1.dy*b1.dy)) < 0.0001 then
b1.dx = 0
b1.dy = 0
endif
if (b1.dx<>0) or (b1.dy<>0) then
// only process moving balls
x1 = b1.x
y1 = b1.y
dx = (b1.dx*timestep)
dy = (b1.dy*timestep)
x2 = b1.x+dx
y2 = b1.y+dy
cleartype(b2)
ccount= 0
// check against walls (cheat.. move walls in by radius, takes care of fuzz automatically
coll=LineIntersectPt(x1,y1,x2,y2,100+rad,50+rad,700-rad,50+rad,ix,iy)
if coll then
addintersect(b1,b2,ix,iy,0)
ballwallcollision(b1,0,ix,iy,timestep)
inc(ccount)
else
coll=LineIntersectPt(x1,y1,x2,y2,100+rad,550-rad,700-rad,550-rad,ix,iy)
if coll then
addintersect(b1,b2,ix,iy,1)
ballwallcollision(b1,1,ix,iy,timestep)
inc(ccount)
else
coll=LineIntersectPt(x1,y1,x2,y2,100+rad,50+rad,100+rad,550-rad,ix,iy)
if coll then
addintersect(b1,b2,ix,iy,2)
ballwallcollision(b1,2,ix,iy,timestep)
inc(ccount)
else
coll=LineIntersectPt(x1,y1,x2,y2,700-rad,50+rad,700-rad,550-rad,ix,iy)
if coll then
addintersect(b1,b2,ix,iy,3)
ballwallcollision(b1,3,ix,iy,timestep)
inc(ccount)
endif
endif
endif
endif
if ccount = 0 then // no wall collisions, so we'll step through the other balls looking for collision
loop b2 through balls
if not (b1 = b2) then // don't check collisions with yourself silly!
x1c = b2.x
y1c = b2.y
dxc = (b2.dx*timestep)
dyc = (b2.dy*timestep)
coll = false
// perform a simple 'swept sphere' type calculation (there is better maths, but it should work)
// number of iterations is up to you, the more you do the better the accuracy (I'm doing 30)
substep = 0
while (substep <= timestep) and (not coll)
//if distance between two centers is < 2 x Radius, they've collided.
if PointDistance(x1+(dx*substep),y1+(dy*substep),x1c+(dxc*substep),y1c+(dyc*substep)) < (rad*2) then
coll=true
ix = ((x1+(dx*substep)) + (x1c+(dxc*substep)))/2
iy = ((y1+(dy*substep)) + (y1c+(dyc*substep)))/2
else
substep = substep + (timestep/30)
endif
wend
if coll then
addintersect(b1,b2,ix,iy,3)
BallBallCollision(B1,b2,substep)
endif
endif
endloop
endif
if ccount = 0 then // collision reaction covers movement in case of collisions
b1.x = b1.x+(b1.dx*timestep)
b1.y = b1.y+(b1.dy*timestep)
else
////writelog('Collision: out2 ('+b1.dx+','+b1.dy+')')
endif
endif
endloop
end
procedure AddIntersect(b1,b2:^aball,x,y:real,wall:integer)
var
coll:^intersect
begin
coll = newitem(collisions)
coll.b1 = b1
coll.b2 = b2
coll.wall = wall
coll.x = x
coll.y = y
end
var
balls : list of aball
collisions: list of intersect
ball:^aball
begin
OpenScreen(800,600,32,FALSE,5)
Randomize
init
createballs(10)
while (not keydown(vk_escape)) and (not ExitRequested)
cls
Iteration(0.05)
redrawscreen
flip
wend
closescreen
end
-
Thanks GrahamK I will give it a look through, Well here is the current state of the collisions there doesn't seem to be any bugs in here still keepin the balls speed under 1 radius per frame but to tell you the truth I dont think it needs to be any faster than this. At full speed the pack breaks preatty well and scatters them all around the table.
controls
left/right = aim
down = increase power
up = reduce power
X = shoot
open window 640, 512
window origin "cc"
holes = 5
dim hx(holes), hy(holes)
data -280,-140, 000,-140, 280,-140
data -280, 140, 000, 140, 280, 140
for a = 0 to holes read hx(a), hy(a) next
colrs = 3
dim red(colrs), grn(colrs), blu(colrs)
data 255,255,255, 255,255,000, 255,000,000, 100,100,100
for a = 0 to colrs read red(a), grn(a), blu(a) next
fric = 0.998
damp = 0.991
bump = 0.950
radi = 12
hradi = radi*1.5
sum_radi = (radi+radi)^2
sum_hradi = hradi^2
minx = -270
miny = -130
maxx = 270
maxy = 130
label setup
balls = 15
redim posx(balls), posy(balls)
redim dirx(balls), diry(balls)
redim colr(balls)
restore setup_balls
for a = 0 to balls
colr(a) = mod(a,2)+1
dirx(a) = 0
diry(a) = 0
read posx(a), posy(a)
next
dirx(0) = ran(10)
colr(0) = 0
colr(balls) = 3
motionless = balls+1
label main
setdispbuf draw
draw = 1 - draw
setdrawbuf draw
clear window
setrgb 1, 000, 100, 000
fill box minx-radi, miny-radi to maxx+radi, maxy+radi
setrgb 1, 255,255,255
for a = 0 to holes circle hx(a), hy(a), hradi next
for a = 0 to balls
for b = 1.0 to 0.1 step -0.1
setrgb 1, red(colr(a))*(1-b), grn(colr(a))*(1-b), blu(colr(a))*(1-b)
fill circle posx(a), posy(a), radi*b
next
next
if (motionless > balls) then
ctrl(peek("port1"))
else
force = 0
angle = 0
motionless = 0
collisions()
fi
goto main
sub ctrl(c)
if (and(c, 32) <> 0) then
angle = angle + pi / 4096
elsif (and(c,128) <> 0) then
angle = angle - pi / 4096
fi
if (and(c, 16) <> 0) then
force = force - 0.01
if (force < 0) force = 0
elsif (and(c, 64) <> 0) then
force = force + 0.01
if (force > radi) force = radi
fi
if (and(c,16384) <> 0) then
dirx(0) = cos(angle)*force
diry(0) = sin(angle)*force
motionless = 1
else
x = posx(0)
y = posy(0)
cs = cos(angle)*force
sn = sin(angle)*force
ct = cos(angle+pi/2)
tn = sin(angle+pi/2)
x1 = x - cs*10
y1 = y - sn*10
x2 = x1 - cos(angle)*200
y2 = y1 - sin(angle)*200
setrgb 1, 255, 255, 255
line x,y to x+cs*30,y+sn*30
setrgb 1, 255, 220, 180
fill triangle x1+ct*2,y1+tn*2 to x2+ct*5,y2+tn*5 to x2-ct*5,y2-tn*5
fill triangle x1+ct*2,y1+tn*2 to x1-ct*2,y1-tn*2 to x2-ct*5,y2-tn*5
fi
end sub
sub collisions()
for a = 0 to balls
if (dirx(a)^2 + diry(a)^2 > 0.0001) then
dxa = dirx(a)*fric
dya = diry(a)*fric
pxa = posx(a)
pya = posy(a)
for b = 0 to balls
if (a <> b) then
adj = posx(b) - pxa
opp = posy(b) - pya
dist = adj^2 + opp^2
if (dist < sum_radi) then
dist = sqrt(dist)
nx = adj / dist
ny = opp / dist
cx = (pxa+posx(b))/2
cy = (pya+posy(b))/2
pxa = cx - nx*radi
pya = cy - ny*radi
posx(b) = cx + nx*radi
posy(b) = cy + ny*radi
product = ((dirx(b)-dxa)*nx + (diry(b)-dya)*ny) * damp
sx = nx * product
sy = ny * product
dxa = dxa + sx
dya = dya + sy
dirx(b) = dirx(b) - sx
diry(b) = diry(b) - sy
fi
fi
next
pxa = pxa + dxa
pya = pya + dya
if (pxa < minx) then
pxa = minx
dxa = -dxa*bump
dya = dya*bump
elsif (pxa > maxx) then
pxa = maxx
dxa = -dxa*bump
dya = dya*bump
fi
if (pya < miny) then
pya = miny
dxa = dxa*bump
dya = -dya*bump
elsif (pya > maxy) then
pya = maxy
dxa = dxa*bump
dya = -dya*bump
fi
posx(a) = pxa
posy(a) = pya
dirx(a) = dxa
diry(a) = dya
for b = 0 to holes
adj = pxa - hx(b)
opp = pya - hy(b)
if (adj^2 + opp^2 < sum_hradi) then
col = colr(a)
for c = a to balls-1
posx(c) = posx(c+1)
posy(c) = posy(c+1)
dirx(c) = dirx(c+1)
diry(c) = diry(c+1)
colr(c) = colr(c+1)
next
posx(balls) = pxa
posy(balls) = pya
dirx(balls) = dxa
diry(balls) = dya
colr(balls) = col
balls = balls - 1
fi
next
else motionless = motionless + 1
fi
next
end sub
label setup_balls
data -140,000
data 100,000, 120,010, 140,-20, 120,-10, 140,020
data 160,-30, 160,010, 160,030, 180,000, 160,-10
data 180,-40, 180,-20, 180,040, 180,020, 140,000
-
Very Nice rain!!! :updance:
Is that the final, or just a visual collision simulation?
-
its the collisions only it needs rules better graphics etc. but the mechanics are up and runnin and we are one step closer btw Hows College ?
-
Uni is great! haha. hadn't had too many hard assignments, and my group are flying with our Innovation and Design assignment (we're making a rope bag for water skiing and abseiling and other rope sports haha!)
Staying on campus is a ball! Haha!
Yea, nice. Do you think you'll use the graphics I used?
-
The collisions look like they work really well, I liked the graphics that you had before, I hope you use them in the finished version. The only things that I would suggest are that the balls are too dark, they take forever to slow down, also aiming and adjusting the power should be faster. These are just minor tweaks though, you've accomplished a lot here. It might be one of the toughest projects you'll do for quite a long time too!
-
Yes Clanky the graphics that you developed are going in there but I wanted to get the rules etc in there first. But I think I will work on this first since both of you guys noticed it (which is a very good indicator that the time is right to address it)
Thanks for pointing out the controls and slow down Shocky I had blinded myself to this as I was building it this became unnoticeable but now that you mention it it does take forever for the balls to stop.
-
Seems to be coming along very nicely, looking forward to see the final prod :)
Pool games are great :updance:
-
Just following the spiders earlier and came across this interesting thread. :)
Did a final version ever get released as would love to see it O0
-
Never did finish this but I will have another go at it. I would like to see this completed myself
-
Update, this is the current game engine. Ball spin is not gonna be included because these routines require straight lines. Collisions are time based and I've used swept routines for everything so ball speed is not constrained.
Well that's the theory anyways in practise it still has some minor glitches in the ball / wall collisions. This is as good as its gonna get cause I wrote that routine over a year ago and it was only loosely commented, I have no idea how it works any more.
The graphics are modified from Clankys design but I made the balls and holes larger the reason being that larger balls seem to reduce issues with the the wall collisions.
I just have to merge some game logic which Clanky has already done some work on. Rules and what not.
-
Excellent engine Rain Storm, I find the controls strange, when I pull the cue back and then hit X the cue flies forward and the cue ball just seems to creep forward, maybe I am missing a trick here?
-
if you tap X it works best, the distance the cue is to striking the white ball when you release determines the power of the shot. I wanna use a timer eventually cause pulling back the cue just doesnt feel right. But it is good for debugging.
-
Awesome RS! That looks so sweet.
The collisions are great.. although it seems as though the balls have the tendency to speed up if they bounce and bounce.
Just a few bugs;
When you sink the white ball - it is placed in the 'sunken balls area'. You can still shoot however.. collisions are calculated within the 'sunken balls area' as well.
Scenario: Once you have sunken a ball, sink the white ball. This will place the white ball in the area outside the table. You will still be able too shoot.. aim at the balls which have already been sunken.. these balls will collide and move around.
The cue is 'stuck' on the white ball after you shoot.. maybe the cue could disappear until you want to shoot again.
I'm still playing it : ) soo cooool.
-
Whew!
I could only juggle two balls, when trying my hand at this.
And I almost dropped them, when coming up with the maths
to get this basic pinball!
open window 640,512
ang1=pi/180
ang2=180/pi
ra=30
ball=6
dim dirs(ball),xs(ball),ys(ball),ssp(ball)
dim hitang(ball),hit(ball),reang(ball)
for a=1 to ball
dirs(a)=0
read xs(a),ys(a)
ssp(a)=0
next a
dirm=30
xm=500
ym=100
msp=8
repeat
setdispbuf vm
vm=1-vm
setdrawbuf vm
clear window
setrgb 1,200,200,0
fill rectangle 0,0 to 640,512
for a=1 to ball
setrgb 1,0,256,0
fill circle xs(a),ys(a),ra
setrgb 1,0,0,0
circle xs(a),ys(a),ra
hitang(a)=atan(xs(a)-xm,ym-ys(a))*ang2+180
hit(a)=(abs(xs(a)-xm)^2+abs(ys(a)-ym)^2)^0.5
reang(a)=((dirs(a)+180)-dirm)*2+dirm-180
if hit(a)<ra*2 dirm=reang(a)
dirs(a)=hitang(a)-90
line xs(a),ys(a) to xs(a)+cos(dirs(a)*ang1)*ra,ys(a)+sin(dirs(a)*ang1)*ra
next a
xm=xm+cos(dirm*ang1)*msp
ym=ym+sin(dirm*ang1)*msp
setrgb 1,250,120,0
fill circle xm,ym,ra
setrgb 1,0,0,0
circle xm,ym,ra
if xm<0+ra dirm=270-dirm+270
if xm>640-ra dirm=90-dirm+90
if ym<0+ra dirm=-dirm
if ym>510-ra dirm=180-dirm+180
if dirm>360 dirm=dirm-360
if dirm<0 dirm=dirm+360
until (1=0)
data 252,126,396,126,468,252,396,378,252,378,180,252
-
Wow thats remarkably tight code and those collisions work very well.
abs(xs(a)-xm)^2
^taken from the pythagoras theorum is that faster (in yabasic) than the way its done below
(xs(a)-xm)*(xs(a)-xm)
also this code uses atan to reflect the movement vector about the normal of the collision plane
hitang(a)=atan(xs(a)-xm,ym-ys(a))*ang2+180
...
reang(a)=((dirs(a)+180)-dirm)*2+dirm-180
...
dirm=reang(a)
dirs(a)=hitang(a)-90
...
xm=xm+cos(dirm*ang1)*msp
ym=ym+sin(dirm*ang1)*msp
dirs is the surface normal and dirm = collision plane? Anyway its much tighter than the way I have done this
ed = 1.0 // energy disapated (lost)
...
D = 1 / sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1))
ax = (x2-x1) * D
ay = (y2-y1) * D
va1 = dirX(A)*ax + dirY(A)*ay
vb1 =-dirX(A)*ay + dirY(A)*ax
va2 = dirX(B)*ax + dirY(B)*ay
vb2 =-dirX(B)*ay + dirY(B)*ax
vaP1 = va1 + (1+ed)*(va2-va1) / (1+mass(A)/mass(B))
vaP2 = va2 + (1+ed)*(va1-va2) / (1+mass(B)/mass(A))
vecX(A) = vaP1*ax - vb1*ay
vecY(A) = vaP1*ay + vb1*ax
vecX(B) = vaP2*ax - vb2*ay
vecY(B) = vaP2*ay + vb2*ax
-
Thanks.
I really had to dig deep to remember the maths you see in the code - and the way it's used - from high school (it's been a while!) and with no reference material.
-
http://www.youtube.com/watch?v=CdpR3hU5bAI
^The 3D pool game written for yabasic, most of you will recognise it from youtube. Well here is the source code for that program...
http://canarddechien.blogspot.com/
Problem is it doesn't run, keeps giving parse errors. I've been reading through it to see how it works, but without the ability to edit and run it's not easy to see the inner workings.
Does anyone recognise this syntax cos it doesn't make any sense to me...
if ctnz< nzc="nzc+1" xoff="FOV*ctnx/ctnz"
strings are not "$" termated variable names, also are those supposed to be c like comparisons or is this source code simply erronious.
-
It looks like most of the quotes shouldn't be there at all.
Jim
-
also the speech marks might be brackets ( ... ) that have got jumbled with formatting. if they are at all needed.
-
on a lighter note this game is finished check my first post for the attachment. it turned out to be >38kb. Better late than never. Hope you dont mind the changes I made to your graphics Clanky, I tried to keep them very close to what you had in mind.
Back to the youtube pool. The source code is badly corrupted it is impossible to restore it with so much of the text missing.
pad="peek(">0 then :rem R
should be something more like
pad=peek("port1")
if pad>0 then :rem Read controller only if input <> 0
with more than half of the code already corrupt in a similar fashion to this. I asked him to reupload a working copy to his blog over on youtube just wait and see what comes of it.
-
ps2Yabasic 3D Pool has been corrected by its author Canard De Chien
http://textsnip.com/a87d35
AWESOME