Показать сообщение отдельно
Старый 30.10.2012, 07:39   #46
radiobutton
Бывалый
 
Регистрация: 16.09.2011
Сообщений: 863
Написано 257 полезных сообщений
(для 546 пользователей)
Ответ: Альтернатива скриптовику.

Вообщем. Пример для XNA.

Скрытый текст (вы должны войти под своим логином или зарегистрироваться и иметь 100 сообщение(ий)):
У вас нет прав, чтобы видеть скрытый текст, содержащийся здесь.

тут 3 файла.
hero.dll
script1.dll
game.exe

hero.dll это вспомогательная библиотека скомпилированная из кода ниже и содержащая класс персонажа с информацией о нем. Персонаж у нас это 2д квадрат 20 на 20. Информация это его положение и цвет.

using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace hero_namespace
{
    public class Hero
    {
        public int x, y, h, w;
        public Color clr;
        Texture2D hz_za4em;
        GraphicsDevice gd;
        SpriteBatch sb;

        public Hero(int x, int y, int h, int w, Color clr, GraphicsDevice gd, SpriteBatch sb)
        {
            this.x = x; this.y = y; this.h = h; this.w = w;
            this.clr = clr;
            this.gd = gd;
            this.sb = sb;
            hz_za4em = new Texture2D(gd, 1, 1);
            hz_za4em.SetData(new Color[] { Color.White });
        }

        public void draw()
        {
            sb.Begin();
            sb.Draw(hz_za4em, new Rectangle(x, y, w, h), clr);
            sb.End();
        }
    }
}


script1.dll это наш скрипт. Он создает одного персонажа и двигает его по окружности с радиусом 80.

using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using hero_namespace;

namespace script_namespace
{
    public class script1
    {
        Hero gamer1;
        int gamer1_x, gamer1_y;
        double gamer1_dx, gamer1_dy;
        GraphicsDevice gd;
        SpriteBatch sb;

        public script1(GraphicsDevice gd, SpriteBatch sb)
        {
            gamer1_x = 200; gamer1_y = 200;
            gamer1_dx = 80; gamer1_dy = 80;
            this.gd = gd; this.sb = sb;
            gamer1 = new Hero(gamer1_x, gamer1_y, 20, 20, Color.Blue, gd, sb);
        }

        public void update(GameTime t)
        {
            gamer1.x = gamer1_x + (int)(Math.Cos((t.TotalGameTime.TotalSeconds)) * gamer1_dx);
            gamer1.y = gamer1_y + (int)(Math.Sin((t.TotalGameTime.TotalSeconds)) * gamer1_dy);
        }

        public void draw()
        {
            gamer1.draw();
        }
    }
}


game.exe это наш скриптовый движок, который читает script1.dll с помощью рефлексии и выполняет соответственно.

using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using System.Reflection;

namespace test_script
{
    public class Game_test : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        public static SpriteBatch spriteBatch;

        MethodInfo method1, method2;
        object test_obj;

        public Game_test()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }

        protected override void Initialize()
        {

            base.Initialize();
        }

        protected override void LoadContent()
        {
            spriteBatch = new SpriteBatch(GraphicsDevice);
           
            Assembly assembly = Assembly.LoadFrom(@"script1.dll");
            Type type = assembly.GetType("script_namespace.script1");
            ConstructorInfo[] ci = type.GetConstructors();
            object[] param = { GraphicsDevice, spriteBatch };
            test_obj = ci[0].Invoke(param);
            method1 = type.GetMethod("update");
            method2 = type.GetMethod("draw"); 
        }

        protected override void UnloadContent()
        {

        }

        protected override void Update(GameTime gameTime)
        {
            if (Keyboard.GetState().IsKeyDown(Keys.Escape) == true) this.Exit();

            method1.Invoke(test_obj,new object[]{gameTime});
            base.Update(gameTime);
        }

        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.Black);
            method2.Invoke(test_obj, null);
            base.Draw(gameTime);
        }

    }
}


Компиляция первых двух библиотек производилась с помощью следующего кода:

using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using Microsoft.CSharp;

namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {

            string s = @"
using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace hero_namespace
{
    public class Hero
    {
        public int x, y, h, w;
        public Color clr;
        Texture2D hz_za4em;
        GraphicsDevice gd;
        SpriteBatch sb;

        public Hero(int x, int y, int h, int w, Color clr, GraphicsDevice gd, SpriteBatch sb)
        {
            this.x = x; this.y = y; this.h = h; this.w = w;
            this.clr = clr;
            this.gd = gd;
            this.sb = sb;
            hz_za4em = new Texture2D(gd, 1, 1);
            hz_za4em.SetData(new Color[] { Color.White });
        }

        public void draw()
        {
            sb.Begin();
            sb.Draw(hz_za4em, new Rectangle(x, y, w, h), clr);
            sb.End();
        }
    }
}
";
            Dictionary<string, string> providerOptions = new Dictionary<string, string>
         {
           {"CompilerVersion", "v4.0"}
         };

            
            CSharpCodeProvider provider = new CSharpCodeProvider(providerOptions);

            CompilerParameters compilerParams = new CompilerParameters { OutputAssembly = "D:\\hero.dll", GenerateExecutable = false };            
            compilerParams.ReferencedAssemblies.Add(@"C:\Program Files (x86)\Microsoft XNA\XNA Game Studio\v4.0\References\Windows\x86\Microsoft.Xna.Framework.dll");
            compilerParams.ReferencedAssemblies.Add(@"C:\Program Files (x86)\Microsoft XNA\XNA Game Studio\v4.0\References\Windows\x86\Microsoft.Xna.Framework.Graphics.dll");
            
            // Компиляция
            CompilerResults results = provider.CompileAssemblyFromSource(compilerParams, s);

            // Выводим информацию об ошибках
            Console.WriteLine("Number of Errors: {0}", results.Errors.Count);
            foreach (CompilerError err in results.Errors)
            {
                Console.WriteLine("ERROR {0}", err.ErrorText);
            }

            Console.Read();

            s = @"

using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using hero_namespace;

namespace script_namespace
{
    public class script1
    {
        Hero gamer1;
        int gamer1_x, gamer1_y;
        double gamer1_dx, gamer1_dy;
        GraphicsDevice gd;
        SpriteBatch sb;

        public script1(GraphicsDevice gd, SpriteBatch sb)
        {
            gamer1_x = 200; gamer1_y = 200;
            gamer1_dx = 80; gamer1_dy = 80;
            this.gd = gd; this.sb = sb;
            gamer1 = new Hero(gamer1_x, gamer1_y, 20, 20, Color.Blue, gd, sb);
        }

        public void update(GameTime t)
        {
            gamer1.x = gamer1_x + (int)(Math.Cos((t.TotalGameTime.TotalSeconds)) * gamer1_dx);
            gamer1.y = gamer1_y + (int)(Math.Sin((t.TotalGameTime.TotalSeconds)) * gamer1_dy);
        }

        public void draw()
        {
            gamer1.draw();
        }
    }
}";                       
            compilerParams = new CompilerParameters { OutputAssembly = "D:\\script1.dll", GenerateExecutable = false };
            compilerParams.ReferencedAssemblies.Add(@"C:\Program Files (x86)\Microsoft XNA\XNA Game Studio\v4.0\References\Windows\x86\Microsoft.Xna.Framework.Dll");
            compilerParams.ReferencedAssemblies.Add(@"C:\Program Files (x86)\Microsoft XNA\XNA Game Studio\v4.0\References\Windows\x86\Microsoft.Xna.Framework.Game.dll");
            compilerParams.ReferencedAssemblies.Add(@"C:\Program Files (x86)\Microsoft XNA\XNA Game Studio\v4.0\References\Windows\x86\Microsoft.Xna.Framework.Graphics.dll");
            compilerParams.ReferencedAssemblies.Add(@"D:\hero.dll");
            
            results = provider.CompileAssemblyFromSource(compilerParams, s);

            Console.WriteLine("Number of Errors: {0}", results.Errors.Count);
            foreach (CompilerError err in results.Errors)
            {
                Console.WriteLine("ERROR {0}", err.ErrorText);
            }

            Console.Read();
            Console.Read();
        }
    }
}


Смысл в том, что скриптовый движок знает только то, что в скрипте есть две функции - draw и update. Соотвественно он их и исполняет. А в них прописано создание объекта персонажа и его движение. Тоесть скрипт.

Возможно из-за криво указанных XNA сборок при компиляции у вас ниче не запустица если их адресс не будит совпадать с моим. =) Без указания полного пути у меня так и не получилось.

Можно компилировать код на c# из текстовых файлов в сборки IL в оперативную память. При запуске игры например. Автоматически.
(Offline)
 
Ответить с цитированием