merge two sprite nodes in sprite kit - objective-c

I am designing a sprite kit game where I want to merge two sprite nodes (rect shapes) together and then act and move them as one sprite node ?
I've been searching lot and I didn't find results
Is that possible in sprite kit ? and how can I do it ?
I'll appreciate any help, Thanks

Add one node as a child of the other. If you set it's node2.physicsbody.dynamic=NO; it will move as a single node. There will be separate physicsbodies but you can set them to the same category bitmask.
The answer linked here may help with notation: How to detect contact on different areas of a physicsbody

If you have two sprite nodes, you simply do this :
[firstSprite addChild:secondSprite]

Here is an answer with which I have achieved what you are looking for using SpriteKit (Swift)
First apply Physics to your scene
Example:
self.physicsWorld.gravity = CGVectorMake(0, -9.8)
physicsWorld.contactDelegate = self
let sceneBody = SKPhysicsBody(edgeLoopFromRect: self.frame)
sceneBody.friction = 1
self.physicsBody = sceneBody
self.physicsBody?.categoryBitMask = PhysicsCategory.Boarder
self.physicsBody?.contactTestBitMask = PhysicsCategory.None
self.physicsBody?.collisionBitMask = PhysicsCategory.Item
Second, Apply Physics to the two skspritenode's that you want to join together
Example
func mySpritetie1() {
spritetie1 = SKSpriteNode(imageNamed: "img1")
spritetie1.name = kAnimalNodeName
spritetie1.position = CGPoint(x: 170, y: 35)
spritetie1.size = CGSizeMake(36, 100)
spritetie1.physicsBody = SKPhysicsBody(rectangleOfSize: CGSizeMake(22, 100))
spritetie1.physicsBody?.affectedByGravity = false
spritetie1.physicsBody?.categoryBitMask = PhysicsCategory.Item
spritetie1.physicsBody?.collisionBitMask = PhysicsCategory.Boarder
spritetie1.physicsBody?.contactTestBitMask = PhysicsCategory.Monster
self.addChild(spritetie1)
}
func mySpritetie2() {
spritetie2 = SKSpriteNode(imageNamed: "img2")
spritetie2.name = kAnimalNodeName
spritetie2.position = CGPoint(x: 250, y: 60)
spritetie2.size = CGSizeMake(90, 79)
spritetie2.physicsBody = SKPhysicsBody(circleOfRadius: 25)
spritetie2.physicsBody?.affectedByGravity = false
spritetie2.physicsBody?.categoryBitMask = PhysicsCategory.Item
spritetie2.physicsBody?.collisionBitMask = PhysicsCategory.Boarder
spritetie2.physicsBody?.contactTestBitMask = PhysicsCategory.Monster
self.addChild(spritetie2)
}
Third, now joining them
Example
let joint = SKPhysicsJointFixed.jointWithBodyA(spritetie1.physicsBody!, bodyB: spritetie2.physicsBody!,
anchor: CGPointMake(CGRectGetMidX(spritetie1.frame), CGRectGetMinY(spritetie2.frame)))
self.physicsWorld.addJoint(joint)
This will join the two body at the anchor point you give.
Now you can animate any one of that (spritetie1 or spritetie2) using SKAction and the other will animate as if they are one and the same joined at the anchor point you defined.
If you feel this answer helped please do approve it. Hope it will help someone out there.
Please use this two link to learn about all thats in my code:
https://developer.apple.com/library/ios/documentation/GraphicsAnimation/Conceptual/SpriteKit_PG/Physics/Physics.html
A very basic and good tutorial to learn about simulating physics https://www.youtube.com/playlist?list=PLa41xEuH5n_pwuNm7Z3L5qxDhVE0sOEqb
Thanks

Related

How to animate geometry using the primitiveRange property in SceneKit?

I am using Apple's SceneKit to render a tube which consists of 50 triangle strips as illustrated here:
I want to animate a "growing" tube by using the primitiveRange property.
let tube = createTube() // create's tube.geometry which has 50 elements
let tubeNode = SCNNode(geometry: tube.geometry)
...
let animation = CABasicAnimation(keyPath: "geometry.elements[0].primitiveRange")
animation.fromValue = NSValue(range: NSRange(location: 0, length: 0))
animation.toValue = NSValue(range: NSRange(location: 0, length: tube.geometry.elements.count))
animation.duration = 5
animation.repeatCount = Float.infinity
tubeNode.geometry?.addAnimation(animation, forKey: "don't care")
scene.rootNode.addChildNode(tubeNode)
Nothing is animating (I simply see the full tube above) and I am not getting any warnings on the console. If I change the key "geometry.elements.primitiveRange" to "foo" I do get the following warning on the console
ExtrudedTube[98737:24354579] [SceneKit] Error: _C3DModelPathResolverRegistryResolvePathWithClassName unknown path (
foo
)
Perhaps this property is not animatable? I don't see documentation that says it is or isn't. Any idea how to create the "growing tube" animation using this mesh in SceneKit?
I was never able to pull off the animation using the "keypath" (I think there probably is a way to do it, but there is no documentation on the details). I can use SCNAction though it it works well:
if let numPrimitives = tubeNode.geometry?.elements[0].primitiveCount {
tubeNode.geometry?.elements[0].primitiveRange = NSRange(location: 0, length: 0)
let duration : Double = 5.0
let growTube = SCNAction.customAction(duration: duration, action: {node, elapsedTime in
let f = Double(elapsedTime)/duration
let n = Int(f*Double(numPrimitives))
node.geometry?.elements[0].primitiveRange = NSRange(location: 0, length: n)
})
tubeNode.runAction(growTube)
}

