WPF/IronPythonで、Silverlightアニメーション(お掃除ロボット)を実行できるようにする。
ネットを検索していると、このSilverlightプログラムが目にとまった。
さっそく、IronPythonで、動かすことにした。少しアレンジしています。
デザインツールで始めるSilverlightアニメ/グラフィック
Silverlight 2で.NET技術をカッコよく使おう(3)
http://www.atmarkit.co.jp/fwcr/rensai2/silverlight2_03/silverlight2_03_3.html
お部屋のXAML ⇒ room.xaml ⇒ フローリング
http://softgarden.lovepop.jp/myBlog/xaml/room.xaml
お掃除ロボットXAML ⇒ loomba.xaml ⇒ ザムルンバ(Xamloomba)君
http://softgarden.lovepop.jp/myBlog/xaml/loomba.xaml
フローリングの好きな位置をクリックすると、Xamloomba君がその方向に回転した後に目的地まで移動します。
この処理はStoryboardを動的に生成して実行して実現していますので、詳しくはソースを確認してください .…
ネットを検索していると、このSilverlightプログラムが目にとまった。
さっそく、IronPythonで、動かすことにした。少しアレンジしています。
デザインツールで始めるSilverlightアニメ/グラフィック
Silverlight 2で.NET技術をカッコよく使おう(3)
http://www.atmarkit.co.jp/fwcr/rensai2/silverlight2_03/silverlight2_03_3.html
お部屋のXAML ⇒ room.xaml ⇒ フローリング
http://softgarden.lovepop.jp/myBlog/xaml/room.xaml
お掃除ロボットXAML ⇒ loomba.xaml ⇒ ザムルンバ(Xamloomba)君
http://softgarden.lovepop.jp/myBlog/xaml/loomba.xaml
フローリングの好きな位置をクリックすると、Xamloomba君がその方向に回転した後に目的地まで移動します。
この処理はStoryboardを動的に生成して実行して実現していますので、詳しくはソースを確認してください .…
#
# myLoomba.py
#
import clr
clr.AddReferenceByPartialName("PresentationFramework")
clr.AddReferenceByPartialName("PresentationCore")
clr.AddReference('WindowsBase') # for Point
from System import Object, TimeSpan, Math
from System.Windows.Markup import XamlReader
from System.Windows import (
Window, Application, Point, Duration, PropertyPath,
HorizontalAlignment, VerticalAlignment )
from System.Windows.Controls import Canvas, StackPanel
from System.Windows.Media.Animation import (
Storyboard, RepeatBehavior, DoubleAnimation,
DoubleAnimationUsingKeyFrames, SplineDoubleKeyFrame, KeyTime )
from System.Windows.Media import RotateTransform
def LoadXamlNet(strUrl):
import System
request = System.Net.WebRequest.Create(strUrl)
response = request.GetResponse()
dataStream = response.GetResponseStream()
try:
element = XamlReader.Load(dataStream)
finally:
dataStream.Close()
response.Close()
return element
class Loomba(Object):
SpeedPerSec = 100
SpeedTurn = 2
def __init__(self):
self.Content = uc = LoadXamlNet("http://softgarden.lovepop.jp/myBlog/xaml/loomba.xaml")
self.loomba = uc.FindName('loomba')
setattr(self, "turnLeft", uc.FindName('turnLeft'))
setattr(self, "turnRight", uc.FindName('turnRight'))
setattr(self, "flushlight", uc.FindName('flushlight'))
setattr(self, "loombaRotate", uc.FindName('loombaRotate'))
def StopCurrentAction(self):
self.turnLeft.Pause()
self.turnRight.Pause()
def Move(self, dest):
self.StopCurrentAction()
original = self.GetOriginalPosition()
current = self.GetCurrentPosition()
distance = self.GetDistanceTo(dest)
angle = self.GetAngleTo(dest)
currentAngle = self.GetCurrentAngle()
angle2 = angle # 0.0 ~ 360.0 へ
if (angle < 0.0 ):
angle2 = 360.0 + angle
currentAngle2 = currentAngle % 360.0
by = angle2 - currentAngle2
if by > 180.0 :
by -= 360.0
elif by < -180.0 :
by += 360.0
#//回転に要する時間
#turnTime = TimeSpan.FromSeconds(Math.Abs(self.GetCurrentAngle() - angle) * 2 / 360)
turnTime = TimeSpan.FromSeconds( ( Math.Abs(by) * 2.0 ) / 360.0 )
#//目的地までの所要時間
time = TimeSpan.FromSeconds(distance / self.SpeedPerSec)
#//ストーリーボードを作成
sb = Storyboard()
#//ストーリーボードの所要時間を設定
sb.Duration = time.Add(turnTime)
#//回転用のアニメーション
turnAnimation = DoubleAnimation()
#turnAnimation.To = angle
turnAnimation.By = by
turnAnimation.Duration = Duration(turnTime)
sb.Children.Add(turnAnimation)
Storyboard.SetTarget(turnAnimation, self.loomba)
Storyboard.SetTargetProperty(turnAnimation,
PropertyPath("(UIElement.RenderTransform).(TransformGroup.Children)[2].(RotateTransform.Angle)"))
#//縦方向移動アニメーション
topAnimation = DoubleAnimationUsingKeyFrames()
topAnimation.BeginTime = turnTime #//回転終了後に開始
topKf = SplineDoubleKeyFrame()
topKf.KeyTime = KeyTime.FromTimeSpan(time)
topKf.Value = dest.Y - original.Y
topAnimation.KeyFrames.Add(topKf)
sb.Children.Add(topAnimation)
Storyboard.SetTarget(topAnimation, self.loomba);
Storyboard.SetTargetProperty(topAnimation,
PropertyPath("(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.Y)"))
#//横方向移動アニメーション
leftAnimation = DoubleAnimationUsingKeyFrames()
leftAnimation.BeginTime = turnTime #//回転終了後に開始
leftKf = SplineDoubleKeyFrame()
leftKf.KeyTime = KeyTime.FromTimeSpan(time)
leftKf.Value = dest.X - original.X
leftAnimation.KeyFrames.Add(leftKf)
sb.Children.Add(leftAnimation)
Storyboard.SetTarget(leftAnimation, self.loomba)
Storyboard.SetTargetProperty(leftAnimation,
PropertyPath("(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)"))
#//ストーリーボードを実行
sb.Begin();
def GetOriginalPosition(self):
this=self.Content
original = Point(Canvas.GetLeft(this), Canvas.GetTop(this))
return original
def GetCurrentPosition(self):
original = self.GetOriginalPosition()
trans = (self.loomba.RenderTransform).Children[3]
current = Point(original.X + trans.X, original.Y + trans.Y)
return current
def GetCurrentAngle(self):
trans = (self.loomba.RenderTransform).Children[2]
return trans.Angle
def GetDistanceTo(self,dest):
current = self.GetCurrentPosition()
dx = current.X - dest.X;
dy = current.Y - dest.Y;
return Math.Sqrt(dx * dx + dy * dy)
def GetAngleTo(self,dest):
current = self.GetCurrentPosition()
dx = current.X - dest.X
dy = current.Y - dest.Y
return Math.Atan2(dy, dx) * 180 / Math.PI - 90
class ExWindow(Object):
def __init__(self, Content=None, **keywords):
self.Root = win = Window(**keywords)
aUserControl = LoadXamlNet("http://softgarden.lovepop.jp/myBlog/xaml/room.xaml")
aUserControl.FindName('floor').MouseLeftButtonDown+=self.Border_MouseLeftButtonDown
aUserControl.FindName('leftButton').Click+=self.leftButton_Click
aUserControl.FindName('startFlush').Click+=self.startFlush_Click
aUserControl.FindName('rightButton').Click+=self.rightButton_Click
setattr(self, "floor", aUserControl.FindName('floor'))
self.swFlush = 0
self.myLoomba = Loomba()
self.myLoomba.Content.RenderTransformOrigin = Point(0.5,0.5)
self.myLoomba.Content.HorizontalAlignment = HorizontalAlignment.Center
self.myLoomba.Content.VerticalAlignment = VerticalAlignment.Center
self.myLoomba.Content.Width = 100
self.myLoomba.Content.Height = 100
Canvas.SetLeft(self.myLoomba.Content,250)
Canvas.SetTop(self.myLoomba.Content,200)
canvas=aUserControl.FindName('myLoombaCanvas')
canvas.AddChild(self.myLoomba.Content)
win.Content = aUserControl
def Border_MouseLeftButtonDown(self,sender, e):
#//マウス位置を取得
mouse = e.GetPosition(self.floor)
#//マウス位置は左上のため、中心点を取得
dest = Point(mouse.X - 50, mouse.Y - 50)
#//XamLoombaの移動
self.myLoomba.Move(dest)
def leftButton_Click(self,sender, e):
#//左へ回転
self.myLoomba.turnLeft.Begin()
def rightButton_Click(self,sender, e):
#//右へ回転
self.myLoomba.turnRight.Begin()
def startFlush_Click(self,sender, e):
#//RepeatBehavior.Foreverを設定することにより、動作を永遠に続けます
self.myLoomba.flushlight.RepeatBehavior = RepeatBehavior.Forever
if self.swFlush == 0:
#//フラッシュを開始
self.myLoomba.flushlight.Begin()
self.swFlush = 3
elif self.swFlush == 1:
#//フラッシュを中断
self.myLoomba.flushlight.Pause()
self.swFlush = 2
elif self.swFlush == 2:
#//フラッシュを再開
self.myLoomba.flushlight.Resume()
self.swFlush = 1
else:
#//フラッシュを停止
self.myLoomba.flushlight.Stop()
self.swFlush = 0
if __name__ == "__main__":
win = ExWindow( Width=608, Height=432 ,Title="myLoomba.py")
Application().Run(win.Root)
# myLoomba.py
#
import clr
clr.AddReferenceByPartialName("PresentationFramework")
clr.AddReferenceByPartialName("PresentationCore")
clr.AddReference('WindowsBase') # for Point
from System import Object, TimeSpan, Math
from System.Windows.Markup import XamlReader
from System.Windows import (
Window, Application, Point, Duration, PropertyPath,
HorizontalAlignment, VerticalAlignment )
from System.Windows.Controls import Canvas, StackPanel
from System.Windows.Media.Animation import (
Storyboard, RepeatBehavior, DoubleAnimation,
DoubleAnimationUsingKeyFrames, SplineDoubleKeyFrame, KeyTime )
from System.Windows.Media import RotateTransform
def LoadXamlNet(strUrl):
import System
request = System.Net.WebRequest.Create(strUrl)
response = request.GetResponse()
dataStream = response.GetResponseStream()
try:
element = XamlReader.Load(dataStream)
finally:
dataStream.Close()
response.Close()
return element
class Loomba(Object):
SpeedPerSec = 100
SpeedTurn = 2
def __init__(self):
self.Content = uc = LoadXamlNet("http://softgarden.lovepop.jp/myBlog/xaml/loomba.xaml")
self.loomba = uc.FindName('loomba')
setattr(self, "turnLeft", uc.FindName('turnLeft'))
setattr(self, "turnRight", uc.FindName('turnRight'))
setattr(self, "flushlight", uc.FindName('flushlight'))
setattr(self, "loombaRotate", uc.FindName('loombaRotate'))
def StopCurrentAction(self):
self.turnLeft.Pause()
self.turnRight.Pause()
def Move(self, dest):
self.StopCurrentAction()
original = self.GetOriginalPosition()
current = self.GetCurrentPosition()
distance = self.GetDistanceTo(dest)
angle = self.GetAngleTo(dest)
currentAngle = self.GetCurrentAngle()
angle2 = angle # 0.0 ~ 360.0 へ
if (angle < 0.0 ):
angle2 = 360.0 + angle
currentAngle2 = currentAngle % 360.0
by = angle2 - currentAngle2
if by > 180.0 :
by -= 360.0
elif by < -180.0 :
by += 360.0
#//回転に要する時間
#turnTime = TimeSpan.FromSeconds(Math.Abs(self.GetCurrentAngle() - angle) * 2 / 360)
turnTime = TimeSpan.FromSeconds( ( Math.Abs(by) * 2.0 ) / 360.0 )
#//目的地までの所要時間
time = TimeSpan.FromSeconds(distance / self.SpeedPerSec)
#//ストーリーボードを作成
sb = Storyboard()
#//ストーリーボードの所要時間を設定
sb.Duration = time.Add(turnTime)
#//回転用のアニメーション
turnAnimation = DoubleAnimation()
#turnAnimation.To = angle
turnAnimation.By = by
turnAnimation.Duration = Duration(turnTime)
sb.Children.Add(turnAnimation)
Storyboard.SetTarget(turnAnimation, self.loomba)
Storyboard.SetTargetProperty(turnAnimation,
PropertyPath("(UIElement.RenderTransform).(TransformGroup.Children)[2].(RotateTransform.Angle)"))
#//縦方向移動アニメーション
topAnimation = DoubleAnimationUsingKeyFrames()
topAnimation.BeginTime = turnTime #//回転終了後に開始
topKf = SplineDoubleKeyFrame()
topKf.KeyTime = KeyTime.FromTimeSpan(time)
topKf.Value = dest.Y - original.Y
topAnimation.KeyFrames.Add(topKf)
sb.Children.Add(topAnimation)
Storyboard.SetTarget(topAnimation, self.loomba);
Storyboard.SetTargetProperty(topAnimation,
PropertyPath("(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.Y)"))
#//横方向移動アニメーション
leftAnimation = DoubleAnimationUsingKeyFrames()
leftAnimation.BeginTime = turnTime #//回転終了後に開始
leftKf = SplineDoubleKeyFrame()
leftKf.KeyTime = KeyTime.FromTimeSpan(time)
leftKf.Value = dest.X - original.X
leftAnimation.KeyFrames.Add(leftKf)
sb.Children.Add(leftAnimation)
Storyboard.SetTarget(leftAnimation, self.loomba)
Storyboard.SetTargetProperty(leftAnimation,
PropertyPath("(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)"))
#//ストーリーボードを実行
sb.Begin();
def GetOriginalPosition(self):
this=self.Content
original = Point(Canvas.GetLeft(this), Canvas.GetTop(this))
return original
def GetCurrentPosition(self):
original = self.GetOriginalPosition()
trans = (self.loomba.RenderTransform).Children[3]
current = Point(original.X + trans.X, original.Y + trans.Y)
return current
def GetCurrentAngle(self):
trans = (self.loomba.RenderTransform).Children[2]
return trans.Angle
def GetDistanceTo(self,dest):
current = self.GetCurrentPosition()
dx = current.X - dest.X;
dy = current.Y - dest.Y;
return Math.Sqrt(dx * dx + dy * dy)
def GetAngleTo(self,dest):
current = self.GetCurrentPosition()
dx = current.X - dest.X
dy = current.Y - dest.Y
return Math.Atan2(dy, dx) * 180 / Math.PI - 90
class ExWindow(Object):
def __init__(self, Content=None, **keywords):
self.Root = win = Window(**keywords)
aUserControl = LoadXamlNet("http://softgarden.lovepop.jp/myBlog/xaml/room.xaml")
aUserControl.FindName('floor').MouseLeftButtonDown+=self.Border_MouseLeftButtonDown
aUserControl.FindName('leftButton').Click+=self.leftButton_Click
aUserControl.FindName('startFlush').Click+=self.startFlush_Click
aUserControl.FindName('rightButton').Click+=self.rightButton_Click
setattr(self, "floor", aUserControl.FindName('floor'))
self.swFlush = 0
self.myLoomba = Loomba()
self.myLoomba.Content.RenderTransformOrigin = Point(0.5,0.5)
self.myLoomba.Content.HorizontalAlignment = HorizontalAlignment.Center
self.myLoomba.Content.VerticalAlignment = VerticalAlignment.Center
self.myLoomba.Content.Width = 100
self.myLoomba.Content.Height = 100
Canvas.SetLeft(self.myLoomba.Content,250)
Canvas.SetTop(self.myLoomba.Content,200)
canvas=aUserControl.FindName('myLoombaCanvas')
canvas.AddChild(self.myLoomba.Content)
win.Content = aUserControl
def Border_MouseLeftButtonDown(self,sender, e):
#//マウス位置を取得
mouse = e.GetPosition(self.floor)
#//マウス位置は左上のため、中心点を取得
dest = Point(mouse.X - 50, mouse.Y - 50)
#//XamLoombaの移動
self.myLoomba.Move(dest)
def leftButton_Click(self,sender, e):
#//左へ回転
self.myLoomba.turnLeft.Begin()
def rightButton_Click(self,sender, e):
#//右へ回転
self.myLoomba.turnRight.Begin()
def startFlush_Click(self,sender, e):
#//RepeatBehavior.Foreverを設定することにより、動作を永遠に続けます
self.myLoomba.flushlight.RepeatBehavior = RepeatBehavior.Forever
if self.swFlush == 0:
#//フラッシュを開始
self.myLoomba.flushlight.Begin()
self.swFlush = 3
elif self.swFlush == 1:
#//フラッシュを中断
self.myLoomba.flushlight.Pause()
self.swFlush = 2
elif self.swFlush == 2:
#//フラッシュを再開
self.myLoomba.flushlight.Resume()
self.swFlush = 1
else:
#//フラッシュを停止
self.myLoomba.flushlight.Stop()
self.swFlush = 0
if __name__ == "__main__":
win = ExWindow( Width=608, Height=432 ,Title="myLoomba.py")
Application().Run(win.Root)
![]() | IronPythonの世界 (Windows Script Programming) |
荒井 省三 | |
ソフトバンク クリエイティブ |
![]() | エキスパートPythonプログラミング |
Tarek Ziade | |
アスキー・メディアワークス |
![]() | Pythonスタートブック |
辻 真吾 | |
技術評論社 |