Windowed, threaded, double-buffered JFrame from applet

Finally figured out a sane transition from “Java Game Programming for Dummies” applets to Brakeen’s wonderful modernity. GPFD is great for learning game programming mechanics [1], but applets are limited in scope: one example is writing to local disk.

Brackeen hits full-screen game dev from the get-go, but my REPL approach calls for windowed tools. My current preferences are authorship via the game engine and being able to jump in instantly while searching SO and surfing the web.

The linked example¬†demonstrates double-buffering [2] of a windowed component with Graphics2D reference for anti-aliasing in a threaded JFrame. A blue ball moves east while a vandal scrawls “Hello world” in magenta on a marbled world. (It’s all present tense because paint() gets called 1000/30 milliseconds.)

hello-world

Next up is to figure out Swing harmony, integrating NullRepaintManager or however the journey goes.

[1] “Java Game Programming for Dummies” is serious; it’s the Java “Gems” of game programming. You will learn momentum, resultant vectors, custom LayoutManager, MouseDrag, sliding block intersection/union rectangle tricks, and a ton more.

[2] Smooth animation, not an assurance of later performance. There are certainly better ways.

Advertisements

Digesting books

When I started mentally replying to an author’s sentences, I thought maybe I had reached the internalization phase: we of one mind, taking a walk in the park, discussing ideas placed on impassive print. Any time before that I could not conspire to claim real comprehension, except at the highest of handwaving heights, yet both kinds can be forgotten without review.

Friends are like that too. That’s why you keep up with them. Memories revive themselves in company; pictures are visual posts. The relief at saving a tangible piece of a fond past, almost a gratefulness to one’s younger self.

It wasn’t a story, though. Maybe philosophy, since we’re thinking about it. I almost grasped the idea of the loop invariant. If the claim is true before the ith iteration, to say that it is true after the next one, is saying that the past is true regardless of the next present. With a zero-based array and the first element sorted, in n-1 loops you’ve got the whole array done, and in iteration n the loop ends.

Writing a date from Excel serial integer off-by-one

Calculating the serial integer of an Excel date had me off by one, but there’s two reasons for being off on the numerical representation:

  • An artifact of Excel fixing a Lotus 1-2-3 bug, (+1)
  • The date 1900/01/01 has the value 1, not zero. (+1)
; date-val.au3
; compile as console executable date-val.exe
; see batch script below

If $CmdLine[0] < 1 Then
  ConsoleWrite("Error: must supply yyyy/mm/dd format." & @CRLF)
  Exit 1
EndIf

Dim $startDate = "1900/01/01"
Dim $endDate = $CmdLine[1]
Dim $dayValue = 1  ; starts at 1

While $startDate <> $endDate
  $dayValue += 1
  $startDate = _DateAdd("D", 1, $startDate)
WEnd
$dayValue += 1 ; Lotus 1-2-3 bug
ConsoleWrite($dayValue & @CRLF)

I had to use a similar solution because a naive SQL query on a workbook, with AutoIt, returns integers rather than dates with the .Value() function. You don’t want the user to filter the workbook and end up with text as dates, so

for /f "tokens=*" %%i in ('date-val 2020/04/01') do (
  echo =DATEVALUE^(YEAR^(%%i^)^&"/"^&MONTH^(%%i^)^&"/"^&^
    DAY^(%%i^)^),col2,col3 >> workbook.txt
)

And then convert it:

> ssconvert workbook.txt workbook.xls

Miserable creativity

One fear I had with cURL was that I would never figure it out, that my proposal to automate network transport would fail. My current knowledge still has the form and feel of a priest, a little more experienced, having a better grasp of where problems might occur. I have a workflow and the tools, but deviating from the prescribed causes me paroxysmal stress.

I learned it because my intuition told me, “This is one approach.” It was built on the foundation of zeal, that at the lowest layer communications occurred in discrete operations without human interference. It happens to be a fact, but mainly I believed it to be true. (Which for a person writing programs seems like a sort of derangement.)

Game programming is similar: here’s a whole ton of code, and out comes a screen and a bouncing ball. Functions invoke out of convenience; logic flows throughout the sap. There’s no real concept of composition: I can’t pause the process, examine something, and later script it with pipes. Everything happens on a relentless tick, updating everything, calculating everything, ceaseless.

Well, there is one more fear: I will have learned these concepts, yet have nothing to create.

An applet a day

Monolithic applet games with package-scope, single-file and moving between sleeping thread-ticks: I think that’s a good place to start a REPL process. Brackeen is awesome, but sometimes the garage is a better place to foment the small: “Java Game Programming for Dummies” is that respite.

JGPD implements game programming concepts, but with less abstractions: the accompanying CD has JDK 1.0.4 and uses java.awt.applet. No real Swing ideas to manage – which by itself is not significant – but no NullRepaintManager, ThreadPool and so forth.