GameMaker 2: Cannot use function/script name for a variable, using "_dir"

after going through the Space Mods - GML - Enemy Factions (2/3) - GameMaker Studio 2 tutorial on YouTube by Gamemaker.
I've came into some trouble with testing the game.
My compile error goes like this:
Script:create_bullet at line 6; cannot use function/script name for a variable, using "_dir"
The script in question:
/// #description create_bullet
/// #arg direction
/// #arg speed
/// #arg faction
function create_bullet(_dir,_spd,_fac,_creator){
var _dir = argument[0];
var _spd = argument[1];
var _fac = argument[2];
var _creator = self;
audio_play_sound(snd_zap, 1, false);
var inst = instance_create_layer(x,y, "Instances", obj_bullet);
with(inst){
direction = _dir();
speed = _spd;
faction = _fac;
creator = _creator;
if(faction == factions.ally) image_blend = c_aqua;
else if(faction == factions.enemy) image_blend = c_red;
}
}
I've checked the comments to see if anyone else has had a similar problem and I can't find the solution myself. Will anyone be able to help and explain. I'm quite new to coding and just taking it step by step.
I found an answer in another forum.
My mistake seems to have been placing brackets after _dir;:
with(inst){
direction = _dir(); <=
speed = _spd;
faction = _fac;
creator = _creator;
After removing that and taking out the var before:
_dir = argument[0];
_spd = argument[1];
_fac = argument[2];
_creator = self;
It seems to work fine now.

Vulkan Instanced Rendering Weird Depth Buffer Behaviour

I am rendering a single mesh test object that contains 8000 cubes, 1 monkey, and 1 plane. I checked normals and winding orders. all seems correct for mesh.
if I render a single instance, the depth buffer works correctly. if I render using instanced when instant number increase depth buffer doesn't work correctly.
//Depth Attachment
//Create Depth Image
depthImage = new Image(
physicalDevice_,
logicalDevice_,
VK_IMAGE_TYPE_2D,
depthFormat,
VK_IMAGE_TILING_OPTIMAL,
swapChainExtent.width,
swapChainExtent.height,
1,
sampleCount_, //do we really need to sample depth????
VK_IMAGE_LAYOUT_UNDEFINED,
VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
depthImageView = new ImageView(
logicalDevice_,
VK_IMAGE_VIEW_TYPE_2D,
depthImage->handle,
depthFormat,
1,
VK_IMAGE_ASPECT_DEPTH_BIT);
//Render pass Depth Attachment
VkAttachmentDescription depthAttachment{};
depthAttachment.format = depthFormat;
depthAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
depthAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
depthAttachment.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
depthAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
depthAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
depthAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
depthAttachment.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
//Graphics Pipeline
VkPipelineDepthStencilStateCreateInfo depthStencil{};
depthStencil.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
depthStencil.depthTestEnable = VK_TRUE;
depthStencil.depthWriteEnable = VK_TRUE;
depthStencil.depthCompareOp = VK_COMPARE_OP_LESS;
depthStencil.depthBoundsTestEnable = VK_FALSE;
depthStencil.minDepthBounds = 0.0f; // Optional
depthStencil.maxDepthBounds = 1.0f; // Optional
depthStencil.stencilTestEnable = VK_FALSE;
depthStencil.front = {}; // Optional
depthStencil.back = {}; // Optional
Below the screen is the view from the 100th instance of that mesh.
The higher the instance number, the more the depth buffer deteriorates.
The result is still the same if I use a different model.
What am I missing?
Result:
Depth Buffer:
For those who may struggle with similar issue. I found a solution.
Actually, this issue is not related to instancing directly but it's a bit confusing issue becomes visible as the instance index increases.
the cause is projection matrix z-near value was so small.
...
fieldOfView = 65.0f;
znear = 0.001f; // ! this much small value cause this problem
zfar = 5000.0f;
...
changed z-near to an acceptable value. Problem solved.
...
fieldOfView = 65.0f;
znear = 0.1f;
zfar = 5000.0f;
...

Cannonjs move body forward according to its quaternion

I'm struggling with Cannonjs physics lib, I got a sphere body with a changing quaternion, I just want that body to move forward according to its quaternion. I found many topics related to that but none of the suggested codes is working.
Is it a simple way to achieve that simple task?
So far I tried the solution given here but the using of vmult() method do not change the vector3 at all...
body.quaternion = new CANNON.Quaternion(0,1,0,0); // Whatever value you put here will not change the result of the vmult() operation below
var localVelocity = new CANNON.Vec3(0, 0, 1);
var worldVelocity = body.quaternion.vmult(localVelocity); //-> worldVelocity = (0,0,1)
body.velocity.copy(worldVelocity);
Try to set and not copy the body.velocity, this way:
let directionVector = new CANNON.Vec3(0, 0, 1);
directionVector.z -= moveDistance;
directionVector = vehicleBody.quaternion.vmult( directionVector );
vehicleBody.velocity.set( directionVector.x, directionVector.y, directionVector.z );

SceneKit repeat texture

For some reason, using the following material on an SCNBox keeps resulting in a stretched texture. Any idea where I'm missing something?
material.diffuse.contents = [SKTexture textureWithImageNamed:#"arrowtexture.jpg"];
material.diffuse.wrapS = SCNWrapModeRepeat;
material.diffuse.wrapT = SCNWrapModeRepeat;
You can control SKTexture's stretch this way:
material.diffuse.contentsTransform = SCNMatrix4MakeScale(3, 1, 1);