add Find_Cone to find objects in a cone

The reason for an engine function for this is speed, an implementation in script needs Find_Func and ensures slowness.
install-platforms
Maikel de Vries 2017-07-19 22:03:37 +02:00
parent 0d58380dbf
commit efe7dcf251
8 changed files with 101 additions and 0 deletions

View File

@ -47,6 +47,7 @@
<funclink>Find_AnyLayer</funclink>
<funclink>Find_AtPoint</funclink>
<funclink>Find_Category</funclink>
<funclink>Find_Cone</funclink>
<funclink>Find_Container</funclink>
<funclink>Find_Distance</funclink>
<funclink>Find_Exclude</funclink>

View File

@ -60,6 +60,7 @@
<funclink>Find_AnyLayer</funclink>
<funclink>Find_AtPoint</funclink>
<funclink>Find_Category</funclink>
<funclink>Find_Cone</funclink>
<funclink>Find_Container</funclink>
<funclink>Find_Distance</funclink>
<funclink>Find_Exclude</funclink>

View File

@ -0,0 +1,54 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!DOCTYPE funcs
SYSTEM '../../../clonk.dtd'>
<?xml-stylesheet type="text/xsl" href="../../../clonk.xsl"?>
<funcs>
<func>
<title>Find_Cone</title>
<category>Objects</category>
<subcat>Search</subcat>
<version>8.0 OC</version>
<syntax>
<rtype>array</rtype>
<params>
<param>
<type>int</type>
<name>radius</name>
<desc>Cone radius.</desc>
</param>
<param>
<type>int</type>
<name>cone_angle</name>
<desc>The angle in which direction the cone points, zero means upwards and positive angles rotate clockwise.</desc>
</param>
<param>
<type>int</type>
<name>cone_width</name>
<desc>The angular width of the cone, all object within an angle of <code>cone_angle - cone_width</code> and <code>cone_angle + cone_width</code> will be found.</desc>
</param>
<param>
<type>int</type>
<name>x</name>
<desc>Distance reference point. In local calls, relative to the calling object.</desc>
<optional />
</param>
<param>
<type>int</type>
<name>y</name>
<desc>Distance reference point. In local calls, relative to the calling object.</desc>
<optional />
</param>
<param>
<type>int</type>
<name>prec_angle</name>
<desc>Precision for the <code>cone_angle</code> and <code>cone_width</code> parameters. For a higher precision while working with integers (whole numbers) you can specify a higher precision value. A precision of 10 will induce an angle range from 0 to 3600.</desc>
<optional />
</param>
</params>
</syntax>
<desc>Search criterion: finds all objects within the cone with specified radius, cone angle and cone width with the tip of the cone originating at the specified coordinates. If no coordinates are specified, the position of the calling object is used.</desc>
<remark>For additional information on the use of this function see <funclink>FindObjects</funclink>.</remark>
<related><funclink>FindObjects</funclink></related>
</func>
<author>Maikel</author><date>2017-7</date>
</funcs>

View File

@ -45,6 +45,7 @@
<funclink>Find_AtPoint</funclink>
<funclink>Find_OnLine</funclink>
<funclink>Find_Category</funclink>
<funclink>Find_Cone</funclink>
<funclink>Find_Container</funclink>
<funclink>Find_Distance</funclink>
<funclink>Find_Exclude</funclink>

View File

@ -68,6 +68,13 @@ global func Find_Distance(int r, int x, int y)
return [C4FO_Distance, x, y, r];
}
global func Find_Cone(int r, int cone_angle, int cone_width, int x, int y, int prec_angle)
{
if (!prec_angle)
prec_angle = 1;
return [C4FO_Cone, x, y, r, cone_angle, cone_width, prec_angle];
}
global func Find_OCF(int ocf)
{
return [C4FO_OCF, ocf];

View File

@ -3008,6 +3008,7 @@ C4ScriptConstDef C4ScriptGameConstMap[]=
{ "C4FO_InArray" ,C4V_Int, C4FO_InArray },
{ "C4FO_Property" ,C4V_Int, C4FO_Property },
{ "C4FO_AnyLayer" ,C4V_Int, C4FO_AnyLayer },
{ "C4FO_Cone" ,C4V_Int, C4FO_Cone },
{ "MD_DragSource" ,C4V_Int, C4MC_MD_DragSource },
{ "MD_DropTarget" ,C4V_Int, C4MC_MD_DropTarget },

View File

@ -158,6 +158,18 @@ C4FindObject *C4FindObject::CreateByValue(const C4Value &DataVal, C4SortObject *
}
return new C4FindObjectDistance(x, y, Data[3].getInt());
}
case C4FO_Cone:
{
int32_t x = Data[1].getInt();
int32_t y = Data[2].getInt();
if (context)
{
x += context->GetX();
y += context->GetY();
}
return new C4FindObjectCone(x, y, Data[3].getInt(), Data[4].getInt(), Data[5].getInt(), Data[6].getInt());
}
case C4FO_OCF:
return new C4FindObjectOCF(Data[1].getInt());
@ -668,6 +680,16 @@ bool C4FindObjectDistance::Check(C4Object *pObj)
return (pObj->GetX() - x) * (pObj->GetX() - x) + (pObj->GetY() - y) * (pObj->GetY() - y) <= r2;
}
bool C4FindObjectCone::Check(C4Object *pObj)
{
bool in_circle = (pObj->GetX() - x) * (pObj->GetX() - x) + (pObj->GetY() - y) * (pObj->GetY() - y) <= r2;
int32_t obj_angle = Angle(x, y, pObj->GetX(), pObj->GetY(), prec_angle);
bool in_cone = Inside(obj_angle, cone_angle - cone_width, cone_angle + cone_width) ||
Inside(obj_angle - 360 * prec_angle, cone_angle - cone_width, cone_angle + cone_width) ||
Inside(obj_angle + 360 * prec_angle, cone_angle - cone_width, cone_angle + cone_width);
return in_circle && in_cone;
}
bool C4FindObjectOCF::Check(C4Object *pObj)
{
return !! (pObj->OCF & ocf);

View File

@ -46,6 +46,7 @@ enum C4FindObjectCondID
C4FO_InArray = 22,
C4FO_Property = 23,
C4FO_AnyLayer = 24,
C4FO_Cone = 25,
// last C4FO must be smaller than C4SO_First.
};
@ -249,6 +250,19 @@ protected:
C4Rect *GetBounds() override { return &bounds; }
};
class C4FindObjectCone : public C4FindObject
{
public:
C4FindObjectCone(int32_t x, int32_t y, int32_t r, int32_t angle, int32_t width, int32_t prec = 1)
: x(x), y(y), r2(r * r), cone_angle(angle % (360 * prec)), cone_width(width), prec_angle(prec), bounds(x - r, y - r, 2 * r + 1, 2 * r + 1) { }
private:
int32_t x, y, r2, cone_angle, cone_width, prec_angle;
C4Rect bounds;
protected:
bool Check(C4Object *pObj) override;
C4Rect *GetBounds() override { return &bounds; }
};
class C4FindObjectOCF : public C4FindObject
{
public: