Ashley's Forum Posts

  • So I've been trying to make a game with save/load capability using a global array

    Why not use the System object's save/load actions? They can save the entire game state to disk.

    [quote:ipk14z1x]In every layout I have a copy of the same array with the "Global" flag on.

    You should only need one array object, in the first layout, with Global enabled. Then, unless you destroy it, the same instance continues to exist the lifetime of the application. If you put other instances in other layouts, these are spawned the first time the layout is opened, and then you have multiple instances of arrays each with their own data, which might cause problems.

    Ticking global should cause it to appear in the event sheet editors for all layouts. If it doesn't, it's a bug.

  • Try Construct 3

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

    Try Now Construct 3 users don't see these ads
  • I just remembered an expression feature I coded a very, very long time ago and forgot about: you can use the ?: operator like in C++.

    For example:

    Set Text object's Text to

    (MouseX < 320) ? "Mouse is on left" : "Mouse is on right"

    There's some weird stuff with operator precedence though, so you need the brackets around the condition as shown. Hopefully there aren't any other problems with it, I haven't used that for a long time...

  • If there isn't already, an if thing would be useful when making equations.

    Such as: if(equation,true,false) or if(5+5=10, 1, 0)

    that would be great <img src="{SMILIES_PATH}/icon_biggrin.gif" alt=":D" title="Very Happy" />

    Try the 'Evaluate' system condition. It runs when the expression entered is nonzero. Note you can use following operators in expressions: AND OR = <> <= < >= >

    For example:

    Evaluate Sprite.X < 50 OR Sprite.Y > 100

  • Well, there's a lot of theoretical talk here. I put it to the test with a little .cap file that moves a sprite at 100 pixels per second for 1 second using TimeDelta, and measures the maximum and minimum distance it travels in that period.

    I struggle to get it to have an error (difference between max and min) of more than 2 pixels. It's usually at most 1.5 pixels. Maybe these fears it could be off by 10 pixels are overblown?

    Also, it performs surprisingly well at low framerates. Even if you fix the framerate at two frames per second, it still lands with nearly perfect accuracy every time.

    I guess I should implement the timedelta override for its various uses, but I really think people's worries about timedelta are still exaggerated. It is remarkably accurate from what I can see. And where pixel precision matters - low res games with generally slower moving objects - it still seems accurate to within pixels. You can also get around any inaccuracy with various tweening methods, such as using a while loop to move the player until they are exactly in the right place, eliminating any error at all. I would still prefer to code it this way for uniform speed of execution, even if it's more events.

    Don't worry - I'll still implement the timedelta override. But I don't think many people will ever need to use it!

  • More flexibility with collision conditions is a common request, so I've added two new conditions for the System object in the next build: On Collision (advanced) and Is Overlapping (advanced). This has two object parameters to pick the objects involved in the collision, and two combo boxes - Pick or Don't pick - allowing you to customise which objects are picked by the condition.

    So, in this case, you can use:

    Blue (don't pick) overlaps Orange (pick): Set Orange X to .X + 10

    Then your example works fine: since Blue is not picked, it doesn't pick the Orange in its container, only the one it's colliding with. And it all works beautifully

    You should only use the advanced collision conditions when you need the specific picking behavior though - I don't think they're quite as fast as the usual ones.

  • Text "in quotes" never changes: it means you want the text object to literally show those characters.

    Take away the quotes and it'll evaluate it as an expression, giving you the width.

  • > We're talking a difference of maybe 10 pixels here. Do you really have areas you can't jump to if you fall 10 pixels short? Or areas you can reach if you jump another 10 pixels high? Really?

    >

    This is the only thing that caught my attention. What if someone is making a retro game, low resolution and all, I think every pixel is important.

    True. I wasn't thinking of retro games, I was thinking of the kind of game I (want to) make, hi-resolution displays and detailed graphics and all. I can see this is a problem for retro games (sorry I didn't check out IWBTG sooner to arrive to this conclusion ) so it becomes a problem for this special case. Still, I'm sure the error would be smaller for decent framerates, and retro-games are usually so low resolution you'd never have any drop in framerate. And the error would be further less assuming small, pixelly games would generally have things moving at lower speeds.

    Running the display and logic asynchronously isn't the right solution for games which fiddle on the pixel level, but I can think of something similar. There could be a mode where the display is V-synced, but the runtime returns a constant value for TimeDelta. For example, if TimeDelta always returns 0.01 regardless of the real value, the built in behaviors and any custom timedelta-based movements would be absolutely exact and work the same way every time.

    Then you have a high-quality display which is exact, but it will still run at different speeds depending on the refresh rate of your monitor. I still don't like that, it makes me think of the DOS games on the old 486 computers decades ago, which ran depending on the speed of your processor. Buy a new CPU and the whole game speeds up... some computer manufacturers even put a "slow" mode on their cases to stop games running ridiculously fast

    Digressions aside, I could (somewhat reluctantly) do the same thing for fixed framerate so the display tears and it plays out the same way every time, and would only ever slow down if the processor couldn't keep up, which is unlikely for retro-style games. I guess this would also silence people who want the physics to play out the same way every time too!

    So I'm proposing a kind of 'Override TimeDelta' option. I think this would solve everything that's been brought up. And if you have a change of heart, you could then easily switch your game to using real TimeDelta values

    Sound good?

  • [quote:3s1anf2w]But I do thing the issue in variable jump height, even in the default behavior, is problematic. Its a big deal when someone can or can't jump some where

    We're talking a difference of maybe 10 pixels here. Do you really have areas you can't jump to if you fall 10 pixels short? Or areas you can reach if you jump another 10 pixels high? Really?

    [quote:3s1anf2w]1) You said precision in time based events will be improved in the next release. Does this mean I can perform time based activities on a much faster scale -- say, reducing each burst of movement from say.. 6 to 1 or 2, to try and minimize the variations?

    Sorry, I don't quite understand... are you talking about 6 milliseconds? The Every event can't trigger more than once a tick, so at 75fps you can't trigger an Every more frequently than once every 13.3ms.

    [quote:3s1anf2w]2) In what way would separating logic and display be either impossible or undesirable? It seems to me most games run in this way and would have the benefits of both tick based precision and computer speed/FPS independence for V-Syncing. I want this suggestion to stop haunting me.

    Suppose you run the logic at 50fps and the display at 100fps. So you'd run: logic, display, display, logic, display, display... you're drawing the screen twice without running any logic in between. Which means you're redrawing an identical screen again, because nothing's changed. That's a waste of processing time.

    Suppose you run the logic at 100fps and the display at 50fps. You'd run: display, logic, logic, display... or, between every drawing of the screen, you run the game logic twice. So any 'x = x + 1' become 'x = x + 2'. Except it's twice as much processing work on the logic. Which is a waste of time.

    So as far as I can see, making the logic and display rates ends up just wasting processing time. You may as well do them in sync.

  • [quote:ol04pk7t]strain the fps

    Just a quick tip - set a fixed framerate of 15 or so in application properties. It's a nice way to simulate a low framerate.

    [quote:ol04pk7t]On consistent FPSsof 60, the cubes mostly behave properly and stop in the same spot every time. Sometimes they're off by a pixel, with the Yellow being most consistent.

    There are inaccuracies in a timer based game. Ticks will not fall on the same timer values every time. For example, if you have "Timer less than 50 ms" as a condition, the first execution could have tick 5 falling at 49ms (condition evaluates to true), or tick 5 falling at 51ms (condition evaluates to false). This is the difference between running the actions either 4 times or 5 times - resulting in a maximum error of one tick. So you can calculate the maximum possible values of motion etc. in your games: over 50ms that's a maximum of timedelta summing up to 0.05, and if you move at 100 pixels per second, that's a maximum of 5 pixels covered. Any errors will result in a smaller value - so you can ensure the player cannot reach locations they could not otherwise reach. It does bias advantage to the higher framerated players - they are less likely to have their values reduced by these one-tick errors - but it is a subtle variation. You can do a few things to get around it too - for example, if the timer is greater than 50ms, set the position to the maximum possible distance. You'll have a box that moves across at a uniform speed and always lands up in the same place. A few more events, yes, but I am pretty sure this is how commercial games do it as well.

    In other words, the error is small, only ever reduces from the maximum value, and gets smaller the higher the framerate. I know you might feel differently, but I think a level of imprecision is going to be inherent and necessary in all games. If someone's crappy PC jumps 7 pixels short I don't think the game is THAT unfair, and I doubt anybody would ever notice either. And I doubt your game requires you to pole vault on to 5 pixel wide platforms!

    It may seem nice in your mind to be able to calculate the precise values that occur over a tick based game, but I doubt a 10 pixel error would ruin your game, and it'll be a smaller error for the 95% of us that can achieve a non-hilariously-bad framerate. In a practical sense, I doubt it matters. Do you think the player can reliably perform the same actions to within a 10 pixel accuracy? And the advantages of using a v-synced timer based game are huge.

    I've said everything I can to try and persuade you to avoid tick-based code - and I'm sorry to insist, but I don't want to implement features that might encourage people to go down a tick-based route, because I really think it's a poor way to design games. I want Construct users to be guided in to making well-designed games - even if it is slightly more difficult!

    And no, of course this is nothing personal and I'm not offended by anything you say. This is a technical discussion, and I'm just trying to convey the pros and cons of both ways

  • Yeah, the layout editor doesn't seem to like commas being decimal separators, which is annoying. I'll try to fix it for the next build.

    3D boxes are not yet fully hardware accelerated (they aren't nearly as fast as they could be). So for now, your tests will show up as skewed sprites being faster. This should change in a future build when 3D boxes are optimised.

    Although skewing is a good alternative, you'll have some really tricky problems getting the Z ordering to work right with depth!

  • I just checked in MMF2 and I Can V-Sync it while insuring machine independent speed

    Are you enabling 'Machine independent speed'? If so, that was designed for a fixed framerate engine so isn't doing anything useful when V-Sync is on. It is designed to skip drawing the screen if it can't hit the fixed framerate, which won't look pretty. Games look best if you can get the game to display once every V-sync. And if it's off, tough luck - your game is framerate dependent and will run at different speeds on different computers. So I disagree, your game either displays badly or is not running at a framerate independent speed.

    [quote:33omzzwg]So the way i'm looking at things, what are they doing that you can't replicate? Pretty much everything else in construct, if not already superior to MMF2, is being on the track to soon surpass it. Anyways from my experience, it's not that objects are moved in a deltatime-ish fashion when subject to slowdown, but that logic is handled separately from display. if i have a value increase by 1 every cycle and a 60 frame game is only running at 50 frames per second, I still end up with 60 at the same time.

    One of the main goals of Construct is to achieve a high quality display for the game. You need V-sync to do that, and skipping frames or running logic at a different rate to the display rate is not as good a solution as just using timedelta. If I implement any of your suggestions I really believe it will result in lower quality games. And if other game development programs choose to go down that path, well, that's not my problem

    If you want a counter to increase by 60 a second, just add 60 * TimeDelta to it every tick. It's really that easy. Instead of coding your games to run tick by tick and just hoping for the best that your game will end up running that fast on the plethora of computers out there, games should be coded to work out how much time has passed in the last tick (that's TimeDelta), then advance the gameplay logic by that amount of time. Oh, then you can also use motion blur, timescaling (slow-motion) and other timer-affecting features. So this is how Construct is designed: code your games to advance the game logic in units of time, not ticks.

    [quote:33omzzwg]Anyways the problem with decreasing by a float is when I use "=" statements in my timers.

    Timers? Can't you use 'Every X milliseconds' instead? As the name suggests, it works in units of time Or, if you decrease using a timedelta-based value, use "less than or equal". In the event, add the timer interval back to the counter (eg. 'TimerValue' less than -0.5: add 0.5 to 'TimerValue'). It will trigger reliably every half a second and this method also compensates for rounding errors meaning it is as accurate as possible.

    [quote:33omzzwg]Anyways, the string slowly decays with each element of the string getting eaten every tick, until there are no more *s. When that happens, you have ran out of time since your first input to execute the move (In this case a Dragon Punch/Shoryuken). It basically defines how fast you have to input the entire motion.

    [quote:33omzzwg]I will miss the precision of doing things tick based though

    On the contrary, the system you have just described is most imprecise! If you use ticks to measure the time you have left to perform an action, and someone's rubbish computer runs at 30fps instead of 60fps, they have twice as long to complete the action so the game is twice as easy for them. Really, that's precise? Sure, you can sacrifice the display quality of your game to make it work, but why on earth would you do that... when you could just code your game properly?

    If you need it to be exact, use a timer to determine whether the time in seconds has elapsed for them to perform the action. It's perfectly precise: either enough time has passed or it hasn't. 'TimeDelta' is accurate to within microseconds, and in the next build of Construct, the main timers are as well.

    I think you are looking at this the wrong way round: tick based games are imprecise, unfair and unreliable, and just being lazy about rendering the display is a poor way to try and half-fix the problem. Whether or not other programs do it the right way or not doesn't affect how I think Construct should tackle the problem. And I think I've done it the right way: the best possible display quality, and a simple way to code timer based games. Don't be lazy or prejudiced. Timedelta for the win.

  • Secondly, shouldn't there be a way to the game adjust automatically? I'm used to hearing good technical reasons for why things can't happen around here (so I'm expecting a 'no'), but I still have to bring it up just in case. I didn't have to do anything like this in Multimedia fusion 2, I could simply set the game to skip frames instead of slow down. I'm going to imagine that most of the FPS problems for most games are on the rendering end -- isn't it possible to still run logic for 60 frames while only updating things visually at a more sustainable frame rate? Or if not, some other solution?

    I can't think of a way to automate the timedelta adjustments. The built in behaviors ideally would do everything you wanted, and with a timedelta based engine, but I guess we're not there yet. And as faggatron said, the engine can't tell the difference between continuous and one-off movement, so it isn't really possible to add it. I don't think it is a complicated thing for users to code, even if it is frustrating to retro-fit it on to a tick based engine - I think TimeDelta is an appropriate and good solution to the problem. For example, running events at 60FPS and displaying at 75FPS means at some point you display the same frame twice without running any events, so you're not actually genuinely achieving 75FPS. It would be pointless.

    I can't think of any reason you wouldn't want to use a V-synced display for games (other than complaining about TimeDelta!) and I can't think of any legitimate uses for anything to be tick-based in Construct. It should all be based off real seconds. That's technically the best solution, which results in best quality games. If MMF2 doesn't implement it, it doesn't mean it works fine, it still suffers from all the problems of tick-based engines. I say this a lot, and I'll say it again: use V-sync, and use timedelta based engines! It's the only way to design a game that isn't going to tear the display, and isn't going to run at different speeds for different people. If you have a fixed framerate, your games will look ugly because they can't V-sync. And if your game slows down due to poor hardware, it will start crawling along reaaallly slow. Timedelta engines keep the gameplay going at the intended speed even if the system can't hit V-sync framerates.

    The whole premise of a fixed framerate is flawed because if a user's system can't achieve that framerate, nothing you've coded runs at the intended speed. You can fix your framerate at 60fps if you want, but someone's old PC might end up running it at 20fps anyway! Do you want the game to run three times slower than it should for them?

    I'm not out to shout you down here or anything - I just think there's a clear case for never using fixed framerate and always using V-sync. I might even add a warning dialog if you choose a fixed framerate. It's not suitable for games. TimeDelta is not a difficult concept and game designers should go to the trouble of learning just a little about it, in order to design games which are fairer, better quality, and more professional.

    Convinced?

  • We're aware of deficiencies in the animation system - and we will be trying to plug them ASAP!

  • I think your problems arise from the fact you try to start loops from actions. There are loops you can run in single conditions in Construct, and these are usually better, because you can put them in a subevent and they remember the picked objects from above. Also, the 'For Each Object' loop sounds like it would be useful here. I think you're aiming for something like:

    + Box is not overlapping ground

    + For Each Box

    ----+ Repeat [number] times

    ----> Set box's Y to .Y + 1

  • I'm a bit confused. I think you want the Function object, which can trigger an event and carry over the picked objects. But why don't you put the action in the actual event instead of starting a loop to call the action? Or, if you do need to repeat it, use a condition loop (like the 'Repeat N times' condition) and put it in a subevent to the main event. It will run the loop, and remember the picked objects. As for "Before updating display", I don't understand that, the display is updated at the end of the events so the events at the end of the event list are run just before updating the display