65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 C# 在 WPF 中嵌入 IronPython

starIconstarIconstarIconstarIconstarIcon

5.00/5 (2投票s)

2007年10月31日

CPOL

13分钟阅读

viewsIcon

55228

downloadIcon

1021

在本文中,我们将了解如何使用 C# 将 IronPython 嵌入到我们的 Windows Presentation Framework 应用程序中。

引言

在本文中,我将解释 IronPython 作为脚本引擎嵌入到 C# 中的用法。在此过程中,我将同时展示 WPF 的基础知识以及如何将 IronPython 集成到 WPF 中,以便我们可以使用 Python 代码来编辑我们的应用程序。Python 也是一种非常容易上手的语言,特别是如果您了解 C#,因为它们非常相似。

介绍 Python

Python 编程语言于 1991 年发布,由 Guido van Rossum 创建。Python 的语法非常清晰简洁,将程序员的精力放在计算机而不是计算机的精力上。该语言本身是一种多范式语言,与 Perl、Ruby 等语言相似。Python 是一个由非营利性 Python 软件基金会管理的开放社区开发模型。

C# 和 Python 的简要区别

Python 的动态类型模型允许它在运行时自动确定数据类型。无需提前声明变量的类型,这是一个非常简单的概念。

声明 C# 和 Python 中变量的区别

C#
int a = 1 
string b = "b"
Python
a = 1
b = 'b'

在 Python 中创建 if 语句与在 C# 中几乎相同,只是 Python 不使用大括号 ({}) 来开始和结束方法。相反,在语句的开头添加冒号 (:) 来开始执行代码。一个问题出现了,因为没有像 C# 的大括号那样的结束指示,所以您只能写一个语句而没有任何其他指示。这可以通过在每个语句末尾加上分号 (;) 来解决,以表明我们还没有完成方法。

在 C# 和 Python 中创建 if 语句的区别

C#
if (a > b)
{
    a = 1;
    b = 2;
}
else if (a < 3 and b > 3)
{
    a = 2;
}
else
{
    b = 3;
}
Python
if (a > b):
    a = 1;
    b = 2;
elif (a < 3 and b > 3):
    a = 2
else:
    b = 3

在 Python 中声明的函数与之前的 if 语句几乎相同,只是它以 "def" 开头。Python 的 def 是可执行代码,因此当您编译代码时,函数在 Python 达到并运行 def 之前不存在。函数类型(如变量)不需要声明类型。

在 C# 和 Python 中创建函数的区别

C#
int MyFunction()
{
    return 5;
}
Python
def MyFunction():
    return 5;

以上是对 Python 的非常简短的介绍。另外,请注意,Python 的许多语法可能与此处所示的不同,但可能表示相同的意思。

IronPython 简介

IronPython 是通过实现 Python 语言而创建的,该语言是为 .NET 环境构建的。IronPython 的创建者是 Jim Hugunnin,IronPython 的第一个版本发布于 2006 年 9 月 5 日。

嵌入 IronPython

IronPython 可以通过几个简单的步骤嵌入到 WPF (Windows Presentation Framework) 应用程序中。

  1. 引用 IronPython 和 IronMath。
  2. 添加命名空间
  3. using IronPython;
    using IronMath;
  4. 声明 PythonEngine
  5. engine = new PythonEngine();

通过完成这三个步骤,您已经初始化了 PythonEngine 开始所需的所有内容。

在您的应用程序中使用 IronPython 主要在于声明变量和加载 Python 脚本(*.py 扩展名)文件。

//Add Variable
PythonEngine.Globals.Add(key, value);

//Load Python File
PythonEngine.CompileFile(string path);

将变量添加到 PythonEngine 全局变量的示例

int var = 1; 
PythonEngine.Globals.Add("var", var);
PythonEngine.Globals["var"] = 3; 

编译 Python (*.py) 文件的示例

Python
//PythonFile.py
//
name = 'Chris'
age = 21
C#
//Example.cs
PythonEngine.CompileFile("PythonFile.py");

//Retrieve Variables
string name = PythonEngine["name"].ToString();
int age = (int)PythonEngine["age"] ;

正如您所见,PythonEngine.Globals 在 C# 和 Python 通信中起着重要作用。

现在,假设您想执行一个简单的命令,例如,在 C# 中使用 Python 的 print 命令。有一个简单的函数可以做到这一点。

//Execute code
PythonEngine.Execute(print name)

