Skip to content
This repository has been archived by the owner on Sep 16, 2021. It is now read-only.

Visuals as components #286

Open
hammeron-art opened this issue Jun 15, 2015 · 11 comments
Open

Visuals as components #286

hammeron-art opened this issue Jun 15, 2015 · 11 comments

Comments

@hammeron-art
Copy link

Sprite being an entity is limiting.
I can't attach or detach the behavior of a sprite to existing entity or extend its functionality to a custom component.

The some goes for all visual classes.
We can't freely use more than one visual feature to the same entity, loop through its components to fetch them or create a new visual taking advantage of the system.

A base VisualComponent class with an "onDraw" method to be overridden would make the render system easier to customize and extend.

@Zielak
Copy link

Zielak commented Jun 15, 2015

You can make a component which has var sprite:Sprite and make use of onadded and onremoved to attach or detach that sprite from parent entity.

I'm not an expert in Luxe philosophy but that's how I would go about solving this problem.

@hammeron-art
Copy link
Author

Well, it's a workaround but is counterintuitive that's why I'm suggesting it.
This also will lead to memory waste as each Visual wrapped in a component has its own entity data instead of pointing to the data of the actual entity.

@ghost
Copy link

ghost commented Jun 15, 2015

iirc I read in the luxe docs that using an inheritance based programming approach or a component based one should be both valid options. Making sprite a component would make the first approach more difficult.

@hammeron-art
Copy link
Author

Can't see how this will make it more difficult.
You can still use inheritance for entities and components as well.
The engine physics system uses components, meshes are components, sprite animations too...

@ruby0x1
Copy link
Member

ruby0x1 commented Jun 15, 2015

hey,

Let's tackle this one bit a time,

  • Things are not finished yet, in general. There are still things to be desired around the Entity/Scene/Component stuff - so keep that in mind.
  • Marc was close in part - but what they were getting at is that, if Sprite was a component, you would have no choice but to use it as one, where now you have the choice to make a component with a sprite as Zielak suggested.

But all that is tertiary, the real logic behind all this follows.


To word this plainly, Sprite is an entity-quad-geometry-with-sprite-powers.

This is the most important point - Sprite is a specialization. That means when trying to shoehorn it into a generalization (or another specialization) - will be uncomfortable.

When looking at it, we don't want to be conflating "entity with geometry" to "is a sprite" - that is not the case here, and won't be (that's a better specialization to be had on it's own).

To be even more precise:
Sprite is a specialized entity.
It has a specialized geometry attached.
It then makes assumptions about itself, because it can.
It then gives you specialized usage patterns (.uv, .rotation_z).

For your point about SpriteAnimation being a component, that was where it landed right now - it is a Sprite specific specialization, it leans on the assumptions made by Sprite, knowing that it will be a quad geometry, and will be on a Sprite entity.

It is not a generic entity (that would be Entity)
It is not a generic quad geometry (that would be QuadGeometry or above it),
It is not even a general purpose geometry entity, that would be Visual*, one above it.

*(and visual has some work to go as its currently harbouring old quad identity).


So stepping back where does that leave us?

It means that Rendering-as-a-component is not the real concern here for me, it's the inverse, using a specialization in another paradigm. If you want to render stuff you create a geometry or use the onrender hooks that are there already (including their associated costs - I'd use geometry because it's more efficient that way).

  • How do we get to the paradigm you're after?

Specialize a component - specifically to what you want it to be.

Make a class SpriteComponent, store a QuadGeometry in it and give it sprite powers if you want them (.uv, .rotation_z, etc) and you're sorted. If you wanted non-quad geometry or inheritance there (not ideal in this placement) you could have VisualComponent too.

Along the way,
I did intend to add a set of components in this paradigm too.
It would require that the existing one be finished ideally, and that there isn't an overloaded sense of how to do the same basic task for tutorials and guides to remain helpful, and quick to jump in and get things moving.

