How to do Item Collection from one script

Hello there, I hope everyone is having a great spring. Currently, I have a game that involves collecting items in a horizontal and sometimes vertical world. I plan for there to be a lot of items in the levels so I realized that it would probably not be the best approach to create a script component specifically for the items that would require me to mount the component on each and every item node. (same thing for mounting RigidBody and Physics Collider components on the item nodes)

Instead what I am doing is attempting to program the collection of items into a main script component mounted on the scene’s canvas node. When the distance between the player and an item is less than a certain distance, the item will play a collection animation then be destroyed. However, I only can access one node at a time using cc.find or by declaring a cc.Node property in the script. Calculating the distance between all of the items and the player would also take too much CPU. How would I go about programming this, given that there may be a large number of items to collect in every level? (Or is there a better way?)

You can try to perform calculations frame by frame.

Hi @Kytos

I has similar issue on my game Crowded Streets - Game Demonstrates Why We Should Stay at Home

I had to trigger event on characters which close to player on we hit whistle or megaphone button (play test the game you’ll see).
I use 2d physics on my game. I have a circle collider on the player with “sensor” and “EnabledContactListener” attributes enabled. If something touches the sensor it triggers onBeginCollision event on player node. So I could handle nodes touching the player area. I don’t calculate distance or anything. Physics engine handles it. If you are not using physics, you may use regular colliders too.

If you want I can record avideo tutorial on this subject. Please let me know.

3 Likes

That would be a good tutorial. :smiley: I also found a different way browsing through an older thread that involves using the player node’s bounding box and checking to see if it intersects with the bounding boxes of other nodes in the scene as well.

you can use the Collider (non-physics one) and set them up on both player and items - i don’t know about its internal implementation (you can look up in the sources) if it does any internal optimizations like quad tree or similar.

you can implement a quad tree for collision yourself, if you feel adventurous.

however, i would recommend the following approach: create a CollectableItem as a child of cc.Component and attach it to each of the item. at game start, run, somewhere in the scene script

items = this.node.getComponentsInChildren(CollectableItem);

then do the bounds checks only between the player and these items.

just how many of these items are you talking about? 100? 1000000?

I was thinking 100s in a level, not necessarily in each one, but I’d like to have that flexibility.

hundreds is not really big, as long as you use squared distance (using the real distance, that computes a sqrt, might have some performance hit).

there are ready made quadtree implementations, e.g. https://www.npmjs.com/package/js-quadtree - that should help with lots of objects. in short, at the beginning of the game, you get all the collectables and push their position (and custom data set to either its node or the component) in the quad tree, then each frame, you query the list of collectables in the vicinity of the player. then you do a normal distance check on this reduced list.

also, if you’re using the simple Collider, make sure you setup groups. add a “player” and a “collectable” group and only enable collision between player and collectable.

later edit: the CollisionManager and CContact implementation (https://github.com/cocos-creator/engine/blob/9428f94afbf93f2f36ce540c15740bc19e96d4ac/cocos2d/core/collider/CCCollisionManager.js), there’s no spacial partitioning algorithm to optimize the collision, so probably you need to implement your own if lots of things need to collide.

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.