androidcodeexamples.com
Offcode ltd logo
ANDROID
APACHE
THUMBNAILS
SHELL SCRIPTS
World-class examples brought to you by Offcode ltd
ANDROID
Developing the empire Bluetooth low energy Facebook API Google URL shortener Short URL lookup Tabs and fragments Privacy policy Front Page
androidcodeexamples.com

Android game programming - Empire game for Android. Chapter one.

In this example we discover a way to create the Empire-like strategy game UI. In this chapter we introduce a way to prepare everything for rendering. Unique GfxItems are declared for each grid item. The GfxItemPool loads up everything into the memory. MapManager creates a random map with desired land/sea ratio.

In the next chapter we show how the actual rendering takes place. This may also serve as a guide for developing any graphics intensive game on Android. Finally all the graphics are disclosed.

Next chapter
Android studio view
Android studio view


GfxItem

GfxItem.java contains the a single bitmap for just one element in the grid. The screen is divided into 128x128 pixel elements forming the grid as seen in the image on the right.

empire grid
The grid
package fi.offcode.empire; 
 
import android.content.res.Resources; 
import android.graphics.Bitmap; 
import android.graphics.BitmapFactory; 
 
/** 
 * Created by Eero on 23.2.2018. 
 */ 
 
public class GfxItem { 
    private Bitmap bitmap = null; 
 
    public GfxItem(Resources res, int id) { 
        bitmap = BitmapFactory.decodeResource(res, id); 
    } 
 
    public Bitmap getBitmap() { 
        return bitmap; 
    } 
} 

GfxItemTypes

This declares all the individual grid elements. All elements are given a unique ID. The ID's don't need to be sequential but unique.

package fi.offcode.empire; 
 
/** 
 * Created by Eero on 23.2.2018. 
 */ 
 
public class GfxItemTypes { 
    static final int gfxItemSea = 0; 
    static final int gfxItemLand = 1; 
 
    // Ids 
    static final int plainSea = 2; 
    static final int plainSea1 = 3; 
    static final int seaDeepSouth = 4; 
    static final int seaDeepNorth = 5; 
    static final int seaDeepEast = 6; 
    static final int seaDeepWest = 7; 
    static final int seaDeepSouthWest = 8; 
    static final int seaDeepSouthEast = 9; 
    static final int seaDeepNorthWest = 10; 
    static final int seaDeepNorthEast = 11; 
 
    static final int seaDeepSouthEastCorner = 12; 
    static final int seaDeepNorthWestCorner = 13; 
 
    static final int seaLandNorth = 22; 
    static final int seaLandNorth1 = 23; 
    static final int seaLandNorth_and_East = 24; 
    static final int seaLandNorth_and_East_and_South = 25; 
    static final int seaLandNorth_and_South = 26; 
 
    static final int seaLandWest = 35; 
    static final int seaLandWest1 = 36; 
    static final int seaLandWest_and_North = 37; 
    static final int seaLandWest_and_North_and_East = 38; 
    static final int seaLandWest_and_East = 39; 
 
    static final int seaLandSouth = 46; 
    static final int seaLandSouth1 = 47; 
    static final int seaLandSouth_and_West = 48; 
    static final int seaLandSouth_and_West_and_North = 49; 
 
    static final int seaLandEast = 62; 
    static final int seaLandEast1 = 63; 
    static final int seaLandEast_and_South = 64; 
    static final int seaLandEast_and_South_and_West = 65; 
 
 
    static final int seaLandNorthWest = 100; 
    static final int seaLandNorthEast = 101; 
    static final int seaLandSouthWest = 102; 
    static final int seaLandSouthEast = 103; 
 
    static final int seaSandNorthWest = 110; 
    static final int seaSandNorthEast = 111; 
    static final int seaSandSouthWest = 112; 
    static final int seaSandSouthEast = 113; 
 
    static final int plainLand = 1024; 
    static final int plainLandGrass512 = 1032; 
    static final int plainLandHill512 = 1033; 
    static final int plainLandSand512 = 1034; 
    static final int plainLandSandBorder512 = 1035; 
    static final int plainLandMountain512 = 1036; 
 
    static final int black = 2048; 
    static final int blackEast = 2050; 
    static final int blackNorth = 2051; 
    static final int blackWest = 2052; 
    static final int blackSouth = 2053; 
 
    static final int blackNorthEast = 2060; 
    static final int blackNorthWest = 2061; 
    static final int blackSouthWest = 2062; 
    static final int blackSouthEast = 2063; 
 
    static final int city = 4096; 
    static final int tank2 = 5000; 
    static final int select = 5010; 
} 

GfxItemPool

empire land
Empire land 512x512 pixels, id = plainLandGrass512
empire sea
Empire sea 128x128 pixels, id = sea

The pool contains all the GfxItems loaded into memory. In short, this has all the graphics. We have a few 512x512 items that fill the background. Most of the Gfx items are sized according to the grid square at 128x128 pixels. Sea is opaque at 74% (alpha channel resulting in transparency), so that we get it looking like a real sea with nice effects.

