Opening door

Blitz3D Forums/Blitz3D Programming/Opening door

Grovesy(Posted 2006) [#1]
Not really a programming question just some general advice/recommendation wanted.

How do you guys make your doors open? (and don't say with the door knob! lol) I guess there are two ways:

1. Create the whole door in your 3d package and animate it in the 3d package also, and then just call the animation function in your game.

2. Create the door frame and door seperately with no animation. Then animate the static models actually in your Blitz3D code (ie using MoveEntity/ RotateEntity or something fancier if you wish)

So my question is what method do people use, or is there another way people do this?

Cheers


Matty(Posted 2006) [#2]
That depends on how you want it to open, I mean 'when' you want it to open. Do you want the door to slide aside when the player or other unit moves near it (in which case I'd build the animation into the door model and simply turn collisions off for the door when it is open)? Or do you want the player to have to walk up to it and collide with it - in which case a single blitz3d entity used combined with rotate/moveentity commands may be used.

If you do it in your 3d package you can have a lot of nice effects when the door opens - particularly if it is a fancy sci fi door with pipes and twisty bits that rotate and disconnect which would be quite difficult I would imagine to perform with simply move/rotate entity commands.

If you are going for the traditional rpg door as seen in Morrowind then I guess rotateentity/moveentity should be pretty easy to implement. It also makes collisions easier as blitz doesn't handle sphere->poly collisions very well against animated entities (I think it only tests against the position of the mesh based on the first frame of animation meaning.)


Shambler(Posted 2006) [#3]
I use 2.

Each door has a start and end position, plus a start and end rotation...I set these attributes in Gile[s].

This allows doors to open by rotating (like normal doors) or moving (like sliding doors) or a combination of both.

A variable that goes between 0.0 and 1.0 is used to determine where the door currently is in regard to the start/end rotation/position and is also used to trigger opening/closing sounds.

The door also has 2 speed parameters so all doors can open/close at different speeds...useful for something like a portcullis door to open it slowly but drop it quickly.

Be sure that when you model your door you pay attention to the origin point 0,0,0 since this is what the door will rotate around.


Sir Gak(Posted 2006) [#4]
The following is how I do doors that hinge on one side, and open by swinging, and also for portcullis that go up and down. These doors/portcullis are being created inside B3D with no external meshes. The textures (ie t_door, t_port, etc) I use are just freebie royalty-free things, which you can get off the web at any number of sites. The variable EastWest is for whether the door should align itself in an East-West direction, or a North-South direction Yeah, it's a bit more code, but it works. Then, when someone "activates" the door/portcullis, I just run the animation that captured the movement (ie rotate or up-down). Finally, here's some code that I use to "activate" the door/portcullis (I click on the object in question). If it's within a certain range, ie within arm's reach, then the animation is run. Notice that I just use a negative value to run the animation "backwards" to close the doors. There may be a few extra code snippets in the folowing, so if you have any questions, post me.

Type entity    ;a type to tell us what entity category we're looking at 
	Field parent
	Field entity
	Field child
	Field kind    ;wall, portcullis, door, fountian
	Field state   ;closed=1, opened=2
;	Field del     ;True/False, i.e. flag to delete this object
	Field seq
End Type

.createdoor
	e.entity = New entity  	 ;create a new instance of the entity type variable
	e\parent=CreatePivot()
	e\entity=CreateCube(e\parent)
	NameEntity e\entity,"Door"
	EntityPickMode e\entity,2
	PositionMesh e\entity,1,1,1 		;move "door" so that it hinges on left side
	ScaleMesh e\entity,1.6,1.8,.125 	;reshape cube to look like door (flatten, etc)
	EntityTexture e\entity,t_door 		;paint the door to look like one
	EntityType e\entity,2
	If EastWest=False Then RotateEntity e\entity,0,90,0
	epitch= EntityPitch(e\entity)
	eyaw  = EntityYaw(e\entity)
	eroll = EntityRoll(e\entity)
	For frame=1 To 45
		TurnEntity e\entity,0,2.0,0 ;turn door on its hinges
		SetAnimKey e\entity,frame
	Next	
	e\seq   = AddAnimSeq(e\entity,frame-1) ;minus 1 because For-Next loops end 1 too many
	e\kind  = door
	e\state = closed
	RotateEntity e\entity,epitch,eyaw,eroll ;undo the positioning done by the animation
Return

.createdoorframe
	e.entity = New entity  	 			;create a new instance of the entity type variable
	e\entity=CreateCube()	 			;store entity handle in the Type variable
	NameEntity e\entity,"Door Frame"
	ScaleMesh e\entity,0.2,2.0,0.4 		;reshape it into a doorpost column
	PositionMesh e\entity,0,.5,0 
	EntityPickMode e\entity,2
	
	topframe = CreateCube(e\entity)
	ScaleMesh topframe,1.6,0.2,0.4
	PositionMesh topframe,1.8,2.3,0
	
	doorframe2 = CopyMesh(e\entity,e\entity) ;copy the doorpost column
	PositionMesh doorframe2,3.6,0,0 

	AddMesh topframe,e\entity
	AddMesh doorframe2,e\entity
	EntityTexture e\entity,t_stone		;paint doorframe with concrete pic
	EntityType e\entity,2
	FreeEntity topframe
	FreeEntity doorframe2
Return

.createportcullis  ;for now, just re-using code for vertical door opening
	Const slatspace#=.291
	e.entity = New entity  	 ;create a new instance of the entity type variable
	e\parent=CreatePivot()
	e\entity=CreateCube(e\parent)
	NameEntity e\entity,"Portcullis"
	ScaleMesh e\entity,.16,1.8,.05 	;reshape cube to look like port slat (flatten, etc)
	PositionMesh e\entity,.4,1.8,.1 		;move "portcullis" 
	EntityPickMode e\entity,2
;	EntityTexture e\entity,t_port 		;paint the port slat to look like one

	bar1=CreateCube(e\entity)
	ScaleMesh bar1,1.6,.16,.05
	PositionMesh bar1,1.6,3.2,0
;	EntityTexture bar1,t_port 		;paint the port slat to look like one

	bar2=CreateCube(e\entity)
	ScaleMesh bar2,1.6,.16,.05
	PositionMesh bar2,1.6,3.2-slatspace*2,0
;	EntityTexture bar2,t_port 		;paint the port slat to look like one

	bar3=CreateCube(e\entity)
	ScaleMesh bar3,1.6,.16,.05
	PositionMesh bar3,1.6,3.2-slatspace*4,0
;	EntityTexture bar3,t_port 		;paint the port slat to look like one

	bar4=CreateCube(e\entity)
	ScaleMesh bar4,1.6,.16,.05
	PositionMesh bar4,1.6,3.2-slatspace*6,0
;	EntityTexture bar4,t_port 		;paint the port slat to look like one

	bar5=CreateCube(e\entity)
	ScaleMesh bar5,1.6,.16,.05
	PositionMesh bar5,1.6,3.2-slatspace*8,0
;	EntityTexture bar5,t_port 		;paint the port slat to look like one

	bar6=CreateCube(e\entity)
	ScaleMesh bar6,1.6,.16,.05
	PositionMesh bar6,1.6,3.2-slatspace*10,0
;	EntityTexture bar6,t_port 		;paint the port slat to look like one

	slat1=CreateCube(e\entity)
	ScaleMesh slat1,.16,1.8,.05 	;reshape cube to look like port slat (flatten, etc)
	PositionMesh slat1,.4+slatspace*2,1.8,.1 		;move "portcullis" 
;	EntityTexture slat1,t_port 		;paint the port slat to look like one

	slat2=CreateCube(e\entity)
	ScaleMesh slat2,.16,1.8,.05 	;reshape cube to look like port slat (flatten, etc)
	PositionMesh slat2,.4+slatspace*4,1.8,.1 		;move "portcullis" 
;	EntityTexture slat2,t_port 		;paint the port slat to look like one

	slat3=CreateCube(e\entity)
	ScaleMesh slat3,.16,1.8,.05 	;reshape cube to look like port slat (flatten, etc)
	PositionMesh slat3,.4+slatspace*6,1.8,.1 		;move "portcullis" 
;	EntityTexture slat3,t_port 		;paint the port slat to look like one

	slat4=CreateCube(e\entity)
	ScaleMesh slat4,.16,1.8,.05 	;reshape cube to look like port slat (flatten, etc)
	PositionMesh slat4,.4+slatspace*8,1.8,.1 		;move "portcullis" 
;	EntityTexture slat4,t_port 		;paint the port slat to look like one

	AddMesh bar1,e\entity : FreeEntity bar1
	AddMesh bar2,e\entity : FreeEntity bar2
	AddMesh bar3,e\entity : FreeEntity bar3
	AddMesh bar4,e\entity : FreeEntity bar4
	AddMesh bar5,e\entity : FreeEntity bar5
	AddMesh bar6,e\entity : FreeEntity bar6
	AddMesh slat1,e\entity: FreeEntity slat1	
	AddMesh slat2,e\entity:	FreeEntity slat2
	AddMesh slat3,e\entity:	FreeEntity slat3
	AddMesh slat4,e\entity:	FreeEntity slat4
	EntityType e\entity,2
;	UpdateNormals e\entity
	EntityTexture e\entity,t_port
	
	If EastWest=False Then RotateEntity e\entity,0,90,0
	ex=EntityX(e\entity)
	ey=EntityY(e\entity)
	ez=EntityZ(e\entity)
	d=0.05
	For frame=1 To 68
		MoveEntity e\entity,0,d,0   ;for vertical portcullis effect 
		SetAnimKey e\entity,frame
	Next
	e\seq   = AddAnimSeq(e\entity,frame-1) ;minus 1 because For-Next loops end 1 too many
	e\kind  = port
	e\state = closed
	PositionEntity e\entity,ex,ey,ez ;undo the positioning done by the animation
Return

.animate
	If MouseDown(1)=True 
		CameraPick(camera,MouseX(),MouseY()) 	
		message$="PickedEntity is "
		pe=PickedEntity()
		px# = (EntityX(pcam)-PickedX#()) 
		pz# = (EntityZ(pcam)-PickedZ#())
		seerange# = Sqr((px*px)+(pz*pz))
		If pe = 0
			message$ = message$+"nothing."
		ElseIf seerange => fogrange-3
			message$ = message$+"Out of Range"
		Else
			message$ = message$+EntityName$(pe)+"."
			For e.entity = Each entity
				If e\entity=pe
					If seerange <4.5
						If e\kind = door
							If Animating(e\entity) = False  ;if door is not moving
								If e\state=closed
									Animate e\entity,3,.5    
									e\state = opened 
								ElseIf e\state = opened
									Animate e\entity,3,-.5
									e\state = closed 
								EndIf
							EndIf
						ElseIf e\kind = port
							If Animating(e\entity) = False
								If e\state=closed
									Animate e\entity,3,.5    ;play animationm forward (ie raise port)
									e\state = opened 
								ElseIf e\state = opened
									Animate e\entity,3,-.5
									e\state = closed 
								EndIf
							EndIf
						EndIf
					Else
						Text 0,220,"Too far to operate!"
					EndIf
				EndIf
			Next
		EndIf
		picked$="PickedX: "+PickedX#() 
		picked$=picked$+" PickedY: "+PickedY#() 
		picked$=picked$+" PickedZ: "+PickedZ#() 
		Text 0, 200, message$ ;text here, so that renderworld does not overwrite it
	EndIf
	cam$="Camera X: "+EntityX(pcam)+" Camera Y: "+EntityY(pcam)+" Camera Z: "+EntityZ(pcam)
	Text 0,100,cam$
	Text 0,120, picked$
	Text 0,140,"See Range = "+seerange
	Flip 
Wend 




jfk EO-11110(Posted 2006) [#5]
I use both methods. For standard doors I use a polling system that will open a door and close it after a certain time automaticly. It's using simple angles, but the door is parented to a pivot. the pivot defines the doors orientation in space. So the door may use simple local angles.

It's important to set the center of the door mesh right, eg:

fitmesh door,0,-meshheight(door)/2.0,-meshdepth(door)/2.0,meshwidth(door),meshheight(door),meshdepth(door)

Animated Meshes for doors are very flexible, but they also lack of some features. For example, when in motion the player may walk trough geometry.
An animated door mesh should contain two animations (open and close) this way it will be easier to play a sound when the door will open and close.