Games Very very very simple Xui2d Test Project

ilan

Expert
Licensed User
Longtime User
ok, so this is my first very simple xui2d example project.
i am sure i am doing it very wrong because i still dont understand everything (or most) of xui2d but i just have to give it a chance and see how it works.

i have some difficulties that i would like to mention.

1, if i want to create a body from a shape i created in tiled i use the TileMap.CreateObject function. it is nice and looks simple but i really would like to create my own object parameters and load them to my game. this is how i do in my iTiled lib i created for b4i (https://www.b4x.com/android/forum/threads/itiled-for-ispritekit.84797/#content)

the cool thing is that i can create any type of parameters and just use them in my app with iTiled.

2, if i resize the window the touched x,y mouse position change so it looks like the X2.ScreenAABB.Height is not updated if i resize my form. is there a different value i can from x2 that is updated if the form is resized? i need to create a ball on the touched mouse x/y position.

3. i would like to draw something to the created body. but without tiled since i create then on the fly. i am sure it is explained in all those great x2 examples but i still need to figure that out :)

i must say that it really looks awesome and having 1 code working on ios and android is really a dream come true. so keep up the good work erel.

thanx, ilan
ps. i will keep investigating this lib and i am sure after a while it will be very simple to use :)

EDIT: new version added!
 

Attachments

  • B4J XUI2D Example 1.zip
    27.4 KB · Views: 572
  • B4J XUI2D Example 1 C.zip
    124.9 KB · Views: 591
Last edited:

ilan

Expert
Licensed User
Longtime User
1, ok after investigating a little bit, i saw that i dont need to remove the bodies once they are outside the screen, xui2d does it already. even though i have not checked in Tile "destroy if invisible" the body is destroyed if it is invisible and the question is why? sometimes i dont want to destroy bodies because i still need them like in a platformer game. so maybe it is a bug or i misunderstand something.

2, i am trying now to follow the xui2d concept and i set the graphic name in tiled but the ground is not drawn correctly. if u use debugdraw you can see that the body and the texture are not aligned correctly.
 

Attachments

  • B4J XUI2D Example 1 b.zip
    170.8 KB · Views: 561

Erel

B4X founder
Staff member
Licensed User
Longtime User
1. Bodies are only destroyed automatically if:
- You checked the 'destroy if invisible' option.
- Or based on the 'time to live' value if it is larger than 0.

Note that by default the tick event is not called for invisible bodies. This is controlled by 'tick if invisible'.

About your example:

1. The structure of the zip file is not the best structure. You should organize the folders as in the examples if you want to create a cross platform solution.
2. The issue with the alignment happens because the default 'angle interval' is 5. You can change it in Tiled.
However there is no reason not to set the angle interval to 1 for static bodies automatically. I've changed X2TileMap to do it.
 

ilan

Expert
Licensed User
Longtime User
1. Bodies are only destroyed automatically if:
- You checked the 'destroy if invisible' option.
- Or based on the 'time to live' value if it is larger than 0.

as far as i remember the 'destroy if invisible' option is unchecked and i also see that the bodies are destroied once they are outside the frame and not afte x ticks. so i am not sure if it is a coding mistake by me or a bug in reading the object properties. i dont have tiled installed in my work so i cannot open the file but you can check it.

1. The structure of the zip file is not the best structure. You should organize the folders as in the examples if you want to create a cross platform solution.

yes that make sense, i just try to understand how xui2d works and later i will do it like you say.

2. The issue with the alignment happens because the default 'angle interval' is 5. You can change it in Tiled.

ok i understand so each tick the image is updated and i can set the angle update value.

what about this?

2, if i resize the window the touched x,y mouse position change so it looks like the X2.ScreenAABB.Height is not updated if i resize my form. is there a different value i can from x2 that is updated if the form is resized? i need to create a ball on the touched mouse x/y position.
 

Erel

B4X founder
Staff member
Licensed User
Longtime User
as far as i remember the 'destroy if invisible' option is unchecked and i also see that the bodies are destroied once they are outside the frame and not afte x ticks. so i am not sure if it is a coding mistake by me or a bug in reading the object properties. i dont have tiled installed in my work so i cannot open the file but you can check it.
It is checked:

SS-2018-09-03_09.06.19.png


ok i understand so each tick the image is updated and i can set the angle update value.
Not exactly.
The 'angle interval' is an optimization feature. It is not relevant for static bodies and X2TileMap was modified to ignore this option for static bodies.
X2.GraphicCache creates the rotated graphics when needed and caches them. It rounds the angle based on the set interval. In most cases an interval of 5 looks good enough and is more efficient.

