Collision Problem.

Blitz3D Forums/Blitz3D Programming/Collision Problem.

WERDNA(Posted 2009) [#1]
Hey,

I'm having a problem with collisions in my game.

When I'm playing the game, sometimes when I try to pick up
a dot by running into it, I get an error that says memory access
violation.

Heres the code where it happens.

For Dot.Dot = Each Dot

If EntityCollided(Player,Type_Dot);<<Heres where it gives the error
If EntityDistance(Dot\en,Player) <= 0.3
MoveEntity Dot\en,0,-50,0
End If
End If


It use to be
If EntityCollided(Player,Type_Dot) = Dot\en

But then I got the error more often so I added the entity distance
code.
I think its happening when 2 dots collide with me at once.

The same thing happens with powerups AND walls!

Heres the wall code.
For Wall.Wall1 = Each Wall1
If EntityCollided(Player,Type_Wall1) = Wall\en;Memory Access Violation!
Wall\AndPlayer = 1
If EntityX(Player) > Wall\x#
Wall\x# = Wall\x# - 0.01
Else If EntityX(Player) < Wall\x#
Wall\x# = Wall\x# + 0.01
End If
PositionEntity Wall\en,Wall\x#,Wall\y#,Wall\z#
End If



How would I go about fixing this\What would cause this?

Is it the EntityRadius's are too big\small?
Just in case it helps, heres the radius sizes, and the EntityType
numbers.


Const Type_Wall1 = 1
Const Type_Wall2 = 2
Const Type_Player = 3
Const Type_Bot = 4
Const Type_Dot = 5
Const Type_Plane = 6
Const Type_Laser1 = 7
Const Type_Laser2 = 8
Const Type_PickUp = 9

Global WallRadius# = 0.1
Global PlayerRadius# = 0.1
Global BotRadius# = 0.1;0.000001
Global DotRadius# = 0.6
Global PlaneRadius# = 0.1
Global LaserRadius# = 0.1
Global PRadius# = 0.1
Global P2Radius# = 3.0


Thanks if you can fix this, and if not, thanks anyways for trying!

WERDNA


GfK(Posted 2009) [#2]
Tried turning Debug on? You'll probably get a more meaningful error message that way.


_PJ_(Posted 2009) [#3]
I'm not sure it's the cause of your issue, but I would refrain from using the Type handle reference the same as the Type.
i.e. instead of:

 For Dot.Dot = Each Dot

use
 MyDot.Dot = Each Dot

It may be confusing for the compiler to differentiate.

Anyway, backt ot he problem in hand:

Are you Delete-ing the Type instance of Dot anywhere, but not Free-ing or 0-ing the actual Entity? This may result in the Dot still appearing onscreen but the Type instance doesn't exist.


WERDNA(Posted 2009) [#4]
Debug IS turned on :(
All it says is Memory access violation, and points to the line of code
thats checking to see if Player collided with whatever.

Changing the type handle is a good idea, lol.
Its not the problem though since the Wall type is named Wall1 and the
handle is just named Wall. Although I'll change it anyways just in case.

;Dot code
For Dot.Dot = Each Dot

If EntityCollided(Player,Type_Dot);(Player,Type_Dot);Memory Access Violation!
If EntityDistance(Dot\en,Player) <= 0.3
MoveEntity Dot\en,0,-50,0
End If
End If

;If the player has Vacuum PowerUp
If Vacuum = 1
If EntityDistance(Dot\en,Player) <= 2
PointEntity Dot\en,Player
MoveEntity Dot\en,0,0,+0.1
End If
End If
;Collisions


;Delete Dots
If EntityY(Dot\en) <= -10
FreeEntity Dot\en
Delete Dot
NumOfDots2 = NumOfDots2-1
End If

Next


Heres the full dot code.
If the player touches the dot, it is moved downwards by 50.
Then at the end of the code, any Dot that is Y-10 or below is deleted.
So it appears to me that I've freed it, although this is my first 3D game
so I might be noobing out somewhere, lol.


And heres the wall code. Walls are NEVER deleted at anytime.

For Wall.Wall1 = Each Wall1
If EntityCollided(Player,Type_Wall1) = Wall\en;Memory Access Violation!
If EntityX(Player) > Wall\x#
Wall\x# = Wall\x# - 0.01
Else If EntityX(Player) < Wall\x#
Wall\x# = Wall\x# + 0.01
End If
PositionEntity Wall\en,Wall\x#,Wall\y#,Wall\z#
End If

If Wall\Hit < 0
PositionEntity Wall\en,Rand(-10,10),0,Rand(-10,10)
Wall\Hit = 50
End If

Next

;This first checks to see if wall and player collide, then checks to see
what side of the wall the player is on so he can push the wall in the
right direction. Then the wall is repositioned using its new coordinates

Then it checks to see if the walls hit points are < 0 and if so, repositions
it in a random location. The walls are NEVER at anytime deleted.
(The walls hit points lessen if it gets hit by a bullet.)

If would help, I could just upload the full game to file front.


I'll change the dot handles name though and see if that helps any.

Thanks guys,

WERDNA


Drak(Posted 2009) [#5]
I'm not sure if this will help, but it sure simplified things for me in the past. I had a simple FPS I made about 2 years back that had powerup boxes that enemies dropped. I had trouble picking them up with Blitz collisions for some reason, so totally omitted collision checking for them and used solely Entitydistance(). The bonuses dissappeared after 10 seconds so there was never more than maybe 2 or 3 in-game at once, which meant I was only doing 2-3 entitydistance calls. I could then retrieve the distance between the player and bonus, and see I was close enough to "pick" it up.

Edit:
I just noticed something.
If EntityCollided(Player,Type_Wall1) = Wall\en ;Memory Access Violation!

It looks like you're saying "if the player collided with wall type 1 is wall\en!" The computer can't decide wether this is true or not.
You want it to say "if the player collided with wall type 1 is TRUE"

If EntityCollided(Player,Type_Wall1) = 1


I myself would try commenting out your entitycollided() lines, and stick with the entitydistance() check. This should produce the same result of a collision.


Drak(Posted 2009) [#6]
I noticed something else again :)

You're checking whether or not wall\hit <= 0, but, you're not subtracing wall\hit anywhere, so it will never get to 0. Unless of course, you're doing this elsewhere, but the logical spot would be the "collision" code.


WERDNA(Posted 2009) [#7]
Uggh :(

I've been going through my code for most of the day trying to get this
fixed, but am having no success :(

If you noticed, I tried two versions of the collisions code.
The one you quoted, and this one.

If EntityCollided(Player,Type_Dot)
If EntityDistance(Dot\en,Player) <= 0.3
MoveEntity Dot\en,0,-50,0
End If
End If

It simply does one general check, to see if the player collided with ANY
dot, and then using entitydistance it only effects the closest dot.
I still get the error with this though :(

I like your entitydistance idea and think that would work out really
nicely!

Also Wall\hit IS reduced somewhere else.
Its reduced in another section of collision code that checks to see if
enemy lasers collide with the wall.

I'm uploading the full game now, so you can look through all of the code.
I made sure to heavily comment it too, because since I have worked
on this project off and on ever since I got Blitz3D, the code is not very
cohesive. Some of its a bit sloppy, some of its not. I've cleaned it up
condsiderably, but some of it is still a bit sloppy.


Thanks again for all of your help, and I'll use your entitydistance idea
if this collision problem doesn't get fixed. Although I WOULD like it to
get fixed, more so I know whats wrong and why it won't work than
anything else.

WERDNA
http://files.filefront.com/13757200
Download it here.


FlagDKT(Posted 2009) [#8]
Modify these functions as follows and let me know if it crash (had not much time to test):

Function MakeWalls1(x#,y#,z#);Make Vertical Blue Walls.
	Wall.Wall1 = New Wall1
	Wall\en = LoadMesh("Robo Attack Wall1.x")
	NameEntity wall\en,Handle(wall)  ;<-- added this
	PaintMesh(Wall\en,brushblue)
	Wall\x# = x#
	Wall\y# = y#
	Wall\z# = z#
	Wall\hit = 50
	PositionEntity Wall\en,Wall\x#,Wall\y#,Wall\z#
	ScaleEntity Wall\en,1.5,1.5,1.5
	EntityType Wall\en,Type_Wall1
	EntityRadius Wall\en,WallRadius#
End Function 

Function MakeWalls2(x#,y#,z#);Make Vertical Purple Walls.
	Wall2.Wall1 = New Wall1
	Wall2\en = LoadMesh("Robo Attack Wall1.x")
	NameEntity wall2\en,Handle(wall2)  ;<-- added this
	PaintMesh(Wall2\en,brushpurp)
	Wall2\x# = x#
	Wall2\y# = y#
	Wall2\z# = z#
	Wall2\hit = 50
	PositionEntity Wall2\en,Wall2\x#,Wall2\y#,Wall2\z#
	ScaleEntity Wall2\en,1.5,1.5,1.5
	EntityType Wall2\en,Type_Wall1
	EntityRadius Wall2\en,WallRadius#
End Function 

Function MakeWalls3(x#,y#,z#);Make Horizontal Blue Walls.
	Wall3.Wall2 = New Wall2
	Wall3\en = LoadMesh("Robo Attack Wall1.x")
	NameEntity wall3\en,Handle(wall3)  ;<-- added this
	PaintMesh(Wall3\en,brushblue)
	Wall3\x# = x#
	Wall3\y# = y#
	Wall3\z# = z#
	Wall3\hit = 50
	PositionEntity Wall3\en,Wall3\x#,Wall3\y#,Wall3\z#
	ScaleEntity Wall3\en,1.5,1.5,1.5
	EntityType Wall3\en,Type_Wall2
	EntityRadius Wall3\en,WallRadius#
	RotateEntity Wall3\en,0,90,0
End Function 

Function MakeWalls4(x#,y#,z#);Make Horizontal Purple Walls.
	Wall4.Wall2 = New Wall2
	Wall4\en = LoadMesh("Robo Attack Wall1.x")
	NameEntity wall4\en,Handle(wall4)  ;<-- added this
	PaintMesh(Wall4\en,brushpurp)
	Wall4\x# = x#
	Wall4\y# = y#
	Wall4\z# = z#
	Wall4\hit = 50
	PositionEntity Wall4\en,Wall4\x#,Wall4\y#,Wall4\z#
	ScaleEntity Wall4\en,1.5,1.5,1.5
	EntityType Wall4\en,Type_Wall2
	EntityRadius Wall4\en,WallRadius#
	RotateEntity Wall4\en,0,90,0
End Function 

Function MakeDots();Make The Dots
	For Dots = 1 To 300
		Dott.Dot = New Dot
		Dott\en = CreateSphere()
		NameEntity Dott\en,Handle(Dott)  ;<-- added this
		
		SetBuffer TextureBuffer( tex )
		EntityTexture Dott\en,DotTexture
		SetBuffer BackBuffer()
		
		Dott\x# = Rnd(-10.0000000001,10.0000000001)
		Dott\y# = -0.8
		Dott\z# = Rnd(-10.0000000001,10.0000000001)
		PositionEntity Dott\en,Dott\x#,Dott\y#,Dott\z#
		ScaleEntity Dott\en,0.1,0.1,0.1
		EntityType Dott\en,Type_Dot
		EntityRadius Dott\en,DotRadius#
		NumOfDots = NumOfDots + 1
		HideEntity Dott\en
	Next
End Function 


Function MakePowerUp(typ);Make Powerups
	P.PickUp = New PickUp
	P\en = CreateSphere()
	NameEntity P\en,Handle(P)  ;<-- added this
	P\typ = typ
	
;Speed
	If P\typ = 1
		PaintMesh(P\en,SpTexture)
	End If 
	
;Vacuum
	If P\typ = 2
		PaintMesh(P\en,VcmTexture)
	End If 
	
;Piercing(Is now bouncing Powerup instead.)
	If P\typ = 3
		PaintMesh(P\en,PrcTexture)
	End If 
	
	P\x# = Rnd(-10.0000000001,10.0000000001)
	P\y# = -0.7
	P\z# = Rnd(-10.0000000001,10.0000000001)
	PositionEntity P\en,P\x#,P\y#,P\z#
	ScaleEntity P\en,0.2,0.2,0.2
	EntityType P\en,Type_PickUp
	EntityRadius P\en,PRadius#
	MakeP2(typ,P\x#,P\y#,P\z#)
	NumOfPowerUps = NumOfPowerUps + 1
End Function 


Function MakeP2(typ2,x#,y#,z#);Make the spiffy little black spheres inside of the PowerUps.
	P2.PickUp = New PickUp
	P2\en = CreateSphere()
	NameEntity P2\en,Handle(P2)  ;<-- added this
	P2\typ = typ2
	P2\x# = x#
	P2\y# = y#
	P2\z# = z#
	
;Speed
	If P2\typ = 1
		PaintMesh(P2\en,Sp2Texture)
	End If 
	
;Vacuum
	If P2\typ = 2
		PaintMesh(P2\en,Sp2Texture)
	End If 
	
;Piercing(Is now Bouncing PowerUp.)
	If P2\typ = 3
		PaintMesh(P2\en,Sp2Texture)
	End If 
	
	PositionEntity P2\en,P2\x#,P2\y#,P2\z#
	ScaleEntity P2\en,0.1,0.1,0.1
	EntityType P2\en,Type_PickUp
	EntityRadius P2\en,P2Radius#
End Function 

Function Col()
	cc=CountCollisions(Player)
	For i=1 To cc
		ce=CollisionEntity(Player,i)
		If GetEntityType(ce)=Type_Wall1 Then
			wall.Wall1=Object.Wall1(EntityName(ce))
			If EntityX(Player) > Wall\x# 
				Wall\x# = Wall\x# - 0.01 
			Else If EntityX(Player) < Wall\x# 
				Wall\x# = Wall\x# + 0.01 
			End If 
			PositionEntity Wall\en,Wall\x#,Wall\y#,Wall\z# 
		ElseIf GetEntityType(CollisionEntity(Player,i))=Type_Dot Then
			Dott.Dot=Object.Dot(EntityName(ce))
			MoveEntity Dott\en,0,-50,0 
		ElseIf	GetEntityType(CollisionEntity(Player,i))=Type_PickUp Then
			P.PickUp=Object.PickUp(EntityName(ce))
			
			MoveEntity P\en,0,-50,0
			
			If P\typ = 1
				PlayerSpeed# = 0.2
				PowerUpTimer = 500
			End If 
			
			If P\typ = 2
				Vacuum = 1
				PowerUpTimer2 = 500
			End If 
			
			If P\typ = 3
				Piercing = 1
				PowerUpTimer3 = 500
			End If 
		ElseIf GetEntityType(CollisionEntity(Player,i))=Type_Wall2 Then
			walls.Wall2=Object.Wall2(EntityName(ce))
			If EntityZ(Player) > Walls\z#
				Walls\z# = Walls\z# - 0.01
			ElseIf EntityZ(Player) < Walls\z# 
				Walls\z# = Walls\z# + 0.01
			End If 
			PositionEntity Walls\en,Walls\x#,Walls\y#,Walls\z#
		EndIf
	Next
	
	For Wall.Wall1 = Each Wall1
		If Wall\Hit < 0
			PositionEntity Wall\en,Rand(-10,10),0,Rand(-10,10)
			Wall\Hit = 50
		End If 
		
	Next 
	
	For p.PickUp=Each PickUp
		If EntityY(P\en) <= -10
			FreeEntity P\en
			Delete P
		End If 
	Next
	
	For Dott.Dot = Each Dot
		If Vacuum = 1
			If EntityDistance(Dott\en,Player) <= 2
				PointEntity Dott\en,Player
				MoveEntity Dott\en,0,0,+0.1
			End If 
		End If 
		
		
		If EntityY(Dott\en) <= -10
			FreeEntity Dott\en
			Delete Dott
			NumOfDots2 = NumOfDots2-1
		End If 
	Next 
	
	
	For Walls.Wall2 = Each Wall2
		If Walls\Hit < 0
			PositionEntity Walls\en,Rand(-10,10),0,Rand(-10,10)
			Walls\Hit = 50
		End If
	Next 
	
End Function 



WERDNA(Posted 2009) [#9]
This might just work. Thanks for all the trouble you went to to write
this ^_^

I'll test it tommorow morning and tell you how it worked out.

Thanks again everyone.

WERDNA


WERDNA(Posted 2009) [#10]
FlagDKT, I tried your code, and although I think its much neater than
my own, it still has the same problem :(
While playing I will frequently get an error concerning this line of code.

If GetEntityType(ce)=Type_Wall1 Then

Since this error comes up even more often then previously, I think
that the game will crash at this point if something is wrong with
the dots,walls, or powerups.

But it's ok, because I tried Drak's version, where literally all I had to
do was comment out the collision code and just check entitydistance
and its working great ^_^
I've added some new features to the game, and it should be ready
for me to put in the Blitz Show Case tomorrow.

Thanks again GFK, Malice, Drak, and FlagDKT!

WERDNA


FlagDKT(Posted 2009) [#11]
Np:)
Maybe i'm wrong but you should submit this to the bugs forum, I didn't find a reason.


WERDNA(Posted 2009) [#12]
Good point.

I'll put it on the bugs forum as soon as I get a chance.

Thanks again for all of your help everyone!

WERDNA


cyberyoyo(Posted 2009) [#13]
At first sight it's difficult to see where is the problem, but in this part
If EntityCollided(Player,Type_Dot);<<Heres where it gives the error
   If EntityDistance(Dot\en,Player) <= 0.3
      MoveEntity Dot\en,0,-50,0 
   End If 
End If 


I personally wouldn't use "moveentity" as moveentity should mess with blitz internal collision system, maybe use positionentity instead, which will just warp the entity to new coordinates without performing more collisions in the blitz internal system. Just an idea.


Stevie G(Posted 2009) [#14]
@ cyberyoyo, Positionentity and moveentity are handled the same for blitz internal collisions. Both will invoke collision checks between last position and new position.


Warner(Posted 2009) [#15]
Yes, so for creating a warp, after using PositionEntity or MoveEntity, use ResetEntity to reset the collisions before using UpdateWorld.
If the error is in this line:
If GetEntityType(ce)=Type_Wall1 Then
It could be, that 'ce' is undefined. Instead, use
If ce<>0 Then If GetEntityType(ce)=Type_Wall1 Then



cash(Posted 2009) [#16]
I heven read the whole post so this may not be relevant, however I have seen these problems when the type (dot) is the last one. There is no longer anything to check but the code still runs.

To fix it you could create an extra dot outside of the gameplay area which is always there, this way you never get the last one.

Or code to ignore the function if the dot does not exist.