Author Topic: Window managers and "printing messages"  (Read 21122 times)

mike3

  • Rogueliker
  • ***
  • Posts: 125
  • Karma: +0/-0
    • View Profile
    • Email
Re: Window managers and "printing messages"
« Reply #15 on: August 08, 2013, 11:26:06 AM »
Hmm. But what about the question I mentioned with whether the window manager+panes should be wrapped or not?

requerent

  • Rogueliker
  • ***
  • Posts: 355
  • Karma: +0/-0
    • View Profile
Re: Window managers and "printing messages"
« Reply #16 on: August 12, 2013, 06:18:28 PM »
Didn't read the whole thread- sorry.



There are, probably, at least 2 forms of feedback. Real-Time and Event-Driven. In a turn-based game, everything is Event-Driven.

Consider,
The "Game" is a Server and the UI is a Client.

The game is turn-based, so the server is oftentimes waiting for input before updating. When the game updates, the Server sends information to the Client, which then decides how that information should be presented to the player. In a similar manner, the UI captures the input and evaluates it at an application level to determine if it is used in the game, if it is, it gets passed to the server.


So-- a generic UIEvent is produced by the Logical Game whenever anything happens, and the Application passes that information down Window Management until something happens.

Let's say you have a 'more' prompt or a confirmation message-- that's ALL UI, it has nothing to do with your game logic.

Similarly, your UIEvents shouldn't target specific windows/panes, but should allow any Client to process that information however it wants. When you take damage, you may want the screen to flash red, the HP bar to go down, and a message in the log saying "You've been hit." The game logic shouldn't know any of that.


A server client relationship, I think, is a good way of looking at the relationship between the UI and the Game. They each have their own logic designed to work with each other, but not dependent of each other.

mike3

  • Rogueliker
  • ***
  • Posts: 125
  • Karma: +0/-0
    • View Profile
    • Email
Re: Window managers and "printing messages"
« Reply #17 on: August 12, 2013, 08:52:09 PM »
Didn't read the whole thread- sorry.



There are, probably, at least 2 forms of feedback. Real-Time and Event-Driven. In a turn-based game, everything is Event-Driven.

Consider,
The "Game" is a Server and the UI is a Client.

The game is turn-based, so the server is oftentimes waiting for input before updating. When the game updates, the Server sends information to the Client, which then decides how that information should be presented to the player. In a similar manner, the UI captures the input and evaluates it at an application level to determine if it is used in the game, if it is, it gets passed to the server.


So-- a generic UIEvent is produced by the Logical Game whenever anything happens, and the Application passes that information down Window Management until something happens.

Let's say you have a 'more' prompt or a confirmation message-- that's ALL UI, it has nothing to do with your game logic.

Similarly, your UIEvents shouldn't target specific windows/panes, but should allow any Client to process that information however it wants. When you take damage, you may want the screen to flash red, the HP bar to go down, and a message in the log saying "You've been hit." The game logic shouldn't know any of that.


A server client relationship, I think, is a good way of looking at the relationship between the UI and the Game. They each have their own logic designed to work with each other, but not dependent of each other.

So would this work? I'm not sure if this is 100% in line with your ideas, but it seems it'd achieve the separation I desire (of UI and logic). One would have a distinct UI object, which can catch UI events. Buried inside the UI object is the window manager and panes. There is an interface available, which is what we can pass around -- that takes up UI events (UIEvent objects). Call it a "UIEventReceiver", for example. It might only provide a single method -- "receiveUIEvent()", for example -- and that's it.

We have the whole program as an "Application" object. Within this is a UI object and GameLogic object. The only thing the GameLogic object knows about the UI object is the interface to pass events (UIEventReceiver). Note that if we want to modify the UI to be a different kind, e.g. a graphical one instead of a console one, or to use a different set of panes, or whatever, we just rewrite the relevant parts of the UI object and the GameLogic and everything associated with it is unaffected, since it only cares about the UIEventReceiver interface and sees and knows of nothing else.

