Adding zero to an int variable results in weird number - javascript

I'm having a problem with what should be simple additon in Javascript.
Take a look at this firebug output:
What I'm making is a 2D tile map in canvas, and for objects in the map that are greater than one tile in size, they have their width and height set to negative numbers, to tell me how many tiles offset in x/y they are to get to the tile with the relevant data.
This works fine for all cases, except when adding zero to a number. This results in strange numbers.
In the image above, there are two click events fired, each starting with "clicking on X x Y" and ending with "modified x/y into X Y". As you can see, clicking on a tile with a -3 for the Y offset works fine, but clicking on a tile with 0 for the Y offset results in 247!??? I've been going over and over this without getting any closer to an answer. All data seems fine, right up to the point when I try and add 0 to the variable y. If that wasn't weird enough, adding zero to the x variable works fine!
Here's the snippet of code that outputs the debug messages and causes the error. x and y are parameters to a function call, and cityMap is a global 3D array.
if (cityMap[x][y]['typeID']<0)
{
// get deffered tile pos
console.debug("Offset x = "+cityMap[x][y]['width']);
console.debug("Offset y = "+cityMap[x][y]['height']);
x += parseInt(cityMap[x][y]['width'], 10);
y += parseInt(cityMap[x][y]['height'], 10);
console.debug("modified x/y into x:"+x+" y:"+y);
}
I'm completely lost for ideas here. Does anyone know what else I can try to stop Javascript doing this?

+1 For all those developers that solve their own questions! I got this one, but I read then your comment so the answer is yours and I'm not writing it down.

Related

Dealing with the inverted Y axis while graphing in Javascript?

I am using Javascripts built in canvas feature to draw a graph showing home loan payments, loan balance, and equity based on user input. I am not able to use any other form of graphing package, as the code is part of an assessment.
My graph is drawn by converting data to X and Y coordinates. When a loan price is input, some home loan payment equations calculate the total amount payed, which is divided by the canvas width to get a spacing variable. This spacing variable is used to convert dollar amounts into pixels on the canvas. A similar setup is used to get the years and months spacing pixels.
The problem I am having is that the Y axis on Javascript's canvas is inverted, with 0 being the top of the canvas and 280, my canvas height, being at the bottom. So far, I have been able to work around this, simply by swapping "+" and "-" operators, however, I am currently creating the code that draws the Loan Balance line on the graph, and the inversion is causing issues that I can't seem to solve. It may be something simple that I'm just not seeing, or it may be a more complex problem that needs to be solved, but either way, I can't figure it out.
X = 0; // same as before, iterators both set back to 0 for the new line.
iterator = 0;
c.beginPath // this next line is for loan balance, it starts at 300000 and goes down with each payment made, then back up with each bit of interest accrued.
// due to the fact that the y axis begins at the top, this means that the pixels for payments is added to the pixel count, and the interest accrued is taken away.
c.moveTo(0, loanLocation) // set starting point to x=0 y= loanLocation
while (X <= 510)// loan balance loop
{
X = X + 0.001; // iterates X by .001 each time, allowing an accurate subpixel resolution loop, see above for why this is needed.
iterator = iterator + 0.001;
if (iterator >= monthSpacing)
{
loanBalance = loanBalance - monthlyPayment + (monthlyInterest * loanBalance);
//alert(loanBalance);
//interestY =
//alert(interestY);
//alert(X + " " + monthSpacing);
loanY = loanY + paymentY - (loanY * monthlyInterest);
//alert(loanY);
//loanY = loanBalance * paySpacing;
c.lineTo(X, loanY);
iterator = 0;
}
}
c.strokeStyle = "black"
c.stroke(); // there is no fill for this line, so it is just left as a stroke.
This is the set of code which draws the line, above it are a few variables which are being used here:
var X = 0;
var iterator = 0;
var monthSpacing = yearSpacing / 12;
//alert(yearSpacing);
//alert(monthSpacing);
var monthlyInterest = interest/1200; // this gives the montly interest rate, the monthly interest pixel amount is below
//alert(monthlyInterest);//debugging, comment out.
var paymentY = monthlyPayment * paySpacing;
var interestY = monthlyInterest * paySpacing; // this is inaccurate, the interestY needs to be gotten by multiplying the remaining loan balance by the
//monthly interest each month.
//var interestY; // will be used further down, must be calculated monthly so cannot be set outside of the line drawing loops.
var totalY = 280;
var equityY = 280;
var loanBalance = loan;
var loanY = loanLocation;
When run I get a strange inversion of the desired outcome, I want the loan balance line to curve down towards zero, but instead, the curve is happening in the opposite direction, I have tried two different ways to get the coordinates, the loanBalance way, which involved working with dollar values and converting that to pixels, and the loanY way, which involved working with pixel values directly.
loanBalance provided a line which was the exact inverse of the desired line, it began at the loan value, and curved upwards in the exact opposite direction to what I want, I am confident that the math I'm using for the loanBalance method is accurate, I simply cannot think of a way to convert that dollar value into pixels due to the inverted nature of the Y axis.
loanY provides a line which is headed "down", but is curving downwards at an increasingly shortened rate, this leads me to believe that while the subtraction (addition due to the inversion) of monthly repayments is accurately being calculated, the addition (subtraction) of monthly interest is being calculated incorrectly. Multiplication cannot be simply replaced with division like addition and subtraction can, so converting this value to pixels is proving difficult. The line drawn by the loanY way is definitely being affected by the inversion, but is not a perfect inverse of the desired line, the math being used for that way is clearly very wrong.
Ideally, I'd like to find a way to use the loanY way, it is consistent with the rest of the program, and can be used when not working with such obvious values as dollars. If I have to though, I will use the loanBalance way.
If you aren't entirely certain what I'm asking, or what the code being used is, I can post the program in it's entirety if that would help. I've not done that yet as I don't want to clutter the question more than I already have.
You can change to a Cartesian coordinate system like this:
// get a reference to your canvas element (eg it might have id='myCanvas')
var canvas=document.getElementById('myCanvas');
// get the context for the canvas
var context=canvas.getContext('2d');
// vertically flip the canvas so its Y origin is at the bottom
context.setTransform(1,0,0,-1,0,canvas.height);
This makes y==0 at the bottom of the canvas and increases upward.
If you're using other transformations, then put this transformation before the others.

