在JRuby中使用Artemis ESF



我正在尝试使用JRuby中的Artemis实体系统框架。下面是我试图转换为JRuby的Java代码:

import com.artemis.Aspect;
import com.artemis.Component;
import com.artemis.Entity;
import com.artemis.World;
import com.artemis.systems.EntityProcessingSystem;
public class MyGame {
    private World world;
    public MyGame() {
        world = new World();
        Entity e = world.createEntity();
        e.addComponent(new Position());
        e.addToWorld();
        world.setSystem(new ConsoleOutputSystem());
        world.initialize();
        for(int i = 0; i < 10; i++) {
            world.setDelta(60);
            world.process();
        }
    }
    public static void main(String[] args) {
        new MyGame();
    }
}
class Position extends Component {
    public int x;
    public int y;
    public Position() {
        this.x = 0;
        this.y = 0;
    }
}
class ConsoleOutputSystem extends EntityProcessingSystem {
    public ConsoleOutputSystem() {
        super(Aspect.getAspectForAll(Position.class));
        System.out.println("In system constructor");
    }
    @Override
    protected void process(Entity entity) {
        System.out.println("processing");
        System.out.println(entity.getUuid());
    }
}

当我执行这个命令时,输出是:

In system constructor
processing
9e8a24a8-b778-4926-b305-5a426a2f0ce1
processing
...

ConsoleOutputSystem.process()方法被调用十次。下面是我的JRuby代码:

require 'artemis.jar'
java_import com.artemis.Entity
java_import com.artemis.World
java_import com.artemis.Component
java_import com.artemis.Aspect
java_import com.artemis.systems.EntityProcessingSystem
class MyGame 
  attr_reader :world
  def initialize
    @world = World.new()
    e = @world.create_entity()
    e.add_component(Position.new())
    e.add_to_world()
    @world.set_system(ConsoleOutputSystem.new())
    #@world.initialize
    @world.java_send :initialize
    10.times do
      @world.set_delta(60)
      @world.process()
    end
  end
end
class Position < Component
    attr_accessor :x, :y
    def initialize ()
        @x = 0
        @y = 0
    end
end
class ConsoleOutputSystem < EntityProcessingSystem
    def initialize()
      puts 'in system constructor'
      super(Aspect.get_aspect_for_all(Position))
    end
    java_signature 'protected void process(Entity)'
    def process(entity)
      puts 'process'
      puts entity.getUuid
    end
end

MyGame.new()

输出为:

in system constructor

因此调用了ConsoleOutputSystem构造函数,但没有调用ConsoleOutputSystem.process()。我试着同时使用@world。Initialize和@world.java_send: Initialize输出是一样的。我尝试的另一件事是将java_signature 'protected void process(Entity)'添加到ConsoleOutputSystem.process()方法中。

Artemis包中的其他几个类都有名为initialize()的保护方法,但我不确定这是否与我的问题有关。

[编辑]

我已经取得了一些进展,因为我张贴的问题。初始化工作,并调用正确的方法。不起作用的是Aspect.get_aspect_for_all()。在Java中,Aspect.getAspectForAll()期望

Class<? extends Component> , Class<? extends Component>[]

作为参数。在JRuby中,这两个参数都不能作为Aspect.getAspectForAll()的参数:

Position
Position.class
Position.java_class
Position.java_proxy_class

唯一有效的方法是预先创建Position实例并将其类传递给Aspect.getAspectForAll():

@position_class = Position.new().getClass()

下面是它的工作代码,但感觉像一个拼凑:

require 'artemis.jar'
java_import com.artemis.Entity
java_import com.artemis.World
java_import com.artemis.Component
java_import com.artemis.ComponentType
java_import com.artemis.ComponentMapper
java_import com.artemis.Aspect
java_import com.artemis.systems.EntityProcessingSystem
class MyGame 
  attr_reader :world
  def initialize
    @world = World.new()
    e = @world.create_entity()
    e.add_component(Position.new())
    e.add_component(Velocity.new())
    e.add_to_world()
    @world.set_system(ConsoleOutputSystem.new(@world))
    @world.java_send :initialize

    5.times do
      @world.set_delta(60)
      @world.process
    end
  end