//Ouputs to the stream
PythonEngine.SetStandardOutput(Stream s)

在 C# 中使用此功能的示例

//
//ExecutePython.cs
//
string name = "Bob";
MemoryStream stream = new MemoryStream();

PythonEngine.Globals.Add("name", name);
PythonEngine.SetStandardOutput(stream); 
PythonEngine.Execute("print name")

//Retrieve data from stream
byte[] data = new byte[stream.Length];
stream.Seek(0, SeekOrigin.Begin);
stream.Read(data, 0, data.Length);
string strdata = Encoding.ASCII.GetString(data);

//Output
//strdata: "Bob"

您还可以连接输入和错误流。

PythonEngine.SetStandardError(Stream s);
PythonEngine.SetStandardInput(Stream s);

使用 WPF 创建应用程序

我在这里创建的应用程序是使用 Windows Presentation Framework 创建的,该程序的目标是用于试验 IronPython 并了解其优势。我将介绍用于创建应用程序基本 UI 的 XAML 和 C# 代码。

为了获得应用程序的“Aero”外观,我必须执行以下步骤。

  1. 添加 PresentationFramework.Aero 引用。
  2. 之后,右键单击引用 PresentationFramework.Aero 并选择:将本地副本设置为 true。
  3. 打开 App.xaml 并添加/编辑
  4. <ResourceDictionary 
      Source="/presentationframework.aero;component/themes/aero.normalcolor.xaml" />
  5. 单击构建应用程序。

Aero 外观现在已应用于 UI。

此应用程序中使用的 TreeView 由父 Scene 节点和 Scene 节点的子节点组成。Scene 节点由三个子节点组成,分别是 ScriptActorsObjectsScript 节点有一个作为子项的组合框,以便用户可以选择当前要渲染到场景的脚本。ActorsObjects 留空以供任何子项使用。节点显示名称使用 Header 属性设置,并使用 IsExpanded="True" 属性展开。

<TreeView Name="treeScene" Background="LightGray" Width="135">
  <TreeViewItem Header="Scene" IsExpanded="True">
     <TreeViewItem Header="Script">
        <ComboBox Name="comboScript" />
     </TreeViewItem>

     <TreeViewItem Header="Actors" IsExpanded="True" />
       <TreeViewItem Header="Objects" IsExpanded="True" />
    </TreeViewItem>
</TreeView>

创建 Actor、Script 或 Object 后,TreeView 会创建和/或更新新内容。使用新内容更新 TreeView 包括以下步骤:

  1. 创建 Actor。
  2. TreeViewItem 添加到 Actors 节点。
  3. 在刚创建的 Actor 节点下创建另一个 TreeViewItem
  4. ComboBox 添加到最新创建的 TreeViewItem

这是实现此过程的 C# 代码。

public void AddTreeItem()
{ 
    TreeViewItem treeItemActor = new TreeViewItem();
    treeItemActor.IsExpanded = true;
    treeItemActor.Header = actorName;
    TreeViewItem treeItemScript = new TreeViewItem();
    treeItemScript.IsExpanded = true;
    treeItemScript.Header = "Script";
    ActorScript = new ComboBox();

    foreach (string scriptName in AIEngine.ScriptFiles.Keys)
    {
        actorScript.Items.Add(scriptName);
    }

    treeItemScript.Items.Add(ActorScript);
    int actorIndex = ((TreeViewItem)((TreeViewItem)
        AIEngine.SceneTree.Items[0]).Items[1]).Items.Add(treeItemActor);
    ((TreeViewItem)((TreeViewItem)((TreeViewItem)
      AIEngine.SceneTree.Items[0]).Items[1]).Items[actorIndex]).Items.Add(
      treeItemScript);

}

每次创建 Actor 时,此过程都会在应用程序中实现。

Screen 由自定义屏幕创建,该屏幕通过继承 DrawingCanvas 类(该类继承 Canvas 类)来创建。DrawingCanvas 类充当用户可以在其上绘制对象的控件。为此,该类必须具有 System.Windows.Media.Visuals 的集合(其中保存了绘图)。此外,我还创建了一个临时视觉集合,以便我可以在不弄乱主视觉集合的情况下制作方形绘图动画。

此处的代码显示了如何实现这一点。

//The screen that holds and draws visuals. This is embedded
//in the XAML code of the MainWnd.

