Hexara rewrite with Java 8 & JavaFX

most recent jar: hexara-feb14-17.jar
in progress jar: Hexara8
Earlier, stalled Java2D version: Hexara (old)

My resolution for 2017 is to finish and publish Hexara. I want to get more adept with JavaFX and Java 8, so I decided to convert the previously stalled project.

Managed to get a running start into the New Year!

I have a three-tiered system set up for timing and animation that seems like it will work out pretty well.

  1. asynchronous, e.g., mouse motions, keyboard input (will be loosely coupled to other tiers) [hasn’t been implemented yet]
  2. graphics animation via an AnimationTimer (runs at 60fps)
  3. scheduled events and sound playback (runs at 44100 fps)

The AnimationTimer has but a single line of code. The overridden handle() method consists of the following:

    for (Animatable aa : Animatables.array) aa.update(); 

Animatable is an Interface with one method: update().
Animatables.array is a static array. I use a CopyOnWriteArrayList rather than an ArrayList, to allow concurrent access (can add or delete while array is iterating).

That covers the “update” portion of the game loop. As for “render”–that seems to be automatically handled by JavaFX. There is no need for Swing’s paintComponent() method or equivalent.

For the blocks that hold the letters: I’m using Rectangles. For the “cold” blocks, the innermost Rectangle is given a fill of silver (outer rectangles are progressively darker, and just the shape is drawn). The letter nodes are drawn after the Rectangle nodes and set up with a black fill.

For the “hot” blocks, the innermost rectangle is overwritten by a WritableImage (replacing awt.image.BufferedImage) created via a PixelWriter (replacing awt.image.WritableRaster) that obtains data over a 64 by 128 rectangle using Z-animation and a Perlin Simplex Noise function. The animation is run at half the speed (30fps – seems sufficient and is less of a cpu load than using a smaller z-increment at full speed) and the resulting graphic is scaled, rotated (for even-numbered positions), and translated via an ImageView node. The six ImageView’s all use the same static WritableImage as a source.

The series of notes played (via a real-time synth) are scheduled with an audio event-scheduler I wrote. When scheduling, it is possible to include a NoteListener as a callback function.

The NoteListener code on the managing class for the TitleBlocks sets a variable that tells the update() method to flip from “cold” to “hot”, for the first six notes. Loose coupling is very important so as not to burden the audio thread–let the animation thread handle the bulk of the work!

The start of the seventh note in the musical motif provides a hook into the note’s main volume envelope and flips a flag, so that the animation loop will inspect and use this value to set the Group (all the blocks) opacity–thus the fading of the graphics is a function of the note dying away. I do a bit of filtering and scaling of the envelope values to manage the visual fade. It probably seems a little long for a title sequence, but the intention is to cross-fade with the sounds and images of the main puzzle panel. Also, there will eventually be another visual animation (glow bloom and fade) triggered by the start of the seventh note.

I’m excited that this is coming together! Am pleased that the JavaFX code is clearer, easier to manage, and less verbose than Java2D, so far. Cross-fading to the puzzle panel is going to require some working out. I’m not sure yet if I’ll be flipping visibility switches and opacity values of nodes, or nulling and resetting the nodes, or if I’ll actually be adding and removing the Nodes from the root node. To be continued.

awesome! glad to see it’s still a living project. the game is really good.

I have coded the dunes landscape and some twinkling stars.
hexaratitlesxfade.jar

The title blocks are fading out and the landscape is coming in.
OOPS–note to self: have to manage the stars that are appearing in the dunes!

Completed fade:

The dunes are also created via Perlin noise. I’d like to have some sort of mountains in the background, and maybe a bit of atmospheric glow near the horizon. The sky I did before has a crude milky-way sort of cloud in it and some comets. On TODO list.

The biggest hitch was getting worried about altering Node values (opacity property values) from outside of the “JavaFX Application Thread”. It took a good half day just to research and figure this out. Turns out that threads created by JavaFX animation timers are considered by JavaFX to be part of the JavaFX Application Thread. So, it’s fine. The main thing is to not forget the plan of limiting the Audio thread to passing messages to the Animation thread, and not have it act directly on the Nodes. (Shouldn’t do this anyway as the Audio thread needs to run as free as possible.)

I hate spending time second-guessing plans that are working, but I did learn important things in the process.