end
class Position < Component
    attr_accessor :x, :y
    def initialize ()
        @x = rand(100)
        @y = rand(100)
    end
end
class Velocity < Component
  attr_accessor :v
  def initialize()
    @v = 1.43
  end
end
class ConsoleOutputSystem < EntityProcessingSystem
  attr_accessor :position_class, :velocity_class
    def initialize(world)
      @position_class = Position.new().getClass()
      @velocity_class = Velocity.new().getClass()
      puts "@position_class: #{@position_class}"
      puts "Position: #{Position}"
      puts "Position.class: #{Position.class}"
      puts "Position.java_class: #{Position.java_class}"
      puts "Position.java_proxy_class: #{Position.java_proxy_class}"
      super(Aspect.get_aspect_for_all(@position_class, @velocity_class))
    end
    def process(entity)
      puts 'process'
      puts entity.getUuid
      position = entity.get_component(@position_class)
      velocity = entity.get_component(@velocity_class)
      position.x += 1
      position.y += 1
      velocity.v += 1
      puts position.x
      puts position.y
      puts velocity.v
      puts '----------'
    end
end
game = MyGame.new()

输出
puts "@position_class: #{@position_class}"
puts "Position: #{Position}"
puts "Position.class: #{Position.class}"
puts "Position.java_class: #{Position.java_class}"
puts "Position.java_proxy_class: #{Position.java_proxy_class}"

:

@position_class: org.jruby.proxy.com.artemis.Component$Proxy0
Position: Position
Position.class: Class
Position.java_class: com.artemis.Component
Position.java_proxy_class: org.jruby.javasupport.proxy.JavaProxyClass

所以,我的问题是如何得到org.jruby.proxy.com.artemis.Component$Proxy0而不创建位置类的实例?

[编辑2]

感谢Namek的回答,这里是有效的代码。它使用

@position_class = Position.java_proxy_class.java_class
@velocity_class = Velocity.java_proxy_class.java_class

所以我不需要创建一个JRuby类的实例来访问它的Java类:

require 'artemis.jar'
java_import com.artemis.Entity
java_import com.artemis.World
java_import com.artemis.Component
java_import com.artemis.ComponentType
java_import com.artemis.ComponentMapper
java_import com.artemis.Aspect
java_import com.artemis.systems.EntityProcessingSystem

class MyGame 
  attr_reader :world
  def initialize
    @world = World.new()
    e = @world.create_entity()
    e.add_component(Position.new())
    e.add_component(Velocity.new())
    e.add_to_world()
    @world.set_system(ConsoleOutputSystem.new(@world))
    @world.java_send :initialize

    5.times do
      @world.set_delta(60)
      @world.process
    end
  end
end

class Position < Component
    attr_accessor :x, :y
    def initialize ()
        @x = rand(100)
        @y = rand(100)
    end
end

class Velocity < Component
  attr_accessor :v
  def initialize()
    @v = 1.43
  end
end

class ConsoleOutputSystem < EntityProcessingSystem
  attr_accessor :position_class, :velocity_class
    def initialize(world)
      @position_class = Position.java_proxy_class.java_class
      @velocity_class = Velocity.java_proxy_class.java_class
      super(Aspect.get_aspect_for_all(@position_class, @velocity_class))
    end
    def process(entity)
      puts 'process'
      puts entity.getUuid
      position = entity.get_component(@position_class)
      velocity = entity.get_component(@velocity_class)
      position.x += 1
      position.y += 1
      velocity.v += 1
      puts position.x
      puts position.y
      puts velocity.v
      puts '----------'
    end
end

game = MyGame.new()

似乎你目前的问题在这里讨论:http://jira.codehaus.org/browse/JRUBY-672

试着让你的Java类像这样:

Position.java_proxy_class.java_class

最新更新