Help with trignometry

Started by Babar, Sat 05/08/2006 16:16:18

Previous topic - Next topic

Babar

Heh, no, I'm not trying to get you to do my homework. See, my problem is that I want that when the player clicks with the right mouse button anywhere on the screen, a dart is thrown by the character in that direction, that only stops when it comes to a wall. I used the tangent formula here, but then realised that because of the inverted screen coordinates, every thing is wrong, and I really can't figure out how to fix it.

Code: ags

else {Ã,  Ã, // right-click
Ã,  Ã,  int tan;
Ã,  Ã,  tan=(cEgo.y-mouse.y-20)/(mouse.x-cEgo.x);
Ã,  Ã,  cDart.ChangeRoom(cEgo.Room, cEgo.x, cEgo.y-20);
Ã,  Ã,  cDart.Walk(320, cEgo.y-(tan*(320-cEgo.x)), eNoBlock, eAnywhere);
Ã,  }


In repeatedly execute I've got a chunk of code that checks if cDart is in the room, and if it has reached x=320, then changes cDart's room to -1 (I don't really mind right now that the dart can go off screen from above and below).
The ultimate Professional Amateur

Now, with his very own game: Alien Time Zone

Colxfile

#1
I don't think there's a problem with your trigonometry. The problem is caused by something else.

Because you're using the integer type, the preciseness is lost. This means that, all too often, tan is assigned the value 0, rather than 0.7625 or -0.0097 or whatever it may be. This means that the dart is always going towards the character's y co-ordinate. Use a floating point instead:

Code: ags

Ã,  Ã, else {Ã,  Ã, // right-click
Ã,  Ã,  float tan;
Ã,  Ã,  float dx;
Ã,  Ã,  float dy;
Ã,  Ã,  dx = IntToFloat(mouse.x - cEgo.x);
Ã,  Ã,  dy = IntToFloat((cEgo.y-20) - mouse.y);
Ã,  Ã,  tan = dy / dx;
Ã,  Ã,  // Uncomment the next two lines to see the difference.
Ã,  Ã,  // Display("Float - dx: %f dy: %f tan: %f", dx, dy, tan);
Ã,  Ã,  // Display("Int - dx: %d dy: %d tan: %d", FloatToInt(dx,eRoundNearest), FloatToInt(dy,eRoundNearest), FloatToInt(tan,eRoundNearest));
Ã,  Ã,  cDart.ChangeRoom(cEgo.Room, cEgo.x, cEgo.y - 20);
Ã,  Ã,  cDart.Walk(320, (cEgo.y - 20) - FloatToInt((tan * IntToFloat((320 - cEgo.x))),eRoundNearest), eNoBlock, eAnywhere);
}


Note, I'll go over this, I may need to swap over the mouse and cEgo co-ords to get the difference right.

As for the inverted screen y co-ords, swap the cEgo.y - (tan*320-cEgo.x) for cEgo.y + (tan*320 - cEgo.x).

EDIT: No. I've changed the dx and dy instead.
Also, using this code, right-clicking between the left edge of the screen and cEgo causes the dart to go down instead of up and vice versa.
Also, I've changed the destnation y co-ordinate to [ (cEgo.y - 20) - FloattoInt ...]because, otherwise, the dart lands below the target y coordinate. Going to bed now


Hope that helps.Ã,  :)
Always carry a UV marker pen with you. When you go to a shop or a friend's house, if you see something you like, put your name and postcode on it. If it gets stolen and subsequently recovered, the police will get in touch with you so that they can 'return' it.

Babar

After two years, I'm back at this! I changed it a bit. See, this is what I have in the on_mouse_click event:
Code: ags

if (IsGamePaused() == 1) // Game is paused, so do nothing (ie. don't allow mouse click)
{
}
else
{
	cChar1.ChangeRoom(cCharacter.Room, cCharacter.x, cCharacter.y);
	xmov = IntToFloat(mouse.x-cCharacter.x);
	ymov = IntToFloat(mouse.y-cCharacter.y);
	float dist=Maths.Sqrt((xmov*xmov)+Maths.RaiseToPower(ymov, 2.0));
	xmov=10.0*xmov/dist;
	ymov=10.0*ymov/dist;
}



And this is what I have in repeatedly_exectute:
Code: ags