Don’t get confused! AnimationTimers are not threads. They’re all invoked on the JavaFX application thread by the JavaFX pulse.

Cas :slight_smile:

Haha, just made almost identical response on Phil’s other topic - heard it from two of us now! ;D

So… this is only a title screen?

The screen with dunes and stars is background on the main game screen. Foreground is coming.

Project got bumped by work (thank you, Microsoft, for causing needless churn and billable hours with updates that aren’t 100% compatible with older versions), two sheet music orders to print (and printer heads that turned out to be cleanable–thought they were destroyed by inexpensive, refilled ink cartridges–almost signed away publishing rights when I thought printer was goner), an article invited to write for the hyperphysics site (almost done), finishing application to tutor on Wyzant. Hopefully I will be back on this by next week at the latest!

Yes, also found the API doc on AnimationTimer being executed on JFX application thread. Thanks again!

Some progress made this week to post. Continuing to work on “presentation layer.” Worked on the glyphs or beads or whatever these piece tokens are. Below is a set testing some colors. I won’t use all the combos, and might tweak them some more. But am trying not to get too nit-picky, as they are in the ball park.

The glyphs themselves are pngs, where the data in them is being used as a stencil. They were inspired by some religious and mystical symbols as well as scientific symbols and icons. I have this notion that each corresponds to a part of life–and the puzzle is to get all of them to fit together.

The colors and shapes are procedurally made. I took a Photoshop tutorial on how to make “gems” and tried to implement it in Java, putting in things like edge darkening, a top-down whitening (Y-axis), and an “inner glow” (made from an oval-band-gradient tool I made). Was able to come up with some significant improvements on the code I originally wrote. For one thing, I only load the “glyphs” once now instead of every time a new bead is made. For another, making the oval-band and the edge-darkening cutout for the hex, I realized that it was possible to take advantage of horizontal and vertical symmetry, and only calculate 1/4 of the area values.

Also, added to the “Pavilion”, including animated incense/smoke pots. Can be seen in the latest in-progress jar on the first post. But here is a graphic.

Was pleased to get what were previously rectangular supporting beams to be round columns. I don’t know why that defied me originally. Then again, I’ve already forgotten how I did it. Would have to read the code to see how the shading and angles of the contact points (roof, floor) were done.
The smoke is a simple particle system. The particles are 40x40, ranging from 1 to 0 over distance = 20. I originally was using a simple linear interpolation, where the value from 1 to 0 was directly proportional to the distance. These values are used as the alpha track on the smoke color that fills the rectangle. But it looks better (I think) when squaring the values. This makes the taper fade better at the transparent end. Again, figured out I could use quadrilateral symmetry and only calculate 1/4th of the rectangle. Also, the base array (a double[][]) is only made once. The 72 or so (haven’t entirely settled on the count yet) progressive images make use of ImageView, and scale the base array, by giving each a gradually diminishing overall alpha and by compressing the early particles on the x-axis and widening them progressively on the X-axis for the later stage particles. The “smoke-genies” have some real time controls for how much they wobble and how high they go. It is possible to introduce a leftward or rightward “wind”. I plan to make the smoke pots get more “active” as the user gets closer to solving the puzzle.

A lot of little touches that really have nothing to do with the puzzle mechanic itself, I know. But my idea is that the puzzle-game is as much about the setting, creating an appealing/peaceful/mysterious place that also supports mental concentration.

I have a bit more to do on the presentation basics: the panels and the hex grid. Then move on to working on the “model” layer, and “controller” layer. There remains implementing some glow sequences, as well.

[EDIT: Not sure if there are limits on the number of posts I can put in a row, and this is a minor update. Managed to finish some work on the “presentation layer” : the hex grid and the panels/scrolls. The blank forms are shown below. In the puzzle game, the icons will populate these structures. I also finished working on a glow-animation. That might be worth an example–will post in a bit.]

Added a glow animation to the capabilities. Jar is here: testglow.jar

The “glow” is a graphic that is made with a tool I wrote called an OvalBandGradient. This is basically a radial gradient, but where you can specify a uniform center region. Thus, the taper can start at a point that is certain distance from the center, rather than exactly at the center.

I’m animating it with an envelope from the audio envelopes I wrote for my synths. The envelope value is being used to update the ImageView.setOpacity() method.

