EXCEPTION_ACCESS_VIOLATION when using RandomPointInBoundingBox method of KismetLibrary - c++

I am facing an issue while generating a random point in a volume using KismetLibrary,
there is the code
#include "Spawner.h"
#include "Components/BoxComponent.h"
#include "Kismet/KismetMathLibrary.h"
#include "BaseCell.h"
// Sets default values
ASpawner::ASpawner()
{
// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
SpawningVolume = CreateDefaultSubobject<UBoxComponent>(TEXT("SpawnVolumeBox"));
RootComponent = SpawningVolume;
Cell = ABaseCell::StaticClass();
}
// Called when the game starts or when spawned
void ASpawner::BeginPlay()
{
Super::BeginPlay();
SpawnCells();
}
// Called every frame
void ASpawner::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
void ASpawner::SpawnCells()
{
if(Cell != NULL)
{
UWorld* const World = GetWorld();
if (World) {
FVector Origin = SpawningVolume->Bounds.Origin;
FVector Extent = SpawningVolume->Bounds.BoxExtent;
FVector SpawnLocation = UKismetMathLibrary::RandomPointInBoundingBox(Origin, Extent);
FRotator SpawnRotation;
SpawnRotation.Pitch = FMath::FRand() * 360.0f;
SpawnRotation.Roll = FMath::FRand() * 360.0f;
SpawnRotation.Yaw = FMath::FRand() * 360.0f;
ABaseCell* SpawnedCell = World->SpawnActor<ABaseCell>(Cell, SpawnLocation, SpawnRotation);
}
}
}
I should be able to generate without using Kismet the random point but i thought if this kind of library exists we should use them...
it's throwing the following error: https://i.stack.imgur.com/6nG45.png
EDIT
when trying to debug i figured that actually it's when i'm accessing private property "SpawningVolume" that error is thrown... still can't figure why
here is the Spawner.h
#include "BaseCell.h"
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Spawner.generated.h"
UCLASS()
class LIFE_API ASpawner : public AActor
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
ASpawner();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
// Spawnable
UPROPERTY(EditAnyWhere, category="Spawning")
TSubclassOf<class ABaseCell> Cell;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
private:
// SpawningVolume as BoxComponent
UPROPERTY(VisibleAnyWhere, category="Spawning", meta=(AllowPrivateAccess="true"))
class UBoxComponent* SpawningVolume;
void SpawnCells();
};
EDIT 2
Just added this condition and it seems that "SpawningVolume" is "nullptr" so i don't know what i'm doing wrong but i keep investigating
void ASpawner::SpawnCells()
{
if(Cell != NULL)
{
UWorld* const World = GetWorld();
if (World) {
// Added condition
if (SpawningVolume != nullptr) {
FVector Origin = SpawningVolume->Bounds.Origin;
FVector Extent = SpawningVolume->Bounds.BoxExtent;
FVector SpawnLocation = UKismetMathLibrary::RandomPointInBoundingBox(Origin, Extent);
FRotator SpawnRotation;
SpawnRotation.Pitch = FMath::FRand() * 360.0f;
SpawnRotation.Roll = FMath::FRand() * 360.0f;
SpawnRotation.Yaw = FMath::FRand() * 360.0f;
ABaseCell* SpawnedCell = World->SpawnActor<ABaseCell>(Cell, SpawnLocation, SpawnRotation);
}
}
}
}
ERROR
Unhandled Exception: EXCEPTION_ACCESS_VIOLATION reading address 0x000000000000012c
UE4Editor_Life_0001!ASpawner::SpawnCells() [C:\Users\Benja\OneDrive\Documents\Unreal Projects\Life\Source\Life\Spawner.cpp:46]

Related

Faster every Frame/Second UnrealEngine C++

