RTS game problem when rotating units formation

G

Gustavo_0

Guest
Ok, so I really tried to upload images to help but I couldn't, it says it has a server error, so if someone can help with that too I'm would be thankful.

Anyway, I was trying to do a rts like project, and I managed to be able to make the units move into formation. However, I tried to make them rotate, the whole formation, using trigonometric functions and I didn't work.

This is how is the code like (I don't think the rest is needed but ask if you need):
Code:
/// @description Insert description here// You can write your code in this editor
x1 = -1;
x2 = -1;
y1 = -1;
y2 = -1;

xOrigin = -1;
yOrigin = -1;

xSecond = -1;
ySecond = -1;


dragging = false;

selectedUnits = ds_list_create();

angle = 0;  //the angle that the units would turn
lastAngle = 0; //to don't keep turning
This is the creation script of the object that manages the movement

Code:
if (mouse_check_button_pressed(mb_left)) {
  
    if(!position_meeting(mouse_x, mouse_y, obj_button)) {
  
        for(i = 0; i<instance_number(troop); i++) {
            ds_list_clear(selectedUnits);
            troopSelected = instance_find(troop, i);
            troopSelected.isSelected = false;
            troopSelected.onlySelected = false; //don't mind this
        }
  
        ds_list_clear(selectedUnits);
  
        dragging = true;
  
        xOrigin = mouse_x;
        yOrigin = mouse_y;
    } else {
      
    }
}

if (mouse_check_button(mb_left)) {
    if (dragging = true) {
        xSecond = mouse_x;
        ySecond = mouse_y;
    }
}

if (mouse_check_button_released(mb_left)) {
    dragging = false;
  
    for(i = 0; i<instance_number(troop); i++) {
        troopSelected = instance_find(troop, i);
        if (
            ((troopSelected.x < x1) and (troopSelected.x > x2)) and
            ((troopSelected.y < y1) and (troopSelected.y > y2))
            ) {
                troopSelected.isSelected = true;
                ds_list_add(selectedUnits, troopSelected);
          
            }
    }
  
    if (ds_list_size(selectedUnits)=1) {
        (ds_list_find_value(selectedUnits, 0)).onlySelected = true;
    }
}


if (xSecond > xOrigin) {
  
    x1 = xSecond;
    x2 = xOrigin;
}

if (xSecond < xOrigin) {
  
    x2 = xSecond;
    x1 = xOrigin;
}

if (ySecond > yOrigin) {
  
    y1 = ySecond;
    y2 = yOrigin;
}

if (ySecond < yOrigin) {
  
    y2 = ySecond;
    y1 = yOrigin;
}

if (mouse_check_button_released(mb_right)) {
    target = array_create(2);
    target[0] = mouse_x;
    target[1] = mouse_y;
    setTargets(selectedUnits, target, angle, lastAngle);
}

//I did this as a simple way to change the rotation
if (keyboard_check(vk_up)) {
    angle +=10;
}

if (keyboard_check(vk_down)) {
    angle -=10;
}
This is the object step code

Code:
units = argument[0];
target2 = argument[1]; //acho que nao interfere
angle2 = 0; //ja que existe outro angulo em object0
angle2=argument[2];
lastAngle = argument[3];

//THE NAMES ARE ALL WEIRD BECAUSE I DISCOVERED THAT YOU CAN REFERENCE
//VARIABLES OF THE OBJECT YOU CALLED ON THE SCRIPT, SO I NEEDED TO CHANGE THEIR NAMES

xOrigin2 = target2[0]; //mesma coisa
yOrigin2 = target2[1];

global.xv = xOrigin2;
global.yv = yOrigin2;


a = 0;

size = ds_list_size(units); //Unit list size
division = 4;               //The maximum of units per row
rest = size mod division;   //The units that will not reach the maximum in the row
restSize = size - rest;

width = 32; //The width of units
space = 0; //The space between units

totalWidth = rest * width + (rest-1) * space;
target2[0] = xOrigin2 - totalWidth/2;


//The loop may be a bit messy since I just did it, sorry
for (i=0; i<size; i++) {

    if (rest > 0) {
      
        if (a>=rest){
          
          
            a = 1;
            rest = 0; //to get out of loop
          
            totalWidth = division * width + (division-1) * space;
          
            target2[0] = xOrigin2 - totalWidth/2;
            target2[1] += 32;
          
            createTarget(target2[0], target2[1], xOrigin2, yOrigin2, i, units, angle2 , lastAngle);
          
            target2[0] += space + width;
          
            continue
        }
      
        a++;
      
        createTarget(target2[0], target2[1], xOrigin2, yOrigin2, i, units, angle2,lastAngle);
      
        target2[0] += space + width;
      
      
        continue
    }
  
    if ((i=0) and (rest=0)) {
        totalWidth = division * width + (division-1) * space;
        target2[0] = xOrigin2 - totalWidth/2;
    }
  
  
    if (a>=division) {
        a = 1;
        target2[0] = xOrigin2 - totalWidth/2;
        target2[1] += 32;
      
        createTarget(target2[0], target2[1], xOrigin2, yOrigin2, i, units, angle2, lastAngle);
      
        target2[0] += space + width;
      
        continue;
    }
  
  
  
    createTarget(target2[0], target2[1], xOrigin2, yOrigin2, i, units, angle2, lastAngle);
  
    target2[0] += space + width;
    a++;


}
This is the movement script

Code:
firstX = real(argument0); //the first x position before rotacting
firstY = real(argument1); //the fisrt y position before rotacting
xOrigin3 = real(argument2); //where the mouse clicks, the x where all the others are calculated from
yOrigin3 = real(argument3); //same as above
b = argument4;
unitss = argument5;
addAngle = real(argument6);
lastAngle = argument7;


xDistance = xOrigin3 - firstX;
yDistance = yOrigin3 - firstY;  
h = xDistance*xDistance + yDistance*yDistance; //distance between the points
h = sqrt(h);


if(xDistance!=0 and h!=0) {
    cosValue = xDistance/h;
} else {
    cosValue = 0;
} if(yDistance!=0 and h!=0) {
    sinValue = yDistance/h;
} else {
    sinValue = 0;
}

if(xDistance!=0 and cosValue!=0) {
    xDiv = xDistance/cosValue;
} else {
    xDiv = 0;
}

if(yDistance!=0 and sinValue!=0) {
    yDiv = yDistance/sinValue;
} else {
    yDiv = 0;
}

originalSin = sinValue;
originalCos = cosValue;

//This part was made because there's more than one angle with the same sines and cosines
//I don't know if it was necessary though
if(originalSin<0) {
  
    aux = (darccos(cosValue));
    angle3= 90 - aux + 270;
  
} if(originalSin>=0) {

    angle3=(darccos(cosValue));
}

if(originalCos<0) {
  
    aux = (darcsin(sinValue));
    angle3= 180 - aux;
  
} if(originalCos>=0) {
  
    angle3=(darcsin(sinValue));
  
}

//This would be to the angle not turn again after it was set
addAngle = addAngle - lastAngle
lastAngle = addAngle;


//I think here is where the proble
cosValue = dcos(angle3-addAngle);
sinValue = dsin(angle3-addAngle);

//This also I think it's not necessary
if(xOrigin>firstX) {
    finalX = xOrigin3 - cosValue*xDiv;
} else {
    finalX = xOrigin3 + cosValue*xDiv;
}

if (yOrigin>firstY) {
    finalY = yOrigin3 - sinValue*yDiv;
} else {
    finalY = yOrigin3 + sinValue*yDiv;
}

unit = ds_list_find_value(unitss, b);
unit.target = instance_create_depth(finalX, finalY, 0, obj_target);
unit.startMoving = true;
And this the other script that should handle rotation

If the code of this last one script was just

Code:
finalX = firstX;
finalY = firstY;

unit = ds_list_find_value(unitss, b);
unit.target = instance_create_depth(finalX, finalY, 0, obj_target);
unit.startMoving = true;
It works without rotation, but if not even with 0 angle the formation is all messy. I added this bit about rotation after I set the movements, so firstX and firstY would be just passed to the instance create method

Also, before I tried various other things, this part looked like this:
Code:
firstX = real(argument0); //the first x position before rotacting
firstY = real(argument1); //the fisrt y position before rotacting
xOrigin3 = real(argument2); //where the mouse clicks, the x where all the others are calculated from
yOrigin3 = real(argument3); //same as above
b = argument4;
unitss = argument5;
addAngle = real(argument6);
lastAngle = argument7;


xDistance = xOrigin3 - firstX;
yDistance = yOrigin3 - firstY;  
h = xDistance*xDistance + yDistance*yDistance; //distance between the points
h = sqrt(h);


if(xDistance!=0 and h!=0) {
    cosValue = xDistance/h;
} else {
    cosValue = 0;
} if(yDistance!=0 and h!=0) {
    sinValue = yDistance/h;
} else {
    sinValue = 0;
}

if(xDistance!=0 and cosValue!=0) {
    xDiv = xDistance/cosValue;
} else {
    xDiv = 0;
}

if(yDistance!=0 and sinValue!=0) {
    yDiv = yDistance/sinValue;
} else {
    yDiv = 0;
}

originalSin = sinValue;
originalCos = cosValue;


//This would be to the angle not turn again after it was set
addAngle = addAngle - lastAngle
lastAngle = addAngle;


//I think here is where the proble
cosValue = dcos(angle3-addAngle);
sinValue = dsin(angle3-addAngle);


finalX = firstX;
finalY = firstY;

unit = ds_list_find_value(unitss, b);
unit.target = instance_create_depth(finalX, finalY, 0, obj_target);
unit.startMoving = true;
Or something like that

Actually, I think I made it worked on accident one time, and they rotated right, but I can't seem to make it work again.
Also I couldn't upload images, so that may make it harder to understand. If someone knows why I can't please tell me


 
Can you describe exactly what your system is trying to do, so that we don't have to reverse engineer it. Figuring out the intent of someone else's code can be especially difficult if the code doesn't work to begin with.

It looks to me that you are doing more than just rotating a point and having the unit move in a straight line to that point. Is that correct?
 
G

Gustavo_0

Guest
Sorry, I tried to upload images to help but they didn't work.
Basically first the code sets the units organized into a formation, like in normla rts games. Then, after that, all the positions of that formation, would be rotated in from an axis, that is where you mouse clicked on this case, so the formation would be the same, but rotated, so each unity would have it's position recalculated, but in such a way that all them were still in the same proportions between each other
 
I presume you already have the point around which the other points should rotate. And that you have calculated the correct angle by which to rotate the formation.

Is the problem just to rotate points around some other point?

If that is the case, origin_x/yy being the point around which you want to rotate, and c and s being the cosine and sine of the angle of rotation (use dcos and dsin if working with degrees), old_point_x/y being the original unrotated point in the formation:

new_point_x = origin_x + (old_point_x - origin_x) * c + (old_point_y - origin_y) * s;
new_point_y = origin_y + (old_point_x - origin_x) * -s + (old_poitn_y - origin_y) * c;
 
G

Gustavo_0

Guest
Thanks! That did work. Where did you learn this by the way? I think I should read more books about calculation
 
Top