Creating a circle of objects
#1

I'm interested on the last couple of months on how is it possible to create a "circle" of objects around a certain point, with a certain radius from the point.
I know it has something to do with the trigonmetric functions, and I know what each one of them does, but I just don't know how to implement it code-wise.
I've seen some filterscript of explosions created around the player, but I can't seem to find it now.
Reply
#2

This has everything you need: http://stackoverflow.com/questions/8...-circumference
Reply
#3

Quote:
Originally Posted by Bakr
Посмотреть сообщение
So it will be something like:
pawn Код:
stock CreateCircleAroundPoint(objectid, Float:x, Float:y, Float:z, Float:radius)
{
    new Float:x2, Float:y2;
    for(new i = 0; i < 360; i++)
    {
        x2 = x + radius * acos(i);
        y2 = y + radius * asin(i);
        CreateObject(objectid, x2, y2, z...);
    }
    return 1;
}
?
Reply
#4

Not acos/asin, just floatcos/floatsin. I'm pretty sure sin is for x, but I forget.
Reply
#5

That would create a complete circle around the origin (x, y). If you only want a specific amount of objects (like 10) around the origin, you will have to adjust the formula accordingly.
Reply
#6

Quote:
Originally Posted by MP2
Посмотреть сообщение
Not acos/asin, just floatcos/floatsin. I'm pretty sure sin is for x, but I forget.
What's the difference? I always wondered.
And why floatsin/floatcos? 'i' is an integer, not a float.
Quote:
Originally Posted by Bakr
Посмотреть сообщение
That would create a complete circle around the origin (x, y). If you only want a specific amount of objects (like 10) around the origin, you will have to adjust the formula accordingly.
Yeah I'll play around with it. Thanks for the help!
Reply
#7

floatsin returns sine of an angle (which is a float), whereas asin is an inverse function of sine (sine^-1). For example:

floatsin(60, degrees) ~ 0.866,
asin(0.866) ~ 60°.



This creates a specific number or objects equally distributed around a point.
pawn Код:
stock CreateCircleAroundpoint(objectid, Float:x, Float:y, Float:z, Float:radius, OBJECT_NUMBER)
{
    new Float:x2, Float:y2, Float:angle = 360/(OBJECT_NUMBER), Float:a = 0.0;
    for(new i=0; i<OBJECT_NUMBER; i++)
    {
        printf("%f",a);
        x2 = x + floatcos(a,degrees) * radius;
        y2 = y + floatsin(a,degrees) * radius;
        a += angle;
        CreateObject(objectid, x2, y2, z, 0.0,0.0,0.0);
    }
}
Reply
#8

Quote:
Originally Posted by Antonio144
Посмотреть сообщение
floatsin returns sine of an angle (which is a float), whereas asin is an inverse function of sine (sine^-1). For example:

floatsin(60, degrees) ~ 0.866,
asin(0.866) ~ 60°.



This creates a specific number or objects equally distributed around a point.
pawn Код:
stock CreateCircleAroundpoint(objectid, Float:x, Float:y, Float:z, Float:radius, OBJECT_NUMBER)
{
    new Float:x2, Float:y2, Float:angle = 360/(OBJECT_NUMBER), Float:a = 0.0;
    for(new i=0; i<OBJECT_NUMBER; i++)
    {
        printf("%f",a);
        x2 = x + floatcos(a,degrees) * radius;
        y2 = y + floatsin(a,degrees) * radius;
        a += angle;
        CreateObject(objectid, x2, y2, z, 0.0,0.0,0.0);
    }
}
Lets create a shitload of objects without any reference of their object ids that way our function fills all the object slots and crashes clients isn't that clever? Even though the rest of the code looks correct we need to add some stuff here so keep track of what those object ids are.

pawn Код:
#include <a_samp>
#include <zcmd>

// Invalid point group ref
#define         INVALID_POINT_GROUP            (0xFFFF)

// Max number of objects creatable around player
#define         MAX_POINT_OBJECT_GROUPS         20

// Max number of objects creatable
#define         MAX_POINT_OBJECTS               500

// Group states
#define         INACTIVE_GROUP                  0
#define         ACTIVE_GROUP                    1

// Individual object data (reference to group and objectid)
enum POINTDATA
{
    PointObjectID,
    PointGroupID
}

// Variables for objects
new PointObjectGroups[MAX_POINT_OBJECT_GROUPS];

// Group reference variable
new PointObject[MAX_POINT_OBJECTS][POINTDATA];

