//World v0.9.6 +|+ vangame
class World {
    
    private canvas:     HTMLCanvasElement;
    private context:    CanvasRenderingContext2D;

    private image:      Images;
    //private colors:     Colors;

    //worldsize
    private mapX :      number = 0;
    private mapY :      number = 0;
    
    //camera pos
    private camX :      number = 0;
    private camY :      number = 0;
    private playerCamPos = [];

    //Player positioning and spawncounts
    private playerX :   number = 0;
    private playerY :   number = 0;
    private playerPos = [];
    private spawncount : number = 0;
    
    //Used for looking up window size to render map
    private windowX :   number = 0;
   	private windowY :   number = 0;
    
    //Map arrays (Heightmap for 3D usage possible)
    private heightmap = new Array();
    private tiles =     new Array();
    private tileSize :  number = 24;
    private maxTiles :  number = 500; 
    private maxBalls :  number = 3000; //1500;

    private tileswitch : boolean = true;
    private tileswitchtimer;

    //Map zoom in/out
    private zoomlevel : number = 1;
    private maxzoomout : number = 5;
    private zoompx : number = 4;

    private tilecolors = [
        //water (0)
        "#4997FF", //"#197CFF", 

        //desert (1, 2)
        "#E8C916", "#E8C916", 

        //plains (3, 4)
        "#5BB822", "#5BB822", 

        //trees (5, 6)
        "#4B981C", "#4B981C", 

        //hills (7, 8)
        "#AFE037", "#AFE037",

        //mountains (9, 10, 11, 12)
        "#CCCCCC", "#CCCCCC", "#CCCCCC", "#FFFFFF",

        //buildings (13, 14)
        "#FFEC8E", "#5BB822",

        //roads (15,25)
        "#808060", "#808060", "#808060", "#808060", "#808060", "#808060", "#808060", "#808060", "#808060", "#808060", "#808060",
        
        //test npc (26)
        "#333333",

        //Wildlife Addition --

        //bushes (27, 28, 29)
        "#5da53a", "#5da53a", "#5da53a",

        //trees (cutted) (30, 31)
        "#4B981C", "#4B981C"
    ];
    
    private minimalimgdraw = 16;

    //what should it say when you click a tile?
    private generictilename = [
        "water", 

        "cactus", "desert", 

        "plains", "plains", 

        "tree", "tree",

        "hills", "hills",

        "mountain", "mountain", "mountain", "mountain snow",
        
        "town", "watch tower",
        
        "road", "road", "road", "road", "road", "road", "road", "road", "road", "road", "road",
        
        "npc",

        //Wildlife Addition --

        "bushes", "bushes", "bushes",
        
        "cutted tree", "cutted tree"
    ];
    
    private typebyheight : number[] = [
        1,
        6,
        40,
        50,
        70
    ];
    
    private spawnlocs = new Array();
    
    private town = new Array();
    private towndistance : number = 15;
    private townid : number = 0;
    
    private minimalWoodstock : number   = 6;
    private minimalStonestock : number  = 10;

