package sig.map; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.util.Arrays; import sig.RabiClone; import sig.engine.Sprite; public class Map { //Maps contain 512x288 tiles, allowing for 16384x9216 pixels of action per map. //Since a screen normally fits 16x9 tiles, you get 32x32 (1024) screens of gameplay per world. // //Starts with 294912 bytes for visual tiles. //After the map data, the next 1024 bytes will indicate the map view information. //After that, the next 1024 bytes will indicate the background information. //After that, the next 1024 bytes will indicate the map color information. //After that, the next 1024 bytes will indicate the map room type. (Might show checkpoints, warp points, POI, etc) //After that, there will be one integer (4 bytes) to indicate how many event tiles there are. //Following that is an integer for each event tile that needs to be loaded in. // //299012 + [event tiles*4] bytes = at least 299KB of memory storage per map. // final public static int MAP_WIDTH=512; final public static int MAP_HEIGHT=288; final public static int MAP_SCREENS_X=32; final public static int MAP_SCREENS_Y=32; char[] tiles = new char[MAP_WIDTH*MAP_HEIGHT]; byte[] views = new byte[MAP_SCREENS_X*MAP_SCREENS_Y]; byte[] backgrounds = new byte[MAP_SCREENS_X*MAP_SCREENS_Y]; byte[] colors = new byte[MAP_SCREENS_X*MAP_SCREENS_Y]; byte[] types = new byte[MAP_SCREENS_X*MAP_SCREENS_Y]; char[] data = new char[MAP_WIDTH*MAP_HEIGHT]; //While it's stored in a char, the map format only reads 14 bits for this value!! Value is between 0-16384! char waterLevel = 144; int eventTileCount=0; final static byte MAP_DATA = 0; final static byte VIEW_DATA = 1; final static byte BACKGROUND_DATA = 2; final static byte COLOR_DATA = 3; final static byte TYPE_DATA = 4; final static byte EVENT_DATA_COUNT = 5; final static byte EVENT_DATA = 6; public static Map LoadMap(Maps map) { try { Map newMap; if (RabiClone.CURRENT_MAP!=null) { newMap = map.getMap(); if (RabiClone.CURRENT_MAP!=map) { Map currentMapData = RabiClone.CURRENT_MAP.getMap(); resetMapData(currentMapData); RabiClone.CURRENT_MAP=map; RabiClone.CURRENT_MAP.setMap(currentMapData); } else { resetAndReloadEventData(RabiClone.CURRENT_MAP); return RabiClone.CURRENT_MAP.getMap(); } } else { map.initializeMap(); RabiClone.CURRENT_MAP=map; newMap = map.getMap(); } DataInputStream stream = new DataInputStream(new FileInputStream(map.getFile())); int marker=0; int iterationCount=MAP_WIDTH*MAP_HEIGHT; int readingData = MAP_DATA; while (stream.available()!=0) { switch (readingData) { case MAP_DATA: char tileValue = stream.readChar(); int ypos=marker/Map.MAP_WIDTH; int xpos=marker%Map.MAP_WIDTH; newMap.tiles[marker++]=tileValue; if (Tile.values()[tileValue].getCollision()==CollisionType.SOLID) { for (int y=0;y>>18); int index = dataPacket&0b00000000000000111111111111111111; System.out.println("Unpacked: "+((int)event)+" // x:"+(index%Map.MAP_WIDTH)+", y:"+(index/Map.MAP_WIDTH)); newMap.data[index]=event; break; } iterationCount--; if (iterationCount<=0) { readingData++; marker=0; iterationCount=MAP_SCREENS_X*MAP_SCREENS_Y; } } stream.close(); return newMap; } catch (IOException e) { e.printStackTrace(); } return null; } private static void resetAndReloadEventData(Maps map) { Arrays.fill(map.getMap().data,(char)0); map.getMap().eventTileCount=0; try { DataInputStream stream = new DataInputStream(new FileInputStream(map.getFile())); final long requestBytes = 294912+1024+1024+1024+1024; long actualBytes = stream.skip(requestBytes); if (actualBytes!=requestBytes) { stream.close(); throw new IOException("Could not read "+requestBytes+" bytes! Read "+actualBytes+" instead."); } map.getMap().eventTileCount=stream.readInt(); int remainingCount = map.getMap().eventTileCount; System.out.println("Found "+remainingCount+" events."); while (remainingCount-->0) { int dataPacket = stream.readInt(); //First 14 bits are event info. Last 18 bits are index info. char event = (char)(dataPacket>>>18); int index = dataPacket&0b00000000000000111111111111111111; System.out.println("Unpacked: "+((int)event)+" // x:"+(index%Map.MAP_WIDTH)+", y:"+(index/Map.MAP_WIDTH)); map.getMap().data[index]=event; } stream.close(); } catch (IOException e) { e.printStackTrace(); } } private static void resetMapData(Map newMap) { Arrays.fill(newMap.tiles,(char)0); Arrays.fill(newMap.views,(byte)0); Arrays.fill(newMap.backgrounds,(byte)0); Arrays.fill(newMap.colors,(byte)0); Arrays.fill(newMap.types,(byte)0); } public static void SaveMap(Maps map) throws IOException { DataOutputStream stream = new DataOutputStream(new FileOutputStream(map.getFile())); saveCharData(stream,map.map.tiles); saveByteData(stream,map.map.views); saveByteData(stream,map.map.backgrounds); saveByteData(stream,map.map.colors); saveByteData(stream,map.map.types); int[] eventData = new int[map.map.eventTileCount]; int eventCounter = 0; for (int y=0;y8192) { value=8192; } data[y*Map.MAP_WIDTH+x]=(char)(value+8192); System.out.println("Tile "+(y*MAP_WIDTH+x)+" is now "+data[y*MAP_WIDTH+x]+"."); } public char getWaterLevel() { return waterLevel; } public void setWaterLevel(char waterLevel) { this.waterLevel = waterLevel; } /** * This will return the tile's value minus 8192. * This value represents a data tile value, but not * necessarily a data tile. */ public char getDataTileValue(int x,int y) { if (data[y*Map.MAP_WIDTH+x]>=8192) { return (char)(data[y*Map.MAP_WIDTH+x]-8192); } else { return Character.MAX_VALUE; } } }