MyPawn.cpp
// Called every frame
void AMyPawn::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
// Handle growing and shrinking based on our "Grow" action
{
float CurrentScale = OurVisibleComponent->GetComponentScale().X;
if (bGrowing)
{
// Grow to double size over the course of one second
CurrentScale = CurrentScale + 2;
}
else
{
// Shrink half as fast as we grow
CurrentScale -= (DeltaTime * 0.5f);
}
// Make sure we never drop below our starting size, or increase past double size.
CurrentScale = FMath::Clamp(CurrentScale, 1.0f, 2.0f);
OurVisibleComponent->SetWorldScale3D(FVector(CurrentScale));
}
// Handle movement based on our "MoveX" and "MoveY" axes
{
if (!CurrentVelocity.IsZero())
{
FVector NewLocation = GetActorLocation() + (CurrentVelocity * DeltaTime);
SetActorLocation(NewLocation);
}
}
}
MyPawn.h
#include "GameFramework/Pawn.h"
#include "MyPawn.generated.h"
UCLASS()
class MYPROJECT_API AMyPawn : public APawn
{
GENERATED_BODY()
public:
// Sets default values for this pawn's properties
AMyPawn();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
// Called to bind functionality to input
virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
UPROPERTY(EditAnywhere)
USceneComponent* OurVisibleComponent;
//Input functions
void Move_XAxis(float AxisValue);
void Move_YAxis(float AxisValue);
void StartGrowing();
void StopGrowing();
//Input variables
FVector CurrentVelocity;
bool bGrowing;
};
I want to add a statement that make my Spawn move faster every Frame or Second while one of the key input pressed (Forward,Backward,Left or Right),
I've tried to add
CurrentVelocity.X += CurrentVelocity.X
or
CurrentVelocity.X += 1
in the AMyPawn::Tick, and tried some more combination with no success, hope u can help me solve this .

My kinematic body position and scale are different than the expected position and scale

I'm trying to create a physics system for my "game engine" using Box2D, And when i create a b2_kinematicBody The position is bigger than the expected position and the scale is small than the expected scale.
I tried to change the SetAsBox parameters with SetAsBox(this->transform->scale.x, transform->scale.y) and the same problem
NOTE: For the rendering i'm using SDL2 and the positions are based in the SDL2 positions.
Example of the error
And here is a video of the problem: https://youtu.be/0fMPh8Rk_pY
This is the code of my KinematicBody2D class.
KinematicBody2D.h
class KinematicBody2D : public Component
{
private:
b2BodyDef k_bodydef;
b2Body* k_body;
b2FixtureDef k_fixtureDef;
b2Fixture *k_fixture;
b2World* k_world;
b2PolygonShape polygonShape;
public:
KinematicBody2D();
KinematicBody2D(Scene scene);
void Start() override;
void Loop(float delta) override;
void MovePosition(Vector2 target);
};
KinematicBody2D.cpp (Just the important part)
void KinematicBody2D::Start()
{
this->k_bodydef.type = b2BodyType::b2_kinematicBody;
this->k_bodydef.position = b2Vec2(this->transform->position.x, this->transform->position.y);
this->k_bodydef.angle = Math::Deg2Rad(this->transform->rotation);
this->k_body = this->k_world->CreateBody(&this->k_bodydef);
this->polygonShape.SetAsBox((this->transform->scale.x / 2.0f), (this->transform->scale.y / 2.0f));
this->k_fixtureDef.shape = &this->polygonShape;
this->k_fixture = this->k_body->CreateFixture(&this->k_fixtureDef);
}
void KinematicBody2D::Loop(float delta)
{
this->transform->position.x = this->k_body->GetPosition().x;
this->transform->position.y = this->k_body->GetPosition().y;
this->transform->rotation = Math::Rad2Deg(this->k_body->GetAngle());
this->polygonShape.SetAsBox((this->transform->scale.x / 2.0f), (this->transform->scale.y / 2.0f));
this->transform->scale = Vector2(this->transform->scale.x, this->transform->scale.y);
return;
}
main.cpp (Just the important part)
int main()
{
GameObject playerObj = GameObject("Player");
Scene scene = Scene("Scene", &playerObj);
playerObj.AddComponent<Sprite>("res/Player.png", Vector4(0, 0, 256, 256),
Vector2(64, 64));
playerObj.AddComponent<Rigidbody2D>(scene);
playerObj.AddComponent<Player>(app.GetRawRenderer());
GameObject floor = GameObject("Floor", "Floor");
floor.AddComponent<Sprite>("res/World 1.png");
floor.AddComponent<KinematicBody2D>(scene);
floor.transform.position = Vector2(100, 200);
}

Access Violation Reading Location when assigning Float (0x0000000000000170)

