This is a follow-up request to https://www.b4x.com/android/forum/t...egarding-screen-and-objects-positions.108254/
While positioning works quite well so far, there are still problems understanding the movement of objects from one point to another.
The intended process is as follows:
As it looks, I currently need concrete help on code level.
The enclosed test project is supposed to be a turn-based top down RPG board game for 2 characters.
Planned course: Players shall roll their dice alternately and advance the corresponding number of fields, sometimes choosing which way to go.
Since the interaction of the X2 framework components has not yet been sufficiently understood, concrete references to the required "best practices" would be needed.
The x2 examples were used to create the basic structures and load the graphics.
Planned course: Players shall roll their dice alternately and advance the corresponding number of fields, sometimes choosing which way to go.
Since the interaction of the X2 framework components has not yet been sufficiently understood, concrete references to the required "best practices" would be needed.
The x2 examples were used to create the basic structures and load the graphics.
B4X:
'
' Java source --> file:///.\Objects\src\b4j\gametest\sn\game.java
'
' ------- -------------- ------
'''#CustomBuildAction: folders ready, %WINDIR%\System32\Robocopy.exe,"..\..\Shared Files" "..\Files"
' This is required to copy all files from the "Shared Files" folder to the "Files" folder of the respective platform.
' Erel --> https://www.b4x.com/android/forum/threads/xui2d-cross-platform-tips.96815/#content
' ------- -------------- ------
' ------- -------------- ------
' X2Test1 "Basic structures"
' x2notes --> https://www.b4x.com/android/forum/threads/some-notes-to-better-understand-the-xui2d-examples.107702/
' x2examples --> https://www.b4x.com/android/forum/threads/xui2d-example-pack.96454/
' @Gunter’s roadmap into the game dev world --> https://www.b4x.com/android/forum/threads/video-tutorial.99172/#post-624377
' ------- -------------- ------
#if B4A
'ignore DIP related warnings as they are not relevant when working with BitmapCreator.
#IgnoreWarnings: 6
#end if
Sub Class_Globals
'
' Basic x2 libraries that are needed in every game
Private xui As XUI 'ignore
Public X2 As X2Utils
Public world As B2World
'
' TileMap specific definitions
Public TileMap As X2TileMap
Public Const ObjectLayer As String = "Object Layer 1"
'
' ExtraClasses
Private mChar1 As Figure
Private mChar2 As Figure
' Gamestate
Private GameOverState As Boolean
Private LastDiceRollVal As Int = 0 ' ####testingonly
' Bodies and joints
Private Border As X2BodyWrapper
Private CharMotor As B2MotorJoint
Private PathMainBCForward As BCPath
Private PathMainBCBackwards As BCPath
Private PathWorld As List
Private BrushRed As BCBrush
'Private ActiveCharacterBody As X2BodyWrapper
Private ActiveCharacterFigure As Figure
' Templates
Type FigureTemplates(Template As X2TileObjectTemplate, XPosition As Float)
Private FigureTemplatesList As List
Type PointTemplates(Template As X2TileObjectTemplate, XPosition As Float)
Private PointTemplatesList As List
Private PointTemplatesListLoop0 As List
Type TextTemplates (Template As X2TileObjectTemplate, XPosition As Float)
Private TextTemplatesList As List
Type LocationTemplates(Template As X2TileObjectTemplate, XPosition As Float)
Private LocationTemplatesList As List
' Layout elements
Private ivForeground As B4XView
Private ivBackground As B4XView
Public lblStats As B4XView
Private pnlTouch As B4XView
Private RadioButton1 As RadioButton' ####testingonly
Private RadioButton2 As RadioButton' ####testingonly
Private Button1 As Button' ####testingonly
Private Label2 As Label' ####testingonly
Private Pane1 As Pane' ####testingonly
Private fx As JFX' ####testingonly
Private TempTestPane As Pane' ####testingonly
End Sub
Public Sub Initialize (Parent As B4XView)
'
' ──────────────────────────────────
' Preparations for Layout and Views
' ──────────────────────────────────
Parent.LoadLayout("GameLayout")
lblStats.TextColor = xui.Color_Black
lblStats.Color = 0x88ffffff
lblStats.Font = xui.CreateDefaultBoldFont(20)
CSSUtils.SetBackgroundColor(Pane1, fx.Colors.LightGray)' ####testingonly
' ──────────────────────────────────
' Preparations for World
' ──────────────────────────────────
world.Initialize("world", world.CreateVec2(0, 0))
X2.Initialize(Me, ivForeground, world)
Dim WorldWidth As Float = 36 'meters
Dim WorldHeight As Float = WorldWidth / 1 'same ratio as in the designer script (in GameLayout.bjl)!!!
X2.ConfigureDimensions(world.CreateVec2(WorldWidth / 2, WorldHeight / 2), WorldWidth)
' ──────────────────────────────────
' Preparations for movements
' ──────────────────────────────────
PathMainBCForward.Initialize(0, 0)
PathMainBCBackwards.Initialize(0, 0)
PathWorld.Initialize
BrushRed = X2.MainBC.CreateBrushFromColor(xui.Color_Red)
' ──────────────────────────────────
' Preparations for graphics
' ──────────────────────────────────
GraphicCache_Put_Characters
' ──────────────────────────────────
' Preparations for screen
' ──────────────────────────────────
SetBackground
'CreateStaticBackground
'CreateBorder
' ──────────────────────────────────
' Preparations for sounds
' ──────────────────────────────────
'X2.SoundPool.AddSound("small jump", File.DirAssets, "small_jump.mp3")
'X2.SoundPool.AddSound("big jump", File.DirAssets, "big_jump.mp3")
'X2.SoundPool.AddSound("powerup", File.DirAssets, "powerup.mp3")
' ──────────────────────────────────
' Debug settings
' ──────────────────────────────────
X2.EnableDebugDraw ' Comment out to disable debug drawing
End Sub
Private Sub SetWorldCenter
' The map size will not be identical to the screen size.
' This happens because the tile size in (bc) pixels needs to be a whole number.
' So we need to update the world center and move the map to the center.
X2.UpdateWorldCenter(TileMap.MapAABB.Center)
End Sub
Public Sub WorldCenterUpdated (gs As X2GameStep)
'CreateEnemies
End Sub
private Sub SetBackground
'X2.SetBitmapWithFitOrFill(ivBackground, xui.LoadBitmapResize(File.DirAssets, "mybackgroundimage.jpg", ivBackground.Width / 2, ivBackground.Height / 2, False))
End Sub
Private Sub GraphicCache_Put_Characters
Log("#-Sub game.GraphicCache_Put_Characters")
' Use bitmap without the transparency placeholdercolor:
Dim bc As BitmapCreator = X2.BitmapToBC( xui.LoadBitmap(File.DirAssets, "RPGCharacterSprites32x32.png"), 1)
RemovePseudoTransparentColor(bc, "#ff00ff") ' pink, magenta
Dim bmp As B4XBitmap = bc.Bitmap
Dim NumberOfSprites As Int = 12
Dim RowWidth As Int = 32
Dim RowHeight As Int = 32
Dim CharHeightMeters As Int = 3
'
Dim RowOfChar1 As Int = 2
Dim character1 As B4XBitmap = bmp.Crop(0, RowHeight * RowOfChar1, NumberOfSprites * RowWidth, RowHeight)
Dim AllChar1 As List = X2.ReadSprites(character1, 1, NumberOfSprites, CharHeightMeters, CharHeightMeters)
X2.GraphicCache.PutGraphic("character1 front walking", Array(AllChar1.Get(0), AllChar1.Get(1), AllChar1.Get(2), AllChar1.Get(3)))
X2.GraphicCache.PutGraphic("character1 front standing", Array(AllChar1.Get(3)))
X2.GraphicCache.PutGraphic("character1 back walking", Array(AllChar1.Get(4), AllChar1.Get(5), AllChar1.Get(6), AllChar1.Get(7)))
X2.GraphicCache.PutGraphic("character1 back standing", Array(AllChar1.Get(7)))
X2.GraphicCache.PutGraphic("character1 side walking", Array(AllChar1.Get(8), AllChar1.Get(9), AllChar1.Get(10)) )
X2.GraphicCache.PutGraphic("character1 side standing", Array(AllChar1.Get(9)) )
'
Dim RowOfChar2 As Int = 3
Dim character2 As B4XBitmap = bmp.Crop(0, RowHeight * RowOfChar2, NumberOfSprites * RowWidth, RowHeight)
Dim AllChar2 As List = X2.ReadSprites(character2, 1, NumberOfSprites, CharHeightMeters, CharHeightMeters)
X2.GraphicCache.PutGraphic("character2 front walking", Array(AllChar2.Get(0), AllChar2.Get(1), AllChar2.Get(2), AllChar2.Get(3)))
X2.GraphicCache.PutGraphic("character2 front standing", Array(AllChar2.Get(3)))
X2.GraphicCache.PutGraphic("character2 back walking", Array(AllChar2.Get(4), AllChar2.Get(5), AllChar2.Get(6), AllChar2.Get(7)))
X2.GraphicCache.PutGraphic("character2 back standing", Array(AllChar2.Get(7)))
X2.GraphicCache.PutGraphic("character2 side walking", Array(AllChar2.Get(8), AllChar2.Get(9), AllChar2.Get(10)) )
X2.GraphicCache.PutGraphic("character2 side standing", Array(AllChar2.Get(9)) )
'
End Sub
Private Sub RemovePseudoTransparentColor(TilesBC As BitmapCreator, clrstring As String)
' Erel --> https://www.b4x.com/android/forum/threads/x2-how-to-use-transparent-color.108173/#post-676534
Dim clr As Int = 0xff000000 + Bit.ParseInt(clrstring.SubString(1), 16)
Dim ptranspm As PremultipliedColor
Dim trans As PremultipliedColor
Dim pm As PremultipliedColor
Dim argb As ARGBColor
TilesBC.ColorToARGB(clr, argb)
TilesBC.ARGBToPremultipliedColor(argb, ptranspm)
For y = 0 To TilesBC.mHeight - 1
For x = 0 To TilesBC.mWidth - 1
TilesBC.GetPremultipliedColor(x, y, pm)
If Bit.And(0xff, pm.r) = ptranspm.r And Bit.And(0xff, pm.g) = ptranspm.g And Bit.And(0xff, pm.b) = ptranspm.b And Bit.And(0xff, pm.a) = ptranspm.a Then
TilesBC.SetPremultipliedColor(x, y, trans)
End If
Next
Next
End Sub
Private Sub PositionObjects
For Each LocationTemplateX As LocationTemplates In LocationTemplatesList
' Initial position on location-objects (works ok)
Select Case True
Case LocationTemplateX.Template.Name.ToLowerCase.EndsWith("c1")
mChar1.bw.Body.SetTransform(LocationTemplateX.Template.Position, 0)
Case LocationTemplateX.Template.Name.ToLowerCase.EndsWith("c2")
mChar2.bw.Body.SetTransform(LocationTemplateX.Template.Position, 0)
End Select
Next
End Sub
private Sub CreateObjects
Log("#-Sub game.CreateObjects")
FigureTemplatesList.Initialize
PointTemplatesList.Initialize
PointTemplatesListLoop0.Initialize
TextTemplatesList.Initialize
LocationTemplatesList.Initialize
TempTestPane.RemoveAllNodes ' ####testingonly
Dim ol As X2ObjectsLayer = TileMap.Layers.Get(ObjectLayer)
For Each TileMapTemplateX As X2TileObjectTemplate In ol.ObjectsById.Values
'Log("#- x203, TileMapTemplateX.Name = " & TileMapTemplateX.Name)
If TileMapTemplateX.FirstTime And TileMapTemplateX.Name.ToLowerCase.StartsWith("p") Then
Dim pt As PointTemplates
pt.Template = TileMapTemplateX
pt.XPosition = TileMapTemplateX.Position.X
PointTemplatesList.Add(pt)
TileMap.CreateObject(TileMapTemplateX)
If Not(TileMapTemplateX.Name.Contains(".")) And Not(TileMapTemplateX.Name.Contains("x")) Then
PointTemplatesListLoop0.Add(pt)
End If
' ####testingonly
Dim lblx As Label
lblx.Initialize("")
lblx.Text = TileMapTemplateX.Name
lblx.TextColor = fx.Colors.Yellow
lblx.Alignment = "CENTER"
Dim bp As B2Vec2 = X2.WorldPointToMainBC( TileMapTemplateX.Position.X, TileMapTemplateX.Position.Y)
Private DebugScale As Float = 1.1 ' found by trial and error
bp.MultiplyThis(DebugScale)
TempTestPane.AddNode(lblx, bp.X, bp.Y, 40dip, 40dip)
' /####testingonly
else If TileMapTemplateX.FirstTime And TileMapTemplateX.Name.ToLowerCase.StartsWith("text") Then
Dim tt As TextTemplates
tt.Template = TileMapTemplateX
tt.XPosition = TileMapTemplateX.Position.X
TextTemplatesList.Add(tt)
TileMap.CreateObject(TileMapTemplateX)
else If TileMapTemplateX.FirstTime And TileMapTemplateX.Name.ToLowerCase.StartsWith("char") Then
Dim ft As FigureTemplates
ft.Template = TileMapTemplateX
ft.XPosition = TileMapTemplateX.Position.X
FigureTemplatesList.Add(ft)
Dim bwChX As X2BodyWrapper = TileMap.CreateObject(TileMapTemplateX)
bwChX.Body.BodyType = bwChX.Body.TYPE_DYNAMIC ' not "TYPE_KINEMATIC": You cannot use forces and motors with kinematic types.
If TileMapTemplateX.Name.ToLowerCase.EndsWith("1") Then
Log("#- x252, mChar1.Initialize, bwChX=" & bwChX.Name)
mChar1.Initialize(bwChX) ' Set the delegate (the class "Figure")
mChar1.FigureNameAndId = TileMapTemplateX.Name & "~" & TileMapTemplateX.id
' not working...
Dim MotorDefChar1 As B2MotorJointDef
MotorDefChar1.Initialize(Border.Body, mChar1.bw.Body)
MotorDefChar1.MaxMotorTorque = 1
MotorDefChar1.MaxMotorForce = 1
MotorDefChar1.CollideConnected = True 'let the Char collide with the borders
CharMotor = X2.mWorld.CreateJoint(MotorDefChar1)
CharMotor.CorrectionFactor = 0.1
else If TileMapTemplateX.Name.ToLowerCase.EndsWith("2") Then
Log("#- x268, mChar2.Initialize, bwChX=" & bwChX.Name)
mChar2.Initialize(bwChX) ' Set the delegate (the class "Figure")
mChar2.FigureNameAndId = TileMapTemplateX.Name & "~" & TileMapTemplateX.id
'' not working...
'Dim MotorDefChar2 As B2MotorJointDef
'MotorDefChar2.Initialize(Border.Body, mChar2.bw.Body)
'MotorDefChar2.MaxMotorTorque = 1
'MotorDefChar2.MaxMotorForce = 1
'MotorDefChar2.CollideConnected = True 'let the Char collide with the borders
'CharMotor = X2.mWorld.CreateJoint(MotorDefChar2)
'CharMotor.CorrectionFactor = 0.1
End If
else If TileMapTemplateX.FirstTime And TileMapTemplateX.Name.ToLowerCase.StartsWith("loc") Then
Dim lt As LocationTemplates
lt.Template = TileMapTemplateX
lt.XPosition = TileMapTemplateX.Position.X
LocationTemplatesList.Add(lt)
TileMap.CreateObject(TileMapTemplateX)
' If TileMapTemplateX.Name.ToLowerCase
' LocC1Body = TileMap.CreateObject2ByName(ObjectLayer, "locC1")
End If
Next
FigureTemplatesList.SortType("XPosition", True)
PointTemplatesList.SortType("XPosition", True)
TextTemplatesList.SortType("XPosition", True)
LocationTemplatesList.SortType("XPosition", True)
Log("#- x206, FigureTemplatesList.size = " & FigureTemplatesList.Size)
Log("#- x207, PointTemplatesList.size = " & PointTemplatesList.Size)
Log("#- x208, TextTemplatesList.size = " & TextTemplatesList.Size)
Log("#- x209, LocationTemplatesList.size = " & LocationTemplatesList.Size)
End Sub
Private Sub CreateStaticBackground
Dim bc As BitmapCreator
bc.Initialize(ivBackground.Width / xui.Scale / 2, ivBackground.Height / xui.Scale / 2)
bc.FillGradient(Array As Int(0xFF001AAC, 0xFFC5A400), bc.TargetRect, "TOP_BOTTOM")
X2.SetBitmapWithFitOrFill(ivBackground, bc.Bitmap)
End Sub
Private Sub CreateBorder
TileMap.CreateObject(TileMap.GetObjectTemplateByName(ObjectLayer, "border"))
End Sub
' ────────────────────────────────────────────────────────────────────────────────────────────────
Public Sub Resize
X2.ImageViewResized
End Sub
Public Sub DrawingComplete
TileMap.DrawingComplete
End Sub
'Return True to stop the game loop.
Public Sub BeforeTimeStep (GS As X2GameStep) As Boolean
If GameOverState Then
Return True
End If
Return False
End Sub
Public Sub Tick (GS As X2GameStep)
' Log("#-Sub game.Tick, gs.GameTimeMs = " & GS.GameTimeMs)
TileMap.DrawScreen(Array("Tile Layer 1"), GS.DrawingTasks)
' MoveChar(GS)
' mChar1.Tick(GS)
' mChar2.Tick(GS)
End Sub
' ────────────────────────────────────────────────────────────────────────────────────────────────
Public Sub GameOver
X2.SoundPool.StopMusic
X2.SoundPool.PlaySound("gameover")
X2.AddFutureTask(Me, "Set_GameOver", 3500, Null)
End Sub
Private Sub Set_GameOver (ft As X2FutureTask)
GameOverState = True
Sleep(500)
StartGame
End Sub
Public Sub StopGame
X2.SoundPool.StopMusic
X2.Stop
End Sub
Public Sub StartGame
If X2.IsRunning Then Return
X2.Reset
X2.UpdateWorldCenter(X2.CreateVec2(X2.ScreenAABB.Width / 2, X2.ScreenAABB.Height / 2))
GameOverState = False
' ──────────────────────────────────
' Preparations for Tilemap
' ──────────────────────────────────
TileMap.Initialize(X2, File.DirAssets, "TiledMapFile_proj01.json", ivBackground)
Dim TileSizeMeters As Float = X2.ScreenAABB.Height / TileMap.TilesPerColumn
TileMap.SetSingleTileDimensionsInMeters(TileSizeMeters, TileSizeMeters)
SetWorldCenter ' Update the world center based on the map size
TileMap.PrepareObjectsDef(ObjectLayer)
Border = TileMap.CreateObject2ByName(ObjectLayer, "border")
' ──────────────────────────────────
' Draw Tilemap
' ──────────────────────────────────
Dim tasks As List
tasks.Initialize
TileMap.Draw(Array("Tile Layer 1"), TileMap.MapAABB, tasks)
For Each dt As DrawTask In tasks
If dt.IsCompressedSource Then
TileMap.CurrentBC.DrawCompressedBitmap(dt.Source, dt.SrcRect, dt.TargetX, dt.TargetY)
End If
Next
' ──────────────────────────────────
' Preparations for bodies
' ──────────────────────────────────
CreateObjects
PositionObjects
ActiveCharacterFigure = mChar1
' ──────────────────────────────────
' Start the Main loop
' ──────────────────────────────────
X2.Start
End Sub
Sub pnlTouch_Touch (Action As Int, X As Float, Y As Float)
' Click is on a "FormPoint": x and y are the form-coordinates topleft=0,0 and bottomright=formheight,formwidth
'
If Action = pnlTouch.TOUCH_ACTION_MOVE_NOTOUCH Then Return
Log("#-Sub pnlTouch_Touch, Action=" & Action & ", x=" & x & ", y=" & y)
Dim WorldPoint As B2Vec2 = X2.ScreenPointToWorld(X, Y)
Dim MainBCPoint As B2Vec2 = X2.WorldPointToMainBC(WorldPoint.X, WorldPoint.Y)
If Action = pnlTouch.TOUCH_ACTION_DOWN Then
Dim FirstPointBC As B2Vec2 = X2.WorldPointToMainBC(ActiveCharacterFigure.bw.Body.Position.X, ActiveCharacterFigure.bw.Body.Position.Y)
' CLONE the paths before modifying them.
PathMainBCForward = PathMainBCForward.Clone
PathMainBCForward.Reset(FirstPointBC.X, FirstPointBC.Y)
PathMainBCBackwards = PathMainBCBackwards.Clone
PathMainBCBackwards.Reset(FirstPointBC.X, FirstPointBC.Y)
PathWorld.Clear
End If
If PathWorld.Size > 0 Then
Dim PrevPoint As B2Vec2 = PathWorld.Get(PathWorld.Size - 1)
Dim distance As B2Vec2 = PrevPoint.CreateCopy
distance.SubtractFromThis(WorldPoint)
'to improve performance we skip very close points.
If distance.LengthSquared < 0.1 Then
Return
End If
End If
PathMainBCForward = PathMainBCForward.Clone
PathMainBCForward.LineTo(MainBCPoint.X, MainBCPoint.Y)
PathWorld.Add(WorldPoint)
End Sub
Sub MoveChar(gs As X2GameStep)
'This loop might be a bit confusing. The loop ends after the first far enough point.
Do While PathWorld.Size > 0
Dim NextPoint As B2Vec2 = PathWorld.Get(0)
Dim CurrentPoint As B2Vec2 = ActiveCharacterFigure.bw.Body.Position
Dim distance As B2Vec2 = NextPoint.CreateCopy
distance.SubtractFromThis(CurrentPoint)
If (distance.Length < 0.3 And PathWorld.Size > 1) Or (distance.Length < 0.1) Then
PathWorld.RemoveAt(0)
Dim v As B2Vec2 = X2.WorldPointToMainBC(NextPoint.X, NextPoint.Y)
'clone the paths before modifying them as they are being drawn asynchronously.
PathMainBCForward = PathMainBCForward.Clone
PathMainBCBackwards = PathMainBCBackwards.Clone
'remove the first point from the "forward" path and add it to the "backwards" path.
PathMainBCForward.Points.RemoveAt(0)
PathMainBCForward.Invalidate 'need to call Invalidate after we directly access the points list.
PathMainBCBackwards.LineTo(v.X, v.Y)
' Continue 'skip to the next point
End If
' Log("#- x467, ActiveCharacterBody = " & ActiveCharacterBody.Name)
CharMotor.AngularOffset = FindAngleToTarget(ActiveCharacterFigure.bw.Body, NextPoint)
Dim delta As B2Vec2 = NextPoint.CreateCopy
delta.SubtractFromThis(Border.Body.Position)
CharMotor.LinearOffset = delta
'draw the small red circle
v = X2.WorldPointToMainBC(NextPoint.X, NextPoint.Y)
gs.DrawingTasks.Add(X2.MainBC.AsyncDrawCircle(v.X, v.Y, 5, BrushRed, True, 0))
' Exit '<-----
Loop
End Sub
Sub FindAngleToTarget(Body As B2Body, Target As B2Vec2) As Float
If Abs(Body.Angle) > 2 * cPI Then
'make sure that the current angle is between -2*cPI to 2*cPI
Body.SetTransform(Body.Position, X2.ModFloat(Body.Angle, 2 * cPI))
End If
Dim angle As Float = ATan2(Target.Y - Body.Position.Y, Target.X - Body.Position.X) + cPI / 2
Dim CurrentAngle As Float = Body.Angle
'find the shortest direction
Dim anglediff As Float = angle - CurrentAngle
If anglediff > cPI Then
angle = -(2 * cPI - angle)
Else If anglediff < -cPI Then
angle = angle + 2 * cPI
End If
Return angle
End Sub
'must handle this event if we want to handle the PreSolve event.
Private Sub World_BeginContact (Contact As B2Contact)
Dim bodies As X2BodiesFromContact = X2.GetBodiesFromContact(Contact, "char1")
' Log("#-Sub World_BeginContact") ', bodies.OtherBody.Name = " & bodies.OtherBody.Name)
If bodies <> Null Then
' If bodies.OtherBody.Name = "mushroom" Then
' 'we cannot modify the world state inside these events. So we add a future task with time = 0.
' X2.AddFutureTask(mChar1, "Touch_Mushroom", 0, bodies.OtherBody)
' End If
End If
' Dim bodies As X2BodiesFromContact = X2.GetBodiesFromContact(Contact, "left edge")
' If bodies <> Null And bodies.OtherBody.DelegateTo Is Enemy Then
' X2.AddFutureTask(Me, "Delete_Enemy", 0, bodies.OtherBody)
' Return
' End If
End Sub
Private Sub World_PreSolve (Contact As B2Contact, OldManifold As B2Manifold)
Dim BodyA As X2BodyWrapper = Contact.FixtureA.Body.Tag
Dim BodyB As X2BodyWrapper = Contact.FixtureB.Body.Tag
If BodyA.IsVisible = False Or BodyB.IsVisible = False Then Return
' CheckMarioCollisions (Contact, X2.GetBodiesFromContact(Contact, "mario"))
' CheckEnemyCollisions(Contact, X2.GetBodiesFromContact(Contact, "enemy bug"))
' CheckEnemyCollisions(Contact, X2.GetBodiesFromContact(Contact, "enemy turtle"))
End Sub
Private Sub World_PostSolve (Contact As B2Contact, Impulse As B2ContactImpulse)
End Sub
Sub ActiveCharacterSelect_SelectedChange(Selected As Boolean) ' ####testingonly
LastDiceRollVal = 0
Label2.Text = "..."
If Not(Selected) Then Return
Log("#-ActiveCharacterSelect_SelectedChange, Selected=" & Selected)
Dim rbx As RadioButton = Sender
Dim tagx As String = rbx.Tag
Select Case True
Case tagx.ToLowerCase = "rbc1"
ActiveCharacterFigure = mChar1
Case tagx.ToLowerCase = "rbc2"
ActiveCharacterFigure = mChar2
End Select
Log("#- x536, tagx.ToLowerCase = " & tagx.ToLowerCase)
Log("#- x537, ActiveCharacterBody.Name = " & ActiveCharacterFigure.bw.Name)
End Sub
Sub Button1_Click ' ####testingonly
LastDiceRollVal = Rnd(1,12)
Label2.Text = LastDiceRollVal
CharAdvance(LastDiceRollVal)
End Sub
Sub CharAdvance(NumberOfSteps As Int)
Log("#-Sub game.CharAdvance, NumberOfSteps=" & NumberOfSteps)
Dim NewPointTemplatesListIndex As Int = ActiveCharacterFigure.LastPositionIndex +NumberOfSteps
Log("#- x579, NewPointTemplatesListIndex=" & NewPointTemplatesListIndex)
For i=ActiveCharacterFigure.LastPositionIndex To NewPointTemplatesListIndex
Dim GotToPosIndex As Int = i Mod PointTemplatesListLoop0.Size
Dim pt As PointTemplates = PointTemplatesListLoop0.Get(GotToPosIndex)
Log("#- x580, GotToPosIndex=" & GotToPosIndex & ", pt.Template.Position=" & pt.Template.Position)
'##### An experiment to move the active character the "nonmotor" way
Dim v As B2Vec2 = ActiveCharacterFigure.bw.Body.Position.CreateCopy
ActiveCharacterFigure.bw.Body.LinearVelocity = v
'/####
Next
ActiveCharacterFigure.LastPositionIndex = NewPointTemplatesListIndex
End Sub
B4X:
' Class "Figure"
Sub Class_Globals
Public FigureNameAndId As String = ""
Public bw As X2BodyWrapper
Public InAir As Boolean
Public IsSmall As Boolean = True
Public LastPositionIndex As Int = 0
Private x2 As X2Utils 'ignore
Private LastTickTime As Int
Private SpecialState As Boolean
Private FaceRight As Boolean = True
Private MaxVelocity As Float = 10
Private ImpulseVector As B2Vec2
Private ProtectedTime As Int
End Sub
Public Sub Initialize (wrapper As X2BodyWrapper)
' Log("#-Sub figure.Initialize")
LastPositionIndex = 0
bw = wrapper
x2 = bw.X2
bw.DelegateTo = Me
UpdateImpulseVector
CreateChar1Legs
End Sub
Private Sub CreateChar1Legs
' see 1--> https://www.b4x.com/android/forum/threads/xui2d-super-mario-example-1.96151/
' see 2--> https://www.b4x.com/android/forum/threads/xui2d-super-mario-example-2.96236/
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
f.Tag = "legs"
End Sub
Private Sub UpdateImpulseVector
Log("#-Sub figure.UpdateImpulseVector, bw.Name=" & bw.Name)
ImpulseVector = x2.CreateVec2(0.5 * bw.Body.Mass * x2.TimeStepMs / 16, 0)
End Sub
Public Sub Hit_Start (ft As X2FutureTask)
If SpecialState Then Return
If x2.gs.GameTimeMs < ProtectedTime Then Return
End Sub
Private Sub StartGameOver
SpecialState = True
bw.GraphicName = "Char1 small strike"
bw.Body.FirstFixture.SetFilterBits(0, 0)
bw.Body.FirstFixture.NextFixture.SetFilterBits(0, 0)
bw.Body.LinearVelocity = x2.CreateVec2(0, 15)
bw.mGame.GameOver
End Sub
Public Sub Tick (GS As X2GameStep)
' Log("#-Sub figure.Tick")
If LastTickTime = GS.GameTimeMs Then Return
LastTickTime = GS.GameTimeMs
' ???
If GS.ShouldDraw Then
bw.UpdateGraphic(GS, True)
End If
End Sub
Public Sub IsLegsFixture (Fixture As B2Fixture) As Boolean
Return Fixture.Tag <> Null And Fixture.Tag = "legs"
End Sub
While positioning works quite well so far, there are still problems understanding the movement of objects from one point to another.
- By reviewing the examples, the MotorJoint was found in the mouse example and tested without success.
- A movement with Body.LinearVelocity was tried, but without real control over the behavior.
The intended process is as follows:
- In Game.CreateObjects a list with the positions of certain points from TiledMap is created (works)
- After building the screen the first character is selected and a random integer (1..12) is created (by button)
- The figure Char1 is moved from the current position along the list of points to the next position (oldindex +randomvalue).
As it looks, I currently need concrete help on code level.
I would be grateful if experienced X2 experts could take a quick look at the test project and help me to implement the movement using motorjoint.