SFML community forums

Help => Graphics => Topic started by: lid6j86 on July 06, 2014, 02:36:46 pm

Title: 2d scaling, pixel size vs. gameworld size
Post by: lid6j86 on July 06, 2014, 02:36:46 pm
So I was looking through and I guess i'm a little confused on the whole texture size/game world object size separation.

What is the most proper way to scale an image down to a specific unit size?  For instance say I made a 64x64 image that i want to be 1x1 game unit (those being soft numbers subject to change), do I have to say for every sprite created  Sprite.Scale(1/width,1/height)  (note* not sure that's the correct calculation, but it seems right off the top of my head)?

when I create a sprite it defaults the size to that of the texture itself, but i'd like to use game world units... or am I looking at this completely incorrectly?
Title: Re: 2d scaling, pixel size vs. gameworld size
Post by: zsbzsb on July 06, 2014, 02:58:53 pm
This belongs in the graphics section since it is not directly related to the binding, however...

You are mentioning several things here, original texture size, world unit measurement, target pixel size, and scaling.

The original texture size is the size of the texture you are drawing. In order to convert to anything else you need to know this value.

World units can make it easier to think of your game world. 1x1 world unit can represent a square tile or 1x5 could represent a platform your player is walking on.

Target pixel size is what each world unit is valued in pixels. Lets say for this example 1 world unit is equal to 64 pixels. So we have a platform that is 1x5 (world units), the actual size of this is 64x320 pixels. All SFML cares about is pixels so you need to be able to convert between world units and pixels.

World Units to Pixels
sf::Vector2f ratio(64, 64);
sf::Vector2f pixelSize( worldUnits * ratio );
 

Pixels to World Units
sf::Vector2f ratio(64, 64);
sf::Vector2f worldUnits( pixelSize / ratio );
 



Now to calculate the sprite scale. Remember that the scale is dependent on pixels and not world units.

sf::Vector2f pixelSize( { 64, 320 } );
sf::Vector2i textureSize( { 128, 640} );
sprite.setScale(pixelSize / textureSize);
 

Lets put it all together.

// 1x5 platform
sprite.setScale( toPixels(1, 5) / texture.getSize() );
 

I hope this clears it up for you.
Title: Re: 2d scaling, pixel size vs. gameworld size
Post by: lid6j86 on July 06, 2014, 03:05:15 pm
this example is exactly what i was looking for, thank you.  I was used to directly dealing with OpenTK, where you basically deal with GW units and the texture is pasted based on the whole (0,0) (0,1) (1,0) (1,1) thing.  Appreciate the help
Title: Re: 2d scaling, pixel size vs. gameworld size
Post by: lid6j86 on July 06, 2014, 06:45:23 pm
having some odd problems,  can get colored verticies to appear, but when i attempt to apply a texture it simply does not show up:

Vertex[] vArray = new Vertex[4];

            Texture tx = new Texture("flag.png");
            RenderStates rs = new RenderStates(tx);


            vArray[0].Position = new Vector2f(0, 0);
            vArray[0].TexCoords = new Vector2f(0, 0);

            vArray[1].Position = new Vector2f(0, 421);
            vArray[0].TexCoords = new Vector2f(0, 421);

            vArray[2].Position = new Vector2f(800, 0);
            vArray[2].TexCoords = new Vector2f(800, 0);

            vArray[3].Position = new Vector2f(800, 421);
            vArray[3].TexCoords = new Vector2f(800, 421);

         
         

            while(true)
            {
                rw.DispatchEvents();

                rw.Draw(vArray,0,4, PrimitiveType.TrianglesStrip , rs);
             


                rw.Display();
            }

anyone see what i'm doing wrong with the texture?

Edit: Just realized the addition to the post should have probably been its own post, apologies
Title: Re: 2d scaling, pixel size vs. gameworld size
Post by: Ixrec on July 06, 2014, 06:52:33 pm
Quote
Texture tx = new Texture("flag.png");
You're dynamically allocating a texture and then assigning the pointer to it to a texture, not a pointer to texture.  I don't think this should even compile, so I assume you typo'd.  Plus, Textures don't have a constructor taking a filepath. You need to use loadFromFile.

Either way, you shouldn't be doing any heap allocation or copying of textures without a good reason.  Just create one texture and load it from a file:
Quote
Texture tx;
if(!tx.loadFromFile("flag.png"))
    std::cout << "Error!" << std::endl;
Title: Re: 2d scaling, pixel size vs. gameworld size
Post by: Laurent on July 06, 2014, 06:57:02 pm
This is C# code, not C++.

And where is this code by the way?
Title: Re: 2d scaling, pixel size vs. gameworld size
Post by: lid6j86 on July 06, 2014, 07:06:22 pm
this was a sample code i was using to get a grasp of the difference between the c++ implementation and making a C# version with primitives.

It's all sitting within the main entry point, with everything declared above, and then rendered in the while loop
Title: Re: 2d scaling, pixel size vs. gameworld size
Post by: Laurent on July 06, 2014, 07:08:35 pm
Sorry, I didn't see the two lines that create the texture and the render states, they are lost in the initialization of the vertex array :P
Title: Re: 2d scaling, pixel size vs. gameworld size
Post by: lid6j86 on July 06, 2014, 07:15:51 pm
yea it's declared at the top, i set the coords, and use a while loop to render (all in the main loop).  if i dont try to add a texture it shows up fine, as soon as i add the texture is when it 'disappears'
Title: Re: 2d scaling, pixel size vs. gameworld size
Post by: Laurent on July 06, 2014, 07:36:12 pm
You never call rw.Clear().
Title: Re: 2d scaling, pixel size vs. gameworld size
Post by: lid6j86 on July 06, 2014, 07:43:31 pm
although that was quite dumb, still didn't cause anything to appear.  I would think that even without clear it would appear, it would just "smear" or do something else unexpected if it weren't static
Title: Re: 2d scaling, pixel size vs. gameworld size
Post by: zsbzsb on July 06, 2014, 08:00:06 pm
Does drawing a normal sprite work?
Title: Re: 2d scaling, pixel size vs. gameworld size
Post by: Laurent on July 06, 2014, 08:34:47 pm
Quote
            vArray[1].Position = new Vector2f(0, 421);
            vArray[0].TexCoords = new Vector2f(0, 421);

Should be vArray[1] ;)
Title: Re: 2d scaling, pixel size vs. gameworld size
Post by: lid6j86 on July 07, 2014, 12:18:54 am
so at this point (that was another dumb one) i have this:

 RenderWindow rw = new RenderWindow(new VideoMode(800, 600), "SFML test box");
 rw.Closed += rw_Closed;

