Download

Could someone simplify my code and get it to work

I have a class to move a cat which is the type Pawn. It seems to go way off in the Y direction and I don’t understand why.

Here is the source:

// Fill out your copyright notice in the Description page of Project Settings.


#include "Cat_Alt.h"

// Sets default values
ACat_Alt::ACat_Alt()
{
 	// Set this pawn to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;
	catSleep = false;
	canMove = true;
	minx = -500;
	maxx = 500;
	miny = -500;
	maxy = 500;

	bminx = -4700;
	bmaxx = 4700;
	bminy = -4700;
	bmaxy = 4700;
	catRotation = 270;
	dirx[0] = 1;
	dirx[1] = 0;
	dirx[2] = -1;
	dirx[3] = 0;
	diry[0] = 0;
	diry[1] = 1;
	diry[2] = 0;
	diry[3] = -1;
	notMoved = true;
	shouldSleep = false;
	angchan = 20;
	moveSpeed = 50;
	catPos = FVector(-550, 0, 8);
	
}

// Called when the game starts or when spawned
void ACat_Alt::BeginPlay()
{
	Super::BeginPlay();
	
}

// Called every frame
void ACat_Alt::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);
	cycle.hours = hours;
	cycle.minutes = minutes;
	cycle.seconds = seconds;
	if (wakeTime > 0) {
		wakeTime -= DeltaTime;
		if (wakeTime <= 0) {
			wakeTime = 0;
			canMove = true;
		}
	}
	if (cycle.callEvent) {
		if (cycle.wakeUp) {
			canMove = false;
			wakeTime = 3;
		}
		if (cycle.shouldSleep) shouldSleep = true;
		if (cycle.mustSleep) catSleep = true;
		cycle.callEvent = false;
	}
	if (canMove && !catSleep) {
		move(DeltaTime);
	}
}

// Called to bind functionality to input
void ACat_Alt::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
	Super::SetupPlayerInputComponent(PlayerInputComponent);

}

void ACat_Alt::move(float delta) {
	if (catRotation != toAngle) {
		if (catRotation > toAngle) {
			catRotation -= delta * angchan;
			if (catRotation < toAngle) catRotation = toAngle;
		}
		else {
			catRotation += delta * angchan;
			if (catRotation > toAngle) catRotation = toAngle;
		}
	}
	if (notMoved) setMovement();

	float xmov = cos(catRotation * 0.01745329251994329576923690768489) * moveSpeed * delta;
	float ymov = sin(catRotation * 0.01745329251994329576923690768489) * moveSpeed * delta;

	catPos += FVector(xmov, ymov, 0);
	if (sign(tox - catPos.X) != dsx || sign(toy - catPos.Y) != dsy) notMoved = true;
}

float ACat_Alt::getToRotation(float x, float y) {
	notMoved = false;
	dsx = sign(tox - catPos.X);
	dsy = sign(toy - catPos.Y);
	
	int i;
	if (x == 0 || y == 0) {
		for (i = 0; i < 4; i++) {
			if (x != 0 && dsx == dirx[i]) break;
			if (y != 0 && dsy == diry[i]) break;
		}
		return 90 * i;
	}
	int rot1 = 0;
	int rot2 = 0;
	for (i = 0; i < 4; i++) {
		if (x != 0 && dsx == dirx[i]) rot1 = i;
		if (y != 0 && dsy == diry[i]) rot2 = i;
	}
	int rota;
	if (rot1 > rot2) {
		rota = rot2;
	}
	else {
		rota = rot1;
	}
	float hypot = pow(x * x + y * y, .5);
	float relx = x / hypot;
	float degMul = 57.295779513082320876798154814105;
	float angle = 0;
	switch (rota) {
	case 0:
		angle = asin(relx) * degMul;
		break;
	case 1:
		angle = 180 - asin(relx) * degMul;
		break;
	case 2:
		angle = 180 - asin(relx) * degMul;
		break;
	case 3:
		angle = 360 + asin(relx) * degMul;
		break;
	}
	return angle;
}

void ACat_Alt::setMovement() {
	float dist = distFrom(catPos.X, catPos.Y);
	float catx = catPos.X;
	float caty = catPos.Y;
	if (shouldSleep) {

	}
	else {
		ranloc dest;
		if (cycle.isHunting) {

		}
		else {
			dest = getALocation();
			toAngle = getToRotation(dest.locx - catx, dest.locy - caty);
		}
	}
}