2, if i resize the window the touched x,y mouse position change so it looks like the X2.ScreenAABB.Height is not updated if i resize my form. is there a different value i can from x2 that is updated if the form is resized? i need to create a ball on the touched mouse x/y position.
The ScreenAABB doesn't change when you resize the window. The screen pixels to meter ratio changes.

The correct code is:
B4X:
Private Sub PanelForTouch_Touch (Action As Int, X As Float, Y As Float)
   If Action = PanelForTouch.TOUCH_ACTION_DOWN Then
       Dim template As X2TileObjectTemplate = TileMap.GetObjectTemplateByName(ObjectLayer, "circle")
       template.BodyDef.Position = X2.ScreenPointToWorld(X, Y)
       TileMap.CreateObject(template)
   End If
End Sub
This is exactly the purpose of X2.ScreenPointToWorld.
 
Last edited:

Erel

B4X founder
Staff member
Licensed User
Longtime User
I'm not updating the examples for now as I made a change that requires an update to all three platforms.

Currently if you follow the examples structure the X2 modules are shared between all examples and the game specific modules are shared between the platform specific projects.
This is nice however you still need to copy the files when they are being updated. Especially the Tiled json file.
The solution is to create a "shared files" folder and use a custom build action to copy the updated files. This line is added to all the Game classes:
B4X:
#CustomBuildAction: folders ready, %WINDIR%\System32\Robocopy.exe,"..\..\Shared Files" "..\Files"
Now we no longer need to worry about outdated files in different platforms.
 

ilan

Expert
Licensed User
Longtime User
Now we no longer need to worry about outdated files in different platforms

This is very handy and smart and will solve a lot of confusions.

Btw i must admit that the objectlayer properties you have built makes it very simple to load bodies to b4x.
is there a possibility to go through a list and upload only bodies that has a shape of ellipse?

does xui2d return a list of all available object in my tiled file so i can go through them and load only bodies i want to load?

like:

B4X:
for i = 0 to tileobjectlist.size -1
dim obj as tiledobject = tileobjectlist.get(i)
if obj.shape = "ellipse" then ...
next

thanx
 

Erel

B4X founder
Staff member
Licensed User
Longtime User
There are several ways to go over the templates or the created bodies.
For example you can create all bodies except of the circle with:
B4X:
Dim ol As X2ObjectsLayer = TileMap.Layers.Get(ObjectLayer)
For Each template As X2TileObjectTemplate In ol.ObjectsById.Values
   Select template.Name
       Case "circle", "hinge"
           'do nothing
       Case "ground"
           Dim bw As X2BodyWrapper = TileMap.CreateObject(template)
           bw.Body.GravityScale = 0 'do something special with the ground bodies.
       Case Else
           TileMap.CreateObject(template)
   End Select
Next

Create all bodies with circle shape:
B4X:
Dim ol As X2ObjectsLayer = TileMap.Layers.Get(ObjectLayer)
For Each template As X2TileObjectTemplate In ol.ObjectsById.Values
   If template.FixtureDef.Shape Is B2CircleShape Then
       TileMap.CreateObject(template)
   End If
Next

Note that there is no ellipse shape in box2d or XUI2D. Tiled ellipses are converted to circles.
 

ilan

Expert
Licensed User
Longtime User
thanks erel!

Note that there is no ellipse shape in box2d or XUI2D. Tiled ellipses are converted to circles.

yes i know that, i was surprissed when i created my box2d game and didnot find an allipse shape in box2d. btw circles are the fastest shape to calculate so if you can use circle instead of polygons or polyline it will make your performance much much better,
 

ilan

Expert
Licensed User
Longtime User
ok i am starting to learn xui2d and making small progress. i still struggle with graphics switching. i also would like to know how i can add more properties to my tiled object in tiled and then read them in my b4x code like

obj.getprop = "status"

please have a look at Event: PanelForTouch_Touch and tell me how i can switch the graphic for my "switch" body when i touch it.

anther issue i see is that the drawing of the lines for my ground doesn't look very nice. how can i get a nice smooth line instead of that very pixelated line?

thanx :)

btw: this is what i have until now :p. and if you are asking yourself what those switches should do then i want them to open doors so the balls will fall through them.

 

Attachments

  • B4J XUI2D Example 1b.zip
    377.9 KB · Views: 525
Last edited:

Erel

B4X founder
Staff member
Licensed User
Longtime User
Very nice!
I see several things that should be improved in the X2 framework.

1. There was an extra space in one of the graphic file names. This causes the program to crash in release mode. I will change X2TileMap to trim extra spaces.

2. X2BodyWrapper.TemplateCustomPropertieswill returns a Map with the custom properties set in Tiled. This allows you to add more properties.

3. There are several ways to change graphics. The simplest way is to set multiple "graphic files":

SS-2018-09-04_08.44.08.png