How do I check my condition on an if statement to see if it is working correctly?

I'm trying to make a type of circular display which cycles through a series of values as well as moving text elements within an svg file. It uses the hammer.js library and uses the drag event. The values can go in either direction. I have it working to some degree. As the last value is shown from an array, it goes back to the beginning of the array to get the first values. Or vice-versa.
var keyArray = ["C","C#","Db","D","D#","Eb","E","F","F#","Gb","G","G#","Ab","A","A#","Bb","B"];
This is my array. Here is how I wrap it past the end of the array and back to the beginning.
** As per the request of a few commenters and the suggested solution by Nina, I have modified the code below to reflect their suggestions. I have also added a few more lines for clarity of what is happening overall.**
var delta = keyArray.length - 5; // can be constant, it is always positive
for(i=0;i<5;i++){
//5 svg text element containing 5 musical keys
keys = document.getElementById("keys"+i);
//ev.deltaX is the change received from the hammer pan event
//text element moves relative to its original starting X
keys.setAttribute("x",startingSpots[i]+ev.deltaX%150);
currentX=keys.getAttribute("x");
currentEdgeIndex=keyArray.indexOf(keys.textContent);
//This if is what appears to be failing.
if (keys.getAttribute("x")>=565){
keys.setAttribute("x",currentX-150);
keys.textContent = keyArray[(currentEdgeIndex + delta) % keyArray.length];
}
}
With the suggested changes, I removed the Number() calls as well as implementing the modulus for the wrapper. The behavior is still erratic. On the example below, if you pan to the right, as the first text element reaches 565, it meets the condition for the if, is moved back to the left by 150.
What it should do next is to change the textContent to the next appropriate value in the array. However, this is where it becomes erratic, it is no longer past 565 so it does not meet the condition of the if statement, but the text changes at every increment of the pan event as if it were.
I am sure I am not seeing something simple that is causing the trouble but not sure what it is.
The array does appear to be circling correctly, though I'm still not sure "How can I check to see if the if statement is being correctly evaluated and met?"
The project can be viewed here. http://codepen.io/cmgdesignstudios/pen/zrmQaE?editors=1010
* Edit with solution *
Nina suggested the problem lie in the handling of the touch event. After further investigation, I found she was correct. I had originally been moving the object relative to its starting position and the deltaX from the touch event. I then was trying to change the current position by simply moving it back to the left rather than adjusting the starting position.
So I replaced the
keys.setAttribute("x",currentX-150);
with
startingSpots[i]-=150;
This kept the movement relative to the starting position and the deltaX of the touch event.
Please delete the Number(...) casting where it's not necessary. ...length returns always number and the result of calculation is a number too.
Your actual key feature is to move 5 entries down, and this can be achieved wit a simple addition and a modulo, to keep the value in a specific range, like
keys.textContent = keyArray[(keyArray.length + currentEdgeIndex - 5) % keyArray.length];
Further simplified can this calculation then lead to just add a positive number of
delta = keyArray.length - 5; // can be constant, it is always positive
keys.textContent = keyArray[(currentEdgeIndex + delta) % keyArray.length];
and make the modulo out of it.