    private townnames = new Array(
        //0
        ["New ", "Old ", "Belle-", "Great ", "Fine ", "Fort ", "Grand ", "Jolly ", "Los ", "Sugary ", "Spooky ", "Lonely ", "Mystic ", "Golden ", "Port ", "San ", "Muddy ", "Snowy ", "Camp ", "Rio ", "Santa ", "Les ", "Cote des ", "El ", "Long ", "Baja ", "Grassy ", "Rosey ", "Lake ", "Hillside ", "Saint ", "Novi ", "Lone ", "Forgotten ", "Priest's ", "Shady ", "Abandoned ", "Hopeless ", "Fore ", "Virgin ", "Haunted ", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""],
        
        //1
        ["Babble", "Courtney", "Mansel", "Winston", "Apple", "Horse", "Otter", "Scorpion", "Banana", "Baby", "Merkel", "Dinkle", "Lumber", "Middle", "Moose", "Camel", "Glenn", "Or", "William", "Black", "White", "Yellow", "Wood", "Stone", "Iron", "Goat", "Gold", "Red", "Copper", "Mud", "John", "Dave", "Snow", "Turkey", "Red", "Cracker", "Miccous", "Mingle", "Fiddle", "Sparkle", "Cox", "Flint", "Triangle", "Gar", "Man", "Power", "Fish", "Bear", "Coffee", "Little", "Ever", "Bread", "Wheat", "Yarn", "Pannekoeken", "Cookie", "Mother", "Tallapoose", "Yazoo", "Skeleton", "Boo", "Fire", "Zulu", "Water", "Sky", "Christmas", "Thanksgiving", "Indiana", "Pine", "Oak", "Willow", "Maple", "Ogre", "Goblin", "Trollen", "Amster", "Bone", "Children", "Bingo", "Wanker", "Church", "God", "Locust", "Crab", "Fertile", "Ash", "Mattock", "Manter", "Yangle", "Work", "Butter", "Jelly", "Liberty", "Milk", "Glob", "Jack", "Duffel", "Corner", "Rabbit", "Christ", "School", "Tornado", "Tsunami", "Earthquake", "Odin", "Zeus", "Fork", "Spoon", "Machete", "Friend", "Kindle", "Chicken", "Goose", "Duck", "Croc", "Alligator", "Rock", "Scissor", "Candle", "Gust", "Chipper", "Spider", "Lady", "Gentle", "Clay", "Serb", "Windmill", "Citron", "Lemon", "Melon", "Paper", "Flash", "Frog", "Toad", "Snake", "Bell", "Ringing", "Pineapple", "Meat", "Super", "Wax", "Herb", "Almond", "Dagger", "Pilk", "Silk", "War"],
        
        //2
        [" Field", "heim", "ville", " City", " Valley", " Town", "shire", "-Pablos", " Village", "ton", "dale", "list", "ington", "-Ex", "lington", "lee", " Harbor", "ey", "moore", "loo", " Hole", " Well", " Plateau", " Swamp", "-Roche", " Rogue", " Crater", " Paradise", " Hill", " Hot", " Station", " Arm", " Coast", " Beach", "daal", " Stad", "er", "ard", "gaard", "garde", "mont", "burg", " Platte", "wood", " Park", " Springs", "green", "ery", " Sad", " Peak", " Edge", " High", "way", "craft", "fall", "clap", " Lodge", "Hope", " Chance", " Vault", "Cafe", "-Ginn", "dam", "'s Last Stand"]);

    constructor(maxtiles:number = 500, balls:number = 1500, sand:number = 1, ground:number = 6, hill:number = 40, mountain:number = 50, snowtop:number = 70, towndistance:number = 15)
    {
        //preload images
        /*for (var i = 0; i < this.tileimgurl.length; i++)
        {
            document.getElementById('preload').innerHTML+="<img src='"+this.tileimgurl[i]+"'/>"; 
        }*/
        this.image = new Images(false);
        
        this.maxTiles = maxtiles;
        this.maxBalls = balls;
        
        this.mapX = this.maxTiles;
        this.mapY = this.maxTiles;
        
        this.windowX = Math.floor(window.innerWidth / this.tileSize)+1;
        this.windowY = Math.floor(window.innerHeight / this.tileSize);

        this.typebyheight[0] = sand;
        this.typebyheight[1] = ground;
        this.typebyheight[2] = hill;
        this.typebyheight[3] = mountain;
        this.typebyheight[4] = snowtop;

        this.runTimers();
    }

    public setupWorld()
    {
        this.generateNewWorld(this.maxTiles, this.maxBalls);
    }
    