But here's where I'm not sure if this works with what you suggest: You mention that Application passes down to the window manager, etc. In the setup I mention above, the thing that receives the UI events is ultimately the UI object. Should Application receive those events instead and store the window manager/panes itself?

When the game logic wants to do something to the UI, like print a message, it sends an event. You mention "UIEvent" is "generic". What does this mean, that it has no derived types? But different types of events may require different parameters. For example, a "warning event" (which may flash the screen red, for example) may not have any parameters, while a "message event" (to print a message) must carry with it the message to be printed, and a "prompt event" must carry with it the prompt text, range of options available (yes/no, a direction, whatever), and also the callback functions to be invoked upon choosing an option. This suggests UIEvent should have derived types for each of these various kinds of event.

Also, when we send UIEvent to the UI object or Application object (?), what should happen right there? Should it be put on a queue of some kind, and then the logic has to finish before the event can be handled (which happens in the outer "main program loop" that pumps the UI), or should it get "handled right then and there", e.g. a pane with the prompt is opened, or the message is stuck in the message buffer, or whatever "thing" the UI does in that case is done?

Also, what about the non-"game" parts? That is, the main menu and player generation screens. These require different panes than the game -- but how do we handle the invoking of them? How is the UI told it needs to do these special actions, when "panes" are an internal? Is it time to resurrect the "game state" idea, but as part of the UI or the Application -- that is, the UI or Application has a number of states, e.g. "Menu" and "Game", and there is a transition which shuts down or loads the appropriate panes? Or is there another way you might know of -- especially since you mentioned in an earlier post the whole window/pane system functions as a kind of state in itself, so it'd seem redundant to have an additional state mechanism in there? What would your suggestion of a mechanism for this be?

And what about when we do the inventory screen? Though I suppose this isn't as much of a problem, since when the UI gets a command requiring inventory, it could just open the screen right there, before the game logic knows about anything. The situation would seem to be different for commands requiring confirmation prompts, like moving on a dangerous piece of terrain, since that requires some game-logicy stuff, namely the evaluation of terrain difficulty, before a prompt can be issued. I'd imagine the UI would pass such a command straight on to the game logic, and it notifies the UI of the confirmation. Or do you suggest some other way?
« Last Edit: August 12, 2013, 09:16:33 PM by mike3 »

requerent

  • Rogueliker
  • ***
  • Posts: 355
  • Karma: +0/-0
    • View Profile
Re: Window managers and "printing messages"
« Reply #18 on: August 13, 2013, 09:27:18 PM »
Quote
So would this work? I'm not sure if this is 100% in line with your ideas, but it seems it'd achieve the separation I desire (of UI and logic). One would have a distinct UI object, which can catch UI events. Buried inside the UI object is the window manager and panes. There is an interface available, which is what we can pass around -- that takes up UI events (UIEvent objects). Call it a "UIEventReceiver", for example. It might only provide a single method -- "receiveUIEvent()", for example -- and that's it.

Yea, totally.

Quote
We have the whole program as an "Application" object. Within this is a UI object and GameLogic object. The only thing the GameLogic object knows about the UI object is the interface to pass events (UIEventReceiver). Note that if we want to modify the UI to be a different kind, e.g. a graphical one instead of a console one, or to use a different set of panes, or whatever, we just rewrite the relevant parts of the UI object and the GameLogic and everything associated with it is unaffected, since it only cares about the UIEventReceiver interface and sees and knows of nothing else.

Yes.

Quote
But here's where I'm not sure if this works with what you suggest: You mention that Application passes down to the window manager, etc. In the setup I mention above, the thing that receives the UI events is ultimately the UI object. Should Application receive those events instead and store the window manager/panes itself?

