Swift Sprite Nodes Colliding - swift

I want to enable two SKSpriteNodes to pass through one another. From my understanding the following code should do the trick:
beam?.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: beam!.size.width - 40, height: beam!.size.height/4));
beam?.physicsBody?.categoryBitMask = ColliderType.BEAM;
beam?.physicsBody?.contactTestBitMask = ColliderType.ENEMY;
beam?.physicsBody?.collisionBitMask = 0;
beam?.physicsBody?.affectedByGravity = false;
beam?.physicsBody?.allowsRotation = false;
item?.physicsBody?.categoryBitMask = ColliderType.CRATES;
item?.physicsBody?.contactTestBitMask = ColliderType.PLAYER;
item?.physicsBody?.collisionBitMask = ColliderType.GROUND;
item?.physicsBody?.affectedByGravity = true;
item?.physicsBody?.allowsRotation = false;
As neither should be picked up by the by the other's collider type. I have tried many different methods already including setting their collision bit masks to 0.
When the two nodes collide the item moves below the beam. Then when the beam disappears the item moves back into its original place. The item must remain dynamic to other nodes, but advice on this topic is greatly appreciated. Thanks.
struct ColliderType {
static let PLAYER: UInt32 = 0;
static let GROUND: UInt32 = 1;
static let CRATES: UInt32 = 2;
static let BULLET: UInt32 = 3;
static let ENEMY: UInt32 = 4;
static let EXPLOSION: UInt32 = 5;
static let UFO: UInt32 = 6;
static let UFOBOMB: UInt32 = 7;
static let SHIELD: UInt32 = 8;
static let BEAM: UInt32 = 9;
}

Related

how to calculate the byte sum of struct in swift

this is the code in OC
It is not easy for me to convert it to swift, especially the calculate of check sum part
If anyone knows how to write, please let me know. Thank you.
OC Code:
MessageToOnboard {
unsigned char header[2];
ushort length;
uint8_t msgID;
uint missionID;
ushort wayPointID;
double lon;
double lat;
float height;
unsigned char wayPointAction;
// unsigned long reserve;
unsigned char checkSum;
}
MessageToOnboard message;
message.header[0] = 'Q';
message.header[1] = 'Z';
message.msgID = 0x21;
message.missionID = 12;
message.wayPointID = 10;
message.lon = 34.2323242;
message.lat = 68.2121221;
message.height = 30;
message.wayPointAction = '2';
message.length = sizeof(message) -5;
uint8_t *msgBIn = (uint8_t *)&message;
int iLength = sizeof(message);
uint8_t icheckSum = 0;
for (int i = 0 ; i < iLength - 3; i++)
{
icheckSum += *(msgBIn+2+i);
}
message.checkSum = icheckSum;
NSData *data = [[NSData alloc] initWithBytes:&message length:sizeof(message)];
Swift Code:
I tried this, but it is not right, I don't know how to use pointer to calculate the sum bytes of struct in swift
let msgBIn = withUnsafePointer(to: &message) {$0}
print(msgBIn.pointee)
let iLength: Int = MemoryLayout<MessageToOnboard>.size
let icheckSum: UInt8 = 0
for i in 0..<iLength - 1 {
let pointer = msgBIn.advanced(by: 2 + i)
icheckSum += UInt8(pointer)
}
finally, solved this problem
Message is a Struct
func sumByte(msg: inout Message) -> UInt8 {
let pointer = withUnsafePointer(to: msg) {UnsafeRawPointer($0)}
var sum: UInt8 = 0;
for i in 0..<(MemoryLayout<Message>.size) {
let nextP = pointer.advanced(by: i)
sum += nextP.load(as: UInt8.self)
}
return sum;
}

Swift scene kit - cant apply velocity WHILE doing rotation? Direction is off?

