JavaFX GameLoop

I have an RPG I am writing in javafx kind of like an RPG / RTS mix. You have many units and there are many enemies. You click on tile to move units , pick up items, pitch tents, launch canoes, ECT. The tiles are all are linked to a GridPane of sub classed buttons that have an event listener tied to each one. Each tile has an array list of items that are drawn and one TileOccupant plant, enemy solider, wall, table that is also drawn. When the Gui needs to be updated only the tiles that change are drawn. The tiles are on maps and each map has 150 x 150 tiles. Each is 25 px by 25 px in size. So drawing just the tiles I need to is faster.
,
I was able to get one man moving from tile to tile using a while loop

while(newLocation != currentLocation){
move();



Enemy  enemy= enemyCheck();


if (enemy!=null){
attack(enemy);
}
if (hunger==0){
eat();
}
if (thirst==0){
drink();
}

hunger--;
thirst--;

}

My horrible plan for the game progressing was to have all the moving /attacking / action code called from the Run() method have each instance of the fighter class (which is the base class that enemies and soliders extend ) implement the Runnable interface and when a new instance of an enemy was created pick a tile and call the Run() method and have start moving somewhere in real time and when hit something start attacking it same for soliders only the the user would tell them where to move through button clicks. Since each time run was called they would be moving / attacking / eating ECt. in new thread the units would be moving in real time like an RTS game.

Now I know my plan stinks and has many pitfalls. I know I need some kind of game loop. I think I still need two threads though as having my game loop running on the JaxaFX applaction thread is not a good Idea. I’m doing this whole game my self and since I suck at drawing and animation there will not but much of that just men / enemies moving from tile to tile. My question is how do I write a proper game loop? Since I’m not animating anything or doing heavy logic what kind of timer do I need for the loop? How do I enter the loop? I have made a loop but after I enter the game while loop the map is never drawn on the screen and the game just stays at the start screen.

here is the drawing code liked to the map classes