What is the math behind this ray-like animation?

I have unobfuscated and simplified this animation into a jsfiddle available here. Nevertheless, I still don't quite understand the math behind it.
Does someone have any insight explaining the animation?
Your fiddle link wasn't working for me due to a missing interval speed, should be using getElementById too (just because it works in Internet Explorer doesn't make it cross-browser).
Here, I forked it, use this one instead:
http://jsfiddle.net/spechackers/hJhCz/
I have also cleaned up the code in your first link:
<pre id="p">
<script type="text/javascript">
var charMap=['p','.'];
var n=0;
function myInterval()
{
n+=7;//this is the amount of screen to "scroll" per interval
var outString="";
//this loop will execute exactly 4096 times. Once for each character we will be working with.
//Our display screen will consist of 32 lines or rows and 128 characters on each line
for(var i=64; i>0; i-=1/64)
{
//Note mod operations can result in numbers like 1.984375 if working with non-integer numbers like we currently are
var mod2=i%2;
if(mod2==0)
{
outString+="\n";
}else{
var tmp=(mod2*(64/i))-(64/i);//a number between 0.9846153846153847 and -4032
tmp=tmp+(n/64);//still working with floating points.
tmp=tmp^(64/i);//this is a bitwise XOR operation. The result will always be an integer
tmp=tmp&1;//this is a bitwise AND operation. Basically we just want to know if the first bit is a 1 or 0.
outString+=charMap[tmp];
}
}//for
document.getElementById("p").innerHTML=outString;
}
myInterval();
setInterval(myInterval,64);
</script>
</pre>
The result of the code in the two links you provided are very different from one another.
However the logic in the code is quite similar. Both use a for-loop to loop through all the characters, a mod operation on a non-integer number, and a bitwise xor operation.
How does it all work, well basically all I can tell you is to pay attention to the variables changing as the input and output change.
All the logic appears to be some sort of bitwise cryptic way to decide which of 2 characters or a line break to add to the page.
I don't quite follow it myself from a calculus or trigonometry sort of perspective.
Consider that each line, as it sweeps across the rectangular area, is actually a rotation of (4?) lines about a fixed origin.
The background appears to "move" according to optical illusion. What actually happens is that the area in between the sweep lines is toggling between two char's as the lines rotate through them.
Here is the rotation eq in 2 dimensions:
first, visualize an (x,y) coordinate pair in one of the lines, before and after rotation (motion):
So, you could make a collection of points for each line and rotate them through arbitrarily sized angles, depending upon how "smooth" you want the animation.
The answer above me looks at the whole plane being transformed with the given formulae.
I tried to simplify it here -
The formula above is a trigonometric equation for rotation it is more simply solved
with a matrix.
x1 is the x coordinate before the the rotation transformation (or operator) acts.
same for y1. say the x1 = 0 and y1 = 1. these are the x,y coordinates of of the end of the
vector in the xy plane - currently your screen. if you plug any angle you will get new
coordinates with the 'tail' of the vector fixes in the same position.
If you do it many times (number of times depends on the angle you choose) you will come back to 0 x = 0 and y =1.
as for the bitwise operation - I don't have any insight as for why exactly this was used.
each iteration there the bitwise operation acts to decide if the point the plane will be drawn or not. note k how the power of k changes the result.
Further reading -
http://en.wikipedia.org/wiki/Linear_algebra#Linear_transformations
http://www.youtube.com/user/khanacademy/videos?query=linear+algebra

Check if two objects are facing eachother

