Games Some notes to better understand the XUI2D examples

fredo

Well-Known Member
Licensed User
Longtime User
During my familiarization with XUI2D it became necessary for me to get to know the elements and mechanisms involved.

For the research the objects in all "Game.bas" modules of the examples were viewed simultaneously.
All examples have been extracted to a directory, so each example is in its own folder.

1. Enter "game.bas" as search term in the file explorertileset

2. Mark all files "game.bas" of the hit list

3. Right click, click on context menu "Edit with Notepad++

4. In NP++ enter "X2BodyWrapper" (or your searchword) in find dialog

5. Click "Find ALL in ALL open documents"

6. See hit list in the lower area


A click in the hit list navigates directly to the appropriate location in the document in question.

2019-07-20_12-03-50.png


You can even copy the result list and analyse it further so you might find out how they create bodies in all the examples:

B4X:
TileMap.CreateObject(TileMap.GetObjectTemplate(ObjectLayer, 3))
TileMap.CreateObject(Template)
TileMap.CreateObject2ByName(ObjectLayer, "power")
TileMap.CreateObject2ByName(ObjectLayer, "ship explosion")
X2.CreateBodyAndWrapper(bd, Null, "laser")
X2.CreateBodyAndWrapper(def, Null, "line")
Cross reference of most used game-subs in all examples:

2019-07-23_12-40-03.png

The notes
Further down are my notes compiled from several sources (links at end of text), which might help others to better understand whats going on in Erel’s examples.

It is not a fully-fledged guide to create a game from scratch. But maybe it can make it easier to get started and get a clearer overview of the jungle of seemingly unmanageable information.

xui2dinfo0.png
If something should be significantly wrong, I would be grateful for concrete hints what would be the correct way.


A quote from Erel from another place in the forum:
"Please ask as many questions as you have (each one in its own thread). This will help other developers to find answers in the future."

Intro

XUI2D is a cross platform framework to create games that consist of a world, actors and physically correct behavior.​

The “Example Pack” has several different examples that show what can be achieved with little effort: https://www.b4x.com/android/forum/threads/xui2d-example-pack.96454/

2019-07-16_12-51-16.png


XUI2D connects a physical engine to a graphical engine and has many game-relevant features like Bodies, Fixtures, Shapes, Sounds, Collisionsensors, ...​

image012.jpg

Components involved

image013.png

The B4X-library “x2.b4xlib” is available here: https://www.b4x.com/android/forum/threads/b4x-x2-xui2d-XUI2D-game-engine.95208/

Basic concepts

There are two realities that need to work together
image014.png


XUI2D helps us to position the graphics on the correct position.

Since XUI2D has no idea, what pixels are we have to convert pixel units to XUI2D units.

After XUI2D has calculated new positions we have to convert XUI2D units to pixel units.

Graphics then can be drawn with the new location information.​


Raw code structure of a game

All setup and drawing is done in the B4X code module “Game”.​

Prepare

image015.png

Draw

image016.png

x2seq.png



B4X Code modules involved

Erel: "Don't be confused from all the X2 modules. Treat them as a library. Most games are implemented in the Game class."


The B4X Main module contains only the invocation of the game class “gm” and listening on key events. (Erel: "The main activity is not relevant as it is not cross platform. The main place for your code is the Game class.")​

B4X:
Sub AppStart
    gm.Init
    gm.StartGame

Sub gmh_KeyPressed(Keycode as string)
    Select Keycode
            Case "Left"
                gm.LeftDown = State

The B4X Game class contains most of the code that makes up the game.

B4X:
Sub Init
    WorldInit
    GraphicsInit
    SoundInit
    ...
Sub StartGame
    TileMapInit
    Build layers
    CreateCharacters
    CreateObjects
    X2.Start
    ...
B4X classes can be used to represent characters and their behavior.
image034.png
image036.png



As developers, we must sooner or later put the conceptually understood facts into practice.

To do this, files must be created in the correct directory and the objects prepared, assessed and suitable values assigned in the IDE.

The X2 examples offer a good basis to look for best practices.

Folder Structure
Erel's "Cross platform tips" https://www.b4x.com/android/forum/threads/xui2d-cross-platform-tips.96815/#content explain the recommended way to organize the projects.
It is very simple and will help to add more platforms in the future.

"Shared Files"?
2019-07-19_07-10-55.png


The simplest way to create a new project is to make a copy of one of the examples inside the X2 folder. As the references are relative all the references will be correct and the projects will be ready.


XUI2D elements
Whereas XUI2D contains a wrapper for the famous jbox2d engine, JBox2d itself is a Java port of the C++ physics engines LiquidFun and Box2d.

JBox2d doesn't understand computer graphics and pixels. It is simply a library that picks up numbers and spits out more numbers.

But XUI2D brings calculation results and your graphics together in a meaningful manner.

image021.png


Everything exists and happens in the...

World

Stores lists of every element in the world.

Knows everything about the coordinate system of the world (not your pixel coordinates!).

Manages the physics simulation.
The mechanisms of XUI2D essentially work with 4 types of objects:

Bodies

The primary element.

They have location, velocity, rotation, reaction to forces but they have no shape or material attributes.​
Shapes

Shapes are all centred on collisions.

They define the borders and the extent of the Bodies (collision geometry) and thus the interactions with other Bodies/forms.​
Fixtures