    public updateWorldDisplay() //CANVAS DRAWING / UPDATING VISUAL
    {
        var canvasx = 0, canvasy = 0, tid, playerID = 0;
        this.canvas = document.getElementsByTagName("canvas")[0];
        this.context = this.canvas.getContext('2d');
        
        this.canvas.style.backgroundColor = this.tilecolors[0];
        
        //for(let x = this.camX; x < this.camX+this.windowX; x++)
        for(let x = this.getPlayerCamX(playerID); x < this.getPlayerCamX(playerID)+this.windowX; x++)
        {
            //for(let y = this.camY; y < this.camY+this.windowY; y++)
            for(let y = this.getPlayerCamY(playerID); y < this.getPlayerCamY(playerID)+this.windowY; y++)
            {
                this.context.beginPath();
                this.context.rect(canvasx, canvasy, this.tileSize, this.tileSize);
                if(this.tiles[x][y] >= 0)
                {
                    this.context.fillStyle = this.tilecolors[this.tiles[x][y]];
                }
                this.context.fill();
                
                //throw border away when done testing?
                this.context.lineWidth = 0;
                this.context.strokeStyle = 'grey';
                this.context.stroke();

                if(this.tileSize > this.minimalimgdraw)
                {
                    var img = new Image();
                    //if(x == this.playerX && y == this.playerY)
                    if(x == this.getPlayerWorldX(playerID) && y == this.getPlayerWorldY(playerID))
                    {
                        //if(this.tiles[this.playerX][this.playerY] > 0)
                        if(this.tiles[this.getPlayerWorldX(playerID)][this.getPlayerWorldY(playerID)] > 0)
                        {
                            //img.src = this.tileimgurl[0];
                            img.src = this.image.getTileImage(0);
                        }
                    }else{
                        if(this.tiles[x][y] > 0)
                        {
                            //img.src = this.tileimgurl[this.tiles[x][y]]; 
                            img.src = this.image.getTileImage(this.tiles[x][y]);
                        }
                    }
                    //+2 for image centering
                    this.context.drawImage(img, canvasx+2, canvasy+2, this.tileSize-4, this.tileSize-4);
                }
                canvasy = canvasy+this.tileSize;	
            }
            canvasx = canvasx+this.tileSize;
            canvasy = 0;
        }
        
        return true;
    }
    