I've searched all over and couldn't find an answer to this seemingly common question, surprisingly. The problem I'm currently facing is checking if the player is facing an enemy, then if so within what range of the players' view (adjustable) and if it's within that range then move away in the nearest safe direction.
Here's a picture :D
So, how would I accomplish this? I have the x, y, and direction, of every ship object. This is my last failed attempt, attempting to consider that the player's direction will be exactly 180 degrees away from the enemy's direction relative to the player.
var direction=Math.direction(this.x,this.y,player.x,player.y,1),
playerview=Math.abs(direction)-Math.abs(player.direction-180)
if(Math.abs(playerview)<10) {
console.log('in view')
this.xVelocity+=AI.speed*Math.sin(playerview*Math.PI/180)
this.xVelocity+=AI.speed*Math.cos(playerview*Math.PI/180)
}
In this example, 10 would be the range. Of course, I've only managed to make ships rotate to the right, so aside from the detection only working on half a circle I can't make the enemy go to the right side either. Any ideas?
In Your code, You are modifying this.xVelocity twice instead of modifying this.yVelocity.
I guess, Math.direction is not in the JavaScript/ECMA standard. Are You sure, You are using it correctly? Consider Math.atan2.
Moreover, You should provide a definition of "facing each other".
If it's "seeing each other", then Your comment "in view" is misleading.
But the main issue is:
Math.abs(angleInDegrees) modifies the angle!
The correct way to build an absolute value of an angle is:
while (angleInDegrees < 0)
{
angleInDegrees += 360;
}
// If necessary, add this too:
while (angleInDegrees >= 360)
{
angleInDegrees -= 360;
}
-10 and 350 are identical, -10 and 10 are 20 degrees apart.
For further explanation, let's call the code above normalizeAngle
(Note: For huge values, the loop may run very long or even forever. If such values may occur, this should be checked.)
The following should do the trick:
playerview = normalizeAngle(direction - player.direction - 180)
if (playerview < range || playerview > 360-range) {
By the way: "playerview" should be the mininum from the player's field of view and the enemy's field of view.

Click detection in a 2D isometric grid?

I've been doing web development for years now and I'm slowly getting myself involved with game development and for my current project I've got this isometric map, where I need to use an algorithm to detect which field is being clicked on. This is all in the browser with Javascript by the way.
The map
It looks like this and I've added some numbers to show you the structure of the fields (tiles) and their IDs. All the fields have a center point (array of x,y) which the four corners are based on when drawn.
As you can see it's not a diamond shape, but a zig-zag map and there's no angle (top-down view) which is why I can't find an answer myself considering that all articles and calculations are usually based on a diamond shape with an angle.
The numbers
It's a dynamic map and all sizes and numbers can be changed to generate a new map.
I know it isn't a lot of data, but the map is generated based on the map and field sizes.
- Map Size: x:800 y:400
- Field Size: 80x80 (between corners)
- Center position of all the fields (x,y)
The goal
To come up with an algorithm which tells the client (game) which field the mouse is located in at any given event (click, movement etc).
Disclaimer
I do want to mention that I've already come up with a working solution myself, however I'm 100% certain it could be written in a better way (my solution involves a lot of nested if-statements and loops), and that's why I'm asking here.
Here's an example of my solution where I basically find a square with corners in the nearest 4 known positions and then I get my result based on the smallest square between the 2 nearest fields. Does that make any sense?
Ask if I missed something.
Here's what I came up with,
function posInGrid(x, y, length) {
xFromColCenter = x % length - length / 2;
yFromRowCenter = y % length - length / 2;
col = (x - xFromColCenter) / length;
row = (y - yFromRowCenter) / length;
if (yFromRowCenter < xFromColCenter) {
if (yFromRowCenter < (-xFromColCenter))--row;
else++col;
} else if (yFromRowCenter > xFromColCenter) {
if (yFromRowCenter < (-xFromColCenter))--col;
else++row;
}
return "Col:"+col+", Row:"+row+", xFC:"+xFromColCenter+", yFC:"+yFromRowCenter;
}
X and Y are the coords in the image, and length is the spacing of the grid.
Right now it returns a string, just for testing.. result should be row and col, and those are the coordinates I chose: your tile 1 has coords (1,0) tile 2 is(3,0), tile 10 is (0,1), tile 11 is (2,1). You could convert my coordinates to your numbered tiles in a line or two.
And a JSFiddle for testing http://jsfiddle.net/NHV3y/
Cheers.
EDIT: changed the return statement, had some variables I used for debugging left in.
A pixel perfect way of hit detection I've used in the past (in OpenGL, but the concept stands here too) is an off screen rendering of the scene where the different objects are identified with different colors.
This approach requires double the memory and double the rendering but the hit detection of arbitrarily complex scenes is done with a simple color lookup.
Since you want to detect a cell in a grid there are probably more efficient solutions but I wanted to mention this one for it's simplicity and flexibility.
This has been solved before, let me consult my notes...
Here's a couple of good resources:
From Laserbrain Studios, The basics of isometric programming
Useful article in the thread posted here, in Java
Let me know if this helps, and good luck with your game!
This code calculates the position in the grid given the uneven spacing. Should be pretty fast; almost all operations are done mathematically, using just one loop. I'll ponder the other part of the problem later.
def cspot(x,y,length):
l=length
lp=length+1
vlist = [ (l*(k%2))+(lp*((k+1)%2)) for k in range(1,y+1) ]
vlist.append(1)
return x + sum(vlist)

Categories

Resources