Interface GameEvent
- All Known Implementing Classes:
GameEvent.CurrentPieceChanged, GameEvent.FrozenBlocksChanged, GameEvent.GameStateChanged, GameEvent.NextPieceChanged, GameEvent.RowsCleared
public sealed interface GameEvent
permits GameEvent.GameStateChanged, GameEvent.NextPieceChanged, GameEvent.CurrentPieceChanged, GameEvent.FrozenBlocksChanged, GameEvent.RowsCleared
Sealed interface representing type-safe events for the Tetris game's
PropertyChangeListener framework. This provides a modern, type-safe alternative
to the string-based property constants defined in
PropertyChangeEnabledGameControls.
Each implementing record represents a specific event that can be observed, carrying the actual event data for compile-time safety. This design enables pattern matching and exhaustiveness checking in switch expressions when handling game events.
Design Pattern: Sealed Classes + Records (Java 21)
- Sealed interface ensures all event types are known at compile time
- Record implementations provide immutability and reduced boilerplate
- Pattern matching enables type-safe event handling without casting
Usage example with PropertyChangeListener:
game.addPropertyChangeListener(evt -> {
if (evt.getNewValue() instanceof GameEvent event) {
switch (event) {
case GameEvent.GameStateChanged e ->
handleStateChange(e.oldState(), e.newState());
case GameEvent.CurrentPieceChanged e ->
updateCurrentPiece(e.piece());
case GameEvent.RowsCleared e ->
handleRowsCleared(e.count());
// compiler ensures all cases are handled
}
}
});
- Version:
- Autumn 2025
- Author:
- Charles Bryan
- See Also:
-
Nested Class Summary
Nested ClassesModifier and TypeInterfaceDescriptionstatic final recordEvent fired when the current movable piece changes state.static final recordEvent fired when the game's frozen blocks change state.static final recordEvent fired when the game state changes.static final recordEvent fired when the next movable piece changes.static final recordEvent fired when one or more lines clear from the frozen blocks. -
Method Summary
Modifier and TypeMethodDescriptiondefault StringReturns the property name for this event type, used when registering property-specific listeners viaPropertyChangeEnabledGameControls.addPropertyChangeListener(String, java.beans.PropertyChangeListener).static longnow()Helper method to get the current time.longReturns the timestamp when this event was created.
-
Method Details
-
timestamp
long timestamp()Returns the timestamp when this event was created.- Returns:
- timestamp in milliseconds since epoch
-
getPropertyName
Returns the property name for this event type, used when registering property-specific listeners viaPropertyChangeEnabledGameControls.addPropertyChangeListener(String, java.beans.PropertyChangeListener).This method provides a self-describing property name for each event type, enabling type-safe listener registration without hardcoded strings.
Default Implementation: Returns the simple class name of the event (e.g., "GameStateChanged", "CurrentPieceChanged"). This ensures consistency between the event type and its property name.
Usage Example:
// Create an event GameEvent event = new GameEvent.GameStateChanged(oldState, newState, GameEvent.now()); // Get its property name programmatically String propertyName = event.getPropertyName(); // Returns "GameStateChanged" // Use it to register a specific listener game.addPropertyChangeListener( new GameEvent.GameStateChanged(null, null, 0).getPropertyName(), evt -> handleStateChange(evt) ); // Or more simply, use the string directly: game.addPropertyChangeListener("GameStateChanged", evt -> ...);Property Names by Event Type:
GameEvent.GameStateChanged→ "GameStateChanged"GameEvent.NextPieceChanged→ "NextPieceChanged"GameEvent.CurrentPieceChanged→ "CurrentPieceChanged"GameEvent.FrozenBlocksChanged→ "FrozenBlocksChanged"GameEvent.RowsCleared→ "RowsCleared"
- Returns:
- the property name string for this event type
- See Also:
-
now
static long now()Helper method to get the current time.- Returns:
- current time in milliseconds since epoch
-