public class MapDraw {
	Stage stage;
	HBox headerPane;
	ScrollPane bottomConsole;
	Label title;
	Console console;
	GridPane mapPane;
	Button [] [] buttonMap;
	StackPane [] [] paneMap;
	int mapCounter;
	int currentMap;
	VBox mainPane;
	Scene scene;
	ScrollPane pane;
	Map []  maps= new Map [4];
	ArrayList <MapButton>  mapChangeButtons = new ArrayList<MapButton>();
	MapDraw(){
		console= new Console();
mainPane= new VBox();
		 headerPane=new HBox();
		 title= new Label("");
		 title.setStyle( "-fx-border-style: none; -fx-border-width: 0; -fx-border-insets: 0; -fx-font-size:34px;");
		 headerPane.setStyle("-fx-background-color: #2A7226");
		 headerPane.setPrefSize(1200,100);
		 headerPane.getChildren().add(title);
		 mapPane= new GridPane();
		 mapPane.setHgap(0);
		 mapPane.setVgap(0);
		 mapCounter=0;
	}
	public void reDrawTile( LandSquareTile tile){
		int xLocation=tile.getLocationx();
		int yLocation=tile.getLocationy();
		System.out.println("xlocation" + xLocation);
		System.out.println("ylocation" + yLocation);
		paneMap[xLocation][yLocation]= new StackPane();
		paneMap[xLocation][yLocation].getChildren().add(buttonMap[xLocation][yLocation]);
		String imageSource=tile.getImage();
		if(imageSource==null){
			imageSource="empty.png";
		}
		Image image= new Image(imageSource);
		ImageView imageView= new ImageView(image);
		imageView.setFitHeight(25);
		imageView.setFitWidth(25);
		imageView.setMouseTransparent(true);
		paneMap[xLocation][yLocation].getChildren().add(imageView);
		ArrayList<Things> thingsToDraw= new ArrayList<Things>();
		thingsToDraw.addAll(tile.getThings());
		int numberOfThings=thingsToDraw.size();
		if (numberOfThings>0){
		for (int counter=0; counter<numberOfThings; counter++){
			 imageSource=thingsToDraw.get(counter).getImageSource();
			drawOnMap( paneMap[xLocation][yLocation], imageSource,  xLocation,  yLocation);
		}
		}
		mapPane.add(paneMap[xLocation][yLocation], xLocation, yLocation );
		reDrawMap();
	}
	public void reDrawTile( ArrayList<LandSquareTile> tiles){
		int size=tiles.size();
		for (int count=0; count<size; count++){
		int xLocation=tiles.get(count).getLocationx();
		int yLocation=tiles.get(count).getLocationy();
		paneMap[xLocation][yLocation]= new StackPane();
		paneMap[xLocation][yLocation].getChildren().add(buttonMap[xLocation][yLocation]);
		String imageSource=tiles.get(count).getImage();
		if(imageSource==null){
			imageSource="empty.png";
		}
		Image image= new Image(imageSource);
		ImageView imageView= new ImageView(image);
		imageView.setFitHeight(25);
		imageView.setFitWidth(25);
		imageView.setMouseTransparent(true);
		paneMap[xLocation][yLocation].getChildren().add(imageView);
		ArrayList<Things> thingsToDraw= new ArrayList<Things>();
		thingsToDraw.addAll(tiles.get(count).getThings());
		int numberOfThings=thingsToDraw.size();
		if (numberOfThings>0){
		for (int counter=0; counter<numberOfThings; counter++){
			 imageSource=thingsToDraw.get(counter).getImageSource();
System.out.println("xlocation" + xLocation);
System.out.println("ylocation" + yLocation);
			drawOnMap( paneMap[xLocation][yLocation], imageSource,  xLocation,  yLocation);
		}
		}
		mapPane.add(paneMap[xLocation][yLocation], xLocation, yLocation );
		}
		reDrawMap();
	}
private	void drawOnMap( StackPane pane, String imageSource, int xLocation, int yLocation){
		Image  image = new Image(imageSource);
		ImageView imageView= new ImageView(image);
		imageView.setMouseTransparent(true);
		double height=imageView.getFitHeight();
		double width=imageView.getFitWidth();
		double newHeight=height;
		double newWidth=width;
		if (height>width){
		 newHeight=20;
		 newWidth= (height/20)*width;
		}
		else if (height>width){
			 newWidth=20;
			 newHeight= (width/20)*height;
			}
		else {
			 newHeight=20;
			 newWidth=20;
		}
		imageView.setFitHeight(newHeight);
		imageView.setFitWidth(newWidth);
		pane.getChildren().add(imageView);
	}
public void addConsoleInfo(String info){
	console.addDisplayInfo(info);
}
	public void drawMap(int xSize, int ySize,  LandSquareTile [] [] map, Button [] [] buttonMap, Stage stage){ /// draws the map of tiles
		this.stage=stage;
			String imageSource="";
		for (int countx=0; countx<xSize; countx++){
			for (int county=0; county<ySize; county++){
				imageSource=map[countx][county].getImage();
				if(imageSource==null){
					imageSource="empty.png";
				}
				Image image= new Image(imageSource);
				ImageView imageView= new ImageView(image);
				imageView.setFitHeight(25);
				imageView.setFitWidth(25);
				imageView.setMouseTransparent(true);
				buttonMap[countx][county].setMinSize(25,25);
				buttonMap[countx][county].setMaxSize(25,25);
				buttonMap[countx][county].setStyle("  -fx-border-style: none; -fx-border-width: 0; -fx-border-insets: 0; -fx-fout-size: 4px");  
				StackPane stackPane= new StackPane();
				stackPane.getChildren().add(buttonMap[countx][county]);
				stackPane.getChildren().add(imageView);
				stackPane.setMaxSize(25,25);
				stackPane.setMinSize(25,25);
				paneMap[countx][county]=stackPane;
			}
		}
		imageSource="";
		this.buttonMap=buttonMap;
		for (int countx=0; countx<xSize; countx++){
			for (int county=0; county<ySize; county++){
				ArrayList<Things> thingsToDraw= new ArrayList<Things>();
				thingsToDraw.addAll(map[countx][county].getThings());
				int numberOfThings=thingsToDraw.size();
				if (numberOfThings>0){
				for (int count=0; count<numberOfThings; count++){
					 imageSource=thingsToDraw.get(count).getImageSource();
					drawOnMap( paneMap[countx][county], imageSource,  count,  county);
				}
			}
				mapPane.add(paneMap[countx][county],countx,county);
			}
		}
		displayMap();
	}
private void displayMap(){
		bottomConsole=console.getConsole();
		ScrollPane pane = new ScrollPane(mapPane);
		pane.setPrefSize(1200,1000);
		String mapName=maps[currentMap].getMapName();
		this.title.setText(mapName);
		mainPane.getChildren().add(headerPane);
		mainPane.getChildren().add(pane);
		mainPane.getChildren().add(bottomConsole);
		scene= new Scene (mainPane);
		stage.setScene(scene);
		stage.show();
		System.out.println("here");
		}
private void reDrawMap(){
 pane = new ScrollPane(mapPane);
	pane.setPrefSize(1200,1000);
	stage.setScene(scene);
	stage.show();
	System.out.println("here");
	}
	public  void newMap(Map map, Stage stage){ // makes a new map button and adds it to the header
		maps[mapCounter]=map;
		currentMap=mapCounter;
		int xSize=map.getXSize();
		int ySize=map.getYSize();
		paneMap= new StackPane[xSize][ySize];
		MapButton button= new MapButton(0, mapCounter, null, map);// y location is mapnumber
		String mapName=map.getMapName();
		button.setText(mapName);
		button.setOnAction(new EventHandler <ActionEvent>(){
			@Override
			public void handle (ActionEvent k ){
				MapButton button= (MapButton) k.getSource();
				int mapNumber= button.getYLocation();
				LandSquareTile[] [] map=maps[mapNumber].getMap();
				Button [] [] buttonMap = maps[mapNumber].getButtonMap();
				int xSize=maps[mapNumber].getXSize();
				int ySize=maps[mapNumber].getYSize();
					currentMap=mapNumber;
				drawMap( xSize, ySize, map, buttonMap, stage);
			}});
		mapChangeButtons.add(button);
		headerPane.getChildren().add(button);
		mapCounter++;
console.addDisplayInfo("welcome to the " +mapName+"!");
	}
	private StackPane getNodeFromGridPane(GridPane gridPane, int col, int row) {
	    for (Node node : gridPane.getChildren()) {
	        if (GridPane.getColumnIndex(node) == col && GridPane.getRowIndex(node) == row) {
	            return (StackPane) node;
	        }
	    }
	    return null;
	}
}




