FX My Life XV: End Game

Blake
6 min readJun 6, 2021

OK, I’m sufficiently bored with this to want to move on. I’m going to push this up to Github at https://github.com/dsbw/fxgames.git.

For future adventures, I’ll do the following: I’ll start a new branch for the game we’re working on, and for each entry in the blog, I’ll commit the changes to git. This should make it super-easy (barely an inconvenience!) to follow along.

I’ll also be a little less drunk in prose and code styles, though not consciously. After all, who wants to be boring? But we learned a lot in this first muddle-through, and that will inform our next muddle-through, so it will seem less muddly.

OK, so before I push, let’s do a little clean-up. I was really just trying to get stuff to work initially, and…oh, what a mess I made!

So many Xs and Os

The first issue I had was putting things in NOT the root. (The files are red because they’re not added to the git repository yet.)

The FXMLs and the graphics should go into a separate directory, I think. Especially as we add new…things…we’re going to want avoid having everything pile up in one location.

I’m used to putting things up at the top, where the resources sub-directory is with the css and gfx sub-directories but ultimately, I dropped them into the main directory because I could not make anything else work.

I’ve tried putting this sub-directory everywhere, and the running code can’t find it. In theory, you’d think that if everything’s in one directory and loading fine, you could just add a sub-directory and load from there, but, no, not exactly.

This stuff is always a royal PITA. IntelliJ will nag you every time you move a file, about adding it to git. You can turn that off, of course, but then you have to remember to turn it back on later (if you want it).

Another tricky thing — and the thing that tripped me up is that you have to rebuild the project or you’ll end up with code that doesn’t recognize that you’ve moved the resource files.

I realized, when I dragged some files to a different directory, IntelliJ helpfully re-addressed them in the code. This gave me an idea of the final structure of the output. It worked for me to add the files under the src directory:

You’ll notice I still have the Xs and Os in the fxgames directory with the code. I want to get rid of the ones I’m not using, so I didn’t want to just dump them ALL in the resources directory.

Searching the code for “X.” reveals that we’re using “X.gif” and “O.gif” as well as “xo.gif”, so let’s get rid of the Xs and Os that aren’t that. Ooh, and we left a tttgrid.fxml in the fxgames sub-dir, so let’s get rid of that.

It’s almost looking civilized:

And you better believe that I’m running the code in-between these deletions. The FXML files themselves are where the GIFs are being used, which is kind of interesting:

</rowConstraints>
<children>
<ImageView id="X" fx:id="X" fitHeight="79.0" fitWidth="105.0" onDragDetected="#handleOnDragDetected" pickOnBounds="true" preserveRatio="true">
<image>
<Image url="@../fxgames/X.gif" />
</image>
</ImageView>
<ImageView id="O" fx:id="O" fitHeight="79.0" fitWidth="105.0" onDragDetected="#handleOnDragDetected" pickOnBounds="true" preserveRatio="true" GridPane.rowIndex="1">
<image>
<Image url="@../fxgames/O.gif" />

So this code is saying “go back up to the parent directory (which would be “src”) then down into “fxgames” to get the gifs. Sorta makes you wonder where it’s starting from. Let’s see what happens if we move ALL the GIFs back into resources.

Why, lookie-lookie:

</rowConstraints>
<children>
<ImageView id="X" fx:id="X" fitHeight="79.0" fitWidth="105.0" onDragDetected="#handleOnDragDetected" pickOnBounds="true" preserveRatio="true">
<image>
<Image url="@X.gif" />
</image>
</ImageView>
<ImageView id="O" fx:id="O" fitHeight="79.0" fitWidth="105.0" onDragDetected="#handleOnDragDetected" pickOnBounds="true" preserveRatio="true" GridPane.rowIndex="1">
<image>
<Image url="@O.gif" />

Now that they’re in the right places, I wonder if IntelliJ will just adjust whenever we move them?

Yes! Look at that!

With the game basically completed, it became a lot easier to focus on this (relatively minor) issue. One thing that happens when one tries to learn something is that there are so many unknowns presenting themselves all at once. It’s kind of helpful to just cope for a while until you can get a handle on things.

But it’s vitally important to go back and fix all the cope-y stuff later. Seriously. Have mercy for the maintainer of your code — it may well be you!

Let’s make a directory for the css, even though we’re not using any yet, and move styles.css in there.

Oh, wow, that broke everything!

Let’s see, we are, actually, using it one place. Over in Main.

scene.getStylesheets().add(getClass().getResource("styles.css").toExternalForm());
primaryStage.setScene(scene);

screenController = new ScreenController(scene); //not using, currently
screenController.addScreen("frame", FXMLLoader.load(getClass().getResource("../resources/main/frame.fxml")));

Well, you’d think we’d be able to just imitate the path for frame.fxml, which does work.

scene.getStylesheets().add(getClass().getResource("../resources/css/styles.css").toExternalForm());

However, you may once again be fooled: Rebuild your project when you’re fiddling with resource files or you may be executing code that doesn’t contain the files in their new locations.

Now, people can (and do) get carried away with the “putting everything in its own folder”. It doesn’t really help to have a zillion folders with one file each in them; that is, you’re not organized just because you put something in a folder. The folders have to make sense. Actually, even more than making sense, they have to reduce the mental burden on the developer.

Like, we could justify putting everything into the root folder initially because we were learning. The burden of having to look for things and making sure that the code was all pointed to the right locations was far greater than the burden of having to sort through a bunch of files to find what we wanted. (That was a fair justification for leaving the extraneous graphics files in, as well.)

But when we start our next game, we don’t want to have to stare at those Xs and Os any more. Also, we may as well put the code into its own folder, as well.

This isn’t so much because those two files are especially burdensome, but future games will all be in their own folders as well, and that will help when working on those. All the main/shared stuff can be in the root.

We’ll have to make some changes, since the games aren’t in the exact same package as the main code. Coord, e.g., needs to be public:

package fxgames;

public class Coord {
public int x;
public int y;

public Coord(int aX, int aY) {
x = aX;
y = aY;
}
}

For some reason, we put NodeController’s addHandler code as protected. I don’t know why, but we need access to it all over, so:

public void addHandler(Node node, EventHandler<ActionEvent> eh) { handlerMap.put(node, eh);}

It’s used in the TttController’s initialize method, which reminds us we still have this ugly bit of code:

NodeController.me.addHandler(outerGroup, (e)

Ugh. “me”. Well, things aren’t going to be perfect for a while yet.

Oh, we should delete that extraneous top-level resources directory. I once forgot to do that and some combination of git and IntelliJ never let me delete it ever again.

I mean, I could delete it, but it would always come back. And I never could figure out which thing was responsible for re-creating it.

OK, I think this is good enough. Let’s push this puppy!

Neat! Now the whole world can read our code and laugh at us for writing it!

OK, my code. And me. They’ll laugh at me. But that’s fine, we did what we set out to do back in March. And we’ll have even more fun next time!

--

--

Blake
0 Followers

I am a poor, wayfaring stranger, traveling through this world of woe.