cacotigon's Forum Posts

  • MultipleChoice: I've tested your original example as well as the one you posted in the bug report test_example.capx. This "shaking" you're referring to, the problem with the "shaking", is it possible that this is a v-sync / graphical glitch?

    Here are some test cases you should try out:

    1. Turn a small layout, disable camera following code

    2. Pixel rounding off / on

    3. Sampling - Linear/Point

    In which combination of these options does the problem go away?

    If we can narrow the problem down to the scrolling code, maybe try only moving the camera when the difference between (Scrollx, scrolly) and (PlayerX, PlayerY) is > 1 pixel. Also try using a lerp for the camera to see if it smooths out the scrolling any.

    Just set a local variable CameraSpeed to 1/2.

    Scroll to position:
    lerp(ScrollX, PlayerBox.X, dt * CameraSpeed)
    lerp(ScrollY, PlayerBox.Y, dt * CameraSpeed)
    [/code:mjecg8gw]
  • MultipleChoice

    Hmmm, I didn't notice any shaking happening testing on Firefox/Chrome. I couldn't fit into the any of the corridors, so I adjusted the bounding box for the player by x +/- 0.5 and the top by -0.5 with pixel rounding ON or OFF this solves the problem and it seems to work okay. Here's the updated capx.

    https://dl.dropboxusercontent.com/u/12667027/Construct%202/updatedtest.capx

    If you want, PM me and we can discuss it further.

  • > Aphrodite

    >

    > It is true that functions cannot be referenced from an event sheet that does not include the relevant sheet containing the function itself. However, event sheets cannot be included conditionally.

    >

    > You will notice that when you include an event sheet, the INCLUDE statement is always placed at the top of the event sheet.

    >

    > A conditional include would look something like this:

    > IF X == TRUE THEN INCLUDE EVENTSHEET1

    > ELSE INCLUDE EVENTSHEET2

    >

    > All event sheets (which are represented as XML) are converted to Javascript and bundled in the final exported code during the build process. When a project is previewed/exported, Construct knows exactly what functions are available at a per-event sheet level.

    >

    > Refeuh

    >

    > You're right about that. As a software engineer by trade, Construct is a way for me to wind-down at the end of the day. It's definitely my favorite RAD tool for games.

    >

    an include can be a subevent, thus conditionnal, C2 may place the include at the top, but you can move it freely.

    Aphrodite It doesn't matter. The include statements are not processed at a run-time conditional level. All event sheets are bundled into the final JS code of a project irrespective of whether they are explicitly included. So you can move the INCLUDE blocks around wherever you want, but it makes no difference.

    Here's a capx demonstrating it and the associated code.

    Capx

    https://dl.dropboxusercontent.com/u/12667027/IncludeTest/includetest.capx

  • Aphrodite

    It is true that functions cannot be referenced from an event sheet that does not include the relevant sheet containing the function itself. However, event sheets cannot be included conditionally.

    You will notice that when you include an event sheet, the INCLUDE statement is always placed at the top of the event sheet.

    A conditional include would look something like this:

    IF X == TRUE THEN INCLUDE EVENTSHEET1

    ELSE INCLUDE EVENTSHEET2

    All event sheets (which are represented as XML) are converted to Javascript and bundled in the final exported code during the build process. When a project is previewed/exported, Construct knows exactly what functions are available at a per-event sheet level.

    Refeuh

    You're right about that. As a software engineer by trade, Construct is a way for me to wind-down at the end of the day. It's definitely my favorite RAD tool for games.

  • A DoesFunctionExist method wouldn't be too difficult to add. Given that functions can't be created/destroyed/modified during run-time, Construct would simply compile a hash list of the function names as part of the build process, and then a DoesFunctionExist event would be a matter of a single dictionary lookup. Negligible as far as performance loss is concerned.

    In terms of these sorts of "reflection"-esque types of methods, I'm still waiting for ObjectInstance.Name which would return the asset library name of any instance at run-time.

  • Hmmm, I just did some testing.

    As I mentioned earlier, bounding box coordinates are stored as ratios in the XML. So for example, if you have an animation with two frames, frame1 is a 32x64 image, and your bounding box coordinates are (0, 32), (0, 64), (32, 64), and (32, 32) -- eg, the lower half of your sprite, then the XML will store these values as (0, 0.5), (0, 1), (1, 1), (1, 0.5). Frame 2 however is 32x128, twice as tall. If you right-click and apply the original bounding box to the entire animation, frame2's bounding box will be *twice* as high as frame1's bounding box.

    Here's a picture to clarify:

    It should be noted that image points are stored internally the same way.

    Obviously this is exaggerated for purposes of explanation, but I'd wager it can lead to potentially subtle bounding issues when you factor in things like toggling pixel rounding, and if a frame's height changed from an even value to an odd value.

    I think people get burned when they don't use fixed dimensions (or they do on import, but then let Construct crop transparent edges). Then they setup a single bounding box on the first frame of some given animation in a sprite and apply that bounding box to an entire set of animation's frames.

    I just did a quick prototype using the SingularEntity (aka Controller also has animations) of Mario. I can walk, run and jump on flat and sloped surfaces without any problems at all. However, I was very careful to import all my animations as a fixed dimension sprite sheet. Seems to work perfectly. I'll post it up later if anyone's interested.

    MultipleChoice, If you still happen to have the old original project with the jittery animation, I'd be willing to take a look at it and see what's going on with it.

  • Yeah, I've always done it that way in the past. The problem is if you have a complex set of animations, you have to be careful with lining up collision boxes in your controller to match the animated sprite, since you'll have to change frames/animations in the controller itself to change the collision box which happens a lot in a character with lots of different styles of movement (example: ducking).

    Finally you get all the collision boxes relatively the same and then later down the line you realize you have to alter some of the frames of the animated sprite.... So you have to go back in and change all the collision boxes in the controller again.

    MultipleChoice - Regarding your animations getting stuck, hmmm, were you using fixed dimensions on each frame or did it change? You'll definitely run into problems on a platformer behavior character if origins/bounding boxes vary from frame to frame in a single animation. I actually noticed that if you have two frames of walking animation, Say F1 and F2, but each frame has a different dimension and you attempt to apply bounding box to whole animation, the bounding box vertices end up as slightly different floating point values - maybe this has to do with the fact that the underlying project XML stores these type of coordinate values as fractional ratios from 0-1 against the whole image.

  • I have a "design-related" problem in Construct.

    For the longest time, I've always used a hidden controller which spawns the connected AnimatedSprite for all entities in the game, players, npcs, enemies, etc. Both the controller and animated sprite would have origins set to the "Center Bottom" of the images to keep things consistent.

    I'm going to define a few terms so that my question is relatively clear:

    Controller - An invisible sprite with logic, and behaviors of the actual entity itself.

    AnimatedSprite - The sprite containing all animations for the entity which is pinned to the controller.

    Animation - A single animation within the AnimatedSprite, such as "Walking", "Running", "Jumping", etc.

    However, I've done three things recently that have made me inclined to change my mind, aka, to want to merge the Controller and AnimatedSprite together as a single Sprite. I will refer to this concept as a "SingularEntity".

    • Fixed Dimensions - All dimensions within a single animation are identical, so all jump frames might be 32x52, all walk frames might be 32x50, etc. Everything is consistent for purposes of bounding boxes, and origins. I'm very careful about this.
    • Origin Point Consistency - For an entire Animated Sprite, all animations have the same origin point, for example, a platforming character's origin point would be center bottom.
    • Construct Family support - With family support, the first time I create a SingularEntity, I put it in a new family. The SingularEntity does not have any member variables, all properties/behaviors *ALWAYS* exist on the Family itself. This means that it is easy to create new Entities with the same behavior as the original.

    What are the advantages of using a SingularEntity?

    I don't have to worry about setting up any pinning behaviors. Easy to draw and change my bounding boxes, since the bounding boxes exist on each respective Animation within the SingularEntity. It is easy to check that my bounding boxes are drawn in the appropriate places since they exist on the actual animations themselves.

    What are the disadvantages of using a SingularEntity?

    The only disadvantage I can think of, is that if you wanted to swap out an entire AnimatedSprite for another AnimatedSprite. For example, let's say the player's character morphed into a completely different character. Having a distinct controller would mean you could replace the old AnimatedSprite with a new AnimatedSprite while preserving all player's stats which live on the invisible Controller itself.

    It seems like the simplification afforded by using a SingularEntity make it worth using over keeping lots and lots of 1:1 controller sprite / animated sprite mappings. Although I'm fairly sure that either solution is viable, I'm hoping to gain some insight on the potential implications of using one over the other.

    Thanks!

  • Try Construct 3

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

    Try Now Construct 3 users don't see these ads
  • I like http://www.screencast-o-matic.com/. They've been around for a few years and I've had pretty good luck recording with them in the past. Since the recorder is a java applet, you don't have to install anything and you can resize the capture window. I've recorded everything from emulated games to presentations with it. It also uploads to Youtube fairly simply.

    Disclaimer: Free version is limited to 15 minutes per video but that should probably be more than adequate for the majority of situations.

    Framerate is also capped at 15fps.

  • Ashley

    That's true. The case usage I was thinking of was more along the lines of, being able to get a quick reference to a member variable of an object instance without having to alter/change the current SOL. (though I guess the SOL will remain intact if you put it in a subevent block)

    With UID indexer it's just nice because you don't have to write a separate "Pick All, Pick by Unique UID, Save Object.MemberVariable to Temporary Local Variable." Event. You can't really use the IID indexer for this type of situation either since IID is not guaranteed to be a consistent reference.

  • +1 for an expression based UID indexer. There was a thread a couple years back about this, perhaps using object[UID] as opposed to object(IID).

    https://www.scirra.com/forum/viewtopic.php?f=146&t=66712

    Ashley Are there any plans to add this? In some cases it would allow us to skip having to make extra picking events altogether.

  • Tokinsom

    Thanks for the reply! Hmmm, I didn't really think about the implications of hotspots. Do you import a single sprite sheet png file into a Construct sprite object and let Construct cut it up by fixed dimensions? Or do you import each frame from a separate file?

    For a while I also tried to use my animation sprite as my collision sprite as well, but if you attempt to apply bounding box to an entire animation where the frames are slightly differently sized (even by a few pixels), the box gets messed up by fractional values. That's why I switched my collision poly over to my invisible base "object controller" with platform behavior.

    Just so I understand you correctly, after the import and as a result of using fixed size sprites for an entire animation, you'll have some transparent borders that might extend a few pixels? Do you usually make the origin point the bottom of the sprite or does it depend?

  • Back in the day, I would always make sure that a set of sprites in an animation had the same fixed dimensions. So if I had a run animation (for example) consisting of four sprites, I would set each sprite's canvas size to be equal to the size of the sprite in the animation with the largest size, which usually resulted in some transparent margins.

    Mostly I did this to make sure that when I was rendering the animation to screen, it ensured that the animation was fixed in place since the origin was usually top-left. It also made it easier to draw sprites via a source rectangle since I usually drew the sprites from a single sprite sheet at run-time.

    With Construct's ability to import a set of images and crop the transparencies, is there any point to using identically fixed-dimensions for each sprite in an animation? It feels like since I can set the origin point to the same absolute location across a set of frames that I don't have to worry if each frame in a given animation has varying sizes. Additionally, like most people using Construct, I use a separate platform sprite for purposes of collision detection.

    What does everyone else think?

  • DuckfaceNinja

    That's what I refer to as "unpacking/packing" in my original post. It's inelegant for a number of reasons especially if you want to preserve a "is host/peer agnostic" type of architecture in the code.

    In order to address the problem, I had to create a top-level function called "CustomSendMessage" which takes three parameters:

    • DestinationId
    • Tag
    • Message

    There is a special global tag I created called "RELAY_MESSAGE" which I will reference later.

    Let me outline the function's logic branches for you:

    • Function is being called by the host: no wrapping is necessary, use Multiplayer Send Message normally.
    • Function is being called by a client but the destination is the host: Again no wrapping is necessary, use Multiplayer Send Message normally.
    • Function is being called by a client and destination is a client: Send a message to the host with Tag (RELAY_MESSAGE), message is modified to be: DestId & "|" & OriginalTag & "|" & OriginalMessage

    Now we need a Host-only Multiplayer On Message RELAY_MESSAGE received logical trigger:

    • Unpacks the modified message, prepares to send a normal message to the true peer DestId with OriginalTag
    • The modified message becomes: Multiplayer.FromID & "|" & OriginalMessage

    Whenever a client receives any message, they have to determine if the true sender was the HOST or a relayed client which is done through a custom function called:

    GetTrueSender (string Message) - Returns Multiplayer.FromID or a token if the true source peer id was packed into the message.

    It works and solves the problem since the messages in my app are fairly infrequent, otherwise this solution might possibly introduce some latency in a different type of app.

    Either way, I'm still having to write a bit of kludge in that I'm adding a potentially unnecessary man-in-the-middle if it is actually possible to send direct messages peer-to-peer. However, this may be a limitation of WebRTC (all messages have to be sent to the peer-to-host-to-peer), I haven't done enough research.

  • It would be great if we had an action that could send a message from a peer to a non-host peer and the host would automatically handle relaying it. I can get around this with some fancy footwork and awkward packing/unpacking functions, but this would save some time:

    Multiplayer.RelayToPeer(Destination Id, Tag, Message, Reliability)

    • If this action is used from host, it functions like a normal Send Message.
    • If this action is used from a non-host peer, it sends the message to the host which would relay the message to the appropriate peer id and also preserve the true from id.

    *** If this is considered too in-depth ***

    Maybe could we just add a simple action BroadcastToSinglePeer which adds a DestPeer Id field?