    private fillNewWorldTiles(max:number) : void //THIS IS WHERE THE WORLD IS FILLED WITH TILES
    {
        //begin
        let scale = 100/max;
        let spawncount = 0;
        for(let x = 0; x < this.mapX; x++)
        {
            for(let y = 0; y < this.mapY; y++)
            {
                let hh = Math.floor(this.heightmap[x][y] * scale);
			    this.heightmap[x][y] = hh;
                
                if(hh >= this.typebyheight[4]){ //snow
                    this.tiles[x][y] = 12;
                }else if(hh >= this.typebyheight[3]){ //mountains
                    if(this.tileSort(50, 0))
                    {
                        if(this.tileSort(50, 0))
                        {
                            this.tiles[x][y] = 10;
                        }else{
                            this.tiles[x][y] = 11;
                        }
                    }else{
                        this.tiles[x][y] = 9;
                    }
                }else if(hh >= this.typebyheight[2]){ //hills
                    if(this.tileSort(50, 0))
                    {
                        this.tiles[x][y] = 8;
                    }else{
                        this.tiles[x][y] = 7;
                    }
                    this.addSpawnLoc(x, y);
                }else if(hh >= this.typebyheight[1]){ //normal ground
                                    
                    if(this.tileSort(98, 0)) //towns
                    {
                        if(this.tileSort(90, 0)) //another check
                        {
                            //looks if theres a town nearby, else place plain land
                            let tdist = Math.floor(Math.random()*(this.towndistance))+this.towndistance;
                            if(this.tileOutRange(x, y, 13, tdist))
                            {
                                let townname = "";

                                for(let i = 0; i < this.townnames.length; i++)
                                {
                                    townname += String(this.townnames[i][Math.floor(Math.random()*this.townnames[i].length)]);
                                }
                                this.tiles[x][y] = 13;
                                this.town[this.townid] = [];
                                this.town[this.townid][0] = townname;
                                this.town[this.townid][1] = x;
                                this.town[this.townid][2] = y;
                                this.town[this.townid][3] = this.minimalWoodstock;
                                this.town[this.townid][4] = this.minimalStonestock;
                                console.log(this.town[this.townid][1]+","+""+this.town[this.townid][2]+" - (tid: "+this.townid+") name: "+ this.town[this.townid][0]);
                                this.townid++;

                            }else{
                                
                                if(this.tileSort(50, 0)) //different plains
                                {
                                    this.tiles[x][y] = 3;
                                }else{
                                    this.tiles[x][y] = 4;
                                }
                                this.addSpawnLoc(x, y);
                            }

                        }else{ //just plain
                            if(this.tileSort(60, 0)) //watchtower or plains
                            {
                                this.tiles[x][y] = 14;
                            }else{
                                
                                if(this.tileSort(50, 0)) //different plains
                                {
                                    this.tiles[x][y] = 3;
                                }else{
                                    this.tiles[x][y] = 4;
                                }
                                this.addSpawnLoc(x, y);
                            }
                        }
                    }else{ //plains/bushes or trees
                        if(this.tileSort(40, 50))
                        {
                            if(this.tileSort(50, 0)) //different trees
                            {
                                if(this.tileSort(8, 0)) //different trees (uncutted and cutted)
                                {
                                    this.tiles[x][y] = 5;
                                }else{
                                    this.tiles[x][y] = 30;
                                }
                            }else{
                                if(this.tileSort(8, 0)) //different trees v2 (uncutted and cutted)
                                {
                                    this.tiles[x][y] = 6;
                                }else{
                                    this.tiles[x][y] = 31;
                                }
                            }
                        }else{
                            if(this.tileSort(15, 0)) //plains or bushes
                            {
                                if(this.tileSort(50, 0)) //different plains
                                {
                                    this.tiles[x][y] = 3;
                                }else{
                                    this.tiles[x][y] = 4;
                                }
                                this.addSpawnLoc(x, y);
                            }else{
                                if(this.tileSort(60, 0)) //different bushes
                                {
                                    this.tiles[x][y] = 27;
                                }else{
                                    this.tiles[x][y] = 29;
                                }
                            }
                        }
                    }
                }else if(hh >= this.typebyheight[0]){
                    if(this.tileSort(8, 0)) //cactus or sandplains
                    {
                        this.tiles[x][y] = 2;
                    }else{
                        this.tiles[x][y] = 1;
                    }
                }else{
                    this.tiles[x][y] = 0;
                }
                
            }
        }
        //end
    }
    
    private generateNewWorld(maxtiles:number, balls:number) //THIS IS ONLY GENERATING HEIGHT
    {   
        //begin
        for(let i = 0; i < this.mapX; i++)
        {
            this.heightmap[i] = [];
            this.tiles[i] = [];
            for(let j = 0; j < this.mapY; j++)
            {
                this.heightmap[i][j] = 0;
            }
        }
        
        let max = 0;
        for(let i = 0; i < balls; i++)
        {
            let ballx = Math.floor(Math.random()*(this.mapX-30)+15);
            let bally = Math.floor(Math.random()*(this.mapY-30)+15);
            let ballr = Math.floor(Math.random()*(10)+5);

            for(let x = -ballr; x <= ballr; x++)
            {
                for(let y = -ballr; y <= ballr; y++)
                {
                    let h = ballr*ballr - x*x - y*y;
                    
                    if(h > 0)
                    {
                        let cx = ballx+x;
                        let cy = bally+y;

                        if(cx > 0 && cx <= this.mapX && cy > 0 && cy <= this.mapY)
                        {
                            
                            let hh = this.heightmap[cx][cy] + h;
                            this.heightmap[cx][cy] = hh;
                            if(hh > max)
                            {
                                max = hh;
                            }
                        }
                    }
                }
            }
        }
        
        this.fillNewWorldTiles(max);
        //end          
    }

