Variable inside lambda function is showing garbage value - c++

I am using this method in a Cocos2d X game.
void OpponentNode::discard(int cardNum)
{
log("\nOpponentNode::discard <%d>\n", cardNum);
for (int i = 0; i < vecOpponentHand.size(); i++)
{
if (vecOpponentHand.at(i) == cardNum)
{
vecOpponentHand.erase(vecOpponentHand.begin() + i);
break;
}
}
CardSprite * discardedCard;
for (int i = 0; i < vecOpponentCards.size(); i++)
{
if (vecOpponentCards.at(i)->getTag() == cardNum)
{
discardedCard = vecOpponentCards.at(i);
vecOpponentCards.erase(vecOpponentCards.begin() + i);
break;
}
}
log("\nOpponentNode::discard <%d>\n", cardNum);
discardedCard->makeFaceUp();
RotateTo * rotate = RotateTo::create(0.4 * SPEED_MULTIPLIER, 0);
MoveTo * move = MoveTo::create(0.4 * SPEED_MULTIPLIER,
origin + Vec2(visibleSize.width * 0.75, visibleSize.height * 0.6));
Spawn * spawn = Spawn::create(rotate, move, NULL);
CallFunc * callFunc = CallFunc::create(
[&]()
{
log("\nOpponentNode::discard <%d>\n", cardNum); //this one shows garbage/different value
if (delegate)
{
delegate->opponentNodeDidFinishDiscard(this, cardNum);
}
this->removeChild(discardedCard);
});
discardedCard->runAction(Sequence::create(spawn, callFunc, NULL));
log("\nOpponentNode::discard <%d>\n", cardNum);
}
Strangely, when I log the integer cardNum like above, I get different value from the log inside the lambda function. For example, I get "OpponentNode::discard <402>" from the top 2 logs and the bottom most log but get "OpponentNode::discard <64>" from the log inside the lambda function.
Other points:
The lambda block is executed last.
I mostly get values like 64 or garbage values like -15493456.
My guess is the integer cardNum is getting deallocated before the execution. Can anyone point me to the right direction?

You're capturing a reference to the cardNum parameter. I would think you want to capture that one by value.
It's not clear to me what delegate is. Assuming it's a class member then I think you just need [this, discardedCard, cardNum]. Which you could abbreviate to just [=], although I think the explicit one is clearer.

Related

Spawning Actor from array of classes UE5

I'm attempting to use SpawnActor() to spawn random actors from an array of classes. I've spent several years using UE4/UE5 blueprints, but this is my first time working in cpp in a long time. The trouble I'm running into is with the SpawnActor function, maybe I'm hooking up the parameters wrong.
Below is the code for my spawning logic in my cpp file:
void ADS_Generator::SpawnFlora()
{
FHitResult CurrentHit;
FActorSpawnParameters SpawnInfo;
for (int F = 0; F < FloraIterations; ++F)
{
if (SpawnedFlora.Num() <= MaxFlora)
{
CurrentHit = SpawnLineTrace(Vertices[FMath::RandRange(0, Vertices.Num() - 1)]);
if (CurrentHit.bBlockingHit == true)
{
if (FMath::RandRange(1, 100) >= FloraTolerance)
{
AActor* CurrentFlora = GetWorld()->SpawnActor(Flora[0], CurrentHit.ImpactPoint, FVector(0, 0, FMath::RandRange(-180, 180)), SpawnInfo);
SpawnedFlora.Add(CurrentFlora);
}
}
}
}
}
Below is the code for my header file where I declare the array of actor classes:
UPROPERTY(EditAnywhere)
TArray<TSubclassOf<class AActor>> Flora;
UPROPERTY(EditAnywhere)
TArray<TSubclassOf<class AActor>> Fauna;
The specific error I'm getting is this:
"C++ no instance of overloaded function matches the argument list
argument types are: (TSubclassOf<AActor>, FVector_NetQuantize, FVector, FActorSpawnParameters)
object type is: UWorld"
I've tried adding "::StaticClass()" as well as using "->StaticClass" to no avail.
Any thoughts or advice? I definitely need to watch some videos and brush up on my cpp, I'm very rusty.
Note: I'm using Flora[0] as a placeholder instead of randomizing the array index just to test.
Found the issue! The problem was my Rotation was defined as a plain FVector, but it needed to be converted to a rotation and then a quaternion, respectively. Below is the code, but fixed:
void ADS_Generator::SpawnFlora()
{
FHitResult CurrentHit;
FActorSpawnParameters SpawnInfo;
for (int F = 0; F < FloraIterations; ++F)
{
if (SpawnedFlora.Num() <= MaxFlora)
{
CurrentHit = SpawnLineTrace(Vertices[FMath::RandRange(0, Vertices.Num() - 1)]);
if (CurrentHit.bBlockingHit == true)
{
UE_LOG(LogTemp, Warning, TEXT("HIT!"));
if (FMath::RandRange(1, 100) >= FloraTolerance)
{
FTransform SpawnLoc;
SpawnLoc.SetLocation(CurrentHit.ImpactPoint);
SpawnLoc.SetRotation((FVector(0, 0, FMath::RandRange(-180, 180)).Rotation().Quaternion()));
SpawnLoc.SetScale3D(FVector(1, 1, 1));
AActor* CurrentFlora = GetWorld()->SpawnActor<AActor>(Flora[0]->StaticClass(), SpawnLoc, SpawnInfo);
SpawnedFlora.Add(CurrentFlora);
UE_LOG(LogTemp, Warning, TEXT("Spawned Flora!"));
}
}
else if(CurrentHit.bBlockingHit == false)
{
UE_LOG(LogTemp, Warning, TEXT("NO HIT"));
}
}
}
}
TLDR; Locations and Rotations are stored differently and I totally forgot.