When I say the Application propagates the event, I mean that logic of the game sends the event to the application, which then broadcasts it to relevant objects. The Game object doesn't have access to the references necessary to directly broadcast to UI elements, but it can provide the application with that information. In this sense, I'd consider the Application the governing intermediary... kind of like a kernel (maybe? >_<).

So, making the application headless, in the case of a server, shouldn't have any UI objects initialized. The Game doesn't know or care about that though, and still sends UI events to the application, which could then send those across a network to a remote client or something like that. I don't recommend going nuts with features that you'll never need, but I think the server-client relationship is a good way to contextualize the distinction between Model and View (relative to MVC- Model View Controller).

Quote
When the game logic wants to do something to the UI, like print a message, it sends an event. You mention "UIEvent" is "generic". What does this mean, that it has no derived types? But different types of events may require different parameters. For example, a "warning event" (which may flash the screen red, for example) may not have any parameters, while a "message event" (to print a message) must carry with it the message to be printed, and a "prompt event" must carry with it the prompt text, range of options available (yes/no, a direction, whatever), and also the callback functions to be invoked upon choosing an option. This suggests UIEvent should have derived types for each of these various kinds of event.

I think it makes it easier to develop if the Game isn't working with a wide variety of Event objects. You can make Events be the product of composition instead of inheritance by passing an array of objects that would represent the construction parameters. Usually the first element would need to be an enum or flag to indicate the type of the event.

Why subvert strong typing? It's personal mostly. "I" don't like having a large library of Events that I would be adding new objects to on a regular basis. If you can easily rationalize a finite set of events that your game would use, then it'd be better to use strong types instead.

Prompts are pure UI. They're simply a menuing schema to help the player communicate to the game what s/he wants to do. Or rather, prompts/menus help the user fill out the parameters necessary to produce a game action that makes sense. In this vein, I don't use callbacks. The Game propagates an event saying what type of situation the player is in and what range of actions are available. The UI is responsible for formatting that information in a way that helps the user select an action and send it to the game. I just don't see where there is a need for a callback (in this case). Even if the action being taken doesn't have to do with the scheduling of the game, it's still a 'wait for player action' scenario, so, again, as long as the UI knows which actions to present to the player, you don't need anything fancy. I don't see any harm in using a callback though.

Similarly, the -more- prompt has nothing to do with the game. The UI simply received too many events to display in the log, so it tells the application that it is going to consume the next input to finish displaying the remaining log messages.

Quote
Also, when we send UIEvent to the UI object or Application object (?), what should happen right there? Should it be put on a queue of some kind, and then the logic has to finish before the event can be handled (which happens in the outer "main program loop" that pumps the UI), or should it get "handled right then and there", e.g. a pane with the prompt is opened, or the message is stuck in the message buffer, or whatever "thing" the UI does in that case is done?

I think that kind of depends. Suppose you send an event for creature that moves in the player's LOS. In this way, the UI can update each move in sequence so that the actions are graphically offset. Alternatively, the event could just throw all the information at once and the UI is just responsible for updating each move in some sequence (which could be canceled by input to skip the animation, or something). The latter case is more elegant and gives your UI more control over how it presents its information. In this sense, you may only 'need' one message sent to the UI that contains all the information about how the game state changed and what actions the game will accept-- the UI can then animate that information or not, doesn't matter to the game.

In cases where there is an interruption and the game is waiting for a decision to be made, it's not really any different. It's not going anywhere while it waits for the UI to tell it what the player has chosen to do. In fact, we could have an aggregating message that builds up in the game logic until the player has an opportunity to make a decision, and then just dump it all on the UI at once.

It really just gets down to, I think, performance and preference- and each case is going to be relative.

Quote
Also, what about the non-"game" parts? That is, the main menu and player generation screens. These require different panes than the game -- but how do we handle the invoking of them? How is the UI told it needs to do these special actions, when "panes" are an internal? Is it time to resurrect the "game state" idea, but as part of the UI or the Application -- that is, the UI or Application has a number of states, e.g. "Menu" and "Game", and there is a transition which shuts down or loads the appropriate panes? Or is there another way you might know of -- especially since you mentioned in an earlier post the whole window/pane system functions as a kind of state in itself, so it'd seem redundant to have an additional state mechanism in there? What would your suggestion of a mechanism for this be?

