April 21st update: part 2 released
June 15th update: part 3 released
Some days ago I received a very very interesting email from Kevin W. (for Kevin: I can give you more credits if you send me some information about you).
It refers to the Line Rider game creation, with a different approach.
Read carefully:
——
I was reviewing parts three and four of your line rider tutorials today because I had never tried out your collision and reaction techniques for myself, when I found some things I didn’t like.
Mostly, the practice of combining and extracting angles constantly using trig, and therefore the need to compensate for the differences between degrees and radians. I didn’t want to do this because I’ve had a lot of bad luck with my own experiments.
I was reminded of a book on Flash MX game design I saw a few months ago. I remembered the author talking about using vectors exactly for this purpose which eliminates the need for taxing trigonometry functions.
The idea is to keep the x and y speeds separate, and use normalization and scalars to determine the resultant speed.
I think the result is somewhat more efficient and basically keeps track of the ball’s momentum which would lead well into the concepts of sliding required for a sled-based game.
I haven’t yet incorporated your fixes for the ball sticking in the terrain and losing energy, but I would like to know what you think of my approach to this problem.
I hope you take this as gratitude on my part for your tutorials. I started in January of this year using just your blog.
By the way, I am Izy who commented on your posts, the one who made the rocket game with the missile.
—–
Kevin sent a fully commented actionscript too, here it is:
//lineRider_ideas//
//////////////////////////
//Initialize all variables to be used//
//and attach all movieclips.////////////////
//M is the ball, T is the terrain, F is a textfield.
//////////////////////////////////////////////////////////
var m:MovieClip = _root.attachMovie("ball", "ball", 1, {_x:125});
var t:MovieClip = _root.attachMovie("terrain", "terrain", 2, {_x:0});
var f:TextField = _root.createTextField("textfield", 20, 100, 25, 300, 25);
var precision:Number = 1;
var radius:Number = m._height/2;
var sum_x:Number = 0;
var sum_y:Number = 0;
var collisions:Number = 0;
var normal_x:Number = 0;
var normal_y:Number = 0;
var vector_length = 0;
var go:Boolean = true;
//////////////////////////////////////////////////////////
//Create an object to hold speed information and gravity//
//////////////////////////////////////////////////////////
var speed:Object = {x:0, y:0, g:0.25};
/////////////////////////////
//Position certain elements//
/////////////////////////////
m._y = m._height;
t._y = 400;
f.text = "Click and drag to reposition the ball.";
///////////////////////////////
//Allow the ball to be positioned//
///////////////////////////////
_root.onMouseDown = function() {
go = false;
speed.x = 0;
speed.y = 0;
m._x = _root._xmouse;
m._y = _root._ymouse;
m.startDrag();
};
_root.onMouseUp = function() {
m.stopDrag();
go = true;
};
////////////////////////////////
//The main part of the code.////
////////////////////////////////
_root.onEnterFrame = function() {
//Reset variables each frame.
sum_x = 0;
sum_y = 0;
collisions = 0;
if (go) {
//Check for collisions by generating points in a slightly different//
//manner than in your tutorials./////////////////////////////////////
for (var i:Number = 1; i<360; i += precision) {
var angle = (i*precision)*(Math.PI/180);
var spot_x = m._x+radius*(Math.sin(angle));
var spot_y = m._y-radius*(Math.cos(angle));
if (t.hitTest(spot_x, spot_y, true)) {
collisions++;
sum_x += spot_x;
sum_y += spot_y;
}
}
if (collisions>0) {
//Here's the real key to my approach.//////////////
//First, I find the magnitude of the speed vector//
//to use as a scalar.//////////////////////////////
var total_speed = Math.sqrt(Math.pow(speed.x, 2)+Math.pow(speed.y, 2));
spot_x = (sum_x/collisions)-m._x;
spot_y = (sum_y/collisions)-m._y;
//Next, I find the length of a the vector that is the line//
//between the point of collision and the center of the object.//
//This is equal to the radius of the circle and so could be replaced
//by a constant instead.//////////////////////////////////////////////
vector_length = Math.sqrt(spot_x*spot_x+spot_y*spot_y);
//Here I normalize the component of the vector by dividing their magnitude
//by the total length of the two vectors, thereby creating another vector
//with a magnitude of exactly one.///////////////////////////////////////
normal_x = spot_x/vector_length;
normal_y = spot_y/vector_length;
//Finally, I multiply the normalized vector by the scalar to proportionally
//achieve the final speed of the ball./////////////////////////////////////
speed.x += -(normal_x*total_speed);
speed.y += -(normal_y*total_speed);
}
//Add gravity to the speed object and then add the speed to the ball's position.//
speed.y += speed.g;
m._x += speed.x;
m._y += speed.y;
}
};
Then, Kevin fixed another problem… read:
—–
I noticed that if you change the code
speed.x += -(normal_x*total_speed);
speed.y += -(normal_y*total_speed);
to
speed.x = -(normal_x*total_speed)*friction;
speed.y = -(normal_y*total_speed)*friction;
it will behave almost identically to your part four code without the sticking bug.
—–
What to say? First, I want to thank Kevin for this precious feedback… then, I am going to study this code and eventually use it in future updates of this tutorial.
Here it is his working final movie
And this is the source code.
Any comment?