Collision Q
Blitz3D Forums/Blitz3D Beginners Area/Collision Q
| ||
I'll right, i'm back with ANOTHER question. I have a type snowball in which has the variable: id. I tried to set up collisions but how can I make it so that when id=1 it is set to playersnowball and when id=2 the collisions are set to enemy snowball. |
| ||
You'll need to specify that in your code when the snowballs are created. You can use the s\id field to specify whether a snowball is friendly or harmful. I'm suggesting 1 = friendly and 2 = harmful. So:;change this: s\id = 1 entitytype s\mesh, type_playersnowball ;to this: s\id = 2 entitytype s\mesh, type_enemysnowball Then later in your code you will check ALL snowballs at once to see if they had a collision. THEN for the ones that DO have a collision you can easily check if the collision was friendly, or harmful. ;pseudocode! if collided_entity = type_enemy and s\id = 1 damage_enemy else if collided_entity = type_player and s\id = 2 damage_player end if I can give you some more specific help on the collision detection if needed, but give it a shot! |
| ||
Just a tip, not really related to your question, but:;Making it snow! Dim snowflake(1000) For p=0 To 1000 snowflake(p)=CreateSphere() ScaleEntity snowflake(p),0.05,0.05,0.05 PositionEntity snowflake(p),Rnd(-50,50),Rnd(1,100),Rnd(-50,50) Next This may not be the best way to approach this. You've got the right idea using arrays and For loops to create snowflakes, but 1000 spheres, each containing 224 polygons (default), results in having to render 112,000 backface culled triangles per loop, which could cause some slowdown. Depending on my setup, I can usually get around 20-100 thousand before I notice slowdown, but I have a relatively old system too. Instead, I would consider using artificial sprites in place of the spheres. Artificial sprites use a quad mesh (2 triangles) with an image for a texture, and they have neat functions like always being able to face the camera so they appear to be 3D rather than 2D images. I say "artificial" because Blitz's native sprite commands aren't much better regarding speed, but there's some good replacements in the archives. I'm using JFK's Sprites Substitute, which basically uses the same function names as Blitz's, so it's easy to implement. Instead of creating 1000 spheres, you should draw a picture of a white snowflake on a black or alpha channel background, and then load the image as a sprite with the alpha flag. Then just copy the sprite 1000 times in place of your sphere, and by doing so, you will reduce the amount of triangles from 112,000 to 2,000, and that should help speed up your game and reduce the amount of stress on the CPU. Plus, you can have a complex snowflake shape without it having any effect on your processing time. I've never thought about making a game about a snowball fight, but that sounds like it would be a lot of fun to play. Good luck! |
| ||
What command would I use to check if the snowball had collided with the enemy? |
| ||
If EntityCollided(enemymesh,type_playersnowball) ;Take enemy's life away EndIf If EntityCollided(playermesh,type_enemysnowball) ;Take player's life away EndIf This is essentially the same thing as Drak's pseudo above with the lines: ;pseudocode! if collided_entity = type_enemy and s\id = 1 damage_enemy else if collided_entity = type_player and s\id = 2 damage_player end if |
| ||
Tell me why this isn't working! |
| ||
I glanced over your code, and the logic seems like it should work. The only thing missing is letting Blitz know what should collide with what and what happens when they do. To do this, you need to add in a "Collisions" command for each type of collision you want. I typically do this right before the main loop so that I don't mistakenly add new collision types later and forget to add a corresponding "Collisions" command. Also, if you're planning on using an imaginary bubble around your entity for collision detection (such as the player camera), you need to also use EntityRadius(). For your purposes, this should help: ;Change this spot of code for your player loading ;Player player=CreateCamera() CameraFogRange player,0.1,400 CameraFogMode player,True CameraClsColor player,100,130,150 CameraFogColor player,100,130,150 ;HERE'S A NEW COMMAND, ENTITYRADIUS EntityRadius player,1,2 ;Play around with the values until it looks right EntityType player,type_player ;Then, right before you call the Main, add these lines Collisions type_player,type_enemysnowball,1,1 Collisions type_enemy,type_playersnowball,2,1 ;############### ;# Main Loop # ;############### ;.... Read up on the Collisions command in the manual if this is confusing. Basically, if you add in those lines, it should work (I think it will, I haven't tested it, I've just read over the logic). EDIT: The way this is set up, you will need some way to let Blitz know that once a snowball collides, it should not be checked for damage again. Otherwise, one hit from a snowball will continually drain your health until the game ends. You can either delete the snowball, or better yet, add in an additional field for the snowball type that keeps track if that particular snowball has already taken life away. If you use the latter, then you have more options such as making the snowball splat on the screen and then gradually melt away. If you need help, feel free to ask. Last edited 2012 |
| ||
First create a sorta "Collision type" or.. a variable which defines which objects u will be colliding. IE: Then, afterwords, define which type of collision it is. Is it a 1: sphere-to-sphere collision, 2: sphere-to-polygon collision, or 3: sphere-to-box collision ? Next, you need to define whether it's a 1: stop collision, 2: a full sliding collision, or 3: a non-sliding slope collision. IE: Now, what you want to do, is apply an "EntityType" to each object. Here's an example: Hope this helps! :) |
| ||
Rez you didn't add anything useful to his code. You're still missing the actual Collision command that sets up the actual collisions, as Rob said. |
| ||
My name is Thundros now -.- Here's a fix: |
| ||
The snowball hits the enemy but slides over it and does not decrease the variable enemyhealth. Why! Why!! P.S Thanks for all your help! |
| ||
The first thing to assume is that the snowball is not colliding. In the If statement where you decrease the player's health, either add in a DebugLog command, or if your not familiar how that works, just add in an "End" command. For example:If EntityCollided(enemy,type_playersnowball) End enemyhealth = enemyhealth - 1 EndIf If the snowball is successfully colliding, the program should end on its own as soon as the player snowball touches the enemy. If the program never ends, then you know the snowball is not colliding with the enemy. Start with that, and let me know what the results are. It might be a while before I respond, but go with that for now. |
| ||
ok cool ill try it. |
| ||
No the program does not end. |
| ||
Then what we've gathered from this is that something is wrong with the collision system. Things to check are: 1. Does every entity involved in collisions have an EntityType() assigned to it? I know you're using types for your snowballs, which is perfect, but make sure whenever you create a new snowball, you give it a collision type. e.g. s.snowball = New snowball s\entity = CreateSphere() EntityType(s\snowball,type_playersnowball) 2. Have you called a Collisions() command at least once in your program? You can assign entity's their collision types until you're blue in the face, but it won't mean anything unless you tell Blitz that you want two types to collide with each other. e.g. Collisions type_player,type_level,2,3 Collisions type_snowball,type_enemy,2,1 Collisions type_this,type_that,1,1 ;ect. As a sub note, make sure you call them in the correct order. For your program, your snowballs are round, and therefore, you want to use EntityRadius() on them. Then, when you check for collisions with them, make sure their entity type is first in the list, such as "Collisions type_playersnowball,type_enemy,2,1". This is because you want Blitz to use their radius against either the radius, exact shape, or bounding box of the enemy, and if it was reversed, it may not collide successfully. 3. Are you calling UpdateWorld() before RenderWorld()? If you neglect to include an UpdateWorld() command, no collisions with ever be checked. 4. Are you using EntityRadius() at all, and if so, is your radius too large or too small? If you aren't using this command, it's OK because Blitz will assume an object has an EntityRadius of 1 unit surrounding it. I imagine that your snowballs are fine, but they might pass through other objects if the radius is too small. For complex geometry, it would be even better to use mode 2 in the Collisions() command (radius against polygons), and this ensures that the snowball will hit the enemy. But, if you're using collision mode 1 (radius against a radius), the enemy radius might be small enough where it will pass right through the enemy except for the 1x1 sphere right in the center of mass of your enemy. 5. Do other collision commands work? Instead of this: If EntityCollided(enemy,type_snowball) End EndIf Try this: If MeshesIntersect(enemy,s\snowball) End EndIf The second option will check if ANY part of the snowball is within any part of the enemy. Take caution, because MeshesIntersect() is a very slow command, but it is useful to know for sure whether or not you are receiving any kind of collision at all. 6. If all the above fails, try this: Global type_playersnowball = 1 Global type_enemy = 2 enemy = LoadMesh("enemy.b3d") EntityType enemy,type_enemy s.snowball = New snowball s\entity = CreateSphere() EntityType(s\snowball,type_playersnowball) Collisions type_playersnowball,type_enemy,2,3 While Not KeyDown(1) PointEntity s\entity,enemy MoveEntity s\entity,0,0,0.1 If EntityCollided(enemy,type_playersnowball) End EndIf UpdateWorld RenderWorld Flip Wend End This will ensure that the snowball will touch the enemy if the program runs long enough. Eventually, it will end, but if it doesn't, then it's time to post some code and we'll see if we can't figure out what's going wrong. Hopefully this all helps. |
| ||
I believe you have to discern which snowball is colliding with the enemy to fix this. The EntityCollided() command only tells you that ONE of the snowballs collided with an enemy, and not which one. You'll have to have your coding figure out which snowball hit the enemy, then act accordingly. If you could edit your code so it contains no loaded media and repost it, I could help out better. You can always load your media after you get everything working with primitives. |
| ||
Can't you CountCollisions() and return the collision entity involved? |
| ||
Yes that's exactly how it's done. With that command you can pick out which entity (of the Type snowball) had the collision. Let me switch computers and I'll post an example for LLama. |
| ||
Ok try adding this: For this to work you need 2 global variables initiated at the beggining of the program: Global collision_id Global collision_entitiy And add this function into your program instead of the other entitycolided() commands: Function snowball_collisions() ;This will work for various collisions that can be added later, example if you want a different collision for the snowfort, etc For s.snowball = Each snowball ;For EACH snowball For collision_id = 1 To CountCollisions(s\mesh) ;Assign a temporary collision id# to each collision this particular snowball has collision_entity = CollisionEntity(s\mesh, collision_id) ;Now we store WHICH entity the snowball collided with If GetEntityType(collision_entity) = type_enemy ;If the collided entity is a TYPE_ENEMY enemyhealth = enemyhealth - s\damage ;reduce the enemie's health by the snowball damage factor FreeEntity s\mesh ;delete the snowball mesh Delete s ;delete the reference to it If enemyhealth <= 0 Then FreeEntity enemy ;delete the enemy if it's dead Exit End If Next Next End Function |
| ||
I added a few things and altered a few things. I replaced all the media with primitive objects to get things working. There were a number of small errors, some as small as a spelling error, but you should be able to build off of this. The collision does work now. Let us know if there's anything else we can help with! |
| ||
Edit: Figured it out on my own! Ha Ha! Last edited 2012 |