Closed Divelix closed 6 years ago
@Jkly
I cannot reproduce the issue and unit tests cover a similar case. Which Kotlin version are you using? Would you mind posting the component classes and Engine
initiation code?
Just so you know, you can use engine.entity
without the add
block. add
is very similar to Kotlin's apply
. This should be an equivalent:
engine.entity {
with<DrawableComponent> {
sprite = Sprite(Texture("image1.png"))
}
with<TransformComponent> {
position.set(50f, 50f)
}
}
ktx-ashley
also uses Ashley 1.7.3 - make sure your dependencies are compatible.
Here is the full code:
class AshleyScreen(game: Main): KtxScreen {
private val engine = Engine()
override fun show() {
engine.add {
entity {
with<DrawableComponent> {
sprite = Sprite(Texture("image1.png"))
}
with<TransformComponent> {
position.set(50f, 50f)
}
}
}
engine.addSystem(RenderSystem())
engine.addSystem(MovingSystem())
}
override fun render(delta: Float) {
clearScreen(0.8f, 0.8f, 0.8f)
engine.update(delta)
}
}
// Components
class DrawableComponent(var sprite: Sprite): Component
class TransformComponent(val position: Vector2 = Vector2()): Component
//Systems
class RenderSystem: IteratingSystem(allOf(TransformComponent::class, DrawableComponent::class).get()) {
val batch = SpriteBatch()
val tansformComponent = ComponentMapper.getFor(TransformComponent::class.java)
val drawableComponent = ComponentMapper.getFor(DrawableComponent::class.java)
override fun processEntity(entity: Entity, deltaTime: Float) {
val t = tansformComponent[entity]
val d = drawableComponent[entity]
d.sprite.setPosition(t.position.x, t.position.y)
batch.begin()
d.sprite.draw(batch)
batch.end()
}
}
class MovingSystem: IteratingSystem(allOf(TransformComponent::class).get()) {
val transformComponent = ComponentMapper.getFor(TransformComponent::class.java)
override fun processEntity(entity: Entity, deltaTime: Float) {
val t = transformComponent[entity]
t.position.y += 1f
}
}
I use Ashley 1.7.3, kotlin 1.2.61 and option with engine.entity
throws same exception
@Divelix It's probably because createComponent is returning null because you don't have a no-arg constructor for DrawableComponent
and TransformComponent
.
The code for createComponent
returns null if it can't create the component via reflection:
public <T extends Component> T createComponent (Class<T> componentType) {
try {
return ClassReflection.newInstance(componentType);
} catch (ReflectionException e) {
return null;
}
}
I think arguably ktx-ashley should throw a more descriptive error if createComponent returns null, something like "Could not instantiate component $type - check the component has a no-arg constructor"
Oh, ok, I just added default values for both components and it works fine now:
class DrawableComponent(var sprite: Sprite = Sprite(Texture("image1.png"))): Component
class TransformComponent(val position: Vector2 = Vector2()): Component
It was really unobvious thing for me, thank you.
@Jkly Do you want me to add the null check or will you submit a PR?
@czyzby if you have time to do it now go for it! Otherwise I will create a PR later today.
Don't mind if you take this one. ;)
@Divelix Just so you know, Sprite
has a no-argument constructor that you can use in your case. You should also avoid creating Texture
objects on demand - they reload the image every time, which might quickly become an issue if you don't cache and reuse Texture
objects.
class DrawableComponent(var sprite: Sprite = Sprite()): Component
This is already addressed on the development branch and should be available soon in the snapshot release.
@Divelix As of 1.9.8-b5
, an exception with a meaningful message is thrown if you're missing a no-arg constructor. It should be available via Maven Central very soon.
I just started to exlore ktx, and stuck on Ashley module. When I add Entity to an Engine "traditional way" everything works fine:
But when I try to do the same in "ktx way" compiler throws an error:
Here is the error:
P.S. it complains on
engine.add
line