Holds a single shape and attaches it to a Body. It also contains collision filtering flags, backpointer to the parent body and a sensor flag.

They provide material attributes to a Body like material density, elasticity, friction.​
Joint

Acts as a connection between two Bodies (or between a Body and the world itself).

Physical actions are manipulated by:
Vec2

Forces and motion are described by vectors.​

B2World


This is the main object (from XUI2D) in which everything happens.

At first you might think that the XUI2D physics engine only deals with gravity and levers.

But the world contains all the things (Bodies and fixtures) that are involved as objects in the game at any given time.

The world object knows the coordinate space and has a list of all elements (world has Bodies, Bodies have fixtures, fixtures have shapes).

The world object manages all allocations for the objects it contains.

But beware! The XUI2D world coordinate system (left) is different from the computer graphics coordinate system (right).​

2019-07-12_14-13-18.png

(Below is a little clarification from Erel about he coordinate system)
XUI2D helps us to convert between those systems back and forth.

The following things can be done with the world:

Specifying gravity

Adjust the physics simulation

Find fixtures in a specific region

Throw a beam and find crossed objects.

The world object will be connected to the screen via an imageview ivForeground in Layout “…”.

The connection between the world object and the imageview is done by X2.Initialize(…)
B4X:
Sub Class_Globals
Public world As B2World
Public X2 As X2Utils
Private ivForeground As B4Xview
…

Sub Initialize (Parent As B4XView)
Parent.LoadLayout("1")
world.Initialize("world", world.CreateVec2(0, -20))
X2.Initialize(Me, ivForeground, world)
Dim WorldHeight As Float = 14
Dim WorldWidth As Float = WorldHeight * 1.3333
X2.ConfigureDimensions(world.CreateVec2(WorldWidth / 2, WorldHeight / 2),_
WorldWidth)
…


The world object raises events based on collissions.


B4X:
Sub World_BeginContact (Contact As B2Contact)
       Dim Bodies As X2BodiesFromContact = X2.GetBodiesFromContact(Contact, "mario")
       …
Sub World_PreSolve (Contact As B2Contact, OldManifold As B2Manifold)
       Dim BodyA As X2BodyWrapper = Contact.FixtureA.Body.Tag
       CheckMarioCollisions (Contact, X2.GetBodiesFromContact(Contact, "mario"))
       …
Angles in X2
... are handled in Radians.

0 corresponds to "East". The angle increases counter-clockwise.

512px-Degree-Radian_Conversion.svg.png