Ok, so Im going straight off Apple's tutorial using a joystick moving an SCNNode for SceneKithere.
I've copied the code and gotten the joystick to both move and rotate the character - but not simultaneously, and not in the right direction relative to the node.
All the correct code is in that download, but what I've done is here is where I get the angle offset of the joystick handle and the float2 from the joystick UI-
characterDirection = float2(Float(padNode.stickPosition.x), -Float(padNode.stickPosition.y))
let direction = theDude.characterDirection(withPointOfView: renderer.pointOfView)
directionAngle = CGFloat(atan2f(direction.x, direction.z))
public func characterDirection(withPointOfView pointOfView: SCNNode?) -> float3 {
let controllerDir = theDude.direction //THIS ISNT BEING UPDATED
if controllerDir.allZero() {
return float3.zero
}
var directionWorld = float3.zero
if let pov = pointOfView {
let p1 = pov.presentation.simdConvertPosition(float3(controllerDir.x, 0.0, controllerDir.y), to: nil)
let p0 = pov.presentation.simdConvertPosition(float3.zero, to: nil)
directionWorld = p1 - p0
directionWorld.y = 0
if simd_any(directionWorld != float3.zero) {
let minControllerSpeedFactor = Float(0.2)
let maxControllerSpeedFactor = Float(1.0)
let speed = simd_length(controllerDir) * (maxControllerSpeedFactor - minControllerSpeedFactor) + minControllerSpeedFactor
directionWorld = speed * simd_normalize(directionWorld)
}
}
return directionWorld
}
I didn't write the last part and still trying to understand it. But what is relevant is I have a float3 and an angle, and they are conflicting when I try to run them both as SCNActions in my renderer update func:
Here is what Apple basically had in update:
// move
if !direction.allZero() {
theDude.characterVelocity = direction * Float(characterSpeed)
var runModifier = Float(1.0)
theDude.walkSpeed = CGFloat(runModifier * simd_length(direction))
// move character - IMPORTANT
theDude.directionAngle = CGFloat(atan2f(direction.x, direction.z))
theDude.node.runAction(SCNAction.move(by: SCNVector3(theDude.characterDirection(withPointOfView: theDude.node)), duration: TimeInterval(40))) //HERE - random time
theDude.isWalking = true
} else {
theDude.isWalking = false
theDude.node.removeAllActions()
}
}
Where on the commented line I applied the move and here Apple had the rotation applied:
var directionAngle: CGFloat = 0.0 {
didSet {
theDude.node.runAction(
SCNAction.rotateTo(x: 0.0, y: directionAngle, z: 0.0, duration: 0.1, usesShortestUnitArc:true))
}
}
They are both happening, problem is I don't know really what to put as my time and my node moves say, left when I have the joystick pointed right, etc because I am not doing the move correctly.
I tried to copy the demo but they have a moving floor, so it is different. What am I doing wrong here?

Unity 5.5 Warning CS0618 "ParticleSystem.startColor" is obsolete: "Start [duplicate]