How does AudioKit's AKNodeOutputPlot pull it's data?

I'm very new to the AudioKit framework and I have been trying to understand a bit more about the DSP side to it. Whilst rummaging around in the source code I realised that AKNodeOutputPlot does not pull data from the node the same way others would.
In the DSP code for the AKAmplitudeTracker an RMS value is calculated for each channel and the result is briefly written to the output buffer but at the end of the for loop the node is essentially bypassed by setting the output to the original input:
void process(AUAudioFrameCount frameCount, AUAudioFrameCount bufferOffset) override {
for (int frameIndex = 0; frameIndex < frameCount; ++frameIndex) {
int frameOffset = int(frameIndex + bufferOffset);
for (int channel = 0; channel < channels; ++channel) {
float *in = (float *)inBufferListPtr->mBuffers[channel].mData + frameOffset;
float temp = *in;
float *out = (float *)outBufferListPtr->mBuffers[channel].mData + frameOffset;
if (channel == 0) {
if (started) {
sp_rms_compute(sp, leftRMS, in, out);
leftAmplitude = *out;
} else {
leftAmplitude = 0;
}
} else {
if (started) {
sp_rms_compute(sp, rightRMS, in, out);
rightAmplitude = *out;
} else {
rightAmplitude = 0;
}
}
*out = temp;
}
}
}
This makes sense since outputting the RMS value to the device speakers would sound terrible but when this node is used as the input to the AKNodeOutputPlot object RMS values are plotted.
I assumed that the leftAmplitude and rightAmplitude variables were being referenced somewhere but even if they are zeroed out the plot works just fine. I'm interested in doing some work on the signal without effecting the output so I'd love it someone could help me figure how the AKPlot is grabbing this data.
Cheers
AKNodeOutputPlot works with something called a "tap":
https://github.com/AudioKit/AudioKit/blob/master/AudioKit/Common/User%20Interface/AKNodeOutputPlot.swift
There are also a few other taps that are not necessarily just for user interface purposes:
https://github.com/AudioKit/AudioKit/tree/master/AudioKit/Common/Taps
Taps allow you to inspect the data being pulled through another node without being inserted into the signal chain itself.

invalid operands to binary expression - when removing object

