View Single Post
  #3  
Old 06-23-2012, 03:09 AM
cbk1994 cbk1994 is offline
the fake one
cbk1994's Avatar
Join Date: Mar 2003
Location: San Francisco
Posts: 10,718
cbk1994 has a reputation beyond reputecbk1994 has a reputation beyond reputecbk1994 has a reputation beyond reputecbk1994 has a reputation beyond reputecbk1994 has a reputation beyond reputecbk1994 has a reputation beyond reputecbk1994 has a reputation beyond reputecbk1994 has a reputation beyond reputecbk1994 has a reputation beyond reputecbk1994 has a reputation beyond repute
Send a message via AIM to cbk1994
Typically when I do collision detection for rotating objects, I setup some points along the object where checks will be done. You can use as many of these as necessary, but for this example, I'll stick with just a few.



I'll be using this very simple car script I made as an example in another thread a while back:
PHP Code:
//#CLIENTSIDE
const MAX_SPEED 3;
const 
FRICTION 0.1;
const 
ACCELERATION 1.2;

function 
onCreated() {
  
this.angle = (pi 2);
  
this.trigger("timeOut"); // v6 only
}

function 
onTimeOut() {
  
player.client.freeze true;
  
hideplayer(0.05);
  
  
// turn the car
  
if (keyDown(1)) {
    
// turn left
    
this.angle += 0.1;
  } else if (
keyDown(3)) {
    
// turn right
    
this.angle -= 0.1;
  }
  
  
// accelerate or deccelerate
  
if (keyDown(0)) {
    
// increase speed
    
this.speed min(MAX_SPEEDmax(0.1this.speed ACCELERATION));
  } else {
    
// decrease speed
    
this.speed *= (FRICTION);
  }
  
  
// move the car
  
temp.newX player.cos(this.angle) * this.speed;
  
temp.newY player.sin(this.angle) * this.speed;
  
  
player.temp.newX;
  
player.temp.newY;
  
  
// show car (you should do this in a GANI attribute so you don't have
  // to have this timeout; it'll look smoother for other players too)
  
with (findImg(200)) {
    
image "era_car1_0.png";
    
    
player.x;
    
player.y;
    
    
rotation thiso.angle - (pi 2);
  }
  
  
// reset the timeout
  
this.setTimer(0.05);

To make it easy to visualize what we're doing, I typically setup a function like this for testing:

PHP Code:
function plotPoint(temp.idxtemp.xtemp.y) {
  
with (findImg(temp.idx)) {
    
red green blue 1;
    
layer 3;
    
    
polygon = {
      
temp.0.1temp.0.1,
      
temp.0.1temp.0.1,
      
temp.0.1temp.0.1,
      
temp.0.1temp.0.1
    
};
  }

In my wall check code, I'll add this:
PHP Code:
temp.centerX temp.newX 2;
temp.centerY temp.newY 3.35;

// plot the center of the car
this.plotPoint(200temp.centerXtemp.centerY); 
It's crucial that you have the center point of the car picked. It should remain in the center regardless of the car's rotation.



This looks to be a bit off, but good enough for this example. Mess with it as necessary until it works for you. Now I'm going to establish an array of the points I want to check for walls at, basing them off the car facing up. I'll label the points in the script like so:



All I'm doing is making an array of the x and y offsets for each point when the car is facing up, and then displaying those points.

PHP Code:
// establish the points where we'll check for walls
temp.checks = {
  
// x offset, y offset
  
{- 0.5, - 3.5}, // F1
  
{  0.5, - 3.5}, // F2
  
  
{- 2.0, - 3.0}, // L1
  
{- 2.0, - 1.7}, // L2
  
{- 2.0, - 0.4}, // L3
  
  
{  2.0, - 3.0}, // R1
  
{  2.0, - 1.7}, // R2
  
{  2.0, - 0.4}  // R3
};

temp.0;

for (
temp.check temp.checks) {
  
temp.checkX temp.centerX temp.check[0];
  
temp.checkY temp.centerY temp.check[1];
  
  
this.plotPoint(201 temp.itemp.checkXtemp.checkY);
  
  
temp.++;

This looks good if I have the car facing up, but not when rotated.



We need these points to follow the rotation of the car. Fortunately, this is pretty easy; the math involved is beyond the scope of this answer, but pretty simple. Googling "2d rotation matrix" should get you to what you need, but here's the script:

PHP Code:
temp.checkX temp.centerX + (temp.check[0] * sin(this.angle)) - (temp.check[1] * cos(this.angle));
temp.checkY temp.centerY + (temp.check[0] * cos(this.angle)) + (temp.check[1] * sin(this.angle)); 
Now our check points follow the rotation of the car.



Let's have each check point look for walls and turn red if it detects one:

PHP Code:
if (onwall(temp.checkXtemp.checkY)) {
  
findImg(201 temp.i).green findImg(201 temp.i).blue 0;
} else {
  
findImg(201 temp.i).green findImg(201 temp.i).blue 1;



It's trivial now to prevent movement on walls; I'll leave the collision behavior up to you. Here's the final example script:

PHP Code:
//#CLIENTSIDE
const MAX_SPEED 3;
const 
FRICTION 0.1;
const 
ACCELERATION 1.2;

function 
onCreated() {
  
this.angle = (pi 2);
  
this.trigger("timeOut"); // v6 only
}

function 
onTimeOut() {
  
player.client.freeze true;
  
hideplayer(0.05);
  
  
// turn the car
  
if (keyDown(1)) {
    
// turn left
    
this.angle += 0.1;
  } else if (
keyDown(3)) {
    
// turn right
    
this.angle -= 0.1;
  }
  
  
// accelerate or deccelerate
  
if (keyDown(0)) {
    
// increase speed
    
this.speed min(MAX_SPEEDmax(0.1this.speed ACCELERATION));
  } else {
    
// decrease speed
    
this.speed *= (FRICTION);
  }
  
  
// move the car
  
temp.newX player.cos(this.angle) * this.speed;
  
temp.newY player.sin(this.angle) * this.speed;
  
  
// determine if we can move the car here (are we touching a wall?)
  
temp.centerX temp.newX 2;
  
temp.centerY temp.newY 3.35;
  
  
// plot the center of the car
  
this.plotPoint(200temp.centerXtemp.centerY);
  
  
// establish the points where we'll check for walls
  
temp.checks = {
    
// x offset, y offset
    
{- 0.5, - 3.5}, // F1
    
{  0.5, - 3.5}, // F2
    
    
{- 2.0, - 3.0}, // L1
    
{- 2.0, - 1.7}, // L2
    
{- 2.0, - 0.4}, // L3
    
    
{  2.0, - 3.0}, // R1
    
{  2.0, - 1.7}, // R2
    
{  2.0, - 0.4}  // R3
  
};
  
  
temp.0;
  
temp.foundWall false;
  
  for (
temp.check temp.checks) {
    
temp.checkX temp.centerX + (temp.check[0] * sin(this.angle)) - (temp.check[1] * cos(this.angle));
    
temp.checkY temp.centerY + (temp.check[0] * cos(this.angle)) + (temp.check[1] * sin(this.angle));
    
    
this.plotPoint(201 temp.itemp.checkXtemp.checkY);
    
    if (
onwall(temp.checkXtemp.checkY)) {
      
temp.foundWall true;
      
findImg(201 temp.i).green findImg(201 temp.i).blue 0;
    } else {
      
findImg(201 temp.i).green findImg(201 temp.i).blue 1;
    }
    
    
temp.++;
  }
  
  if (! 
temp.foundWall) {
    
player.temp.newX;
    
player.temp.newY;
  } else {
    
this.speed *= (- 0.7);
  }
  
  
// show car (you should do this in a GANI attribute so you don't have
  // to have this timeout; it'll look smoother for other players too)
  
with (findImg(200)) {
    
image "era_car1_0.png";
    
    
player.x;
    
player.y;
    
    
rotation thiso.angle - (pi 2);
  }
  
  
// reset the timeout
  
this.setTimer(0.05);
}

function 
plotPoint(temp.idxtemp.xtemp.y) {
  
with (findImg(temp.idx)) {
    
red green blue 1;
    
layer 3;
    
    
polygon = {
      
temp.0.1temp.0.1,
      
temp.0.1temp.0.1,
      
temp.0.1temp.0.1,
      
temp.0.1temp.0.1
    
};
  }

__________________
Reply With Quote