I'm crashing with a Access Violation reading location. I'm doing this in Unreal Engine, but it's simple and I feel the issue should be universally applicable within C++, though I am new to it.
I am crashing when trying to assign LastDoorOpenTime in OpenDoor() of OpenDoor.cpp (below). I'm able assign to it successfully at the start of the program in UOpenDoor::BeginPlay(), but trying the same thing in OpenDoor() crashes the application with "Access Violation reading location".
OpenDoor.h:
#pragma once
#include "CoreMinimal.h"
#include "Components/ActorComponent.h"
#include "GameFramework/Actor.h"
#include "Engine/TriggerVolume.h"
#include "Engine/World.h"
#include "OpenDoor.generated.h"
UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
class ESCAPEROOM_API UOpenDoor : public UActorComponent
{
GENERATED_BODY()
public:
// Sets default values for this component's properties
UOpenDoor();
protected:
// Called when the game starts
virtual void BeginPlay() override;
void OpenDoor();
void CloseDoor();
public:
// Called every frame
virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;
private:
UPROPERTY(VisibleAnywhere)
float OpenAngle = -60.f;
UPROPERTY(EditAnywhere)
ATriggerVolume* PressurePlate;
UPROPERTY(EditAnywhere)
float DoorCloseDelay = 1.f;
float LastDoorOpenTime;
AActor* ActorThatOpens;
AActor* Owner;
bool IsDoorOpen;
UWorld* ThisWorld;
};
OpenDoor.cpp:
#include "OpenDoor.h"
// Sets default values for this component's properties
UOpenDoor::UOpenDoor()
{
// Set this component to be initialized when the game starts, and to be ticked every frame. You can turn these features
// off to improve performance if you don't need them.
PrimaryComponentTick.bCanEverTick = true;
// ...
}
// Called when the game starts
void UOpenDoor::BeginPlay()
{
Super::BeginPlay();
ThisWorld = GetWorld();
ActorThatOpens = ThisWorld->GetFirstPlayerController()->GetPawn();
AActor* Owner = GetOwner();
IsDoorOpen = false;
}
void UOpenDoor::OpenDoor()
{
Owner->SetActorRotation(FRotator(0.f, OpenAngle, 0.f));
int cow = 1 + 1;
LastDoorOpenTime = 0.f; //ACCESS VIOLATION HERE
IsDoorOpen = true;
}
void UOpenDoor::CloseDoor()
{
Owner->SetActorRotation(FRotator(0.f, 0.f, 0.f));
IsDoorOpen = false;
}
// Called every frame
void UOpenDoor::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
if (PressurePlate->IsOverlappingActor(ActorThatOpens)) {
OpenDoor();
}
if (IsDoorOpen) {
if (ThisWorld->GetTimeSeconds() >= LastDoorOpenTime + DoorCloseDelay) {
CloseDoor();
}
}
}
Changing: "AActor* Owner = GetOwner();" to "Owner = GetOwner();" fixed it.

Perfectly Straight Vertical/Horizontal Line When Pressing the Shift Key (C++ and Qt 5.8)