public class DrawingCanvas : Canvas
{
    //The collection of visual(drawings) the screen has
    private List<Visual>
    visuals = new List<Visual>();
    //Temprorary visuals that are deleted periodicly.
    //Such as drawing the square, in order to animate the 
    //dragging ability, we must delete visuals.
    private List<Visual>
    tempvisuals = new List<Visual>();
    //This tells the AddVisual whether or not add the visual
    //temprorary or in the visual collection.
    public bool startTempVisual = false;

    //Get the current visual count
    protected override int VisualChildrenCount
    {
        get
        {
            if (!startTempVisual)
            {
                return visuals.Count;
            }
            else
            {
                return tempvisuals.Count;
            }
        }
    }
    //Get a visual
    protected override Visual GetVisualChild(int index)
    {
        if (!startTempVisual)
        {
            return visuals[index];
        }
        else
        {
            return tempvisuals[index];
        }
    }

    //Add a temporary or normal visual
    public void AddVisual(Visual visual, bool tempVisual)
    {
        if (tempVisual)
        {
            tempvisuals.Add(visual);
        }
        else
        {
            visuals.Add(visual);
        }

        base.AddVisualChild(visual);
        base.AddLogicalChild(visual);
    }

    //Delete a temporary or normal visual
    public void DeleteVisual(Visual visual, bool tempVisual)
    {
        if (tempVisual)
        {
            tempvisuals.Clear();
        }
        else
        {
            visuals.Remove(visual);
        }
        
        base.RemoveVisualChild(visual);
        base.RemoveLogicalChild(visual);
    } 
}

然后将 DrawingCanvas 类嵌入到 MainWindow 的 XAML 中。

<local:DrawingCanvas Name="drawingScreen" Background="DimGray"></local:DrawingCanvas>

local:”标签用于从命名空间引用 DrawingCanvas

xmlns:local="clr-namespace:AIEditor.Core;assembly=AIEditor.Core"

Screen 背景中显示的网格是使用 System.Windows.Media.DrawLine 绘制并添加到 DrawingCanvas 的视觉集合中的。

窗口加载时,将触发此事件以绘制背景网格。

private void Window_Loaded(object sender, RoutedEventArgs e)
{
    visual = new DrawingVisual(); 
    int heightIncrements = (int)drawScreen.RenderSize.Height / 10; 
    int widthIncrements = (int)drawScreen.RenderSize.Width / 10; 
    int horizontalLength = (int)drawScreen.RenderSize.Width; 
    int verticalLength = (int)drawScreen.RenderSize.Height; 
    float verticalIncrement = 0; 
    float horizontalIncrement = 0; 
    float largerIndicator = 0; 

    using (DrawingContext dc = visual.RenderOpen()) 
    {
        //Draw Horizontal Lines 
        for (int h = 0; h < heightIncrements + 1; h++) 
        { 
            if (largerIndicator == 5) 
            { 
                Point fromPoint = new Point(0, verticalIncrement); 
                Point toPoint = new Point(horizontalLength, verticalIncrement); 
                HorizontalLines.Add(new Point[] { fromPoint, toPoint }); 
                Pen pen = new Pen(Brushes.DarkKhaki, .5); 
                dc.DrawLine(pen, fromPoint, toPoint); 
                largerIndicator = 0; 
            }
            else 
            { 
                Point fromPoint = new Point(0, verticalIncrement); 
                Point toPoint = new Point(horizontalLength, verticalIncrement); 
                HorizontalLines.Add(new Point[] { fromPoint, toPoint }); 
                Pen pen = new Pen(Brushes.Gray, .5); 
                dc.DrawLine(pen, fromPoint, toPoint); 
            } 
            largerIndicator += 1; 
            verticalIncrement += 10; 
        } 
        largerIndicator = 0; 

        //Draw Vertical Lines 
        for (int w = 0; w < widthIncrements + 1; w++) 
        { 
            if (largerIndicator == 5) 
            { 
                Point fromPoint = new Point(horizontalIncrement, verticalLength); 
                Point toPoint = new Point(horizontalIncrement, 0); 
                VerticalLines.Add(new Point[] { fromPoint, toPoint }); 
                Pen pen = new Pen(Brushes.DarkKhaki, .5); 
                dc.DrawLine(pen, fromPoint, toPoint); 
                largerIndicator = 0; 
            } 
            else 
            { 
                Point fromPoint = new Point(horizontalIncrement, verticalLength); 
                Point toPoint = new Point(horizontalIncrement, 0); 
                VerticalLines.Add(new Point[] { fromPoint, toPoint }); 
                Pen pen = new Pen(Brushes.Gray, .5); 
                dc.DrawLine(pen, fromPoint, toPoint); 
            } 
            largerIndicator += 1; 
            horizontalIncrement += 10; 
        } 
    } 
    drawScreen.AddVisual(visual, false); 
}

