Quick Links: Download Gideros Studio | Gideros Documentation | Gideros Development Center | Gideros community chat | DONATE
Waiting for user input — Gideros Forum

Waiting for user input

qxmat2qxmat2 Member
edited November 2017 in General questions
Hi there!

I am programming a little card game for learning purposes. I stepped into a little problem, where I don't know the best practice howto solve it.

If the player (me) throws a certain card, an additional dialog pops up and asks the player which face (spades, diamonds...) he wants from the opponent as the next card, so the opponent is forced to serve this face.

The pseudo code looks like this
function playerMove(playercards, opencardOnStack){
  foreach(playercards as card){
    if(card==opencardOnStack){ success=1; playerWantToThrowthisCard=card }
  }
 
  if(success==1){
    if(playerWantToThrowthisCard == "Jack"){ -- the Jack is the special card which enables the player to wish a face from the opponent
 
     doWait = true
 
      dialog = Dialog
      dialog:addEventListener("click", function(){ print("clicked"); doWait=false}
      dialog:showDialog(wishedFaceFromOpponent = function(){ print("which face do you want from the opponent"); return function readFace() }
 
      while doWait==true
      end
 
      print("the player wants the opponent to throw a" .. wishedFaceFromOpponent)
 
    }
 
  }
  nextPlayersTurn()
}
So I have implemented a kind of "active waiting" which is bad programming practise and additionally it doesn't work, because it hangs my simulator.

Of course I could pack the further statements, which should be executed after "clicked" into that event listener, but that doesn't work with my code well, because it consists of many nested subroutines, beside that it would branch my code even more. For this to work, I'd had to completely redesign my code only for this single purpose, that cannot be the only solution.

I googled but cannot seem to find the right way to do this. The function I'm seeking for is something like waitForEventCompleted(), which halts the further execution as long as the user clicked something in the dialog. This functions should substitute the "while doWait==true end" active wait statement. I guess this "waiting" thing is something different in event-driven environments.

Comments

  • You need to make a state machine or use fake threads.
    Coder, video game industry veteran (since the '80s, ❤'s assembler), arrested - never convicted hacker (in the '90s), dad of five, he/him (if that even matters!).
    https://deluxepixel.com
  • Oh well, so there isn't already an easy to use implementation for such a simple task? I mean to block the execution of the code until a signal is fired. I've read somewhere that gideros is single threaded, is that the reason why this isn't possible? Would you say, if I need such an function, my program design is bad?
  • hgy29hgy29 Maintainer
    Yes, gideros being single threaded at heart (not speaking about fakethreads), you can't wait in an event handler, otherwise you'll block the whole app. You should either handle the user response and everything that comes after in the 'click' event listener, or use fakethreads which can yield (sleep).
  • antixantix Member
    Accepted Answer
    @qxmat2, I would probably go with a simple state machine too. I'm not sure how your whole program is structured but in theory all of your UI elements have event listeners attached so they can do things like update your state machine when required. A simple state machine would be implemented in the EnterFrame event..
    state = "normal"
     
    local function onEnterFrame(e)
      local dt = e.deltaTime
     
      local state = state
     
      if state == "playerTurn" then
        -- code run when it is the players turn
     
      elseif state == "opponentTurn" then
        -- code run when it is the players turn
     
      elseif state == "add more states here" then
      elseif state == "add more states here" then
      elseif state == "add more states here" then
     
      else
        -- nothing happens for unrecognized modes
      end
     
      -- code run no matter what the state is
    end
     
    stage:addEventListener(Event.ENTER_FRAME, onEnterFrame)
    I hope that makes sense :)

    Likes: qxmat2

    +1 -1 (+1 / -0 )Share on Facebook
  • Your example makes it very clear what a statemachine in this context means, so it looks like my whole app is the statemachine, at least from the moment it branches in either the players code or the opponents code. Your example points me, that it is (obviously) better to set the state who can play as early as possible. Due to not being familar with event-driven paradigm I missed that point, now I switch and call player/opponent code all over my classes, which makes the whole code unreadable and hardly tracable. Thanks for your example, I think I can do it better the next time.
    +1 -1 (+2 / -0 )Share on Facebook
  • @qxmat2 Sorry I just said 'state machine' - I was short on time and I though a clue is better than nothing. :)

    Likes: antix

    Coder, video game industry veteran (since the '80s, ❤'s assembler), arrested - never convicted hacker (in the '90s), dad of five, he/him (if that even matters!).
    https://deluxepixel.com
    +1 -1 (+1 / -0 )Share on Facebook
  • SinisterSoftSinisterSoft Maintainer
    edited November 2017
    @oleg Gideros also has a different type of co-routine ("fake threads") that doesn't need a yield - it auto yields. The Lua code runs in unused time between frame events. See:
    http://docs.giderosmobile.com/reference/gideros/Core/asyncCall#Core.asyncCall
    You can have multiple fake threads running, when it reaches the end of the code it's automatically removed. It's akin to time slices, not parallel.

    Likes: oleg

    Coder, video game industry veteran (since the '80s, ❤'s assembler), arrested - never convicted hacker (in the '90s), dad of five, he/him (if that even matters!).
    https://deluxepixel.com
    +1 -1 (+1 / -0 )Share on Facebook
  • For a beginner I would still go with a simple Finite State Machine :)

    Likes: SinisterSoft

    +1 -1 (+1 / -0 )Share on Facebook
  • john26john26 Maintainer
    edited November 2017
    Yes, for card games or strategy games, anything which is turn based or sequential you need to use coroutines (Core.asyncCall). Using ENTER_FRAME or GTween will soon give you an unmaintainable mess. Here's an example of sequential (and concurrent) animation using coroutines each of which acts as a thread.

    http://giderosmobile.com/forum/discussion/comment/48666#Comment_48666

    Likes: oleg

    +1 -1 (+1 / -0 )Share on Facebook
Sign In or Register to comment.