Poor zooming out distance field font? - libgdx

Being quite new with shaders, I was pleased when I successful(ish) managed to get a DistanceFieldFont shader working.
It seems to work great at making text look sharp when zoomed in....
...but when zoomed out it looks hideous:
The text on the left is a normal LibGDX label for comparison.
The code making the material is;
Texture texture = generateTexture(contents); //function generate text-texture from supplied letters
texture.setFilter(TextureFilter.MipMapLinearLinear, TextureFilter.Linear);//Isnt this supposed to ensure smooth zoomout?
Material mat = new Material(TextureAttribute.createDiffuse(texture), new BlendingAttribute(1f),ColorAttribute.createDiffuse(Color.CYAN));
labelModel = ModelMaker.createRectangle(0, 0, 400,400, 0, mat);
labelInstance = new ModelInstance(labelModel);
labelInstance.userData = MyShaderProvider.shadertypes.distancefield;
and the code generating the texture;
private Texture generateTexture(String text) {
String Letters=text;
Pixmap textPixmap = new Pixmap(TITLE_WIDTH, TITLE_HEIGHT, Format.RGBA8888);
BitmapFontData data = DefaultStyles.standdardFont.getData(); //new BitmapFontData(Gdx.files.internal(data.imagePaths[0]), true);
Pixmap fontPixmap = new Pixmap(Gdx.files.internal(data.imagePaths[0]));
// draw the character onto our base pixmap
int totalwidth=0;
int current_testedwidth=0;
int currentX=0;
float scaledown = 1f;
Glyph defaultglyph = data.getGlyph(Letters.charAt(0));
int totalheight=defaultglyph.height+9;
Gdx.app.log(logstag,"scaledown="+scaledown);
double lastremainder =0;
int yp=0;
for (int i = 0; i < Letters.length(); i++) {
Glyph glyph = data.getGlyph(Letters.charAt(i));
if (glyph==null){
glyph=defaultglyph; //temp
}
if (Letters.charAt(i) == '\n'){
Gdx.app.log(logstag,"______________adding line=");
//new line
yp=(int) (yp+(defaultglyph.height* scaledown)+5);
currentX=0;
}
int cwidth = (int)(glyph.width * scaledown);
int cheight = (int)(glyph.height * scaledown);
int yglyphoffset = (int) (glyph.yoffset * scaledown);
textPixmap.drawPixmap(
fontPixmap,
glyph.srcX,
glyph.srcY,
glyph.width,
glyph.height+1,
0+currentX+glyph.xoffset,
0+(yp+(yglyphoffset )),//+(TILE_HEIGHT - (cheight)) / 2,
cwidth,
cheight);
double newprecisepos = ((glyph.xadvance+2) * scaledown)+lastremainder;//glyph.width+3
lastremainder = newprecisepos - Math.floor(newprecisepos);
int newpos = (int) (Math.floor(newprecisepos));
currentX=currentX + newpos;
}
return new Texture(textPixmap,true);
}
Is it supposed to look this bad?
I'll post the glsl stuff if needed, but (I think) zoom out should work better then this regardless no ? :?
Any help appreciated.

Not completely satisfactory, but after looking around theres tweaks to the shader which produce better results;
http://www.java-gaming.org/index.php?topic=33612.0
Essentially you need to add supersampleing.
Oddly it seems to work better WITHOUT mip-maps.

Related

as3 - converting bitmap back to vector in view