A conversion to degrees is integrated in x2.
(Example from the "Newton Cradle" example:
B4X:
Dim Rope As CompressedBC = X2.GraphicCache.GetGraphic2("rope", 0, X2.B2AngleToDegrees(ATan2(vec.y, vec.x) + cPI / 2), False, False)


X2BodyWrapper


Bodies
are the primary elements in XUI2D that live within the world. But Bodies are not the things we see on screen. Bodies are invisible objects that carry properties. What we see and what collides are shapes.

Bodies move around and experience forces or are static at a specific position (ground or wall).

The Bodies itself will keep track of its own location. No external lists necessary.

Bodies have no geometry and are nothing physical.

They have Shapes attached to them so collisions can be calculated.

B4X:
Sub Class_Globals
       Public Const ObjectLayer As String = "Object Layer 1"
       …

Sub StartGame
       TileMap.Initialize(X2, File.DirAssets, "mario 1.json", ivBackground)
       TileMap.PrepareObjectsDef(ObjectLayer)
       Dim bw As X2BodyWrapper = TileMap.CreateObject(                                           TileMap.GetObjectTemplate(ObjectLayer,  3))    '3 = mario id
bw.Body.BodyType = bw.Body.TYPE_DYNAMIC
mMario.Initialize(bw)
…

Sub CheckMarioCollisions
mMario.bw.Body.ApplyLinearImpulse(X2.CreateVec2(0, 20 * mMario.bw.Body.Mass), _
                mMario.bw.Body.WorldCenter)
…

To create or remove a Body we call functions of the XUI2D world to do this for us.

Once Bodies have been created, you can apply some properties to them such as location. But remember to tell XUI2D the value in world coordinates and not in graphics coordinates!

A Body can be one of three Bodytypes:

Dynamic. This will be used most often. A “fully simulated” Body. A dynamic Body moves around the world, collides with other Bodies, and responds to the forces in its environment.

Static. A static Body is one that cannot move (infinite mass). Static Bodies are used for fixed platforms and boundaries.

Kinematic. A kinematic Body can be moved manually by setting its velocity directly. A user-controlled object would be a kinematic Body. Note that kinematic Bodies collide only with dynamic Bodies and not with other static or kinematic ones.
If a Body in motion should slow down over time, you can apply friction or damping.
B4X:
bw.Body.LinearDamping = 0.9
Bodies that move very fast can have a bullet flag set, so that collision detections are more precise.
B4X:
bw.Body.Bullet = true
But! A Body cannot exist on its own in the world. It must be attached to a shape with a fixture.

B4X:
Sub CreateMarioLegs
       Dim rect As B2PolygonShape
       rect.Initialize
       rect.SetAsBox2(0.45, 0.05, x2.CreateVec2(0, -x2.GetShapeWidthAndHeight(bw.Body.FirstFixture.Shape).y / 2 + 0.05), 0)
       Dim f As B2Fixture = bw.Body.CreateFixture2(rect, 0.1)
       f.Friction = 1

The job of the shape is to keep track of all the necessary collision geometry attached to a Body.

A shape also has several important properties that affect the Body’s motion:
  • There is density, which ultimately determines that Body’s mass.
  • Shapes also have friction and restitution (“bounciness”) which will be defined through a fixture.
Shapes can even be created and destroyed on the fly while the game is running.
  1. Create body
  2. Define shape
  3. Create fixture
  4. Assign shape to fixture
  5. Attach shape to Body
One Body can have multiple fixtures attached to it, and the center of mass of the Body will be affected by the arrangement of its fixtures. When two Bodies collide, their fixtures are used to decide how they will react.

XUI2D separates the concepts of Bodies and shapes into two separate objects. So you can attach multiple shapes to a single Body in order to create more complex forms.​

"Center of body" and "center of mass"
http://box2d.org/manual.pdf , page 29, "Position and angle"
The body definition gives you the chance to initialize the position of the body on creation.

This has far better performance than creating the body at the world origin and then moving the body.

Caution
Do not create a body at the origin and then move it. If you create several bodies at the origin, then performance will suffer.
A body has two main points of interest:

  • The first point is the body's origin. Fixtures and joints are attached relative to the body's origin.
  • The second point of interest is the center of mass. The center of mass is determined from mass distribution of the attached shapes or is explicitly set with b2MassData.
Much of Box2D's internal computations use the center of mass position. For example b2Body stores the linear velocity for the center of mass.

When you are building the body definition, you may not know where the center of mass is located. Therefore you specify the position of the body's origin.

You may also specify the body's angle in radians, which is not affected by the position of the center of mass. If you later change the mass properties of the body, then the center of mass may move on the body, but the origin position does not change and the attached shapes and joints do not move.

B4X:
bodyDef.position.Set(0.0f, 2.0f); // the body's origin position.
bodyDef.angle = 0.25f * b2_pi; // the body's angle in radians.
A rigid body is also a frame of reference. You can define fixtures and joints in that frame. Those fixtures and joint anchors never move in the local frame of the body.​


Collisions
Collisions are a central element in Box2d and therefore also in X2. All interactions are registered by collisions and handled by events.

So that every collision between objects does not have to be evaluated individually (time requirement!), rules can be defined. In the end, it all boils down to "who ignores whom".

The rules are defined by the interaction of the properties "The object belongs to a category" and "The object reacts to certain categories".

Erel presented the interaction in this detailed example: https://www.b4x.com/android/forum/threads/xui2d-to-collide-or-not-to-collide.97144/


2019-08-05_07-07-18.png


To simplify the calculation of the mask bits, @Gunther has introduced a tool here: https://www.b4x.com/android/forum/t...-masks-calculator-collision-filtering.103320/
In this blog post there are more hints, among others about groups:
https://www.aurelienribon.com/post/2011-07-box2d-tutorial-collision-filtering


X2Utils

This is the main class with the game loop implementation and various utility methods.

You can't conclude "best practices" with this yet, but you get an idea of what x2utils is used for.

B4X:
X2.AddFutureTask(Me, "Create_Bird", 1500, Null)
X2.AddFutureTask(Me, "Show_GetReady", 0, Null )
X2.ConfigureDimensions(X2.CreateVec2(WorldWidth / 2, WorldHeight / 2), WorldWidth)
X2.GraphicCache.GetGraphic2("fried", 0, 0, True, False)
X2.GraphicCache.PutGraphic("bg", Array(X2.LoadBmp(File.DirAssets, "bg.png", WorldWidth, WorldHeight, False)))
X2.GraphicCache.PutGraphic("bug", Array(all.Get(0), all.Get(1)))
X2.GraphicCache.PutGraphic("explosion", X2.ReadSprites(xui.LoadBitmap(File.DirAssets, "explosion_atlas.png"), 3, 3, TruckWidth, TruckWidth))
X2.GraphicCache.PutGraphic("fried", Array(X2.LoadBmp(File.DirAssets, "fried.png", 0.5, 0.5, True))).VerticalSymmetry = True
X2.GraphicCache.PutGraphic2("rope", Array(X2.LoadBmp(File.DirAssets, "rope-34141_1280.png", 0.1, 1, True)), True, 5)
X2.GraphicCache.WarmGraphic(Truck.GraphicName)
X2.ImageViewResized
X2.LastDrawingTasks.Add(X2.MainBC.AsyncDrawLine(bcpoint.X, bcpoint.Y, HookPointRight.X, HookPointRight.Y, PulleyBrush, 5))
X2.mWorld = vWorld
X2.SetBitmapWithFitOrFill(ivBackground, xui.LoadBitmapResize(File.DirAssets, "Sky.jpg", ivBackground.Width / 2, ivBackground.Height / 2, False))
X2.SlowDownPhysicsScale = 5
X2.SoundPool.AddSound("laser", File.DirAssets, "pew.wav")
X2.SoundPool.StopMusic
X2.Start
X2.Stop
X2.UpdateTimeParameters
X2.UpdateWorldCenter(ClampScreenCenter(X2.ScreenAABB.Center.X - dx))
X2.UpdateWorldCenter(TileMap.MapAABB.Center)
X2.UpdateWorldCenter(X2.CreateVec2(Tank.Body.Position.X, X2.ScreenAABB.Height / ZoomFactor / 2))

2019-07-22_18-26-44.png


X2TileMap

Every game consists of countless graphic elements that move on the screen or are in the way as "things of the world". Since this would be too complex from a programming point of view, the concept of tiled maps is used.

Maps are laid out in a grid pattern and stacked as layers of foils.

Maps can easily be created with the famous "Tiled" MapEditor: https://www.mapeditor.org/

Basic work- and data flow
(1) In the editor "Tiled" a new "Tilemap" is created and stored in the format ".json" in the own project folder "Shared Files" (7).

(2) In the "Layers" window there is already a "Tile Layer 1" on which our map is drawn. In the saved json file this layer is saved with its properties.

(3) After downloading a tileset graphic file into the folder "Shared files" (7), you create a "New tileset" with the help of "Browse..." and select the tileset graphic file there. In the json file only the name and some properties of the graphic file are stored. In the code later X2 uses some of them.

(4) You draw your playing surface with stamps selected on the tileset. The resulting bitmap is stored in a special format within the json file.

(5) In the Layers window you create an "Object Layer 1" to place objects on it.

(6) You can place as many objects as you like. However, these are only data points that are filled with life later in the code by the X2 framework.

(7) As already mentioned, the graphic files and the json files are in the "Shared files" folder. When compiling, the files are automatically copied into the "Files" folder of B4J, B4A and B4i.

(8) The drawn map is imported into the code by reading the created json file through the X2 framework.

2019-07-31_17-21-31 - Kopie.png


The most common layers are the Tile Layer and the Object Layer. There is also an Image Layer for including simple foreground or background graphics.

Tile Layers
They provide an efficient way of storing a large area filled with tile data.
The data is a simple array of tile references. The information needed to render each tile layer is stored with the map.
Object Layers
They can store many kinds of information that would not fit in a tile layer.
Objects can be Rectangle, Ellipse, Point, Polygon, Polyline, Tile, Text.
They can be freely positioned, resized and rotated.
They can also have individual custom properties (see "objecttypes.json").
Objects are identified by id.
Objects can be named (multiple objects can have the same name!).
Objects can be given a type, to customize properties for this object type.
Object types
Note that in B4X there is a file named "objecttypes.json" in the Files tab. This is a new file that is required when using X2TileMap. It holds the objects custom properties defaults. You can import it to Tiled with "View - Objects Type Editor", "File - Import".
The edited Tilemap is to be exported as ".json" file into the "Shared Files" folder of our B4X project.

X2TileMap allows loading those map files (the "mario 1.json" file) and the additional informations attached to each layer into the B4X game.
Drawing is done automatically by calling DrawScreen or if you need more control you can call Draw and pass the required area.

X2TileMap only draws the currently visible tiles.
B4X:
Public Sub Tick (GS As X2GameStep)
    mMario.Tick(GS) 'run first as mario updates the world position
    TileMap.DrawScreen(Array("Tile Layer 1", "Tile Layer 2"), GS.DrawingTasks)
End Sub
Public Sub DrawingComplete
    TileMap.DrawingComplete
End Sub
X2TileMap is used to "communicate" between the game and the map we created with "Tiled":

Set Map Dimensions
Set Backgroundcolor
Handle Tile layer
Handle Object layer objects
It can even be used to create Bodies that were defined on an object layer.
2019-07-18_17-01-49.png

Tilesets
These are graphic images referred to as tiles laid out in a grid.

Tilesets are created by graphically more artistically gifted people and can be downloaded and used free of charge or at low cost from the internet (see Game assets below).

During the training in "Tiled" it is easy to learn the principle of spritesheets and tilesets.

There is a recommendation to use tilesets that contain more than 1 tile.

Tile flipping and rotation is supported. The tiles images must be the same size as the map tiles.

(To be contiued …)


Information sources


Examples
The links are summarized here, because the results of the forum standard search produces a mix of too many aspects. The search on this one website may lead gamedev-beginners faster to the keyword via browser [ctl]+f.

Erel: "You can do whatever you like with the code including releasing the games as-is to the stores. Notes:- All of the games resources (graphics and sounds) were taken from open source projects. Make sure to check their licenses. - The Mario and Angry birds examples were created for educational purposes."

(The XUI2D “example pack” contains all “Erel-Examples” shown so far in the forum)

Single examples from the x2ep with video and special informations:

https://www.b4x.com/android/forum/threads/xui2d-flappy-bird-example.95302/

https://www.b4x.com/android/forum/threads/xui2d-x2tilemap-tiled-maps.95508/

https://www.b4x.com/android/forum/threads/xui2d-hello-world-2-based-on-tile-map.96103/

https://www.b4x.com/android/forum/threads/xui2d-super-mario-example-1.96151/

https://www.b4x.com/android/forum/threads/xui2d-super-mario-example-2.96236/

https://www.b4x.com/android/forum/threads/xui2d-space-invaders-1.96263/

https://www.b4x.com/android/forum/threads/xui2d-space-invaders-2.96322/

https://www.b4x.com/android/forum/threads/xui2d-joints-example.96547/

https://www.b4x.com/android/forum/threads/xui2d-tank-example.96567/

https://www.b4x.com/android/forum/threads/xui2d-monster-truck-example-wheeljoint.96622/

https://www.b4x.com/android/forum/threads/xui2d-drawing-lines-example.96934/

https://www.b4x.com/android/forum/threads/xui2d-newtons-cradle-example.97029/

https://www.b4x.com/android/forum/t...ap-example-hello-world-with-background.97657/
https://www.b4x.com/android/forum/threads/xui2d-floating-bodies-simulation.98243/

https://www.b4x.com/android/forum/threads/xui2d-mouse-following-a-path.98895/

https://www.b4x.com/android/forum/threads/xui2d-angry-birds-example.99052/

https://www.b4x.com/android/forum/threads/xui2d-tetris.107698/
More examples besides the pack:

Inverted Pendulum on a cart which is actuated by motors on the wheels: https://www.b4x.com/android/forum/threads/inverted-pendulum-on-cart-and-pidcontroller-class.99894/

Inverted Pendulum with a single wheeled pendulum (Segway): https://www.b4x.com/android/forum/t...e-wheel-and-pid-controller.99973/#post-628956

MouseJoint Example: https://www.b4x.com/android/forum/threads/mousejoint-example.100181/#post-630290

Continuous movement between two points: https://www.b4x.com/android/forum/threads/follow-path-from-tiled.103991/#post-652062

Complex body made of multiple images: https://www.b4x.com/android/forum/threads/xui2d-image-body-different-size.105212/#post-659107

Example of creating a body just as a stub for an image: https://www.b4x.com/android/forum/threads/xui2d-image-body-different-size.105212/#post-659241

Creating a non-centered shape: https://www.b4x.com/android/forum/threads/no-position-for-b2circleshape-in-xui2d.106943/#post-669331


Erel’s Tutorials
The links are summarized here, because the results of the forum standard search produces a mix of too many aspects. The search on this one website may lead gamedev-beginners faster to the keyword via browser [ctl]+f.

https://www.b4x.com/android/forum/threads/xui2d-units-and-scales.95285/

https://www.b4x.com/android/forum/threads/xui2d-bitmapcreator-vs-compressedbc.98217/

https://www.b4x.com/android/forum/threads/xui2d-performance.96326/

https://www.b4x.com/android/forum/threads/xui2d-first-joints-demo.96383/

Create the bitmaps or animations using xui2d: https://www.b4x.com/android/forum/threads/xui2d.96556/page-2#post-609204

Another way to set the graphics: https://www.b4x.com/android/forum/threads/xui2d.96556/page-2#post-609216

GS.DrawingTask is a list of DrawingTask types: https://www.b4x.com/android/forum/threads/xui2d.96556/page-2#post-609220

Test whether one of the wheels touches something: https://www.b4x.com/android/forum/threads/xui2d-monster-truck-example-wheeljoint.96622/#post-615967
B4X:
If FrontJoint.BodyB.GetContactList(True).Size > 0 Or RearJoint.BodyB.GetContactList(True).Size > 0 Then
   Log("on ground")
Else
   Log("in air")
End If
There are several ways to go over the templates or the created bodies: https://www.b4x.com/android/forum/t...-simple-xui2d-test-project.96793/#post-610646
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
Code for finding the touched body. An efficient solution based on box2d internal tree of AABBs: https://www.b4x.com/android/forum/t...-simple-xui2d-test-project.96793/#post-610850 (para 4)
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
https://www.b4x.com/android/forum/threads/xui2d-cross-platform-tips.96815/

https://www.b4x.com/android/forum/threads/xui2d-to-collide-or-not-to-collide.97144/

The correct way to set the world center is: https://www.b4x.com/android/forum/threads/xui2d-how-is-the-tilemap-drawn.97652/#post-615435
B4X:
Dim WorldWidth As Float = 25 'meters
Dim WorldHeight As Float = WorldWidth / RatioSetInDesignerScript 'same ratio as in the designer script
X2.ConfigureDimensions(world.CreateVec2(WorldWidth / 2, WorldHeight / 2), WorldWidth)
Erel's updated X2Tiles example that now limits the map movement to the visible map: https://www.b4x.com/android/forum/t...sing-the-world-edges.97550/page-2#post-616171
B4X:
Sub ClipScreenCenterToMapArea (v As B2Vec2) As B2Vec2
   Dim ScreenHalfWidth As Float = X2.ScreenAABB.Width / 2
   Dim ScreenHalfHeight As Float = X2.ScreenAABB.Height / 2
   v.X = Max(ScreenHalfWidth, Min(TileMap.MapAABB.Width - ScreenHalfWidth, v.X))
   v.Y = Max(ScreenHalfHeight, Min(TileMap.MapAABB.Height - ScreenHalfHeight, v.Y))
   Return v
End Sub
The scaling strategy that Erel chose: https://www.b4x.com/android/forum/threads/xui2d-designer-variable-mixed-up.97663/#post-615617

https://www.b4x.com/android/forum/threads/xui2d-bitmapcreator-vs-compressedbc.98217/

Jumptest: https://www.b4x.com/android/forum/threads/xui2d-jumptest-physics.98343/#post-619747

Make Joints more rigid: https://www.b4x.com/android/forum/threads/xui2d-connection-force-of-joints.98691/#post-621834

Chain, connection force of joints: https://www.b4x.com/android/forum/threads/xui2d-connection-force-of-joints.98691/#post-622024

Static drawings that are not being updated too frequently: https://www.b4x.com/android/forum/threads/how-to-draw-a-line.98846/#post-622847
B4X:
'BrushBackwards is a global variable.
'Created like this: BrushBackwards = X2.MainBC.CreateBrushFromColor(xui.Color_Red)
Public Sub Tick (GS As X2GameStep)
   If GS.ShouldDraw Then
       GS.DrawingTasks.Add(X2.MainBC.AsyncDrawCircle(100, 100, 50, BrushBackwards, True, 10))
       GS.DrawingTasks.Add(X2.MainBC.AsyncDrawLine(0, 0, X2.MainBC.mWidth, X2.MainBC.mHeight, BrushBackwards, 5))
   End If
End Sub
How to use Raycast callbacks: https://www.b4x.com/android/forum/threads/xui2d-world-raycast-callback-procedure.98870/#post-622735
B4X:
Private Sub Panel1_Touch (Action As Int, X As Float, Y As Float)
   If Action = Panel1.TOUCH_ACTION_DOWN Then
       Dim p As B2Vec2 = X2.ScreenPointToWorld(X, Y)
       'cast a ray from the kid to the point
       RaycastBody = Null
       RaycastPoint = p
       world.RayCast(mKid.bw.Body.Position, p)
       If RaycastBody <> Null And RaycastBody.IsDeleted = False Then
           'ray hit a body
           RaycastBody.TimeToLiveMs = 1
       End If
       CreateLaser
   End If
End Sub

Private Sub World_RaycastCallback (Fixture As B2Fixture, Point As B2Vec2, Normal As B2Vec2, Fraction As Float) As Float
   Dim bw As X2BodyWrapper = Fixture.Body.Tag
   'ignore static bodies
   If bw.Body.BodyType = bw.Body.TYPE_STATIC Then Return -1
   RaycastBody = bw
   RaycastPoint = Point.CreateCopy
   'return fraction to limit the ray up to the current fixture.
   'The result is that the last event will be the closest body.
   Return Fraction
End Sub
How to distinguish between different "sources" of Callback: https://www.b4x.com/android/forum/t...ferent-sources-of-callback.98925/#post-623192
B4X:
Private Sub Panel1_Touch (Action As Int, X As Float, Y As Float)
   If Action = Panel1.TOUCH_ACTION_DOWN Then
       Dim p As B2Vec2 = X2.ScreenPointToWorld(X, Y)
       'cast a ray from the kid to the point
       RaycastBody = Null
       RaycastPoint = p
       world.RayCast(mKid.bw.Body.Position, p)
       If RaycastBody <> Null And RaycastBody.IsDeleted = False Then
           'ray hit a body
           RaycastBody.TimeToLiveMs = 1
       End If
       CreateLaser
   End If
End Sub

Private Sub World_RaycastCallback (Fixture As B2Fixture, Point As B2Vec2, Normal As B2Vec2, Fraction As Float) As Float
   Dim bw As X2BodyWrapper = Fixture.Body.Tag
   'ignore static bodies
   If bw.Body.BodyType = bw.Body.TYPE_STATIC Then Return -1
   RaycastBody = bw
   RaycastPoint = Point.CreateCopy
   'return fraction to limit the ray up to the current fixture.
   'The result is that the last event will be the closest body.
   Return Fraction
End Sub
A nice trick to calculate the points of AngryBird’s future movement trajectory: https://www.b4x.com/android/forum/threads/xui2d-angry-birds-example.99052/#post-623655
B4X:
'This code is similar to the code that moves the real bird.
Private Sub RunSimulation (gs As X2GameStep)
   If gs.ShouldDraw Then
       SimulationBird.GravityScale = 0
       SimulationBird.LinearVelocity = X2.CreateVec2(0, 0)
       For i = 1 To 20
           Dim vec As B2Vec2 = HookCenter.Body.Position.CreateCopy
           vec.SubtractFromThis(SimulationBird.Position)
           Dim angle As Float = ATan2(vec.Y, vec.X)
           If SimulationBird.Position.X < HookCenter.Body.Position.X Then
               Dim length As Float = vec.Length
               Dim force As B2Vec2 = X2.CreateVec2(Cos(angle), Sin(angle))
               force.MultiplyThis(1.5 * length)
               SimulationBird.ApplyForce(force, SimulationBird.Position)
           Else
               SimulationBird.GravityScale = 1
           End If
           SimulationWorld.TimeStep(X2.TimeStepMs / 1000 * 4, 1, 1) '<--- let the simulation play
           Dim v As B2Vec2 = X2.WorldPointToMainBC(SimulationBird.Position.X, SimulationBird.Position.Y)
           X2.LastDrawingTasks.Add(X2.MainBC.AsyncDrawCircle(v.X, v.Y, 10, HintBrush, True, 0))
       Next
   End If
End Sub
Two different approaches to the set a drawtask in Angry Birds Example: https://www.b4x.com/android/forum/threads/angry-birds-example.99058/#post-623653

@Gunter’s roadmap into the game dev world: https://www.b4x.com/android/forum/threads/video-tutorial.99172/#post-624377
1) take the Tank-Example which is the easiest to start
2) then change the TiledMap behind, modify the bodies inside and add some own bodies
3) check the commands and the behavior when changed to a different value
4) see the tank movement (left right and screen clipping etc)
5) change the tank it self by own graphics or sprites

