Munashedov

Territory maps v2

Jun 20th, 2021
694
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // TODO:
  2. /*
  3. -Fix the border overlay system
  4. -Make the map dynamically resize to match the window(?)
  5. -Add zoom levels?
  6. -Add an actual territory class
  7. -Make a player class that controls territories
  8. -Add a sense of time (turns or steps?)
  9. -Concept of selecting a territory
  10. */
  11.  
  12. PImage gameMap;
  13.  
  14. color WHITE = color(255);
  15. color BLACK = color(0);
  16. color MAGENTA = color(255,0,255);
  17. color BLUE_L = color(120, 120, 255);
  18. color PINK_L = color(200,50,200);
  19.  
  20. boolean isResized = false;
  21.  
  22. boolean randomizePerSecond = false;
  23. boolean showDebug = true;
  24.  
  25.  
  26. double delta = 0;
  27.  
  28. void settings(){
  29.   size(640,400);
  30.   noSmooth();
  31.  
  32. }
  33.  
  34. FrameBuffer buffer = new FrameBuffer(200);
  35. void setup(){
  36.   colorMode(HSB, 360, 100, 100);
  37.   textSize(10);
  38.   fill(WHITE);
  39.   surface.setResizable(true);
  40.  
  41.   String imageName = "map-us-edit.png";
  42.   m = new Map(imageName);
  43.   if(m.rawMap != null){
  44.     m.discoverTerritories();
  45.     gameMap = m.map.copy();
  46.   } else {
  47.     println("Failed to find " + "\""+imageName+"\"");
  48.     exit();
  49.   }
  50. }
  51.  
  52. void draw(){
  53.   frameRate(144);
  54.  
  55.   delta = System.nanoTime();
  56.  
  57.   resizeWindowOnce();
  58.  
  59.   m.update();
  60.   m.display();
  61.  
  62.   drawDebugText();
  63.  
  64.   printFrameTime(delta);
  65. }
  66.  
  67.  
  68. void drawDebugText(){
  69.     if(showDebug){
  70.     text("FPS: "+ frameRate, 1,10);
  71.     text("Randomize?: "+ randomizePerSecond, 1,30);
  72.     text("FrameBuffer: "+ buffer.queryState(), 1,40);
  73.   }
  74. }
  75.  
  76. void resizeWindowOnce(){
  77.   if(!isResized){
  78.       surface.setSize(gameMap.width, gameMap.height);
  79.       isResized = true;
  80.   }
  81. }
  82.  
  83.  
  84.  
  85.  
  86. class FrameBuffer{
  87.   ArrayList<PImage> frames = new ArrayList<PImage>();
  88.   boolean shouldCaptureFrames = true;
  89.   boolean hasDumped = false;
  90.   int maxCapacity;
  91.   int saveCounter;
  92.   boolean dumpInProgress = false;
  93.  
  94.   FrameBuffer(int _maxCapacity){
  95.     maxCapacity = _maxCapacity;
  96.   }
  97.  
  98.   void dump(){
  99.     if(frames.size() == 0){
  100.       println("Attempted to dump buffer, but it was empty.");
  101.     } else {
  102.       for(int n = 0; n < frames.size(); n++){
  103.         frames.get(n).save("f-"+ n +".png");
  104.       }
  105.       println("Dumped "+frames.size() +" images.");
  106.       hasDumped = true;
  107.       frames.clear();
  108.     }
  109.   }
  110.  
  111.   void progressiveDump(){
  112.     if(dumpInProgress){
  113.       if(frames.size() == 0){
  114.         println("Dump finished - "+ saveCounter +" frames saved to disk.");
  115.         dumpInProgress = false;
  116.         saveCounter = 0;
  117.         return;
  118.       } else {
  119.           frames.get(0).save("f-"+ (saveCounter) +".png");
  120.           //println(frames.size());
  121.           //println(frames.size() - saveCounter);
  122.           println(saveCounter);
  123.           saveCounter++;
  124.           frames.remove(0);
  125.       }
  126.     }
  127.   }
  128.  
  129.   String queryState(){
  130.     if(hasDumped){
  131.       return "Flushed";
  132.     } else {
  133.       return str(frames.size());
  134.     }
  135.   }
  136.  
  137.   boolean addFrame(PImage image){
  138.     hasDumped = false;
  139.     if(frames.size() < maxCapacity){
  140.       frames.add(image);
  141.       return true;
  142.     } else {
  143.       return false;
  144.     }
  145.   }
  146. }
  147.  
  148. class ImageDumpThread extends Thread{
  149.   FrameBuffer buffer;
  150.  
  151.   ImageDumpThread(FrameBuffer _buffer){
  152.     buffer = _buffer;
  153.   }
  154.  
  155.   void run(){
  156.     println("ImageDumpThread started.");
  157.     buffer.dump();
  158.     println("ImageDumpThread finished");
  159.   }
  160. }
  161.  
  162. //Not in use, but random opacity overlays for texture should be considered
  163. PImage generateTextureEffect(PImage _map, float _frequency){
  164.   PImage map = _map.copy();
  165.   PImage overlay = createImage(map.width, map.height, ARGB);
  166.   overlay.loadPixels();
  167.   for(int i = 0; i < overlay.pixels.length; i++){
  168.     if(random(1) > _frequency){
  169.       overlay.pixels[i] = color(1,1,1,50);
  170.     }
  171.   }
  172.   overlay.updatePixels();
  173.   return overlay;
  174. }
  175.  
  176.  
  177.  
  178. Map m;
  179. class Map{
  180.   PVector pos;
  181.   PVector dims;
  182.   float widthMultiplier;
  183.   float heightMultiplier;
  184.   PImage map;
  185.   PImage rawMap;
  186.   IntList territoryIDs = new IntList();
  187.  
  188.   Map(String _mapImageFileName){
  189.     rawMap = loadImage(_mapImageFileName);
  190.     if(rawMap != null){
  191.       pos = new PVector(0,0);
  192.       dims = new PVector(rawMap.width, rawMap.height);
  193.       println("Map dimensions: "+rawMap.width+","+rawMap.height);
  194.     } else {
  195.       exit();
  196.     }
  197.   }
  198.  
  199.   void discoverTerritories(){
  200.     rawMap.loadPixels();
  201.     int maxAttemps = 1;
  202.     int lastIndex = 0;
  203.     int steps = 0;
  204.     int fillEvents = 0;
  205.    
  206.     nextTerritory();
  207.    
  208.     for(int n = 0; n < maxAttemps; n++){
  209.       for(int i = lastIndex; i < rawMap.pixels.length; i++){
  210.         steps++;
  211.         if(validTarget(i)){
  212.           floodFill(rawMap, i%rawMap.width, floor(i/rawMap.width), currentTerritory());
  213.           nextTerritory();
  214.           lastIndex = i;
  215.           fillEvents++;
  216.           if(buffer.shouldCaptureFrames){
  217.             buffer.addFrame(rawMap.copy());
  218.           }
  219.         }
  220.       }
  221.     }
  222.     rawMap.updatePixels();
  223.     map = rawMap.copy();
  224.  
  225.     println("Pixels checked: "+ steps +"/"+ rawMap.pixels.length);
  226.     println("Fill Events: "+ fillEvents);
  227.   }
  228.  
  229.   void nextTerritory(){
  230.     //territoryIDs.append(randomColor(200,255));
  231.     //territoryIDs.append(color(random(360),random(60,80),random(60,80)));
  232.     territoryIDs.append(color(random(360),random(60,70),90));
  233.   }
  234.  
  235.   int currentTerritory(){
  236.     return territoryIDs.get(territoryIDs.size()-1);
  237.   }
  238.  
  239.   boolean validTarget(int t){
  240.     if(rawMap.pixels[t] == BLACK){
  241.       return false;
  242.     }
  243.     if(territoryIDs.hasValue(rawMap.pixels[t])){
  244.       return false;
  245.     }
  246.     return true;
  247.   }
  248.  
  249.   void colorReplace(int _tx, int _ty, color newColor){
  250.     int tx = transformMouseX(_tx);
  251.     int ty = transformMouseY(_ty);
  252.     if(!isPointOutOfBounds(tx, ty)){
  253.       rawMap.loadPixels();
  254.       if(rawMap.pixels[tx+ty*rawMap.width] != BLACK){
  255.         rawMap = floodFill(rawMap, tx, ty, newColor);
  256.       }
  257.       rawMap.updatePixels();
  258.       map = rawMap.copy();
  259.     }
  260.   }
  261.  
  262.   void randomize(){
  263.      territoryIDs.clear();
  264.      discoverTerritories();
  265.   }
  266.  
  267.   void printMapDims(){
  268.     println("Map dimensions: "+rawMap.width+","+rawMap.height);
  269.   }
  270.  
  271.   boolean isPointOutOfBounds(int x, int y){
  272.      if(x < 0 || y < 0 || x >= map.width || y >= map.height){
  273.        return true;
  274.      } else {
  275.        return false;
  276.      }
  277.   }
  278.  
  279.   boolean colorPick(int x, int y){
  280.     int tx = transformMouseX(x);
  281.     int ty = transformMouseY(y);
  282.     if(!isPointOutOfBounds(tx, ty)){
  283.       if(m.territoryIDs.hasValue(m.map.get(tx, ty))){
  284.         currentColor = m.map.get(tx, ty);
  285.         return true;
  286.       }
  287.     }
  288.     return false;
  289.   }
  290.  
  291.   void randomizePerSecond(){
  292.     if(randomizePerSecond){
  293.       if(frameCount % 144 == 1){
  294.         randomize();
  295.       }
  296.     }
  297.   }
  298.  
  299.   void updateMultipliers(int newWidth, int newHeight){
  300.     widthMultiplier = (float)map.width/newWidth;
  301.     heightMultiplier = (float)map.height/newHeight;
  302.   }
  303.  
  304.   int transformMouseX(int mX){
  305.     return floor((float)mX * widthMultiplier);
  306.   }
  307.  
  308.   int transformMouseY(int mY){
  309.     return floor((float)mY * heightMultiplier);
  310.   }
  311.  
  312.   void update(){
  313.     randomizePerSecond();
  314.     updateMultipliers(width, height);
  315.   }
  316.  
  317.   void display(){
  318.     image(map, pos.x, pos.y, width, height);
  319.   }
  320. }
  321.  
  322.  
  323.  
  324.  
  325. PImage floodFill(PImage image, int sr, int sc, int newColor){
  326.   if(image.pixels[sr+sc*image.width] == newColor) return image;
  327.   Fill(image, sr, sc, image.pixels[sr+sc*image.width], newColor);
  328.   return image;
  329. }
  330.  
  331. void Fill(PImage image, int sr, int sc, int curColor, int newColor){
  332.   if(sr < 0 || sc < 0 || sr >= image.width || sc >= image.height || image.pixels[sr+sc*image.width] != curColor){
  333.     return;
  334.   }
  335.   image.pixels[sr+sc*image.width] = newColor;
  336.   Fill(image, sr-1, sc, curColor, newColor);
  337.   Fill(image, sr+1, sc, curColor, newColor);
  338.   Fill(image, sr, sc-1, curColor, newColor);
  339.   Fill(image, sr, sc+1, curColor, newColor);
  340. }
  341.  
  342.  
  343.  
  344. void mouseMoved(){
  345.   if(mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height){
  346.   }
  347. }
  348.  
  349. color currentColor = BLUE_L;
  350. void mousePressed(){
  351.   int mX = mouseX;
  352.   int mY = mouseY;
  353.   //println("Mouse: "+ mX + "," + mY);
  354.   if(mouseButton == LEFT){
  355.     m.colorReplace(mX, mY, currentColor);
  356.   }
  357.   if(mouseButton == RIGHT){
  358.       m.colorPick(mouseX, mouseY);
  359.   }
  360. }
  361.  
  362. void mouseDragged(){
  363.   if(mouseButton == LEFT){
  364.     m.colorReplace(mouseX, mouseY, currentColor);
  365.   }
  366. }
  367.  
  368. void keyReleased(KeyEvent event){
  369.   int e = event.getKey();
  370.   if(e == '1'){ showDebug = !showDebug; }
  371.   if(e == '2'){ randomizePerSecond = !randomizePerSecond; }
  372.   //if(e == 'p'){ buffer.dumpInProgress = true; }
  373.   if(e == 'p'){
  374.     new ImageDumpThread(buffer).start();
  375.   }
  376.   if(e == 'd'){
  377.     m.printMapDims();
  378.   }
  379. }
  380.  
  381.  
  382. color randomColor(int min, int max){
  383.   return color(int(random(min,max)),int(random(min,max)),int(random(min,max)));
  384. }
  385.  
  386. void printFrameTime(double delta){
  387.   delta -= System.nanoTime();
  388.   if(showDebug){
  389.     text("MS: "+ abs((float)(delta*0.000001)), 1,20);
  390.   }
  391. }
RAW Paste Data