So I found a V-CAM source, I am now using it and quite happy however, is it possible to untoggled bitmap when the objects that are bitmapped are viewed by the cam? For instance, lets say I have a vector movieclip with a bunch of vector art, I toggle export as bitmap on the movieclip from my IDE, now would it be possible to add on to my VCAM, that everything in its view (it resizes stage) untoggles or redraws back to vector, while the rest of map/movieclip is still in bitmap? And as the VCAM moves away, what was shifted from bitmap to vector gets shifted back to bitmap?
var camColor: ColorTransform = new ColorTransform();
var parentColor: ColorTransform = new ColorTransform();
var cX: Number;
var cY: Number;
var sX: Number;
var sY: Number;
this.visible = false;
var oldMode: String = stage.scaleMode;
stage.scaleMode = StageScaleMode.EXACT_FIT;
cX = stage.stageWidth / 2;
cY = stage.stageHeight / 2;
sX = stage.stageWidth;
sY = stage.stageHeight;
stage.scaleMode = oldMode;
camColor = this.transform.colorTransform;
parentColor = this.parent.transform.colorTransform;
camControl(new Event(Event.ENTER_FRAME));
addEventListener(Event.ENTER_FRAME, camControl);
addEventListener(Event.REMOVED, resetStage);
function camControl(event: Event): void {
camColor = this.transform.colorTransform;
parent.transform.colorTransform = camColor;
var xScale: Number = sX / this.width;
var yScale: Number = sY / this.height;
parent.x = cX - (this.x * xScale);
parent.y = cY - (this.y * yScale);
parent.scaleX = xScale;
parent.scaleY = yScale;
}
function resetStage(event: Event): void {
removeEventListener(Event.ENTER_FRAME, camControl);
parent.transform.colorTransform = parentColor;
parent.scaleX = 1;
parent.scaleY = 1;
parent.x = 0;
parent.y = 0;
}
I think you'd better use another camera with higher bitmap dimensions (2x-4x) to render those scenes from vector that you feel are too pixelized. In terms of export, just export the character's bitmaps 2x-4x larger, or you can just have it as a vector somewhere in your app, maybe hidden, and do realtime render when needed, or plain have it in your display list as a vector and not a bitmap.
In case you need to have some complex vector form into a bitmap-based engine, you can use realtime bitmap drawing of a single source in various postures/rotations, then use those rendered bitmaps to get performance. Check the game "Enigmata: Stellar War" for this technique, how does it look in the process (hint: when it says "Loading boss" it does all the render behind the scenes).
Getting a vectorized source form bitmaps is a lot more processor consuming than having a ready-made vectorized source stored somewhere. Also you won't get your original vector restored in exact form, as converting a vector to a bitmap is a lossy transformation.

Libgdx AtlasTmxMapLoader with multiple tilsets