此绘图首先将屏幕大小除以十以获得每条网格线之间的间隔。我们通过 for 循环遍历每个间隔,并设置绘制所需的 fromPointtoPoint 绘制位置,以绘制从点 A 到点 B 的线。horizontalIncrementverticalIncrement 存储当前递增位置以绘制下一条线,当我们绘制线时,我们希望线延伸到屏幕的末端,因此我们使用 horizontalLengthvertialLength 来绘制到点。当每增加 5 条线时,画笔颜色将更改为 Dark Khaki。在遍历完所有垂直和水平增量后,我们将最终视觉添加到 DrawingCanvas

在此应用程序中,创建 Actor 的过程非常直接。应用程序遵循以下步骤来创建和绘制 Actor:

  1. 单击“创建 Actor”菜单项。
  2. 单击 DrawingCanvas 屏幕。
  3. 调用 DrawActor,并将一个视觉对象添加到 DrawingCanvas

这是“创建 Actor”菜单项的 XAML。

<ToolBar Height="25"
     Margin="0,18,2,0"
     Name="toolBarMain" VerticalAlignment="Top"
     Grid.Column="1">
  <Button Name="btnCreateActor" Content="Create Actor" />
</ToolBar>

设置 Actor 工具

private void btnCreateActor_Click(object sender, EventArgs e)
{
    Engine.Draw.CurrentTool = AIDraw.DrawingTools.Actor;
}

调用 DrawActor 将 Actor 添加到 DrawingCanvas 视觉对象中。

//Create an Actor
public void DrawActor(){
    visual = new DrawingVisual();

    using (DrawingContext dc = visual.RenderOpen())
    {
        dc.DrawEllipse(drawingBrush, drawingPen,
        fromMousePoint, 4, 4);
    }
    drawScreen.AddVisual(visual, true);
}

在此过程结束时,您的 Actor 将被添加到 DrawingCanvas 的视觉对象中并添加到 Screen

方形绘图是两者中最复杂的,因为它具有拖动正方形边缘到任意所需大小的动画效果,同时保持正方形形状。此绘图还使用临时视觉集合来获得其动画效果。创建正方形时遵循的流程:

  1. 单击“创建正方形”菜单项。
  2. 在屏幕上单击并拖动鼠标以绘制正方形。
  3. 通过放开鼠标左键退出绘图过程,并将正方形视觉对象添加。

这是 XAML 中的“CreateSquare”菜单项。

<ToolBar Height="25"
      Margin="0,18,2,0"
      Name="toolBarMain" VerticalAlignment="Top"
      Grid.Column="1">
   <Button Name="btnCreateSquare" Content="Create Square" />
</ToolBar>

设置正方形工具

private void btnCreateSquare_Click(object sender, EventArgs e)<
{
    Engine.Draw.CurrentTool = AIDraw.DrawingTools.Square;
}

调用 DrawSquare

//Create a Square
public void DrawSquare(Point ToPoint)
{
    if (cleanupFirstVisual)
        drawScreen.DeleteVisual(visual, true);

    visual = new DrawingVisual(); 

    using (DrawingContext dc = visual.RenderOpen())
    {
        Brush brush = drawingBrush;

        dc.DrawRectangle(null, drawingPen, new Rect(fromMousePoint, ToPoint));
    }

    drawScreen.AddVisual(visual, true);
    grabLastVisual = visual;

    if (!cleanupFirstVisual)
        cleanupFirstVisual = true;

    toMousePoint = ToPoint;
}

DrawSquareDrawActor 相比非常不同。这是因为现在我们必须添加临时视觉对象,以便在拖动正方形时,可以删除集合中的前一个视觉对象。如果我们不删除前一个视觉对象,每次移动鼠标时都会看到无数个正方形被绘制。

当鼠标左键按下且我们正在移动鼠标(以调整正方形大小)时,此事件会被激活。

private void drawingScreen_MouseMove(object sender, EventArgs e)
{
    Point position = MousePosition;
    if (drawsquare) 
    { 
        DrawSquare(MousePosition); 
    } 
}