6) go to Clumsy Bird example for sprite animation
7) check for parallax effect and how it is done with the background

8) go for Walking Character example for how collisions detection is done, later may be the Mario Example

9) Check the Joints Example how joints are done. Add new different types of joints
10) build a Rag Doll with Tiled and Joints
10a) check the Collisions Example to avoid the shaggy situations of the Ragdoll

11) add some brain, play around and ask questions here in the forum.

12) google the internet for information like the Box2D manual. http://box2d.org/manual.pdf

13) try to build an extreme simple platformer
-> make a Tiled Map, put your world in there.
-> Tileset and pictures
-> characters

-> setup your world by copy and paste the Tiled code in your project

14) make your characters move around in the world

15) try to add more items by code or change the once you brought by Tiles into your world

16) don't assume that you are creating a milion dollar game at the beginning.
17) just add more complex items features. It is only your sandbox for spoil yourself.
@Gunter’s Helper method to get a perpendicular vector (b2cross, b2dot): https://www.b4x.com/android/forum/threads/vector-x-and-dot-product-for-b2world.99615/#post-626932

Create a polygon and use this polygon to create a bitmap to be used as the preloaded graphic for the GraphicCache: https://www.b4x.com/android/forum/t...o-scaledbitmap-not-drawing.99784/#post-627995

