Video of what's happening exactly
Specs are:
Display being recorded 2560x1080#60hz
Display that the window goes offscreen 3840x2160#24hz (tested with 60hz too)
Windows 10
GPU Nvidia 970 GTX
Just started learning godot this week and lost hours to this strange behavior.
Godot specifics:
Scale of shapes and bodies are not modified (not to mess with physics)
Starting out trying to create an Entity class, that extends KinematicBody2D, to create instances of enemies within my game. Just using the dummy block for now to test if collisions are indeed working (stopped here due to what happened on the video)
The big dummy square that has one square texture is said Entity, with a collision with huge Y size just to test things out.
The area2d I want to trigger the signal is the small rectangle in front of the character.
Is there something I should know that is causing the signal to only fire while the debug window is on the other display? Should I just move the debug window to the other display and trust the game will work?
Code snippets
Creation of Area2D inside my animation controller
func _create_shape_with_collision(s : Shape2D, parentNode : Node) -> Node:
var ret = Area2D.new()
ret.connect('body_entered', self, '_check_body_entered')
var c = CollisionShape2D.new()
c.shape = s
parentNode.add_child(ret)
c.disabled = true
c.name = 'collision_shape'
ret.add_child(c)
return ret
signal function
func _check_body_entered(body : Node):
print(body.name)
PS: Attempted to type some stuff to help with autocomplete within Godot's interface, but my created classes were not working properly.
PS2: posted this same message on godot's reddit page, in hopes of better visibility
Make sure you have a matching Collision layer and mask in the Area2D node.
Shape2D is a resource, meaning if you don't create .new() then all CollisionShape2D are using the same instance of the shape. If anyone sets explicitly it free it's gone for everyone (so try printing if you accidentally are assigning a null shape). There's some weirdness on resizing after assigning not happening when CollisionShape2D is ready.
But also you have c.disabled = true that probably shouldn't be there.
Because #Theraot laid a path towards writing an issue on Godot's Github page, I was able to determine the cause of the above bug, while creating a minimal project.
In fact, it does not relate at all with the code, but on project settings. The physics FPS was set at 60, while my secondary screen was able to capture the event, as VSYNC was also on by default (caps FPS at refresh rate, secondary screen is 24hz).
Increasing the physics FPS to 120 (empyrical at this point) made the signal work on all displays.
Will gladly accept a better answer, explaining what are the impacts of changing such number (the strain on devices etc), if it is a bad practice or if there is another way to configure individual faster ticks for Area2Ds or PhysicsBody2Ds. Could not write such answer due to my current lack of knowledge/research. Trying to write it at this point would be a sophism.
Since i'm just coding some basic game elements while writing a Game Design Document, it's so far so good for me.
Edit:
After an insight from user #Theraot, I overlooked how different _process and _physics_process worked; For my use case, most of what I was doing should be inside _physics_process, so I could revert the engine's physics FPS back to default value.
Related
So when my player falls off the map, I want the level to reload. I have used an area2d with a collisionshape2d to create an area that will call a function when the player collides with this area. However, when the game is run with this code included, the player will animate through a few frames then the game completely freezes before I can even move the player.
func _on_Area2D_body_entered(body):
get_tree().reload_current_scene()
If I delete this code, or set monitoring to off, and re-run the game it will not freeze.
Below is a screenshot of my level design.
Level design
Any help would be greatly appreciated :) - Is this a bug or am I doing something stupid?
When I set a breakpoint on the get_tree().reload_current_scene() line the following report shows
debugger
does this mean the player is colliding with a tile - If this is the case I don't see how as the program freezes before the player touches the ground.
As I said in the comments, this line:
get_tree().reload_current_scene()
Returns a value.
Now, you have said that 0 is "continuously outputted". In this context 0 means OK, in other words: it was able to reload the scene. The problem is the "continuously" part. It means that the scene reloads and then this code is triggered, and then it reloads again, and then this code is triggered again, and so on.
Now, apparently the Area2D is colliding with the TileMap. That makes sense. If it is a collision between the Area2D and a tile upon loading the scene, you would get the observed behavior. And the way the Area2D and TileMap are positioned in the scene supports the idea.
And about fixing it. I'll give you three solutions, either of these will work, with their drawbacks and caveats:
Don't have the Area2D positioned in a way that intersects non-passable tiles. This is easy to do by moving the Area2D further down, or by removing any tiles that overlap it.
The drawback with this approach is that it is fragile. You may forget in the future and move the Area2D or add tiles or something else that make the problem return. Also, it might not work well with your intended scenario design.
Change the collision_mask and collision_layer in such way that the tiles and the Area2D do not collide. As long as the bits from the mask do not overlap the bits from the layer of the other and viceversa, Godot will not even check for a collision between them.
The main drawback with this approach is that you have limited number of layers.
There is also the fact that it is less intuitive that simply placing things in such a way they don't collide.
To make it easier to work with, assign layers to different kinds of things… Go to your Project Settings, on the General Tab, under Layer Names, and 2D Physics, and give them names (e.g. "environment", "enemies", "enemy bullets", "player", "player bullets", "items", "others").
Then you can assign to each object on collision_layer what they are, and on collision_mask set every thing they MUST collide with. With the caveat that Godot will check both ways.
In this case you would set the collision_layer of the player character physics object (the KinematicBody2D) to "player" (or similar), and put the collision_mask of the Area2D to the same, so they collide. Have the collision_layer of the TileMap set to something else (e.g. "environment") that is not in the collision_mask of the Area2D, so the Area2D and the TileMap do not collide. And set the collision_mask of the player character to something that include the layer you set to the TileMap, so the player character also collides with it. I hope that makes sense.
And, of course, you can filter on the Area2D, with a little of code. It can be checking the class, or node group, or the name of the physics body. For example you can insert at the start of the method something like this: if body.name != "player": return. So that it exits the method before it reaches reload_current_scene unless it is the correct physics body.
The drawback with this approach is that it is still checking and registering the collision, so it has worse performance that using collision_mask and collision_layer. But it will work, and it will perform OK for a small to mid sized game.
For more complex situations, you may employ a combination of these approaches (because, as I said, there is a limited number of layers, so you need to add filtering on top of it). I have a more detailed explanation of how to setup physics objects, including the techniques mentioned here, in another answer.
I have 3 scenes. one that is named "KinematicBody2D.tscn" which a KinematicBody2D node. this scene is a player which moves from left to right across the screen. I also have a scene named "mob.tscn" which is a rigidbody2d node. this scene only has the sprite and a tiny piece of code that makes it so that the mob deletes itself once it leaves the screen using the visibility notifier(I also turned of the mask square so there would be no physic) . finally I have the main scene with has the player scene inside it and instances the mob scene every so often to spawn mobs at the top of the screen.
I want to detect when the mob touches the player and give an output
please explain everything very thoughrouly as I have been trying for the past couple of days to figure it out but most of the places I have looked I didn't understand what to do and when I copied the code it didn't work. some examples of things I would like to be more clear are
where and how do I add a collision shape 2d or area2d or other nodes along those lines.
where & how to connect and write the code
thank you in advance
For this answer I will start by explaining collision layers and mask. Then move on to detecting the collision. Then filtering physic bodies and communication. And I'll mention some stuff about raycast and area, and other queries at the end. No, you don't need to know all that, but you asked for "everything very thoughrouly".
While the question is about 2D, for 3D it is mostly the same provided you use the 3D versions of the nodes. I'll mention where it differs. On that note, just in case, know that 3D objects can't collide with 2D objects.
If I say Class(2D), I mean that what I'm saying applies for both Class and Class2D.
Also, since we are talking about physics, in general you will be working in _physics_process. I'll mention any case when you need to write code somewhere else.
Collision Layers and Collision Mask
To begin with, the default values of the collision_layer and collision_mask properties is set so that everything collides with everything.
Otherwise, it can be useful to define some layers. You can go to Project Settings -> General -> Layer names -> 2d Physics (or 3d Physics if you are working in 3D), and give names to the layers there.
For example, you may have layers for these (depending on the kind o game you are doing):
The player character
The enemy characters
Player projectiles
Enemy projectiles
Collectible objects
Ground and walls
Something like that. Then you give each physics object its own collision_layer depending on what they are.
In the collision_mask you set what they can collide with※. Sometimes it is easier to think about what they can't collide with. For example, an enemy projectile should not collide with other enemy projectiles (and telling Godot to not check for those collision can help with performance). The player character probably won't interact with player projectiles, and enemy character won't interact with enemy projectiles. Similarly, the enemy characters probably won't interact with collectibles. And everything collides with ground and walls.
※: Actually an object will collide with whatever they specify in their collision mask, and any object that specify them in their collision mask. That is, collisions are checked both ways. That is changing for Godot 4.0.
You have a total of 32 layers to work with. And for some people that is not enough, and we will have to resource to other ways of filtering we will see later. Regardless, try to be efficient with your layers. Use them as broad categories.
If you want to set the collision_layer and collision_mask properties from code, you need to keep in mind that they are sets of binary flags. I have explained that elsewhere.
Setting up colliders
The kinematic, static, and rigid bodies, and also area, need CollisionShape(2D) or CollisionPolygon(2D) as child. Direct node children. This is what defines their size and shape as far as physics is concerned. Adding a sprite or other graphic node is only concerned with graphics and has no effect in physics.
If you use CollisionShape(2D), make sure to set the shape to your CollisionShape(2D). Once you picked the type of shape you want, the editor will allow you to modify it visually, or you can set its parameters in the Inspector panel.
Similarly, if you use CollisionPolygon(2D), you need to edit the polygon (which is an array of points) property of your CollisionPolygon(2D). For that the editor will allow you to draw the polygon, or you can modify the coordinates of each point in the Inspector panel.
By the way, you can have multiple of these nodes. That is, if a single CollisionShape(2D) or CollisionPolygon(2D) is not enough to specify the shape and size of your object, you can add more. On that note, be aware that the simpler they are the better the performance.
If you have a graphic node (e.g. a sprite), look for a tool menu that should appear on the top (to the right from "View") when you have it selected. There you can find options to generate a CollisionShape(2D) or CollisionPolygon(2D) from your graphic node. I find this particularly useful with MeshInstance in 3D.
A simple typical setup may look like this:
KinematicBody2D
├ CollisionShape2D
└ Sprite
Or like this (3D):
KinematicBody
├ CollisionShape
└ MeshInstance
Detecting the collision
We have two objects colliding. Either of them can detect the collision.
Detecting on a Kinematic Body
The kinematic body can only detect objects it runs into as a result of its own motion. That is, if another object hits it, it might not be able to detect it.
We have two approaches depending on whatever you use move_and_collide or move_and_collide. We could also take advantage of an area for better detection. I'll come back to that.
move_and_collide
When you move the kinematic body using move_and_collide, it returns a KinematicCollision(2D) object that tells you information of what it collided with. You can get the object it collided by checking its collider property:
var collision := move_and_collide(direction * delta)
if collision != null:
var body := collision.collider
print("Collided with: ", body.name)
move_and_slide
In the more common case you move the kinematic body with move_and_slide (or move_and_slide_with_snap). In which case you should call get_slide_collision, which also gives us a KinematicCollision(2D) object. Here is an example:
velocity = move_and_slide(velocity)
for index in get_slide_count():
var collision := get_slide_collision(index)
var body := collision.collider
print("Collided with: ", body.name)
As you can see, we use get_slide_count to figure out with how many objects the kinematic body collided (sliding included) in its motion. And then we get each one taking advantage of get_slide_collision.
Detecting on a Rigid Body
To react to rigid body collision, you need to set its contact_monitor property to true and increase its contacts_reported property. That limits the number of collisions the rigid body will track. And thus, even thought you are probably only interested on the collision with the kinematic body, you need to keep room for walls and floor or other collision that might be going on at the time.
Next you are going to use the "body_entered" and "body_exited" signals. You can connect them to a script in the same rigid body (see "About connecting signals" for how to do that). The handlers would look like this:
func _on_body_entered(body:Node):
print(body, " entered")
func _on_body_exited(body:Node):
print(body, " exited")
Even though they are called "body_entered" and "body_exited", you can think of them as beginning and ending contact. If you only care about the instant of collision, then you want "body_entered":
func _on_body_entered(body:Node):
print("Collided with: ", body.name)
Detecting on an Area
The area node is a collision object, but not a physics object. It does not push things around and thing don't push it around. Instead they pass through.
They are monitoring collision by default (controlled by the monitoring property), and also have "body_entered" and "body_exited" signals that you can use the same way as the ones in rigid body. You can set a collision_mask to control that.
Furthermore, area has "area_entered" and "area_exited" signals. That is, they can detect other areas. Which is where its collision_layer and monitorable comes in.
I'll come back to uses of area.
Pickable
You can also make collision objects (static, kinematic, rigid bodies or area) pickable with the mouse or pointing device by setting input_pickable (or input_ray_pickable in 3D) to true.
Then connect the input_event signal (or override the _input_event method) of the body or area to find out when a player clicked it.
This is how the _input_event method would look like for a 2D node:
func _input_event(viewport: Object, event: InputEvent, shape_idx: int) -> void:
pass
And this is how the _input_event method would look like for a 3D node:
func _input_event(camera: Object, event: InputEvent, position: Vector3, normal: Vector3, shape_idx: int) -> void
pass
Do not confuse these with _input.
About connecting signals
You can connect signals from the editor, in the Node panel -> Signals tab, you will find the signals of the selected node. From there you can connect them to any node on the same scene that has a script attached. And thus, you should have an script attached beforehand on the node you want to connect the signal to.
Once you tell Godot to connect a signal, it will ask you to select the node you will connect it to, and allow you to specify the name of the method that will handle it (a name is generated by default). Under "advanced" you can also add extra parameters to be passed to the method, whether or not the signal can/will wait for the next frame ("deferred"), and if it will disconnect itself once triggered ("oneshot").
By pressing the Connect button, Godot will connect the signal accordingly, creating a method with the provided name in the script of the target node if it does not exist.
It is also possible to connect and disconnect signals from code. To do that use the connect, disconnect and is_connected methods. So you can, for example, instance a scene from code, and then use the connect methods to connect the signals to and from the instance.
Filtering physic bodies and communication
We have already been over your first tool to filter collision: collision layers and masks.
Now, by whatever means you are detecting collisions, you are getting the node the collision happened with. But you need to distinguish between them.
To do that we commonly use three types of filters:
Filter by class.
Filter by group.
Filter by property.
Filter by class
To filter by class, we can use the is operator. For example:
if body is KinematicBody2D:
print("Collided with a KinematicBody2D")
Keep in mind this also works with user defined classes. So we can do this:
if body is PlayerCharacter:
print("Collided with a PlayerCharacter")
Provided that we added a const PlayerCharacter := preload("player_character.gd") in the script. Or we added class_name PlayerCharacter in our player character script.
Another way to do this is with the as operator:
var player := body as PlayerCharacter
if player != null:
print("Collided with a PlayerCharacter")
Which also gives us type safety. We can then easily access its properties:
var player := body as PlayerCharacter
if player == null:
return
print(player.some_custom_property)
Filtering by groups
Nodes also have node groups. You can set them from the editor in the Node panel -> Groups tab. Or you can manipulate them from code with add_to_group, remove_from_group. And, of course, we can check if an object is in a group with is_in_group:
if body.is_in_group("player"):
print("Collided with a player")
Filtering by property
You can, of course filter by some properties for the node. For starters, its name:
if body.name == "Player":
print("Collided with a player")
Or you could check if the collision_layer has a flag you are interested in:
if body.collision_layer & layer_flag != 0:
print("Collided with a player")
It is not straightforward to get the flag from the layer name, yet possible. I found an example elsewhere.
Communication
Once you have the object identified, you probably want to interact with it. Sometimes it is a good idea to add a method (func) to the player character explicitly to be called by other objects that collide with it.
For example, in your player character:
func on_collision(body:Node) -> void:
print("Collided with ", body.name)
And in your rigid body:
func _on_body_entered(body:Node):
var player := body as PlayerCharacter
if player == null:
return
player.on_collision(self)
You may also be interested in a signal bus, which I have explained elsewhere.
Uses of Area
You can improve upon the detection of a kinematic or static body by adding an area node as child. Give it the same collision shape as its parent, and connect its signals to it. That way you can get "body_entered" and "body_exited" on your kinematic or static body.
The setup looks something like this:
KinematicBody2D
├ CollisionShape2D
├ Sprite
└ Area2D
└ CollisionShape2D
With signals connected from Area2D to KinematicBody2D.
You can add an area to an enemy and make it larger. This is useful to define a "view cone" where enemies can detect the player. You can also combine this with raycasts to make sure the enemy has line of vision. I recommend the video The Easy Way to Make Enemies See in Godot by GDQuest.
Areas also allow you to override gravity (used by rigid bodies) locally. To do that use the properties under "Physics Overrides" in the Inspector panel. They allow you to have areas where the gravity has a different direction or strength, or even make the gravity point instead of a direction.
It is also a good idea to use areas for collectible objects, which should not cause any physic reaction (no bouncing, pushing, etc), but you still need to detect when the player collides with it.
And, of course, what I would argue is the prime use of areas: you can define areas in your map that will trigger some event when the player steps on it (e.g. a door closes behind the player).
RayCast
To detect collision on a RayCast(2D), make sure its enabled property is set to true. You can also specify the collision_mask. And make sure to set the cast_to to something sensible.
The raycast will allow you to query what physics object is in the segment from its position to where cast_to points to (the cast_to vector with the transform of the raycast applied. i.e. cast_to is relative to the raycast).
Note: no, an infinite cast_to cannot work. It is not simply a performance problem. The issue is that infinite vectors don't behave well when transformed (notably when rotated).
You can call is_colliding() to find out if the raycast is detecting something. And then get_collider() to get it. This is updated by Godot once per physics frame.
Example:
if $RayCast.is_colliding():
print("Detected: ", $RayCast.get_collider)
If you need to move the raycast and detect more often than once per physics frame, you need to call force_update_transform and force_raycast_update on it.
If you want to have have enemies avoid falling from platforms, you can use raycast to detect if there is ground ahead (example).
3D games may also use raycasts to detect what the player is looking at, or what the player clicked on. In 2D, you may want the method intersect_point I mention below.
Physic Queries
Sometimes we want to ask the Godot physics engine about stuff, without any collisions or extra nodes (such as area and raycast).
First of all, move_and_collide has a test_only parameter, which, if set to true, will give you the collision information, but not actually move the kinematic body.
Second, your rigid bodies have a test_motion method that will tell you if the rigid body would collide or not given a motion vector.
But, third… We don't need a node dedicated to raycast. We can do this:
3D: get_world().direct_space_state.intersect_ray(start, end). See PhysicsDirectSpaceState.
2D: get_world_2D().direct_space_state.intersect_ray(start, end). See Physics2DDirectSpaceState.
The 2D version of direct_space_state also gives you intersect_point which will allow you to check what physic object is in an specific point. There is also an intersect_point_on_canvas, which allows you to specify a canvas id, which is intended to match a CanvasLayer.
And the other methods you find in direct_space_state are shape casts. That is, they do not check only a segment (like the raycast) or a point (like intersect_point), but a shape.
Tutorials and resources
See the article "Tutorials and resources" on Godot's official documentation.
A note on debugging
While everything I said above are things to check if they are correct when something goes wrong. There are some tools and techniques for debugging to be aware of.
First of all, you can set breakpoints (with F9 or with the breakpoint keyword) and step through the code (F10 steps over and F11 steps into).
For debugging physics in particular you want to turn on "Visible Collision Shapes" from the debug menu.
Also, while Godot is running you can go to the Scene panel, and select the Remote tab, which will allow you to see and edit the nodes as they are on the game currently running.
You can also use the Project Camera Override option (the camera icon on the toolbar which is disabled while the game is not running) to control the camera of the running game form the editor.
And finally, you might be familiar with using print as a debugging tool. It allows you to log when an event happened and the values of variables. The visual equivalent would be to spawn visual objects (sprites or mesh instances) that show you when and where and event was triggered (perhaps using the color to convey extra information). Since Godot 3.5 includes Label3D you could use it to write some values too.
A note on copying code
Reasons why the code you copied didn't work may include that the scene tree was setup differently, or that some signal wasn't connected. However, it may also be whitespace. In GDScript whitespace is important (you can review GDScript basics). You may have to adjust the indentation level to make it work with your code. Also don't mix tabs and spaces, in particular in older versions of Godot.
A note on explaining problems
So your copied code and it didn't work. What does that mean? Did it do the wrong thing or did it do nothing? Was there any error or warning? "it didn't work" isn't a good way to describe a problem.
These Q&A sites work better if you have something you are trying to solve, such some code that does not work.
I want to encourage pointing out the specific problem. Either as a new question on this or a similar site, or as a comment to the author of the answer or tutorial that is giving you trouble. So, yes, if there is something here that is not working, tell me in the comment and I'll to improve the answer. But also go bother whoever provided the code you copied that didn't work (even if that is me again). Put some pressure on them to improve.
I'm kind of a UI buff - every "screen" in my game should transition in/out when it appears or disappears. Because my game is simple in terms of resources, I thought I'd just make each "screen" a CCLayer and define a function for the transitions, leaving everything in memory. It's turning out to be more complicated than I expected.
I think I have two main problems right now:
1) Each "screen" is a CCLayer. This looks fine, but I can't seem to stop receiving touch events, even when they are inactive. Child sprites do not seem to respect the isTouchEnabled property, so I'm hitting invisible buttons all the time.
2) I wrote a custom button class that is basically a sprite with a few separate textures for states. It uses the CCTargetedTouchDelegate protocol. I'm thinking this is a big part of the above problem.
I'm not quite clear on the CCMenu stuff. Is there a tutorial or documentation out there that better explains its designed purpose and how to use it? The documentation for cocos2d doesn't talk at all about what each class does, which makes it much, much harder to properly use the library. Also, when should I use a scene instead of layers? Can I write custom transitions?
I found that if you have multiple layers in a single scene for menus, such as for a main menu (simpler to have a layer for load game, new game, etc. than an entire scene) that if you add all of you buttons as children of the layer; then to stop them from receiving touches, simply move the layer off screen when not in use. Heres an example.
[loadLayer setPosition:CGPointMake(-1000,-1000)];
[settingsLayer setPosition:CGPointMake(-1000,-1000)];
[menuLayer setPosition:CGPointMake(0,0)];
And each time you select a button that would take you to say the load game layer just reverse it for the right layer.
[loadLayer setPosition:CGPointMake(0,0)];
[settingsLayer setPosition:CGPointMake(-1000,-1000)];
[menuLayer setPosition:CGPointMake(-1000,-1000)];
It's more convenient to use CCScenes for menus. All of the children of an inactive CCScene will not receive touch events, so you don't have to manage that behavior. CCScenes also have built-in transitions like a crossfade, but if you're like me, you'll probably just want to run an action to make the scene transition out, then call CCDirector:replaceScene.
I am using Player (Player/Stage) on the iRobot Create. The interface for getting odometry data from the robot is fairly simple: call playerc_client_read, and then if you've properly subscribed a playerc_position2d proxy, you should be able to access the proxy's members px, py, pa for distance traveled in x and y (in meters); and rotation (in radians).
I have no issue with doing this in a single threaded application -- all the odometry data is perfectly where I need it to be.
However, when I try to move the robot controller to its own thread (with pthreads), I run into some issues. The issue is that only px seems to be updated. py and pa always remain 0.
Here's the gist of the robot thread
//declare everything (including the playerc_client_t* object and playerc_position2d_t* object)
//connect to server (in pull mode or push mode, it doesn't seem to matter)
//subscribe to position2d proxy
while(!should_quit) {
playerc_client_read(client)
double xPosition = position2d->px;
double yPosition = position2d->py;
double radians = position2d->pa;
//do some stuff
sleep(10 milliseconds)
}
cleanup and unsubscribe
and sure enough, only xPosition is ever set while yPosition and radians remain 0 no matter how the robot moves.
I couldn't find anything else online, is this a known bug? Has anybody else had this issue? Can someone provide insight as to why this may be happening? Thank you.
Full disclosure: I'm a graduate student and this is for a class project.
The issue here is not necessarily with threading.
What we found is that the Create's internal odometry is very inconsistent, especially when a netbook is sitting atop it.
To get any semblance of an accurate reading, one has to set the angular velocity high enough (higher than 0.11 rads/s in our case).
This site helped explain a few things -- namely that the Creates use motor power to determine odometry, and not wheel counters or any kind of analog.
To get accurate odometry for dead reckoning tasks, one either needs to build their own accurate estimator, or use some external sensors that give better information about positional changes.
Our specific problem was caused by a thresholding in the multithreaded case that set angular velocity to low to register a change, whereas the sequential code did not have such thresholding.
I'm currently designing a game using Cocos2d. There's no code yet, as I'm still developing my ideas. But, I've run across a question I can't answer and want to know if I'm just missing something or what? Here's what I'm currently thinking:
I am "dropping" multiple blocks from the top of the screen and they move down the screen in random directions. They will eventually settle at the bottom of the screen and stack up one on top of the other. Eventually, while falling, some blocks are going to collide with others. When two blocks collide I want to test to see if certain characteristics of each block are equal (e.g. size, color, orientation, etc.). Each block is it's own object, will handle it's own movement and collision detection, and will have accessor methods for size, color, orientation, etc.
Here's my question:
Am I correct in thinking that each block is a separate unit in itself and doesn't know anything about the other blocks? Block A, for instance, collides with Block B and only knows that it collided with something, but doesn't know it was another block? If this is so, then how do I do a proper comparison? How do I tell which block has collided with which block and get access to each block's data and where do I do the comparison? In the layer?
I'd love to be pointed in a decent direction here. I'm not really sure if what I'm wanting to do is even doable? Any suggestions?
You could use a physics engine that usually comes along with cocos2d- either chipmunk or box2d. The physics engines will take care of collisions for you, and if you implement collision callbacks then you can know when two objects hit each other. You can then check the characteristics of each object and react accordingly. This tutorial on Chipmunk and cocos2d integration might be helpful.