Change origin at runtime

  • Hey guys.

    First of all I know little about programming (let alone javascript), but I really needed this functionality in the sprite plugin.

    So i fiddled around with the SDK and added 2 actions in the sprite plugin. To my surprise, it seems to work. The problem is that the collision poly doesn't get updated and I would really need some help from the gurus here!

    Please backup the official sprite plugin before trying this.

    https://dl.dropboxusercontent.com/u/14855413/c2/origruntime/sprite.rar

    capx:

    https://dl.dropboxusercontent.com/u/14855413/c2/origruntime/hotspot1.capx

  • rexrainbow

    @R0J0hound

    @ruskul

    @newt

    Sorry for tagging you guys (i'm sure I forget others too), but I would greatly appreciate if you can take a look at this and give me some guidelines.

  • You may try looking in this plugin here:

    In it there's an action to move the origin around and the collision polygon is updated. Maybe that could be a reference.

  • R0J0hound thank you very much!

    I took a look at this excellent plugin and if I understand right, the setOrigin action offsets the polygon vertices?

    What I'm aiming for is exactly how the Construct 2 editor works: When you change the origin of a sprite inside the editor, the origin stays at the current x and y and it's just the texture that "jumps" to an offset position. In the polygon plugin that doesn't seem to be the case.

    However, I found a line of code inside the plugin that seems to do what I want but i can't figure out what values to pass:

    this.collision_poly = new cr.CollisionPoly(new Array(0,0,0,0,0,0,0,0));

    It seems these are pairs of x,y values for each point in the collision poly, starting from top-left and going in a clockwise fashion? I can't understand if these are local or world coordinates.

    Thanks in advance.

  • Best I know those are local points relative to the top left of the unrotated and unscaled object. It could be center too, you'd just have to test it. Worst case it would be relative to the hotspot.

    Just a thought, I haven't looked at your code but it might be enough to just call update_bbox() after changing the hotspot.

  • R0J0hound

    I will try to figure out what those values mean. I already called update_bbox() and set_bbox_changed(), it's just the collision poly points that don't get updated and I suppose I'll have to find a way to shift them manually.

    Once more thank you for your time!

  • OK it seems I found something:

    Firstly, It seems that if the collision poly is set to bounding box, the first point is bottom-left and the rest are in a clockwise fashion.

    With the following code I was able to calculate the new collision poly:

    this.type.animations[0].frames[0].poly_pts[0]= -hx/this.width

    this.type.animations[0].frames[0].poly_pts[2]= -hx/this.width

    this.type.animations[0].frames[0].poly_pts[4]= 1-(hx/this.width)

    this.type.animations[0].frames[0].poly_pts[6]= 1-(hx/this.width)

    this.type.animations[0].frames[0].poly_pts[1]= 1-(hy/this.height)

    this.type.animations[0].frames[0].poly_pts[3]= -hy/this.height

    this.type.animations[0].frames[0].poly_pts[5]= -hy/this.height

    this.type.animations[0].frames[0].poly_pts[7]= 1-(hy/this.height)

    Now the problem is that it's not instantly updated. It's only when you perform a scale or rotation operation that it "snaps" into its proper position.

    Updated plugin and CAPX:

    https://dl.dropboxusercontent.com/u/14855413/c2/originatruntime2/sprite.rar

    https://dl.dropboxusercontent.com/u/14855413/c2/originatruntime2/hotspot1.capx

    If you try it out, first enter some new values for x,y origin and then use right click to rotate and middle click to scale.

    Please if someone can share his thoughts or can find why the poly is updated only after a rotation/scale operation I would really appreciate it.

  • Any chance you could do a quick copy paste of the code? I can't download the files currently but I could look at the code if it were here. Thanks!

  • ruskul , sure man and thanks in advance!

    edittime:

    AddNumberParam("HotspotX", "Set the sprite's HotspotX", "1");
    AddAction(12, 0, "Set HotspotX", "Size & Position", "Set hotspotX to <i>{0}</i>", "Set the sprite's HotspotX", "SetHotspotX");
    
    AddNumberParam("HotspotY", "Set the sprite's HotspotY", "1");
    AddAction(13, 0, "Set HotspotY", "Size & Position", "Set hotspotY to <i>{0}</i>", "Set the sprite's HotspotY", "SetHotspotY");
    
    [/code:w2hpv2km]
    
    runtime:
    [code:w2hpv2km]    Acts.prototype.SetHotspotX = function (hx)
        {
            this.hotspotX=hx/this.width;
            this.type.animations[0].frames[0].poly_pts[0]= -hx/this.width
            this.type.animations[0].frames[0].poly_pts[2]= -hx/this.width
            this.type.animations[0].frames[0].poly_pts[4]= 1-(hx/this.width)
            this.type.animations[0].frames[0].poly_pts[6]= 1-(hx/this.width)
            this.set_bbox_changed();
            log("points = "+this.type.animations[0].frames[0].poly_pts );
            
        };
    
        Acts.prototype.SetHotspotY = function (hy)
        {
            this.hotspotY=hy/this.height;
            this.type.animations[0].frames[0].poly_pts[1]= 1-(hy/this.height)
            this.type.animations[0].frames[0].poly_pts[3]= -hy/this.height
            this.type.animations[0].frames[0].poly_pts[5]= -hy/this.height
            this.type.animations[0].frames[0].poly_pts[7]= 1-(hy/this.height)
            this.set_bbox_changed();
            log("points = "+this.type.animations[0].frames[0].poly_pts );
            
    	};[/code:w2hpv2km]
  • Its cool you have gotten this far with it. For claiming to not know much code, you are well on your way. I am curious, I know its not ideal but can you set the angle of the sprite to itself.angle right after changing the polygon. You said that updates the polygon right? You could simply call it good if it works from there... I say this, but that solution would drive me up the wall...

    So, what I think is, I imagine that internally contruct 2 only refreshes the polygon when it needs to. Basically, Lets say you have the polygons points stored in A. When construct 2 runs, it stores a new set of points in B. These are calculated based on the rotation and scale of the sprite. Calculating B takes a bit of work and there is no reason to perform that work every tick unless you have to. Changing an angle or scale would be a good reason to recalculate B. If you think about it, A is only useful for calculating B, where B is actually the real points of a collision polygon in the game world. Does this all make sense? Its the same reason you tell construct 2 to update the bbox. There is no reason to recalculate its position when it isn't changing. The same thing is true of the collision polygons points relative positions based on rotation.

    I think if you look into the sprite you might find a clue in .SetAngle()... I am going to take a peek when I get a chance, but thats where I would start.

    I am completely pulling this out of nowhere, just a hunch. But it would explain why

  • Try Construct 3

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

    Try Now Construct 3 users don't see these ads
  • Well, you can strike my last comment. When an angle is changed, contruct 2 calls bbox changed after updating the angle. hmmm

  • ruskul your thoughts are very useful to me and thanks for taking the time to respond!

    I tried to change the angle to self.angle right after changing the origin, but construct is smart enough to NOT trigger an update to the collision box! It does exactly as you said, no unnecessary calculations without a reason because the engine understands there wasn't a real change in angle.

    I also took a look at commonace.js but I couldn't find how the collision poly is moved after rotate/scale. All those actions just call this.set_bbox_changed();

  • Ya you are right, I realized when looking at the change angle that it only changes the angle if it is different. You might try getting Ashley to weigh in on the conversation. There have been a few times when I wanted to do something but didn't know if I was overlooking something or if it was part of the blackbox portion of c2 we can't touch.

    Either way, he might add it to an update if it is something simple. One workaround you might try is simply to add an offset vector and store it to the sprite. you could then use that offset to artificially change its position for visual appearance or use it in collision detection as overlapping offset. I know it doesn't actually address the problem though.... Personally I hate workarounds even if they did work perfectly, lol but here I am offering a "why don't you do this instead" type comment...

    It is a bit of a conundrum.

  • Thanks again for your help man! Although I know he's extremely busy I will tag Ashley and maybe he can shed some light when he has time!

    BTW in common_prelude I see tons of stuff about points cache and I'm thinking It might have to do something with updating the poly.

  • It looks like you'll need to call this function:

    CollisionPoly_.prototype.cache_poly = function(w, h, a)[/code:1bjeiulg]
    The only catch is it won't update if the width, height or angle haven't changed. So you'll probably need to change one of those first.
    
    I only took a quick look so I didn't investigate where that function is usually called.  You may even be able to change the size or angle of the object to force a update without calling the function if it's called every tick anyways.  Or instead you could change the .cache_width value from the polygon.
Jump to:
Active Users
There are 1 visitors browsing this topic (0 users and 1 guests)