Draw a polygon based on a polygon shape: https://www.b4x.com/android/forum/t...o-scaledbitmap-not-drawing.99784/#post-628010

Tiled and rotated graphics: https://www.b4x.com/android/forum/threads/tiled-and-turned-graphics.100092/#post-629625

It is not good that the cache needs to be cleared too frequently: https://www.b4x.com/android/forum/threads/prototype-planetsgravity.100338/#post-630805

Always use CreateCopy when you modify a vector that you haven't created yourself: https://www.b4x.com/android/forum/t...distance-between-2-bodies.100624/#post-632527

Distance between 2 bodies: https://www.b4x.com/android/forum/t...distance-between-2-bodies.100624/#post-632519
B4X:
Dim v As B2Vec2 = bw1.Body.WorldCenter.CreateCopy
v.SubtractFromThis(bw2.Body.WorldCenter)
Log(v.Length)
Get savely the dimensions for a chain shape: https://www.b4x.com/android/forum/t...widthandheight-chainshape.100702/#post-632924

Change Alphalevel of cached graphic: https://www.b4x.com/android/forum/t...halevel-of-cached-graphic.100730/#post-632998

Better results with an image without antialiasing: https://www.b4x.com/android/forum/t...che-not-available-anymore.101725/#post-638882

Get the width and height of an object: https://www.b4x.com/android/forum/t...h-and-height-of-an-object.102147/#post-641239