I am working on a Libgdx game which loads Tiled maps. The current map I am working on makes use of 2 tilesets, one for shadow/light and another for terrain and buildings. The general process I do, that has been working fine, is that I receive the sprite sheet from the artist, design the maps, then take the spritesheet file and split it using ImageMagick. From there I take the split images and create an optimized png and atlas file with TexturePacker.
However, this is the first map I have made that makes use of multiple tilesets. The issue I am having is when loading the map with AtlasTmxMapLoader it relies on a single atlas file property in the map. My shadows and lighting are split into a separate image and atlas and Id rather not merge them all into one in Tiled (and have to re-do a portion of the map).
Perhaps I am missing something simple. How can I handle multiple tilesets?
So after reading more into how .tmx files are read I was able to fix my problem.
Here is how to properly do it when working with multiple tilesets and re-packing your spritesheets in TexturePacker. First, cut up the tileset images using a utility like ImageMagick and make sure they are indexed (specified by an underscore and number in the filename). You can do this with the crop command in ImageMagick like so:
convert.exe "shrine_tileset.png" -crop 16x16 "shrine_tileset_%02d.png"
Second, re-pack all tiles from all tilesets into a single atlas in TexturePacker. If it works correctly you will see the name of each tileset in the atlas file with an associated index based on the tile id. For example:
shrine_tileset
rotate: false
xy: 382, 122
size: 16, 16
orig: 16, 16
offset: 0, 0
index: 703
Finally (and this is the part I could not figure out), make sure each tileset's tile indexes start from the "firstgid" value in the .tmx file. For example, my second tilesheet starts from 2049, as their are 2048 tiles in the first sheet. This should be denoted at the top of the .tmx file for each tileset.
<tileset firstgid="2049" source="shadow_light.tsx"/>
So when cutting up the tiles for my tileset "shadow_light", I would start them from index 2048, one less than the gid, EX: "shadow_light_2048.png".
Hopefully this helps someone!
I am no LibGDX expert but almost all tilemap renderers I've seen rely on working with 1 tileset. The reason is that they are rendered using OpenGL. The renderer sets the texture and draws all tiles with 1 draw call. You can't switch textures in between.
The best way would be to create 2 (or more) separate layers. Each layer uses 1 tileset. E.g. 1 for the background, 1 for the shadows, 1 for the foreground (e.g. walls).
This issue is fixed in 1.9.11. If you are using an earlier version you can override AtlasTmxMapLoader with a fix.
MyAtlasTmxMapLoader.Java
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.maps.ImageResolver;
import com.badlogic.gdx.maps.MapProperties;
import com.badlogic.gdx.maps.tiled.AtlasTmxMapLoader;
import com.badlogic.gdx.maps.tiled.TiledMapTile;
import com.badlogic.gdx.maps.tiled.TiledMapTileSet;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.GdxRuntimeException;
import com.badlogic.gdx.utils.SerializationException;
import com.badlogic.gdx.utils.XmlReader.Element;
public class MyAtlasTmxMapLoader extends AtlasTmxMapLoader {
/**
* Same as AtlasTmxMapLoader, but fixed to get the firstid attribute from the tileset element in the TMX file, not tsx file.
*/
#Override
protected void loadTileSet(Element mapElement, FileHandle tmxFile, ImageResolver imageResolver) {
if (mapElement.getName().equals("tileset")) {
String imageSource = "";
int imageWidth = 0;
int imageHeight = 0;
FileHandle image = null;
Element element = null;
String source = mapElement.getAttribute("source", null);
if (source != null) {
FileHandle tsx = getRelativeFileHandle(tmxFile, source);
try {
element = xml.parse(tsx);
Element imageElement = element.getChildByName("image");
if (imageElement != null) {
imageSource = imageElement.getAttribute("source");
imageWidth = imageElement.getIntAttribute("width", 0);
imageHeight = imageElement.getIntAttribute("height", 0);
image = getRelativeFileHandle(tsx, imageSource);
}
} catch (SerializationException e) {
throw new GdxRuntimeException("Error parsing external tileset.");
}
} else {
Element imageElement = mapElement.getChildByName("image");
if (imageElement != null) {
imageSource = imageElement.getAttribute("source");
imageWidth = imageElement.getIntAttribute("width", 0);
imageHeight = imageElement.getIntAttribute("height", 0);
image = getRelativeFileHandle(tmxFile, imageSource);
}
}
String name = element.get("name", null);
// Get the firstid attribute from the tileset element in the TMX file, not tsx file.
int firstgid = mapElement.getIntAttribute("firstgid", 1);
int tilewidth = element.getIntAttribute("tilewidth", 0);
int tileheight = element.getIntAttribute("tileheight", 0);
int spacing = element.getIntAttribute("spacing", 0);
int margin = element.getIntAttribute("margin", 0);
Element offset = element.getChildByName("tileoffset");
int offsetX = 0;
int offsetY = 0;
if (offset != null) {
offsetX = offset.getIntAttribute("x", 0);
offsetY = offset.getIntAttribute("y", 0);
}
TiledMapTileSet tileSet = new TiledMapTileSet();
// TileSet
tileSet.setName(name);
final MapProperties tileSetProperties = tileSet.getProperties();
Element properties = element.getChildByName("properties");
if (properties != null) {
loadProperties(tileSetProperties, properties);
}
tileSetProperties.put("firstgid", firstgid);
// Tiles
Array<Element> tileElements = element.getChildrenByName("tile");
addStaticTiles(tmxFile, imageResolver, tileSet, element, tileElements, name, firstgid, tilewidth,
tileheight, spacing, margin, source, offsetX, offsetY, imageSource, imageWidth, imageHeight, image);
for (Element tileElement : tileElements) {
int localtid = tileElement.getIntAttribute("id", 0);
TiledMapTile tile = tileSet.getTile(firstgid + localtid);
if (tile != null) {
addTileProperties(tile, tileElement);
addTileObjectGroup(tile, tileElement);
addAnimatedTile(tileSet, tile, tileElement, firstgid);
}
}
map.getTileSets().addTileSet(tileSet);
}
}
}
And then call:
new MyAtlasTmxMapLoader().load(pathname)
Source: [Tutorial] Using multiple Tilesets with Libgdx and Tiled

I want to use a code like the one I made in processing

I'm new to coding and I have a question.
I've made this simple code in processing and I was wondering if I could use it and how to do the same with an image inside a div.
This is the code:
<i>int x, y;
PImage img;
void setup () {
size(800, 739);
img = loadImage("1.jpg");
}
void draw () {
for (int i=0; i < mouseX/10; i ++) {
int x = (int) random(width);
int y = (int) random(height);
color cor = img.get(x, y);
float t = random(5, 25);
fill(cor, 30);
noStroke ();
ellipse(x, y, t, t);
}
}
</i>
If you know the location of the image (the src attribute of the <img> tag), then all you need to do is change this line:
img = loadImage("1.jpg");
To something like this:
img = loadImage("http://example.com/YourImageFile.jpg");
If you don't know the location of the image ahead of time, then there are ways to get the location of the image using JavaScript. Any JavaScript you write can call any Processing code you write, so you might have something like this in your Processing code:
void setImageLocation(String location){
img = loadImage(location);
}
Then all you need to do is write JavaScript that gets the location of the image and calls that function.
Check out the Accessing Processing from JavaScript section of the Processing.js tutorial for more info.