Short term, the simpler imperative approach is preferred, because it doesn't require an existing set of knowledge to get something on the screen ("what is a component?") - it's just a class instance.

Hope that clarifies things a bit for everyone :)
And of course, I'm always open to contributions and discussion.
Thanks for the feedback.


minor notes:

  • The mesh, physics and other components are optional. They all have examples not using them as components - Only sprite animation which is specialized currently has that :)

@hammeron-art
Copy link
Author

Hi, thanks for the explanation.

Transformation data like rotation_z is more of a entity property rather than a sprite property to me.
My suggestion comes from the concept that sprites (or any visual) has nothing to do with any of the entity properties as a texture file has nothing to do in which position will be rendered in the screen so I can't see why make it a specialized entity.

Also because I was used to think of entity as generic objects and the components are the ones to make features.
For example the RenderSystem loop through all the VisualComponents rendering then, my custom EnemySystem loop through all the EnemyComponent updating IA, the PhysicsSystem loop through all RigidBoydComponents updating its entity transform and so on.
The Game update method loop through all systems update methods making everything very modular and extensible while still full supported by the engine itself just by inheriting from a base component and system class.

@JunoNgx
Copy link

JunoNgx commented Jun 21, 2015

The way I understand it, you would like to use multiple visual elements to display one single Entity. Correct me if I'm wrong.

If it happens to be the case, Luxe.draw might be your solution, from what I know of. Luxe.draw allows independently drawing of simple geometry or texture, whose data can be referred to Entity's data.

For example:

class DrawBox extends Component {

    override public function update(dt: Float) {
        Luxe.draw.ngon({
            r: 32,
            sides: 3,
            solid: true,
            color: new luxe.Color(1, 0.5, 1, 1),
            x: entity.pos.x,
            y: entity.pos.y
        });
    }

}

This component will draw a red triangle with a radius of 32 pixels using entity.pos (or the position of the entity it was attached to, in human's terms). Using this method, it is possible represent an Entity with as many visual elements as you need to, without resorting to luxe.Sprite or complicated extension.

However, as of this moment, Luxe.draw is very limited in its capability compared to its counterpart in other game engines (i.e. HaxePunk or Love2d), which is why I opened issue#275 (probably not a big problem for you, if you're using solely textures). The other problem is a slightly delay in more complicated draw, which I believe is the performance issue mentioned on devlog5, and I hope it will eventually be fixed.

A very detailed example using Luxe.draw can be found in \git\tests\features\draw.

@hammeron-art
Copy link
Author

@JunoNgx Not really.
There are some cases where I could use a visual definition without rely specifically in the base entity.
I could use it for a UI widget for example which maybe could work great as a child class of entity.
Set position relative to the object holding it instead of it having it own position seems more flexible to me.

I don't have problems at all coding a custom component. It's just a suggestion of a design decision to be explored by the engine.

Btw, I think you are creating a ngon each frame instead of batch it.
Usually do a lot of debug draw so was coding a draw system around the concept of "building blocks" like Love2D and HTML5 canvas.

@kevinresol
Copy link
Contributor

Instead of Sprite extends Visual extends Entity:

class Sprite extends Visual (extends Entity)
{
  // lots of sprite specific codes....
}

could it become Sprite is simply an Entity with a visual/sprite Component by default?

class Sprite extends Entity
{
  var visual:VisualComponent; // all the sprite specific codes moved into the component
  public var rotation_z(get, set); // forward the properties to the component
}

So at the end, new users can get things to display on screen with the same minimal effort as now. But that would also enable advanced users to compose their own class with the visual/sprite component?

@ruby0x1
Copy link
Member

ruby0x1 commented Jun 23, 2015

You're not unable to compose your own, as it is.
As mentioned above - you're not prevented from this pattern.
Make a SpriteComponent, compose it of a QuadGeometry.

@kevinresol
Copy link
Contributor

I am just trying to give some suggestions that makes Luxe easy to use for both new users and advanced users.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants