|
2D bouncing at an angle. SOLVED
#298307
11/13/09 18:16
11/13/09 18:16
|
Joined: Oct 2008
Posts: 67
Crypton
OP
Junior Member
|
OP
Junior Member
Joined: Oct 2008
Posts: 67
|
Basically I'm creating a pong game for learning purposes and I have come to a point where I need to change direction of my "ball". My question is, how could I calculate the angle that ball must bounce off when colliding with the defined edge and with platforms? Right now I have something like this (inside function main): //ball_dir is randomly generated value between 30 and 150.
//Move ball with a direction
ballx += spd*cosv(ball_dir)*time_step;
bally += spd*sinv(ball_dir)*time_step;
//Collision with "walls"
-------------------------------------
if ((ballx > game_minx & ballx+6 < game_maxx)){ //game_minx = 1/3 of screen_size.x and game_maxx = 2/3 screen_size.x
ball_dir = ball_dir; //Keep the direction
}else{//If out of boundaries
ball_dir = (180 - abs(ball_dir)); //Change the direction
}
//Checking collision with platforms!
if (rect_collision(P_ball.pos_x, P_ball.pos_y, P_ball.size_x, P_ball.size_y, P_ai.pos_x, P_ai.pos_y, P_ai.size_x, P_ai.size_y)
| rect_collision(P_ball.pos_x, P_ball.pos_y, P_ball.size_x, P_ball.size_y, P_player.pos_x, P_player.pos_y, P_player.size_x, P_player.size_y)){
ball_dir = (180 - abs(ball_dir)); //Trying to change dir here.
}
But (180 - dir) doesn't always work. I have also searched the internet for vectors to calculate new vector to move on, but I don't know how to implement them in LiteC or is it even practical in this case. Any suggestion solving this?
Last edited by Crypton; 11/18/09 20:29. Reason: solved
New into Gamestudio and eager to learn it.. Stuff and games done in 2D: LINK
|
|
|
Re: 2D bouncing at an angle.
[Re: muffel]
#298338
11/14/09 11:04
11/14/09 11:04
|
Joined: Jan 2003
Posts: 4,615 Cambridge
Joey
Expert
|
Expert
Joined: Jan 2003
Posts: 4,615
Cambridge
|
you have to mirror the colliding direction along the normal. that's simple and works in every dimension, given you're in hilbert space. n normal c colliding vector b bouncing vector b = |<c,n>|*n + (c+|<c,n>|*n) = 2*|<c,n>|*n + c to implement it you only need to know that |<,>| is abs(vec_dot(...)) here and the normal points away from the surface and has length 1 (use vec_normalize). sample: your screen has coordinates x growing from left to right, y from top to bottom. your ball has speed (5,3), the normal of your right screen side is (-1,0). then b is b = 2*|<(5,3),(-1,0)>|*(-1,0) + (5,3) = 2*|5*(-1)+3*0|*(-1,0) + (5,3) = 10*(-1,0) + (5,3) = (-5,3) as expected. another example. your surface normal is angular in the top left, so the normal is something like (3,4)/5 (this is normalized to 1!). your ball has speed (-3,-10), so b is b = 2*|<(3,4)/5,(-3,-10)>|*(3,4)/5 + (-3,-10) = 2*|(-9/5-40/5)|*(3,4)/5 + (-3,-10) = (8.76,5.68) and again the length is preserved, as expected. i hope you get it done now greetings, joey. edit: if you want to use your own variables, not vectors, know that |<a,b>| = abs(ax*bx + ay*by) as i used it in the examples. normalizing surface vectors can also be done by hand, just use n_normalized = n / |<n,n>| = n / ||n||
|
|
|
Re: 2D bouncing at an angle.
[Re: Joey]
#298387
11/14/09 16:17
11/14/09 16:17
|
Joined: Oct 2008
Posts: 67
Crypton
OP
Junior Member
|
OP
Junior Member
Joined: Oct 2008
Posts: 67
|
Thanks! Seems logical enough but still having problems implementing. basically as I can see that formula is calculated by vec_bounce, so i tried to use it. Doesn't work the way it should.. Tried to make VECTOR vBall; definitions for my ball vector but engine started crashing. So I tried with this, seems logical to me. The LiteC version of your given formula: vec_cross(vBall, 2*abs(vec_dot(vBall, vector(1,0,0))), vector(1,0,0));//EDIT: Tried also with if (vBall[1]+6 > game_maxx){ //Right side of the game area var a = 2*abs(vec_dot(vBall, vector(1,0,0))); vBall = vec_scale(vBall, a); vBall = vec_add(vBall, vBall); } as I forgot to add vBall at the end. But still, same effect. Snippet consisting parts with ball: (Collision part is somewhere in the middle of main()
///////////////////////////////
#include <acknex.h>
#include <default.c>
var ball_dir;
var ballx;
var bally;
var vBall[3];
var spd = 20;
var game_start = 0;
var game_minx = 267;
var game_maxx = 533;
PANEL* P_player =
{
//pos_x = 0;
pos_y = 550;
size_x = 100;
size_y = 10;
flags = SHOW | LIGHT;
}
PANEL* P_ai =
{
pos_x = 0;
pos_y = 50;
size_x = 100;
size_y = 10;
flags = SHOW | LIGHT;
}
PANEL* P_ball =
{
pos_x = 0;
pos_y = 0;
size_x = 6;
size_y = 6;
flags = SHOW | LIGHT;
}
function rect_collision(var x1, var y1, var w1, var h1, var x2, var y2, var w2, var h2)
{
if (x1 > (x2 + w2) | (x1 + w1) < x2){return (0);}
if (y1 > (y2 + h2) | (y1 + h1) < y2){return (0);}
return (1);
}
function hcenter_panel(PANEL* panel)
{
panel.pos_x = (screen_size.x - panel.size_x)/2;
//panel.pos_y = (screen_size.y - panel.size_y)/2;
}
function launch_ball()
{
ball_dir = -60; //-random2(30, 150);
vBall = vector(spd*cosv(ball_dir)*time_step, spd*sinv(ball_dir)*time_step, 0);
}
function trace_mouse(PANEL* panel)
{
panel.pos_x = mouse_pos.x-50;
panel.pos_x = clamp(panel.pos_x,game_minx, game_maxx-100);
}
//==============================================================================================
function main()
{
video_mode = 7;
mouse_mode = 4;
random_seed(0);
wait(3);
hcenter_panel(P_player);
hcenter_panel(P_ai);
vec_set(P_ball.blue,vector(0,0,200));
while(1)
{
trace_mouse(P_player); //move platform with the mouse
if (game_start == 0){
//ball is moving with the platform. Works!
vBall[1] = P_player.pos_x + (P_player.size_x/2) - 3;
vBall[2] = P_player.pos_y - P_ball.size_y - 1;
//Hitting a left button launches the ball
if (mouse_left == 1){
launch_ball();
game_start = 1;
}
}else{
//Keep the ball moving. Wroks!
vBall[1] += spd*cosv(ball_dir)*time_step;
vBall[2] += spd*sinv(ball_dir)*time_step;
//Collision with walls! ------------------------------------
if (vBall[1] < game_minx){ //Left side of the game area
vec_cross(vBall, 2*abs(vec_dot(vBall, vector(1,0,0))), vector(1,0,0));
//vec_bounce(vBall, vector(1,0,0));
}
if (vBall[1]+6 > game_maxx){ //Right side of the game area
vec_cross(vBall, 2*abs(vec_dot(vBall, vector(-1,0,0))), vector(-1,0,0));
//vec_bounce(vBall, vector(-1,0,0));
}
if (rect_collision(P_ball.pos_x, P_ball.pos_y, P_ball.size_x, P_ball.size_y, P_ai.pos_x, P_ai.pos_y, P_ai.size_x, P_ai.size_y)
| rect_collision(P_ball.pos_x, P_ball.pos_y, P_ball.size_x, P_ball.size_y, P_player.pos_x, P_player.pos_y, P_player.size_x, P_player.size_y)){
//ball_dir = (180 - abs(ball_dir));
}
//-----------------------------------------------------------
}
//Keep the panel moving along those coordinates
P_ball.pos_x = vBall[1]; //ballx;
P_ball.pos_y = vBall[2]; //bally;
//moving AI Platform.
P_ai.pos_x = P_ball.pos_x - ((P_ai.size_x-P_ball.size_x)/2);
P_ai.pos_x = clamp(P_ai.pos_x,game_minx, game_maxx-100);
draw_line(vector(game_minx,0,0),NULL,100); // move to first corner
draw_line(vector(game_maxx,0,0),vector(0,0,255),100);
draw_line(vector(game_maxx,599,0),vector(0,0,255),100);
draw_line(vector(game_minx,599,0),vector(0,0,255),100);
draw_line(vector(game_minx,0,0),vector(0,0,255),100);
wait(1);
}
}
//==============================================================================================
Looking forward to know what i'm doing wrong.
New into Gamestudio and eager to learn it.. Stuff and games done in 2D: LINK
|
|
|
Re: 2D bouncing at an angle.
[Re: Joey]
#298415
11/14/09 21:19
11/14/09 21:19
|
Joined: Oct 2008
Posts: 67
Crypton
OP
Junior Member
|
OP
Junior Member
Joined: Oct 2008
Posts: 67
|
mm yes I got carried away. Didn't think that LiteC was able to multiply vectors like that and looked depthlessly into cross like a multiplication, just got known about it . My code has changed a lot since my last post. I actually have been able to get the calculation right:
[code]var c[3] = {480, 543, 0};
var n[3] = {-1, 0, 0};
var b[3];
//n = vec_normalize(n,1);
// b = 2*|<c,n>|*n + c Bounce vector's formula.
var a;
function main()
{
video_mode = 7;
wait(3);
a = 2*abs(vec_dot(c, n));
vec_set(b, vector(a*n[0], a*n[1],0));
vec_add(b, c);
}
This is giving me right answers. But Placing it into my pong thing, it won't do the same job.
//Collision with walls! ------------------------------------
if (vBall[0] < game_minx){ //Left side of the game area
// b = 2*|<c,n>|*n + c Bounce vector's formula.
//Into Parts:
//a = 2*|c,n|
//we change (0,0,0) to (a*(-1), a*0, 0) with vec_set
//add (480, 543,0) and (-a, 0, 0)
a = 2*abs(vec_dot(vBall, nvec_minx));
vec_set(vBounce, vector(a*nvec_minx[0], a*nvec_minx[1],0));
vec_add(vBall, vBounce);
}
I personally think my movement code for the ball is messing things up, but I can't see any other way of moving my ball... //Keep the ball moving. vBall[0] += spd*cosv(ball_dir)*time_step; vBall[1] += spd*sinv(ball_dir)*time_step; ...to be more precise. I think that bounce vector is right but I can't make it influence ball's movement.
Last edited by Crypton; 11/14/09 21:35.
New into Gamestudio and eager to learn it.. Stuff and games done in 2D: LINK
|
|
|
Re: 2D bouncing at an angle.
[Re: Joey]
#298446
11/15/09 03:30
11/15/09 03:30
|
Joined: Nov 2009
Posts: 34
Sepiantum
Newbie
|
Newbie
Joined: Nov 2009
Posts: 34
|
|
|
|
|