In this jar, I set the envelope to first “flash” and then do a gradual fade-in and fade-out. The only reason for this is to show the envelope can loop and have multiple stages (6 levels/rates in this case).

I’m not totally convinced. Not sure what is bugging me about it. Will have to play with it some more but am also open to comments.

The lighting is kind of “domelike” at the max levels that I use. I’m wondering if instead of a linear gradient in the oval band I should do something like with the smoke particles and have the slope of the gradient be exponential, e.g., a function of the square of the distance from the top edge rather than just a linear calculation. Also wondering about adding some sort of randomization or disruption to the effect, so it isn’t quite so uniform.

I just overlay the glow and change the alpha. Maybe more needs to be done, such as adding another color transform limited directly to the pot, to make this more effective. But I don’t plan to actually glow the pots in the game. This is intended more for the Hex and glyph icons.

In any event, this accounts for most of the “presentation” layer at this point. I need to start focusing on the model and control layers now.

As usual, there are interruptions and distractions. This time, the possibility has opened up that I might be able to join a team working on a demo/proposal (bringing sound/audio expertise to the party) for a VR contract for a classic SciFi story (has been done as film and computer game but not 3D/VR). As a result, am putting energy into audio research: reading up on 3D audio issues, investigating some older voice-simulation tech (e.g., VOSIM), designing some speculative “useful” sounds with my FM synth and “box-filter-noise” tools. (Also: rereading the novel, have watched the film/tv-series anew checking out the use of sound, and need to check out the already existing games.)

Hi Phil, played it shortly, and got some stuff right (more based on intuition than logic lol), and was very curious about the beautiful smoke effect you created. Well, no need to ask about that since you explained it all here. I made some smoke effects for Bee Aware as well, but much simpler and not as beautiful as yours (although I guess the process is (roughly) about the same, animate some imageviews on a timeline (or similar), playing with random positions and scaling, opacity/fading and a bit of rotating). Anyway, I’ll keep your approach in mind for my next game (work has already started, but I have other priorities now, like finishing the publish process on Steam for Bee Aware). Also tried out your noise sculpting experiment, and liked the effects it made. I guess for background sounds it gives less load on the JVM than when using looping mp3’s?
Anyway, have a nice day! Greetz, Danny.

Thanks!

I really should follow through on this game. Am still muddling through figuring out how to release my first application. Aiming for itch instead of steam. Closer I get the more resistance to overcome. Seems to be a personal issue.

mp3’s are definitely more of a load than playing wavs which is more of a load than playing from memory, but I’m not sure how much. Half a dozen years ago, the commonly accepted notion was that you could play one mp3 (for background music, say) and a handful of short SFX cues at the same time, in a game. I’d be surprised if performance hasn’t progressed an order of magnitude since then.

Did you see the slice-streaming alternative to looping that I wrote? I should make an AudioCue version available. With this, it is possible to play a continuous, non-repeating audio stream from a small source (e.g., 3-5 seconds). I have examples up for a literal stream (a brook) and a campfire (could be improved with a second layer of random pops).

Happy to share the details of the “smoke genies”. I actually learned this algorithm from example code promoting the first iteration of JavaFX (back in 2011 or something?).

itch.io is just a joy to use. So simple, such a nice interface.

Cas :slight_smile:

@philfrei Thanks, I’ll keep your offer for the smoke code in mind, for now I really have to focus on getting Bee Aware on Steam. I guess I have to overcome what I call ‘publishing fear’…is my game good enough?.. will I sell even one copy?.. what if I sell thousands (aaaargh)?.. what if there are bugs I didn’t notice (more aaaaargh)? Anyway, just a bit more testing and text checking, and I’m really, really done.
I think you should not only consider Itch, Steam is the best platform when it comes to public attention (millions daily online instead of thousands). Only disadvantage is the api jungle (lol), took me some time before I figured that out, and ofcourse your store page, also takes some time before that is done. If you go for Steam, I suggest adding a lot of achievements (and maybe stats), which can help boost sales. And then there’s Steamworks4J, a (free) thin Java wrapper which connects your app with the Steam api (which is written in C). You’re definitely going to need that wrapper.
Ofcourse, there are more indie sites, like IndieDB (!) and IndieXPO. Anyway, if you do consider Steam, and need any help, just pm me.