    //update a single tile
    private TileSwitcher(type : number, playerID : number = 0)
    {
        //player flicker
        if(type == 0)
        {
            this.canvas = document.getElementsByTagName("canvas")[0];
            this.context = this.canvas.getContext('2d');	

            if(this.tileswitch){
                this.tileswitch = false;
            }else{
                this.tileswitch = true;
            }

            //var ux = (this.playerX-this.camX)*this.tileSize;
            //var uy = (this.playerY-this.camY)*this.tileSize;
            
            //var ux = (this.getPlayerWorldX(playerID)-this.camX)*this.tileSize;
            //var uy = (this.getPlayerWorldY(playerID)-this.camY)*this.tileSize;
           
            var ux = (this.getPlayerWorldX(playerID)-this.getPlayerCamX(playerID))*this.tileSize;
            var uy = (this.getPlayerWorldY(playerID)-this.getPlayerCamY(playerID))*this.tileSize;

            var img = new Image();
            
            this.context.beginPath();
            this.context.rect(ux, uy, this.tileSize, this.tileSize);
            //this.context.fillStyle = this.tilecolors[this.tiles[this.playerX][this.playerY]];
            this.context.fillStyle = this.tilecolors[this.tiles[this.getPlayerWorldX(playerID)][this.getPlayerWorldY(playerID)]];
            this.context.fill();

            if(this.tileSize > this.minimalimgdraw)
            {	
                if(this.tileswitch)
                {	
                    //img.src = this.image.getTileImage(this.tiles[this.playerX][this.playerY]);
                    img.src = this.image.getTileImage(this.tiles[this.getPlayerWorldX(playerID)][this.getPlayerWorldY(playerID)]);
                }else{
                    img.src = this.image.getTileImage(0);
                }
                this.context.drawImage(img, ux+2, uy+2, this.tileSize-4, this.tileSize-4);
            }else{ //make only player position visible by maximum outzooming
                img.src = this.image.getTileImage(0);
                this.context.drawImage(img, ux-4, uy-4, this.tileSize+8, this.tileSize+8);
            }
        }else{
        //----------------------------------
        /*if(type == 1) //npc flicker
        {

            if(tileswitcher[type]){
                tileswitcher[type] = false;
            }else{
                tileswitcher[type] = true;
            }
            if(tileSize > minimalimgdraw)
            {
                for(var i = 0; i < npc.length; i++)
                {	
                    var npcX = npc[i][1];
                    var npcY = npc[i][2];

                    ux = (npcX-camX)*tileSize;
                    uy = (npcY-camY)*tileSize;

                    var img = new Image();
                    
                    context.beginPath();
                    context.rect(ux, uy, tileSize, tileSize);
                    context.fillStyle = tilecolors[tiles[npcX][npcY]];
                    context.fill();

                        
                    if(tileswitcher[type])
                    {	
                        img.src = tileimgurl[tiles[npcX][npcY]];
                    }else{
                        img.src = tileimgurl[npc[i][3]];
                    }
                    context.drawImage(img, ux+2, uy+2, tileSize-4, tileSize-4);
                    
                }
            }*/
        }
    }

    //tile generation placement chance
    private tileSort(range:number, extraoff:number)
    {
        if(Math.floor(Math.random()*(100)-extraoff) > range)
        {
            return true;
        }else{
            return false;
        }
    }
    
    //checks if a tile is out of a specific range
    private tileOutRange(x:number, y:number, tiletype:number, distance:number)
    {
        for(let x2 = x+distance; x2 > (x-distance); x2--)
        {
            for(let y2 = y+distance; y2 > (y-distance); y2--)
            {
                if(x2 > distance && y2 > distance && x2 < this.mapX-distance && y2 < this.mapY-distance)
                {
                    if(this.tiles[x2][y2] == tiletype)
                    {
                        return false;
                    }
                }
            }	
        }
        return true;
    }
    
    private addSpawnLoc(x:number, y:number)
    {
        this.spawnlocs[this.spawncount] = [];
        this.spawnlocs[this.spawncount][0] = x;
        this.spawnlocs[this.spawncount][1] = y;
        return this.spawncount++;
    }

