The Worlds first 100% XML Mark-up Driven Puzzle Game made with XOML

Well we finally cracked it, we’ve been aiming to create a game in 100% XOML mark-up and it finally happened. We created a small logic puzzle game called 10.

The game itself has simple rules. The screen is filled with cards, each card having a value of 0 to 9. The user selects 3 cards, who’s total value must total 10. When the user selects 3 cards that total 10 they are removed from play. To complete the round the user must eliminate all cards on the play field. The idea is simple but the game can be become incredibly difficult.

The game is 100% XOML based using only actions and variables to create the logic and no additional C/C++. We will be providing the project as an example project when we release IwGame 0.36.

Note that the game will not work with version 0.35 of IwGame.

We are getting closer to bringing cross platform mobile game and app development to the hands of none programmers 🙂

Oh and For the sake of clarity, we are not stating a worldwide claim over all mark-up languages as that would be ludicrous, only the XOML mark-up language.

A Windows build of the Game of 10 is available for download at

[sourcecode language=”xml”]
<?xml version="1.0"?>

<Style Name="GenericSceneStyle">
<Set Property="CanvasSize" Value="-100, -100" />
<Set Property="CanvasFit" Value="none" />
<Set Property="CanvasOrigin" Value="centre" />
<Set Property="Colour" Value="255, 255, 255, 255" />
<Set Property="AllowSuspend" Value="false" />
<Set Property="Physics" Value="false" />

<!– Load a UI style to style the user interface –>
<LoadXOML File="UIStyle.xml" />

<!– Create a scene to hold or game –>
<Scene Name="GameScene" Style="GenericSceneStyle" Camera="Cam" Extents="-1000, -400, 2000, 800" Current="true" Batch="false" ClipStatic="true">

<!– Create a camera –>
<Camera Name="Cam" Position="0, 0" Angle="0" Scale="1.0" />

<!– Score / round variables –>
<Variable Name="Score" Type="int" Value="0" />
<Variable Name="RoundScore" Type="int" Value="0" />
<Variable Name="CurrentRound" Type="int" Value="0" />
<!– TargetValue determines the valuue that all 3 user selections should add up to gain a correct answer –>
<Variable Name="TargetValue" Type="int" Value="10" />
<!– TotalCardsValue is the current value of all selected cards –>
<Variable Name="TotalCardsValue" Type="int" Value="0" />
<!– CardValues is an array that holds the value of each card –>
<Variable Name="CardValues" Type="arrayint" Size="15" Value="0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0" />
<!– CardsCount is the total number of cards in play –>
<Variable Name="CardsCount" Type="int" Value="15" />
<!– CardsFoundCount is the total number of cards that the user has successfully found –>
<Variable Name="CardsFoundCount" Type="int" Value="0" />
<!– SelectedCardNames is an array that holds the names of the currently selected cards –>
<Variable Name="SelectedCardNames" Type="arraystring" Size="3" Value="none, none, none" />
<!– CardIndex is the current selection index –>
<Variable Name="CardIndex" Type="int" Value="0" />

<!– CardIndexIs are conditions used to determine the currently selected index –>
<Variable Name="CardIndexIs0" Type="condition" Value="CardIndex == 0"/>
<Variable Name="CardIndexIs1" Type="condition" Value="CardIndex == 1"/>
<Variable Name="CardIndexIs2" Type="condition" Value="CardIndex == 2"/>
<Variable Name="CardIndexIs3" Type="condition" Value="CardIndex == 3"/>
<!– CardsMatch is a condition used to determine if the total of all currently selected cards add up to the the target value of 10 –>
<Variable Name="CardsMatch" Type="condition" Value="TotalCardsValue == TargetValue"/>
<!– NoCardsLeft is a condition used to determine if there are any cards left in play –>
<Variable Name="NoCardsLeft" Type="condition" Value="CardsCount == CardsFoundCount"/>

<!– IsRound is a condition used to determine the current round –>
<Variable Name="IsRound0" Type="condition" Value="CurrentRound == 0"/>
<Variable Name="IsRound1" Type="condition" Value="CurrentRound == 1"/>
<Variable Name="IsRound2" Type="condition" Value="CurrentRound == 2"/>

<!– Load the first set of cards –>
<File Name="RoundFile" Location="Round1.txt" FileType="text" Preload="true" Blocking="true" Variable="CardValues" />