CS6 - Actionscript 3.0 Collisions, points and the lack of a bump

I've been toying with flash for a bit, I usually solve my problems fairly quick, however I have been stuck on this one for a few days, google hasn't been useful, and I do not have friends that know much about flash.
So, I've been working on making a basic 2D platform. I'm having problems figuring out how to implement the points on the character and bg.hitTestPoint. As it stands, before I worked the points and everything in, it was working fine. I have a trace in, to let me know when it considers it a collision with the object (In this case a wall).
The character's dimensions are:
Top Center: (42,0)
Bot Center: (42,112)
R. Center: (84,56)
L. Center: (0,56)
Total Image: 84 x 112 (px)
The character's location on the screen:
Top Center: (46, 460)
Bot Center: (46, 379)
L. Center: (20, 440)
R. Center: (80,420)
Here are the blocks:
The bump/collision variables:
var leftB:Boolean = false;
var rightB:Boolean = false;
var topB:Boolean = false;
var botB:Boolean = false;
var topBPt:Point = new Point(42, 0);
var botBPt:Point = new Point(42, 112);
var leftBPt:Point = new Point(0, 56);
var rightBPt:Point = new Point(84, 56);
The hitTestPoint block: (To save space, I'll just do the top one.)
if(bg.hitTestPoint(fag.x + topBPt.x, fag.y + topBPt.y, true))
{
trace("Top Bump works.");
topB = true;
}
else
{
topB = false;
}
if(topB)
{
if(ySpeed < 0)
{
ySpeed *= -0.5;
}
}
I tried to use different dimensions, there is a small chance I may just not have understood the full explanation on the site I was reading.
Also, I have a feeling I can work around it by just making it a hitTestObject, and manually making each part of the wall different...But I don't see that as efficient or reasonable. Thanks for any help.
The math for finding out the collision for rectangular areas is generally the same.
First of all after glancing your code, define your screen objects as objects... I mean sublass Sprite class and add properties to it, do not do it via globals...
Like:
public class myScreenObjs extends Sprite {
// Add the tricky cool specialities and properties here
}
Normally a sprite exposes its x and y coordinates. If dynamically created x and y are at top left of the sprite, if via cs6 you better take the o with cross from center to top left for having a common ground of reference. Centered x y references are good for 3d specially when rotation needed.
A sprite has width and height properties also.
Lets assume you have sprites c (character) and b (block to bump)
Given:
left is left x of an object.
right is right x of an object.
top is top y of an object.
bottom is bottom y of an object.
I know this is a not very optimal function but I am writing it for demonstration purpose.
function bumpTest(c: Sprite, b: Sprite):Object {
var
r: * = {},
cLeft : int = c.x, // doing this for demonstrating you can directly use c.x
cRight : int = c.x + c.width,
cTop : int = c.y, // same
cBottom : int = c.y + c.height,
bLeft : int = b.x, // same
bRight : int = b.x + b.width,
bTop : int = b.y, // same
bBottom : int = b.y + b.height;
r.left = Boolean ((cLeft >= bLeft) && (cLeft <= bRight));
r.right = Boolean ((cRight >= bLeft) && (cRight <= bRight));
r.top = Boolean ((cTop >= bTop) && (cTop <= bBottom));
r.bottom = Boolean ((cBottom >= bTop) && (cBottom <= bBottom));
r.bump = Boolean ((r.left || r.right)&&(r.top || r.bottom));
return(r);
}
Now r has the complete answer, If r.bump is false the other values in r are irrelevant.
If r.bump turns to be true, then you can check via r.left etc from where c bumps into b. since:
r.left true means c left is into or at boundary of b.
r.right true means c right is into or at boundary of b.
r.top true means c top is into or at boundary of b.
r.bottom true means c bottom is into or at boundary of b.

Finding Something lighter than Sprites!

I am making a Sim City like game. There are lots of tiles. When I first started. I was just using a tilesheet. I was copying the necessary pieaces from the tilesheet. on to a blank bitMapData. I then took the bitMapData and put it into a bitMap which I then put into a DisplayObject. It worked great!
tileSheet:BitMapData <----- data is already in
loop { loop through and tiled
bg:bitMapData= new bitMapData();
bg.copyPixel(tileSheet,rect,point);
}
canvas.BitMap(bg);
addChild(canvas);
Only problem was I needed to make my tiles interactive. I needed to highlight them and change colors and stuff. So I used the Sprite object. It works great but I can only have so many on the stage at once. or else it moves slow when I scroll. I need something Lighter then a sprite, but yet I can still turn into a object to make interactive. Anyone have any ideas ???
If you have a lot of tiles, that will impact performance because Flash needs to update the transformations of a lot of display objects (which internally means a lot of matrix calculations, and subsequent redraws of big areas of the screen.)
There is another way to achieve interactivity, if you find that you must use a single bitmap data for performance. Keep an "abstract" (i.e. not graphical) data model in memory, that stores your game state. Make sure that you are able to read from your store where a certain element is positioned in the game world. Then you can use a flat bitmap data to render the game world, because the individual positions are stored elsewhere.
When the user clicks the DisplayObject containing the bitmap data (a Sprite in which the bitmap is drawn using a bitmap fill, or that wraps a Bitmap), look in your model which of your game elements was hit by that click.
// myTileSprite is a Sprite with a bitmap fill
myTileSprite.addEventListener(MouseEvent.CLICK, handleWorldClick);
function handleWorldClick(ev : MouseEvent) : void
{
var i : int;
// Loop through all game element data models
for (i=0; i<myGameElements.length; i++) {
// Test the mouse position against the element model
if (myGameElements[i].hitTest(myTileSprite.mouseX, myTileSprite.mouseY)) {
trace('this was the element that was clicked: '+myGameElements[i].toString());
}
}
}
Here, whenever the player clicks the world graphics, the loop tries to find that element which was directly under the mouse position. You will need to implement a hitTest() method on all your game element data models, of course. Such a method simply checks the supplied world space position against the tile's area:
// GameElement.hitTest():
/**
* Tests a world position against the position and area of this game
* element tile. Returns a boolean indicating whether this tile was hit.
*/
public function hitTest(mouseX : Number, mouseY : Number) : void
{
var rect : Rectangle = new Rectangle(this.worldX, this.worldY, this.width, this.height);
if (mouseX > rect.left && mouseX < rect.right
&& mouseY > rect.top && mouseY < rect.top) {
return true;
}
else return false;
}
The GameElement class is not an display object, but has worldX and worldY properties indicating where it is located in the world. It's width and height properties define it's dimensions.
The trick from hereon is to make sure that the rendered bitmap and your model storage is synchronized, so that a tile's position on the bitmap really corresponds to it's worldX/worldY properties in the data model.
I am one step ahead of you. And that is a great idea. Its alot easier to keep a data representation of the world when the tiles are squared. I therefore can take my mouseX/tileWidth, and thats hw many columns I moved from left to right. same with the Y axis.
Not only that but coordinates start at top left corner.
But issue I have is that my tiles are Isometric. So instead of the X axis start off like...
012345678
0
1
2
3
4
5
6
7
8
My tiles are aligned like...
00
1 1
2 2
3 3
4 4
5 6
its a little sloppy. but the right side represents the y axis and the left represents the x axis. and the center origin is in the center of the screen. not on the top left. I am trying to figure out how to measure where my mouse is from the center and out on both sides. This sounds extremely difficult. I am not sure if its possible. The game is suppose to be like a sim city like game. The first sim city was squares not isometric. I dont think they went isometric until they started using 3d. I wonder if its possible to create a illusion of isometric on a square tile.
Ive been reading this great book on isometrics. They show to calculate tiles in 3d space. and even calculate your mouse in 3d space as well. here is the code. Its alot, but I hope someone else understands it more then I. The book was written by jobe makar on building multiplayer worlds. I wanted to share it because the code it is pretty simple as far as amount of code put into it. only 2 classes needed. I am not that good with trigonometry. so I cant really interpret how the math is getting the results. hopefully someone can explain that for me :D.
Y coordinates are not given because the width is = to height. The coordinates method is just a custom made Point class which holds x, y and z.
package com.gamebook.grid {
import com.gamebook.utils.geom.Coordinate;
import com.gamebook.utils.Isometric;
import flash.display.MovieClip;
import flash.events.MouseEvent;
/**
* ...
* #author Jobe Makar - jobe#electrotank.com
*/
public class Map extends MovieClip{
private var _grid:Array;
private var _iso:Isometric;
private var _tileWidthOnScreen:int;
private var _tileHeightOnScreen:int;
private var _tileWidth:Number;
private var _tileHeight:Number;
private var _cols:int;
private var _rows:int;
private var _lastTile:Tile;
public function Map() {
initialize();
}
private function initialize():void{
_iso = new Isometric();
//when mapped to the screen the tile makes a diamond of these dimensions
_tileWidthOnScreen = 64;
_tileHeightOnScreen = 32;
//figure out the width of the tile in 3D space
_tileWidth = _iso.mapToIsoWorld(64, 0).x;
//the tile is a square in 3D space so the height matches the width
_tileHeight = _tileWidth;
buildGrid();
addEventListener(MouseEvent.MOUSE_MOVE, mouseMoved);
}
private function mouseMoved(e:MouseEvent):void {
if (_lastTile != null) {
_lastTile.alpha = 1;
_lastTile = null;
}
var coord:Coordinate = _iso.mapToIsoWorld(mouseX, mouseY);
var col:int = Math.floor(coord.x / _tileWidth);
var row:int = Math.floor(Math.abs(coord.z / _tileHeight));
if (col < _cols && row < _rows) {
var tile:Tile = getTile(col, row);
tile.alpha = .5;
_lastTile = tile;
}
}
private function buildGrid():void{
_grid = [];
_cols = 10;
_rows = 10;
for (var i:int = 0; i < _cols;++i) {
_grid[i] = [];
for (var j:int = 0; j < _rows;++j) {
var t:Tile = new Tile();
var tx:Number = i * _tileWidth;
var tz:Number = -j * _tileHeight;
var coord:Coordinate = _iso.mapToScreen(tx, 0, tz);
t.x = coord.x;
t.y = coord.y;
_grid[i][j] = t;
addChild(t);
}
}
}
private function getTile(col:int, row:int):Tile {
return _grid[col][row];
}
}
}
Then we have the isometric class that calculates 3d space.
package com.gamebook.utils {
import com.gamebook.utils.geom.Coordinate;
/**
* #author Jobe Makar - jobe#electrotank.com
*/
public class Isometric {
//trigonometric values stored for later use
private var _sinTheta:Number;
private var _cosTheta:Number;
private var _sinAlpha:Number;
private var _cosAlpha:Number;
/**
* Isometric class contrustor.
* #param declination value. Defaults to the most common value, which is 30.
*/
public function Isometric() {
var theta:Number = 30;//even though the tiles are already isometric, you still have to put the degrees the tiles will be turned.
var alpha:Number = 45;//45 degrees on y axis, 30 dgrees on x axis
theta *= Math.PI/180; // then you translate to radians
alpha *= Math.PI/180;
_sinTheta = Math.sin(theta);
_cosTheta = Math.cos(theta);
_sinAlpha = Math.sin(alpha);
_cosAlpha = Math.cos(alpha);
}
/**
* Maps 3D coordinates to the 2D screen
* #param x coordinate
* #param y coordinate
* #param z coordinate
* #return Coordinate instance containig screen x and screen y
*/
public function mapToScreen(xpp:Number, ypp:Number, zpp:Number):Coordinate {
var yp:Number = ypp;
var xp:Number = xpp*_cosAlpha+zpp*_sinAlpha;
var zp:Number = zpp*_cosAlpha-xpp*_sinAlpha;
var x:Number = xp;
var y:Number = yp*_cosTheta-zp*_sinTheta;
return new Coordinate(x, y, 0);
}
/**
* Maps 2D screen coordinates into 3D coordinates. It is assumed that the target 3D y coordinate is 0.
* #param screen x coordinate
* #param screen y coordinate
* #return Coordinate instance containig 3D x, y, and z
*/
public function mapToIsoWorld(screenX:Number, screenY:Number):Coordinate {
var z:Number = (screenX/_cosAlpha-screenY/(_sinAlpha*_sinTheta))*(1/(_cosAlpha/_sinAlpha+_sinAlpha/_cosAlpha));
var x:Number = (1/_cosAlpha)*(screenX-z*_sinAlpha);
return new Coordinate(x, 0, z);
}
}
}