The 512x512 image is in jpg format here for saving space. However, all images are available in png format. In fact, all images we use in the app are in png format.

getGfxItem() returns (the last function in GfxItemPool.java) the bitmap according to its unique id.

package fi.offcode.empire; 
 
import android.content.res.Resources; 
import android.util.SparseArray; 
 
/** 
 * Created by Eero on 23.2.2018. 
 */ 
 
public class GfxItemPool { 
    private final SparseArray<GfxItem> gfxItems = new SparseArray<>(); 
 
    public GfxItemPool(Resources res) { 
        int type; 
 
        type = GfxItemTypes.plainSea; 
        GfxItem item = new GfxItem(res, R.drawable.sea); 
        gfxItems.append(type, item); 
 
        type = GfxItemTypes.plainSea1; 
        item = new GfxItem(res, R.drawable.sea1); 
        gfxItems.append(type, item); 
 
        type = GfxItemTypes.seaDeepSouth; 
        item = new GfxItem(res, R.drawable.sea_deep_south); 
        gfxItems.append(type, item); 
 
        type = GfxItemTypes.seaDeepNorth; 
        item = new GfxItem(res, R.drawable.sea_deep_north); 
        gfxItems.append(type, item); 
 
        type = GfxItemTypes.seaDeepEast; 
        item = new GfxItem(res, R.drawable.sea_deep_east); 
        gfxItems.append(type, item); 
 
        type = GfxItemTypes.seaDeepWest; 
        item = new GfxItem(res, R.drawable.sea_deep_west); 
        gfxItems.append(type, item); 
 
        type = GfxItemTypes.seaDeepSouthWest; 
        item = new GfxItem(res, R.drawable.sea_deep_southwest); 
        gfxItems.append(type, item); 
 
        type = GfxItemTypes.seaDeepSouthEast; 
        item = new GfxItem(res, R.drawable.sea_deep_southeast); 
        gfxItems.append(type, item); 
 
        type = GfxItemTypes.seaDeepNorthWest; 
        item = new GfxItem(res, R.drawable.sea_deep_northwest); 
        gfxItems.append(type, item); 
 
        type = GfxItemTypes.seaDeepNorthEast; 
        item = new GfxItem(res, R.drawable.sea_deep_northeast); 
        gfxItems.append(type, item); 
 
        type = GfxItemTypes.seaDeepSouthEastCorner; 
        item = new GfxItem(res, R.drawable.sea_deep_southeast_corner); 
        gfxItems.append(type, item); 
 
        type = GfxItemTypes.seaDeepNorthWestCorner; 
        item = new GfxItem(res, R.drawable.sea_deep_northwest_corner); 
        gfxItems.append(type, item); 
 
        type = GfxItemTypes.seaLandNorth; 
        item = new GfxItem(res, R.drawable.sea_land_north); 
        gfxItems.append(type, item); 
 
        type = GfxItemTypes.seaLandNorth1; 
        item = new GfxItem(res, R.drawable.sea_land_north1); 
        gfxItems.append(type, item); 
 
        type = GfxItemTypes.seaLandNorth_and_East; 
        item = new GfxItem(res, R.drawable.sea_land_north_east); 
        gfxItems.append(type, item); 
 
        type = GfxItemTypes.seaLandNorth_and_East_and_South; 
        item = new GfxItem(res, R.drawable.sea_land_north_east_south); 
        gfxItems.append(type, item); 
 
        type = GfxItemTypes.seaLandNorth_and_South; 
        item = new GfxItem(res, R.drawable.sea_land_north_and_south); 
        gfxItems.append(type, item); 
 
        type = GfxItemTypes.seaLandWest; 
        item = new GfxItem(res, R.drawable.sea_land_west); 
        gfxItems.append(type, item); 
 
        type = GfxItemTypes.seaLandWest1; 
        item = new GfxItem(res, R.drawable.sea_land_west1); 
        gfxItems.append(type, item); 
 
        type = GfxItemTypes.seaLandWest_and_North; 
        item = new GfxItem(res, R.drawable.sea_land_west_north); 
        gfxItems.append(type, item); 
 
        type = GfxItemTypes.seaLandWest_and_North_and_East; 
        item = new GfxItem(res, R.drawable.sea_land_west_north_east); 
        gfxItems.append(type, item); 
 
        type = GfxItemTypes.seaLandWest_and_East; 
        item = new GfxItem(res, R.drawable.sea_land_west_and_east); 
        gfxItems.append(type, item); 
 
 
        type = GfxItemTypes.seaLandSouth; 
        item = new GfxItem(res, R.drawable.sea_land_south); 
        gfxItems.append(type, item); 
 
        type = GfxItemTypes.seaLandSouth1; 
        item = new GfxItem(res, R.drawable.sea_land_south1); 
        gfxItems.append(type, item); 
 
        type = GfxItemTypes.seaLandSouth_and_West; 
        item = new GfxItem(res, R.drawable.sea_land_south_west); 
        gfxItems.append(type, item); 
 
        type = GfxItemTypes.seaLandSouth_and_West_and_North; 
        item = new GfxItem(res, R.drawable.sea_land_south_west_north); 
        gfxItems.append(type, item); 
 
        type = GfxItemTypes.seaLandEast; 
        item = new GfxItem(res, R.drawable.sea_land_east); 
        gfxItems.append(type, item); 
 
        type = GfxItemTypes.seaLandEast1; 
        item = new GfxItem(res, R.drawable.sea_land_east1); 
        gfxItems.append(type, item); 
 
        type = GfxItemTypes.seaLandEast_and_South; 
        item = new GfxItem(res, R.drawable.sea_land_east_south); 
        gfxItems.append(type, item); 
 
        type = GfxItemTypes.seaLandEast_and_South_and_West; 
        item = new GfxItem(res, R.drawable.sea_land_east_south_west); 
        gfxItems.append(type, item); 
 
 
        type = GfxItemTypes.seaLandNorthWest; 
        item = new GfxItem(res, R.drawable.sea_land_northwest); 
        gfxItems.append(type, item); 
 
        type = GfxItemTypes.seaLandNorthEast; 
        item = new GfxItem(res, R.drawable.sea_land_northeast); 
        gfxItems.append(type, item); 
 
        type = GfxItemTypes.seaLandSouthWest; 
        item = new GfxItem(res, R.drawable.sea_land_southwest); 
        gfxItems.append(type, item); 
 
        type = GfxItemTypes.seaLandSouthEast; 
        item = new GfxItem(res, R.drawable.sea_land_southeast); 
        gfxItems.append(type, item); 
 
 
        type = GfxItemTypes.seaSandNorthWest; 
        item = new GfxItem(res, R.drawable.sea_sand_northwest); 
        gfxItems.append(type, item); 
 
        type = GfxItemTypes.seaSandNorthEast; 
        item = new GfxItem(res, R.drawable.sea_sand_northeast); 
        gfxItems.append(type, item); 
 
        type = GfxItemTypes.seaSandSouthWest; 
        item = new GfxItem(res, R.drawable.sea_sand_southwest); 
        gfxItems.append(type, item); 
 
        type = GfxItemTypes.seaSandSouthEast; 
        item = new GfxItem(res, R.drawable.sea_sand_southeast); 
        gfxItems.append(type, item); 
 
 
 
        type = GfxItemTypes.plainLand; 
        item = new GfxItem(res, R.drawable.land); 
        gfxItems.append(type, item); 
 
        type = GfxItemTypes.plainLandGrass512; 
        item = new GfxItem(res, R.drawable.land_grass512_m2); 
        gfxItems.append(type, item); 
 
        type = GfxItemTypes.plainLandHill512; 
        item = new GfxItem(res, R.drawable.hill); 
        gfxItems.append(type, item); 
 
        type = GfxItemTypes.plainLandSand512; 
        item = new GfxItem(res, R.drawable.land_sand512); 
        gfxItems.append(type, item); 
 
        type = GfxItemTypes.plainLandSandBorder512; 
        item = new GfxItem(res, R.drawable.land_sand_border512); 
        gfxItems.append(type, item); 
 
        type = GfxItemTypes.plainLandMountain512; 
        item = new GfxItem(res, R.drawable.mountain512); 
        gfxItems.append(type, item); 
 
        type = GfxItemTypes.black; 
        item = new GfxItem(res, R.drawable.black); 
        gfxItems.append(type, item); 
 
        type = GfxItemTypes.blackEast; 
        item = new GfxItem(res, R.drawable.black_east); 
        gfxItems.append(type, item); 
 
        type = GfxItemTypes.blackNorth; 
        item = new GfxItem(res, R.drawable.black_north); 
        gfxItems.append(type, item); 
 
        type = GfxItemTypes.blackWest; 
        item = new GfxItem(res, R.drawable.black_west); 
        gfxItems.append(type, item); 
 
        type = GfxItemTypes.blackSouth; 
        item = new GfxItem(res, R.drawable.black_south); 
        gfxItems.append(type, item); 
 
        type = GfxItemTypes.blackNorthEast; 
        item = new GfxItem(res, R.drawable.black_northeast); 
        gfxItems.append(type, item); 
 
        type = GfxItemTypes.blackNorthWest; 
        item = new GfxItem(res, R.drawable.black_northwest); 
        gfxItems.append(type, item); 
 
        type = GfxItemTypes.blackSouthWest; 
        item = new GfxItem(res, R.drawable.black_southwest); 
        gfxItems.append(type, item); 
 
        type = GfxItemTypes.blackSouthEast; 
        item = new GfxItem(res, R.drawable.black_southeast); 
        gfxItems.append(type, item); 
 
        type = GfxItemTypes.city; 
        item = new GfxItem(res, R.drawable.city); 
        gfxItems.append(type, item); 
 
        type = GfxItemTypes.tank2; 
        item = new GfxItem(res, R.drawable.tank2); 
        gfxItems.append(type, item); 
 
        type = GfxItemTypes.select; 
        item = new GfxItem(res, R.drawable.select); 
        gfxItems.append(type, item); 
    } 
 
