Inaccuracies in round (sind)/(cosd). Trajectory help.
Author |
Message |
CobainMcLean
|
Posted: Fri Jan 20, 2012 1:53 pm Post subject: Inaccuracies in round (sind)/(cosd). Trajectory help. |
|
|
Top-Down Trajectory?
Trajectory off? Drawing line using sind and cosd of rotation?
The problem I'm having is, when determining the point where a bullet will go (Represented by the red line), it is terrible inaccurate. You'll notice that I multiply sind (rotation) by 10000. This makes it MUCH more accurate, but is still not the true trajectory.
Everything in the game is based around the max resolution of your screen, could this be causing the problem?
Describe what you have tried to solve this problem
For one, I've asked my Computer Sciences teacher for help. She doesn't seem to know how to fix this problem either...
I've looked into arcsin/arccos, but can't seem to understand if that will help me?
Also, I know that the program is slightly ineffacant. I'm still working on it, and I'm learning. Any tips are GREATLY appreciated.
Thanks in advance for any help.
Turing Version:
4.1
Description: |
|
![](http://compsci.ca/v3/pafiledb/images/icons/clip.gif) Download |
Filename: |
Backuptds.t |
Filesize: |
3.22 KB |
Downloaded: |
92 Time(s) |
|
|
|
|
|
![](images/spacer.gif) |
Sponsor Sponsor
![Sponsor Sponsor](templates/subSilver/images/ranks/stars_rank5.gif)
|
|
![](images/spacer.gif) |
DemonWasp
|
Posted: Fri Jan 20, 2012 2:28 pm Post subject: RE:Inaccuracies in round (sind)/(cosd). Trajectory help. |
|
|
What do you mean by "terrible inaccurate"?
If you mean the fact that it "jitters" when you're aiming upwards, you should look at this bit of code more carefully:
Turing: |
if rotation <= 1 then
rotation := 360
elsif rotation >= 360 then
rotation := 1
end if
|
If you mean that rotation moves in large jumps, rather than smoothly, then that has to do with rotating too quickly. Your main loop runs as fast as it can; you should use Time.DelaySinceLast to keep it at a relatively constant rate. You should also use a separate rotation speed and movement speed (you seem to be using the same one for both).
|
|
|
|
|
![](images/spacer.gif) |
CobainMcLean
|
Posted: Fri Jan 20, 2012 3:00 pm Post subject: Re: Inaccuracies in round (sind)/(cosd). Trajectory help. |
|
|
Oh, yeah. I never thought that jittering was from that. Duh
However, what I mean, is how as you turn (a and d keys) the red line does not stay centred between the "eyes".
I know I could use an image, but I need (and am, as we speak) working on bullets that will follow that red lines path (or use the equasion of it) once fired.
Thanks for pointing out that stupid error.
|
|
|
|
|
![](images/spacer.gif) |
Insectoid
![](http://compsci.ca/v3/uploads/user_avatars/13760332514cbd0ce972eaa.jpg)
|
Posted: Fri Jan 20, 2012 3:18 pm Post subject: RE:Inaccuracies in round (sind)/(cosd). Trajectory help. |
|
|
You're probably experiencing inaccurate float operations. Floats ('reals' in Turing) are only accurate up to a specified number of significant digits. Since this is a hardware limitation, the only solution is to not use floats (you saw increased accuracy by multiplying by 10000- this increases the accuracy of the value by reducing decimal places).
Then again, I didn't read your code so I might be completely wrong.
|
|
|
|
|
![](images/spacer.gif) |
Dreadnought
|
Posted: Fri Jan 20, 2012 3:29 pm Post subject: Re: Inaccuracies in round (sind)/(cosd). Trajectory help. |
|
|
First, you need to understand what the sine and cosine of an angle are. In a right angle triangle, the sine of an angle is the length of the side opposite the angle over the length of the hypotenuse. The cosine is the length of the side adjacent the angle over the hypotenuse.
This means that given the angle, you can compute the length of the two sides like so.
opposite = sin(angle) * hypotenuse
adjacent = cos(angle) * hypotenuse
Now let's see what you're doing.
I don't know why you use floor for one and ceil for the other but that's not important. What is different in your code from the formulas I wrote?
The hypotenuse doesn't change length. However, Pic.Width(Level) and Pic.Height(Level) are two different lengths. So you're finding the sides of two different triangles.
That will fix part of the problem.
The other part of the problem, is that you've found the lengths in x and y of the triangle formed by the line of fire of the bullet. However, you forgot to take into account the position of the player on the screen. So the line will change orientation from simple translations of the object, when it should only change from rotation.
So in the end I hope that you see that, in fact, it is not the sin and cos functions causing you trouble.
Hope this helps.
|
|
|
|
|
![](images/spacer.gif) |
DemonWasp
|
Posted: Fri Jan 20, 2012 4:14 pm Post subject: RE:Inaccuracies in round (sind)/(cosd). Trajectory help. |
|
|
Dreadnought makes a few good points (edit: I should read more carefully--he actually highlights all of the following. Still, I typed it up, and I won't un-type it). I took another look and you've got several different bugs in that Draw.Line call.
First, your (x2,y2) coordinates in that Draw.Line are wrong. Specifically, your first coordinates (x1,y1) are for the center of your object. Your second coordinates (x2,y2) are for the point several thousand units in the direction your object is facing measured from (0,0), instead of from your object. Try this thought experiment: if your object is at (100,0) and looks straight down, should he be looking at (0, large_number_here) or (100, large_number_here)?
Second, you should put your multiply-by-distance inside your floor() or round() or ceil() call. All of those calls will lose some of the precision available, so do that as late as possible (in particular, try to do any multiplication--especially by numbers above 1--before you cut out the precision). This is why multiplying by 10000 inside the floor() call "improves" accuracy: you are keeping more digits around, so the result seems more accurate.
Third, you should not be multiplying by the width or height of the level. That will produce a kind of ellipsoid (oval) shape instead of the circle you're hoping for.
This snippet works better:
Turing: |
var x : int := round (Px + Pic.Width (PlayerImage (2)) / 2) % These are exactly what you had already
var y : int := round (Py + Pic.Width (PlayerImage (2)) / 2)
Draw.Line (
x,
y,
x + round (cosd (rotation + 90) * 100 ), % Note that we add to the coordinates of your object to produce a location relative to it
y + round (sind (rotation + 90) * 100 ), % Note that the multiplication by the distance (100) is inside the round() operation.
brightred
)
Time.DelaySinceLast(100) % If you slow things down, they will be easier to debug. This limits you to drawing and updating 10 times per second (once every 100 milliseconds).
|
|
|
|
|
|
![](images/spacer.gif) |
CobainMcLean
|
Posted: Sun Jan 22, 2012 6:05 pm Post subject: Re: Inaccuracies in round (sind)/(cosd). Trajectory help. |
|
|
Alright, I see what I'm doing wrong.
The x2 and y2 of the line where off by half of the player image. As both Dreadnought and DemonWasp pointed out.
So, using the snippet of code offered by DemonWasp, the line works almost perfectly.
Thanks a bunch guys!
Now, I'm having another problem... Now with creating the bullets.
I have a type which holds a record of X, Y, Xup and Yup. These are the locations of the bullets, and then how much it goes up in the X, and Y axis.
I then declare a new variable of that record type,as a flexible array.
code: |
type Bullet :
record
X, Y, Type, Xup, Yup : int
end record
var Bullets : flexible array 1 .. 0 of Bullet
new Bulllets, upper (Bullets) + 1 % Thinking it was because upper of bullets < 1 I added this. I've also tried without.
procedure BulletLogic (New : boolean)
if New = true and Rate <= 0 then
Rate := 5
new Bullets, upper (Bullets) + 1
Bullets (upper(Bullets)).X := round (Px)
Bullets (upper(Bullets)).Y := round (Py)
Bullets (upper(Bullets)).Xup := round (cosd (rotation) / Pic.Width (Level))
Bullets (upper(Bullets)).Yup := round (sind (rotation) / Pic.Width (Level))
end if
for X : 1 .. upper (Bullets)
Draw.Dot (Bullets(X).X, Bullets(X).Y, green)
end for
Rate -= 1
end BulletLogic
|
The problem I'm having, is when it gets to the for loop, the upper command seems to call back that Bullets is out of range.
So, I tried simply using :
put upper (Bullets)
And that gives me a segmentation error.
It seems ANYTHING I do to the Bullets array bring up a segmentation error (IE: Drawing Dots in a for statement).
I guess this has something to do with too much memory being used, or rather trying to use memory that doesn't exist?
Is it that I'm going about this wrong, or am making a mistake, or does my program just have another blind mistake?
|
|
|
|
|
![](images/spacer.gif) |
Dreadnought
|
Posted: Sun Jan 22, 2012 11:02 pm Post subject: Re: Inaccuracies in round (sind)/(cosd). Trajectory help. |
|
|
Well, this line, at the start of the program, should not be there I think Turing: | new Bulllets, upper (Bullets ) + 1 |
It create an entry on the array with values that you never set.
Other than that and a typo (bulllet with 3 L's) I couldn't reproduce your segmentation errors.
Here's the code I used to try it out.
Turing: | type Bullet :
record
X, Y, Type, Xup, Yup : int
end record
var Bullets : flexible array 1 .. 0 of Bullet
var Rate : int := - 1
var Px : int := 0
var Py : int := 0
var rotation : int := 90
procedure BulletLogic (New : boolean)
if New = true and Rate <= 0 then
Rate := 5
new Bullets, upper (Bullets ) + 1
Bullets (upper (Bullets )).X := round (Px )
Bullets (upper (Bullets )).Y := round (Py )
Bullets (upper (Bullets )).Xup := round (cosd (rotation ) / maxx)
Bullets (upper (Bullets )).Yup := round (sind (rotation ) / maxx)
end if
for X : 1 .. upper (Bullets )
Draw.Oval (Bullets (X ).X, Bullets (X ).Y, 20, 20, green) % Ovals are bigger
end for
Rate - = 1
end BulletLogic
var mousebutton: int % I never use this other than for the mouse
loop
Mouse.Where (Px, Py, mousebutton ) % I'm drawing the bullets at the mouse
locate (1, 1)
put "number of bullets: ", upper (Bullets )
BulletLogic (true)
Time.DelaySinceLast (50)
end loop |
So Bullet Logic may not be the cause of your segmentation error. I do remember getting segmentation errors when trying to use flexible arrays with functions in some weird way (I think I was using forward declaration, but I'm not sure). After the trouble I've had with flexible arrays I tend to stay away from them, but they can be very useful. Perhaps if you post more code we can find the problem.
|
|
|
|
|
![](images/spacer.gif) |
Sponsor Sponsor
![Sponsor Sponsor](templates/subSilver/images/ranks/stars_rank5.gif)
|
|
![](images/spacer.gif) |
CobainMcLean
|
Posted: Mon Jan 23, 2012 7:57 am Post subject: RE:Inaccuracies in round (sind)/(cosd). Trajectory help. |
|
|
Thanks for that, Dreadnought, but It must have something to do with the rest of the program, as I still get the error. :/ When I'm not getting an "Array dimension passed to upper is out of range." error, it's a segmentation error.
Time to do some re-thinking.
Anyways, I'll post what I have later on today, during Computer Sciences class.
|
|
|
|
|
![](images/spacer.gif) |
CobainMcLean
|
Posted: Mon Jan 23, 2012 10:05 am Post subject: Re: Inaccuracies in round (sind)/(cosd). Trajectory help. |
|
|
Okay, so here's the updated code.
I commented on the things I've tried, which you'll see in the BulletLogic procedure.
Sorry if anything I'm trying to point out is confusing.
Description: |
|
![](http://compsci.ca/v3/pafiledb/images/icons/clip.gif) Download |
Filename: |
TDS2.t |
Filesize: |
4.51 KB |
Downloaded: |
78 Time(s) |
|
|
|
|
|
![](images/spacer.gif) |
Dreadnought
|
Posted: Mon Jan 23, 2012 1:13 pm Post subject: Re: Inaccuracies in round (sind)/(cosd). Trajectory help. |
|
|
I had had problems from nearly the same thing before. I never knew what the problem was, but today I figured it out.
Here's some code I wrote that will show the problem.
Turing: | % We declare a second procedure that calls the first one in some way
proc CallAccessArray
AccessArray
end CallAccessArray
% Will Produce an error since TestArray has not been declared yet and is thus not in range
CallAccessArray
var TestArray : flexible array 1 .. 0 of int % We declare a global flexible array
% Will run properly snce the flexible array has been declared and is thus in range
CallAccessArray
/* We give the frst procedure a body
Note that we do this after declaring the global flexible array
so that the arra is in range (can be accessed)
*/
body proc AccessArray
% This just creates a counter everytime you hit a key, nothing fancy
loop
cls
if hasch then
new TestArray, upper (TestArray ) + 1
TestArray (upper (TestArray )) := 0
end if
for i : 1 .. upper (TestArray )
TestArray (i ) + = 1
put TestArray (i )
end for
Input.Flush
Time.DelaySinceLast (100)
end loop
end AccessArray
% Will aso run properly
CallAccessArray |
This problem is very subtle. One would think that as long as the body of the procedure that accesses the array is declared after the flexible array is declared, everything will work. But we must think about how things will run. Variable declaration actually happens when the program gets to the line of code that declares it. And so if we call a procedure that wants to use this variable before we declare it then the variable is out of range. Normally this would be obvious, but because of the particular way in which we declared and called our procedures and our array, we have made things out of range.
Note, segmentation errors occur when you try to access an index of a flexible array that does not exist. So when you forced your for loop to run once, it tried to read the first element in an empty array.
In your case, you simply have to declare your flexible array before you call the Load procedure.
Good luck.
|
|
|
|
|
![](images/spacer.gif) |
CobainMcLean
|
Posted: Mon Jan 23, 2012 2:19 pm Post subject: RE:Inaccuracies in round (sind)/(cosd). Trajectory help. |
|
|
Oh! I see what was wrong.
As the program would execute the Load procedure, it would skip the code before it, which is where my flexible array was declared.
So, it never really made the array?
Then, it'd skip to Update, then work it's way up to BulletLogic, where it would try to access the array that was never created.
You're a life saver! Thank you so much.
Once I build up some bits + Karma, I'll be sure to Applaud you.
Thanks again.
|
|
|
|
|
![](images/spacer.gif) |
Dreadnought
|
Posted: Mon Jan 23, 2012 2:38 pm Post subject: Re: Inaccuracies in round (sind)/(cosd). Trajectory help. |
|
|
No problem, I actually forgot the forward statement line at the top of my example code, but you got the point.
This was actually, a problem I had run into a while back, but I was never able to fix it, so I change the whole structure of the code. I forgot what I had done to produce the errors. So it was nice to see it again and be able to figure out the problem.
|
|
|
|
|
![](images/spacer.gif) |
|
|