From d4ef778cc8bb2aab4ecd7a992926d3c11ef69cd4 Mon Sep 17 00:00:00 2001 From: Paolo Capriotti Date: Fri, 19 Jun 2009 11:55:18 +0200 Subject: [PATCH] Add path specification for movement animations. Paths are functions that compute the increment in position at time i. A linear path and an L-shaped path have been added. The L-shaped path has been mapped to the chess knight movement. --- lib/animations.rb | 36 ++++++++++++++++++++++++++++++++---- lib/animator_helper.rb | 4 ++-- lib/{games => }/factory.rb | 0 lib/games/chess/animator.rb | 13 +++++++++++-- lib/games/chess/chess.rb | 1 - lib/games/games.rb | 2 ++ test/test_animations.rb | 2 +- test/test_animator_helper.rb | 2 +- 8 files changed, 49 insertions(+), 11 deletions(-) rename lib/{games => }/factory.rb (100%) diff --git a/lib/animations.rb b/lib/animations.rb index 7f66308..8321b91 100644 --- a/lib/animations.rb +++ b/lib/animations.rb @@ -1,4 +1,5 @@ require 'animation_field' +require 'factory' module Animations LENGTH = 100 @@ -24,18 +25,18 @@ module Animations end end - def movement(item, src, dst) + def movement(item, src, dst, path_factory) if item src = board.to_real(src) dst = board.to_real(dst) - delta = dst - src + path = path_factory.new(src, dst) SimpleAnimation.new "move to #{dst}", LENGTH, nil, - lambda {|i| item.pos = src + delta * i }, + lambda {|i| item.pos = src + path[i] }, lambda { item.pos = dst } end end - + def disappear(item, name = "disappear") if item SimpleAnimation.new name, LENGTH, @@ -60,3 +61,30 @@ module Animations Animation.new(name) { board.remove_item p } end end + +module Path + Linear = Factory.new do |src, dst| + delta = dst - src + lambda {|i| delta * i } + end + + class LShape + FACTOR = Math.exp(3.0) - 1 + def initialize(src, dst) + @delta = dst - src + nonlin = lambda{|i| (Math.exp(3.0 * i) - 1) / FACTOR } + lin = lambda {|i| i } + if @delta.x.abs < @delta.y.abs + @x = lin + @y = nonlin + else + @y = lin + @x = nonlin + end + end + + def [](i) + Qt::PointF.new(@delta.x * @x[i], @delta.y * @y[i]) + end + end +end diff --git a/lib/animator_helper.rb b/lib/animator_helper.rb index 390dad2..40ea8fd 100644 --- a/lib/animator_helper.rb +++ b/lib/animator_helper.rb @@ -3,9 +3,9 @@ require 'animations' module AnimatorHelper include Animations - def move!(src, dst) + def move!(src, dst, path) piece = board.move_item(src, dst) - movement(piece, src, dst) + movement(piece, src, dst, path) end def disappear_on!(p, opts = {}) diff --git a/lib/games/factory.rb b/lib/factory.rb similarity index 100% rename from lib/games/factory.rb rename to lib/factory.rb diff --git a/lib/games/chess/animator.rb b/lib/games/chess/animator.rb index bdbdff0..719dbb1 100644 --- a/lib/games/chess/animator.rb +++ b/lib/games/chess/animator.rb @@ -8,7 +8,16 @@ module Chess def initialize(board) @board = board end - + + def specific_move!(piece, src, dst) + path = if piece.type == :knight + Path::LShape + else + Path::Linear + end + move!(src, dst, path) + end + def warp(state, opts = { :instant => true }) res = [] @@ -32,7 +41,7 @@ module Chess def forward(state, move) capture = disappear_on! move.dst - actual_move = move! move.src, move.dst + actual_move = specific_move! state.board[move.dst], move.src, move.dst extra = if move.type == :king_side_castling move! move.dst + Point.new(1, 0), move.dst - Point.new(1, 0) elsif move.type == :queen_side_castling diff --git a/lib/games/chess/chess.rb b/lib/games/chess/chess.rb index dbc626b..c180f0c 100644 --- a/lib/games/chess/chess.rb +++ b/lib/games/chess/chess.rb @@ -6,7 +6,6 @@ require 'games/chess/policy' require 'games/chess/animator' require 'games/chess/validator' require 'games/chess/serializer' -require 'games/factory' module Chess diff --git a/lib/games/games.rb b/lib/games/games.rb index 9d65921..3a5c4ed 100644 --- a/lib/games/games.rb +++ b/lib/games/games.rb @@ -1,3 +1,5 @@ +require 'factory' + class Game GAMES = { } diff --git a/test/test_animations.rb b/test/test_animations.rb index c1df617..4f166e9 100644 --- a/test/test_animations.rb +++ b/test/test_animations.rb @@ -72,7 +72,7 @@ class TestAnimations < Test::Unit::TestCase def test_movement item = GeneralMock.new - @field.run @c.movement(item, Point.new(3, 4), Point.new(5, 6)) + @field.run @c.movement(item, Point.new(3, 4), Point.new(5, 6), Path::Linear) @field.run_test old_p = nil diff --git a/test/test_animator_helper.rb b/test/test_animator_helper.rb index ee5694d..980f6b2 100644 --- a/test/test_animator_helper.rb +++ b/test/test_animator_helper.rb @@ -44,7 +44,7 @@ class TestAnimatorHelper < Test::Unit::TestCase def test_move @items[Point.new(3, 3)] = "white knight" - anim = @animator.move!(Point.new(3, 3), Point.new(5, 4)) + anim = @animator.move!(Point.new(3, 3), Point.new(5, 4), Path::Linear) assert_animation(:movement, anim) do |args| piece, src, dst = args assert_equal "white knight", piece -- 2.11.4.GIT