Before 5.5 particle system variables could be accessed via ParticleSystem and were read/write. Now they're accessed via ParticleSystem.MainModule and thus a lot of code has become obsolete. The API Updater has not been able to fix most of the issues. I've read through the new documentation but I can't figure out how the new variable types are supposed to be used. For example in JetParticleEffect.cs this line causes a warning:
// set the original properties from the particle system
m_OriginalLifetime = m_System.startLifetime;
The warning states: 'ParticleSystem.startLifetime' is obsolete: 'startLifetime property is deprecated. Use main.startLifetime or main.startLifetimeMultiplier instead.'
I've tried the following:
m_OriginalLifetime = m_System.main.startLifetime;
// error: Cannot implicitly convert type 'UnityEngine.ParticleSystem.MinMaxCurve' to 'float'
I believe the answer has something to do with the minMaxCurve constant variables as this compiles:
m_OriginalLifetime = m_System.main.startLifetime.constant;
But there is almost no explaination in the docs. Can anyone shed some light on this?
Also, where do the new multipliers fit in? I assume where previously you could do this:
particle.startSize *= myMultiplier
... you should now do this?
particle.main.startSizeMultiplier = myMultiplier
particle.startLifetime:
First of all, what Unity did in Unity 5.5 was to add new futures to the ParticleSystem. They also exposed some ParticleSystem API that was hidden before.
ParticleSystem.MainModule.startLifetime is now a type of MinMaxCurve instead of float like ParticleSystem.startLifetime.
By doing this, you are now given more options such as modifying the startLifetime as a curve.
Reading or writing to ParticleSystem.MainModule.startLifetime depends on the value of ParticleSystem.MainModule.startLifetime.mode which is set through the Editor or via code.
The default value of ParticleSystem.MainModule.startLifetime.mode is ParticleSystemCurveMode.Constant
So your m_OriginalLifetime = m_System.main.startLifetime.constant; is fine.
If startLifetime is dynamically or randomly changed to another mode during run-time, then you will have to do something like this:
ParticleSystem m_System = GetComponent<ParticleSystem>();
ParticleSystem.MainModule main = m_System.main;
ParticleSystem.MinMaxCurve minMaxCurve = main.startLifetime;
if (minMaxCurve.mode == ParticleSystemCurveMode.Constant)
{
m_OriginalLifetime = m_System.main.startLifetime.constant;
}
else if (minMaxCurve.mode == ParticleSystemCurveMode.Curve)
{
AnimationCurve animCurveLifetime = m_System.main.startLifetime.curve;
}
...
particle.startSize:
The-same thing apply to particle.startSize.
The particle.startSize property is now m_System.main.startSize;
Although you can't do m_System.main.startSize.constant *= myMultiplier; because your old code was particle.startSize *= myMultiplier.
You need to get m_System.main.startSize, modify it then assign the modified m_System.main.startSize back to m_System.main.startSize.
particle.startSize *= myMultiplier should be:
ParticleSystem m_System = GetComponent<ParticleSystem>();
ParticleSystem.MainModule main = m_System.main;
ParticleSystem.MinMaxCurve minMaxCurve = main.startSize; //Get Size
minMaxCurve.constant *= myMultiplier; //Modify Size
main.startSize = minMaxCurve; //Assign the modified startSize back
Then, what are particle.main.startSizeMultiplier and particle.main.startSize used for?
This two variables can also be used to change startLifetime and startSize. It's main advantage is that it is very efficient. It does not not require that you make a copy of MinMaxCurve like we did above, in order to change startSize or startSizeMultiplier.
ParticleSystem m_System = GetComponent<ParticleSystem>();
ParticleSystem.MainModule main = m_System.main;
main.startSizeMultiplier = 5;
and
ParticleSystem m_System = GetComponent<ParticleSystem>();
ParticleSystem.MainModule main = m_System.main;
main.startLifetimeMultiplier = 8;
Use them if your ParticleSystem.MainModule.startLifetime.mode is constant. This will to change the overall lifetime multiplier or the the overall size multiplier efficiently.
Changing Color and Color Modes
Color:
There is an implicit operator that lets you use:
ParticleSystem.MainModule main = trailPartical.main;
main.startColor = Color.red;
but startColor is not actually type of Color. The startColor variable is now a type of ParticleSystem.MinMaxGradient.
This is how you should be changing the particle startColor:
//Create Color
ParticleSystem.MinMaxGradient color = new ParticleSystem.MinMaxGradient();
color.mode = ParticleSystemGradientMode.Color;
color.color = Color.red;
//Assign the color to your particle
ParticleSystem.MainModule main = trailPartical.main;
main.startColor = color;
Gradient:
public ParticleSystem particleSystem;
void Start()
{
//Create Gradient key
GradientColorKey[] gradientColorKey;
gradientColorKey = new GradientColorKey[3];
gradientColorKey[0].color = Color.red;
gradientColorKey[0].time = 0f;
gradientColorKey[1].color = Color.blue;
gradientColorKey[1].time = 0.5f;
gradientColorKey[2].color = Color.green;
gradientColorKey[2].time = 1f;
//Create Gradient alpha
GradientAlphaKey[] gradientAlphaKey;
gradientAlphaKey = new GradientAlphaKey[3];
gradientAlphaKey[0].alpha = 1.0f;
gradientAlphaKey[0].time = 0.0f;
gradientAlphaKey[1].alpha = 0.5f;
gradientAlphaKey[1].time = 0.5f;
gradientAlphaKey[2].alpha = 1f;
gradientAlphaKey[2].time = 1f;
//Create Gradient
Gradient gradient = new Gradient();
gradient.SetKeys(gradientColorKey, gradientAlphaKey);
//Create Color from Gradient
ParticleSystem.MinMaxGradient color = new ParticleSystem.MinMaxGradient();
color.mode = ParticleSystemGradientMode.Gradient;
color.gradient = gradient;
//Assign the color to particle
ParticleSystem.MainModule main = particleSystem.main;
main.startColor = color;
}
Random Between Two Colors:
//Create Color from Gradient
ParticleSystem.MinMaxGradient color = new ParticleSystem.MinMaxGradient();
color.mode = ParticleSystemGradientMode.TwoColors;
color.colorMin = Color.red;
color.colorMax = Color.green;
//Assign the color to the particle
ParticleSystem.MainModule main = particleSystem.main;
main.startColor = color;
Random Between Two Gradients:
public ParticleSystem particleSystem;
void Start()
{
//Create Gradient key Min
GradientColorKey[] gradientColorKeyMin;
gradientColorKeyMin = new GradientColorKey[3];
gradientColorKeyMin[0].color = Color.red;
gradientColorKeyMin[0].time = 0f;
gradientColorKeyMin[1].color = Color.blue;
gradientColorKeyMin[1].time = 0.5f;
gradientColorKeyMin[2].color = Color.green;
gradientColorKeyMin[2].time = 1f;
//Create Gradient alpha Min
GradientAlphaKey[] gradientAlphaKeyMin;
gradientAlphaKeyMin = new GradientAlphaKey[3];
gradientAlphaKeyMin[0].alpha = 1.0f;
gradientAlphaKeyMin[0].time = 0.0f;
gradientAlphaKeyMin[1].alpha = 0.5f;
gradientAlphaKeyMin[1].time = 0.5f;
gradientAlphaKeyMin[2].alpha = 1f;
gradientAlphaKeyMin[2].time = 1f;
//Create Gradient key Max
GradientColorKey[] gradientColorKeyMax;
gradientColorKeyMax = new GradientColorKey[3];
gradientColorKeyMax[0].color = Color.red;
gradientColorKeyMax[0].time = 0f;
gradientColorKeyMax[1].color = Color.blue;
gradientColorKeyMax[1].time = 0.5f;
gradientColorKeyMax[2].color = Color.green;
gradientColorKeyMax[2].time = 1f;
//Create Gradient alpha Max
GradientAlphaKey[] gradientAlphaKeyMax;
gradientAlphaKeyMax = new GradientAlphaKey[3];
gradientAlphaKeyMax[0].alpha = 1.0f;
gradientAlphaKeyMax[0].time = 0.0f;
gradientAlphaKeyMax[1].alpha = 0.5f;
gradientAlphaKeyMax[1].time = 0.5f;
gradientAlphaKeyMax[2].alpha = 1f;
gradientAlphaKeyMax[2].time = 1f;
//Create Gradient Min
Gradient gradientMin = new Gradient();
gradientMin.SetKeys(gradientColorKeyMin, gradientAlphaKeyMin);
//Create Gradient Max
Gradient gradientMax = new Gradient();
gradientMax.SetKeys(gradientColorKeyMax, gradientAlphaKeyMax);
//Create Color from Gradient
ParticleSystem.MinMaxGradient color = new ParticleSystem.MinMaxGradient();
color.mode = ParticleSystemGradientMode.TwoGradients;
color.gradientMin = gradientMin;
color.gradientMax = gradientMax;
//Assign the color to the particle
ParticleSystem.MainModule main = particleSystem.main;
main.startColor = color;
}
Random Color:
public ParticleSystem particleSystem;
void Start()
{
//Create Gradient key Min
GradientColorKey[] gradientColorKeyMin;
gradientColorKeyMin = new GradientColorKey[3];
gradientColorKeyMin[0].color = Color.red;
gradientColorKeyMin[0].time = 0f;
gradientColorKeyMin[1].color = Color.blue;
gradientColorKeyMin[1].time = 0.5f;
gradientColorKeyMin[2].color = Color.green;
gradientColorKeyMin[2].time = 1f;
//Create Gradient alpha Min
GradientAlphaKey[] gradientAlphaKeyMin;
gradientAlphaKeyMin = new GradientAlphaKey[3];
gradientAlphaKeyMin[0].alpha = 1.0f;
gradientAlphaKeyMin[0].time = 0.0f;
gradientAlphaKeyMin[1].alpha = 0.5f;
gradientAlphaKeyMin[1].time = 0.5f;
gradientAlphaKeyMin[2].alpha = 1f;
gradientAlphaKeyMin[2].time = 1f;
//Create Gradient key Max
GradientColorKey[] gradientColorKeyMax;
gradientColorKeyMax = new GradientColorKey[3];
gradientColorKeyMax[0].color = Color.red;
gradientColorKeyMax[0].time = 0f;
gradientColorKeyMax[1].color = Color.blue;
gradientColorKeyMax[1].time = 0.5f;
gradientColorKeyMax[2].color = Color.green;
gradientColorKeyMax[2].time = 1f;
//Create Gradient alpha Max
GradientAlphaKey[] gradientAlphaKeyMax;
gradientAlphaKeyMax = new GradientAlphaKey[3];
gradientAlphaKeyMax[0].alpha = 1.0f;
gradientAlphaKeyMax[0].time = 0.0f;
gradientAlphaKeyMax[1].alpha = 0.5f;
gradientAlphaKeyMax[1].time = 0.5f;
gradientAlphaKeyMax[2].alpha = 1f;
gradientAlphaKeyMax[2].time = 1f;
//Create Gradient Min
Gradient gradientMin = new Gradient();
gradientMin.SetKeys(gradientColorKeyMin, gradientAlphaKeyMin);
//Create Gradient Max
Gradient gradientMax = new Gradient();
gradientMax.SetKeys(gradientColorKeyMax, gradientAlphaKeyMax);
//Create Color from Gradient
ParticleSystem.MinMaxGradient color = new ParticleSystem.MinMaxGradient();
color.mode = ParticleSystemGradientMode.RandomColor;
color.gradientMin = gradientMin;
color.gradientMax = gradientMax;
//Assign the color to the particle
ParticleSystem.MainModule main = particleSystem.main;
main.startColor = color;
}