if (cChar1.Room==cCharacter.Room)
{
	if ((cChar1.x>=640)||(cChar1.x<=0)||(cChar1.y>=480)||(cChar1.y<=0)) cChar1.ChangeRoom(-1);
	cChar1.x=FloatToInt(IntToFloat(cChar1.x)+xmov, eRoundNearest);
	cChar1.y=FloatToInt(IntToFloat(cChar1.y)+ymov, eRoundNearest);
}


It is almost totally perfect, but at some points, it becomes inexact:

The start and the projectile are both characters, so their x and y are calculated from the lower middle, and the mouse x and y is calculated from the centre. However, even taking that into account, it still isn't exact. Is there any way to make it more exact?
Also, out of curiosity, if the sprite is has an even number of horizontal pixels, which one is used to calculate its x and y?

Thanks!
The ultimate Professional Amateur

Now, with his very own game: Alien Time Zone

Akatosh

If I had to guess, I'd say it's probably errors caused by rounding piling up. You might wanna try something like this (untested, but sounds decent in my head):

Code: ags

float realX=IntToFloat(cChar1.X), realY=IntToFloat(cChar1.Y);


Code: ags

if (cChar1.Room==cCharacter.Room)
{
	if ((cChar1.x>=640)||(cChar1.x<=0)||(cChar1.y>=480)||(cChar1.y<=0)) cChar1.ChangeRoom(-1);

        realX+=xmov; 
        realY+=ymov;
	cChar1.x=FloatToInt(realX, eRoundNearest);
	cChar1.y=FloatToInt(realY, eRoundNearest);
}

Khris

As far as I can see, you don't need trigonometry at all (and no floats).

Code: ags
 // on click

  int dx = mouse.x - cCharacter.x;
  int dy = mouse.y - cCharacter.y;

  int dist = Maths.Sqrt(dx*dx + dy*dy);
  if (dist == 0) return;
  dist = 640/dist+1;   // calculate factor

  dx = dx * dist;
  dy = dy * dist;


Now move the dart from the character's position to charpos + (dx;dy).
It should always go through the spot you clicked on.

Babar

#5
Most excellent! Thanks, 'tosher! I didn't even think of doing it like that! Now, as a final request, can someone tell me how to get the sprite height of the mouse or character? I seem to remember there being some command for that, but I'm having trouble finding it in the help file now. If I knew that, I could adjust for the character base y coords without hardcoding the value, and everything would be good!

EDIT:
Hey Khrismuc! You are correct, I don't need trigonometry, the original code is the old code (from 2 years back), and used trigonometry. I changed it up a bit now, but still posted in the same topic as I used before. However, I'm not sure what you did in those last 3 lines. Excuse my stupidity, but could you explain? Is it better than what I did in my own code?
The ultimate Professional Amateur

Now, with his very own game: Alien Time Zone

Khris

Looking at it again, it's exactly as Akatosh says.

beomoud

i'm sorry to bring this up out of nowhere but i used to be good in maths and i have been busting my brains to understand how KhrisMUC came up with dist = 640/dist +1.
You don't have to reply i was just intrigued...

beomoud

nevermind, stupid question, i got it now, sorry for that.  ::)

Khris

In case anyone else is wondering, I don't need the distance after that line again so I reused the var to hold the factor.

beomoud

Can't the same problem be solved using the dot product of the vectors? Maybe we can solve this without resulting to the euclidean rule a = square((b*b) + (c*c)), which could slow down the engine....

monkey0506

Quote from: Babar on Fri 23/01/2009 12:29:45Now, as a final request, can someone tell me how to get the sprite height of the mouse or character? I seem to remember there being some command for that, but I'm having trouble finding it in the help file now. If I knew that, I could adjust for the character base y coords without hardcoding the value, and everything would be good!

It's Game.SpriteHeight and Game.SpriteWidth which are both arrays which use the sprite number as the index.

So:

Code: ags
int mouseHeight, mouseWidth, characterHeight, characterWidth;

int mouseGraphic = mouse.GetModeGraphic(mouse.Mode);
mouseHeight = Game.SpriteHeight[mouseGraphic];
mouseWidth = Game.SpriteWidth[mouseGraphic];
ViewFrame *frame = Game.GetViewFrame(theCharacter.View, theCharacter.Loop, theCharacter.Frame);
characterHeight = Game.SpriteHeight[frame.Graphic];
characterWidth = Game.SpriteWidth[frame.Graphic];

SMF spam blocked by CleanTalk