程序会不断更新每一帧,这使得计算狐狸与兔子之间的距离变得困难(这几乎是一个相同的值)
我尝试使用双精度,以便距离值可以补偿很小的变化,但这没有用。
define OLC_PGE_APPLICATION
#include "olcPixelGameEngine.h"
int x = 0;
class Example : public olc::PixelGameEngine
{
private:
olc::Sprite* rabbit;
olc::Sprite* bush;
olc::Sprite* fox;
olc::Sprite* evilfox;
int size = 3;
double rabbitPosX = 30.0;
double rabbitPosY = 30.0;
double rabbitXvel = 0.0;
double rabbitYvel = 0.0;
double FoxPosX[3] = { 50.0f,80.0f,70.0};
double FoxPosY[3] = { 80.0f,50.0f,200.0};
double FoxXvel = 0.0;
double FoxYvel = 0.0;
public:
Example()
{
sAppName = "Example";
}
public:
double distanceForm(double x1, double x2, double y1, double y2)
{
double distance = sqrt((x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1));
return distance;
}
bool checkCurFox(double arrX[], double arrY[], int size, int count)
{
for (int i = count+1; i < size; i++)
{
if (distanceForm(arrX[count], arrX[i], arrY[count], arrY[i]) > 15)
{
return true;
}
}
}
double moveRabbitX(double rabbitX, double VelX, double ETime)
{
if (VelX > 0)
{
double NewrabbitX = rabbitX + VelX * ETime;
return NewrabbitX;
}
double NewrabbitX = rabbitX + VelX * ETime;
return NewrabbitX;
}
double moveRabbitY(double rabbitY, double VelY, double ETime)
{
if (VelY > 0)
{
double NewrabbitY = rabbitY + VelY * ETime;
return NewrabbitY;
}
double NewrabbitY = rabbitY + VelY * ETime;
return NewrabbitY;
}
double moveFoxX(double FoxX, double VelX, double ETime)
{
if (VelX > 0)
{
double NewFoxX = FoxX + VelX * ETime;
return NewFoxX;
}
double NewFoxX = FoxX + VelX * ETime;
return NewFoxX;
}
double moveFoxY(double FoxY, double VelY, double ETime)
{
if (VelY > 0)
{
double NewFoxY = FoxY + VelY * ETime;
return NewFoxY;
}
double NewFoxY = FoxY + VelY * ETime;
return NewFoxY;
}
bool OnUserCreate() override
{
// Called once at the start, so create things here
//DrawRect(0,0,ScreenWidth(),ScreenHeight(),olc::DARK_VERY_DARK_GREEN);
/*DrawSprite(30,40,)*/
FillRect(0, 0, ScreenWidth(), ScreenHeight(), olc::VERY_DARK_GREEN);
DrawString(80, 0, "Fox Escape", olc::RED, 1);
rabbit =new olc::Sprite("Rabbit.png");
DrawSprite(30, 30, rabbit,1);
/*bush = new olc::Sprite("Bush.png");
DrawSprite(50, 50, bush, 2);*/
fox = new olc::Sprite("Fox.png");
//DrawSprite(50, 70, fox, 1);
evilfox = new olc::Sprite("evilfox.png");
return true;
}
bool OnUserUpdate(float fElapsedTime) override
{
int Omg = 1;
// called once per frame
for (int j = 0; j < 3; j++)
{
double distance = distanceForm(rabbitPosX, FoxPosX[j], rabbitPosY, FoxPosY[j]);
double distanceMxUp = distanceForm(rabbitPosX, FoxPosX[j], rabbitPosY, moveFoxY(FoxPosY[j], -20, fElapsedTime));
double distanceMxDown = distanceForm(rabbitPosX, FoxPosX[j], rabbitPosY, moveFoxY(FoxPosY[j], +20, fElapsedTime));
double distanceMyRight = distanceForm(moveFoxX(FoxPosX[j], 20, fElapsedTime), rabbitPosX, FoxPosY[j], rabbitPosY);
double distanceMyLeft = distanceForm(moveFoxX(FoxPosX[j], -20, fElapsedTime), rabbitPosX, FoxPosY[j], rabbitPosY);
double arr[4] = { distanceMxUp,distanceMxDown,distanceMyRight,distanceMyLeft };
double temp;
for (int i = 0; i < 3; i++)
{
for (int j = i + 1; j < 3; j++)
{
if (arr[i] > arr[j])
{
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
}
int tempX = FoxPosX[j];
int tempY = FoxPosY[j];
for (int k = 0; k < 3; k++)
{
if (checkCurFox(FoxPosX, FoxPosY, size, j))
{
if (arr[k] == distanceMxUp)
{
k = 3;
double NewFoxY = moveFoxY(FoxPosY[j], -10, fElapsedTime);
FillRect(FoxPosX[j], FoxPosY[j], 15, 15, olc::VERY_DARK_GREEN);
FoxPosY[j] = NewFoxY;
DrawSprite(FoxPosX[j], FoxPosY[j], fox, 1);
if (distance < 6)
{
FillRect(0, 0, ScreenWidth(), ScreenHeight(), olc::Pixel(0, 0, 0));
DrawSprite(0, 0, evilfox, 1);
}
}
if (arr[k] == distanceMxDown)
{
k = 3;
double NewFoxY = moveFoxY(FoxPosY[j], 10, fElapsedTime);
FillRect(FoxPosX[j], FoxPosY[j], 15, 15, olc::VERY_DARK_GREEN);
FoxPosY[j] = NewFoxY;
DrawSprite(FoxPosX[j], FoxPosY[j], fox, 1);
if (distance < 6)
{
FillRect(0, 0, ScreenWidth(), ScreenHeight(), olc::Pixel(0, 0, 0));
DrawSprite(0, 0, evilfox, 1);
}
}
if (arr[k] == distanceMyRight)
{
k = 3;
double NewFoxX = moveFoxX(FoxPosX[j], 10, fElapsedTime);
FillRect(FoxPosX[j], FoxPosY[j], 15, 15, olc::VERY_DARK_GREEN);
FoxPosX[j] = NewFoxX;
DrawSprite(FoxPosX[j], FoxPosY[j], fox, 1);
if (distance < 6)
{
FillRect(0, 0, ScreenWidth(), ScreenHeight(), olc::Pixel(0, 0, 0));
DrawSprite(0, 0, evilfox, 1);
}
}
if (arr[k] == distanceMyLeft)
{
k = 3;
double NewFoxX = moveFoxX(FoxPosX[j], -10, fElapsedTime);
FillRect(FoxPosX[j], FoxPosY[j], 15, 15, olc::VERY_DARK_GREEN);
FoxPosX[j] = NewFoxX;
DrawSprite(FoxPosX[j], FoxPosY[j], fox, 1);
if (distance < 6)
{
FillRect(0, 0, ScreenWidth(), ScreenHeight(), olc::Pixel(0, 0, 0));
DrawSprite(0, 0, evilfox, 1);
}
}
}
}
}
if (GetKey(olc::Key::RIGHT).bHeld)
{
rabbitXvel = 30.0f;
double NewrabbitX = moveRabbitX(rabbitPosX, rabbitXvel, fElapsedTime);
FillRect(rabbitPosX, rabbitPosY, 7, 8,olc::VERY_DARK_GREEN);
rabbitPosX = NewrabbitX;
DrawSprite(rabbitPosX, rabbitPosY, rabbit);
}
if (GetKey(olc::Key::LEFT).bHeld)
{
rabbitXvel = -30.0f;
double NewrabbitX = moveRabbitX(rabbitPosX, rabbitXvel, fElapsedTime);
FillRect(rabbitPosX, rabbitPosY, 7, 8, olc::VERY_DARK_GREEN);
rabbitPosX = NewrabbitX;
DrawSprite(rabbitPosX, rabbitPosY, rabbit);
}
if (GetKey(olc::Key::UP).bHeld)
{
rabbitYvel = -30.0f;
double NewrabbitY = moveRabbitY(rabbitPosY, rabbitYvel, fElapsedTime);
FillRect(rabbitPosX, rabbitPosY, 7, 8, olc::VERY_DARK_GREEN);
rabbitPosY = NewrabbitY;
DrawSprite(rabbitPosX, rabbitPosY, rabbit);
}
if (GetKey(olc::Key::DOWN).bHeld)
{
rabbitYvel = 30.0f;
double NewrabbitY = moveRabbitY(rabbitPosY, rabbitYvel, fElapsedTime);
FillRect(rabbitPosX, rabbitPosY, 7, 8, olc::VERY_DARK_GREEN);
rabbitPosY = NewrabbitY;
DrawSprite(rabbitPosX, rabbitPosY, rabbit);
}
//Draw(rabbitPosX, rabbitPosY, olc::YELLOW);
return true;
}
};
int main()
{
Example demo;
if (demo.Construct(256, 240, 4, 4))
demo.Start();
return 0;
}
我希望狐狸避免彼此碰撞。
答案 0 :(得分:1)
几个月前,我偶然发现this terrific blog post,它解释了“仿制”植绒行为。要在狐狸中创造逼真的动作,您需要做一些事情。快速摘要:
以您的示例为例,如果狐狸严格表现为追逐兔子并彼此远离,则需要使用分隔。如果将狐狸存储在数组中,则伪代码可能如下所示。
WFUserGroup
但是功能呢?
fox foxarray[size_of_array]
rabbit rabb
//separate the foxes if they get too close
for(each fox in foxarray) {
current_fox = //the fox you're checking
for(every other fox in foxarray) {
other_fox = //the other ones you'll look at
if(distanceFrom(current_fox, other_fox) < some_threshold_value) {
/*
use a function to check the positions of the foxes,
and then adjust their velocities to move away from
one another.
*/
move_apart(curernt_fox, other_fox)
}
}
}
//chase the rabbit
for(each fox in foxarray) {
current_fox = //the fox you're checking
/*
this would check their positions, and then adjust the fox's velocity
to move it towards the rabbit.
i'm assuming the rabbit is player-controlled, so its velocity
wouldn't be changed
*/
move_towards(current_fox, rabb)
}
这些仅仅是个简单的例子,我发现,如果将狐狸彼此分开多远,也可以实现更好的运动,即它们越近,它们试图分开的速度就越快。我还发现,如果将它们的位置和速度表示为2D向量(void move_apart(fox f1, fox f2) {
//set f1's velocity away from f2
//first, get f2's position relative to f1, then add velocity
//to move away from it
f2xPos = f2.x - f1.x;
f2yPos = f2.y - f1.y;
if(f2xPos < 0) {
//if f2xPos is negative, add some positive x velocity to move away
f1xVel += some_velocity;
}
else {
//add some negative velocity to move away
f1xVel -= some_velocity;
}
//repeat for f2 - or, alternatively, call move_apart() with
//f2 and f1 flipped.
}
//============================================================
void move_towards(fox f, rabbit r) {
//very similar to move_apart, but you'd flip the signs of
//the velocity so you can move the fox towards the rabbit.
}
自展开数组),则管理它们将变得更加容易。
如果您愿意重构代码和/或计划使游戏更大,我强烈建议您将移动的实体(狐狸和兔子)分离到自己的类中,而不是在引擎类中使用双精度数组。这使实现实体的功能,更改其行为以及跟踪其位置和速度变得非常容易得多。
另外,如果程序遇到帧速率问题,以每秒数百帧的速度疯狂检查每帧狐狸的位置,则可以考虑在帧之间使用std::vector
来减慢执行速度。
祝你游戏好运!