@ Basjak: But in Phaelax's example neither line is aligned with an axis. If I understand your method that would make it not work.
I have to go for an hour or so, so I'll post what I've done and come back to it later. Haven't tried to solve the problem, but I did generalize the isometric-ness so that I don't have to deal with the magic numbers (32/64)
global pixelOffsetX
global pixelOffsetY
global ix as float
global iy as float
global jx as float
global jy as float
global scale as float
initCoordinates(0,0)
scale=30
pixelOffsetX=100
pixelOffsetY=100
a as float
b as float
do
cls
a=a+1
b=b+1
initCoordinates(a,b)
drawGrid(10,10)
loop
wait key
end
function drawGrid(x,y)
//draw horizontal lines
for n=0 to x-1
for m=0 to y
line getXCoord(n,m),getYCoord(n,m),getXCoord(n+1,m),getYCoord(n+1,m)
next m
next n
//draw vertical lines
for n=0 to x
for m=0 to y-1
line getXCoord(n,m),getYCoord(n,m),getXCoord(n,m+1),getYCoord(n,m+1)
next m
next n
endfunction
function getXCoord(x,y)
n#=pixelOffsetX+(ix*x+jx*y)*scale
endfunction n#
function getYCoord(x,y)
n#=pixelOffsetY+(iy*x+jy*y)*scale
endfunction n#
function initCoordinates( theta as float,phi as float)
ix=cos(theta)
iy=sin(theta)*cos(phi)
jx=-sin(theta)
jy=cos(theta)*cos(phi)
endfunction
Basically, the axis vectors i and j (not unit length) define the coordinate system for the isometric grid. To convert from mouse coordinates, you'd need to take the vector from the pixeloffset to the mouse, and take the dot product with both vector i and vector j. (multiplied by the scale). Round each of those down to an integer and you'll have the x and y coordinate! Of course once you use this in your game you can simplify the math for the i and j vectors and you won't have to do this explicitly, but this is essentially what basjak was doing (just with an x unit vector that points in a different direction)
Quote: "Wheres Neuro Fuzzy when you need him?"
I always get a huge smile on my face when I read things like this :3
[edit]
Alright, I got it working with a lot of comments on the linear algebra:
global pixelOffsetX
global pixelOffsetY
global ix as float
global iy as float
global jx as float
global jy as float
global scale as float
initCoordinates(0,0)
scale=30
pixelOffsetX=100
pixelOffsetY=100
a as float
b as float
do
cls
a=a+1
b=b+1
initCoordinates(a,b)
drawGrid(10,10)
drawMousePos()
loop
wait key
end
function drawMousePos()
n=floor(getMouseXGrid())
m=floor(getMouseYGrid())
text 0,0,"Grid Mouse Position: ("+str$(n)+", "+str$(m)+")"
circle getXCoord(n+.5,m+.5),getYCoord(n+.5,m+.5),10
endfunction
remstart
Now to solve for the mouse position. given mouse position P (relative to the pixel offset)
and vectors I and J, we want to find n and m such that n*I+m*J=P. Normally this is easy to
solve because normally I and J are perpendicular unit vectors, so we can say: n*I*I+m*J*I=P*I,
and since I*I=1 and I*J=0, n=P*I. (keeping in mind '*' here is the dot product operator).
However none of those constraints are satisfied, so we have to use a different method.
Let Jp be a vector perpendicular to J. (an vector perpendicular to (x,y) is (-y,x))
THEN J*Jp=0, so we have n*I*Jp=P*Jp, n=(P*Jp)/(I*Jp). We can do the same to solve for m.
Also there's a factor of scale in there, in this case we'd have I=scale*(ix,iy) and same for J,
so we get a factor of 1/scale multiplying our results.
remend
function getMouseXGrid()
x=mousex()-pixelOffsetX
y=mousey()-pixeloffsetY
n#=(y*jx-x*jy)/(iy*jx-ix*jy)
n#=n#/scale
endfunction n#
function getMouseYGrid()
x=mousex()-pixelOffsetX
y=mousey()-pixeloffsetY
n#=(y*ix-x*iy)/(jy*ix-iy*jx)
n#=n#/scale
endfunction n#
function drawGrid(x,y)
//draw horizontal lines
for n=0 to x-1
for m=0 to y
line getXCoord(n,m),getYCoord(n,m),getXCoord(n+1,m),getYCoord(n+1,m)
next m
next n
//draw vertical lines
for n=0 to x
for m=0 to y-1
line getXCoord(n,m),getYCoord(n,m),getXCoord(n,m+1),getYCoord(n,m+1)
next m
next n
endfunction
`the linear combination of the two coordinate vectors.
`offset+i*n+j*m = any point in our 2D coordinate system. where i,j,offset are vectors and n,m are scalars.
`This accepts a float argument in case you want the middle of a tile, in which case you'd pass in
`get_coord(.5,.5)
function getXCoord(x as float,y as float)
n#=pixelOffsetX+(ix*x+jx*y)*scale
endfunction n#
function getYCoord(x as float,y as float)
n#=pixelOffsetY+(iy*x+jy*y)*scale
endfunction n#
remstart
long matrix explanation. You don't need the matrices, you can just input two vectors i and j,
but I like it because you can easily liken it to 3D
We just need a way to get the coordinate vectors. Here, theta represents an angle about the XY plane,
and phi represents a rotation about the YZ plane. Working in 3D for a moment, if we rotate the vectors
that form a 2D square in the XY plane ([0,0,0],[1,0,0],[1,1,0],[0,1,0]) by the theta rotation and then
by the phi rotation, we can drop the Z component of the resulting vector, and that's our orthogonal
projection!
Matrix is:
[1 0 0 ] [cos(theta) -sin(theta) 0]
[0 cos(phi) sin(phi)]*[sin(theta) cos(theta) 0]*Vectors
[0 -sin(phi) cos(phi)] [0 0 1]
The vector [1,1,0] when rotated is just a sum of components of [1,0,0] and [0,1,0], and the
vector [0,0,0] will remain the same under rotation, so we only need to calculate those two
rotations.
remend
function initCoordinates( theta as float,phi as float)
ix=cos(theta)
iy=sin(theta)*cos(phi)
jx=-sin(theta)
jy=cos(theta)*cos(phi)
endfunction
To get the angles and everything like phaelax's was, we can set i=(32,-16) (negative being UP), j=(32,16). (and scale=1, meaning ignore it). That simplifies down to this:
global pixelOffsetX
global pixelOffsetY
pixelOffsetX=100
pixelOffsetY=100
do
cls
drawGrid(10,10)
drawMousePos()
loop
wait key
end
function drawMousePos()
n=floor(getMouseXGrid())
m=floor(getMouseYGrid())
text 0,0,"Grid Mouse Position: ("+str$(n)+", "+str$(m)+")"
circle getXCoord(n+.5,m+.5),getYCoord(n+.5,m+.5),10
endfunction
function drawGrid(x,y)
//draw horizontal lines
for n=0 to x-1
for m=0 to y
line getXCoord(n,m),getYCoord(n,m),getXCoord(n+1,m),getYCoord(n+1,m)
next m
next n
//draw vertical lines
for n=0 to x
for m=0 to y-1
line getXCoord(n,m),getYCoord(n,m),getXCoord(n,m+1),getYCoord(n,m+1)
next m
next n
endfunction
//mathy functions simplified with i=(32,-16),j=(32,16),scale=1
function getMouseXGrid()
x=mousex()-pixelOffsetX
y=mousey()-pixeloffsetY
n#=(x-y*2)/64.0
endfunction n#
function getMouseYGrid()
x=mousex()-pixelOffsetX
y=mousey()-pixeloffsetY
n#=(y*2+x)/64.0
endfunction n#
function getXCoord(x as float,y as float)
n#=pixelOffsetX+32*x+32*y
endfunction n#
function getYCoord(x as float,y as float)
n#=pixelOffsetY-16*x+16*y
endfunction n#
