Sunday, April 11, 2010

Finally...

I'm glad to announce the first "playable" version of Laterna Magica. Features:
  • A rather simple GUI
  • Drawing a card during your draw step
  • Playing Lands
  • An opponent who does... nothing
Before I present you some screenshots, let me explain the "glue" I've talked about the last time, especially the controller.

The class Player in laterna magica is more or less a data structure and can only perform tasks that don't need decisions - like loosing life, drawing a card or discarding a card at random.
Discarding a chosen card is different, because it needs knowledge, which is something the Player class should not have. Different players make different decisions, and in different ways.

The solution is the Actor class. Whenever some decision is needed, like which card to discard, the actor is asked for that decision. The actor may implement an AI algorithm for choosing, it may get the choice over the network, or, most naturally, depend on user input from the GUI.

Although separating actor from player was a clear choice for me, I don't know how that class will look in the end. Magic is a game with tons of choices - there's not only "discard a card" but also "discard two cards", "discard a creature card", "discard a card of each color"... you know what I mean, this can quickly get messy.
For now, there's basically only "You have priority. What do you want to do?", so that problem is still far away.


And now screenies! When you start the program, you get a GUI with an empty board, like this:

But it doesn't stay for long, it will quickly populate your game with cards. You can watch how your library grows and you draw cards!
After passing priority twice, It will be your main, and you can play one of your (many) Plains:
Looks great? Look at that, during your next turn, you can do it again^^
What you have just seen demonstrates some important things:
  • Laterna Magica has many events. Playing a land doesn't explicitly remove it from the panel. Instead, the panel listens for cards entering/exiting the zone (and later also controller changes) to keep track of what cards are to be shown. When the land is played, the rules engine moves it, and the GUI listens to the rules engine. Similar things are true for the zone size labels, the life total labels and the turn progress label.
  • And because swing supports it, the game loop (passing priority back and forth, basically) can run in an extra thread. Whenever the player "freak" has priority, the GameLoop queries the Actor for what to do. That actor is a GuiActor and waits for the user to either click "Pass priority" or a Plains card. Therefore, the GUI thread is not blocked when the game loop is working.
  • The GUI has a utility for finding all the actions possible for clicking a card. Currently, there's only playing a land, but it will also check for playing spells or activated abilities, unmorphing etc. in the future. That Utility also checks if the action is legal (timing, only one land per turn etc.)
  • what aparently doesn't work is discarding excess cards at end of turn. While it's easy, I've chosen to show you what I have as soon as drawing and playing a land works.
  • If you would click yourself all the way through until a library is empty, you would notice that the game doesn't end with that. Although the state based action does exist, the loseGame() method of player is a No-Op.
okay, enough for now. Have fun playing some real games ;)

    6 comments:

    Incantus said...

    Nice job! I remember when I first got the basics of my rule engine working. It was so exciting to be able to go through a few phases and perform user actions. And your separation of UI and rules engine sounds a lot like the approach I took.

    Silly Freak said...

    yes, it's a nice feeling to see how your program does just what it should! I hope I'll have it a little more often in the future, but right now, mana costs really hurt my brain. I took a quick and dirty aproach for my Llanowar Elves, which seems to work, but that one isn't suitable at all for parsed cards, so I have to redo it...

    nantuko84 said...

    is it possible to run this example using svn version?
    and if I'm not mistaken, LaternaDoc missing tools.jar library so I had to change build path to use Laterna\lib\tools.jar

    Bruno Cardoso said...

    I think there are a couple of dependencies problems on SVN.

    LaternaMagica for example depends on a project called "TransformedPanel" that is missing.

    Anyway... I manage to run the example using TestCardPanel.

    nantuko84 said...

    > Bruno Cardoso
    thanks, TestCardPanel is what I needed =)
    btw, you are right, there are some dependencies missing. moreover eclipse has some problem with compiling laterna.pictures.Test.java

    Silly Freak said...

    tools.jar is included with the JDK, and since everyone has it in another location, I didn't include it in the libs. you should use your own. with the original .classpath file, go to Windows/Preferences..., Java/Build Path/User Libraries and add "Javadoc" with tools.jar. Eclipse should then find it

    TransformedPanel is more or less obsolete, it's a little utility of mine that I don't need any longer. I will remove it from SVN the next time I have something serious to commit, probably aling with Test.java

    by the way, I have tried to play human vs human (possible by simply setting a GuiActor on the second player) and noticed that my GUI-Code (ZonePanel) can't handle multiple players controlling permanents:
    Every zone panel shows only those controlled by one player, but uses indices from the zone, which contains all the permanents...