That's what the WM is for. You make a selection to start a new character. That menu sends a message to the WM to queue up all the necessary input prompts to build the necessary parameters to pass into a new game (possibly closing itself out  in the process). The WM should manage which inputs go where.

Quote
And what about when we do the inventory screen? Though I suppose this isn't as much of a problem, since when the UI gets a command requiring inventory, it could just open the screen right there, before the game logic knows about anything. The situation would seem to be different for commands requiring confirmation prompts, like moving on a dangerous piece of terrain, since that requires some game-logicy stuff, namely the evaluation of terrain difficulty, before a prompt can be issued. I'd imagine the UI would pass such a command straight on to the game logic, and it notifies the UI of the confirmation. Or do you suggest some other way?

When the player moves onto dangerous terrain, the game tells the UI that the player has an additional action to take. That additional action, in this case, is a binary yes/no. The UI presents these options in a way that makes sense to the player, and then sends that selection back to the game. The game, on the other hand, simply popped a UIEvent and waits for the player to take an action.

Inventory screen is typically pure UI, though you could make it so that looking at inventory is an action sent to the game which then responds with a UIEvent that provides all the information necessary to present the inventory. In this case, that action doesn't consume a turn, so the game is still waiting for an action that results in a game update.

mike3

  • Rogueliker
  • ***
  • Posts: 125
  • Karma: +0/-0
    • View Profile
    • Email
Re: Window managers and "printing messages"
« Reply #19 on: August 13, 2013, 11:01:57 PM »
Comments but also some more questions:

Quote
I think it makes it easier to develop if the Game isn't working with a wide variety of Event objects. You can make Events be the product of composition instead of inheritance by passing an array of objects that would represent the construction parameters. Usually the first element would need to be an enum or flag to indicate the type of the event.

However, in the languages I'm using (C++), an array must all be of a single type, yet depending on the kind of event we may need parameters of multiple types. E.g. a message event may take in both a message -- a string -- and also a color -- a number -- to display it as. So a single array would not work. A "ChangeLevel" event (signals that we are transitioning to a different level map) would have to pass a reference/pointer/handle/etc. to the new level map -- yet another type (though a handle might still just be a number). So we have strings, numbers, pointers to level maps. That's 3 different types right there. An "explosion" event might need a reference or handle for the asset of the explosion, PLUS a coordinate indicating where it happens. So there is 2 types in the same event: reference/handle to asset and a coordinate (which in my program is a single type and not just two numbers separate from each other).

What do you suggest should be done in this case?

Quote
Prompts are pure UI. They're simply a menuing schema to help the player communicate to the game what s/he wants to do. Or rather, prompts/menus help the user fill out the parameters necessary to produce a game action that makes sense. In this vein, I don't use callbacks. The Game propagates an event saying what type of situation the player is in and what range of actions are available. The UI is responsible for formatting that information in a way that helps the user select an action and send it to the game. I just don't see where there is a need for a callback (in this case). Even if the action being taken doesn't have to do with the scheduling of the game, it's still a 'wait for player action' scenario, so, again, as long as the UI knows which actions to present to the player, you don't need anything fancy. I don't see any harm in using a callback though.

Why callbacks? Well, the answer was discussed earlier in this thread. We have a main loop (this is not the game logic loop, but the main program loop), which fetches the input and passes it to the window manager:

Code: [Select]
Loop until (stopping condition):
          input = inputSource.grabInputEvent();
          UI.handleInputEvent(input);
          UI.render();

or something like that. So there's a simple sequence input -> logic -> render involved. The input goes into the window manager and then to the pane that's focused. Note that the above loop is sort of akin to a Windows message loop in a Windows program.