现在,当所有这些发生时,我们将内容添加到 DrawingCanvas temporaryvisual 集合中并定期删除它们。但是,现在我们需要一个事件来处理鼠标左键抬起的情况,这样我们就可以将最终视觉添加到主视觉集合中,并且临时视觉集合将被完全清除。

private void drawingScreen_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{ 
    cleanupFirstVisual = false; 

    if (drawsquare) 
    { 
        drawsquare = false; 
        drawScreen.startTempVisual = false; 
        drawScreen.DeleteVisual(visual, true); 
        drawScreen.AddVisual(grabLastVisual, false); 
        CurrentTool = DrawingTools.Arrow; 
    } 
}

如果我们想在拖动正方形时取消绘制怎么办?我们只需检查鼠标右键单击事件即可删除当前正在绘制的视觉对象。

private void drawingScreen_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
{ 
    drawScreen.DeleteVisual(visual, true); 
}

现在,这是此应用程序中一些 WPF 控件的基本概述。

使用应用程序(在 WPF 中试验 IronPython)

本文介绍的应用程序主要基于在 Windows Presentation Framework 中试验 IronPython。它设置为您可以导入 Actor Python 脚本和 Scene Python 脚本。两者之间的区别在于,Actor 脚本仅初始化一次,而 Scene 脚本在每个帧中都初始化。在游戏循环中,Scene 脚本在每个帧中渲染,这会调用 DispatcherTimerDispatcherTimer 允许您控制场景渲染速度的间隔,例如每秒帧数。

我还包含了一些简单的 Python 代码示例,位于 zip 文件的 PythonSamples 文件夹中。我将简要解释这些示例的用法。

绘制视觉示例

DrawingVisual 文件夹中的 DrawingVisual 示例是一种非常简单、直接的在 Python 中使用 System.Windows.Media.VisualsSystem.Windows.Media.DrawingContexts 进行绘图的方法。

首先,让我们看看 C# 代码,看看 Python 完成绘图过程需要什么。

我们需要将 DrawingCanvas 类设置到 IronPython 的全局变量中。

DrawingCanvas drawScreen; 

ScriptEngine.Globals.Add("drawScreen", drawScreen);

C# 代码就到这里,现在来看 Python 代码。

我们需要声明我们的 Actor.py 代码。此代码将只初始化一次,与 Scene.py 文件不同。

//Actor.py
visual = System.Windows.Media.DrawingVisual()
context = System.Windows.Media.DrawingContext
pen = System.Windows.Media.Pen(System.Windows.Media.Brushes.Purple, 3)
brush = System.Windows.Media.Brush

brush = System.Windows.Media.Brushes.Blue

context = visual.RenderOpen()
context.DrawRectangle(brush, pen, System.Windows.Rect(Point(5,50), Point(400,400)))
context.Close()

drawScreen.AddVisual(visual, False)

笔刷和填充是 System.Windows.Media 命名空间提供的简单属性。视觉对象和上下文是绘制对象到 DrawingCanvas 的定义部分。在声明之后,我们启动 visual.RenderOpen() 来表示我们将开始创建我们的视觉对象。然后我们使用 context.DrawRectangle 通过输入声明的属性来初始化我们的新 Rectangle。在 DrawRectangle 声明之后,我们关闭上下文,以便我们可以停止绘制新的视觉对象。然后将视觉对象添加到我们的 drawScreen,即屏幕的 DrawingCanvas。我们还将 drawScreen.AddVisual 中的第二个参数设置为 false,因为我们不希望将视觉对象绘制为临时视觉对象。

Scene.py 文件留空,因为我们不需要在游戏循环中持续渲染视觉对象才能在屏幕上看到它。

现在,要查看绘图视觉对象在实际中的效果。启动应用程序,单击“创建 Actor”工具栏项,然后选择您希望创建 Actor 的位置。然后,单击“脚本”菜单项并选择“导入”。从 PythonSamples/DrawingVisuals 文件夹中选择 Scene.pyActor.py。完成此操作后,进入 TreeView,然后在 Scene 下,您应该会看到 Script 节点,在其下方应该有一个组合框。在组合框中选择 Scene.py,并对 Actor 执行相同的操作,选择 Actor.py。在 Scene 和 Actor 选择脚本后,单击工具栏中的 Play。您应该会看到一个框被绘制。

输入示例

PythonSamplesInput 文件夹包含一个关于在 IronPython 和 C# 之间添加键盘输入通信的示例。为了将键盘事件传递给 IronPython,我必须首先在 IronPython 的全局变量中创建一个 Key 变量。

