How to store/retrieve SCNNode position? - position

How to store and retrieve SceneKit SCNNode position ?
Any Objective C code example ?
Many thanks.

SCNNode position is an SCNVector3
// Storing the position of myNode node into nodePosition variable
SCNVector3 nodePosition = myNode.position;
However, if there is an animation or physics simulation playing .position properties of the nodes involved are not updated.
Instead, you should read .presentationNode property for the current position:
// Getting the current position of myNode
// if an animation or physics simulation is in progress
SCNVector3 nodePosition = myNode.presentationNode.position;

Related

Godot - Enemy does not move to player when player is on the left

The enemy in my game will not move towards the left when player is on the left but will move to the right. Then when the player is on the right the enemy will move to the player.
code for enemy:
extends KinematicBody2D
var run_speed = 100
var velocity = Vector2.ZERO
var collider = null
func _physics_process(delta):
velocity = Vector2.ZERO
if collider:
velocity = position.direction_to(collider.position) * run_speed
velocity = move_and_slide(velocity)
func _on_DetectRadius_body_entered(body):
collider = body
func _on_DetectRadius_body_exited(body):
collider = null
I suspect you are using an Area2D and it is detecting something other than the player character. I remind you can use collision_mask and collision_layer to narrow what objects are detected. For example, are you sure the Area2D is not detecting the enemy itself? For a quick check you can have Godot print the collider to double check it is what you expect.
Furthermore, notice that wen an object leaves the Area2D it will set collider to null regardless if there is still some object inside the Area2D or not. I remind you that an alternative approach is using get_overlapping_bodies.
And, of course, you can query each body you get to see if it is the player character (for example by checking its node group, name, class, etc...). I go over filtering in more detail in another answer.
If you are getting the player character, there is another possible source of problems: position vs global_position. The code you have like this:
position.direction_to(collider.position)
Is correct if both the enemy and the collider it got have the same parent. In that case their positions are in the same space. Otherwise, you may want to either work on global coordinates:
global_position.direction_to(collider.global_position)
Or you can bring the collider position to local coordinates:
position.direction_to(to_local(collider.global_position))
And of course, double check that the Area2D is positioned correctly. You can enable "Visible Collision Shapes" on the "Debug" menu, which will show it when running the game from the editor.

How to make a 2D sprite follow mouse in Godot

Please provide minimal code example of Sprite following the mouse in Godot. There are complex and big sample projects, but I didn't found nothing small and clear.
Put the Sprite node in the scene, and attach the following script to it.
const SPEED = 500
func _process(delta):
var vec = get_viewport().get_mouse_position() - self.position # getting the vector from self to the mouse
vec = vec.normalized() * delta * SPEED # normalize it and multiply by time and speed
position += vec # move by that vector

Change the color or texture of a SCNText node object (Swift - Scenekit)

How do I set the texture of a SCNText object? This is what I have and nothing changes in the appearance:
// myNode is a working SCNText element
let mat = SCNMaterial()
met.diffuse.contents = UIImage(contentsOfFile: "texture.png")
myNode.geometry.firstMaterial = mat
A text geometry may contain one, three, or five geometry elements:
If its extrusionDepth property is 0.0, the text geometry has one element corresponding to its one visible side.
If its extrusion depth is greater than zero and its chamferRadius property is 0.0, the text geometry has three elements, corresponding to its front, back, and extruded sides.
If both extrusion depth and chamfer radius are greater than zero, the text geometry has five elements, corresponding to its front, back, extruded sides, front chamfer, and back chamfer.
Scene Kit can render each element using a different material. For details, see the description of the materials property in SCNGeometry Class Reference.
just like for any other geometry, simply set its materials property.

Check mouse in one Model or not?

