Dramatic introduction
Well, I have a tendency to make platformers/overhead games that involve balls (don't ask). And these balls end up moving prety fast. Surprisingly, even though you see this kinda thing all the time on the portal, we still haven't really gotten it down. In mouse games, the cursors fly through the walls, and in platformers, characters glitch out towards the corners all the time. Now after struggling with the stupid problem for like a zillion years, and either not having the ability to solve it or not wanting to invest the time, I finally fixed it.
What is it
It's an overhead engine. It could also work for platformers, if you program in gravity. I'm pretty positive it has no major glitches. The biggest limitation is that it only works for square objects.
What do I need
An object named ball (ideally 25x25) and another object named wall.
The code
var boundary:Array = [];
for (i=0;i<5;i++){
boundary.push(new Point(0,i*(ball.height/5)));
boundary.push(new Point(i*(ball.width/5), 0));
boundary.push(new Point(25, i*(ball.height/5)));
boundary.push(new Point(i*(ball.width/5), 25));
}
//The big idea here is that we want to create an array of points
//that surround the box that we're doing collision detection on.
//Later on, we will cycle through these points with hitTestPoint to
//see if we've hit something.
//This avoids sloppy code later on with 20,000 or statements, and
// makes collision more accurate than just using a few points.
//we have to initialize these values or else they get set to some
//ridiculous number
ball.vx=0;
ball.vy=0;
addEventListener(Event.ENTER_FRAME, enterframe);
function enterframe(e:Event) {
var d=0; //this represents the distance that we know we can travel without hitting anything
//This is a really slick way of dealing with assigning velocities
//since we know true values evaluate to 1
ball.vx +=4*(keys[68]-keys[65]);
ball.vy +=4*(keys[83]-keys[87]);
//This will be either 1 or -1 depending on if we are moving left or right
var sign = ball.vx/Math.abs(ball.vx);
//the big idea here is that we iterate 1 point left or right at a time in the direction of our velocity.
//if we hit, we stop instantly.
while (Math.abs(d)<Math.abs(ball.vx)){
d+=sign;
//iterate through every boundary point to check if we have a collision
//this could theoretically be improved 4x by only checking the points in the direction of the velocity
//but AS3 is fast enough, and the distance between 20 and 5 isn't huge.
for (i=0;i<boundary.length;i++){
if (w.hitTestPoint(boundary[i].x + ball.x+d, boundary[i].y + ball.y, true)){
//if we have a hit
ball.vx=0;
d-=sign;
//stop instantly
break;
}
}
}
ball.x +=d; //add on the distance we know we can travel
//we repeat the process for up/down
d=0;
sign = ball.vy/Math.abs(ball.vy);
while (Math.abs(d)<Math.abs(ball.vy)){
d+=sign;
for (i=0;i<boundary.length;i++){
if (w.hitTestPoint(boundary[i].x + ball.x, boundary[i].y + ball.y +d, true)){
ball.vy=0;
d-=sign;
break;
}
}
}
ball.y +=d;
//this takes care of friction
ball.vx != 0 ? (ball.vx>0 ? ball.vx -= 2 : ball.vx += 2) : null;
ball.vy != 0 ? (ball.vy>0 ? ball.vy -= 2 : ball.vy += 2) : null;
}
//Keypress stuff... if you don't know what this is, look it up somewhere else :P
var keys:Array=new Array(255);
stage.addEventListener(KeyboardEvent.KEY_DOWN, kDown);
stage.addEventListener(KeyboardEvent.KEY_UP, kUp);
for (var i=0; i<256; i++) {
keys[i]=false;
}
function kDown(e:KeyboardEvent) {
keys[e.keyCode]=true;
}
function kUp(e:KeyboardEvent) {
keys[e.keyCode]=false;
}
Feel free to use this in any context, except to sell unmodified. I don't mind if you reference me or not (although it would be cool if you did). I woulda killed for this script maybe 8 years ago, so now I hope I can do all you young aspiring Flash coders a favor :)
Come join music competitions on Chips Compo and hang on our Discord!
Good artists copy. Great artists get banned from the Audio Portal.