Tower Defense in JavaFX
I wanted to use my Game Engine to write a Tower Defense game for a long time, but since there was an effort to create a JavaFX Tower Defense Game by another group, I thought I should rather create a different game instead. From the mailing list I learnt, that the other game is no longer being developed. So I decided I should give it a try.
Tower Defense is a game that is perfect for a Tile based approach, so I started to look for some tiles. I found some here and the artist, Silviu Ploisteanu, gave me the permission to use them in my demo. Tower Defense as a game is very similar to a TileMap editor, so I’ll be able to reuse a lot of code from the Editor I’ve created a while ago:
The first thing to do was to combine the individual graphics into images for tiling. I grouped the enemies, the turret bases, the cannons, the terrain, and also created a single tile tileset for the background. After that I used a TileMap Editor (http://www.mapeditor.org/) to create TileSets from these images. I’ll probably have to do that part again, because Gimp changed the colors in this process, but for now I don’t care too much about the visuals.
Then I added 5 layers from bottom to top to a new map: “background”, “terrain”, “turret-bases” and “turret-cannons”, and “enemies”. There will be a “bullets and explosions” layer as well, but I’ll add that manually later on. So far, no coding is involved, and through the TileMap based approach we already have a serialization format for the game. So when the user edits the map, we can simply store the changes to a TileMap. This is how the map looks now:
The next step is the coding. I simply created a new JavaFX Application with a BorderPane. In the center I’ll have the playfield, to the right I’ll have a palette with cannons.
This is how you create the GameCanvas:
tileMap = TileMapReader.readMap(fileURL); canvas = new GameCanvas(tileMap.getTilewidth() * tileMap.getWidth(), tileMap.getHeight() * tileMap.getTileheight(), tileMap.getTilewidth() * tileMap.getWidth(), tileMap.getHeight() * tileMap.getTileheight()); // add all the layers ArrayList layers = tileMap.getLayers(); for (TileMapLayer tileMapLayer : layers) { canvas.addLayer(tileMapLayer); }
Then I get the TileSet with the cannons and create the Palette. I’m using a VBox for the Palette, since I want to make the terrain editable as well, and I might add another TileSet for that later:
TileSet turrets = tileMap.getTileSet("turrets"); TileSetView turretView = new TileSetView(turrets); VBox palette = new VBox(); palette.getChildren().addAll(turretView);
The TileSetView simply displays the Base image, and allows you to select a Tile via mouse click. I’ll maybe show the code a bit later, when we start with the user interaction. For now this is what we see after launching the game:
The ugly red area is the default background. Unfortunately the background image Dimension isn’t a multiple of the tile size, so I’ll have to define an offest later on. For now I’ll ignore it, it’s just a backgound…
Now we want the user to be able to place turrets. For now the player has an unlimited amount of money, so he can place as many turrets as he wants. The only constraint is, that he can only place them if he’s on a platform, and if there’s not a turret already. So we add an EventHandler for Mouse Events that get’s the selected Turret from the Palette, and adds it to the turret-base layer. For the sake of simplicity, I’ve combined the turret-base and the turret into one image for now:
canvas.setOnMousePressed(new EventHandler() { @Override public void handle(MouseEvent t) { double x = t.getX(); double y = t.getY(); int idx = (int) ((int) x / tileMap.getTilewidth() + (((int) y / tileMap.getTileheight()) * tileMap.getWidth())); if (platformLayer.getGid(idx) != 0 && turretBaseLayer.getGid(idx)==0) { turretBaseLayer.getData().setGid(idx, turretView.getSelectedGid()); } } });
As a result, we can now place turrets whereever there’s a platform and no turret yet:
I think that first part already shows, that the API is really nice to create simplegames without having to write an awful lot of code. In the next part we’ll add the spawnpoint and the target and use A* to calculate the enemies path.
Why do you not have the jar and source up here?
Do you finished your game ? Can i see the source code please ?