November 9, 2010

pixtur pixtur
Lab Rat
1 posts

Implementing States with QML

 

Hi everybody,

I spent some days struggling with a nice implementation of states for a little game. From other projects, I’m used to implementing a small state-machine that provides the following attributes for each state:

1. actions on entering state
2. sub states with default state
3. action on leaving state
4. transition between states (action/methods that can be invoked)
5. automatic transition to another state if state is complete (e.g. after loading, etc.) –

Although QML transition seem to be nice for small animation demos, they feel immature when it comes to logic and structure. – I want to implement the following state-chart:

http://www.pixtur.de/pub/game-state-chart.png

Some of my questions:

1. Why are are states identified by Strings instead of IDs ?
2. Why can’t Transitions be normal objects of a state (instead of items in the transitions property list?
3. How can I easily define to jump from one state to another after a timeout or a keypress?

My current implementation looks like this:

  1. import Qt 4.7
  2. import "ovilogo"
  3. import "warp5"
  4.  
  5. Item {
  6.     id:        main
  7.     width:      864
  8.     height:     480
  9.  
  10.  
  11.     Component.onCompleted: {
  12.         main.state = "OVI_LOGO";
  13.         console.log("onCompleted");
  14.     }
  15.  
  16.  
  17.     Image {
  18.         anchors.fill:  parent
  19.         source:  "images/game-background.jpg"
  20.     }
  21.  
  22.     Image {
  23.         anchors.fill:  parent
  24.         source:  "images/game-shading-with-playfields.png"
  25.     }
  26.  
  27.  
  28.     Component {
  29.         id: ovilogo
  30.         Ovilogo {  }
  31.     }
  32.     Component {
  33.         id: warp5
  34.         Warp5 { id:qmlRef }
  35.     }
  36.  
  37.     Game {
  38.         id:game
  39.         visible: false
  40.     }
  41.  
  42.     Loader {
  43.         anchors.fill:  parent
  44.         id:mainLoader
  45.     }
  46.  
  47.     states: [
  48.         State {
  49.             name: "OVI_LOGO"
  50.         },
  51.         State {
  52.             name: "WARP5_LOGO"
  53.         },
  54.         State {
  55.             name: "GAME"
  56.         }
  57.     ]
  58.  
  59.  
  60.     transitions: [
  61.         Transition {
  62.             to: "OVI_LOGO"
  63.             SequentialAnimation {
  64.                 ScriptAction {
  65.                     script: { console.log("mainLoader"); mainLoader.sourceComponent = ovilogo;}
  66.                 }
  67.                 PauseAnimation { duration: 2000 }
  68.                 ScriptAction {
  69.                     script: { console.log("settings state to warp5..."); main.state = "WARP5_LOGO"; }
  70.                 }
  71.             }
  72.         },
  73.  
  74.         Transition {
  75.             to: "WARP5_LOGO"
  76.             SequentialAnimation {
  77.                 ScriptAction {
  78.                     script: { console.log("setting source to warp5..."); mainLoader.sourceComponent = warp5;}
  79.                 }
  80.                 PauseAnimation { duration: 5000 }
  81.                 ScriptAction { script: { console.log("settings state to game...");  main.state = "GAME";}  }
  82.             }
  83.         },
  84.  
  85.         Transition {
  86.             to: "GAME"
  87.             ScriptAction {
  88.                 script: { console.log("setting source to warp5..."); mainLoader.visible = false; game.visible = true;}
  89.             }
  90.         }
  91.     ]
  92. }

—————-
ps: Is there a link how formatting works on this forum?

edit : Code highlighted properly / Denis Kormalev

3 replies

November 9, 2010

Denis Kormalev Denis Kormalev
Lab Rat
1654 posts

Just use @ tags

November 10, 2010

mbrasser mbrasser
Lab Rat
452 posts
pixtur wrote:
Although QML transition seem to be nice for small animation demos, they feel immature when it comes to logic and structure.

Yes, QML states certainly don’t provide the level of sophistication found in e.g. the Qt C++ State Machine Framework [doc.qt.nokia.com]

pixtur wrote:
1. Why are are states identified by Strings instead of IDs ?

In part so they can be easily manipulated outside the component in which they are defined.

pixtur wrote:
2. Why can’t Transitions be normal objects of a state (instead of items in the transitions property list?

One transition can apply to multiple state changes, which is why they aren’t associated with a single state.

pixtur wrote:
3. How can I easily define to jump from one state to another after a timeout or a keypress?

A keypress could be accomplished with something like:

  1. // in OVI_LOGO state
  2. PropertyChanges {
  3.     target: main
  4.     Keys.onPressed: main.state = "WARP5_LOGO"
  5. }

November 12, 2010

pixtur pixtur
Lab Rat
1 posts

Hi,

thanks for these answers. Most of them makes sense. However, I am still convinced that transitions and states are not so closely related as it is enforced by QML. To me, states are more about logic, than about properties and assigned transitions. Thus the most important thing would not be transitions but onEnter, onLeave, onUpdate handlers and of course custom methods/actions. From these I could easily invoke any transition, which would more become a collection of Animations. This would nicely decouple the two things, and I could even reusing transitions for different states or objects or even refactor them into a separate file.

I have to try your key-press example. I guess, I’m slowly understanding what you are doing there. :-)

Powerful stuff, once you understood QML’s potential…

 
  ‹‹ XmlRole with Flickr API      Buttons in a Flickable item ››

You must log in to post a reply. Not a member yet? Register here!