How to transition an isometric object from one tile to another without overlapping other tiles - game-engine

I've created an isometric environment, all in Javascript and HTML5 (2D Canvas), which mostly works fine. The problem I'm facing is to do with having different height tiles and then sorting the indexes of objects on the tiles (in this case, while moving between two tiles side-by-side).
For example, one object may be behind a tile in front of it because the height of the tile it is on is -1. The solution I came up with was to draw each object of a tile directly after drawing the tile, starting at 0,0 and drawing each row and column from there.
This works well until I need to transition an object between two tiles. At this point, either the object must use an intermediate tile (this is what is implemented in the images below) or the tile will overlap the object as the tile is drawn after the object. Using an intermediate tile also gives a problem where the fence object on the same "row" gets draw over because the cube is using much higher z-index from the tile at 1,3 (this is slightly visible in image 1).
http://i.stack.imgur.com/PQJ0H.png
http://i.stack.imgur.com/DupM7.png
I think the tried and tested way of drawing isometric environments is just to have 1 layer for tiles and 1 layer for objects and then objects can never be behind tiles, but this is just a limitation that I don't want to adhere to.
So my question is, when drawing the entire environment from top to bottom (or any other way if it makes it possible), drawing each tile and it's objects in turn, is there a clever way to defer drawing of an object or create an array of objects to be drawn in the correct order? Has anyone else encountered similar issues and has anyone else found any solutions for this?
All help much appreciated.
An example of my tiling code:
// each column
for(y=0; y<totalColumns; y++){
// each row
for(x=0; x<totalRows; x++){
tile = tiles[y][x];
// draw tile
drawTile(tile);
objects = objects[y][x];
// draw objects for that tile
drawObjects(objects);
}
}
Edit:
One solution I have thought of (after reading the question back to myself) is to loop through all the tiles, get an array of tile heights, sort that, then do the traditional drawing. Like so:
var layers = [];
for(var y=0; y<cols; y++){
for(var x=0; x<rows; x++){
tile = tiles[y][x];
if(!layers.indexOf(tile.height)) layers.push(tile.height);
}
}
// sort layers
layers.sort(/*function here to sort layers*/);
for(l=0; l<layers.length; l++){
// draw tiles for this layer
// draw objects for this layer
}
Any other solutions possible?

Your doing the exact right thing in your solution. You want to do this for everything that doesn't have an alpha.
As far as other solutions go I would recommend looking at using an insertion sort rather than rebuilding the list time and time again. In your case there is very little change so just update the ones that need it.

Related

parameters of Viewport instantiation

After many tutorials I am still having trouble understanding viewports and how exactly do they relate to cameras. What exactly do the numbers you put in for example
viewport = new ExtendViewport(10,10,camera)
actually mean? I was using ShapeRenderer and a Texture to see if changing numbers have any effect on how the Rectangle moves around. I used keyDown method of InputProcessor with the implementation like this:
if(keycode== Input.Keys.X){
xRect-=10;
}
No matter what the numbers were in viewport instantiation, the Rectangle always moved for the same amount. Also, the Texture was always drawn at the same place at the same aspect ratio. So what does these numbers actually mean?

three.js: how to control rendering order

Am using three.js
How can I control the rendering order? Let's say I have three plane geometries, and want to render them in a specific order regardless of their spatial position.
thanks
You can set
renderer.sortObjects = false;
and the objects will be rendered in the order they were added to the scene.
Alternatively, you can leave sortObjects as true, the default, and specify for each object a value for object.renderOrder.
For more detail, see Transparent objects in Threejs
Another thing you can do is use the approach described here: How to change the zOrder of object with Threejs?
three.js r.71
for threejs r70 and higher is renderDepth removed.
Using object.renderDepth worked in my case. I had a glass case and bubbles inside that were transparent. The bubbles were getting lost at certain angles.
So, setting their renderDepth to a high number and playing with other elements depths in the scene fixed the issue. Hooking up a dat.gui control to the renderDepth property made it very easy to tweak what needed to be at what depth to make the scene work.
So, in my fishScene, I have gravel, tank and bubbles. I hooked up the gravel mesh with a dat.gui control and with in a few seconds, I had the depth I needed.
this.gui.add(this.fishScene.gravel, "renderDepth", 0, 200);
i had a bunch of objects which was cloned from a for loop in random position x and y... and obj.z ++, so they would line up in line.. including obj.renderOrder ++; in the loop solved my issue.