World and Screen Sizes: https://www.b4x.com/android/forum/threads/xui2d-world-and-screen-sizes.102649/

Adding 2nd Game-Module: https://www.b4x.com/android/forum/threads/adding-2nd-game-module-is-failing.103010/#post-646062

ScreenPointToWorld: https://www.b4x.com/android/forum/t...e-a-x2-mainbctoworldpoint.103234/#post-647095
B4X:
Sub PanelForTouch_Touch (Action As Int, X As Float, Y As Float)
   If Action = PanelForTouch.TOUCH_ACTION_DOWN Or Action = PanelForTouch.TOUCH_ACTION_MOVE Then
       For Each bw As X2BodyWrapper In X2.GetBodiesIntersectingWithWorldPoint(X2.ScreenPointToWorld(X, Y))
           If bw.Name = "car" Then
               'never do physcial stuff from the Touch event. Only from inside the game loop
               X2.AddFutureTask(Me, "car_touched", 0, "")
           End If
       Next
   End If
End Sub
Create a zoom effect: https://www.b4x.com/android/forum/t...ture-during-the-game-loop.103553/#post-649197
B4X:
Sub btnZoom_Click
    If ZoomFactor = 1 Then ZoomFactor = 2 Else ZoomFactor = 1

    StretchImageViewAsNeeded
 
    'set the world center to be above the tank.
    X2.UpdateWorldCenter( X2.CreateVec2( Tank.Body.Position.X, X2.ScreenAABB.Height / ZoomFactor / 2))
End Sub

Sub StretchImageViewAsNeeded
    Dim width As Int = OriginalWidth * ZoomFactor
    Dim Height As Int = OriginalHeight * ZoomFactor
    Dim parent As B4XView = ivForeground.Parent
    ivForeground.SetLayoutAnimated(0, parent.Width / 2 - width / 2, parent.Height / 2 - Height / 2, width, Height)
    ivBackground.SetLayoutAnimated(0, ivForeground.Left, ivForeground.Top, width, Height)
End Sub
Pause to the Game Loop: https://www.b4x.com/android/forum/threads/wish-add-x2-pause-to-the-game-loop.103683/#post-649986

How to return list of all bodies in a given range: https://www.b4x.com/android/forum/t...t-all-bodies-in-the-range.103847/#post-651088

Move object to another object position: https://www.b4x.com/android/forum/t...o-another-object-position.103901/#post-651593
B4X:
Private Sub MoveEnemy
    Dim v As B2Vec2 = Mouse.Body.Position.CreateCopy
    v.SubtractFromThis(Enemy.Body.Position)
    If v.Length > 0.7 Then ' <--- check, if they are too close to each other
        v.NormalizeThis
        ' you could multiply that v by a scalar to change the speed like:
        ' v.MultiplyThis(1.5) ' >1 = faster, <1 = slower
        Enemy.Body.LinearVelocity = v
        Enemy.Body.SetTransform(Enemy.Body.Position, ATan2(v.Y, v.X) + cPI / 2) ' <--- turning the enemy in player direction
    Else
        Enemy.Body.LinearVelocity = X2.CreateVec2(0, 0) ' <--- yes, too close, therefore stop enemy
        Enemy.Body.AngularVelocity = 0 ' <--- stops the spinning
    End If
 
