CompSci 308
Spring 2023
Advanced Software Design and Implementation

OOGASalad

What if the behavior of your system was largely controlled by the configuration of its plugins? What power would that give you? — Robert C Martin

Specification

In teams, write a Java program from scratch using OpenJFX (without FXML), that provides a No-Code authoring environment for game designers to build 2D games of a specific genre using a interactive, visual tools that require minimal programming, such as:

Game Genre

Example game genres include:

Data Files

No modern game hardcodes individual level data into its source code, likewise your game variations should be determined solely by configuration data files that also activate general game features (these files can facilitate the use reflection to specify game specific Java code to run, but cannot require specific Java setup code for an individual game). Games should be saved in a format that allows them the be loaded for additional editing or played by a user (perhaps using a separate program that might be run on the same machine as the editor or it might get access to game files via the web). The exact format and content of configuration file(s) will be determined by your team, but it must be a standard file type with a parser (rather than developing your own) such as:

Example Games

Create a variety of games (as a team and individually) that differ primarily in their behavior to demonstrate the flexibility of your project's design:

Game Player

Create a separate game player program that allow users to:

Note, this program can be as simple or complex as your team is interested in making it, depending on whether or not you want to add embellishments beyond simply playing games (like accounts, ratings, comments, etc.).

Separate Style and Language

Any colors, fonts, or other appearance styling should be able to be changed dynamically between at least three different options (such as Dark or Light modes, Duke or UNC colors, larger fonts for presentation mode, etc.). Any text displayed should be able to appear in at least four languages (Pig Latin is a popular option or you can use Google Translate if no one on your team can do it).

Testing

Test your program using JUnit and TestFX (with assertions both for typical situations and all possible thrown Exceptions) to separately verify the Model and View work as intended. Generally, aim to create a test class for each of your concrete classes with at least two well-named tests for each non-trivial public method (more than two are expected for complex methods) and try to achieve at least 85% Line test coverage of each class.

Extensions

Additionally, your team must include features from each category below to stretch your design further and to differentiate your project from others. These extensions must further the good design of your program by being integrated into the project through abstractions, not simply added at the last minute as classes or methods that require changing existing APIs or code that should be closed.

Some ideas include:

Submitting Your Work

Use GIT to push your team's implementation to the master branch of the provided, sharedoogasalad_teamNN repository hosted in the course's Gitlab group.

As your submission for this project, use GIT to add, commit, and push the following:

Your code is expected to follow the course coding conventions and follow Javadoc conventions.

Your team's project GIT repository must show many, purposeful, commits from all team members rather than just one or two large "kitchen sink" commits and marathon merging or redesign sessions. Specifically, we will be looking for deliberate attempts to regularly:

We strongly suggest using the course's suggested GIT workflow for teams to manage this process.

Deliverables

Each week you will have something due:

With each deliverable:

Example

Consider the (un)popular game Monopoly and its official rules (which most people have likely never actually read) that determine:

Games that have a similar look and feel, but differ only in storyline are easy to implement. For example, Duke-opoly is a variation that can be implemented simply by changing the text and images used in the basic game. A great many different games have successfully been made in this way (localizing Monopoly's properties has been popular since the game was first invented), but they are exactly the same game. You should be able to support these simple MODs (simply by not hardcoding values within your code), but do not limit your design to only these kinds of variations.

But Monopoly has an amazing number of variations, some of which completely change the game play in an effort to tie it into popular trends and products, modernize it, shorten it, or even encourage cooperation (people can even propose their own rules). For example:

These games (and many other Monopoly variants) share common traits, but allow for different behavior within them, such as:

It should be clear from this brief description that a design must be fairly general in order to support any of these varieties without changing any code, just selecting different subclasses. If you were just building a program to implement a basic Monopoly game, you might have classes called "Utility", "Dice", or "Chance". Instead, your design should use more general terms to indicate more possibilities, like CombinableProperty, Randomizer, and Action, and allow them to be instantiated with options or subclassed to make a specific kind of game. This is especially important when designing protocols for how parts of the game interact.

Your task is to create a design that can accommodate many variations in the behavior of individual games, while using the basic play expectations within your game or genre to structure your work so the code does not have to be completely abstract. To verify your design's generality, you will need to demonstrate games that differ in as many ways as you can think of. If you are not certain about the abstractions at the start, think as concretely as possible about how to implement two different games, paying special attention to the code that they would have in common and the code that would differ. Then figure out a way to design something that captures that difference as an abstraction that can be used by the common parts so that, by the end of the project, any differences can be configured from a data file rather than special case code.

Design Specifications

Your overall grade will be based on the program's design, the diversity of your games, and the overall complexity of the genre and features you choose to implement (i.e., Checkers or Monopoly are more complex games than Solitaire or Breakout). So every team, no matter the size or ability, should be able to create a complete, well designed, program by picking a less complex game genre if necessary.

Ideally, a well-designed program will make implementing new features easier so, when choosing a new feature to implement, look for something that fits into your design or refactor your code first to accommodate it. Specifically, your design should be thoughtful and intentional: clearly avoiding duplicate code structures and making it easy to add new game variations without changing the existing code.

Adding functionality not related to an abstraction or resulting in poor code that diminishes your overall design efforts will not be rewarded. Specifically, the credit you receive for a functionality feature will be in proportion to how clearly it shows that your core classes are closed to modification while open to extension using abstractions to remove dependencies on concrete classes. Thus, a program with fewer features, but plenty of clear paths to easy expansion, is worth more than a program with many features but lacking clean code and good abstractions.

In addition to following the course Code Design Habits Checklist, your project design should clearly show the your progress learning the topics we have discussed in the course:

APIs

The many variations within your game or genre typically differ in certain ways that you can exploit to create APIs that allow specific features to be "plugged into" your general frameworks, thus providing for the extensibility to support as many different variations as you can. In other words, the core should be a platform that exposes APIs for extending a game in different ways so that concrete pieces can be created and combined to make a specific playable game.

At a high level, these programs are multiple views of the backend and can be easily divided into at least the following APIs:

Ideally, an API should not be changed after it is defined because that affects other's code. If, during the course of the project, an API must be changed, the change and its reasons must be clearly described in a separate file, doc/API_CHANGES.md, that is updated regularly.

Individual Responsibilities when Working as a Team

This project requires steady, consistent, work — only by putting in consistent time each week will you see measurable progress and not have to pull "heroic" all-nighters.

Although this is a team project, everyone has individual responsibilities to the team that can be summed up as follows:

Unfortunately conflicts are likely to occur, so please let the Teaching Team know as soon as possible — even if it has happened just once or twice since it is better to deal with the situation early rather than having a disaster at the end when little can be done to get back on track.

Resources