ipad frame max size is not enough

I'm developing an ipad application about 2d drawing.
I need a UIView.frame size of 4000x4000. But if I set a frame with size 4000x4000 the application
crash since i get memory warning.
Right night I'm using 1600*1000 frame size and the user can add new object (rectangle) on frame. User can also translate fram along x and y axis using pan gesture in order to see or add new object.
Have you got some suggestion? how can I tackle this problem?
thanks
Well, I would suggest what is used in video games for a long time - creating a tiled LOD mechanism, where only when you zoom in toward specific tiles, they are rendered at an increasing resolution, while when zoomed out, you only render lower resolution.
If the drawing in based on shapes (rectangles, points, lines, or anything can be represented by simple vector data) there is no reason to create a UIView for the entire size of the drawing. You just redraw the currently visible view as the user pans across the drawing using the stored vector data. There is no persistent bitmapped representation of the drawing.
If using bitmap data for drawing (i.e. a Photoshop type of app) then you'll likely need to use a mechanism that caches off-screen data into secondary storage and loads it back onto the screen as the user pans across it. In either case, the UIView only needs to be as big as the physical screen size.
Sorry I don't have any iOS code examples for any of this - take this as a high-level abstraction and work from there.
Sounds like you want to be using UIScrollView.

How to render a 2d side-scroller game

I do not really understand the way I'm suppose to render a side-scroller? How do I know what to render when my character move? What kind of positionning should I use for the characters?
I hope my question is clear
The easiest way i've found to do it is have a characterX and characterY variable [integer or float, whatever you want] Then have a cameraX and cameraY variable. Every object in the scene is drawn at theObjectX-cameraX, theObjectY-cameraY...
CameraX/CameraY are tweened by a similar-to-midpoint formula so eventually they'll reach playerx/playery[Cx = (Cx*99+Px)/100] ... yeah
By doing this, every object moves in the stage's space, and is transformed only on render [saving you from headaches]
Use a matrix to define a camera reference frame.
Use space partitioning to split up your level into screens/windows.
Think of your player sprite as any other entity, like enemies and interactive objects.
Now what you want is the abstraction of a camera. You can define a camera as a 3x3 matrix with this layout:
[rotX_X, rotY_X, 0]
[rotX_Y, rotY_Y, 0]
[transX, transY, 1]
The 2x2 sub-matrix in the top-left corner is a rotation matrix. transX and transY defines the translation part, i.e the origin. You also get scaling for free. Just simply scale the rotation part with a scalar, and you have yourself a zoom.
For this to work properly with rotation, your sprites need to be polygons/primitives, say like triangles or quads; you can't just apply the matrix to the positions of the sprites when drawing. If you don't need rotation, just transforming the center point will work fine.
If you want the camera to follow the player, use the player's position as the camera origin. That is the translation vector [transX, transY]
So how do you apply the matrix to entity positions and model vertices? You do a vector-matrix multiplication.
v' = vM^-1, where v' is the new vector, v is the old vector, and M^-1 is the matrix inverse. A camera needs to be an inverse transform because it defines a local coordinate system. An analogy could be: If you are in front of me and I turn left from my reference frame, I am turning your right. This applies to all affine and linear transformations, like scaling, rotation and translation.
Split up your level into sub-parts so you can cull objects and scenery which does not need to be rendered. Your viewport is of a certain size/resolution. Only render scenery and entities which intersect with your viewport. Instead of checking each and every entity against the viewport bounds, assign each entity to a certain sub-screen and test the bounds of the sub-screen against the viewport and camera bounds. If your divide your levels into parts which are the same size as your viewport, then the maximum number of screens visible
at any particular time is:
2 if your camera only scrolls left and right.
4 if your camera scrolls left, right, up and down.
4 if your camera scrolls in any direction, and additionally can be rotated.
A screen-change is an event you can use to activate entities belonging to that screen. That could be enemies, background animations, doors or whatever you like.
If this is your first foray into writing a side-scroller, I'd suggest considering using an already existing game engine (like Construct or Gamemaker or XNA or whatever fits your experience level) so you don't have to worry about what order to render things and how to make it all work. Mess with that a bit--probably exploring a few of them--to get a feel for how they do things then venture out to your own once you've gotten used to it.
Not that there's anything wrong with baptism by fire but it can get pretty overwhelming in my opinion.