I am performing a task to implement a perfectly straight vertical/horizontal line when the shift key is pressed in a program called EasyPaint. I have no errors in my code, but unfortunately, it also has zero effect on the program itself. When I draw a line and press shift, it does absolutely nothing. The code below is my method shiftPressEvent and my other method isMod. I tried to do a calculation of degrees to try and specify when the line should snap to a vertical alignment or horizontal alignment, but obviously, it seems to not be doing its intended job. If another set of eyes could maybe analyze the code and see where the problem lies, I'd greatly appreciate it. Also, if any further information is needed, please comment below. I can easily post the entire class of LineInstrument, but it's a tad lengthy.
Added Methods in LineInstrument.cpp Before Edits
void LineInstrument::shiftPressEvent(QKeyEvent *event, ImageArea &imageArea){
if (imageArea.isPaint())
{
imageArea.setImage(mImageCopy);
double Y = mStartPoint.y() - mEndPoint.y();
double X = mStartPoint.x() - mEndPoint.x();
radianAngle = atan2(Y, X);
degreeAngle = radianAngle * 180 / atan(1) * 4;
if (isMod(event->key()))
{
if (abs(degreeAngle) >= 45 && abs(degreeAngle) <= 135)
{
mEndPoint.setX(mStartPoint.x());
}
else if (abs(degreeAngle) < 45 && abs(degreeAngle) > 135)
{
mEndPoint.setY(mStartPoint.y());
}
imageArea.update();
}
}
}
bool LineInstrument::isMod(int key){
if (key == Qt::Key_Shift)
{
return true;
}
return false;
}
Added Methods in LineInstrument.cpp After Edits
void LineInstrument::shiftPressEvent(QKeyEvent *event, ImageArea &imageArea)
{
if (imageArea.isPaint())
{
imageArea.setImage(mImageCopy);
double Y = mStartPoint.y() - mEndPoint.y();
double X = mStartPoint.x() - mEndPoint.x();
if (isMod(event->key()) && fabs(X) > fabs(Y))
{
mEndPoint.setY(mStartPoint.y());
paint(imageArea, false);
}
else if (isMod(event->key()) && fabs(Y) >= fabs(X))
{
mEndPoint.setX(mStartPoint.x());
paint(imageArea, false);
}
}
}
bool LineInstrument::isMod(int key)
{
if (key == Qt::Key_Shift)
{
return true;
}
return false;
}
LineInstrument Header File Before Edits
#ifndef LINEINSTRUMENT_H
#define LINEINSTRUMENT_H
#include "abstractinstrument.h"
#include <QtCore/QObject>
#include <QKeyEvent>
/**
* #brief Line instrument class.
*
*/
class LineInstrument : public AbstractInstrument
{
Q_OBJECT
public:
explicit LineInstrument(QObject *parent = 0);
void mousePressEvent(QMouseEvent *event, ImageArea &imageArea);
void mouseMoveEvent(QMouseEvent *event, ImageArea &imageArea);
void mouseReleaseEvent(QMouseEvent *event, ImageArea &imageArea);
void shiftPressEvent(QKeyEvent *event, ImageArea &imageArea);
bool isMod(int key);
protected:
void paint(ImageArea &imageArea, bool isSecondaryColor = false, bool additionalFlag = false);
private:
double radianAngle;
double degreeAngle;
};
#endif // LINEINSTRUMENT_H
LineInstrument Header File After Edits
#ifndef LINEINSTRUMENT_H
#define LINEINSTRUMENT_H
#include "abstractinstrument.h"
#include <QtCore/QObject>
#include <QKeyEvent>
/**
* #brief Line instrument class.
*
*/
class LineInstrument : public AbstractInstrument
{
Q_OBJECT
public:
explicit LineInstrument(QObject *parent = 0);
void mousePressEvent(QMouseEvent *event, ImageArea &imageArea);
void mouseMoveEvent(QMouseEvent *event, ImageArea &imageArea);
void mouseReleaseEvent(QMouseEvent *event, ImageArea &imageArea);
void shiftPressEvent(QKeyEvent *event, ImageArea &imageArea);
bool isMod(int key);
protected:
void paint(ImageArea &imageArea, bool isSecondaryColor = false, bool additionalFlag = false);
};
#endif // LINEINSTRUMENT_H
Part of the problem is that you aren't calculating the angle in degrees properly. This line doesn't do what you think it does:
degreeAngle = radianAngle * 180 / atan(1) * 4;
That's the same as:
degreeAngle = 4 * radianAngle * 180 / atan(1);
What you should do is create a proper named constant for pi by doing something like this:
const double kPi = atan(1.0) * 4.0;
And you should probably create a function to convert radians to degrees like this:
double toDegrees(double radians)
{
return radians * 180.0 / kPi;
}
You can also figure out whether you want horizontal or vertical snapping much more easily by simply comparing the x delta and the y delta. If X is greater than Y, then you want a horizontal line, otherwise you want a vertical one. Something like this should do the trick:
if (fabs(X) > fabs(Y))
{
mEndPoint.setY(mStartPoint.y());
}
else
{
mEndPoint.setX(mStartPoint.x());
}
Now whether this will fix your problem or not depends on how your drawing actually happens.

How do I restore the sprite into original image after swapped it to another one in coco2dx?