    private clickedTileInfo(x, y)
    {
        var string = "", playerID = 0;
        /*for(var i = 0; i < npc.length; i++) //NO NPCS YET
        {
            if(x == npc[i][1] && y == npc[i][2])
            {
                string = "<p>clicked on "+npc[i][6]+" ("+x+"-"+y+"-"+tiles[x][y]+")</p>";
                return document.getElementById('clickinfo').innerHTML = string;
                break;
            }
        }*/
        //if(x == this.playerX && y == this.playerY)
        if(x == this.playerPos[playerID][0] && y == this.playerPos[playerID][1])
        {
            string = "<p>clicked on player ("+x+"-"+y+"-"+this.tiles[x][y]+")</p>";	
        }else{
            //if(this.tiles[x][y] < 13)
            //{
                string = "<p>clicked on "+this.generictilename[this.tiles[x][y]]+" ("+x+"-"+y+"-"+this.tiles[x][y]+")</p>";	
            //}else
             if(this.tiles[x][y] == 13){
                for(var i = 0; i < this.town.length; i++)
                {
                    if(this.town[i][1] == x && this.town[i][2] == y)
                    {
                        string = "<p>clicked on '"+this.town[i][0]+"' ("+x+"-"+y+"-"+this.tiles[x][y]+" townid "+i+" | woodstock = "+this.town[i][3]+", stonestock = "+this.town[i][4]+")</p>";		
                        return document.getElementById('clickinfo').innerHTML = string;
                    }
                }
             }
            /*}else{
                string = "<p>clicked on "+x+"-"+y+"-"+this.tiles[x][y]+"</p>";	
            }*/
            
        }
        return document.getElementById('clickinfo').innerHTML = string;
    }

    public getTileType(x :number, y : number)
    {
        return this.tiles[x][y]
    }

    public setTileType(x :number, y : number, type : number)
    {
        return this.tiles[x][y] = type;
    }

    public addPlayer(playerID) : void
    {
        this.playerPos[playerID] = [];
        this.playerPos[playerID][0] = 0;
        this.playerPos[playerID][1] = 0;

        this.playerCamPos[playerID] = [];
        this.playerCamPos[playerID][0] = 0;
        this.playerCamPos[playerID][1] = 0;
    }

    //looks for a specific tile around player
    public getTileAroundPlayer(playerID : number = 0, x : number = 0, y : number = 0)
    {
        //return this.tiles[this.playerX+x][this.playerY+y]
        return this.tiles[this.playerPos[playerID][0]+x][this.playerPos[playerID][1]+y]
    }
    
    public getPlayerTile(playerID : number = 0)
    {
        //return this.tiles[this.playerX][this.playerY]
        return this.tiles[this.playerPos[playerID][0]][this.playerPos[playerID][1]]
    }

    public setPlayerCamera(playerID : number = 0, x : number, y : number) : void
    {
        this.playerCamPos[playerID][0] = x;
        this.playerCamPos[playerID][1] = y;
    }

    public setPlayerCameraX(playerID : number = 0, x : number)
    {
        return this.playerCamPos[playerID][0] = x;
    }

    public setPlayerCameraY(playerID : number = 0, y : number)
    {
        return this.playerCamPos[playerID][1] = y;
    }

    public getPlayerWorldX(playerID : number = 0)
    {
        //return this.playerX
        return this.playerPos[playerID][0];
    }
    
    public getPlayerWorldY(playerID : number = 0)
    {
        //return this.playerY
        return this.playerPos[playerID][1];
    }

    public setPlayerWorldPos(playerID : number = 0, x : number, y : number) : void
    {
        /*this.playerX = x;
        this.playerY = y;*/

        this.playerPos[playerID][0] = x;
        this.playerPos[playerID][1] = y;
    }

    public getPlayerCamX(playerID : number = 0) {
        //return this.camX
        return this.playerCamPos[playerID][0];
    }

    public getPlayerCamY(playerID : number = 0) {
        //return this.camY
        return this.playerCamPos[playerID][1];
    }

    /*public setCamPos(x : number, y : number) : void
    {
        this.camX = x;
        this.camY = y;
    }*/