how to generate graphs using integer values in iphone

i want to show a grapph/bar chart in iphone how do i do this without custom API;s
You may want to investigate the Core Plot project [code.google.com]. Core Plot was the subject of this year's scientific coding project at WWDC and is pretty useable for some cases already. From its inception, Core Plot was intended for both OS X and iPhone uses. The source distribution (there hasn't been a binary release yet) comes with both OS X and iPhone example applications and there's info on the project wiki for using it as a library in an iPhone app. Here's an example of it's current plotting capabilities.
(source: googlecode.com)
Write your own. It's not easy, I'm in the process of doing the same thing right now. Here's how I'm doing it:
First, ignore any desire you may have to try using a UIScrollView if you want to allow zooming. It's totally not worth it.
Second, create something like a GraphElement protocol. I have a hierarchy that looks something like this:
GraphElement
GraphPathElement
GraphDataElement
GraphDataSupplierElement
GraphElement contains the basic necessary methods for a graph element, including how to draw, a maximum width (for zooming in), whether a point is within that element (for touches) and the standard touchBegan, touchMoved, and touchEnded functions.
GraphPathElement contains a CGPath, a line color and width, a fill color and a drawing mode. Whenever it's prompted to draw, it simply adds the path to the context, sets the colors and line width, and draws the path with the given drawing mode.
GraphDataElement, as a subclass of GraphPathElement, takes in a set of data in x-y coordinates, a graph type (bar or line), a frame, and a bounds. The frame is the actual size of the created output CGPath. The bounds is the size of the data in input coordinates. Essentially, it lets you scale the data to the screen size.
It creates a graph by first calculating an affine transform to transform the bounds to the frame, then it loops through each point and adds it as data to a path, applying that transform to the point before adding it. How it adds data depends on the type.
If it's a bar graph, it creates a rectangle of width 0, origin at (x,frame.size.height-y), and height=y. Then it "insets" the graph by -3 pixels horizontally, and adds that to the path.
If it's a line graph, it's much simpler. It just moves to the first point, then for each other point, it adds a line to that point, adds a circle in a rect around that point, then moves back to that point to go on to the next point.
GraphDataSupplierElement is the interface to my database that actually contains all the data. It determines what kind of graph it should be, formats the data into the required type for GraphDataElement, and passes it on, with the color to use for that particular graph.
For me, the x-axis is time, and is represented as NSTimeIntervals. The GraphDataSupplierElement contains a minDate and maxDate so that a GraphDateElement can draw the x-axis labels as required.
Once all this is done, you need to create the actual graph. You can go about it several ways. One option is to keep all the elements in an NSArray and whenever drawRect: is called, loop through each element and draw it. Another option is to create a CALayer for each element, and use the GraphPathElement as the CALayer's delegate. Or you could make GraphPathElement extend from CALayer directly. It's up to you on this one. I haven't gotten as far as trying CALayers yet, I'm still stuck in the simple NSArray stage. I may move to CALayers at some point, once I'm satisfied with how everything looks.
So, all in all, the idea is that you create the graph as one or many CGPaths beforehand, and just draw that when you need to draw the graph, rather than trying to actually parse data whenever you get a drawRect: call.
Scaling can be done by keeping the source data in your GraphDataElement, and just change the frame so that the scaling of the bounds to the frame creates a CGPath wider than the screen, or whatever your needs are. I basically re-implemented my own pinch-zoom for my Graph UIView subclass that only scales horizontally, by changing its transform, then on completion, get the current frame, reset the transform to identity, set the frame to the saved value, and set the frame of all of the GraphElements to the new frame as well, to make them scale. Then just call [self setNeedsDisplay] to draw.
Anyway, that's a bit ramble-ish, but it's an outline of how I made it happen. If you have more specific questions, feel free to comment.