Program a door to move or animate it?

Blitz3D Forums/Blitz3D Programming/Program a door to move or animate it?

Imperium(Posted 2013) [#1]
I'm trying to think of the best approach to add in simple doors into my fps game. Should I animate the objects or just manipulate the door itself in real time? Examples would be great. Think of in Doom or Wolfenstein 3d. Doors went up an down and only side to side.





Yasha(Posted 2013) [#2]
I would say this is a matter of style really. A decision like this reflects the architecture of your program.

-- animated objects place the movement code in your media/data. The program has no control over what actually happens, only over the trigger. Users can replace or modify the movement in mods.

-- manipulating the object places the movement code in your program/engine. The program is completely aware of the concept of "a door" and has direct control over it, but the downside is that there's a limit to the number of things you can control this way and it is harder to mod and extend.

Given the nature of your game and level design (based on the other threads), it seems like doors and potentially any other moving platforms probably ought to "belong" to the engine in this setup, because of the simple design that "claims" a lot of ownership of the level design already.

The other thing is that doors are inherently more connected to the second category, because animations are normally used to visualise an effect that's already actually happening in the world (e.g. a player emitting a spray of bullets is not dependent on them bracing against the recoil), whereas here the door opening is an effect in and of itself, so it should be represented at a less ephemeral level. If I wanted to mod in more kinds of moving platform at a later date (how many kinda can there be anyway?), I would feel "cleaner" having script hooks attached to my level rather than using animation effectively as a scripting tool it wasn't designed to be.

Plus, using code lets you take more control over every aspect of what the door is doing and lets you have a proper locking and keycard or remote switch system: you'd have to have this anyway so tying it in with animation would just stretch your concerns over a wider area of implementation.

Finally, the fine control of animation seems overkill for linear movement.

(I know there are intermediate positions like the aforementioned scripts attached to a level, or config files to control animation parameters, but these are distractions from the issue of problem ownership: that's still a code/data distinction.)


Imperium(Posted 2013) [#3]
Programmed manipulation is response I anticipated. Like you already stated I need to code a locking/keycard/remote system anyway so it would likely work best if the doors function as part of the level itself. I'm not doing anything very fancy yet so this should work well enough.


RemiD(Posted 2013) [#4]
Your question is about if it is better to use MoveEntity or/and TurnEntity rather than AnimateEntity ?

I think that there is no best answer, that's your choice.

You can also create animations inside blitz3d with code if you want to add complex movements of the parts.


_PJ_(Posted 2013) [#5]
All I will say is this:

Depending on how much of your program code requires some form of frame-limiting or time - management will affect the ease of which method you choose.

ANimateEntity is somethign that takles a little more work in setting up, i.e. loading or defining the animation frames and keys - but is a lot easier to manage once done.
However, it also adds a little to VRam I believe (possibly not an issue in real terms though)

When Turn or Rotate etc. is used, however, these may need to be time-dependant.
Imagine a game running at 60fps - A door opening at 1 degree per frame is going to take 1.5 seconds to open
If the time taken is to be controlled, then it may be necessary to ensure that flags for the door state (i.e. closed, opemn, openING or closING) are used, and a record of the timing and 'speed'.


Imperium(Posted 2013) [#6]
My game runs at 60fps but the logic is limited to 30fps. I think a door would be a great candidate for createtimer().


jfk EO-11110(Posted 2013) [#7]
well that would be delta timing, pretty easy to implement. i suggest not to use animation because it will cause troubles with collision. handling doors is really one of the easier things. a swinging door can even determine the players position and swing away from him automaticly. you can use tricky atan code for that, or simply stick a pivot to each side of the door and check which one is closer to the player.

hold an array or type list in memory that stores the state of each door. check them frequently and if one door is open for 10+ secs, close it automaticly and set its state to ""can be opened again.
if a door should be opened, turn it repeatedly, until it reaches eg. 90 degrees do the same in reverse to close it. turn it every frame a few degrees, depending on the framerate. note delta timing has been explained several times, should be easy to search for.


John Blackledge(Posted 2013) [#8]
I do agree with all of the above.
But also bear in mind that an animated entity which has the animation built in by the modelling program will open, but Blitz read the collisions from the first frame (e.g. closed) so you'll never be able to walk through.
I wasted many weeks until I realised this was happening.

Manually opened doors are of course far more work, but allow greater control, e.g. a door opening sound, slamming sound.

I have type HINGED, LIFTING, SLIDING, then jump to the appropriate section of code when triggered, and also monitor the angle/height/position to stop when at the maximum.
Unfortunately my code is integral to the engine, so could not be separated to be given away, but just work away at it logically.
It's a great feeling to see your first Doom-type door open!


RemiD(Posted 2013) [#9]

But also bear in mind that an animated entity which has the animation built in by the modelling program will open, but Blitz read the collisions from the first frame (e.g. closed) so you'll never be able to walk through.


Not if you create a separate collider and set it as a child of the joint which move|rotate the door.
But i understand what you mean.


jfk EO-11110(Posted 2013) [#10]
you're right about that, but it requires some sort of joint naming rules and complicates things, eg. who will make the collider?
It's a great feeling to see your first Doom-type door open!


my words!


Yasha(Posted 2013) [#11]
an animated entity which has the animation built in by the modelling program will open, but Blitz read the collisions from the first frame (e.g. closed) so you'll never be able to walk through.


I know this is definitely true for bone-based animations because they just redraw the vertices rather than moving anything, but is it also true for segmented-mesh animation (i.e. classic 3DS style)? Segmented animation genuinely moves the whole mesh, after all, not just the control pivot.


Imperium(Posted 2013) [#12]



Replace "HAVE" with "HAVING" in above explanation.

I hope all of this makes sense. Basically if you step on the hidden red trigger the door moves up if you hit spacebar. Then the door stops moving up when it hits the green trigger. Finally it then resets after a certain amount of time. Seems simple enough right?


RemiD(Posted 2013) [#13]

Basically if you step on the hidden red trigger the door moves up if you hit spacebar. Then the door stops moving up when it hits the green trigger. Finally it then resets after a certain amount of time. Seems simple enough right?


Too simple !

What if :
The door is closing and the player or a bot collides with it ?
The door is opening an the player or a bot collides with it ?

Keep in min that with Blitz3d you can only retrieve infos about a collision between a moving collider sphere and a static collider sphere, or collider box, or collider mesh, or between a moving collider sphere and a moving collider sphere...
But there is also Mesh intersect which can be useful in this case (with a distance check before doing the mesh intersect check, to make sure the player or a bot is near enough, because meshintersect takes time. Whatever approach you choose, i suggest to use low tris colliders hidden with EntityAlpha set to 0.0)

Where are the buttons ? From your explanations you don't want buttons, you use triggers.

Where are the locks ?

Where are the keys ? or the keycards ?

Think about it.

For the movement of a door, i use these states :
IsClosed
IsOpening
IsBlockedWhileOpening
IsOpened
IsClosing
IsBlockedWhileClosing


Imperium(Posted 2013) [#14]
What if :
The door is closing and the player or a bot collides with it ?
The door is opening an the player or a bot collides with it ?

The Door1 model is tagged as a solid object so you should simply not be able to move through it because the players mass restricts what you can and cannot move into. The player can still try and move through the door while it's opening but they won't pass though until its high enough to allowl the invisible mass of the player or bot to pass through. This should work in theory.


Where are the buttons ? From your explanations you don't want buttons, you use triggers.

The buttons are on the door lol. Basically this is a Doom style door so if you are roughly in front of it you can trigger it to open.


Where are the keys ? or the keycards ?

This will be handled by inventory items or should the key actually be tied specifically to the door itself?


RemiD(Posted 2013) [#15]

This will be handled by inventory items or should the key actually be tied specifically to the door itself?


You do as you want, this is your game, i suggested these things because i had to think about the same things for my game.


Kryzon(Posted 2013) [#16]
Hi. Using colliders the way you're doing has you not taking the player's orientation in consideration. The player would be able to open a door by stepping on its collider, facing the opposite way and hitting the action button.
You need to check if the player is 'looking' at the door, and only allow him to open it if this is true.

I think using colliders at all for this may be a bit over-engineering.

You can try a different approach:
At any moment the player uses the action button, you resort to CameraPick( camera, screenCenterX, screenCenterY ), so you can see if-
A) The player is facing the door (the picked entity is the door mesh, as some part of it is right on the middle of the screen).
B) The player is close enough to the door (PickedTime from the CameraPick multiplied by the camera-range = distance in 3D units).
Then if the above is true you can change the door's "moving" state flag to True. So the player can keep pressing the action button and even if the conditions above are true, this flag will prevent the door from repeatedly opening\closing.

Now for actually animating the door; You're interpolating between two transformation "stages". That is, in one stage the door is with a specific position\rotation\scale combo, and in the other stage the door has another position\rotation\scale combo.
What you can do is define these two stages. For this you can either manually store somewhere these transformation values, or you can use a pair of pivots as facilitators to hold these values (so each pivot is positioned\rotated\scaled to represent the final state of how you want the door to be on each stage).
With stages like these, you can program code that based on a normalized fractional value (that is, a variable going from 0.0 ~ 1.0), transforms the door by interpolating between these two stages. Each door has its own fractional value, it's just a Float field in the door Type.

You also need another Float field in the door Type which is the speed by which this fractional value changes (you can do some interesting Ease-In, Ease-Out effects by changing this speed instead of keeping it constant).
Every frame the door's "moving" state is True, you add the speed to the interpolation value, and check if this value has reached one of the extremes.

You can make some definitions based on the fractional value used to interpolate between the stages. If the value is '0', you know the door is closed. If it's '1', you know the door is open.
Once the fractional value reaches one of these extreme values, you can switch the "moving" state flag to False so the player can use the door again, and you can also flip the sign of the speed value that changes the fractional value (this means the next time the door's "moving" state is True, it changes to the other stage).
You can also automate it so that when the "moving" state flag is False (meaning, the door is stationary as it has reached one of the stages), and its fractional value is 1.0 (it's the open stage, the door is open), it times it and switches the "moving" flag back to True so the door changes to the other stage (that is, it closes automatically after some time).


RemiD(Posted 2013) [#17]
If your doors will only be at front, at back, at left, at right, you could also use a XZcoordinates calculation to know if a character is on a trigger, and deltayaw to know if he is looking towards the door or not.


Yasha(Posted 2013) [#18]
Colliders seem like overkill for this (they're intended to stop objects, not work as tripwires and can be buggy in that respect if objects aren't moving exactly as expected) - I'd suggest replacing them with a check against an oriented bounding box.

There's some existing code for that here: Lib to create an OBB and test if a point or entity is inside its space