Vertex[] vArray = new Vertex[4];

            Texture tx = new Texture("flag.png");
           
            RenderStates rs = new RenderStates(tx);


            vArray[0].Position = new Vector2f(0, 0);
            vArray[0].TexCoords = new Vector2f(0, 0);

            vArray[1].Position = new Vector2f(0, 421);
            vArray[1].TexCoords = new Vector2f(0, 421);

            vArray[2].Position = new Vector2f(800, 0);
            vArray[2].TexCoords = new Vector2f(800, 0);

            vArray[3].Position = new Vector2f(800, 421);
            vArray[3].TexCoords = new Vector2f(800, 421);

         
         
            while(true)
            {
                rw.DispatchEvents();
                rw.Clear();

                rw.Draw(vArray, 0, 4, PrimitiveType.TrianglesStrip, rs);

                rw.Display();
            }

        }

        static void rw_Closed(object sender, EventArgs e)
        {
            ((RenderWindow)sender).Close();
            Environment.Exit(0);
        }


    }

Title: Re: 2d scaling, pixel size vs. gameworld size
Post by: lid6j86 on July 07, 2014, 04:33:00 am
so interesting (perhaps odd?) update, i tried it again using vertexarray instead of individual vertices, and it is now displaying correctly.

I'm wondering:  I used quads instead of triangle fan, and i just went clockwise for vertex declaration... did that previous code have a logic error in the vertex  declaration?  I thought Triangle fan should be jagged? (i.e.  top left, bottom left, top right, bottom right, etc...)?

I'll try it again one more time with basic vertices and see if i can't reproduce the problem
Title: Re: 2d scaling, pixel size vs. gameworld size
Post by: lid6j86 on July 07, 2014, 04:44:24 am
I solved the problem.... C# structs strike again.  using the non-default constructor (declaring the position and texture when making a new vertex) it showed up perfectly.

Can someone explain to me more thoroughly why this behavior occurs?  What exactly is going on here?  it seems very strange that using the default constructor ruins everything. 

Is it because you can't initialize anything internally because you can't set a default constructor?  If that's the case, would it make sense in the .net model to add an Initialize method to all structs?  It's very counter intuitive as it sits right now (not that an initialize method is necessarily crystal clear, but i think far less confusing).
Title: Re: 2d scaling, pixel size vs. gameworld size
Post by: Joki on July 10, 2014, 12:03:04 am
Hello lid6j86.

This behaviour is a result of a somewhat poor design choice, of not implementing all structs as immutables in the .net bindings version of SFML. You want to only allow setting field values of value types during construction, either via using a parameterized constructor, or the initialization syntax, e.g.

var vertex = new Vertex { Position = new Vector2f(50, 50) };

It was correctly done with for example the operator overloads of Vertex2f, but not its fields. As a result, people will call the implicit default constructor and forget to assign values to some of the fields.

In your example, when you created a new Vertex using the default (non explicit) constructor, the color was intialized with rgba values (0, 0, 0, 0).

vArray[0].Position = new Vector2f(0, 0);
vArray[0].TexCoords = new Vector2f(0, 0);
vArray[0].Color = new Color(255, 255, 255, 255);   //fine

If all value types would have only read only fields, you would not be able forget to set any of its fields, so it is intialized with the default value of the type of the field. (Or, if you use the initialization syntax with curly brackets, your IDE will probably display all fields and you will not forget to assign a value to the color )
Title: Re: 2d scaling, pixel size vs. gameworld size
Post by: Laurent on July 10, 2014, 08:05:51 am
I'm still looking for a nice way to work around this very stupid limitation of C#, so thanks for your feedback.

Making all structures immutable is an interesting idea. However it would make the developer's life harder, since it's relatively common to have to change a vertex attribute after it has been created. Same for vectors.

By the way, if anyone wants to discuss further on this subject, please open a new thread on the .Net forum.
Title: Re: 2d scaling, pixel size vs. gameworld size
Post by: Joki on July 10, 2014, 07:47:16 pm
I have opened a new thread with that suggestion on the .net subforum, see here (http://en.sfml-dev.org/forums/index.php?topic=15770.0).  :)

Also it would not really make developers life harder, if you instead turn the fields into properties, and have the setter return a new instance of the modified struct. You might also use extension methods instead, or offer both versions to the users. :)