我正在尝试使用 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() 的受保护方法,但我不确定这是否与我的问题有关。
[编辑]
自从我发布问题以来,我已经取得了一些进展。@world.java_send :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
所以,我的问题是如何在不创建 Position 类的实例的情况下访问 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()