I want to remove an object from an array.
The problem is that i don't know the index, so i try the remove method.
The method is definded like this:
void ofxDTangibleManager::updateList(vector<ofxDTangible> &oldList, vector<ofxDTangible> &newList) {
Here is the part where it goes wrong:
for(int i = 0; i < oldList.size(); i++) {
if(newList.size() == 0) {
break;
}
ofxDTangible &t = oldList[i];
ofxDTangible &closest = getClosestTangible(t, newList, false);
float d = distSquared(t, closest);
if(d < maxMoveDistSquared) {
refound[i] = true;
// copy values of new one over
// todo
// set as target so we can interpoplate if required
// remove it so we make sure we don't assign it to multiple tangibles
remove(newList.begin(), newList.end(), closest);
}
}
This are the errors:
How can i get around this problem?

Is it possible to create a std::map of *CCAnimation objects?

They seem to all get autoreleased the moment I create them =s
void SceneView::createAnimation(KillerRabbit* killerRabbit, std::string animation) {
CCArray* animFrames = CCArray::createWithCapacity(15);
int first = std::stoi(killerRabbit->spriteSheetMap[animation]["FIRST"]);
int last = std::stoi(killerRabbit->spriteSheetMap[animation]["LAST"]);
char str[100] = {0};
for (int i = first; i <= last; i++) {
// Obtain frames by alias name
sprintf(str, (killerRabbit->spriteSheetMap[animation]["KEY"]+"[%d].png").c_str(), i);
CCSpriteFrame* frame = sharedSpriteFrameCache->spriteFrameByName(str);
animFrames->addObject(frame);
}
spriteAnimationsMap[killerRabbit->spriteName][animation] = CCAnimation::createWithSpriteFrames(animFrames, 0.1f);
// 14 frames * 1sec = 14 seconds
rabbitSprites[killerRabbit->spriteName][animation]->
runAction(CCRepeatForever::create(CCAnimate::create(spriteAnimationsMap[killerRabbit->spriteName][animation])));
}
If I omit this part of the code:
rabbitSprites[killerRabbit->spriteName][animation]->
runAction(CCRepeatForever::create(CCAnimate::create(spriteAnimationsMap[killerRabbit->spriteName][animation])));
And try to access the object in:
spriteAnimationsMap[killerRabbit->spriteName][animation]
In a later part of the code with another method, the object inside that map would have been autoreleased, how can I retain it so I can use the different animations stored in it at a later time?
Oh, silly me, I had to do this:
spriteAnimationsMap[killerRabbit->spriteName][animation]->retain();

Callback function confuses argument?

I have a sfml window container, and it appears to be working, however the glViewPorts are the wrong size, which I assume is because the wrong sf::Window is being passed.
Here is a function which adds to the window: It takes some information about the sfml window.
int WindowContainer::PushBack(WindowData& data)
{
if(data.WindowSettingsOK() && data.VideoModeOK()){
mWindowVector.resize(mWindowVector.size() + 1);
mDisplayFuncVector.resize(mWindowVector.size());
mInputFuncVector.resize(mWindowVector.size());
mWindowVector.at(mWindowVector.size() - 1) = new sf::Window();
mWindowVector.at(mWindowVector.size() - 1)->Create(data.VideoMode(), data.Title(), data.Style(), data.Settings());
mWindowVector.at(mWindowVector.size() - 1)->SetPosition(data.PositionX(), data.PositionY());
mDisplayFuncVector.at(mWindowVector.size() - 1) = nullptr;
mInputFuncVector.at(mWindowVector.size() - 1) = nullptr;
return 0;
}
else{
PrintError(ErrorMessageType::BadSettings);
return 1;
}
}
Alternatively, this function may be called to setup the display and input function callbacks:
int WindowContainer::PushBack(WindowData& data, function_p displayFunc, function_p inputFunc)
{
int return_val = PushBack(data);
mDisplayFuncVector.at(mWindowVector.size() - 1) = displayFunc;
mInputFuncVector.at(mWindowVector.size() - 1) = inputFunc;
return return_val;
}
Then, when the window needs .Display()'ing, this function is called:
void WindowContainer::ProcessDisplay()
{
for(unsigned int i = 0; i < mWindowVector.size(); i ++){
if(mDisplayFuncVector.at(i) != nullptr){
mDisplayFuncVector.at(i)(*mWindowVector.at(i), mClock, (const void*&)mExternalDrawingDataPointer);
}
mWindowVector.at(i)->Display();
}
}
... This is all good, until the result on the screen is that resizing one window affects the viewport of both windows. This suggests that calling the callback function: mDisplayFuncVector.at(i)(*mWindowVector.at(i), mClock, (const void*&)mExternalDrawingDataPointer); gives the argument of *mWindowVector.at(0) each time, instead of each window individually. (As in *mWindowVector.at(i))
Can anyone help with this problem?
The main loop contains this code:
while(container.Access(0)->IsOpened()){
container.ProcessInput();
container.ProcessDisplay();
}
Container.Access(int) is this function:
const sf::Window*& WindowContainer::Access(unsigned int index)
{
if(index > mWindowVector.size()){
PrintError(ErrorMessageType::IndexOutOfRange);
}
else{
return (const sf::Window*&)mWindowVector.at(index);
}
return (const sf::Window*&)mWindowVector.at(0);
}
Thanks again, I'm sure I have made a mistake somewhere but cannot spot it.
I have been thinking about this question and suspect openGL becomes confused with which window is it drawing to if more than one object is pushed back without a call to Display() to sync everything.
I am yet to test this and confirm.
EDIT The window container now works. It has nothing to do with the callback functions argument.