Collision Problem.
Blitz3D Forums/Blitz3D Programming/Collision Problem.
| ||
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 |
| ||
Tried turning Debug on? You'll probably get a more meaningful error message that way. |
| ||
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. |
| ||
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 |
| ||
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. |
| ||
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. |
| ||
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. |
| ||
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 |
| ||
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 |
| ||
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 |
| ||
Np:) Maybe i'm wrong but you should submit this to the bugs forum, I didn't find a reason. |
| ||
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 |
| ||
At first sight it's difficult to see where is the problem, but in this partIf 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. |
| ||
@ cyberyoyo, Positionentity and moveentity are handled the same for blitz internal collisions. Both will invoke collision checks between last position and new position. |
| ||
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 ThenIt could be, that 'ce' is undefined. Instead, use If ce<>0 Then If GetEntityType(ce)=Type_Wall1 Then |
| ||
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. |