Graal Forums

Graal Forums (https://forums.graalonline.com/forums/index.php)
-   NPC Scripting (https://forums.graalonline.com/forums/forumdisplay.php?f=8)
-   -   Some angle help (https://forums.graalonline.com/forums/showthread.php?t=77353)

coreys 10-28-2007 10:42 PM

Some angle help
 
I'm working on some fairly basic object physics on Maloria, where hitting an object will make it move. I'm at the part where I need it to kind of bounce off a wall when it collides with it a bit, but I'm having trouble figuring out how I would do that. Here's what I have:
PHP Code:

function onCreated() {
  if (!(
"function_domove" in  this.joinedclasses))
    
join("function_domove");
  
this.moving false;
  
this.canhurt false;
  
this.distgone 0;
  
this.lastpos = {this.xthis.y};
}
function 
onActionHit(damageaccuracyeffectsaccpxpy) {
  
this.dist 0;
  
this.distgone 0;
  
this.speed 0;
  
this.canhurt false;
  
this.angle getangle(px this.xpy this.y);
  if (
this.angle degtorad(180))
    
this.angle -= degtorad(180);
  else 
this.angle += degtorad(180);
  
this += degtorad(int(random(-1011)));
  
temp.friction this.weight damage;
  if (
temp.friction >= 1this.dist 0;
  else 
this.dist .75 temp.friction;
  
this.moving true;
  
this.speed damage/5;
  if (
this.speed 5this.canhurt true;
  
onTimeOut();
}
function 
onTimeOut() {
  if (
this.moving) {
    if (
this.distgone this.dist) {
      
temp.dir getDir(this.lastpos[0]-this.x,this.lastpos[1]-this.y);
      
this.dir temp.dir;
      
this.lastpos = {this.xthis.y};
      
temp.move doMove(this.anglethis.dist/this.speed);
      if (
temp.movethis.distgone += this.dist/this.speed;
      else {
        
//collision stuff here
      
}
      if (
this.canhurt)
        
triggeraction(this.x+1+vecx(temp.dir)*(this.dist/this.speed), this.y+1+vecy(temp.dir)*(temp.dist/this.speed),"Hit",this.dist/2,40);
      
setTimer(0.05);
    }
    else 
this.moving false;
  }


The class function_domove would be Zero's movement system. ("doMove(angle, speed)")...I need it to move "this.dist/this.speed" distance...but the problem if figuring out how to get the angle at which it would bounce off...

Tolnaftate2004 10-28-2007 10:58 PM

I'll assume that anything this object is going to hit will be a horizontal or vertical line.

If it hits a horizontal line, the angle becomes 180-angle.
If it hits a vertical line, the angle becomes -angle.

coreys 10-28-2007 11:02 PM

It's always become a 180 angle when it hits a horizontal line...? o_O
That doesn't seem right...

But also, part of the problem is figuring out if it's hitting a horizontal line or a vertical line...doMove() returns true or false, telling you whether it can move there or no (if it will run into a wall), but the problem is figuring out if it's hitting a horizontal wall or a vertical wall, since the object doesn't just move straight left, right, up, or down, it moves at angles.

Tolnaftate2004 10-28-2007 11:08 PM

180 minus the angle.

Those work for all angles.

coreys 10-28-2007 11:22 PM

Apparently I'm doing something wrong, since doMove() isn't returning false unless it's stuck in a corner, most of the time. And when it returns false properly, moving it at the angle 180 - the original angle doesn't work.

Tolnaftate2004 10-29-2007 12:18 AM

I hope you're not using 180 - this.angle. It should certainly be pi - this.angle. I was hoping to simplify it a bit in my first post, sorry.

coreys 10-29-2007 01:28 AM

I actually used degtorad(180) - this.angle

Tolnaftate2004 10-29-2007 03:15 AM

Strange. You should perhaps split up the movement into vertical and horizontal components and check them individually to see if it's a horizontal or vertical wall.

DustyPorViva 10-29-2007 06:23 AM

Instead of using angles, use a separate velocity for x and y. Then if it hits on the x-axis, invert the x velocity, and same for the y-axis.

coreys 10-30-2007 11:44 PM

Quote:

Originally Posted by Tolnaftate2004 (Post 1355212)
Strange. You should perhaps split up the movement into vertical and horizontal components and check them individually to see if it's a horizontal or vertical wall.

You mean like this.x += bla; this.y += bla;?
I'm not sure how to use that to go at a certain angle D:

Tolnaftate2004 10-31-2007 12:23 AM

Quote:

Originally Posted by coreys (Post 1355506)
You mean like this.x += bla; this.y += bla;?
I'm not sure how to use that to go at a certain angle D:

move_dist*cos(angle) is the x component;
move_dist*sin(angle) is the y component (might need to be negative since (0,0) is the UPPER left corner on a level).

coreys 10-31-2007 01:17 AM

Alright, thanks, but I think there's something wrong with my onwall checks...
PHP Code:

function onCreated() {
  
this.anglex this.angley NULL;
  
this.moving this.canhurt false;
  
this.velocity this.dist this.momentum NULL;
  
this.distgone this.time this.timetotal NULL;
}
function 
onActionHit(damageaccuracyeffectsaccpxpy) {
  
temp.px px+1.5temp.py py+2;
  
this.distgone 0;
  
this.anglex getangle(temp.px-this.x,temp.py-this.y);
  if (
this.anglex degtorad(180))
    
this.anglex -= degtorad(180);
  else 
this.anglex += degtorad(180);
  
this.angley this.anglex;
  
this.velocity = ((damage*4.45)/this.weight)*.05;
  
temp.momentum this.weight this.veolocity;
  if (
temp.momentum 5this.canhurt true;
  else 
this.canhurt false;
  
temp.friction this.weight/damage;
  if (
temp.friction>=1this.dist 0;
  else 
this.dist .75 temp.friction;
  
this.moving true;
  
onTimeOut();
}
function 
onTimeOut() {
  if (
this.moving) {
    if (
this.distgone<this.dist) {
      
temp.dx this.x+(this.velocity*cos(this.anglex));
      
temp.dy this.y+(this.velocity*(-sin(this.angley)));
      if (!
onwall(temp.dx,temp.dy)) {
        
this.temp.dxthis.temp.dy;
        
this.distgone += this.velocity;
      }
      else {
        
temp.bx onwall(temp.dx,this.y);
        
temp.by onwall(this.x,temp.dy);
        if (
temp.bx && temp.by) {
          
this.anglex pi this.anglex;
          
this.angley this.anglex;
        }
        else {
          if (
temp.bxthis.anglex pi this.anglex;
          if (
temp.bythis.angley pi this.angley;
        }
        
//this.velocity = this.velocity/2;
        
this.dist this.dist-this.distgone;
        
this.distgone 0;
      }
      
setTimer(0.05);
    }
  }


They're pretty off...

coreys 10-31-2007 04:32 AM

-bump-
Halp D:

Tolnaftate2004 10-31-2007 06:28 AM

You only need one angle...

coreys 10-31-2007 07:14 AM

Well...I was gonna do that...I actually kinda forgot what forced me to do that, actually...
What would you suggest I do? ._.
What I did there works, except that the onwall checks are off by 1-2 tiles

Tolnaftate2004 10-31-2007 08:57 AM

That's probably an issue with the position of the onwall checks. You need to check from the center of the object outwards, or you'll have it hitting walls about 1 tile too soon when headed up/left, and a tile too late the other directions. But this all also depends on the velocity, as is apparent in your script.

More elegant scripts use a for loop to check more elementary distances (e.g. 1 pixel) and determine if a wall is within 1 "velocity's" range.

DustyPorViva 10-31-2007 06:18 PM

This is what I used when I was messing around with a pong thing:
PHP Code:

this.velocity={random(-1,1),random(-1,1)};
x+=this.velocity[0];
y+=this.velocity[1];
if (
onwall(x+this.velocity[0],y+.5)) this.velocity[0]=this.velocity[0]*-1//Assuming the center is half a tile in
if (onwall(x+.5,y+this.velocity[1])) this.velocity[1]=this.velocity[1]*-1

Of course, this script itself isn't going to work, but you can see where I'm going with it.

coreys 11-03-2007 07:55 PM

I've tried everything I could think of, and I still can't get the onwall checks to be correct:
PHP Code:

function onTimeOut() {
  if (
this.distgone this.dist) {
    
temp.this.x+1temp.this.x+1;
    
temp.dx temp.x+(this.velocity*cos(this.anglex));
    
temp.dy temp.y+(this.velocity*(-sin(this.angley)));
    
temp.dir getdir(temp.dx-temp.xtemp.dy-temp.y);
    if (!
onwall(temp.dx,temp.dy)) {
      
this.+= this.velocity*cos(this.anglex);
      
this.+= this.velocity*(-sin(this.angley));
      
this.distgone += this.velocity;
      
this.velocity = (this.velocity/5)*4;
    }
    else {
      
temp.bx onwall(temp.dx,temp.y);
      
temp.by onwall(temp.x,temp.dy);
      if (
temp.bx && temp.by) {
        
this.anglex pi this.anglex;
        
this.angley this.anglex;
      }
      else {
        if (
temp.bxthis.anglex pi this.anglex;
        if (
temp.bythis.angley pi this.angley;
      }
      
temp.dx this.x+1+(this.velocity*cos(this.anglex));
      
temp.dy this.y+1+(this.velocity*(-sin(this.angley)));
      if (!
onwall(temp.dx,temp.dy)) {
        
this.temp.dx-1;
        
this.temp.dy-1;
        
this.distgone += this.velocity;
      }
      
this.velocity = (this.velocity/5)*3;
    }
    if (
this.velocity <= .005this.dist this.distgone 0;
    else 
setTimer(0.05);
  }


I only have the angles split into x and y because of checking if it's hitting a wall vertically or horizontally. That's the only way I could think of doing it.

This is really starting to frustrate me.

Tolnaftate2004 11-03-2007 09:53 PM

Quote:

Originally Posted by coreys (Post 1356125)
I only have the angles split into x and y because of checking if it's hitting a wall vertically or horizontally. That's the only way I could think of doing it.

This is probably why it's not functioning like you'd want it to. sin() and cos() already split an angle into y- and x-components. So, you only need a single angle.

Here is an example:
PHP Code:

//#CLIENTSIDE
function onCreated() {
  
this.img showimg(2001,"block.png",40,40);
  
this.img.layer 7;
  
this.img.angle pi/8;
  
this.img.velocity 8;
  
this.img.getimgwidth(this.img.image);
  
this.img.getimgheight(this.img.image);
  
onTimeout();
}
function 
onTimeout() {
  
with (this.img) {
    for (
temp.i=0temp.i<this.velocitytemp.i++) {
      if (
abs(screenwidth/2-this.x-cos(this.angle)-this.w/2)<screenwidth/2-this.w/2)
        
this.+= cos(this.angle);
      else 
        
this.angle pi-this.angle;
      if (
abs(screenheight/2-this.y+sin(this.angle)-this.h/2)<screenheight/2-this.h/2)
        
this.-= sin(this.angle);
      else 
        
this.angle = -this.angle;
    }
  }
  
timeout 0.05;



coreys 11-03-2007 10:57 PM

But shouldn't the first onwall (onwall(temp.dx, temp.dy)) still work when it's first hit, then? Because in that case this.anglex and this.angley are exactly the same.

In any case, I just plain ****ed it up...
PHP Code:

function onActionHit(damageaccuracyeffectsaccpxpy) {
  
this.distgone 0;
  
this.angle getangle(px-this.x,py-this.y);
  if (
this.angle degtorad(180))
    
this.angle -= degtorad(180);
  else 
this.angle += degtorad(180);
  
this.velocity = ((damage*4.45)/this.weight)*.05;
  
temp.friction this.weight/damage;
  if (
temp.friction>=1this.dist 0;
  else 
this.dist .75 temp.friction;
  
onTimeOut();
}
function 
onTimeOut() {
  if (
this.distgone this.dist) {
    
temp.this.x+1temp.this.y+1;
    
temp.dx temp.x+(this.velocity*cos(this.angle));
    
temp.dy temp.y+(this.velocity*(-sin(this.angle)));
    if (!
onwall(temp.dxtemp.dy)) {
      
this.temp.dxthis.temp.dy;
      
this.distgone += this.velocity;
      
this.velocity = (this.velocity/5)*4;
    }
    else {
      
temp.bx onwall(temp.bx,temp.y);
      
temp.by onwall(temp.y,temp.by);
      if (
temp.bx && temp.by) {
        if (
this.angle degtorad(180))
          
this.angle -= degtorad(180);
        else 
this.angle += degtorad(180);
      }
      else {
        if (
temp.bxthis.angle pi this.angle;
        if (
temp.bythis.angle = -this.angle;
      }
      
this.velocity = (this.velocity/5)*3;
      
temp.dx temp.x+(this.velocity*cos(this.angle));
      
temp.dy temp.y+(this.velocity*(-sin(this.angle)));
      if (!
onwall(temp.dxtemp.dy)) {
        
this.temp.dxthis.temp.dy;
        
this.distgone += this.velocity;
      }
    }
    if (
this.velocity <= .005this.dist this.distgone 0;
    else 
setTimer(0.05);
  }



coreys 11-03-2007 11:16 PM

(Sorry for double posting)
I changed it to this:
PHP Code:

function onTimeOut() {
  if (
this.distgone this.dist) {
    
temp.this.x+1temp.this.y+1;
    if (!
onwall(temp.x+cos(this.angle)*this.velocitytemp.y))
      
this.+= cos(this.angle)*this.velocity;
    else
      
this.angle pi this.angle;
    if (!
onwall(temp.x,temp.y+(-sin(this.angle))*this.velocity))
      
this.+= -sin(this.angle)*this.velocity;
    else
      
this.angle = -this.angle;
    
this.distgone += this.velocity;
    
this.velocity = (this.velocity/7)*6;
    
setTimer(0.05);
  }


But the onwall checks are still off o.o

coreys 11-04-2007 01:19 AM

Sorry to triple post, but I fixed it. :D


All times are GMT +2. The time now is 03:40 PM.

Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2026, vBulletin Solutions Inc.
Copyright (C) 1998-2019 Toonslab All Rights Reserved.