Another Basic Problem Door Open/Shut
Blitz3D Forums/Blitz3D Programming/Another Basic Problem Door Open/Shut
| ||
Allright, I may seem stupid, but I have been learning blitz for all of two days, and I am still having some difficulties. I am trying to get a door to open and close using the same key (e). My code is: If KeyHit(18) Then If EntityDistance#(p\entity,motellcd) < 20 If EntityYaw# (motellcd) = 0 Then .Dooro If doory<91 Then doory=doory+1 RotateEntity motellcd,0,doory,0 Goto dooro EndIf EndIf If EntityYaw# (motellcd) > 89 Then .Doorc If doory2>0 Then doory2=doory2-1 RotateEntity motellcd,0,doory2,0 Goto doorc EndIf EndIf EndIf EndIf Of course what happens is the door will open but not close. Is there any way of fixing this... I have gotten the code to work using two seperate keys, but not using the same key. |
| ||
Some advice: 1) NEVER USE GOTO - NEVER ! 2) use a status to handle the door. For example, when your door is closed, its status is D_CLOSED. When the door is in this status, and the player is near the door and press a key, then change the status to D_OPENING. While in the status D_OPENING, open the door and continue to do so until the door is completely opened. When this is achieved, then change again the door status with D_OPENED; and so on. Example: ;const values for door status const D_OPENING = 1 const D_CLOSING = 2 const D_OPENED = 3 const D_CLOSED = 4 ;main loop while not keydown(1) select door_status case D_OPENING ;continue to open opening_door() case D_CLOSING ;continue to close closing_door() case D_CLOSED ;attempt to open the door open_door() case D_OPENED ;atempt to close the door close_door() end select ;end of main loop wend end ;=============================== function opening_door() ;=============================== If doory<91 Then doory=doory+1 RotateEntity motellcd,0,doory,0 else door_status = D_OPENED endif end function ;=============================== function closing_door() ;=============================== If doory2>0 Then doory2=doory2-1 RotateEntity motellcd,0,doory2,0 else door_status = D_CLOSED endif end function ;=============================== function open_door() ;=============================== If KeyHit(18) Then If EntityDistance#(p\entity,motellcd) < 20 If EntityYaw# (motellcd) = 0 Then door_status = D_OPENING endif endif endif end function ;=============================== function close_door() ;=============================== If KeyHit(18) Then If EntityDistance#(p\entity,motellcd) < 20 then If EntityYaw# (motellcd) = 0 Then door_status = D_CLOSING endif endif endif end function Another advice is to use a type structure for your door, so to handle multiple doors having their proper flags: type t_door field status ;the door status field speed# ;the speed used to move the door field orientation ;x,y,z where the door should move to field mesh ;the door model field x#,y#,z# ;the position of the door in 3D world end type Global door.t_door . . for door.t_door = each t_door select door\status case D_OPENING opening_door(door) . . . next function opening_door(door.t_door) . . end function Hope this has sense for you, Sergio. |
| ||
1) NEVER USE GOTO - NEVER ! Don't subscribe to the dogma, but use goto as a last resort. It can sometimes make code clearer than trying to wrap status flags around everything. |
| ||
Yeah there are some situations where a a goto is the best choice, or even the fastest, calling a function every game loop is not always as efficent as using a goto :) |
| ||
This isn't exactly what you wanted, but it could be adapted pretty easily. http://www.binary-people.com/downloads/lbexamplelevel.zip It's a 'tech-demo' example I put together with LightBulb. The source is in there and it's pretty well commented. The doors are 'automatic' but could just as easily be activated by a keypress with a bit of creative coding. Hope that's of some help. :) |
| ||
Well I got it eventually. Semars post was really helpful, although it took me a couple of hours to figure out doory had to be global :O. Oh well. Thanks for the help. |
| ||
Okay.. Just a couple of more questions on this matter. I was attempting to use the type, because I want many doors in my level. Here is my code: Not in the main loop: Type doorprop Field status ; the door status Field speed# ; the speed used to move the door Field orientation ;x,y,z where the door should move to Field mesh ;the door model End Type In the UpdateGame function (called in the main loop): For door.doorprop = Each doorprop Select door\status Case D_OPENING ;continue To open opening_door(door) Case D_CLOSING ;continue To close closing_door(door) Case D_CLOSED ;attempt to open the door open_door(door) Case D_OPENED ;attempt to close the door close_door(door) End Select Next Below the above function: Function opening_door(door.doorprop) If EntityYaw# (motellcd)<90 doory=1 TurnEntity motellcd,0,doory,0 Else door\status = D_OPENED EndIf End Function Function closing_door(door.doorprop) If EntityYaw# (motellcd)>0 doory=-1 TurnEntity motellcd,0,doory,0 Else door\status = D_CLOSED EndIf End Function Function open_door(door.doorprop) If KeyHit(18) If EntityDistance(dummy,motellcd)<10 door\status = D_OPENING EndIf EndIf End Function Function close_door(door.doorprop) If KeyHit(18) Then If EntityDistance(dummy,motellcd)<10 door\status = D_CLOSING EndIf EndIf End Function And finally in the setup: motel=LoadAnimMesh( "motel\motellcdsep.3ds") PositionEntity motel, 0,0,100 ScaleEntity motel, .15,.15,.15 EntityType motel, TYPE_SCENERY, 1 motellcd=FindChild( motel,"LCDDoor" ) door.doorprop = New doorprop door\status=D_CLOSED Now there are a couple of things. 1. With this code, nothing happens, I can go up to the door, hit E and nothing happens when it should. 2. Is there a way to have it so that it searches all of the entities within a model that have door or doors with consecutive numbers have the door open action applied to them? Thank you in advance :). |
| ||
Hum... 1) Motellcd should be declared as Global 2) Did you have also declared the Consts for D_CLOSED, and such ? 3) put a stop in the related function that should be called, turn the debug on, and watch if the program stops as expected. Try with simple mesh - ex create a cube and scale it appropriately to make a door, and see if it opens and closes. When you have this working, then change the cube with the model you need, and check if it works too. Is there a way to have it so that it searches all of the entities within a model that have door or doors with consecutive numbers have the door open action applied to them? Well this is up to programming; I did not used yet the FindChild command, I guess you have to provide the child name$ for each door, so at every call you should create a new type, and assign an ID to it (just add an ID field in the door type, and assign a progressive value as you create new type elements). Another method - which happens to be what I use - is to make a level without doors, then use Droplet (by Dr Av - look for it @ www.blitzcoder.com ) to place waypoints in your .B3D level. Then, use the waypoints coordinates in the program, to position your doors - which could be, again, simple scaled cube, textured with whatever you like). Droplet comes with an useful example source code, so you can see how it works and use the functions to extract the values for each waypoints. So each time you create a door (a cube), you create a type, and just assign the value you like to ID field: type t_door field x#,y#,z# ;coordinates field the_door ;the entity field ID ;ID number end type Global door.t_door door.t_door = new t_door door\x = ... door\y = ... door\z = ... door\the_door = createcube() scaleentity door\the_door,scalex,scaley,scalez ;the scale vaoues depend on the door orientation among the x,y,z axes total_doors = total_doors + 1 ;a local variable that you increase at each door creation door\id = total_door Hope this helps, Sergio. |
| ||
Well your debug help really helped me... I got it working with the types and all... Just one other question. How would I go about using the Type command to create many doors? |
| ||
Just one other question. How would I go about using the Type command to create many doors? Do you mean the command to create a new type element ? type t_door ;type declaration field ... ;fields... . . end type Global door.t_door ;global pointer ;let's create 10 'doors' for n = 1 to 10 ;loop from 1 to 10 door.t_door = New t_door ;Note the New statement. This creates a new door element next Being more specific, what I do is to place 'door' objects using Droplet (see above post), and then in the program, at the beginning of a level, I read each 'door' info from the .drp file generated by droplet, which contains the info related to each object placed from within droplet. Then, simply check wich type of object should be created, and if it is a 'door', then... creates a door !! Advice: Download droplet, is free and very useful. Have a play with it, position some object in your .B3D level, then use the object viewer - an handy function included in Droplet - and see how it works; I bet you can master it in a couple of minutes.. ;-) Hope this has sense for you, Sergio. |
| ||
Hmm... I still don't understand. I tried to create a new door by using the code motellcd=FindChild( motel,"LCDoor" ) door.doorprop = New doorprop door\status=D_CLOSED door\mesh=motellcd For one door, and door1=FindChild( food,"door9" ) door.doorprop = New doorprop door\status=D_CLOSED door\mesh=door1 For the other. Now with this code I can open the first door, but not the second, why? Also if I rem the first set of code (for the motellcd) I can open the second door (as such it isn't the code)... What have I done wrong? I am not too fond of using an external editor for placing my doors. They have all been placed and their origins have been worked out in my 3D program, so I should be able to seperate them... |
| ||
Do you loop through all the type collection, when you close/open a door ? You have to control all the doors, not only one. If you use always the same door pointer, then you will only act on the same door. I mean, in the section where the call to the open_door(door.t_door) function is, you should have a loop like: For door.t_door = Each t_door open_door(door) . . next In this way you loop through all the doors. If it works only with one door, is probably because the door pointer points always to the same type element... More, you don't need to create a temporary mesh like you do with motellcd (and door1): motellcd=FindChild( motel,"LCDoor" ) door.doorprop = New doorprop door\status=D_CLOSED door\mesh=motellcd You can write instead: door.doorprop = New doorprop ;I would use t_door as type name, is more readable and mnemonic IMO. door\mesh = FindChild( motel,"LCDoor" ) door\status = D_CLOSED Now open all doors !!! Then listen some song from 'The Doors' - LOL ! Sergio. |
| ||
Hmm I did loop the Type collection like so For door.doorprop = Each doorprop Select door\status Case D_OPENING ;continue To open opening_door(door) Case D_CLOSING ;continue To close closing_door(door) Case D_CLOSED ;attempt to open the door open_door(door) Case D_OPENED ;attempt to close the door close_door(door) End Select Next But that was the only type loop, does there have to be others? |
| ||
But that was the only type loop, does there have to be others? No. It should work. Check if 'door' points at different meshes each time - just inspect the value of door\mesh, you should get two values at each loop: for..each . Debuglog.print door\mesh . next Do you place the doors at corrected positions ? Did you try with two simple cubes, one red and one green, and see if both can be opened/closed ? Also, you seem to use always the same model when testing the distance with the player: If EntityYaw# (motellcd)>0 and If EntityDistance(dummy,motellcd)<10 You should use something like: If EntityYaw# (door\mesh)>0 and If EntityDistance(dummy,door\mesh)<10 Check this also for moving and rotation commands, and verify that you use the generic door\mesh, instead of the 'fixed' ones (motellcd for example). Sergio. |
| ||
Hmm... This is very strange. When I write it to the Debug log thing I get two numbers written, and both doors work, but when I turn it off the doors don't work. Whats the problem? |
| ||
BUMP! Any fixes? |