1
\$\begingroup\$

I use Artemis and LibGDX. I have the following two components which manipulate a texture:

  • ComponentTexture // Stores the texture
  • ComponentSource // Define a region for the texture, that will only be shown
  • ComponentSize // The size of the texture
  • ComponentMirror // Stores wether you want to flup on x and y axe
  • ComponentOrigin // The origin of the texture
  • ComponentPosition // The position of the texture
  • ComponentRotation // Rotation of the texture
  • ComponentScale // The scale of the texture

Than I have a System that requires the Texture and position component(Thats the minimum to draw a texture) and draw them to screen, before I render I check if it has some possible extra components.

@Override protected void process(Entity entity) 
{
    final ComponentTexture  componentTexture    = mComponentTextureMapper.get(entity);
    final ComponentSource   componentSource     = mComponentSourceMapper.getSafe(entity);
    final ComponentSize     componentSize       = mComponentSizeMapper.getSafe(entity);
    final ComponentMirror   componentMirror     = mComponentMirrorMapper.getSafe(entity);
    final ComponentOrigin   componentOrigin     = mComponentOriginMapper.getSafe(entity);
    final ComponentPosition componentPosition   = mComponentPositionMapper.get(entity);
    final ComponentRotation componentRotation   = mComponentRotationMapper.getSafe(entity);
    final ComponentScale    componentScale      = mComponentScaleMapper.getSafe(entity);

    // Texture
    final Texture texture = componentTexture.getTexture();

    // Source
    final Rectangle source;
    if(componentSource == null)
    {
        source = new Rectangle(0, 0, texture.getWidth(), texture.getHeight());
    }
    else
    {
        source = componentSource.getSource();
    }

    // Size
    final Vector2 size;
    if(componentSize == null)
    {
        size = new Vector2(texture.getWidth(), texture.getHeight());
    }
    else
    {
        size = componentSize.getSize();
    }

    // Mirror
    final boolean mirrorX;
    final boolean mirrorY;
    if(componentMirror == null)
    {
        mirrorX = false;
        mirrorY = false;
    }
    else
    {
        mirrorX = componentMirror.isMirrorX();
        mirrorY = componentMirror.isMirrorY();
    }

    // Origin
    final Vector2 origin;
    if(componentOrigin == null)
    {
        origin = new Vector2(0, 0);
    }
    else
    {
        origin = componentOrigin.getOrigin();
    }

    // Position
    final Vector2 position = componentPosition.getPostion();

    // Rotation
    final float rotation;
    if(componentRotation == null)
    {
        rotation = 0;
    }
    else
    {
        rotation = componentRotation.getRotation();
    }

    // Scale
    final Vector2 scale;
    if(componentScale == null)
    {
        scale = new Vector2(1, 1);
    }
    else
    {
        scale = componentScale.getScale();
    }

    mSpriteBatch.draw(texture, position.x - origin.x, position.y - origin.y, origin.x, origin.y, size.x, size.y, scale.x, scale.y, rotation, (int) source.x, (int) source.y, (int) source.width, (int) source.height, mirrorX, mirrorY);
}

I can create 5000 Entities with textures and a small rotation animation. I'm wondering about the efficiency of this method and how bad of a performance hit I will get from creating a lot of instances in the method. I plan to optimize this.

Does anyone have a good idea as to how I can get better performance from drawing textures?

How I can avoid the check for every component that the entity has?

Thanks for reading :D

\$\endgroup\$
3
\$\begingroup\$

You could create a single component to represent all of the information that a texture would hold. That way you aren't requesting 4 different components every time to go to draw something.

You listed having a transformation component. But you can use that component for all of the extra information you listed, rotations, flips, etc.. You can use a scale on the x or y in the transform that's negative as a "flipped" image and you just check the sign before you draw.

Only requesting two components and not worrying about "extra" components by storing all of that information in existing components would help. Also if you make one component that stores all of the "extra" information that a texture might have that would also reduce the overhead of component requests.

You can do more by passing an array or a container of the components you want to use to the function and looping over it rather than passing a single entity every time.

All of these things might make it faster but profiling would tell and if it's not a bottleneck now you shouldn't worry as much about it until it does become an issue.

\$\endgroup\$
1
\$\begingroup\$

First, echoing what Connor said. Breaking components up into a bunch of tiny attributes is a piece of bad advice I keep seeing repeated. You don't want mega-huge components that do 50 different things, no, but you absolutely do not want 50 micro components that all must be combined to do anything useful, especially as it just means your data is now spread all over the place instead of in one place. 1 component = 1 feature is a decent if somewhat loose guideline. Especially if you're sticking with an ECS, either going too large or too small negates any possible performance advantage (Java pushes you to go too small as you can't contiguously allocate user-defined types, unfortunately; C# is a much better choice for a Java-like language for games).

Second, you have mSpriteBatch.draw(texture, position.x - origin.x, position.y - origin.y, origin.x, origin.y, size.x, size.y, scale.x, scale.y, rotation, (int) source.x, (int) source.y, (int) source.width, (int) source.height, mirrorX, mirrorY); at the end there but I don't see it declared anywhere. The name indicates it's a member of... something. A single system maybe? Try to avoid using many different batches. It's hard to tell if you are or not.

\$\endgroup\$
  • \$\begingroup\$ No, I use only one SpriteBatch foll the full game. \$\endgroup\$ – user2933016 Dec 20 '13 at 11:36
0
\$\begingroup\$

OK, I made now, one Transform component:

Position, Origin, Rotation, Scale, Size

And a Texture component: Texture, Source, MirrorX, MirrorY

But it seems, that the performance is not better(5000 Entities are the maximum). You spoke from an profiler, I know what it is, but I have nether used one before. Knwo you a recommend profiler, which is easy to use ?

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.