End Sub
Skipping frame: https://www.b4x.com/android/forum/threads/skipping-frame-and-nothing-show.104364/#post-654119

Find the position of all bodies: https://www.b4x.com/android/forum/threads/track-the-position-of-a-body.104693/#post-656255
B4X:
Dim bodies As List = world.AllBodies
For Each body As B2Body In bodies
   Dim bw As X2BodyWrapper = body.Tag
   If bw.Name <> "" Then
       Log(bw.Name & ": " & bw.Body.Position)
   End If
Next
Find position of body by id: https://www.b4x.com/android/forum/threads/track-the-position-of-a-body.104693/#post-656504
B4X:
For Each bw As X2BodyWrapper In X2.GetBodiesWrappersByIds(Array(IdOfPowerBodyThatYouShouldFindInTiled))
 Log(bw.Body.Position.Y)
Next
Where an image is assigned to the game: https://www.b4x.com/android/forum/threads/space-shooter-image-assignment.104758/#post-656282
Game Assets and tools
Graphics

Sounds

Formulas

Tools
Free "Tile" editor: https://www.mapeditor.org/

Free, The swiss army knife of image processing:http://www.graphicsmagick.org/index.html

Free Animation graphics editor: https://graphicsgale.com/us/

20$, Editor with Special Game Development Tools: https://www.cosmigo.com/pixel_animation_software/features

Gunther’s Exeltool which calculates the Masks according to the categories to which the single category shall collide: https://www.b4x.com/android/forum/t...lator-collision-filtering.103320/#post-647531

Informatix's Scene Editor: https://www.b4x.com/android/forum/threads/scene-editor.107420/

Online "Sprite sheet cutter": https://ezgif.com/sprite-cutter

Additional supports
If you want to see your game get downloads: https://www.b4x.com/android/forum/threads/make-games-with-me.102290/





_____________________________
(To be contiued …)​
 
Last edited:

Informatix

Expert
Licensed User
Longtime User
Great ! It will help me understand how X2 works. I don't have the courage to dive into a new framework without explanation.

But beware! The XUI2D world coordinate system (left) is different from the computer graphics coordinate system (right).

This depends on the game engine/framework you are using. In libGDX for example, and for everything based on OpenGL, the Y axis points down, so your sentence is a little too generic. Secondly, I don't notice in my use of XUI2D that everything has to be calculated in reverse for the Y axis. I'll leave you to judge with the little example provided. In this example, I make a very simple use of XUI2D to display the fall and then the rotation of two objects in a graphical coordinate system where the 0 is in the top left corner. The two images are drawn exactly where the two bodies are located. There is no scaling or inversion calculation.

If you define gravity with a positive sign, objects are attracted to the bottom of the screen in a coordinate system where the 0.0 point is at the top left. If you define it, as in the examples of X2, with a negative sign, then the objects are attracted in the other direction and you have to reverse everything. There may be an interest in doing this, but it escapes me.

In addition, there is no reason to distribute the objects around the axes considering that the 0.0 is in the center of the screen, as suggested in the diagram. Without the notion of Viewport (XUI2D does not export the class), it doesn't matter to users. And there is nothing to prevent everything from being placed in the positive part of both axes.

EDIT: This message refers to an older version of the coordinate system diagram of XUI2D in these notes that was wrong. There is no need to take into consideration the differences in orientation of the Y axes since X2 and XUI2D use the same Cartesian system. These are the units that differ between the two systems (meters vs. pixels).
 

Attachments

  • CircleAndRectangle.zip
    14.9 KB · Views: 398
Last edited:

Erel

B4X founder
Staff member
Licensed User
Longtime User
There is a small confusion about the terminology. In all my posts when I refer to XUI2D I'm actually referring to the X2 framework. The X2 framework is made of XUI2D as the physical engine, BitmapCreator (with a very specific configuration) as the drawing engine and X2 library that connects them and also adds other features.

In the X2 framework:

1. Coordinates are measured in meters.
2. The x axis goes from left to right (similar to the "regular" coordinates).
3. The y axis goes from bottom to top (opposite than the "regular" coordinates).
 

RandomCoder

Well-Known Member
Licensed User
Longtime User
One word of warning. A TileSet has to contain more than one tile!
It took me days to work out where I was going wrong with a new project. My approach was to start off small and grow my understanding, but having just one Tile to begin with properly tripped me up.
 
Top