Rubyでどう書く?:RubyCocoa+Core Animationでお手軽アニメーション

佐藤伸吾(KBMJ)
2008-08-14 08:00:00
  • このエントリーをはてなブックマークに追加

問題

 RubyCocoaは、Mac OS XのCocoaオブジェクトをRubyスクリプトからRubyオブジェクトとして扱うための、Ruby用ライブラリとフレームワークです。RubyCocoaを用いれば、RubyでCocoaアプリケーションを記述することができるのです。

 Core AnimationはMax OS Xのフレームワークで、その利点は手軽さにあります。普通にアニメーションプログラミングを行おうとすると、時間軸管理、非同期な描画スレッド、パフォーマンスの向上など、考慮すべき点があまりにも多すぎます。

 しかし、Core Animationを用いれば、面倒な部分はOSに任せて、自分の実現したいことに集中できるのです。

 今回はRubyCocoaとMac OS XのフレームワークであるCore Animationを使って、お手軽にアニメーションを作成してみましょう。

回答例

 AppController.rbを作成し、以下のように記述します。

require 'osx/cocoa'
OSX.require_framework 'QuartzCore'

class AppController < OSX::NSObject
ib_outlet :window
ib_outlet :view
ib_action :pressPosition
ib_action :pressRotation
ib_action :pressSepia
ib_action :pressBloom
ib_action :pressHole
ib_action :pressZoom
ib_action :pressHalftone

def awakeFromNib
bitmapImage = OSX::NSBitmapImageRep.imageRepWithContentsOfFile_('/Users/ssato/Pictures/ruby.png')
image = bitmapImage.CGImage()

layer = OSX::CALayer.layer()
layer.contents = image
layer.frame = OSX::CGRectMake(0,0,995/4,996/4)

black=OSX::CGColorCreateGenericRGB(0,0, 0,1.0)
backgroundLayer=OSX::CALayer.layer()
backgroundLayer.backgroundColor=black

backgroundLayer.addSublayer_(layer)

@view.setLayer_(backgroundLayer)
@view.setWantsLayer_(true)
end
def pressPosition(sender)
animation = OSX::CABasicAnimation.animationWithKeyPath_('position')
animation.duration = 1.0

layer = @view.layer.sublayers.objectAtIndex_(0)
position = layer.position
animation.fromValue = OSX::NSValue.valueWithPoint_(OSX::NSPointFromCGPoint(position))
position.x += 256;
position.y += 160;
animation.toValue = OSX::NSValue.valueWithPoint_(OSX::NSPointFromCGPoint(position))
animation.autoreverses = true
animation.repeatCount = 4
layer.addAnimation_forKey_(animation, 'positionAnimation')
end
def pressRotation(sender)
animation = OSX::CABasicAnimation.animationWithKeyPath_('transform')
animation.duration = 0.5
animation.autoreverses = true
animation.repeatCount = 4
transform = OSX::CATransform3DIdentity
animation.fromValue = OSX::NSValue.valueWithCATransform3D(transform)
transform = OSX::CATransform3DMakeRotation(Math::PI, 0, 1.0, 0)
transform.m34 = 1.0 / -420.0
animation.toValue = OSX::NSValue.valueWithCATransform3D(transform)
layer = @view.layer.sublayers.objectAtIndex_(0)
layer.addAnimation_forKey_(animation, 'transformAnimation')
end
def pressSepia(sender)
filter = OSX::CIFilter.filterWithName_('CISepiaTone')
filter.setDefaults()
layer = @view.layer.sublayers.objectAtIndex_(0)
layer.name = 'sepiaFilter'
layer.setFilters_(OSX::NSArray.arrayWithObject_(filter))
end
def pressBloom(sender)
filter2 = OSX::CIFilter.filterWithName_('CIBloom')
filter2.setDefaults
filter2.setValue_forKey_(OSX::NSNumber.numberWithFloat_(0.0), 'inputIntensity')
filter2.setValue_forKey_(OSX::NSNumber.numberWithFloat_(5.0), 'inputRadius')
filter2.setName_('bloomFilter')

layer = @view.layer.sublayers.objectAtIndex_(0)
layer.setFilters_(OSX::NSArray.arrayWithObject_(filter2))

pluseAnimation = OSX::CABasicAnimation.animation
pluseAnimation.keyPath = 'filters.bloomFilter.inputIntensity'
pluseAnimation.fromValue = OSX::NSNumber.numberWithFloat_(0.0)
pluseAnimation.toValue = OSX::NSNumber.numberWithFloat_(1.5*2)
pluseAnimation.duration = 1.0
pluseAnimation.repeatCount = 4
pluseAnimation.autoreverses = true
layer.addAnimation_forKey_(pluseAnimation, 'bloom')
end
def pressHole(sender)
filter = OSX::CIFilter.filterWithName_('CIHoleDistortion')
filter.setDefaults()
layer = @view.layer.sublayers.objectAtIndex_(0)
layer.setFilters_(OSX::NSArray.arrayWithObject_(filter))
end
def pressZoom(sender)
filter = OSX::CIFilter.filterWithName_('CIZoomBlur')
filter.setDefaults()
layer = @view.layer.sublayers.objectAtIndex_(0)
layer.setFilters_(OSX::NSArray.arrayWithObject_(filter))
end
def pressHalftone(sender)
filter = OSX::CIFilter.filterWithName_('CICMYKHalftone')
filter.setDefaults()
layer = @view.layer.sublayers.objectAtIndex_(0)
layer.setFilters_(OSX::NSArray.arrayWithObject_(filter))
end
end

 Interface Builderで画像1のようにコンポーネントを配置します。

画像1 画像1

 NSObjectを追加して、ClassにAppcontrollerを指定します(画像2)。

画像2 画像2

 OutletsとActionsのConnectionを画像3のように設定します。

画像3 画像3

実行結果

 Positionボタンを押すと、画像が斜めに移動します(画像4)。

画像4

 Rotationボタンを押すと画像が回転し、Sepiaをクリックすると画像がセピア色になります(画像5)。

画像5 画像5

 同様に、Bloomは画像が光り輝き(画像6)、Holeは画像に穴が空きます(画像7)。Zoomボタンはズームエフェクト(画像8)で、Halftoneはハーフトーンフィルタです(画像9)。

画像6 画像6
画像7 画像7
画像8 画像8
画像9 画像9

解説

  • 新着記事
  • 特集
  • ブログ