Бывалый
Регистрация: 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 в оперативную память. При запуске игры например. Автоматически.
|