Okay, I've been trying to combine part of the Space Invaders example with the Space Shooter example and it's just not triggering the collisions between the space ship and the barriers and I just can't see why. I've looked at Tiled and am now happy that the bit mask and so on are correct and I've even set them manually to try to force them but for some reason it just isn't acting as expected.
I'm sure it's probably an obvious issue, but I just cannot fathom why right now and I've been looking at it for far too long!
Any thoughts?
Some of the code below and I've attached some of the source code, which is literally Space Shooter with the barrier code from Space Invaders placed in there. Including the json file for the objects..
Shield Code Module
If I bang my head any more on this I'll pass out!!
ETA : I've already looked at this https://www.b4x.com/android/forum/threads/xui2d-to-collide-or-not-to-collide.97144/
I'm sure it's probably an obvious issue, but I just cannot fathom why right now and I've been looking at it for far too long!
Any thoughts?
Some of the code below and I've attached some of the source code, which is literally Space Shooter with the barrier code from Space Invaders placed in there. Including the json file for the objects..
B4X:
Public Sub Start
If X2.IsRunning Then Return
'Make sure that start was not called while the message appeared (this can happen in edge cases where the app moves to the background
'and then quickly to the foreground several times).
StartIndex = StartIndex + 1
Dim MyIndex As Int = StartIndex
Wait For (ShowMessage("Get Ready...")) Complete (Success As Boolean)
If MyIndex <> StartIndex Then Return
X2.Reset
Multitouch.ResetState
Dim ratio As Float = ivForeground.Width / ivForeground.Height
WorldWidth = 6
WorldHeight = WorldWidth / ratio
X2.ConfigureDimensions(X2.CreateVec2(WorldWidth / 2, WorldHeight / 2), WorldWidth)
'comment to disable debug drawing
' X2.EnableDebugDraw
TileMap.Initialize(X2, File.DirAssets, "space shooter.json", Null)
'square tiles. The base size is the world width.
TileMap.SetSingleTileDimensionsInMeters(WorldWidth / TileMap.TilesPerRow, WorldWidth / TileMap.TilesPerRow)
TileMap.PrepareObjectsDef(ObjectLayer)
lblMessages.Visible = False
LeftBorder = TileMap.CreateObject2ByName(ObjectLayer, "left border")
TileMap.CreateObject2ByName(ObjectLayer, "right border")
Ship = TileMap.CreateObject2ByName(ObjectLayer, "ship")
If xui.IsB4J Then
Ship.Body.SetTransform(X2.CreateVec2(Ship.Body.Position.X, 0.5), 0)
End If
Ship.Body.LinearDamping = 4 'stop quickly
ShipWidth = X2.GetShapeWidthAndHeight(Ship.Body.FirstFixture.Shape).X
ScoreLabel1.SetValueNow(0)
CreateShields
SetLives(3)
ivForeground.Visible = True
'motor is used in B4A and B4i to move the ship to the touch position.
Dim motor As B2MotorJointDef
motor.Initialize(LeftBorder.Body, Ship.Body)
motor.MaxMotorForce = 0
motor.CollideConnected = True
ShipMotor = world.CreateJoint(motor)
ShipMotor.CorrectionFactor = 0.2
X2.Start
InputsDisabled = False
End Sub
Sub World_BeginContact (Contact As B2Contact)
Dim bc As X2BodiesFromContact = X2.GetBodiesFromContact(Contact, "fire")
If bc <> Null And bc.OtherBody.Name.StartsWith("asteroid") Then
X2.AddFutureTask2(Me, "Destroy_Asteroid", 0, bc, True)
Else
Log("fire")
bc = X2.GetBodiesFromContact(Contact, "ship")
If bc <> Null Then
If bc.OtherBody.Name = "power" Then
X2.AddFutureTask(Me, "Power_Up", 0, bc.OtherBody)
' Else If bc.OtherBody.Name.StartsWith("asteroid") And IsProtected = False Then
' X2.AddFutureTask(Me, "Destroy_Ship", 0, Null)
End If
End If
End If
If bc <> Null Then
If bc.OtherBody.Name = "left edge" Then
X2.AddFutureTask(Me, "change_direction", 0, True)
Else If bc.OtherBody.Name = "right edge" Then
X2.AddFutureTask(Me, "change_direction", 0, False)
Else If bc.OtherBody.Name = "ship laser" Then
X2.AddFutureTask(Me, "EnemyHit_WithMissle", 0, bc)
Else If bc.OtherBody.Name = "ship" Then
X2.AddFutureTask(Me, "ShipHit_WithEnemy", 0, bc)
End If
End If
' bc = X2.GetBodiesFromContact(Contact, "enemy laser")
' If bc <> Null And bc.OtherBody.Name = "ship" Then
' X2.AddFutureTask(Me, "ShipHit_WithMissile", 0, bc)
' End If
bc = X2.GetBodiesFromContact(Contact, "shield")
Log("shieldcontact1")
If bc <> Null Then
X2.AddFutureTask(Me, "Shield_Hit", 0, bc)
End If
End Sub
Private Sub Shield_Hit (ft As X2FutureTask)
Log("Shield_Hit")
Dim bodies As X2BodiesFromContact = ft.Value
If bodies.OtherBody.Name <> "enemy" Then
bodies.OtherBody.Delete(X2.gs) 'delete the missile
End If
Dim shld As Shield = bodies.ThisBody.DelegateTo
shld.Hit(bodies.ThisFixture)
End Sub
Shield Code Module
B4X:
Sub Class_Globals
Public bw As X2BodyWrapper
Private x2 As X2Utils 'ignore
Private bc As BitmapCreator
Private ShapeSize As B2Vec2
Private cbc As CompressedBC
Private HalfWidth, HalfHeight As Float
Private xui As XUI
End Sub
Public Sub Initialize (wrapper As X2BodyWrapper)
bw = wrapper
x2 = bw.X2
bw.DelegateTo = Me
ShapeSize = x2.GetShapeWidthAndHeight(bw.Body.FirstFixture.Shape)
bc.Initialize(x2.MetersToBCPixels(ShapeSize.X), x2.MetersToBCPixels(ShapeSize.Y))
bc.FillGradient(Array As Int(0xFF006016, 0xFF92F7AA), bc.TargetRect, "RECTANGLE")
'remove the large shape and create smaller blocks
bw.Body.DestroyFixture(bw.Body.FirstFixture)
Dim fd As B2FixtureDef
Dim rect As B2PolygonShape
rect.Initialize
fd.Shape = rect
Dim BlocksPerRow = 6, BlocksPerColumn = 3 As Int
HalfWidth = ShapeSize.X / BlocksPerRow / 2
HalfHeight = ShapeSize.Y / BlocksPerColumn / 2
fd.Friction = 0
fd.IsSensor = True
For y = 0 To BlocksPerColumn - 1
For x = 0 To BlocksPerRow - 1
Dim position As B2Vec2 = x2.CreateVec2(-ShapeSize.X / 2 + (x * 2 + 1) * HalfWidth, -ShapeSize.Y / 2 + (y * 2 + 1) * HalfHeight)
rect.SetAsBox2(HalfWidth, HalfHeight, position, 0)
Dim fixture As B2Fixture = bw.Body.CreateFixture(fd)
' bw.Body.FirstFixture.SetFilterBits(4,65535)
fixture.Body.FirstFixture.SetFilterBits(4,65535)
'we save the x and y indices. Later they will be used to clear the broken fixtures.
fixture.Tag = Array As Float(x / BlocksPerRow, y / BlocksPerColumn)
Next
Next
UpdateCBC
End Sub
Public Sub Hit(Fixture As B2Fixture)
Log("shield hit")
Dim xy() As Float = Fixture.Tag
bw.Body.DestroyFixture(Fixture)
Dim rect As B4XRect
Dim width As Int = x2.MetersToBCPixels(HalfWidth * 2)
Dim height As Int = x2.MetersToBCPixels(HalfHeight * 2)
'need to turn the y position upside down.
rect.Initialize(xy(0) * bc.mWidth - 1, bc.mHeight - height - xy(1) * bc.mHeight, 0, 0)
rect.Width = width + 2
rect.Height = height + 2
bc.FillRect(xui.Color_Transparent, rect)
UpdateCBC
End Sub
Private Sub UpdateCBC
cbc = bc.ExtractCompressedBC(bc.TargetRect, x2.GraphicCache.CBCCache)
End Sub
Public Sub Tick (GS As X2GameStep)
If GS.ShouldDraw Then
GS.DrawingTasks.Add(x2.CreateDrawTaskFromCompressedBC(cbc, x2.WorldPointToMainBC(bw.Body.Position.X, bw.Body.Position.Y), cbc.TargetRect))
End If
End Sub
If I bang my head any more on this I'll pass out!!
ETA : I've already looked at this https://www.b4x.com/android/forum/threads/xui2d-to-collide-or-not-to-collide.97144/