In XNA 4.0 3D. I want to Drag and Drop one model 3D.So,I must check mouse in a Model or not. My problem is I don't know change position and rate this Model from 3D to 2D. It's related Matrix View and Matrix Projection of camera??
This is my code:
http://www.mediafire.com/?3835txmw3amj7pe
Check out this article on msdn: Selecting an Object with a Mouse.
From that article:
MouseState mouseState = Mouse.GetState();
int mouseX = mouseState.X;
int mouseY = mouseState.Y;
Vector3 nearsource = new Vector3((float)mouseX, (float)mouseY, 0f);
Vector3 farsource = new Vector3((float)mouseX, (float)mouseY, 1f);
Matrix world = Matrix.CreateTranslation(0, 0, 0);
Vector3 nearPoint = GraphicsDevice.Viewport.Unproject(nearsource,
proj, view, world);
Vector3 farPoint = GraphicsDevice.Viewport.Unproject(farsource,
proj, view, world);
// Create a ray from the near clip plane to the far clip plane.
Vector3 direction = farPoint - nearPoint;
direction.Normalize();
Ray pickRay = new Ray(nearPoint, direction);
For proj and view use your own projection and view matrices accordingly.
Now when you have your Ray, you need to have a BoundingBox or a BoundingSphere (or multiple) that are roughly encompassing your model.
A simple solution is to use BoundingSphere properties of ModelMesh for each mesh in your Model.Meshes.
foreach(ModelMesh mesh in model.Meshes)
{
if(Ray.Intersects(mesh.BoundingSphere))
{
//the mouse is over the model!
break;
}
}
Since BoundingSphere of each ModelMesh is going to encompass all vertices in that mesh, it might not be the most precise representation of the mesh if it is not roughly round (i.e. if it is very long). This means that the above code could be saying that the mouse intersects the object, when visually it is way off.
The alternative is to create your bounding volumes manually. You make instances of BoundingBox or BoundingSphere objects as suits your need, and manually change their dimensions and positions based on runtime requirements. This requires slightly more work, but it isn't hard.

How to detect touches on child sprites

I'm writing a cocos2d-x application. I have a sprite with a couple of child sprites over it. These sprites represent one logical object on the screen that is transformed as a whole object. Now, when the object is touched, I need to discover which of the child sprites was touched.
The problem is that, while the parent sprite gives me all the information (bounding box, scale, rotation etc.) as it currently is, the child sprites stay with their original numbers, despite being transformed together with the parent, and I cannot figure out the correct way to calculate the "real" dimensions for the children.
As it looks to me, two facts cause all the difficulties:
The child bounding box has its initial dimensions which are reported relative to the parent's initial bounding box.
I cannot calculate the parent's initial bounding box after the parent was rotated (see the picture below), thus I cannot calculate where now is the lower left corner of the parent sprite, which I need as the relation point for child transformations.
Here's a drawing of such a situation:
So, to summarize, in order to check whether a touch hit a child sprite, I need to calculate the current bounding box of the children, based on the parent's transformations. I can calculate the scaling and the rotation of the child, but I don't know where it should be positioned relative to the parent because the parent's bounding box is very different from what it was in the beginning. Add weird anchor points to the story and it becomes even more complicated. The perfect solution would be to get the vertices of the original sprite and not the bounding box. Is it possible?
Any ideas? Am I missing something?
The source code of boundingBox() maybe helpful. You can get the affinetransform by nodeToParentTransform(),and use CCPointApplyAffineTransform to get the new position of the four points. Then you can write a new method to check if the touch locate in the new rect.
Assume you Have a parent
CCSprite* parent;
and a Child,
CCSprite* child; //child Tag is 100
you can give it a try in your touch method:
YOUR_CLASS::ccTouchBegan(CCTouch* pTouch, CCEvent* pEvent){
CCPoint touchLocation = parent->convertTouchToNodeSpace(pTouch);
if (CCRect::CCRectContainsPoint(parent->getChildByTag(100)->boundingBox(),touchLocation)){
//do something
CCLOG("touch on child");
}
}
If someone wants to find out the letters bounding boxes in a rotated label:
int maxIdx = label->getStringLength() -1;
Mat4 trans = label->getNodeToParentTransform();
for(int idx = 0; idx<=maxIdx; idx++) {
Sprite* letter = label->getLetter(idx);
Rect letterRect = letter->getBoundingBox();
Point p = PointApplyTransform(letterRect.origin, trans);
Rect rect = Rect(p.x, p.y, 10, 10); // Letter Approximation rect
}

Resources