// Initialize objectids to INVALID_OBJECT_ID
public OnFilterScriptInit()
{
    for(new i = 0; i < MAX_POINT_OBJECT_GROUPS; i++) { PointObject[i][PointObjectID] = INVALID_OBJECT_ID; }
    return 1;
}

// Create the objects around a point
stock CreateCircleAroundpoint(objectid, Float:x, Float:y, Float:z, Float:radius, OBJECT_NUMBER)
{
    // Find a valid group
    for(new i = 0; i < MAX_POINT_OBJECT_GROUPS; i++)
    {
        // Group used continue
        if(PointObjectGroups[i] == ACTIVE_GROUP) continue;
       
        // Variables
        new Float:x2, Float:y2, Float:angle = 360/(OBJECT_NUMBER), Float:a = 0.0, k, count;

        // loop through objects
        for(new j = 0; j < OBJECT_NUMBER; j++)
        {
            // Find a free object slot
            for(; k < MAX_POINT_OBJECTS; k++)
            {
                // Found object slot
                if(PointObject[k][PointObjectID] == INVALID_OBJECT_ID)
                {
                    // Create object here
                    x2 = x + floatcos(a,degrees) * radius;
                    y2 = y + floatsin(a,degrees) * radius;
                    a += angle;
                    PointObject[k][PointObjectID] = CreateObject(objectid, x2, y2, z, 0.0,0.0,0.0);
                    PointObject[k][PointGroupID] = i;
                    count++;

                    // No need to keep iterating break out of loop here
                    break;
                }
            }
        }

        // Objects created? Return the groupid
        if(count)
        {
            PointObjectGroups[i] = ACTIVE_GROUP;
            return i;
        }
       
        // No objects? Return INVALID_POINT_GROUP
        else return INVALID_POINT_GROUP;
    }
    // No groups left
    print("Error: Tried to create too many point object groups!");
    return INVALID_POINT_GROUP;
}

// Remove a point object group
forward RemovePointObjectGroup(index);
public RemovePointObjectGroup(index)
{
    // Make sure the point is valid
    if(PointObjectGroups[index] != INVALID_POINT_GROUP)
    {
        new count;

        // Find all objects associated with group
        for(new i = 0; i < MAX_POINT_OBJECTS; i++)
        {
            // Found an object delete
            if(PointObject[i][PointGroupID] == index)
            {
                count++;
                DestroyObject(PointObject[i][PointObjectID]);
                PointObject[i][PointObjectID] = INVALID_OBJECT_ID;
                PointObject[i][PointGroupID] = INACTIVE_GROUP;
            }
        }
        // Group is now inactive return the number of objects removed
        PointObjectGroups[index] = INVALID_POINT_GROUP;
        return count;
    }
    // Group was invalid
    print("Error: Tried to delete an invalid group!");
    return INVALID_POINT_GROUP;
}

// Tests the system
CMD:testcmd(playerid, arg[])
{
    new Float:x, Float:y, Float:z;
    GetPlayerPos(playerid, x, y, z);
    new GID = CreateCircleAroundpoint(954, x, y, z, 2.0, 16);
    if(GID != INVALID_POINT_GROUP) SetTimerEx("RemovePointObjectGroup", 20000, false, "i", GID);
    return 1;
}
Reply
#9

Quote:
Originally Posted by [uL]Pottus
Посмотреть сообщение
Lets create a shitload of objects without any reference of their object ids that way our function fills all the object slots and crashes clients isn't that clever? Even though the rest of the code looks correct we need to add some stuff here so keep track of what those object ids are.

pawn Код:
#include <a_samp>
#include <zcmd>

// Invalid point group ref
#define         INVALID_POINT_GROUP            (0xFFFF)

// Max number of objects creatable around player
#define         MAX_POINT_OBJECT_GROUPS         20

// Max number of objects creatable
#define         MAX_POINT_OBJECTS               500

// Group states
#define         INACTIVE_GROUP                  0
#define         ACTIVE_GROUP                    1

// Individual object data (reference to group and objectid)
enum POINTDATA
{
    PointObjectID,
    PointGroupID
}

// Variables for objects
new PointObjectGroups[MAX_POINT_OBJECT_GROUPS];

// Group reference variable
new PointObject[MAX_POINT_OBJECTS][POINTDATA];