and my crappy game loop that doesn’t work the drawing code is called from each fighter function to update the map with the changed tiles.

MainLoop(){
		
	}
	public void setMap(Map map){
		this.map=map;
	}
	
	public void moveLoop(){
	run();
		
	}
		
	public void 	run(){

	
	
	
	int times=0;
	
	 while(numberOfSoliders!=0){
if( times==0){
	map.drawMap();
	
}
		String action="";
	int size=fightersOnMap.size();
	
		 for (int count=0; count<size; count++){
			 action=fightersOnMap.get(count).getAction();
			 if  (action.equals("move")){
			 fightersOnMap.get(count).run();
			 }
			 if  (action.equals("rest")){
				 fightersOnMap.get(count).rest();
				 }
			 if  (action.equals("attack")){
				 fightersOnMap.get(count).attack();
				 }
			 if  (action.equals("distanceattack")){
				 fightersOnMap.get(count).distanceAttack();
				 }
			 if  (action.equals("tent")){
				 fightersOnMap.get(count).pitchTent();
				 }
			 if  (action.equals("eat")){
				 fightersOnMap.get(count).eat();
				 }
			 if  (action.equals("drink")){
				 fightersOnMap.get(count).drink();
				 }
			 if  (action.equals("pick up")){
				 fightersOnMap.get(count).pickUpItem();
				 }
			 if  (action.equals("throw")){
				 fightersOnMap.get(count).throwItem();
				 }
			 
			 if  (action.equals("launchcanoe")){
				 ((Soliders) fightersOnMap.get(count)).launchCanoe();
				 }
		 
		 
		 times++;
		 
		 
	 }

	 }
		 
	}
	
	
	
	 
		public void addFighter(Enemies  fighter){ // add a new enemy to the game loop
			
			fightersOnMap.add(fighter);
			numberOfEnemies++;
			
		}
public void addFighter(Soliders fighter){ // adds a new solider to the game loop
			
			fightersOnMap.add(fighter);
			numberOfSoliders++;
			System.out.println("ewghwefy");
					
			
		}

public void removeFighter(Enemies fighter){ // removes an an enemy from the game loop
	
	fightersOnMap.remove(fighter);
	numberOfEnemies--;
	
}
public void removeFighter(Soliders fighter){ //removes  a solider from the game loop
	
	fightersOnMap.remove(fighter);
	numberOfSoliders--;
	
	
}
				
		
		
		
	}