    public GfxItem getGfxItem(int mapId) { 
        return gfxItems.get(mapId); 
    } 
} 

MapManager

game land desert
Land / desert border

MapManager manages the map and its creation. A random map is created out of thin air. This map is layered. Land/sea is the first layer and all others are composed on top. Actually the land is written in multi-block writes as we'll soon find out.

This file has a lot of so called "rules" that form the final grid element according to its position. For example, if a grid element has land in every direction, there's nothing special to do. If there's sea in every direction, and the current location is sea, the location is considered as deep sea.

The sea/land borders are actually always sea, containing very little landspace. If the current position is sea and towards north there's land, it has a special Gfx item for just this kind of a position. If there's also land to the east, west or both, the rules apply the proper piece of graphics.

It's very likely that the endless if() statements could be combined to some extent. This is how I started it but that way it gets so complicated and hard to understand that I prefer to make the rules exact - one for every potential case. Let the compiler optimize the rest!

package fi.offcode.empire; 
 
import java.util.Random; 
 
/** 
 * Created by Eero on 23.2.2018. 
 */ 
 
public class MapManager { 
    // The map contains a 100x100 grid 
    private final int MAX_X = 100; 
    private final int MAX_Y = 100; 
    // Arrays: 
    // One for land and sea 
    private int[][] land_sea_map = null; 
    // One for the background 512x512 image(s) 
    private int[][] land_bg = null; 
    // One for specifying the exact grid element 
    private int[][] map = null; 
    // One for potential effects on the element 
    private int[][] special = null; 
    // One for sea effects, deep sea etc 
    private int[][] sea_effects = null; 
    // One for the black discovered area 
    private int[][] discovered = null; 
 