<!– Action that resets the round –>
<Actions Name="RestartRound">
<Action Method="SetVar" Param1="RoundScore" Param2="0" />
<Action Method="SetVar" Param1="TotalCardsValue" Param2="0" />
<Action Method="SetVar" Param1="CardsFoundCount" Param2="0" />
<Action Method="CallActions" Param1="ResetSelection" />
<Action Method="ShowActor" Param1="Card0" />
<Action Method="ShowActor" Param1="Card1" />
<Action Method="ShowActor" Param1="Card2" />
<Action Method="ShowActor" Param1="Card3" />
<Action Method="ShowActor" Param1="Card4" />
<Action Method="ShowActor" Param1="Card5" />
<Action Method="ShowActor" Param1="Card6" />
<Action Method="ShowActor" Param1="Card7" />
<Action Method="ShowActor" Param1="Card8" />
<Action Method="ShowActor" Param1="Card9" />
<Action Method="ShowActor" Param1="Card10" />
<Action Method="ShowActor" Param1="Card11" />
<Action Method="ShowActor" Param1="Card12" />
<Action Method="ShowActor" Param1="Card13" />
<Action Method="ShowActor" Param1="Card14" />
<Action Method="SetProperty" Param1="Timeline" Param2="StillAnim" Param3="Card0" />
<Action Method="SetProperty" Param1="Timeline" Param2="StillAnim" Param3="Card1" />
<Action Method="SetProperty" Param1="Timeline" Param2="StillAnim" Param3="Card2" />
<Action Method="SetProperty" Param1="Timeline" Param2="StillAnim" Param3="Card3" />
<Action Method="SetProperty" Param1="Timeline" Param2="StillAnim" Param3="Card4" />
<Action Method="SetProperty" Param1="Timeline" Param2="StillAnim" Param3="Card5" />
<Action Method="SetProperty" Param1="Timeline" Param2="StillAnim" Param3="Card6" />
<Action Method="SetProperty" Param1="Timeline" Param2="StillAnim" Param3="Card7" />
<Action Method="SetProperty" Param1="Timeline" Param2="StillAnim" Param3="Card8" />
<Action Method="SetProperty" Param1="Timeline" Param2="StillAnim" Param3="Card9" />
<Action Method="SetProperty" Param1="Timeline" Param2="StillAnim" Param3="Card10" />
<Action Method="SetProperty" Param1="Timeline" Param2="StillAnim" Param3="Card11" />
<Action Method="SetProperty" Param1="Timeline" Param2="StillAnim" Param3="Card12" />
<Action Method="SetProperty" Param1="Timeline" Param2="StillAnim" Param3="Card13" />
<Action Method="SetProperty" Param1="Timeline" Param2="StillAnim" Param3="Card14" />

<!– Action that moves to the next round –>
<Actions Name="NextRound">
<Action Method="CallActions" Param1="RestartRound" />
<Action Method="AddVar" Param1="CurrentRound" Param2="1" />
<Action Method="LoadFile" Param1="RoundFile" Param2="true" Param3="Round1.txt" Condition="IsRound0" />
<Action Method="LoadFile" Param1="RoundFile" Param2="true" Param3="Round2.txt" Condition="IsRound1" />
<Action Method="LoadFile" Param1="RoundFile" Param2="true" Param3="Round3.txt" Condition="IsRound2" />

<!– Action that is called when a correct answer is given –>
<Actions Name="CorrectAnswer">
<Action Method="AddVar" Param1="RoundScore" Param2="1" />
<Action Method="HideActor" Param1="SelectedCardNames:0" />
<Action Method="HideActor" Param1="SelectedCardNames:1" />
<Action Method="HideActor" Param1="SelectedCardNames:2" />
<Action Method="AddVar" Param1="CardsFoundCount" Param2="3" />
<Action Method="SetProperty" Param1="Text" Param2="Correct, well done" Param3="AnswerNotification" />
<Action Method="SetTimeline" Param1="AnswerNotificationAnim" Param2="AnswerNotification" />

<!– Action that is called when an incorrect answer is given –>
<Actions Name="WrongAnswer">
<Action Method="SetProperty" Param1="Text" Param2="Incorrect, try again" Param3="AnswerNotification" />
<Action Method="SetTimeline" Param1="AnswerNotificationAnim" Param2="AnswerNotification" />

<!– Action that is called when the user has finished selecting 3 cards –>
<Actions Name="ResetSelection">
<Action Method="SetVar" Param1="CardIndex" Param2="0" />
<Action Method="SetVar" Param1="TotalCardsValue" Param2="0" />

<!– Action that is used to check the answer –>
<Actions Name="CheckAnswer">
<Action Method="CallActions" Param1="CorrectAnswer" Condition="CardsMatch" />
<Action Method="CallActions" Param1="WrongAnswer" Condition="!CardsMatch" />
<Action Method="CallActions" Param1="ResetSelection" />
<Action Method="CallActions" Param1="RoundComplete" Condition="NoCardsLeft" />
<Action Method="SetProperty" Param1="Timeline" Param2="StillAnim" Param3="SelectedCardNames:0" />
<Action Method="SetProperty" Param1="Timeline" Param2="StillAnim" Param3="SelectedCardNames:1" />
<Action Method="SetProperty" Param1="Timeline" Param2="StillAnim" Param3="SelectedCardNames:2" />