    public getSpawnLocations() {
        return this.spawnlocs;
    }

    // looks for tile appearance, only gives back true or false
    public searchForTileType(x : number, y : number, tiletype : number)
    {
        let beginx = x-1,
            beginy = y-1,
            endx = x+1,
            endy = y+1

        for(let i = beginx; i <= endx; i++)
        {
            for(let j = beginy; j <= endy; j++)
            {
                if(this.tiles[i][j] == tiletype)
                {
                    return true
                }
            }
        }
        return false;
    }

    //returns the surrounding tiles back
    public searchForTileTypeReturnClosest(x : number, y : number, tiletype : number)
    {
        let beginx = x-1,
            beginy = y-1,
            endx = x+1,
            endy = y+1,
            ret = new Object(),
            nr = 0;

        for(let i = beginx; i <= endx; i++)
        {
            for(let j = beginy; j <= endy; j++)
            {
                
                if(this.tiles[i][j] == tiletype)
                {
                    ret[nr] = [];
                    ret[nr][0] = i;
                    ret[nr][1] = j;
                    ret[nr][2] = this.tiles[i][j];
                    nr++;
                } 
            }
        }
        return ret;
    }

    public camMovement(playerID : number = 0, dir:string) : void
    {
        if(dir == 'left')
        {
            if(this.getPlayerCamX(playerID) > 0)
            {
                //this.camX = this.camX - 1;
                this.setPlayerCameraX(playerID, (this.getPlayerCamX(playerID)-1));
            }
        }
        if(dir == 'right')
        {
            if(this.getPlayerCamX(playerID) < this.mapX-this.tileSize)
            {
                //this.camX = this.camX + 1;
                this.setPlayerCameraX(playerID, (this.getPlayerCamX(playerID)+1));
            }
        }
        if(dir == 'up')
        {
            if(this.getPlayerCamY(playerID) > 0)
            {
                //this.camY = this.camY - 1;
                this.setPlayerCameraY(playerID, (this.getPlayerCamY(playerID)-1));
            }

        }
        if(dir == 'down')
        {
            if(this.getPlayerCamY(playerID) < this.mapY-this.tileSize)
            {
                //this.camY = this.camY + 1;
                this.setPlayerCameraY(playerID, (this.getPlayerCamY(playerID)+1));
            }
        }
        this.updateWorldDisplay();
        //return true;
    }

    public mapZoom(zoom)
    {
        if(zoom == 'in' && this.zoomlevel > 0)
        {
            this.zoomlevel--;
            this.tileSize += this.zoompx;
            this.windowX = Math.floor(window.innerWidth / this.tileSize)+1,
            this.windowY = Math.floor(window.innerHeight / this.tileSize);
            
            return this.updateWorldDisplay();
        }
        else if(zoom == 'out' && this.zoomlevel < this.maxzoomout)
        {
            this.zoomlevel++;
            this.tileSize -= this.zoompx;
            this.windowX = Math.floor(window.innerWidth / this.tileSize)+1,
            this.windowY = Math.floor(window.innerHeight / this.tileSize);
            
            return this.updateWorldDisplay();
        }
    }

    public getPlayerClickedTileInfo(playerID : number = 0, ex : number, ey : number) : void
    {
        let cx = 0,
            cy = 0;
        
        cx = Math.floor(ex / this.tileSize);
    	cy = Math.floor(ey / this.tileSize);

		//cx = cx+this.camX;
		//cy = cy+this.camY;

        cx = cx+this.getPlayerCamX(playerID);
		cy = cy+this.getPlayerCamY(playerID);
		
		this.clickedTileInfo(cx, cy);
		//console.log("clicked type: " + this.tiles[cx][cy] + " " + cx + "-" + cy)
    }

    public runTimers()
    {
        this.tileswitchtimer = setInterval(()=> { this.TileSwitcher(0); }, 500);
    }

    public destroyTimer()
    {
        clearInterval(this.tileswitchtimer);
    }
}