In my gaming context, the sprite is a smiling baby, when the baby is touched, the current sprite image changed to a crying baby, then after 3 seconds of crying sound effect ended, the sprite will restore to the smiling baby image.
My problem is
How to swap back with the previous image?
I have changed the smiling baby to a crying one, but i have no idea how could I swap it with the original smiling one?
How to ensure one click at one time?
Each time the baby sprite is touched, the audio will start to play which is not ideal, because I hope the event function is only called after the previous event process is finished.
here is my code, and thank you a lot!
bool HelloWorld::init()
{
// 1. super init first
if ( !Layer::init() )
{
return false;
}
Size visibleSize = Director::getInstance()->getVisibleSize();
Vec2 origin = Director::getInstance()->getVisibleOrigin();
//add background scene
auto backgroundSprite = Sprite :: create("scene001.jpg");
backgroundSprite->setAnchorPoint(Vec2(0,0));
backgroundSprite->setScaleX((visibleSize.width / backgroundSprite->getContentSize().width) * 1);
backgroundSprite->setScaleY((visibleSize.height / backgroundSprite->getContentSize().height) * 1);
addChild(backgroundSprite);
//add smileBaby sprite
auto smileBabySprite = Sprite :: create("figure001.png");
smileBabySprite -> setPosition(Vec2(500,400));
addChild(smileBabySprite);
//add crying audio
auto audio = CocosDenshion::SimpleAudioEngine::getInstance();
auto babyListener = EventListenerTouchOneByOne::create();
babyListener -> onTouchBegan = [smileBabySprite, audio](Touch* touch, Event* event)
{
//change smileBaby sprite to cryingBaby sprite
smileBabySprite->setTexture(CCTextureCache::sharedTextureCache()->addImage("figure002.png"));
audio -> playEffect("babycry.mp3",false,1.0f,1.0f,1.0f);
return true;
};
babyListener -> onTouchEnded=[smileBabySprite](Touch* touch, Event* event )
{
};
_eventDispatcher -> addEventListenerWithSceneGraphPriority(babyListener, this);
return true;
}
What you want is to keep state about if the baby is crying or not. The best thing to do is keep this logic in a custom Node subclass.
Here is some (almost pseudo-)code to get you started:
Baby.h:
#pragma once
#include "cocos2d.h"
class Baby : public cocos2d::Node
{
private:
cocos2d::Sprite *_sprite; // Weak reference
bool _crying;
float _cryingTime;
public:
CREATE_FUNC(Baby);
protected:
virtual bool init() override;
virtual void update(float delta) override;
public:
void touched();
bool isInside(cocos2d::Touch *touch) const
protected:
void setSprite();
};
Baby.cpp:
#include "Baby.h"
USING_NS_CC;
bool Baby::init()
{
if (!Node::init())
return false;
_crying = false;
setSprite();
scheduleUpdate();
return true;
}
void Baby::update(float delta)
{
Node::update(delta);
if (_crying) {
_cryingTime -= delta;
if (_cryingTime <= 0.0f) {
_crying = false;
setSprite();
}
}
}
void Baby::touched()
{
if (_crying)
return; // Already crying
_crying = true;
_cryingTime = 3.0f; // Length of audio, I guess?
setSprite();
// Start crying sound here
}
bool Baby::isInside(Touch *touch) const
{
Vec2 locationInNode = _sprite->convertToNodeSpace(touch->getLocation());
Size size = _sprite->getContentSize();
Rect rect = Rect(0.0f, 0.0f, size.width, size.height);
return rect.containsPoint(locationInNode);
}
void Baby::setSprite()
{
if (_sprite)
_sprite->removeFromParent();
_sprite = Sprite::initWithFile(_crying ? "baby_crying.png" : "baby.png");
Vec2 size = getContentSize();
_sprite->setPosition(size.width * 0.5f, size.height * 0.5f);
addChild(_sprite);
}
You add the Baby node in the parent instead of the sprite, using:
_baby = Baby::create();
_baby->setPosition(Wherever);
addChild(_baby);
Where _baby is an instance variable and use the isInside() method to test if a touch event is within the bounds of the sprite and call its touched() method:
Touch *touch = ...;
if (_baby->isInside(touch)) {
_baby->touched();
}
and the Baby object will ignore the touch depending on state.