没有WPF的XAML-动画
我试图在WPF之外完全使用XAML,特别是在XNA应用程序中。到目前为止,我已经设法(非常容易,我很惊讶地承认)从XAML文件在我的XNA应用程序中加载了一些数据。当我决定要设置类的一个属性的动画时,问题就开始了……什么都没有发生:( 以下是我从XAML文件加载的主要类:没有WPF的XAML-动画,wpf,xaml,xna,animation,Wpf,Xaml,Xna,Animation,我试图在WPF之外完全使用XAML,特别是在XNA应用程序中。到目前为止,我已经设法(非常容易,我很惊讶地承认)从XAML文件在我的XNA应用程序中加载了一些数据。当我决定要设置类的一个属性的动画时,问题就开始了……什么都没有发生:( 以下是我从XAML文件加载的主要类: [ContentPropertyAttribute("Animation")] public class Test : FrameworkContentElement { public string Text { get;
[ContentPropertyAttribute("Animation")]
public class Test : FrameworkContentElement
{
public string Text { get; set; }
public Vector2 Position { get; set; }
public Color Color { get; set; }
public Storyboard Animation { get; set; }
public static DependencyProperty RotationProperty =
DependencyProperty.Register("Rotation", typeof(double), typeof(Test), new PropertyMetadata(0.0));
public double Rotation { get { return (double)GetValue(RotationProperty); } set { SetValue(RotationProperty, value); } }
}
<l:Test xmlns:l="clr-namespace:XAMLAndXNA;assembly=XAMLAndXNA"
xmlns:a1="clr-namespace:System.Windows.Media.Animation;assembly=PresentationFramework"
xmlns:a2="clr-namespace:System.Windows.Media.Animation;assembly=PresentationCore"
Text="Testo" Position="55,60" Color="0,255,255,255">
<a1:Storyboard>
<a2:DoubleAnimation a1:Storyboard.TargetProperty="Rotation"
From="0"
To="360"
Duration="00:00:10.0"/>
</a1:Storyboard>
</l:Test>
以下是XAML文件:
[ContentPropertyAttribute("Animation")]
public class Test : FrameworkContentElement
{
public string Text { get; set; }
public Vector2 Position { get; set; }
public Color Color { get; set; }
public Storyboard Animation { get; set; }
public static DependencyProperty RotationProperty =
DependencyProperty.Register("Rotation", typeof(double), typeof(Test), new PropertyMetadata(0.0));
public double Rotation { get { return (double)GetValue(RotationProperty); } set { SetValue(RotationProperty, value); } }
}
<l:Test xmlns:l="clr-namespace:XAMLAndXNA;assembly=XAMLAndXNA"
xmlns:a1="clr-namespace:System.Windows.Media.Animation;assembly=PresentationFramework"
xmlns:a2="clr-namespace:System.Windows.Media.Animation;assembly=PresentationCore"
Text="Testo" Position="55,60" Color="0,255,255,255">
<a1:Storyboard>
<a2:DoubleAnimation a1:Storyboard.TargetProperty="Rotation"
From="0"
To="360"
Duration="00:00:10.0"/>
</a1:Storyboard>
</l:Test>
我好奇死了:)在WPF应用程序的正常循环之外,我怀疑是否有任何方法可以驱动动画。可能有一些类你可以推动或推动他们,但它很可能是密封的 您可能会在另一个线程上构建自己的动画执行引擎,并确保更新发生在您的UI线程上,这意味着要么找到重用调度程序的方法,要么重新创建类似的东西
这是一个有趣的项目。。。我很想知道你是否成功 哇,这真是太棒了!不幸的是,这可能归结为某些内部API中正在进行的某种“更新”类型的调用。如果你不调用它,动画将不会动画。。。就像XNA游戏没有调用Update方法一样
我非常想了解更多关于你是如何做到这一点的信息,以及你的成功程度。你应该在某处写一篇博客文章:-)尽管XAML独立于WPF,但视觉元素却不是。特别是,动画和布局是WPF的一部分,取决于WPF管道的存在——通过应用程序对象、PresentationSource(如HwndSource)、XBAP PresentationHost.exe等 因此,您可以在XAML中读取并获取测试对象的对象图,其中包含一个子情节提要对象,但该测试对象在放置到WPF上下文中之前不会连接到动画或布局引擎。XAML提供给您的只是一个哑内存对象图:是WPF而不是XAML使对象“活动” 因此,正如本所说,你可能最终需要自己“推动或推动”动画。我不知道有任何关于如何做到这一点的文档,但通过在Reflector中查看,它看起来像是关键API,其中的文档说: 值会立即更新为 反映由于 参见Kalignedtolastick,尽管 屏幕不反映这些更改 直到屏幕更新 注意第二条。通常,WPF会在可视对象值更改时处理屏幕的更新。如果您没有使用WPF,那么就由您读取更改的值并相应地重新绘制屏幕:您没有WPF布局管理器来为您处理它 最后,请注意,我还没有测试SeekAlignedToLastTick是否能在没有加载WPF管道的环境中工作。听起来应该如此,因为它不在乎是WPF还是用户代码在驱动时钟,但我不能做出任何承诺。。。虽然我承认你让我好奇
更新:我快速尝试了一下,它似乎确实有效。这是一个在Windows窗体中托管动画的演示(在本例中使用的是一个普通的ol'Windows窗体计时器,但在XNA中,我想框架将为您提供一个游戏计时器——我不知道XNA,所以没有尝试)。假设您有一个带有计时器(timer1)和标签(label1)的普通Windows窗体,并且项目引用了WPF程序集 首先,我对你们班的简化版本:
[ContentProperty("Animation")]
public class Fie : DependencyObject
{
public double Test
{
get { return (double)GetValue(TestProperty); }
set { SetValue(TestProperty, value); }
}
public static readonly DependencyProperty TestProperty =
DependencyProperty.Register("Test", typeof(double), typeof(Fie),
new FrameworkPropertyMetadata(0.0));
public Storyboard Animation { get; set; }
}
现在,使用WPF代码从XAML加载其中一个婴儿并开始动画:
private Fie _f;
private DateTime _startTime;
public Form1()
{
InitializeComponent();
string xaml =
@"<local:Fie xmlns:local=""clr-namespace:AnimationsOutsideWpf;assembly=AnimationsOutsideWpf""
xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""
xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml""
>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty=""Test""
From=""0""
To=""360""
Duration=""00:00:10.0""/>
</Storyboard>
</local:Fie>";
_f = (Fie)XamlReader.Load(XmlReader.Create(new StringReader(xaml)));
Storyboard.SetTarget(_f.Animation, _f);
_f.Animation.Begin();
_startTime = DateTime.Now;
timer1.Enabled = true;
}
test = XamlReader.Load(new XmlTextReader("SpriteBatchStuff.xaml")) as Test;
Storyboard.SetTarget(test.Animation, test);
test.Animation.Begin();
我已经存储了动画的开始时间,并用它来计算我们进入动画的距离。WinForms计时器有点粗糙,但这足以证明其概念;毫无疑问,XNA会有更好的产品。然后我调用Storyboard.SeekAlignedToLastTick,它会更新动画值。没有任何东西会自动显示,因为我的XAML对象没有连接到显示上,但我可以检查它的测试属性并验证它是否确实正在制作动画。实际上,我会用它来更新XAML对象所代表的任何XNA可视元素的位置或方向。仅供参考,我现在将记录我是如何使用XNA实现这一点的。感谢itowlson提供了缺少的链接:否则我必须创建一个带有不可见窗口的空应用程序 我们用XAML定义类及其动画(请注意xmlns指令): 在XNA游戏类的初始化函数中,我们反序列化xaml文件并启动动画:
private Fie _f;
private DateTime _startTime;
public Form1()
{
InitializeComponent();
string xaml =
@"<local:Fie xmlns:local=""clr-namespace:AnimationsOutsideWpf;assembly=AnimationsOutsideWpf""
xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""
xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml""
>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty=""Test""
From=""0""
To=""360""
Duration=""00:00:10.0""/>
</Storyboard>
</local:Fie>";
_f = (Fie)XamlReader.Load(XmlReader.Create(new StringReader(xaml)));
Storyboard.SetTarget(_f.Animation, _f);
_f.Animation.Begin();
_startTime = DateTime.Now;
timer1.Enabled = true;
}
test = XamlReader.Load(new XmlTextReader("SpriteBatchStuff.xaml")) as Test;
Storyboard.SetTarget(test.Animation, test);
test.Animation.Begin();
更新功能将GameTime作为输入,提供TotalGameTime字段,用于存储自应用程序启动以来经过的时间跨度:这正是故事板需要勾选的内容:
protected override void Update(GameTime gameTime)
{
// Allows the game to exit
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
test.Animation.SeekAlignedToLastTick(gameTime.TotalGameTime);
base.Update(gameTime);
}
在“绘制”方法中,我们可以使用“旋转”属性绘制一些文本,该属性现在将正确设置动画:
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
spriteBatch.Begin();
spriteBatch.DrawString(Content.Load<SpriteFont>("font"), test.Text, test.Position, test.Color, (float)test.Rotation, Vector2.Zero, 1.0f, SpriteEffects.None, 0.0f);
spriteBatch.End();
base.Draw(gameTime);
}
protected override void Draw(游戏时间游戏时间)
{
图形设备。清晰(颜色:矢车菊蓝);
spriteBatch.Begin();
spriteBatch.DrawString(Content.Load(“font”)、test.Text、test.Position、test.Color、(float)test.Rotation、Vector2.Zero、1.0f、SpriteEffects.None、0.0f);
spriteBatch.End();
基础。抽签(游戏时间);
}
多么酷的主意!你有没有试过在普通的WPF应用程序中调试动画,看看哪些组件触发了更新?我知道这是一个老问题,但我很好奇你在这方面做了多少?我一直在玩弄在XNA内部托管XAML的想法。甚至这个显示如何添加基本动画的问题也是一个很好的开始。做得很好!我真的很震惊,事情竟如此直截了当。我原以为会有很多密封类的方式。