Swift: How to make sure that code is not optimized out?

I want to zero-out the contents of an UnsafeMutablePointer in Swift.
In C you usually have something like this:
void freeSecure(void *buffer, uint64_t size) {
// Create volatile pointer to make sure that the code won't be optimized away
volatile uint8_t *ptr = buffer;
for (uint64_t i = 0; i < size; i++) ptr[i] = 0x00;
free(buffer);
}
How can I achieve the same thing in Swift?
// Is extension of `UnsafeMutablePointer`
public func KC_dealloc(allocated: Int) {
if num == 0 {
self.destroy()
self.dealloc(allocated)
return
}
let byteCount = sizeof(Memory) * allocated
let ptr = UnsafeMutablePointer<UInt8>(self) // volatile???
for var i = 0; i < byteCount; i++ {
ptr[i] = 0x00
}
self.destroy()
self.dealloc(allocated)
}
Okay, I asked the same question in the Apple-developer-forum and some guy there pointed me to the memset_s-function which does what I want.
So my Swift-code should look like this:
// Is extension of `UnsafeMutablePointer`
public func KC_dealloc(allocated: Int) {
if num == 0 {
self.destroy()
self.dealloc(allocated)
return
}
let byteCount = sizeof(Memory) * allocated
let ptr = UnsafeMutablePointer<UInt8>(self) // volatile???
memset_s(ptr, byteCount, 0x00, byteCount) // Defined in C11
self.destroy()
self.dealloc(allocated)
}