However, Brackeen’s book goes farther: parallax backgrounds, 3d, and modern networking principles with Java NIO. The books together form a potent one-two punch. My task is to push out the first fifty go-carts. My lab is a world spaced by timeslices; my stories play out in little windows.

Go, gameplay, go!

The king’s panel

Getting windowed mode is not as much of a change as I thought. Using Brackeen’s code, I eschew the DisplayMode object and initialize a personal handle on a specialized type-of JPanel: my own, which installs for itself a NullRepaintManager. My drawing routines go into the paint() method.

This instance of a special JPanel is wrapped by a subclass of JFrame, whose paint() method delegates to the panel. Similarly to the SimpleScreenManager example, I instantiate this is-a JFrame in main() and invoke run() with the DEMO_TIME thread sleep. Instead of restoring the screen as in the full-screen example, the finally clause has System.exit(0) and the constructor is initialized with setDefaultCloseOperation() to exit on close.

So I get the same behavior of exiting after a limited time and the blue background, and the “Hello world” words, except it’s in a convenient smaller window. Whether this will work with GameCore and a game loop in general remains to be seen.

My hope is this establishes an intermediate practice of an arbitrary canvas that can be nestled into a larger GUI of established widgets, easing the development of tools and intra-window friendliness: software isn’t made in a vacuum; games shouldn’t be any different.

Unconscionable sprites

Some guilt with drawing sprites at work: the future app is “something” and I’m doing research; then why do I feel self-conscious?

A big part of games – I mean – realtime updates on an arbitrary canvas – is graphics, art. Maybe I can get away with reskinning widgets and custom components. I may need them later; I could sell them in some foreign marketplace.

Fullscreen is hard to take: I like having other windows around. On the other hand, creating things with the same engine that powers the end-user experience is like eating one’s own dog food: development of the tech proceeds in synced step.

The Java Trail hints that if full screen mode is prohibited, a windowed viewing mode should suffice. This implies either is possible. So let’s get with that. I want to use Netbeans’ GUI builder to place widgets just so, knowing that GUI layout is the bane of every starting project, ever.

Old dogs, new tricks

Arranging my room to prepare for new beginnings, I unearthed two books from college: one on object-oriented design and analysis and another on software engineering. My path so far has been one of scripts and macros – short, small programs to run little tasks; each building up to perform “things of value,” but otherwise scattered and bespoke.

An emergent property is a characteristic of a system’s layer that could not have been predicted by the layer beneath it. TCP, a duplex, reliable channel, was built on top of the abstraction of information broken into packets, sent on a prayer. Organs are assembled from tissues, which are composed of cells.

A part of me wants to understand why it makes sense that “square” objects send messages to “player” objects, and why it’s okay to do “Pure Fabrication” to describe dice in a cup. It’s all messages, right? Yet there’s an approach to it, a sense of grasping sanity, which eludes me in Java land.

I think it will be worthwhile to at least go through those two books, because I would very much like to model within domains without thinking about API calls. Life is frittered away with API calls. Simplify, simplify.

Launch4j 3.1.0 beta2 creates exe file from Java jar

AutoIt compiles to a standalone executable and this is magic deployment. Not having to configure a JRE would put Java on the same level.

Launch4j 3.1.0 beta2 lets me create executables of .jar files built from Netbeans. This lets me use GUI builder for the frontend and keep AutoIt as a database interface.

Getting started is easy:

  • Basic tab: name your .exe, select your .jar file, and put a . (period) in the Change Directory field.
  • Classpath tab: check custom classpath, choose your .jar file, and uncheck custom classpath. Launch4j found the main class automatically!
  • JRE tab: enter “1.7.0” in the minimum JRE version.
  • Copy over the massive, 143 MB jre7/ folder to the same location as your output directory.
  • Type “jre7” (without quotes) in the JRE path under the JRE tab.

Click the compile button and you will have an .exe! You can move this around with your ancillary programs, and the internal relative paths will work. I rely heavily on piped procs, so it is essential that the Java program’s working directory adjusts to its executing location.

Forty-three megabyte executables, even standalone, is abhorrent. But that might do for now.

Small steps outside bounds

My vector into Java was from the command-line: receiving from standard out, reading from standard in, reading from files, and writing to the same. I threw String[] arrays around, comma-separated lines, among the model, view and controller.

I thought about Brackeen’s ScreenManager: the small steps, an ArrayList, solving exercises in the context of a full screen. Animation and graphics as the new lingua franca: in place of drawString(), graphics “primitives.” A falling bar as a fuel tank, seventeen circles less eight for nine. Composite shapes expressed as combined calls, wrapped in an object and passed relative coordinates.

Chapter 5 is the culmination: after it is NIO-lib networking and 3d-graphics. Before it is Chris Crawford’s admonition: your first fifty games will suck.

Feature-based packaging lets me put the controller with the model, but the latter remains package-private. The view can only instantiate the controller. I tried to “use” an interface but it didn’t make sense. Maybe the context should be

  1. minimizing resistance to change, and
  2. rapid turnaround

All design culminating toward the ship. All iterations user-centric.