-
-
Notifications
You must be signed in to change notification settings - Fork 709
feat: allow selecting difficulty in the gameplay menu #1471
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -16,6 +16,7 @@ import com.almasb.fxgl.dsl.* | |
| import com.almasb.fxgl.dsl.FXGL.Companion.animationBuilder | ||
| import com.almasb.fxgl.dsl.FXGL.Companion.random | ||
| import com.almasb.fxgl.dsl.FXGL.Companion.texture | ||
| import com.almasb.fxgl.gameplay.GameDifficulty | ||
| import com.almasb.fxgl.input.Input | ||
| import com.almasb.fxgl.input.InputModifier | ||
| import com.almasb.fxgl.input.Trigger | ||
|
|
@@ -258,6 +259,12 @@ open class FXGLDefaultMenu(type: MenuType) : FXGLMenu(type) { | |
| itemOptions.setChild(createOptionsMenu()) | ||
| box.add(itemOptions) | ||
|
|
||
| if (enabledItems.contains(MenuItem.DIFFICULTY)) { | ||
| val itemDifficulty = MenuButton("menu.difficulty") | ||
| itemDifficulty.setMenuContent({ createDifficultyMenu() }) | ||
| box.add(itemDifficulty) | ||
| } | ||
|
|
||
| if (enabledItems.contains(MenuItem.EXTRA)) { | ||
| val itemExtra = MenuButton("menu.extra") | ||
| itemExtra.setChild(createExtraMenu()) | ||
|
|
@@ -297,6 +304,12 @@ open class FXGLDefaultMenu(type: MenuType) : FXGLMenu(type) { | |
| itemOptions.setChild(createOptionsMenu()) | ||
| box.add(itemOptions) | ||
|
|
||
| if (enabledItems.contains(MenuItem.DIFFICULTY)) { | ||
| val itemDifficulty = MenuButton("menu.difficulty") | ||
| itemDifficulty.setMenuContent({ createDifficultyMenu() }) | ||
| box.add(itemDifficulty) | ||
| } | ||
|
|
||
| if (enabledItems.contains(MenuItem.EXTRA)) { | ||
| val itemExtra = MenuButton("menu.extra") | ||
| itemExtra.setChild(createExtraMenu()) | ||
|
|
@@ -343,6 +356,30 @@ open class FXGLDefaultMenu(type: MenuType) : FXGLMenu(type) { | |
| return MenuBox(itemGameplay, itemControls, itemVideo, itemAudio, btnRestore) | ||
| } | ||
|
|
||
| private fun createDifficultyMenu(): MenuContent { | ||
| val difficultyBox = getUIFactoryService().newChoiceBox( | ||
| FXCollections.observableArrayList(GameDifficulty.entries) | ||
| ) | ||
|
|
||
| difficultyBox.styleClass.add("fxgl-difficulty-choice-box") | ||
|
|
||
| difficultyBox.value = getSettings().gameDifficulty | ||
| getSettings().gameDifficultyProperty().bindBidirectional(difficultyBox.valueProperty()) | ||
|
|
||
| difficultyBox.valueProperty().addListener { _, _, _ -> | ||
| switchMenuContentTo(EMPTY) | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you remind me what this does / why this is needed?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, in hindsight I should've left this in a comment. The rest of the code adds a listener that reacts whenever the difficulty selection changes, hiding the dropdown menu and returning the user to the previous menu. Which was the alternative to adding a seperate back button somewhere else in the menu, increasing visual clutter. I tested adding a back button but it made more sense to me to keep it so when the difficulty is changed (or in the event of not changing, clicking the already-selected difficulty) returns the user back to the previous menu.
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Or we could just leave the user in the same view, i.e. the difficulty menu remains where it is and the user can select the difficult value multiple times. Will this cause an issue do you think?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's fine, it won't cause an issue - it was that way initially during testing. How would you suggest leaving the difficulty menu after the changes have been made? Perhaps when another menu item (options, extras..) is selected, it hides the difficulty choicebox? As opposed to having a back button or something of that sort.
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's keep it as is for now. We can always action this separately if users raise an issue. |
||
| } | ||
|
|
||
| val row = HBox( | ||
| 25.0, | ||
| getUIFactoryService().newText(localizedStringProperty("menu.difficulty").concat(":")), | ||
| difficultyBox | ||
| ) | ||
| row.alignment = Pos.CENTER | ||
|
|
||
| return MenuContent(row) | ||
| } | ||
|
|
||
| private fun createExtraMenu(): MenuBox { | ||
| log.debug("createExtraMenu()") | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be the other way around? I'm thinking of a case where the user sets the difficulty in the main menu, then opens the game menu. At this point does the above mean the settings difficulty will rebound to the UI box's value property?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe it is in the correct order. For example, if the user sets the difficulty in the main menu, that will update
getSettings().gameDifficulty. Then later, the game menu creates its owndifficultyBoxand executesdifficultyBox.value = getSettings().gameDifficulty->bindBidirectional(difficultyBox.valueProperty(), the box will show the same difficulty that was set in the main menu, any changes in either place after that will update the other.I havent' tested the reverse order, but if the value was bound first and then assigned to one side, the assigned value should still propagate to the other menu because of the bidirectional binding.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, 2 questions:
is
createDifficultyMenu()rebuilt on each menu creation or is it built only once and cached? For example, main menu -> game menu -> main menu (at this last step do we still have the samedifficultyBoxthat was created the first time main menu was constructed?)can one property be bidirectionally bound to multiple objects?
If the answer to question 1 is "no, the menu items are cached rather than rebuilt" and if the answer to question 2 is also "no", then I can see a potential issue:
Are you able to test this scenario and see if it works as expected?
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To answer question 1: The
createDifficultyMenu()is rebuilt on each menu creation. The bound difficulty value persists as that setting lives outside of the UI controls (settings.kt).As for question 2: As far as I'm aware the answer is no, but I have just tested it and these were the results:
Perhaps this is due to the two seperate bidirectional bindings from both the main menu and game menu to the same difficulty property in the settings, allowing the difficulty to persist between each menu type.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good, thanks for testing.
I've looked up documentation of Property. Turns out we can have multiple bidirectional bindings. There is a note about weak listeners and garbage collection, but I don't expect any issues if the menu is rebuilt every time.