Getting value from unSafeMutablePointer Int16 in Swift for audio data purposes

I'm working to convert to Swift this code which helps get me get audio data for visualizations. The code I'm working with in Obj C, which works well, is:
while (reader.status == AVAssetReaderStatusReading) {
AVAssetReaderTrackOutput *trackOutput = (AVAssetReaderTrackOutput *)[reader.outputs objectAtIndex:0];
self.sampleBufferRef = [trackOutput copyNextSampleBuffer];
if (self.sampleBufferRef) {
CMBlockBufferRef blockBufferRef = CMSampleBufferGetDataBuffer(self.sampleBufferRef);
size_t bufferLength = CMBlockBufferGetDataLength(blockBufferRef);
void *data = malloc(bufferLength);
CMBlockBufferCopyDataBytes(blockBufferRef, 0, bufferLength, data);
SInt16 *samples = (SInt16 *)data;
int sampleCount = bufferLength / bytesPerInputSample;
for (int i=0; i<sampleCount; i+=100) {
Float32 sample = (Float32) *samples++;
sample = decibel(sample);
sample = minMaxX(sample,noiseFloor,0);
tally += sample;
for (int j=1; j<channelCount; j++)
samples++;
tallyCount++;
if (tallyCount == downsampleFactor) {
sample = tally / tallyCount;
maximum = maximum > sample ? maximum : sample;
[fullSongData appendBytes:&sample length:sizeof(sample)];//tried dividing the sample by 2
tally = 0;
tallyCount = 0;
outSamples++;
}
}
CMSampleBufferInvalidate(self.sampleBufferRef);
CFRelease(self.sampleBufferRef);
free(data);
}
}
In Swift, I'm trying to write is this part:
while (reader.status == AVAssetReaderStatus.Reading) {
var trackOutput = reader.outputs[0] as! AVAssetReaderTrackOutput
self.sampleBufferRef = trackOutput.copyNextSampleBuffer()
if (self.sampleBufferRef != nil) {
let blockBufferRef = CMSampleBufferGetDataBuffer(self.sampleBufferRef)
let bufferLength = CMBlockBufferGetDataLength(blockBufferRef)
var data = NSMutableData(length: bufferLength)
CMBlockBufferCopyDataBytes(blockBufferRef, 0, bufferLength, data!.mutableBytes)
var samples = UnsafeMutablePointer<Int16>(data!.mutableBytes)
var sampleCount = Int32(bufferLength)/bytesPerInputSample
for var i = 0; i < Int(sampleCount); i++ {
var sampleValue = CGFloat(samples[i]) etc. etc.
However, when I println() sampleValue is just comes out (Opaque Value) in the console. I can't figure out how to actually read the sampleValue.
I'm new at trying to read audio data for visualization purposes. Any help on getting a buffer of audio data to work with would be helpful. Thank you.
Use stride?
let bytesPerInputSample = 4 // assumption ;)
var samplePtr = data.mutableBytes
for _ in stride(from: 0, to: data.length, by: bytesPerInputSample) {
let currentSample = Data(bytes: samplePtr, count: bytesPerInputSample)
// do whatever is needed with current sample
//...
// increase ptr by size of sample
samplePtr = samplePtr + bytesPerInputSample
}