Upscale layer position offset fix

0 favourites
  • 10 posts
  • Hello all,

    I have a large group of multiple objects. This group of objects needs to be able to be upscaled/downscaled as a whole, at runtime. I decided the most efficient way to do this is to put the objects on a separate layer, and scale this layer up/down.

    The scaling works well, but the cluster of objects now seems to have a positional offset. It does not stay in one place as expected, but moves around relative to the viewing window. The cluster of objects is directly in the centre of the layout, if that simplifies things. There is no parallax.

    Any way to fix/change/compensate for this?

    Thanks, sqiddster

  • Try Construct 3

    Develop games in your browser. Powerful, performant & highly capable.

    Try Now Construct 3 users don't see these ads
  • Is the layout smaller than the screen size it's scaling to? If so, you need to set unbounded scrolling to yes for centered things to actually be centered :)

  • MonstaMunch, this is not the issue. The layout is quite large, and unbounded scrolling is on anyway.

  • <img src="http://dl.dropbox.com/u/36472942/construct/forumhelp/LayerSize_offset_explanation.png" border="0" />

    The black layer is the original layer, the blue one is the sized layer, using the same center.

    Indeed there is an offset between the original and resized ones.

    "Lazy" solution, place all "swarm" objects in a family and reduce the size of each object of the family by a certain percentage.

  • Kyatric, the image you posted is indeed my problem.

    However, the lazy solution you suggested simply makes all the objects bigger... how would I increase the size of the whole by adjusting the position of all the objects accordingly?

  • Hmm... any mathies care to help? How do I correctly adjust the object's positions and size so that they adjust to create a larger shape?

  • I guess it's a bit the same trigonometry formulas that we used for the rotary competition.

    You need a "reference" point as the original distance and angle towards another "member" of the group of object, and on resize you use the layer's size as a factor instead of the new angle.

    I guess that's for theory, for the formula itself unfortunately, I don't know.

  • Well Kyat you said it all,

    For the reference point you can take the average point

    Global number scale = 1
    System: On Start of Layout
      -> Object: set scale to scale 
    on anything
      Local number xSomme = 0
      Local number ySomme = 0
      Local number cx = 0  // X center of scale
      Local number cy = 0  // Y center of scale
      [Empty]
        -> System: set scale to 0.5
      System:Foreach object
       -> System: add object.X to xSomme
       -> System: add object.Y to ySomme
      [Empty]
       -> System: set cx to xSomme/object.count
       -> System: set cy to ySomme/object.count
      System: Foreach object
       -> Object: set distance to distance(cx,cy,self.X,self.Y)
       -> Object: set a to angle(cx,cy,self.X,self.Y)
      [Empty]
       -> Object: set distance to self.distance/self.scale
       -> Object: set width to self.width/self.scale
       -> Object: set height to self.height/self.scale
       -> Object: set scale to scale
       -> Object: set distance to self.distance*self.scale
       -> Object: set width to self.width*self.scale
       -> Object: set height to self.height*self.scale
       -> Object: set X to cx+cos(self.a)*self.distance
       -> Object: set Y to cy+sin(self.a)*self.distance

    Should work but untested.

    Explanation :

    System: On Start of Layout
      -> Object: set scale to scale 

    We make sure each object always "knows" at which scale they are. Else if you want to put the scale to 0.5 when the scale is already at 0.5 you might end up with a scale at 0.25...

    on anything
      Local number xSomme = 0
      Local number ySomme = 0
      Local number cx = 0  // X center of scale
      Local number cy = 0  // Y center of scale
      [Empty]
        -> System: set scale to 0.5
      System:Foreach object
       -> System: add object.X to xSomme
       -> System: add object.Y to ySomme
      [Empty]
       -> System: set cx to xSomme/object.count
       -> System: set cy to ySomme/object.count

    "On anything" 'cause it depends on your implementation.

    We declare some local variables

    We set the scale to whatever you want (here 0.5)

    The rest is pretty much an average calculation. To take the average between a bunch of number you add them and then divide by the number of value you added. I do the addition in the foreach and the division in the [Empty] condition (for those who doesn't know [empty] is the same as "Every Tick")

      System: Foreach object
       -> Object: set distance to distance(cx,cy,self.X,self.Y)
       -> Object: set a to angle(cx,cy,self.X,self.Y)

    We calcultate the distance from the average point and the angle and we store them in instance variables 'distance' and 'a' ('angle' couldn't be used as it's the angle of the object).

      [Empty]
       -> Object: set distance to self.distance/self.scale
       -> Object: set width to self.width/self.scale
       -> Object: set height to self.height/self.scale
       -> Object: set scale to scale
       -> Object: set distance to self.distance*self.scale
       -> Object: set width to self.width*self.scale
       -> Object: set height to self.height*self.scale
       -> Object: set X to cx+cos(self.a)*self.distance
       -> Object: set Y to cy+sin(self.a)*self.distance

    As we only operate on instance variable properties we don't need a foreach (it's kinda implicit).

    [1st to 3rd action] we bring distance and size back to what it would be at scale 1. As we always store the current scale in the 'scale' instance variable.

    [4th action] We apply the 'scale' global number to the 'scale' instance variable (oh yeah just to confuse you :D)

    [5th to 8th action] Then we apply the scaling transformation on distance and size.

    [9th and 10th action] We move objects toward or away from the average center depending on 'distance' and 'a' (obviously angle never need to be scaled)

    That's al foks

  • Wow, thanks Yann! I'll try to implement this soon. I assume this will work for a family eh?

  • As long as it uses family variable instead of instance variables yes

Jump to:
Active Users
There are 1 visitors browsing this topic (0 users and 1 guests)