bool ACat_Alt::inBounds(float x, float y) {
	return (((x > bminx && x < bminx) || (x > maxx && x < bmaxx)) && ((x > bminy && x < bminy) || (x > maxy && x < bmaxy)));
}

float ACat_Alt::distFrom(float x, float y) {
	float hypot = pow(x * x + y * y, .5);
	float abx = abs(x / hypot);
	float aby = abs(y / hypot);
	if (abx == aby) {
		return hypot - maxx * 1.4142135623730950488016887242097;
	}
	float lesval;
	float grval;
	if (abx > aby) {
		lesval = aby;
		grval = abx;
	}
	else {
		lesval = abx;
		grval = aby;
	}
	float relval = lesval / grval;
	float adv = 0;
	float ang = asin(relval);

	for (float i = 2; i > pow(2, -24); i /= 2) if (asin((adv + i) / pow((adv + i) * (adv + 1) + 1, .5)) <= ang) adv += i;
	return maxx * adv;
}

int ACat_Alt::sign(float val) {
	if (val == 0) {
		return 0;
	}
	else {
		if (val > 0) {
			return 1;
		}
		else {
			return -1;
		}
	}
}



ranloc ACat_Alt::getALocation() {
	ranloc retv;
	bool notTested = true;
	float posx, posy;
	float catx = catPos.X;
	float caty = catPos.Y;
	bool signCh = false;
	int tsign = 1;
	float tx[4] = { -500, 500, -500, 500 };
	float ty[4] = { -500, -500, 500, 500 };
	while (notTested) {
		posx = rand.generate() * 2000 - 1000;
		posy = rand.generate() * 2000 - 1000;
		if (!(posx > minx && posx < maxx && posy > miny && posy < maxy)) {
			// (y2-y1)*x + (x1-x2)*y + (x2*y1-x1*y2)
			for (int i = 0; i < 4; i++) {
				if ((posy - caty) * tx[i] + (posx - catx) * ty[i] + (posx * caty - catx * posy) == 0) {
					signCh = true;
					break;
				}
				else {
					if (sign((posy - caty) * tx[i] + (posx - catx) * ty[i] + (posx * caty - catx * posy)) != tsign && i > 0) {
						signCh = true;
						break;
					}
					else {
						tsign = sign((posy - caty) * tx[i] + (posx - catx) * ty[i] + (posx * caty - catx * posy));
					}
				}
				if (signCh) {
					if ((posx > 500 && catx > 500) || (posx < -500 && catx < -500) || (posy > 500 && caty > 500) || (posy < -500 && caty < -500)) signCh = false;
				}
				if (signCh) notTested = false;
			}
		}
	}
	tox = posx;
	toy = posy;
	return retv;
}

The number -500 to 500 in x and y this is where I have a house where the cat is not supposed to go.

Did you write that code yourself?

Yes, why?

The thing is my cat is supposed to go between -1000 and 1000 except where the house is when it is in it’s current mode. It goes way off in the Y direction.

The reason I asked this, is because sometimes people just copy/paste code without knowing what the code does, but this is not the case.

Well, there’s a lot of math going on, it will be hard to find the problem by only looking at the code.

Can’t you troubleshoot with debugging or by adding UE_LOG entries?

I’d just assign the thing an AIController, and tell teh AIController MoveTo(location)

I agree with @eblade , and I’ll add a little more:

First, you don’t want movement itself to live in the Pawn; you want it to live in a controller.

Second, you don’t want the controller to directly affect the pawn location, but instead, you want it to affect whatever movementcomponent (physical simulation) the pawn uses.

Third, you’ll almost certainly want to use a subclass of AIController to implement the cat behavior, and you’ll likely want to use a Character (or subclass thereof – but I think the base thing will just work) to actually build the cat.

So, the Character (or other Pawn actor subclass) brings together the components, and imbues the mesh animation behaviors.
The MovementComponent on the Character (or other Pawn) actually decides/simulates the position of the main body of the character (typically, some collision proxy, like the capsule that Character uses.)
The Controller then tells the Character/MovementComponent what the “desire” is – where to move, for example.
The Animation blueprint of the skinned mesh used by the Character then gets the necessary properties from the Character to figure out what animations to play, and how.

1 Like