Code archives/3D Graphics - Mesh/Doors 101 - Simple multiple door system

This code has been declared by its author to be Public Domain code.

Download source code

Doors 101 - Simple multiple door system by D4NM4N2007
Very simple "Multi-Door" system for beginners with speedup and slam.

It works by using a simple 4 state 'latch' with a single trigger.

Helpful for learning the following techniques:
Functions, types and simple triggers, latches.

It can be modified easily to incorporate SFX(see comments) and you can change the behavior to slide etc.

Note: if using render tweening (if you dont know what this is then you probably aren't) you will need to adjust the speed appropriately.

CODE:
Graphics3D 640,480
SetBuffer BackBuffer()

light=CreateLight(2)
MoveEntity light,-5,5,-5


;make a camera 
cam=CreateCamera()
MoveEntity cam,4,2,-5


;create cutom type add what you like to the fields like "key numbers" etc
Type doormesh
  Field door,activate,doorstate,speed#
End Type

;Create 2 doors, ideally this needs to be 'functionized' as it would be less messy and 
could eliminate the need for d1, d2 etc.
;for example: function CreateDoor.doormesh(px,py,pz,rx,ry,rz,sz,sy,sz)

;create first door object
d1.doormesh= New doormesh
d1\activate=0
d1\doorstate=0
d1\door=CreateCube()
PositionMesh d1\door,1,0,0
ScaleEntity d1\door,1,2,.1
EntityColor d1\door,255,0,0

;create a second door object
d2.doormesh= New doormesh
d2\activate=0
d2\doorstate=0
d2\door=CopyEntity (d1\door)
MoveEntity d2\door,-2,0,0
EntityColor d1\door,0,255,0


;point camera at door just so we can see whats going on
PointEntity cam,d1\door



;main loop
Repeat

	If KeyHit(2) D1\ACTIVATE=1
	If KeyHit(3) D2\ACTIVATE=1

	
	;do world updates
	UpdateAllDoors()

        ;Render 3d to backbuffer
	RenderWorld
	
	;display instructions on bbuffer
	Text 0,0,"Press '1' or '2' To open/close doors"

        ;flip the visible screen
	Flip


Until KeyHit(1)




;------------------------End of main code--------------------------------------------




Function UpdateAllDoors()  ;gets called every loop
For d.doormesh=Each doormesh
   Select d\doorstate
      Case 0 ;if standing shut
        If d\activate         ;this is your initial trigger
           d\activate=0       ;reset trigger
           d\doorstate=2        ;door is shut so set open trigger to beginon Next loop
          ;playsound (CREAK)
       EndIf

     Case 1  ; if standing open
       If d\activate
          d\activate=0
          d\doorstate=3
          ;playsound (CREAK)
       EndIf

     Case 2  ;if opening door
      If EntityYaw(d\door)<90 d\speed=d\speed+0.02 Else d\doorstate=1
	  If EntityYaw(d\door)>90 d\speed=0.00: RotateEntity d\door,0,90,0
	

     Case 3 ;if closing door
      If EntityYaw(d\door)>0 d\speed=d\speed-0.02 Else d\doorstate=0
	  If EntityYaw(d\door)<0 
	     d\speed=0.00: 
	     RotateEntity d\door,0,0,0:
	     ;playsound (SLAM)
	  endif

   End Select

   TurnEntity d\door,0,d\speed,0
	
Next
End Function

Comments

Blitzplotter2007
Cool...


D4NM4N2007
Thx :)

-----------------Update------------------------
You can modify it to use camerapick to open them with a small mod:
Where pickedmesh is the picked entity handle:

MOUSECLICK CODE:
;NOTE! for this to work you need to set:
;entitypickmode d\door,2
;when creating the door!!!

;replace the lines:
;	If KeyHit(2) D1\ACTIVATE=1
;	If KeyHit(3) D2\ACTIVATE=1
;with the following:
pickedmesh=camerapick(cam,mousex(),mousey())
Updatedoors(pickedmesh)


;then add this to door func to functions area (or for the more advanced, incorporate it into upddatealldoors!):
Function updatedoors(pickedmesh)
For d.doormesh=Each doormesh
   if pickedmesh=d\door ;was door clicked on?
       if entitydistance (hero,d\door) < 50 ;so you gotta be close
           ;you could always but another condition in here for if player has d\key (for example) ;)
           d\activate=1
           exit
       endif 
   endif 
next
end function

job done!


nrasool2008
Hey Dan, this is for the latter mod, the mouseclick mod, there is a mistake, eg camerapick should include the camera :-)

However I can't get the camerapick to work, here is your code in full, so you can copy and paste it:

Graphics3D 640,480
SetBuffer BackBuffer()

light=CreateLight(2)
MoveEntity light,-5,5,-5


;make a camera 
cam=CreateCamera()
MoveEntity cam,4,2,-5


;create cutom type add what you like to the fields like "key numbers" etc
Type doormesh
  Field door,activate,doorstate,speed#
End Type

;Create 2 doors, ideally this needs to be 'functionized' as it would be less messy and 
;could eliminate the need For d1, d2 etc.
;for example: function CreateDoor.doormesh(px,py,pz,rx,ry,rz,sz,sy,sz)

;create first door object
d1.doormesh= New doormesh
d1\activate=0
d1\doorstate=0
d1\door=CreateCube()
PositionMesh d1\door,1,0,0
ScaleEntity d1\door,1,2,.1
EntityColor d1\door,255,0,0
EntityPickMode d1\door,2


;create a second door object
d2.doormesh= New doormesh
d2\activate=0
d2\doorstate=0
d2\door=CopyEntity (d1\door)
MoveEntity d2\door,-2,0,0
EntityColor d2\door,0,255,0
EntityPickMode d2\door,2



;point camera at door just so we can see whats going on
PointEntity cam,d1\door



;main loop
Repeat

	pickedmesh=CameraPick(cam,MouseX(),MouseY())
	;do world updates
	UpdateAllDoors()

        ;Render 3d to backbuffer
	RenderWorld
	
        ;flip the visible screen
	Flip


Until KeyHit(1)




;------------------------End of main code--------------------------------------------




Function UpdateAllDoors()  ;gets called every loop
For d.doormesh=Each doormesh


		If pickedmesh=d\door ;was door clicked on?
    	;   If EntityDistance (hero,d\door) < 50 ;so you gotta be close
        	   ;you could always but another condition in here for if player has d\key (for example) ;)
           	d\activate=1
           Exit
     ;  EndIf 
   EndIf 


   Select d\doorstate
      Case 0 ;if standing shut
        If d\activate         ;this is your initial trigger
           d\activate=0       ;reset trigger
           d\doorstate=2        ;door is shut so set open trigger to beginon Next loop
          ;playsound (CREAK)
       EndIf

     Case 1  ; if standing open
       If d\activate
          d\activate=0
          d\doorstate=3
          ;playsound (CREAK)
       EndIf

     Case 2  ;if opening door
      If EntityYaw(d\door)<90 d\speed=d\speed+0.02 Else d\doorstate=1
	  If EntityYaw(d\door)>90 d\speed=0.00: RotateEntity d\door,0,90,0
	

     Case 3 ;if closing door
      If EntityYaw(d\door)>0 d\speed=d\speed-0.02 Else d\doorstate=0
	  If EntityYaw(d\door)<0 
	     d\speed=0.00: 
	     RotateEntity d\door,0,0,0:
	     ;playsound (SLAM)
	  EndIf

   End Select

   TurnEntity d\door,0,d\speed,0
	
Next
End Function



D4NM4N2008
ok thanks nadeem ill look into it :)

at first glance without trying it i think you missed out the parameter:

Function UpdateAllDoors(pickedmesh)

Argh i wish b3D had stricts!

I wrote the update above out of my head and forgot to test it sorry :(


nrasool2008
Ahh nice one Dan, yes you are right, the functions needs arguments, however now only one door opens if you using mousehit

Here is the updated code:

Graphics3D 640,480
SetBuffer BackBuffer()

light=CreateLight(2)
MoveEntity light,-5,5,-5


;make a camera 
cam=CreateCamera()
MoveEntity cam,4,2,-5


;create cutom type add what you like to the fields like "key numbers" etc
Type doormesh
  Field door,activate,doorstate,speed#
End Type

;Create 2 doors, ideally this needs to be 'functionized' as it would be less messy and 
;could eliminate the need For d1, d2 etc.
;for example: function CreateDoor.doormesh(px,py,pz,rx,ry,rz,sz,sy,sz)

;create first door object
d1.doormesh= New doormesh
d1\activate=0
d1\doorstate=0
d1\door=CreateCube()
PositionMesh d1\door,1,0,0
ScaleEntity d1\door,1,2,.1
EntityColor d1\door,255,0,0
EntityPickMode d1\door,2


;create a second door object
d2.doormesh= New doormesh
d2\activate=0
d2\doorstate=0
d2\door=CopyEntity (d1\door)
MoveEntity d2\door,-2,0,0
EntityColor d2\door,0,255,0
EntityPickMode d2\door,2



;point camera at door just so we can see whats going on
PointEntity cam,d1\door



;main loop
Repeat

	pickedmesh=CameraPick(cam,MouseX(),MouseY())
	;do world updates
	UpdateAllDoors(pickedmesh)

        ;Render 3d to backbuffer
	RenderWorld
	
        ;flip the visible screen
	Flip


Until KeyHit(1)




;------------------------End of main code--------------------------------------------




Function UpdateAllDoors(pickedmesh)  ;gets called every loop

For d.doormesh=Each doormesh

If MouseHit(1)
		If pickedmesh=d\door ;was door clicked on?
		
    	;   If EntityDistance (hero,d\door) < 50 ;so you gotta be close
        	   ;you could always but another condition in here for if player has d\key (for example) ;)
           	d\activate=1
           Exit
     ;  EndIf 
	EndIf