    public static final int regionSand = 4*8; 
 
    public static final int landBg = 0x2000; 
    public static final int landBgSand = 0x4000; 
    public static final int landBgSandBorder = 0x8000; 
    public static final int landBgMountain = 0x10000; 
    public static final int deepSeaSouth = 0x2; 
    public static final int deepSeaNorth = 0x4; 
    public static final int deepSeaEast = 0x8; 
    public static final int deepSeaWest = 0x10; 
    public static final int deepSeaSouthWest = 0x20; 
    public static final int deepSeaSouthEast = 0x40; 
    public static final int deepSeaNorthEast = 0x80; 
    public static final int deepSeaNorthWest = 0x100; 
 
    public static final int deepSeaSouthEastCorner = 0x200; 
    public static final int deepSeaNorthWestCorner = 0x400; 
 
 
    public static final int landSouthEast = 0x01; 
    public static final int landSouthWest = 0x02; 
    public static final int landNorthWest = 0x04; 
    public static final int landNorthEast = 0x08; 
    public static final int sandSouthWest = 0x800; 
    public static final int sandSouthEast = 0x1000; 
    public static final int sandNorthEast = 0x2000; 
    public static final int sandNorthWest = 0x4000; 
    public static final int city = 0x10000; 
 
    public static final int black = 0x1; 
    public static final int blackEast = 0x02; 
    public static final int blackWest = 0x04; 
    public static final int blackSouth = 0x8; 
    public static final int blackNorth = 0x10; 
    public static final int blackNorthWest = 0x20; 
    public static final int blackNorthEast = 0x40; 
    public static final int blackSouthEast = 0x80; 
    public static final int blackSouthWest = 0x100; 
 