The reason for the callbacks is to keep things so that all input-getting and render is handled by that loop. Suppose we press a key to do something in the game, and the logic says it needs a confirmation prompt. The event goes out to the UI object (or the Application, but gets there somehow), and the UI processes it (this all happens when the logic called the receiveUIEvent() thingy). So the UI does something, like put out a pane showing the confirmation prompt. But now in order for input to hit that confirmation prompt, control has to return to the outer, main loop just mentioned. So our logic function must stop there and let control bubble back up to the main loop where the input is gotten and passed on to the UI to handle the prompt. Which means once the prompt is satisfied, the logic must resume, and the callback handles this by calling the logic function that handles everything post-prompt.

The other way I mentioned, which would avoid a callback, would require the UI to spawn a new "pump" (like the main loop just mentioned) when it receives an event, to handle this, creating a blocking call when such a UI event is sent. But it seems this would break the centralization of the getting of input, the logic, and the render and we'd end up ultimately starting a UI pump inside a UI pump.

Or do you know of a third option? If so, what is it? Also, if you use a non-callback option, how do you get the return values from the prompts (whether yes or no was pressed, for example)?

Quote
I think that kind of depends. Suppose you send an event for creature that moves in the player's LOS. In this way, the UI can update each move in sequence so that the actions are graphically offset. Alternatively, the event could just throw all the information at once and the UI is just responsible for updating each move in some sequence (which could be canceled by input to skip the animation, or something). The latter case is more elegant and gives your UI more control over how it presents its information. In this sense, you may only 'need' one message sent to the UI that contains all the information about how the game state changed and what actions the game will accept-- the UI can then animate that information or not, doesn't matter to the game.

But it still seems that even in the second approach we need some kind of ordering/sequencing system either way, to, e.g. order monster moves and other things (if one monster moves first, then there is an explosion, then a second monster moves). We have to know which monster moved before which other one, so some kind of sequence specification seems unavoidable. If we just sent something saying "on this turn there was an explosion, monster A moved and monster B moved", the order is lost. This sequencing information could not be reconstructed by the UI, since it could be just the case that B moved before A as much as A moving before B, unless it is explicitly provided. We don't even know whether the explosion came between the moves of A and B or not. Unless you're suggesting to dispense with chronological accuracy, in which case sending a single giant command might work.

So how do you propose to address this?

Quote
That's what the WM is for. You make a selection to start a new character. That menu sends a message to the WM to queue up all the necessary input prompts to build the necessary parameters to pass into a new game (possibly closing itself out  in the process). The WM should manage which inputs go where.

In what I have now, the menu is a pane, and panes are registered with window managers. They know their window manager, so all it does is fire up a new pane for the selected menu option and then close itself. The PC-generation wizard then is just the sequence of panes, with an object passing from one to the next that accumulates the parameters that have been input, and then at the end a new PC is generated and goes into the game.

It would seem also that the UI object would need to sense when the panes for the game are open so it can properly handle game UI events, though. Of course, since it knows about the WM and panes, then this shouldn't be a problem.

Quote
Inventory screen is typically pure UI, though you could make it so that looking at inventory is an action sent to the game which then responds with a UIEvent that provides all the information necessary to present the inventory. In this case, that action doesn't consume a turn, so the game is still waiting for an action that results in a game update.

And this is where the callback would also come in handy. The inventory screen could get an item, or it could be dismissed. If the pane is dismissed, then it doesn't call the callback that runs the turn logic.
« Last Edit: August 15, 2013, 02:11:13 AM by mike3 »

mike3

  • Rogueliker
  • ***
  • Posts: 125
  • Karma: +0/-0
    • View Profile
    • Email
Re: Window managers and "printing messages"
« Reply #20 on: August 14, 2013, 11:52:17 PM »
I updated the post to include some more questions.
« Last Edit: August 15, 2013, 09:10:24 AM by mike3 »