EndIf
	


   Select d\doorstate
      Case 0 ;if standing shut
        If d\activate         ;this is your initial trigger
           d\activate=0       ;reset trigger
           d\doorstate=2        ;door is shut so set open trigger to beginon Next loop
          ;playsound (CREAK)
       EndIf

     Case 1  ; if standing open
       If d\activate
          d\activate=0
          d\doorstate=3
          ;playsound (CREAK)
       EndIf

     Case 2  ;if opening door
      If EntityYaw(d\door)<90 d\speed=d\speed+0.02 Else d\doorstate=1
	  If EntityYaw(d\door)>90 d\speed=0.00: RotateEntity d\door,0,90,0
	

     Case 3 ;if closing door
      If EntityYaw(d\door)>0 d\speed=d\speed-0.02 Else d\doorstate=0
	  If EntityYaw(d\door)<0 
	     d\speed=0.00: 
	     RotateEntity d\door,0,0,0:
	     ;playsound (SLAM)
	  EndIf

   End Select

   TurnEntity d\door,0,d\speed,0
	
Next

End Function


If you are using IDEal IDE, that has strict built in :-)


Rodjoe2008
The code of nrasool doesn't work ,only one door(red) open when I click


D4NM4N2009
I see why!!!!

The keyhit is inside the for next loop. Its not actually good practice to use more than one mouse or key hit statement unless doing something special, as the event is reset each time called.
It is always better to call it once and transfer it to a global.
-This is not true of the 'down' statements though, they can be used as many times as you like.

Here is the working one:

Graphics3D 640,480
SetBuffer BackBuffer()

light=CreateLight(2)
MoveEntity light,-5,5,-5


;make a camera 
cam=CreateCamera()
MoveEntity cam,4,2,-5


;create cutom type add what you like to the fields like "key numbers" etc
Type doormesh
  Field door,activate,doorstate,speed#
End Type

;Create 2 doors, ideally this needs to be 'functionized' as it would be less messy and 
;could eliminate the need For d1, d2 etc.
;for example: function CreateDoor.doormesh(px,py,pz,rx,ry,rz,sz,sy,sz)

;create first door object
d1.doormesh= New doormesh
d1\activate=0
d1\doorstate=0
d1\door=CreateCube()
PositionMesh d1\door,1,0,0
ScaleEntity d1\door,1,2,.1
EntityColor d1\door,255,0,0
EntityPickMode d1\door,2


;create a second door object
d2.doormesh= New doormesh
d2\activate=0
d2\doorstate=0
d2\door=CopyEntity (d1\door)
MoveEntity d2\door,-2.5,0,0
EntityColor d2\door,0,255,0
EntityPickMode d2\door,2



;point camera at door just so we can see whats going on
PointEntity cam,d1\door



;main loop
Repeat

	If MouseHit(1) pickedmesh=CameraPick(cam,MouseX(),MouseY())
	;do world updates
	UpdateAllDoors(pickedmesh)

        ;Render 3d to backbuffer
	RenderWorld
	
        ;flip the visible screen
	Flip


Until KeyHit(1)




;------------------------End of main code--------------------------------------------




Function UpdateAllDoors(pickedmesh)  ;gets called every loop

;bomb out if nothing to do
If not pickedmesh return

For d.doormesh=Each doormesh
        If pickedmesh=d\door ;was door clicked on?	
    	  ;If EntityDistance (hero,d\door) < 50 ;so you gotta be close
        	  ;you could always but another condition in here for if player has d\key (for example) ;)
           	d\activate=1
            Exit
           ;EndIf 
        EndIf
	


   Select d\doorstate
      Case 0 ;if standing shut
        If d\activate         ;this is your initial trigger
           d\activate=0       ;reset trigger
           d\doorstate=2        ;door is shut so set open trigger to beginon Next loop
          ;playsound (CREAK)
       EndIf

     Case 1  ; if standing open
       If d\activate
          d\activate=0
          d\doorstate=3
          ;playsound (CREAK)
       EndIf

     Case 2  ;if opening door
      If EntityYaw(d\door)<90 d\speed=d\speed+0.02 Else d\doorstate=1
	 If EntityYaw(d\door)>90 d\speed=0.00: RotateEntity d\door,0,90,0
	

     Case 3 ;if closing door
      If EntityYaw(d\door)>0 d\speed=d\speed-0.02 Else d\doorstate=0
	 If EntityYaw(d\door)<0 
	    d\speed=0.00: 
	    RotateEntity d\door,0,0,0:
	    ;playsound (SLAM)
	 EndIf

   End Select

   TurnEntity d\door,0,d\speed,0
	
Next

End Function



NewHuman6662016
you still got no hero,
For a nice mouse-over effect use (pickedmesh) argument for the hero from the first two code posts


Code Archives Forum