<!– Action that is called when the round is complete –>
<Actions Name="RoundComplete">
<Action Method="AddVar" Param1="Score" Param2="RoundScore" />
<Action Method="CallActions" Param1="NextRound" />

<!– Create a grid cell actor template to represent our card –>
<Template Name="CardTemplate">
<Label Name="Card$index$" Size="-18, -28" Background="Button1Brush" BackgroundColour="255, 255, 200, 255" SelectedColour="200, 255, 200, 255" Font="font1" GridPos="$gridpos$" HitTest="true" SelectType="normal" Selected="false" OnTapped="CardSelected">
<Timeline Name="FlashAnim" AutoPlay="true">
<Animation Anim="Flashing" Repeat="0" Target="Scale"/>
<Actions Name="CardSelected">
<Action Method="SetVar" Param1="SelectedCardNames:0" Param2="Card$index$" Condition="CardIndexIs0" />
<Action Method="SetVar" Param1="SelectedCardNames:1" Param2="Card$index$" Condition="CardIndexIs1" />
<Action Method="SetVar" Param1="SelectedCardNames:2" Param2="Card$index$" Condition="CardIndexIs2" />
<Action Method="AddVar" Param1="TotalCardsValue" Param2="CardValues:$index$" />
<Action Method="AddVar" Param1="CardIndex" Param2="1" />
<Action Method="SetTimeline" Param1="FlashANim" />
<Action Method="CallActions" Param1="CheckAnswer" Condition="CardIndexIs3" />

<!– Create a grid that contains our cards –>
<Variable Name="SelectedCard" Type="int" Value="-1" />
<Grid Name="ItemsGrid" Size="-100, -90" Docking="bottom" Background="PanelBrush" BackgroundColour="150, 200, 255, 255" SelectedColour="150, 200, 255, 255" HitTest="false" ClipMargin="10, 10, 10, 10" MultiSelect="true" UseParentOpacity="false" ItemsData="CardValues" ItemsTemplate="CardTemplate" ItemsTargetType="text" Selection="SelectedCard">
<RowDefinition Name="r0" AlignV="middle" Height="-33" />
<RowDefinition Name="r1" AlignV="middle" Height="-33" />
<RowDefinition Name="r2" AlignV="middle" Height="-33" />
<ColumnDefinition Name="c0" AlignH="left" Width="-20" />
<ColumnDefinition Name="c1" AlignH="left" Width="-20" />
<ColumnDefinition Name="c2" AlignH="left" Width="-20" />
<ColumnDefinition Name="c3" AlignH="left" Width="-20" />
<ColumnDefinition Name="c5" AlignH="left" Width="-20" />

<!– Create the menu at the top of the screen –>
<StackPanel Size="-100, -10" HitTest="false" Docking="top" Orientation="horizontal">
<Label Name="Restart" Background="Button1Brush" SelectedColour="80, 80, 80, 255" Size="-15, -100" Font="smallfont1" Text="Restart" Margin="0, -5, 0, 0" OnTapped="RestartRound" />
<Label Background="PanelBrush" Size="-10, -100" Font="smallfont1" Text="Round" />
<Label Name="RoundScore" Background="PanelBrush" Size="-10, -100" Font="smallfont1" Binding="[Text]CurrentRound" />
<Label Background="PanelBrush" Size="-10, -100" Font="smallfont1" Text="Score" />
<Label Name="Score" Background="PanelBrush" Size="-10, -100" Font="smallfont1" Binding="[Text]Score" />
<Label Background="PanelBrush" Size="-10, -100" Font="smallfont1" Text="Round Score" />
<Label Name="RoundScore" Background="PanelBrush" Size="-10, -100" Font="smallfont1" Binding="[Text]RoundScore" />
<Label Name="Test3" Background="PanelBrush" Size="-10, -100" Font="smallfont1" Binding="[Text]TotalCardsValue" />

<!– Create answer notification overlay –>
<Animation Name="AnswerNotificationAnim" Duration="2" Type="float">
<Frame Value="-2000" Time="0" Easing="quadin" />
<Frame Value="0" Time="0.5" />
<Frame Value="0" Time="1.5" Easing="quadout" />
<Frame Value="2000" Time="2" />
<Timeline Name="AnswerNotificationAnim" AutoPlay="true">
<Animation Anim="AnswerNotificationAnim" Repeat="1" Target="PositionX" />
<Label Name="AnswerNotification" Position="-2000, 0" Size="-50, -15" Background="PanelBrush" BackgroundColour="80, 255, 80, 255" Font="font1" HitTest="false" />