Ambiera Forum

Discussions, Help and Support.

Ambiera Forum > CopperCube > Feature requests and bug reports
Randomize the positions of some scene nodes

TD_9844
Guest
Quote
2017-04-17 13:37:07

Hi everyone, I posted this in another thread in response to another user:

It would be nice to have a behaviour which allows you to randomize the positions of some scene nodes (random position, but attached to the floor/terrrain).

Besides this, it would be nice to choose the minimum distance between scene nodes (so do not put them too close or overlapped).

In this way the game would be more dynamic, it would be awesome...
Everytime you run the game, enemies or objects would be at different places on the scene.

I think this behavior really would make a difference between a static and dynamic game.

For example, I made 30 similar scenes for my game, it would be nice if the position of the nodes on the scene was dynamic.

Is there a behaviour for this? Or can someone please explain a way for doing this?

Thanks and sorry for my poor english.


TD_9844
Guest
Quote
2017-04-18 12:03:37

Really?

Nobody can help?

I could pay money if someone could create a behaviour that works perfectly before April 25.

Maybe niko, just_in_case or jaimezegpi?


just_in_case
Moderator
Quote
2017-04-19 06:02:58

I remember you posted this with reference to my post in open discussion...


Well ,I don't understand what you really want to do..

If your idea is to randomise positions of somescenenode when the game starts then you can do that easily...

Use the behaviour or action set random value...
Give the variable name positions...
Provide minimum and maximum value like 0 and 10

And now add another action if a variable has value do something..
Now if variable positions has value 0 then execute javascript...

Var s = Ccbgetscenenodebyname("enemy")
CcbSetscenenodeproperty (s,'position', x,y,z);



Here x,y,z are the value for position.... Add same script for all the value of variable position like upto 10... But remember to use diffrent value of x,y,z everytime...



And you can also do this in another way by using math.random.... But i think you should try learning javascript....


If you are comfortable with the above method, and if your scene contains more scennode thatn one then you can do the same thing ..
For example adding 10 positions for one scenenode to randomise...
And another 10 for another scennode...

To prevent the overlapping problem you can use diffrent variable name for diffrent character or try using difrrent minimum and maximum value...

For example we have used minimum value '0' and maximum value '10' in the above example for variable position...
Now we can either use diffrent variable like positionghost... Or we can use diffrent minimum and maximum like minmum '11' and maximum '20'...

Thus scennodes will never get overlapped....

Note:- if you want the scenenodea to be always on ground or terrain then don't change the value of 'Y', or if your scenenode has a behaviour applied 'collide whwn moved' then there will be jo problem they will always be on ground'


And there is already an behaviour for this all you had to is before starting the scene do something... Then add action change position of a scenenode select your scenenode and choose set to a random position in the area... and specify the minimum and maximum distance... Do this for all of your scenenodes... And dont use same minima and maxima to prevent from overlapping...



Sorry, i wrote too much.... Hope you understand this..


TD_9844
Guest
Quote
2017-04-19 11:05:12

Hi just_in_case,

I already knew of this method you wrote, but the problem it that I have almost 40 different scenes, and for every scene I want to randomize the position of 10-15 objects (it depends on the scene, some have 10 objects, some 15, some 12, ...).

Some scene have bigger terrain size, some have smaller.

So your solution is not a dynamic one, because for every scene I have to write a new code, not even possible to do just copy/paste because of all these differences.


Regarding the set to a random position in the area, i will try and find out... but anyway, it's not comfortable to do this for 500+ scene nodes.

If there would be a behaviour that let you choose a scene node (maybe a folder) and than randomize the positions of all his children nodes, it would be awesome!


pk12
Registered User
Quote
2017-04-19 16:08:45

