I have a terrible time, suitable for a good question. Title ... sorry / edit if your brain has less shot than mine.
I'm having some problems processing my game cards on the client side. My game is based on using 32x32 pixel tiles. My first game card was 1750 x 1750 tiles. I had a bunch of layers on the client side, but I managed to reduce it to 2 (land and buildings). I previously loaded all map layers into memory (short arrays). When I jumped to 2200 x 2200 tiles, I noticed that the old computer was having problems with out of memory (1 GB +). I would like to have a data type between byte and short (I am aiming for ~ 1000 different tiles). My game supports several resolutions, so the visible space of the players can display 23.17 tiles for 800x600 resolution up to 45.29 tiles for 1440x1024 resolutions (plus). I use Tiled to draw my maps and output two layers into separate text files, using a format similar to the following (0, 0, 2, 0, 3, 6, 0, 74, 2 ...) all on one line.
Through many SO questions and some research, I came up with a map splitting strategy. Using the playerโs current coordinates as the center point, I load a sufficient number of tiles 5 times the size of the visual map (the largest will be 45 * 5.29 * 5 = 225,145 tiles). The player is always drawn in the center, and the earth moves below it (when you go east, the earth moves west). The minimum is drawn, showing one screen in all directions, three times the size of the visible map. Please see below (very reduced) visual presentation to explain better than I probably explained it.

My problem is this: when a player moves "1/5 fragment fragment size" from the origin coordinates of the center point (chunkX / Y), I challenge the game to re-view the file. A new scan will use the playerโs current coordinates as the center point. Currently, this question that I have is interception, which takes about 5 seconds on my computer (this is a pretty high specification). The map is not updated for 1-2 tile steps.
To deal with the problem above, I tried to start scanning files in a new stream (before hitting the 1 / 5th point) into a temporary massive buffer. Then, as soon as this was done, I copied the buffer to the real array and called back (). In random order, I saw some problems with this, which did not really matter. Even worse, I saw him draw a random part of the map for 1-2 frames. Sample code below:
private void checkIfWithinAndPossiblyReloadChunkMap(){ if (Math.abs(MyClient.characterX - MyClient.chunkX) + 10 > (MyClient.chunkWidth / 5)){ //arbitrary number away (10) Runnable myRunnable = new Runnable(){ public void run(){ logger.info("FillMapChunkBuffer started."); short chunkXBuffer = MyClient.characterX; short chunkYBuffer = MyClient.characterY; int topLeftChunkIndex = MyClient.characterX - (MyClient.chunkWidth / 2) + ((MyClient.characterY - (MyClient.chunkHeight / 2)) * MyClient.mapWidth); //get top left coordinate of chunk int topRightChunkIndex = topLeftChunkIndex + MyClient.chunkWidth - 1; //top right coordinate of chunk int[] leftChunkSides = new int[MyClient.chunkHeight]; int[] rightChunkSides = new int[MyClient.chunkHeight]; for (int i = 0; i < MyClient.chunkHeight; i++){ //figure out the left and right index points for the chunk leftChunkSides[i] = topLeftChunkIndex + (MyClient.mapWidth * i); rightChunkSides[i] = topRightChunkIndex + (MyClient.mapWidth * i); } MyClient.groundLayerBuffer = MyClient.FillGroundBuffer(leftChunkSides, rightChunkSides); MyClient.buildingLayerBuffer = MyClient.FillBuildingBuffer(leftChunkSides, rightChunkSides); MyClient.groundLayer = MyClient.groundLayerBuffer; MyClient.buildingLayer = MyClient.buildingLayerBuffer; MyClient.chunkX = chunkXBuffer; MyClient.chunkY = chunkYBuffer; MyClient.gamePanel.repaint(); logger.info("FillMapChunkBuffer done."); } }; Thread thread = new Thread(myRunnable); thread.start(); } else if (Math.abs(MyClient.characterY - MyClient.chunkY) + 10 > (MyClient.chunkHeight / 5)){ //arbitrary number away (10) //same code as above for Y } } public static short[] FillGroundBuffer(int[] leftChunkSides, int[] rightChunkSides){ try { return scanMapFile("res/images/tiles/MyFirstMap-ground-p.json", leftChunkSides, rightChunkSides); } catch (FileNotFoundException e) { logger.fatal("ReadMapFile(ground)", e); JOptionPane.showMessageDialog(theDesktop, getStringChecked("message_file_locks") + "\n\n" + e.getMessage(), getStringChecked("message_error"), JOptionPane.ERROR_MESSAGE); System.exit(1); } return null; } private static short[] scanMapFile(String path, int[] leftChunkSides, int[] rightChunkSides) throws FileNotFoundException { Scanner scanner = new Scanner(new File(path)); scanner.useDelimiter(", "); int topLeftChunkIndex = leftChunkSides[0]; int bottomRightChunkIndex = rightChunkSides[rightChunkSides.length - 1]; short[] tmpMap = new short[chunkWidth * chunkHeight]; int count = 0; int arrayIndex = 0; while(scanner.hasNext()){ if (count >= topLeftChunkIndex && count <= bottomRightChunkIndex){ //within or outside (east and west) of map chunk if (count == bottomRightChunkIndex){ //last entry tmpMap[arrayIndex] = scanner.nextShort(); break; } else { //not last entry if (isInsideMapChunk(count, leftChunkSides, rightChunkSides)){ tmpMap[arrayIndex] = scanner.nextShort(); arrayIndex++; } else { scanner.nextShort(); } } } else { scanner.nextShort(); } count++; } scanner.close(); return tmpMap; }
I really agree with that. I want to be able to move beyond this crap GUI and work on real game mechanics. Any help would be greatly appreciated. Sorry for the long post, but trust me, a lot of thoughts / sleepless nights went for it. I need ideas from SO experts. Thank you very much!
ps I came up with some potential optimization ideas (but not sure if this will solve part of the problem):
split map files into several lines, so that I can call scanner.nextLine () 1 time, and not scanner.next () 2200 times
come up with a formula that would give the 4 corners of the map fragment, will know if the given coordinate is in it. this would allow me to call scanner.nextLine () when at the farthest point on the piece for a given line. this will require a multi-line map file file above.
- throw away only the 1/5th piece, move the array and load the next 1/5 part