Sonic Maths?
BlitzPlus Forums/BlitzPlus Programming/Sonic Maths?
| ||
Can someone help me with the maths involved in making a game like sonic? I suppose it involves pi and gravity.. Just don't refer to the "sonicblitz" please, I don't get anything of that code... |
| ||
Maybe I should be more specific: I was thinking about the loops in particular... |
| ||
...And the Sonic game I refer to is that of a certain hedgehog... |
| ||
loops ? your going to have to give us more to go on than that. how about you tell us what sort of coding level your at then we can help better, also let us know exactly what it is your asking. Help with loops could be anything . as there will be millions of code iterations in any game. |
| ||
Pretty simple. Increase speed if button pressed (unless at max speed) but only if Sonic is touching 'ground'. Decrease speed if button not pressed (unless at zero speed) or if Sonic is NOT touching 'ground'. Move forward an amount relative to speed (following contour of environment). Apply gravity. Should do it for ya. |
| ||
>>Following contour of environment>> That's the tricky part - in a loop that sonic should run (being upside down and so, with a certain generosity to actual gravity rules though) |
| ||
speed move :;#1 SonicY=(SonicY+1) If ImagesOverlap (TileOfSonic,TileOfGroundY);bla bla, change it SonicY=(TileOfGroundY-TileOfSonic) ;#2 SonicX=(SonicX+SonicSpeed) Select SonicScript Case 0;Sonic doesn't move SonicSpeed=(SonicSpeed-1) If SonicSpeed<0 SonicSpeed=0 case 1;sonic script left SonicSpeed=(SonicSpeed+1) If SonicSpeed>8 SonicSpeed=8 endif |
| ||
What is the issue is not movement across common ground but on the inside of a looping, where he tilts to match the part of the loop-road he is stepping on, pointing head to ground when he is in the very roof of the loop. Can someone help me with the maths to do that? |
| ||
One idea would be to use his speed as a countering force against gravity. So do a linepick from his head towards his feet. Whatever the surface normal is that you hit, apply the countering force in the opposite direction of that normal. If he's going fast enough, that should make him stick to the top of loops and such. As for moving him forward, you'll have to do that same check but probably bust out a cross product to get the "forward" vector in relation to whatever surface he's on at any given moment. |
| ||
The only problem with that is that I assume he's trying to do this in 2d, not 3d. So there's no linepicks or surface normals. You could still do that using the same principal though. If you're using a tile map, just store collision data in the form of a line for each tile. When your character collides with the line, you can get the normal of the line by taking the line vector, diving 1 by it, and switching the sign. Then you can convert the normal into degrees usins Sin() and Cos(). You can then use that angle to draw your character pointing in the right direction. That probably didn't make any sense, so if you want me to explain a little more, I might consider writing a tutorial on doing this. |
| ||
Please do that, that would be very kind of you. You would need to explain even things like normals and tilemaps though. |
| ||
Since this is 2D, the most important thing to learn is pinball physics. If you use a black and white mask and get a ball working on a pinball table, you will have the required physics for use in a sonic game. |
| ||
>>Since this is 2D, the most important thing to learn is pinball physics>> I guess so. Any help on that? I can't help but think it should be quite simple in terms of the code size? |
| ||
The yellow lines are the normals.Graphics 640,480,0,2 For n=0 To 359 Step 10 x=Sin(n)*200+320 y=Cos(n)*200+240 Color 0,255,0 Line x+(Sin(n-90)*15),y+(Cos(n-90)*15),x+(Sin(n+90)*15),y+(Cos(n+90)*15) Color 255,255,0 Line x,y,x+(Sin(n+180)*15),y+(Cos(n+180)*15) Next WaitKey |
| ||
If this is 2D and your play area is larger than a single screen then you'll need tilemaps. Would it be possible to use pre-calculated waypoints (connected using Bezier curves or sin/cos table?)around the inside of the loops and a min speed threshold. If you duck below that speed you branch to a 'start_dropping' function? |
| ||
Tony, that seems like a terrible way of handling the game. Basically you'll need a real basic physics engine that holds your xspeed and yspeed. xspeed increases and decreases as you press left and right if keydown(right) then xspeed=xspeed+1 (where 1 is an acceleration speed) if keydown(left) then xspeed=xspeed-1 xspeed gets dampened by friction xspeed=xspeed*friction (where 1 would be no friction and 0 would make you stop immediately) yspeed always accelerates downwards at the force of gravity yspeed=yspeed+gravity_constant yspeed gets adjusted by height differences upwards that the player has made. if oldy<y then yspeed=yspeed-((currenty-oldy)*lift_constant) Adjust x and y positions based on the x and y speeds x=x+xspeed y=y+yspeed Make sure player hasn't fallen through the ground or through the ceiling and adjust the y accordingly. If you hit the jump key then you make yspeed = -5 (or something similar) and everything will work fine. Anyway... that's how I'd do it. |
| ||
Just knocked this up... it might help a bit...; ======================================================================= ; Basic physics engine Rob Farley 2004 ; ; http://www.mentalillusion.co.uk rob@... ; ======================================================================= Graphics 640,480,0,2 SetBuffer BackBuffer() Dim ground(639) createground() Const keyRht=205 Const keyLft=203 Const keyUp =200 Const KeyDwn=208 Const accel#=0.5 Const friction#=0.9 Const gravity#=0.5 x#=320.0 y#=240.0 oldy#=y xs#=0.0 ys#=0.0 ontheground=False Repeat Cls ; draw ground Color 0,255,0 For n=0 To 639 Plot n,ground(n) Next ; draw player Color 255,255,255 Oval x-5,y-11,11,11,True oldy=y ; get user input If ontheground If KeyDown(keyrht) Then xs=xs+accel If KeyDown(keylft) Then xs=xs-accel If KeyDown(keyup) Then ys=ys-5 ; jump xs=xs*friction ; add friction EndIf x=x+xs ; update x position ys=ys+gravity ; add gravity y=y+ys ; add the y speed to the y position ; wrap x If x>639 Then x=0 If x<0 Then x=639 ; hit the ground If y<ground(x) Then ontheground=False Else ontheground=True ; are you on the ground If y>ground(x) Then y=ground(x):ys=-ys/5 ;bounce If ontheground ; things to deal with when on the ground: If y<oldy Then ys=ys-(oldy-y) ; lift from hills hl#=ground(wrap(x-1,0,639)) hr#=ground(wrap(x+1,0,639)) xs=xs+((hr-hl)/10) ; the /10 reduces the amount of affect the ground has EndIf Flip Until KeyHit(1) ; create the ground ; this just creates a bunch of random places and cosine interpolates between them to create ; a rolling landscale. Function createground() steps#=50 fraction#=640/steps gap#=640/fraction old_random=Rand(0,100) For x#=0 To fraction random=Rand(0,100) For n#=0 To 1 Step .001 Color 0,255,0 xx=Int((x*gap)+(n*gap)) If xx>-1 And xx<640 Then ground(xx)=(cosine_interpolate(old_random,random,n))+300 Next old_random=random Next End Function Function cosine_interpolate#(a#, b#, x#) f#=(1-Cos(x*180))/2 Return a*(1-f)+(b*f) End Function Function wrap(x,low,high) If x<low Then x=x+(high-low) If x>high Then x=x-(high-low) Return x End Function |
| ||
Excellent little snippet you got there Rob.. :) |
| ||
WillKoh: Never look a gift horse in the mouth... ...Unless you're checking for sharp objects that might have an adverse affect on your plans for it later. |
| ||
Btw, you're asking for something really complicated to do right. Hacking it though... Well you could do that. That's what Sega did. What you need to do is detect when Sonic enters a loop, and then switch him to a mode where he'll follow the path of a circle. First you need to know where the center of the loop is. That is Lx#, Ly#. Then you need to know the radius of the loop. That is the distance from the center to the edge. That is R#. The equations then are: X# = Lx# + R#*Cos(A#) Y# = Ly# + R#*Sin(A#) The problem is, what value should you use for A#? X# and Y# are the location to put Sonic at. Now, when Sonic enters the loop, A# will be -90. You will need to increment that value as he goes around. At 0 he will be on the left of the loop, and at 90 he will be at the top of the loop. At 180 he is on the right, and at 270 he exits the loop. But how much should you increment A# by each loop? Well, that depends on two things. One, is Soncic's velocity. That is to say, how far does he move each second? The second is, what is the distance betweem one degree and another on a circle? The answer to that is this: D# = (Pi#/180.0) * R# Where pi is 3.14159265 And where R is the radius of our circle. So now that we know how far sonic will move if he moves one degree on the circle, we can calculate how many degrees we should move him if we want to move him 10 pixels this frame, assuming the radius of our circle is in pixels. So if V# is the number of pixels to move this frame, then A# is: A# = V# / D# So now we know all the variables for our first two equations. Except that you should know that A# here is just an increment for A for the above equations. In other words, add this A to the A from the last frame, using the current velocity of Sonic. I leave the rest as an excerise for the reader. :-) |