Key input = new Key();
ScriptEngine.Globals.Add("key", input);

设置好之后,我们需要在 MainWindow 中创建一个键盘事件,以便在按下键盘时设置 ScriptEngine 中的 key 变量。

private void MainWnd_KeyDown(object sender, KeyEventArgs e)
{
    //Pass the key input to the ScriptEngine so it may be used
    AIEngine.ScriptEngine.Globals["key"] = e.Key;
}

此外,我们还需要跟踪何时释放键盘,以便知道何时发送 null 键。

private void MainWnd_KeyUp(object sender, KeyEventArgs e)
{
    //If no keys are being hit, send a null value to the PythonEngine
    AIEngine.ScriptEngine.Globals["key"] = null;
}

运行应用程序时,单击“创建 Actor”并选择一个 Actor 在屏幕上创建。

现在,由于我们所有的 C# 代码都在更新 ScriptEngine 中的 key 变量,剩下的就是 Python 代码了。

首先,让我们在 Actor.py 文件中声明我们的 Actor 的移动变量。

#Actor.py
actorPosX = 250
actorPosY = 250

这些变量将是 Actor 的默认位置。

让我们创建 Scene.py,其中将包含键盘输入检查。我们只需要一个 if 语句来检查我们想要的每个键,然后如果按下键,就递增 Actor 的位置。

#Scene.py

if (key == System.Windows.Input.Key.W):
    actorPosY -= 1

if (key == System.Windows.Input.Key.S):
    actorPosY += 1

if (key == System.Windows.Input.Key.D):
    actorPosX += 1

if (key == System.Windows.Input.Key.A):
    actorPosX -= 1

Actor9.ActorPosition = System.Windows.Point(actorPosX, actorPosY)

Actor9.ActorPosition 变量是 AIEditor.Core.AIActor 中的一个属性,用于设置 Actor 的位置并重绘视觉对象以反映新位置。如您所见,Actor9 变量并未在 AIActor 类中声明或设置。当我们在场景中创建 Actor 时,我们的 Scene TreeView 会使用新创建的 Actor 名称进行更新,该名称将类似于 Actor9、Actor14 等。所有这些 Actor 都已通过我们正常的 Actor 创建过程添加到 ScriptEngine.Globals 中。因此,您可能需要根据您的应用程序中 Actor 的名称来更新 Actor9 的名称。

您可能还想知道我们是如何在 Python 脚本中使用一些 System.Windows 命名空间的。PythonEngine 中有一个函数允许您加载程序集。

PythonEngine.LoadAssembly(Assembly assembly);

这使我们能够加载 System.Windows.Point

ScriptEngine.LoadAssembly(Assembly.Load("WindowsBase"));

将程序集添加到 Python 脚本中是一个巨大的好处,它将使您能够创建结构良好的 IronPython 应用程序。

还有一个命名空间导入函数。

PythonEngine.Import(string namespace)

现在回到主要话题。运行应用程序时,您应该首先从“创建 Actor”菜单项创建一个 Actor,然后通过单击“脚本”菜单项并选择“导入”,从 PythonSamples 文件夹导入 Actor.pyScene.py 脚本。完成此操作后,转到您的 Actors 节点,在其下方,应该有一个标题类似于 Actor#(# 是分配给 Actor 的数字)的 TreeViewItem。展开节点直到到达 Actor# 的 Script 的组合框,然后选择 Actor.py。完成此操作后,还必须在 Scene 父节点正下方的 Script 节点中选择 Scene.py 脚本。所有 Python 文件都选定后,单击“Play”菜单项。这将开始游戏循环并编译脚本。如果脚本中有错误,它还会弹出一个消息框。现在,按下键盘上的 W、S、A、D 键中的任何一个,您应该会看到您的 Actor 在场景中移动。

要查看绘图视觉对象在实际中的效果,请启动应用程序,单击“创建 Actor”工具栏项并选择您希望创建 Actor 的位置。然后,单击“脚本”菜单项并选择“导入”。从 PythonSamples/DrawingVisuals 文件夹中选择 Scene.pyActor.py。完成此操作后,进入 TreeView,然后在 Scene 下,您应该会看到 Script 节点,在其下方应该有一个组合框。在组合框中选择 Scene.py,并对 Actor 执行相同的操作,选择 Actor.py。在 Scene 和 Actor 选择脚本后,单击工具栏中的 Play,您应该会看到一个框被绘制。

© . All rights reserved.