    public void createMap() { 
        int i, j, land_or_sea, rnd; 
        map = new int[MAX_X][MAX_Y]; 
        land_sea_map = new int[MAX_X][MAX_Y]; 
        special = new int[MAX_X][MAX_Y]; 
        sea_effects = new int[MAX_X][MAX_Y]; 
        discovered = new int[MAX_X][MAX_Y]; 
        land_bg = new int[MAX_X][MAX_Y]; 
 
        // Random map 
        for (i = 0; i < MAX_X; i++) { 
            for (j = 0; j < MAX_Y; j++) { 
                // 1/3 is land, 2/3 is sea. 
                land_or_sea = new Random().nextInt(3); 
                // Change the logic here if you want more 
                // land than sea. 
                if (land_or_sea == 0) { 
                    land_sea_map[i][j] = GfxItemTypes.plainLand; 
                } else { 
                    land_sea_map[i][j] = GfxItemTypes.plainSea; 
                } 
 
                if (i < 2 || j < 2) { 
                    land_sea_map[i][j] = GfxItemTypes.plainSea; 
                } 
 
                map[i][j] = land_sea_map[i][j]; 
 
                special[i][j] = 0; 
                land_bg[i][j] = 0; 
                // All is black initially 
                discovered[i][j] = black; 
            } 
        } 
 
        // Fill the background with 512x512 pixel elements. 
        // They cover 4x4 grid elements which makes it look 
        // good! 
        for (j = 0; j < (MAX_Y - 4 - 1); j+=4) { 
            for (i = 0; i < (MAX_X - 4 - 1); i+=4) { 
                if (j < regionSand) 
                    land_bg[i][j] |= landBg; 
                else if (j == regionSand) { 
                    land_bg[i][j] |= landBgSandBorder; 
                } else { 
                    land_bg[i][j] |= landBgSand; 
                } 
            } 
        } 
 
        for (j = 1; j < (MAX_Y - 1); j++) { 
            for (i = 1; i < (MAX_X - 1); i++) { 
 
                if (land_sea_map[i][j] != GfxItemTypes.plainSea) { 
                    rnd = new Random().nextInt(30); 
                    if (rnd == 20) { 
                        special[i][j] |= city; 
                    } 
 
                    continue; 
                } 
 
                if (land_sea_map[i - 1][j] == GfxItemTypes.plainSea) { 
                    if (land_sea_map[i][j - 1] == GfxItemTypes.plainSea) { 
                        if (land_sea_map[i][j + 1] == GfxItemTypes.plainSea) { 
                            if (land_sea_map[i + 1][j] == GfxItemTypes.plainSea) { 
                                if (land_sea_map[i + 1][j + 1] == GfxItemTypes.plainSea) { 
                                    if (land_sea_map[i - 1][j - 1] == GfxItemTypes.plainSea) { 
                                        if (land_sea_map[i - 1][j + 1] == GfxItemTypes.plainSea) { 
                                            if (land_sea_map[i + 1][j - 1] == GfxItemTypes.plainSea) { 
                                                map[i][j] = GfxItemTypes.plainSea1; 
                                                //land_sea_map[i][j] = GfxItemTypes.plainLand; 
                                            } 
                                        } 
 
                                    } 
                                } 
                            } 
                        } 
                    } 
                } 
 
                if (land_sea_map[i - 1][j] == GfxItemTypes.plainLand) { 
                    if (land_sea_map[i][j - 1] == GfxItemTypes.plainLand) { 
                        if (land_sea_map[i][j + 1] == GfxItemTypes.plainLand) { 
                            if (land_sea_map[i + 1][j] == GfxItemTypes.plainLand) { 
                                map[i][j] = GfxItemTypes.plainLand; 
                                land_sea_map[i][j] = GfxItemTypes.plainLand; 
                            } 
                        } 
                    } 
                } 
 
                if (land_sea_map[i - 1][j] == GfxItemTypes.plainSea) { 
                    if (land_sea_map[i][j - 1] == GfxItemTypes.plainSea) { 
                        if (land_sea_map[i + 1][j] == GfxItemTypes.plainLand) { 
                            if (land_sea_map[i][j + 1] == GfxItemTypes.plainLand) { 
                                map[i][j] = GfxItemTypes.seaLandEast_and_South; 
                            } 
                        } 
                    } 
                } 
 
                if (land_sea_map[i - 1][j] == GfxItemTypes.plainSea) { 
                    if (land_sea_map[i][j - 1] == GfxItemTypes.plainSea) { 
                        if (land_sea_map[i + 1][j] == GfxItemTypes.plainLand) { 
                            if (land_sea_map[i][j + 1] == GfxItemTypes.plainSea) { 
                                if (map[i][j - 1] == GfxItemTypes.seaLandEast) { 
                                    map[i][j] = GfxItemTypes.seaLandEast1; 
                                } else { 
                                    map[i][j] = GfxItemTypes.seaLandEast; 
                                } 
                            } 
                        } 
                    } 
                } 
 
                if (land_sea_map[i - 1][j] == GfxItemTypes.plainSea) { 
                    if (land_sea_map[i][j - 1] == GfxItemTypes.plainSea) { 
                        if (land_sea_map[i + 1][j] == GfxItemTypes.plainSea) { 
                            if (land_sea_map[i][j + 1] == GfxItemTypes.plainLand) { 
                                rnd = new Random().nextInt(2); 
                                if (rnd == 0) 
                                    map[i][j] = GfxItemTypes.seaLandSouth1; 
                                else 
                                    map[i][j] = GfxItemTypes.seaLandSouth; 
                                if (map[i - 1][j] == GfxItemTypes.seaLandSouth) { 
                                    map[i][j] = GfxItemTypes.seaLandSouth1; 
                                } /*else { 
                                    map[i][j] = GfxItemTypes.seaLandSouth; 
                                }*/ 
                            } 
                        } 
                    } 
                } 
 
                if (land_sea_map[i - 1][j] == GfxItemTypes.plainLand) { 
                    if (land_sea_map[i][j - 1] == GfxItemTypes.plainLand) { 
                        if (land_sea_map[i][j + 1] == GfxItemTypes.plainLand) { 
                            if (land_sea_map[i + 1][j] == GfxItemTypes.plainSea) { 
                                map[i][j] = GfxItemTypes.seaLandSouth_and_West_and_North; 
                            } 
                        } 
                    } 
                } 
 
                if (land_sea_map[i - 1][j] == GfxItemTypes.plainLand) { 
                    if (land_sea_map[i][j - 1] == GfxItemTypes.plainLand) { 
                        if (land_sea_map[i][j + 1] == GfxItemTypes.plainSea) { 
                            if (land_sea_map[i + 1][j] == GfxItemTypes.plainSea) { 
                                map[i][j] = GfxItemTypes.seaLandWest_and_North; 
                            } 
                        } 
                    } 
                } 
 
                if (land_sea_map[i - 1][j] == GfxItemTypes.plainLand) { 
                    if (land_sea_map[i][j - 1] == GfxItemTypes.plainSea) { 
                        if (land_sea_map[i][j + 1] == GfxItemTypes.plainSea) { 
                            if (land_sea_map[i + 1][j] == GfxItemTypes.plainSea) { 
                                rnd = new Random().nextInt(2); 
                                if (rnd == 1) { 
                                    map[i][j] = GfxItemTypes.seaLandWest1; 
                                } else { 
                                    map[i][j] = GfxItemTypes.seaLandWest; 
                                } 
                                if (map[i][j - 1] == GfxItemTypes.seaLandWest) 
                                    map[i][j] = GfxItemTypes.seaLandWest1; 
                                /*else 
                                    map[i][j] = GfxItemTypes.seaLandWest;*/ 
                            } 
                        } 
                    } 
                } 
 
 
                if (land_sea_map[i - 1][j] == GfxItemTypes.plainSea) { 
                    if (land_sea_map[i][j - 1] == GfxItemTypes.plainLand) { 
                        if (land_sea_map[i][j + 1] == GfxItemTypes.plainSea) { 
                            if (land_sea_map[i + 1][j] == GfxItemTypes.plainLand) { 
                                map[i][j] = GfxItemTypes.seaLandNorth_and_East; 
                            } 
                        } 
                    } 
                } 
 
                if (land_sea_map[i - 1][j] == GfxItemTypes.plainLand) { 
                    if (land_sea_map[i][j - 1] == GfxItemTypes.plainSea) { 
                        if (land_sea_map[i][j + 1] == GfxItemTypes.plainLand) { 
                            if (land_sea_map[i + 1][j] == GfxItemTypes.plainLand) { 
                                map[i][j] = GfxItemTypes.seaLandEast_and_South_and_West; 
                            } 
                        } 
                    } 
                } 
 
                if (land_sea_map[i - 1][j] == GfxItemTypes.plainLand) { 
                    if (land_sea_map[i][j - 1] == GfxItemTypes.plainLand) { 
                        if (land_sea_map[i][j + 1] == GfxItemTypes.plainSea) { 
                            if (land_sea_map[i + 1][j] == GfxItemTypes.plainLand) { 
                                map[i][j] = GfxItemTypes.seaLandWest_and_North_and_East; 
                            } 
                        } 
                    } 
                } 
 
                if (land_sea_map[i - 1][j] == GfxItemTypes.plainSea) { 
                    if (land_sea_map[i][j - 1] == GfxItemTypes.plainLand) { 
                        if (land_sea_map[i][j + 1] == GfxItemTypes.plainLand) { 
                            if (land_sea_map[i + 1][j] == GfxItemTypes.plainLand) { 
                                map[i][j] = GfxItemTypes.seaLandNorth_and_East_and_South; 
                            } 
                        } 
                    } 
                } 
 
                if (land_sea_map[i - 1][j] == GfxItemTypes.plainLand) { 
                    if (land_sea_map[i][j - 1] == GfxItemTypes.plainSea) { 
                        if (land_sea_map[i][j + 1] == GfxItemTypes.plainSea) { 
                            if (land_sea_map[i + 1][j] == GfxItemTypes.plainLand) { 
                                map[i][j] = GfxItemTypes.seaLandWest_and_East; 
                            } 
                        } 
                    } 
                } 
 
                if (land_sea_map[i - 1][j] == GfxItemTypes.plainLand) { 
                    if (land_sea_map[i][j - 1] == GfxItemTypes.plainSea) { 
                        if (land_sea_map[i][j + 1] == GfxItemTypes.plainLand) { 
                            if (land_sea_map[i + 1][j] == GfxItemTypes.plainSea) { 
                                map[i][j] = GfxItemTypes.seaLandSouth_and_West; 
                            } 
                        } 
                    } 
                } 
 
                if (land_sea_map[i - 1][j] == GfxItemTypes.plainSea) { 
                    if (land_sea_map[i][j - 1] == GfxItemTypes.plainLand) { 
                        if (land_sea_map[i][j + 1] == GfxItemTypes.plainSea) { 
                            if (land_sea_map[i + 1][j] == GfxItemTypes.plainSea) { 
                                rnd = new Random().nextInt(2); 
                                if (rnd == 1) 
                                    map[i][j] = GfxItemTypes.seaLandNorth1; 
                                else { 
                                    if (map[i - 1][j] == GfxItemTypes.seaLandNorth) 
                                        map[i][j] = GfxItemTypes.seaLandNorth1; 
                                    else 
                                        map[i][j] = GfxItemTypes.seaLandNorth; 
                                } 
                            } 
                        } 
                    } 
                } 
 
                if (land_sea_map[i - 1][j] == GfxItemTypes.plainSea) { 
                    if (land_sea_map[i][j - 1] == GfxItemTypes.plainLand) { 
                        if (land_sea_map[i][j + 1] == GfxItemTypes.plainLand) { 
                            if (land_sea_map[i + 1][j] == GfxItemTypes.plainSea) { 
                                map[i][j] = GfxItemTypes.seaLandNorth_and_South; 
                            } 
                        } 
                    } 
                } 
 
                if (land_sea_map[i][j - 1] == GfxItemTypes.plainSea) { 
                    if (land_sea_map[i + 1][j] == GfxItemTypes.plainSea) { 
                        if (land_sea_map[i + 1][j - 1] == GfxItemTypes.plainLand) { 
                            // NE 
                            if (j < (regionSand+3)) 
                                special[i][j] |= landNorthEast; 
                            else 
                                special[i][j] |= sandNorthEast; 
                        } 
                    } 
                } 
 
                if (land_sea_map[i - 1][j] == GfxItemTypes.plainSea) { 
                    if (land_sea_map[i][j - 1] == GfxItemTypes.plainSea) { 
                        if (land_sea_map[i - 1][j - 1] == GfxItemTypes.plainLand) { 
                            // NW 
                            if (j < (regionSand+3)) 
                                special[i][j] |= landNorthWest; 
                            else 
                                special[i][j] |= sandNorthWest; 
                        } 
                    } 
                } 
 
                if (land_sea_map[i - 1][j] == GfxItemTypes.plainSea) { 
                    if (land_sea_map[i][j + 1] == GfxItemTypes.plainSea) { 
                        if (land_sea_map[i - 1][j + 1] == GfxItemTypes.plainLand) { 
                            // SW 
                            if (j < (regionSand+2)) 
                                special[i][j] |= landSouthWest; 
                            else 
                                special[i][j] |= sandSouthWest; 
                        } 
                    } 
                } 
 
                if (land_sea_map[i + 1][j] == GfxItemTypes.plainSea) { 
                    if (land_sea_map[i][j + 1] == GfxItemTypes.plainSea) { 
                        if (land_sea_map[i + 1][j + 1] == GfxItemTypes.plainLand) { 
                            //map[i][j] = GfxItemTypes.seaLandSouthEast; 
                            if (j < (regionSand+2)) 
                                special[i][j] |= landSouthEast; 
                            else 
                                special[i][j] |= sandSouthEast; 
                        } 
                    } 
                } 
            } 
        } 
 
        for (j = 1; j < (MAX_Y - 1); j++) { 
            for (i = 1; i < (MAX_X - 1); i++) { 
 
                if (land_sea_map[i][j] == GfxItemTypes.plainLand) 
                    continue; 
                // Sea dark border 
                if (map[i][j+1] == GfxItemTypes.plainSea1) { 
                    if (map[i][j] != GfxItemTypes.plainSea1) { 
                        sea_effects[i][j] |= deepSeaSouth; 
                    } 
                } 
                if (map[i][j-1] == GfxItemTypes.plainSea1) { 
                    if (map[i][j] != GfxItemTypes.plainSea1) { 
                        sea_effects[i][j] |= deepSeaNorth; 
                    } 
                } 
                if (map[i+1][j] == GfxItemTypes.plainSea1) { 
                    if (map[i][j] != GfxItemTypes.plainSea1) { 
                        sea_effects[i][j] |= deepSeaEast; 
                    } 
                } 
                if (map[i-1][j] == GfxItemTypes.plainSea1) { 
                    if (map[i][j] != GfxItemTypes.plainSea1) { 
                        sea_effects[i][j] |= deepSeaWest; 
                    } 
                } 
 
                // both 
                if (map[i+1][j] == GfxItemTypes.plainSea) { 
                    if (map[i][j] == GfxItemTypes.plainSea) { 
                        sea_effects[i][j] |= deepSeaEast; 
                        sea_effects[i][j-1] |= deepSeaSouthEast; 
                        sea_effects[i][j+1] |= deepSeaNorthEast; 
                    } 
                } 
                if (map[i-1][j] == GfxItemTypes.plainSea) { 
                    if (map[i][j] == GfxItemTypes.plainSea) { 
                        sea_effects[i][j] |= deepSeaWest; 
                        sea_effects[i][j-1] |= deepSeaSouthWest; 
                        sea_effects[i][j+1] |= deepSeaNorthWest; 
                    } 
                } 
 
                if (map[i-1][j-1] == GfxItemTypes.plainSea1) { 
                    if (map[i][j] != GfxItemTypes.plainSea1) { 
                        sea_effects[i][j] |= deepSeaNorthWest; 
                    } 
                } 
                if (map[i+1][j-1] == GfxItemTypes.plainSea1) { 
                    if (map[i][j] != GfxItemTypes.plainSea1) { 
                        if (map[i+1][j] != GfxItemTypes.plainSea1) { 
                            sea_effects[i][j] |= deepSeaNorthEast; 
                        } 
                    } 
                } 
                if (map[i+1][j+1] == GfxItemTypes.plainSea1) { 
                    if (map[i][j] != GfxItemTypes.plainSea1) { 
                        if (map[i+1][j] != GfxItemTypes.plainSea1) { 
                            rnd = new Random().nextInt(2); 
                            //if (rnd == 0) { 
                                sea_effects[i][j] |= deepSeaSouthEast; 
                            //} else { 
                            //    sea_effects[i][j] |= deepSeaSouthEast_e; 
                            //} 
                        } 
                    } 
                } 
                if (map[i-1][j+1] == GfxItemTypes.plainSea1) { 
                    if (map[i][j] != GfxItemTypes.plainSea1) { 
                        sea_effects[i][j] |= deepSeaSouthWest; 
                    } 
                } 
 
                if (map[i+1][j] == GfxItemTypes.plainSea1) { 
                    if (map[i][j+1] == GfxItemTypes.plainSea1) { 
                        if (map[i][j] != GfxItemTypes.plainSea1) { 
                            sea_effects[i][j] |= deepSeaSouthEastCorner; 
                        } 
                    } 
                } 
 
                if (map[i-1][j] == GfxItemTypes.plainSea1) { 
                    if (map[i][j-1] == GfxItemTypes.plainSea1) { 
                        if (map[i][j] != GfxItemTypes.plainSea1) { 
                            sea_effects[i][j] |= deepSeaNorthWestCorner; 
                        } 
                    } 
                } 
 
 
            } 
        } 
 
    } 
 
