Thanks for the kind words guys, I’d glady send the code if anyone is interested.
Regarding the linux issue it is probably related to my image loading algorythm.
It’s not well written. doesn’t work in jar files, and i suspect that is why it’s not working
on your platform as well
… and the easy way would be fiddling with the OpenGL Projection Matrix! (me == lazy)
The projection matrix would be like:
(this one zapped a few of my brainscells while creating)
1.0, 0.0, -1.0, 0.0 // x
0.5, 1.0, 0.5, 0.0 // y
0.0, -0.05, 0.0, 0.0 // depth
0.0, 0.0, 0.0, 1.0 // [nothing]
Scale a bit (in model-space), transpose and upload to gfx-card!
~~
Pros:
- any shape of any object is supported
- hardware accelerated gfx
- depth-buffer to reduce fills
Cons:
- less 1337!
~~
http://home.hccnet.nl/s.balk/static/isometric.png
~~
… ;D
I really like your engine better. Rendering that in software is much harder than my ‘quick’ hack. Well done!
That is really interesting. I never got around to toying with hardware accelerators.
Would you mind sharing your code?
but i gotta add, the pixel method I use can handle any shape too
This is the Projection Matrix:
1.0, 0.0, -1.0, 0.0 // x
0.5, 1.0, 0.5, 0.0 // y
0.0, -0.05, 0.0, 0.0 // depth
0.0, 0.0, 0.0, 1.0 // [nothing]
This is the transposed Matrix:
(OpenGL works with transposed matrices)
// x y depth [nothing]
1.0, 0.5, 0.0, 0.0
0.0, 1.0, -0.05, 0.0
-1.0, 0.5, 0.0, 0.0
0.0, 0.0, 0.0, 1.0
Store that in a FloatBuffer:
FloatBuffer matrixBuffer = BufferUtils.createFloatBuffer(4*4); // LWJGLs way
<or do>
FloatBuffer matrixBuffer = ByteBuffer.allocateDirect(4*4 * 4).order(ByteOrder.nativeOrder()).asFloatBuffer().; // own way
matrixBuffer.put(new float[]{1.0F, 0.5F, 0.0F, 0.0F, 0.0F, 1.0F, -0.05F, 0.0F, -1.0F, 0.5F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 1.0F});
matrixBuffer.flip();
Send to gfx-card:
glMatrixMode(GL_PROJECTION);
glLoadMatrix(matrixBuffer);
// scale down projection a bit, like factor 10
// otherwise a flat 1x1 quad kinda fills the screen
float s = 0.1F;
glScalef(s, s, s);
// switch to model-view matrix for further transformations
glMatrixMode(GL_MODELVIEW);
Well, for everything else you need to know your OpenGL
To be honest I’ve never heard of Isometric stuff done in the Projection Matrix, but I thought it would be worth the adventure of figuring out how matrix-calculations are actually performed and trying to create my own matrix after I figured out the formulas of real->iso. It’s always fun to share such stuff
Yeah, i havnt done any openGL in java yet. I guess i’ve allways been charmed by software rendering
I’ll upload the formulas i use for transforming real to isometric coordinates and back…
I never thought of expressing them on matrix form, but that might be a good way to go.
Id imagine its more optimized.
Anyways, its on my laptop so i cant access it right now. stay tuned
Well, it’s only more optimized when using hardware-acceleration.
As there are quite a few occurences of 0.0 in that matrix, you are constantly multiplying values by 0.0, which can be skipped if you use your own formulas. (Edit: same for 1.0 ofocurse)
Thanks for the GL isometric mode stuff, seem very useful!
Kev
Correction:
This is the Projection Matrix:
1.0, 0.0, -1.0, 0.0 // x
0.5, 2.0, 0.5, 0.0 // y
0.0, -0.05, 0.0, 0.0 // depth
0.0, 0.0, 0.0, 1.0 // [nothing]
This is the transposed Matrix:
(OpenGL works with transposed matrices)
// x y depth [nothing]
1.0, 0.5, 0.0, 0.0
0.0, 2.0, -0.05, 0.0
-1.0, 0.5, 0.0, 0.0
0.0, 0.0, 0.0, 1.0
I changed the 1.0 @ [1][1] to 2.0. Otherwise everything is squeezed on the y-axis.
Note that that -0.05 (for depth) is pretty randomly chosen, it works for me, if it doesn’t for you - when your near/far planes are off - adjust it a bit.
Ah, that explain why my chaps look a little stocky
http://www.cokeandcode.com/asd/screenshots/isoasd.png
I’ll adjust tonight, thanks for the update.
Only thing I had to change was to flip round the axis since I’m use Z as up/down not Y (just because I’m working in 2D really, honest).
Kev
I’ve done some real improvment on the engine.
alot of it is under the hood, like GUI-mouse handling, but one thing
i just know youre gonna like is the lanscapting tool.
This is really getting somewhere =)
Err…could u explain how it works?Maybe send some code.
I want to start coding something like this myself, but i dont know how to detect mouse entering over a tile…Plz help dude
Sure i’ll help.
But my current GUI system i rather complex. I’ll try to explain the flow…
The game runs in a seperate thread from the frame window.
Whenever a key is pressed or released or mouse moved or clikced functions are called in the frame class.
These functions store mouse and keyboard info in local variables.
Then when ever its time to update the GUI the mainloop sends these mouse states into a GUI class.
the GUI class now determins what so called GUIElement the mouse is over.
All objects you see drawn inherit from this GUIelement class, so that every object can get mouse focus and stuff.
All the elements are stored in an ArrayList and drawn in order.
When determining what object the mouse is over you go backwards (so that the upper object is checked first) through this list,
and if the mouse IS over the element you’re at now, stop reversing.
All GUIElements are square, so determining if the mouse is over it is easy. check if the mousex and mousey are within its (x,y) and (x+w,y+h)
Checking the objects in the world(buildings, tiles, people, whatever) is slightly more complicated since they are not rectangular.
But if that is what you wanna do i can show you how.
Need any code too?
Yeah, it would be great ! :
Yeah, rectangular checking is easy, but that iso tile stuff is a bit trickier. I could really use some code and guidance.
Btw, i m also developing an engine of my own, so i ll add your iso implementation to it.
Thanx in advance.
The basic idea is very simple:
Every object on the map inherites a basic sprite class, in my engine called a MapObject.
Every mapobject har a function Draw(Graphics g) that draws it onto the graphics surface g.
Whenever an object is drawn, it’s x and y coodinates are stored localy in variables called drawnToxX and drawnToY. (that is the screen coordinates, not the isometric/map coordinates)
Then, when you want to check if the mouse is over this object, simply check if it is between drawnToX and drawnToX+spriteWidth. same for Y coordinates.
Further, grab the color of the pixel at (mouseX-drawnToX, mouseY-drawnToY) from the MapObjects sprite.
If this pixel is opaque it means we found our object =)
If it is transparant it would mean this object (even though the mouse is within its boundingbox) is not the one we want, and we should proceed our search…
Code:
//returns the object under the cursor
public MapObject getClickedObject(int sx, int sy){
for(int i=partnerWorld.getMapObjectList().size()-1; i>=0; i--){//move backwards through the list
MapObject o = partnerWorld.getMapObjectList().get(i);
int x = o.drewToX, y = o.drewToY;
int w = o.spriteW, h = o.spriteH;
//check if the mouse is within the object sprite
if(sx>x && sx<x+w)//are we within this objects bounding box x-wise?
if(sy>y && sy<y+h){//are we within this objects bounding box y-wise?
//get color at coord. and correct for frame and rotation sprite offset and stuff. idunno, tired now
if(o.getImage().getRGB(sx-x+o.getFrameOffset() ,sy-y+o.getRotationOffset()) >>> 24 == 255){//is this pixel opaque
return o;//if so, return this object
}
}
}
return null;
}
But as I said, you’re gonna need alot more to get a fully functional GUI. You guys want the whole engine perhaps? its open source anyways
Whoa neat stuff to check for transparency. I thought that i had to make up with some maths to find rombs
Idea is great, thx a lot!
But you might have tiles with transparent areas in the romb… then that method doesn’t work…
but that’s stating the obvious of course…
:~/Desktop/iso$ java -classpath . misc.MainClass
ERROR LOADING IMAGE FILE: tiles.gif
----Terminating----
Could you fix a linux version, please?
the problem might be the “\” instead File.separatorChar on the file path.
thanks
Very nice.
I would mention that start.bat didn’t work until I added a “-cp .” option to java.
Note that when you raise your foreground tiles sufficiently, their edges become visually colinear with background tiles. This causes a loss of depth perception. You could overcome this by shading your tiles based on height. Even a subtle gradient would convey the necessary information.
Below I have a shot of a little map I made to demonstrate the problem, and then a photoshopped example suggestion. You could also shade the tiles based on vertex distance from ‘camera’, which would basically be a fogging effect, which would be more subtle but maybe neater.
Again, very cool.
Thanks for the feedback guys.
Im working on a linux version, and it shouldn’t be much work. the only problem as I see it is my picture loading algorythm.
If anyone knows how this is best done, so it works on all platforms, I’d REALLY appreciate it.
This is my code as it is now:
//ripped from http://wiki.java.net/bin/view/Games/TextureLoadingExample, all hail them
private static BufferedImage loadImage(String ref) throws IOException {
File file = new File("images\\" + ref);
if (!file.isFile()) {
throw new IOException("Cannot find: images\\"+ref);
}
BufferedImage bufferedImage = ImageIO.read(new BufferedInputStream(
new FileInputStream(file))
);
System.out.println("picture preloaded: " + ref);
return bufferedImage;
}
To adress the height problem, ive kinda got an idea.
If you look at other engines like this you’ll see that tiles that are elevated and does not
have a tile behind it at the same level have an extra line drawn on them.
http://www.jonask.com/img/rct_height_issue.png
This picture from RCT illustrates the solution.
I was thinking maybe i could do something like that later on, but right now im focused on other elements of the game =)