If 'switch frame interval' is set to 0 then the graphics will not change automatically.
This will allow you to manually change the current frame:
B4X:
Dim Sw As SwitchData = Switch.Tag
Sw.State = Not(Sw.State)
If Sw.State Then
   Switch.CurrentFrame = 1
Else
   Switch.CurrentFrame = 0
End If

4. Your code for finding the touched body is not very efficient. Especially if there will be many bodies. A more efficient solution based on box2d internal tree of AABBs:
B4X:
Sub TouchedSwitch(x As Float, y As Float) As X2BodyWrapper
   Dim aabb As B2AABB
   Dim vec As B2Vec2 = X2.ScreenPointToWorld(x, y)
   aabb.Initialize2(vec, vec)
   For Each body As B2Body In world.QueryAABBToMapOfBodies(aabb).Keys
       If body.FirstFixture.Shape.TestPoint(body.Transform, vec) Then
           Dim bw As X2BodyWrapper = body.Tag
           If bw.Tag Is SwitchData Then
               Return bw
           End If
       End If
   Next
   Return Null
End Sub
The second check is required as the first test doesn't consider the actual shape. Only the bodies AABB rectangle.

5. There was a bug in X2.GetBodiesFromContact that could caused the game to crash in an edge case where the body is deleted during the contact. Fixed.

6. About the non-smooth lines. There is currently a limit for the maximum graphic size that is being antialiased. The size is set to 300. I'm not sure that it shouldn't be changed to a much higher value. For now you should change the limit yourself in X2SpriteGraphicCache:
B4X:
Public const MAX_SIZE_FOR_ANTIALIAS As Int = 300 'change to 800
Note that it would have probably looked better in B4A and B4i.

7. The usage of tags is fine. However it would not have been required if you used a class for the balls and the switches. It is up to you.


A modified example is attached. It is based on the standard X2 classes without any modifications.

test.gif
 

Attachments

  • B4J XUI2D Example 1b.zip
    35.2 KB · Views: 535

ilan

Expert
Licensed User
Longtime User
If 'switch frame interval' is set to 0 then the graphics will not change automatically.
This will allow you to manually change the current frame:

awesome this is very simple and will do the work.

4. Your code for finding the touched body is not very efficient. Especially if there will be many bodies. A more efficient solution based on box2d internal tree of AABBs:

ok i understand, in spritekit it is very simple to get a body from a point. you can ask to get a list of all bodies that collide with your touched point and like this you can work with those bodies.

7. The usage of tags is fine. However it would not have been required if you used a class for the balls and the switches. It is up to you.

it is simpler for me to code like this. everything i know about coding i learned in forums like this. so object oriented coding is still a thing i need to investigate.


about the fixed x2 classes, do i need to update them ? or they are still not available ? (crash fixes,...)

ps: thank you erel for your detailed response. i will keep working on my example and see how i can modify it and add cool stuff to it.
 

Erel

B4X founder
Staff member
Licensed User
Longtime User
about the fixed x2 classes, do i need to update them ? or they are still not available ? (crash fixes,...)
They are included in the project I've uploaded.

ok i understand, in spritekit it is very simple to get a body from a point. you can ask to get a list of all bodies that collide with your touched point and like this you can work with those bodies.
I can add this code to X2Utils.
 

Erel

B4X founder
Staff member
Licensed User
Longtime User
The code becomes:
B4X:
Private Sub PanelForTouch_Touch (Action As Int, X As Float, Y As Float)
   If Action = PanelForTouch.TOUCH_ACTION_DOWN Then
       Dim worldpoint As B2Vec2 = X2.ScreenPointToWorld(X, Y)
       For Each TouchedBody As X2BodyWrapper In X2.GetBodiesIntersectingWithWorldPoint(worldpoint)
           If TouchedBody.Tag Is SwitchData Then
               Log("YOU TOUCHED A SWITCH")
               Dim Sw As SwitchData = TouchedBody.Tag
               Sw.State = Not(Sw.State)
               If Sw.State Then
                   TouchedBody.CurrentFrame = 1
               Else
                   TouchedBody.CurrentFrame = 0
               End If
               Return
           End If
       Next
       Dim template As X2TileObjectTemplate = TileMap.GetObjectTemplateByName(ObjectLayer, "ball")
       template.BodyDef.Position = worldpoint
       CreateBall(template)
   End If
End Sub
 
Last edited:

Erel

B4X founder
Staff member
Licensed User
Longtime User
just have a curiosity: what AABB is?
It is explained in section 4.5: http://box2d.org/manual.pdf
AABB - axis aligned bounding boxes

Each body (actually fixture) has a bounding box and these boxes are organized in a tree. This allows to quickly find all bodies that intersect with a point or another box.
 
Top