Building a Ruby/DHTML Turn Based Strategy Game... in 20 minutes

Topher Cyll

FOSCON II

Okay

Who plays video games?

Okay

Who plays turn based strategy?

Okay

Plot ideas?

Tools

DHTML

Tools

Rails?

Today

Ruby Backend
|
TBS Tuples
|
DHTML Frontend

Tomorrow

Ruby Backend
|
TBS Tuples
|
Native Frontend...?

TBS Tuples


(Message "hello, there!")

TBS Tuples


(Message "hello, there!")

(Choose (Unit 0 0)
        (Unit 3 4)
        (Done))

TBS Tuples


(Message "hello, there!")

(Choose (Unit 0 0)
        (Unit 3 4)
        (Done))

(Draw ((Forest Water ...)
       (Forest ...))
      ((Ninja, nil...)
       (...)))

Encoding

JSON

JSON TBS Tuples


["Message", "hello, there!"]

JSON TBS Tuples


["Message", "hello, there!"]

["Choose", ["Unit", 0, 0],
           ["Unit", 3, 4],
           ["Done"]]

JSON TBS Tuples


["Message", "hello, there!"]

["Choose", ["Unit", 0, 0],
           ["Unit", 3, 4],
           ["Done"]]

["Draw", [["Forest", "Water"...],
          ["Forest" ...]],
         [["Ninja", null...]
          [...]]]

Caution

Just for fun

MIT License

Freely available

Starting...

Now

Getting Started


# Available at
# http://cyll.org/tbs.shtml
require_gem 'tbs'

First Working Version


class CowboyBattle < TBS::Game
  @@name = "Cowboy Battle"
end

First Working Version


def turn(player)
  player.new_turn






end

First Working Version


def turn(player)
  player.new_turn

  draw_all()




end

First Working Version


def turn(player)
  player.new_turn

  draw_all()

  # This next line is *barely* legal
  player.choose([["Nevermind"]]) do
  end
end

First Working Version


map = TBS::Map.new terrain_key, <<-END
  gggppppppp
  ggppggwtpt
  ggpgggwwtt
END



First Working Version


map = TBS::Map.new terrain_key, <<-END
  gggppppppp
  ggppggwtpt
  ggpgggwwtt
END

game.add_map(map)

First Working Version


terrain_key = {
  "p" => TBS::Plains.new,
  "g" => TBS::Grass.new,
  "w" => TBS::Water.new,
  "t" => TBS::Town.new,
}

First Working Version


human = TBS::Players::DHTML.new("cowboy", "Topher")




First Working Version


human = TBS::Players::DHTML.new("cowboy", "Topher")

game = CowboyBattle.new
game.add_player human

First Working Version


TBS::Spawner.new(2002) do
  # ...
  Thread.new{ game.run }
  human.method(:callback)
end.run

Check it out!

What's missing?

Now what?

Adding Units


class Unit < TBS::Unit
end

Adding Units


class Captain < Unit
  def initialize(*args)
    super(*args)
    @hp   = 10
    @move = 1
    @actions.push TBS::Attack
  end
end

Adding Units


stanley = Captain.new(human, "Stanley")


Adding Units


stanley = Captain.new(human, "Stanley")
map.place(0, 0, stanley)

Check it out!

What's missing?

Now what?

Moving Units


choices = player.not_done_unit_choices
player.choose_all_or_done(choices) do |choice|
  break if choice == TBS::DONE
  unit = choice.call

Moving Units


player.choose(unit.move_choices) do |move|
  move.call
end
unit.done

Check it out!

What's missing?

Now what?

Attacking


computer = TBS::Players::DumbComputer.new("Computer")
game.add_player computer

Attacking


class EvilCaptain < Captain
end

Attacking


evilcaptain = EvilCaptain.new(computer, "EvilTwin")
map.place(0, 2, evilcaptain)

Attacking


choices = unit.action_choices
player.choose(choices) do |action|
  action.call
end
unit.done

Check it out!

HTML

Slots
Mochikit
Extendable

Javascript


<script src="core.js"></script>
<script src="draw.js"></script>
<script src="choices.js"></script>
<!-- Your scripts go here -->
<script src="eventloop.js"></script>

Javascript


choiceRegistry.Move = function(x, y) {
  highlight(terrainid(x, y));
  $(terrainid(x, y)).onclick = function() {
    reply(repr(["Move", x, y]));
  };
};

CSS


.Grass { 
    background-color: #006633;
}

CSS


.Town { 
    background-color: #CDAA7D;
    background-image: url("images/house.png");
}

CSS


.Captain {
    background-image: url("images/captain.png");
}

Your Turn


$ wget http://cyll.org/tbs-0.1.gem




Your Turn


$ wget http://cyll.org/tbs-0.1.gem
$ sudo gem install tbs



Your Turn


$ wget http://cyll.org/tbs-0.1.gem
$ sudo gem install tbs
$ wget http://cyll.org/cowboy.tar.gz


Your Turn


$ wget http://cyll.org/tbs-0.1.gem
$ sudo gem install tbs
$ wget http://cyll.org/cowboy.tar.gz
$ tar zxvf cowboy.tar.gz