Games X2 sprite graphics

developer_123

Active Member
Licensed User
Longtime User
I've done queries before regarding image quality for sprites and I don't see the light at the end of the road yet. I have tried what is indicated in indicated in the following link (https://www.b4x.com/android/forum/t...lking-character-solution.136579/post-864221), which does improve but not much, and also tried to reduce the imagen (.png) resolution pixels so that it remains at the same resolution according the relationship of the each patterns as the one configured in tiled (it also improves a bit but it is far from being a good image quality), so I started to review the source code of the X2 library regarding X2.ReadSprites and X2.GraphicCache.PutGraphic, in order to see if I could play around with any relevant variables that might come up with a solution to poor sprite quality.


If I think I'm right, these are the classes that capture the variables for creating the sprite graphics.

Inside X2Utils:

B4X:
Public Sub ReadSprites (Bmp As B4XBitmap, Rows As Int, Columns As Int, WidthMeters As Float, HeightMeters As Float) As List
    Dim res As List
    res.Initialize
    Dim scale As Float = mBCPixelsPerMeter * BmpSmoothScale
    Dim RowHeight As Int = Bmp.Height / Rows
    Dim ColumnWidth As Int = Bmp.Width / Columns
    For r = 0 To Rows - 1
        For c = 0 To Columns - 1
            Dim b As B4XBitmap = Bmp.Crop(ColumnWidth * c, RowHeight * r, ColumnWidth, RowHeight).Resize(WidthMeters * scale, HeightMeters * scale, False)
            Dim sb As X2ScaledBitmap
            sb.Bmp = b
            sb.Scale = BmpSmoothScale
            res.Add(sb)
        Next
    Next
    Return res
End Sub

Inside X2SpriteGraphicCache

B4X:
Public Sub PutGraphic(Name As String, X2ScaledBitmaps As List) As X2SpriteGraphicData
    Dim sb As X2ScaledBitmap = X2ScaledBitmaps.Get(0)
    Dim antialias As Boolean = sb.Bmp.Width / sb.Scale * sb.Bmp.Height / sb.Scale < 3000
    If Name.StartsWith(TempPrefix) Then antialias = False
    Return PutGraphic2(Name, X2ScaledBitmaps, antialias, 5)
End Sub

'Name - Key
'X2ScaledBitmaps - List or array with the ScaledBitmaps objects.
'AntiAlias - Whether to use antialiasing when rotating the images. Can have a large impact on performace.
'AngleInterval - Default value is 5 degrees.
Public Sub PutGraphic2(Name As String, X2ScaledBitmaps As List, AntiAlias As Boolean, AngleInterval As Int) As X2SpriteGraphicData
    #if Not (X2SkipLogs)
    Log($"New graphic: ${Name}"$)
    #end if
    Dim data As X2SpriteGraphicData
    data.Initialize
    data.Name = Name
    data.MapsOfCompressedBCs.Initialize
    data.OriginalBCs.Initialize
    data.LastUsed = DateTime.Now
    For Each sb As X2ScaledBitmap In X2ScaledBitmaps
        Dim bc As BitmapCreator
        bc.Initialize(sb.Bmp.Width, sb.bmp.Height )
        bc.CopyPixelsFromBitmap(sb.bmp)
        data.OriginalBCs.Add(bc)
        Dim m As Map
        m.Initialize
        Dim cbc As CompressedBC = bc.ExtractCompressedBC(bc.TargetRect, CBCCache)
        m.Put(0, cbc)
        data.MapsOfCompressedBCs.Add(m)
        data.SizeOfAllCompressed = data.SizeOfAllCompressed + cbc.mBuffer.Length
    Next
    data.AngleInterval = AngleInterval
    data.AntiAlias = AntiAlias
    cache.Put(data.Name.ToLowerCase, data)
    TotalSize = TotalSize + data.SizeOfAllCompressed
    Return data
End Sub

As I am not familiar with several of the functions that are used in these classes such as "CompressedBC" , "ExtractCompressedBC" and others, so, my interaction attempt to play with the code was not very successful.

I would appreciate any idea to know if from these lines of code of the X2 source library, it is possible to adjust some value that allows me to considerably improve the quality of the sprites and perhaps also of the drawn text when using the following code (the result is also very low quality)

B4X:
    Dim gname As String = X2.GraphicCache.GetTempName
    Dim ShapeSize As B2Vec2 = X2.GetShapeWidthAndHeight(template.FixtureDef.Shape)
    ShapeSize.MultiplyThis(X2.mBCPixelsPerMeter)
    Dim cvs As B4XCanvas = X2.GraphicCache.GetCanvas(ShapeSize.X / X2.BmpSmoothScale)
    cvs.ClearRect(cvs.TargetRect)
    Dim text As String = Score
    Dim r As B4XRect = cvs.MeasureText(text, ScoreFont2)
    Dim BaseLine As Int = ShapeSize.Y / 2 - r.Height / 2 - r.Top
    cvs.DrawText(text, ShapeSize.X / 2, BaseLine, ScoreFont2,  xui.Color_yellow, "CENTER")
    Dim sb As X2ScaledBitmap
    sb.Bmp = cvs.CreateBitmap.Crop(0, 0, ShapeSize.X, ShapeSize.Y)
    sb.Scale = 1
    X2.GraphicCache.PutGraphic(gname, Array(sb))
    bw.GraphicName = gname


To improve the images of the characters and elements of the Game I have tried a solution and it is to create imageviews dynamically for each object, and make these images follow the position of the objects, and using a bitmap array, load each image from each frame of the sprite .
The visual result of the quality of the imageviews is considerably much better than the sprites drawn by X2, but I think that should not be the solution since I suppose that in the first place it would consume more processor resources when making an ImageView for each object, and Secondly, because I think that the correct thing to do is to use the tools designed for this purpose.

I appreciate Any iddea!
 
Last edited:

developer_123

Active Member
Licensed User
Longtime User
Which platform?
B4i, B4J and B4A
Are you testing on real device?
Yes, in three cases, I'm testing in real devices. Samsung Galaxy S9, Iphone 6 and Iphone 11, and my Personal Computer.

Create a simple project with your graphics and upload it.
Below I link the test project link on the 3 Platforms. I used the Monster Track example. I created three images to illustrate the situation. The three images are composed of 2 objects created in the tiled, and an imageview.

I use in each case the same sprite images so that you can see the difference in quality.

In the first object created in the tiled I use a sprite with an image size of 1134 X 187 pixels. This is the case that shows the image on the screen with lower quality.

In the second object created in Tiled I use a sprite with a much smaller image size, equivalent to 224 X 37 Pixels. This case improves the image a bit. Although the file image loses a lot of detail, thanks to the reduction for the display on the screen the resulting image improves a bit. However, the quality is still quite low.

In the third option I used an imageview, to which I changed the image of each frame based on the currentframe of the Body created from Tiled. In this case I used each frame as an individual image in a .png file.
When loading each image with the "xui.LoadBitmapResize" instruction, I configured a width and a height of 100 (this value configures the dpi? Would there be a way to modify the equivalent of this value in the sprites used in X2?)

The result and the difference are obvious to the naked eye, and in this case the image quality is really good. This type of quality is what is really needed in the images created for games, since it does not matter if the logic of the Game is very interesting, if the quality of the images is poor the result will be inconspicuous and will give the impression of a product rustic finish.

I thank you for showing me the way to obtain the images on the screen that display a good visual quality, similar to the ImageViews Case.

https://wetransfer.com/downloads/9d...ce83330d920cfac4e18ee50520220601010205/f88fa2
 

Erel

B4X founder
Staff member
Licensed User
Longtime User
This change:
B4X:
ivForeground.Width = ivForeground.Width * xui.Scale
    ivForeground.Height = ivForeground.Height * xui.Scale
    X2.Initialize(Me, ivForeground, world) '<--- this is the original line in Game.Initialize
    ivForeground.Width = ivForeground.Width / xui.Scale
    ivForeground.Height = ivForeground.Height / xui.Scale
will only have an effect in B4A. xui.Scale is 1 on other platforms.

The main issue with the chicken sprite is related to the antialias effect that is inside the image. You will get better results with images without antialias (no semitransparent pixels in the edges).
 

developer_123

Active Member
Licensed User
Longtime User
The main issue with the chicken sprite is related to the antialias effect that is inside the image. You will get better results with images without antialias (no semitransparent pixels in the edges).
Erel, thank you very much for your answer. The sprite with semi-transparent pixels is the low-resolution one. Removing the semi-transparent pixels from the edges may correct the sprite's outline definition, but what about the rest of the image? is say the inner part of the image?
If you were able to see the example that I uploaded on Wetransfer, you can see that not only the edges of the images are blurred, but also the entire sprite. Seeing most games from the AppStore or Google Play stores, or App Gallery, the images of the animations or sprites are always displayed with an acceptably good quality and not so blurry.
Is it possible that I am ignoring some step or wrongly setting some variable in the sprite definition?

I really wouldn't worry so much about this issue if the loss of image quality wasn't so great. Literally that all definition of the sprite is lost with relatively small images.

I understand then, that there is no way to make sprites have a definition similar to ImageViews?

Is there any other alternative to obtain sprites in X2 that do not lose so much definition?
 

developer_123

Active Member
Licensed User
Longtime User
1. Comencemos con B4A.
¡OK!
2. Cargue la imagen del sprite que desea mostrar. Asegúrate de que no tenga bordes semitransparentes.
In fact, in the example that I had previously uploaded, one of the tiled objects already had a sprite like this. However, as we go step by step, I leave only visible in this case the object that uses the sprite without any semi-transparent pixels. The name of the sprite file is "sprite_walking_chicken.png" and it is 1134 X 187 pixels in size.
The result inside link below:
https://we.tl/t-ehR4wCwkI3
 

Erel

B4X founder
Staff member
Licensed User
Longtime User
Looks fine to me.

1654241159506.png
 

Attachments

  • Project.zip
    222.2 KB · Views: 314

developer_123

Active Member
Licensed User
Longtime User
O
Looks fine to me.

Of course, at the size you're giving the sprite it looks fine. However I mean the same images but a little smaller. Below are the screenshots of my Samsung Galaxy S9 phone (you can verify it, It is the same example of the first file shared in WETRANSFER of this same thread. In fact, in the same example you answered me in, if you reduce the object just a little bit directly from the Tiled, the same thing happens with the quality.).
Note that I intentionally place the car close to the chickens so you can see the proportion. Without a doubt, the IMAGEVIEW image is the target.

1654559451627.png



1654559394169.png
 
Top