Here you go - a behavior that randomizes position (and optionally rotation) of all children of given mesh node and attaches them to its surface (doesn't work for terrain however). You can also specify minimal distance between the positions. Keep in mind that it may be slow for complex surfaces!

It uses the JavaScript API Wrapper (https://github.com/pkorzeniewski...)

Let me know if something doesn't work :)


/*
<behavior jsname="behavior_RandomizeNodesPositions"
description="Randomize Nodes Positions">
<property name="RandomizeRotation" type="bool" default="false" />
<property name="MinimalDistance" type="int" default="0" />
</behavior>
*/

behavior_RandomizeNodesPositions = function() {};

behavior_RandomizeNodesPositions.prototype.onAnimate = function(_node) {
this.onAnimate = function() {};

var self = this;
var node = ccb.node.get(_node);
var bbox = node.getWorldBBox();
var positions = [];

function createPosition() {
return new ccb.vector(ccb.core.randRange(bbox.min.x, bbox.max.x), node.getWorldPosition().y, ccb.core.randRange(bbox.min.z, bbox.max.z));
}

function findPosition() {
var position = createPosition();

if(self.MinimalDistance > 0) {
_.every(positions, function(_position) {
if(position.getDistanceTo(_position) < self.MinimalDistance) {
position = findPosition();
return false;
}

return true;
});
}

return position;
}

_.each(node.getChildren(), function(child) {
var position = findPosition();

var line = new ccb.line(position.clone().sub(new ccb.vector(0, 5000, 0)), position.clone().add(new ccb.vector(0, 10000, 0)));
var intersection = node.getIntersectionWithLine(line);

if(intersection) {
position.y = intersection.y;
}

if(self.RandomizeRotation) {
var rotation = child.getRotation().clone();
rotation.y = ccb.core.randRange(0, 360);
child.setRotation(rotation);
}

child.setPosition(node.transformWorldPointToLocal(position));

positions.push(position);
});
};



TD_9844
Guest
Quote
2017-04-20 11:17:14

Wooow pk2 I think that this is exactly what am I looking for.

I have not tried it yet because I have some questions:

- Do I need to download the JavaScript API wrapper to make it work?

- If yes, how to install it to make it work with CopperCube?

Thank you very much, I really appreciate your help


pk12
Registered User
Quote
2017-04-20 12:16:31

Yes, you need to download the JavaScript API Wrapper but it's very easy to install (check the link https://github.com/pkorzeniewski... for instructions).


TD_9844
Guest
Quote
2017-04-20 13:42:41

Thank you pk12,
does it work for mac OS?

Because i'm using a macbook pro for my project...


pk12
Registered User
Quote
2017-04-20 15:14:33

Yes, it should work on mac OS without any problem


TD_9844
Guest
Quote
2017-04-20 16:32:50

I tried it and when i run it, it doesn't work.
If i attach the behavior "Randomize Nodes Positions" to a folder that has some objects inside as children, in the debug console i get this:
CopperCube Debug Console
string
string
string
string
string
string
string
string
string
Hello world!
action_JSAPIWrapper:6583:TypeError: xyz is undefined
If i attach the behavior "Randomize Nodes Positions" to a planeMesh with some object inside as children, in the debug console i get this:
CopperCube Debug Console
string
string
string
string
string
string
string
string
string
Hello world!
object
object
object
object
object
object
object
object
object
object
I added "Load JavaScript API Wrapper" and "Load MyGame" in "Before first drawing do something", than I tried to attach the behavior for the random position to a folder and it doesn't work, to a planeMesh and again it doesn't work.
Can you please upload a simple .ccb file with the example?


pk12
Registered User
Quote
2017-04-20 17:37:06

Please download the latest release of JavaScript API Wrapper, I've commited a small fix.

I've tested it on the following scene and it works fine:
🔎︎



TD_9844
Guest
Quote
2017-04-20 17:59:47

Thank you pk12! Now it works!
Just one last thing: is it possible to make objects attached to the surface but not trepassing it?

Now the object is half above and half below the surface:
🔎︎
I'd like the object to be attached on the surface just on the upper side.

Like if i have enemies, their feet will be attached to the surface, and not below.

Is it possible?

P.S. You did an amazing work and thank you!


TD_9844
Guest
Quote
2017-04-20 18:10:15

Another thing: for me the "minimal distance" doesn't work, does it work for you?


pk12
Registered User
Quote
2017-04-20 19:02:30

Updated behavior (objects now should be placed above terrain):

/*
<behavior jsname="behavior_RandomizeNodesPositions"
description="Randomize Nodes Positions">
<property name="RandomizeRotation" type="bool" default="false" />
<property name="MinimalDistance" type="int" default="0" />
</behavior>
*/

behavior_RandomizeNodesPositions = function() {};

behavior_RandomizeNodesPositions.prototype.onAnimate = function(_node) {
this.onAnimate = function() {};

var self = this;
var node = ccb.node.get(_node);
var bbox = node.getWorldBBox();
var positions = [];

function createPosition() {
return new ccb.vector(ccb.core.randRange(bbox.min.x, bbox.max.x), node.getWorldPosition().y, ccb.core.randRange(bbox.min.z, bbox.max.z));
}

function findPosition() {
var position = createPosition();

if(self.MinimalDistance > 0) {
_.every(positions, function(_position) {
if(position.getDistanceTo(_position) < self.MinimalDistance) {
position = findPosition();
return false;
}

return true;
});
}

return position;
}

_.each(node.getChildren(), function(child) {
var position = findPosition();

var line = new ccb.line(position.clone().sub(new ccb.vector(0, 5000, 0)), position.clone().add(new ccb.vector(0, 10000, 0)));
var intersection = node.getIntersectionWithLine(line);

if(intersection) {
position.y = intersection.y;
}

if(self.RandomizeRotation) {
var rotation = child.getRotation().clone();
rotation.y = ccb.core.randRange(0, 360);
child.setRotation(rotation);
}

position.y += child.getBBox().getSize().y / 2;

child.setPosition(node.transformWorldPointToLocal(position));

positions.push(position);
});
};

The minimal distance should work fine - keep in mind that it's the distance between center of objects, so if an object has size 10x10, the minimal distance must be set to > 10 to prevent objects from colliding.

You can also again download newest version of the wrapper - I've removed the debug logs.


TD_9844
Guest
Quote
2017-04-20 19:50:32

Thank pk12,

Have you tried it with animated meshes?

For me it doesn't work with animated meshes... do you know why?


Create reply:


Posted by: (you are not logged in)


Enter the missing letter in: "Internati?nal" (you are not logged in)


Text:

 

  

Possible Codes


Feature Code
Link [url] www.example.com [/url]
Bold [b]bold text[/b]
Image [img]http://www.example.com/image.jpg[/img]
Quote [quote]quoted text[/quote]
Code [code]source code[/code]

Emoticons


   






Copyright© Ambiera e.U. all rights reserved.
Privacy Policy | Terms and Conditions | Imprint | Contact