    private int discoveredLayer(int x, int y) { 
        int ret = 0; 
 
        if ((discovered[x][y] & black) == black) { 
            return black; 
        } 
        if (x > 0 && y > 0 && x < (MAX_X - 2) && y < (MAX_Y - 2)) { 
            if ((discovered[x - 1][y] & black) == black) { 
                ret |= blackWest; 
            } 
            if ((discovered[x + 1][y] & black) == black) { 
                ret |= blackEast; 
            } 
            if ((discovered[x][y + 1] & black) == black) { 
                ret |= blackSouth; 
            } 
            if ((discovered[x][y - 1] & black) == black) { 
                ret |= blackNorth; 
            } 
            if ((discovered[x+1][y + 1] & black) == black) { 
                if ((discovered[x+1][y] & black) != black) { 
                    if ((discovered[x][y+1] & black) != black) { 
                        ret |= blackSouthEast; 
                    } 
                } 
            } 
            if ((discovered[x-1][y + 1] & black) == black) { 
                if ((discovered[x-1][y] & black) != black) { 
                    if ((discovered[x][y+1] & black) != black) { 
                        ret |= blackSouthWest; 
                    } 
                } 
            } 
 
            if ((discovered[x-1][y - 1] & black) == black) { 
                if ((discovered[x-1][y] & black) != black) { 
                    if ((discovered[x][y-1] & black) != black) { 
                        ret |= blackNorthWest; 
                    } 
                } 
            } 
 
            if ((discovered[x + 1][y - 1] & black) == black) { 
                if ((discovered[x+1][y] & black) != black) { 
                    if ((discovered[x][y-1] & black) != black) { 
                        ret |= blackNorthEast; 
                    } 
                } 
            } 
        } 
        return ret; 
    } 
 
    public int getAtPos(int x, int y) { 
        if (map[x][y] == GfxItemTypes.plainLand) 
            return 0; 
        return map[x][y]; 
    } 
 
    // City and corners 
    public int getAtPosSpecial(int x, int y) { 
        return special[x][y]; 
    } 
 
    public int getAtPosSeaEffects(int x, int y) { 
        return sea_effects[x][y]; 
    } 
 
    public int getAtPosDiscovered(int x, int y) { 
        return discoveredLayer(x, y); 
    } 
    public int getAtLandBg(int x, int y) { 
        return land_bg[x][y]; 
    } 
    public void setDiscovered(int x, int y) { 
        if (x > 0 && y > 0) { 
            discovered[x][y] = 0; 
 
            discovered[x-1][y-1] = 0; 
            discovered[x][y-1] = 0; 
            discovered[x+1][y-1] = 0; 
 
            discovered[x-1][y] = 0; 
            //discovered[x][y] = 0; 
            discovered[x+1][y] = 0; 
 
            discovered[x-1][y+1] = 0; 
            discovered[x][y+1] = 0; 
            discovered[x+1][y+1] = 0; 
        } 
    } 
} 


Written on April 2018 by Eero Nurkkala

contact information