// Initialize objectids to INVALID_OBJECT_ID
public OnFilterScriptInit()
{
    for(new i = 0; i < MAX_POINT_OBJECT_GROUPS; i++) { PointObject[i][PointObjectID] = INVALID_OBJECT_ID; }
    return 1;
}

// Create the objects around a point
stock CreateCircleAroundpoint(objectid, Float:x, Float:y, Float:z, Float:radius, OBJECT_NUMBER)
{
    // Find a valid group
    for(new i = 0; i < MAX_POINT_OBJECT_GROUPS; i++)
    {
        // Group used continue
        if(PointObjectGroups[i] == ACTIVE_GROUP) continue;
       
        // Variables
        new Float:x2, Float:y2, Float:angle = 360/(OBJECT_NUMBER), Float:a = 0.0, k, count;

        // loop through objects
        for(new j = 0; j < OBJECT_NUMBER; j++)
        {
            // Find a free object slot
            for(; k < MAX_POINT_OBJECTS; k++)
            {
                // Found object slot
                if(PointObject[k][PointObjectID] == INVALID_OBJECT_ID)
                {
                    // Create object here
                    x2 = x + floatcos(a,degrees) * radius;
                    y2 = y + floatsin(a,degrees) * radius;
                    a += angle;
                    PointObject[k][PointObjectID] = CreateObject(objectid, x2, y2, z, 0.0,0.0,0.0);
                    PointObject[k][PointGroupID] = i;
                    count++;

                    // No need to keep iterating break out of loop here
                    break;
                }
            }
        }

        // Objects created? Return the groupid
        if(count)
        {
            PointObjectGroups[i] = ACTIVE_GROUP;
            return i;
        }
       
        // No objects? Return INVALID_POINT_GROUP
        else return INVALID_POINT_GROUP;
    }
    // No groups left
    print("Error: Tried to create too many point object groups!");
    return INVALID_POINT_GROUP;
}

// Remove a point object group
forward RemovePointObjectGroup(index);
public RemovePointObjectGroup(index)
{
    // Make sure the point is valid
    if(PointObjectGroups[index] != INVALID_POINT_GROUP)
    {
        new count;

        // Find all objects associated with group
        for(new i = 0; i < MAX_POINT_OBJECTS; i++)
        {
            // Found an object delete
            if(PointObject[i][PointGroupID] == index)
            {
                count++;
                DestroyObject(PointObject[i][PointObjectID]);
                PointObject[i][PointObjectID] = INVALID_OBJECT_ID;
                PointObject[i][PointGroupID] = INACTIVE_GROUP;
            }
        }
        // Group is now inactive return the number of objects removed
        PointObjectGroups[index] = INVALID_POINT_GROUP;
        return count;
    }
    // Group was invalid
    print("Error: Tried to delete an invalid group!");
    return INVALID_POINT_GROUP;
}

// Tests the system
CMD:testcmd(playerid, arg[])
{
    new Float:x, Float:y, Float:z;
    GetPlayerPos(playerid, x, y, z);
    new GID = CreateCircleAroundpoint(954, x, y, z, 2.0, 16);
    if(GID != INVALID_POINT_GROUP) SetTimerEx("RemovePointObjectGroup", 20000, false, "i", GID);
    return 1;
}
Wow... Thanks for the organized code, but can you tell me what's the difference? Why is there a need to keep track on the objects?
Quote:
Originally Posted by Antonio144
Посмотреть сообщение
floatsin returns sine of an angle (which is a float), whereas asin is an inverse function of sine (sine^-1). For example:

floatsin(60, degrees) ~ 0.866,
asin(0.866) ~ 60°.



This creates a specific number or objects equally distributed around a point.
pawn Код:
stock CreateCircleAroundpoint(objectid, Float:x, Float:y, Float:z, Float:radius, OBJECT_NUMBER)
{
    new Float:x2, Float:y2, Float:angle = 360/(OBJECT_NUMBER), Float:a = 0.0;
    for(new i=0; i<OBJECT_NUMBER; i++)
    {
        printf("%f",a);
        x2 = x + floatcos(a,degrees) * radius;
        y2 = y + floatsin(a,degrees) * radius;
        a += angle;
        CreateObject(objectid, x2, y2, z, 0.0,0.0,0.0);
    }
}
Now it all makes sense. I thought asin and floatsin are the same. I guess asin is arcsine then. Thanks for that
And what is OBJECT_NUMBER? The number of objects to be created?
Reply
#10

more objects created = more gaps between the circle are filled, depending on the size (width) of the objects ofc
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)