Code archives/3D Graphics - Misc/interactive entities

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

Download source code

interactive entities by Chris C2004
this code should be enough to get you going with
active entities, collisions and "gravity" that allows
you to walk up and down stairs included!

left mouse walk
mid mouse jump!
right mouse activate switch


doors must have
classname: door
name: door1 (a unique name)

switches must have
classname: switch
target: door1 (the door name the switch activates)


Enjoy!
maxdoor=10
Dim door_ent(maxdoor),door_name$(maxdoor),door_state$(maxdoor),door_time(maxdoor)
; really must get round to doin' a door type!

Global door
Const type_character=1,type_scenery=2 ; collision types
Const sx=640,sy=480 ; size of screen
Const camhigh=160

Graphics3D sx,sy,16
SetBuffer BackBuffer()

cam = CreateCamera() 

EntityType cam,type_character
EntityRadius cam,30
CameraRange cam,1,10000
PositionEntity cam,-650,40,120
UpdateWorld

CameraZoom cam,1.5

;CreateLight()

map=LoadCSM("test.csm","textures\")
EntityType map,type_scenery

Collisions type_character,type_scenery,2,2



While Not KeyDown(1) ; if ESCAPE pressed then exit 

	mys = MouseYSpeed() 

	If Abs(EntityPitch(cam)+mys) < 75 TurnEntity cam, mys,0,0  
	TurnEntity cam,0,-MouseXSpeed(),0 
	RotateEntity cam,EntityPitch(cam),EntityYaw(cam),0


	LinePick(EntityX(cam),EntityY(cam),EntityZ(cam),0,-1000,0)
	th=PickedY()+camhigh
	If th>EntityY(cam) Then
		yvel=0
		PositionEntity cam,EntityX(cam),th,EntityZ(cam)	
	EndIf
	If th<EntityY(cam) Then yvel=yvel-1
	If th=EntityY(cam) And MouseDown(3) Then yvel=10

	MoveEntity cam,0,yvel,0

	If MouseDown(1) Then MoveEntity cam,0,0,3

	MoveMouse sx/2,sy/2 ; centre mouse cursor 


	UpdateWorld

	RenderWorld
	
	Text 0,0,"pos x="+EntityX(cam)
	Text 200,0,"pos y="+EntityY(cam)
	Text 400,0,"pos z="+EntityZ(cam)

	Text 200,10,"th="+th

	Text 0,20,"cam colls="+CountCollisions(cam)

	CameraPick(cam,sx/2,sy/2)

	cp=PickedEntity() 
	Text sx/2,sy/2,cp,True,True
	If cp Then 
		Text sx/2,10+sy/2,"classname="+KeyValue(cp,"classname")
		Text sx/2,20+sy/2,"target="+KeyValue(cp,"target")
		For n=0 To door-1
			If door_name(n)=KeyValue(cp,"target") And Keyvalue(cp,"classname")="switch" Then 
				Text sx/2,-30+sy/2,"**** right mouse to trigger ****",True
				Text sx/2,30+sy/2,"door ent="+door_ent(n)
				If MouseDown(2) Then
					If door_state(n)="" Then 
						door_time(n)=50
						door_state(n)="opening"
					End If
				End If
			EndIf
		Next
	EndIf



	For n=0 To door-1
		If door_time(n)=0 Then
			If door_state(n)="closing" Then	door_state(n)=""
			If door_state(n)="waiting" Then
				door_state(n)="closing" 
				door_time(n)=50
			EndIf
			If door_state(n)="opening" Then	
				door_state(n)="waiting" 
				door_time(n)=200
			EndIf
		EndIf

		If door_state(n)="opening" Then MoveEntity door_ent(n),0,4,0
		If door_state(n)="closing" Then MoveEntity door_ent(n),0,-4,0
		If door_time(n) Then door_time(n)=door_time(n)-1
	
		Text 0,100+(n*10),n+"="+door_state(n)+","+door_time(n)	

	Next 


	Flip

Wend 


;=================================================
;=================================================
Function LoadCSM(file$,texturepath$=".\")

f=ReadFile(file)
If Not f Return

ChangeDir FileDir(file)

lightmapbank=CreateBank()
texturebank=CreateBank()

;Version - this will load CShop 4.0 and CShop 4.1 maps
version=ReadInt(f)
If version<>4 And version<>5
CloseFile f
Return
EndIf

map=CreatePivot()

;Groups
;DebugLog groupcount+" groups"
groupcount=ReadInt(f)
For n=1 To groupcount
flags=ReadInt(f)
group=ReadInt(f)
Properties$=readstringn(f)
r=ReadInt(f)
g=ReadInt(f)
b=ReadInt(f)
Next

;Visgroups (new in 4.1)
If version=5
visgroupcount=ReadInt(f)
For n=1 To visgroupcount
name$=readstringn(f)
flags=ReadInt(f)
r=ReadInt(f)
g=ReadInt(f)
b=ReadInt(f)
Next
EndIf

;Lightmaps
lightmapcount=ReadInt(f)
;DebugLog lightmapcount+" lightmaps"
For n=1 To lightmapcount
w=ReadInt(f)
h=ReadInt(f)
texture=CreateTexture(w,h)
TextureCoords texture,1
ResizeBank lightmapbank,BankSize(lightmapbank)+4
PokeInt lightmapbank,BankSize(lightmapbank)-4,texture
LockBuffer TextureBuffer(texture)
For ty=0 To h-1
For tx=0 To w-1
hue=ReadInt(f)
WritePixelFast tx,ty,hue,TextureBuffer(texture)
Next
Next
UnlockBuffer TextureBuffer(texture)
Next

;Meshes
meshcount=ReadInt(f)

;DebugLog meshcount+" meshes"
For n=1 To meshcount
	flags=ReadInt(f)
	group=ReadInt(f)
	properties$=readstringn(f)
	r=ReadInt(f)
	g=ReadInt(f)
	b=ReadInt(f)
	x#=ReadFloat(f)
	y#=ReadFloat(f)
	z#=ReadFloat(f)
	

	If version=5 visgroup=ReadInt(f)

	facecount=ReadInt(f)
	;DebugLog facecount+" surfaces."

	mesh=CreateMesh(map)
	PositionEntity mesh,x,y,z
;	If properties<>"" Then
		EntityPickMode(mesh,2)
;	End If
	
	EntityType mesh,type_scenery
	NameEntity mesh,properties
	
	If keyvalue(mesh,"classname")="door" Then
		door_ent(door)=mesh
		door_name$(door)=keyvalue(mesh,"name")
		door=door+1
	EndIf
	
	;Surfaces
	For s=1 To facecount
		flags=ReadInt(f)
		texturefile$=readstringn(f)
		lightmapindex=ReadInt(f)
		offsetu#=ReadFloat(f)
		offsetv#=ReadFloat(f)
		scaleu#=ReadFloat(f)
		scalev#=ReadFloat(f)
		rotation#=ReadFloat(f)
		vertexcount=ReadInt(f)
		;DebugLog vertexcount+" vertices"
		trianglecount=ReadInt(f)
		;DebugLog trianglecount+" triangles"
		linecount=ReadInt(f)

		surf=CreateSurface(mesh)
		brush=CreateBrush()
		texturefile=Lower(texturefile)
		texture=retrievetexture(texturepath+texturefile,texturebank)
		If texture BrushTexture brush,texture
		If lightmapindex>0 And lightmapindex*4<=BankSize(lightmapbank)
			lightmap=PeekInt(lightmapbank,(lightmapindex-1)*4)
			If lightmap
				BrushTexture brush,lightmap,0,1
				BrushFX brush,1
			EndIf
		EndIf
		PaintSurface surf,brush
		FreeBrush brush

;Vertices
		For v=0 To vertexcount-1
			x#=ReadFloat(f)
			y#=ReadFloat(f)
			z#=ReadFloat(f)
			nx#=ReadFloat(f)
			ny#=ReadFloat(f)
			nz#=ReadFloat(f)
			r=ReadInt(f)
			g=ReadInt(f)
			b=ReadInt(f)
			u0#=ReadFloat(f)
			v0#=ReadFloat(f)
			w0#=ReadFloat(f)
			u1#=ReadFloat(f)
			v1#=ReadFloat(f)
			w1#=ReadFloat(f)

			TFormPoint x,y,z,0,mesh
			AddVertex surf,TFormedX(),TFormedY(),TFormedZ(),u0,-v0
			VertexColor surf,v,r,g,b
			VertexTexCoords surf,v,u1,-v1,0,1
			VertexNormal surf,v,nx,ny,nz
		Next

;Triangles
		For t=0 To trianglecount-1
			a=ReadInt(f)
			b=ReadInt(f)
			c=ReadInt(f)
			AddTriangle surf,a,c,b
		Next

		For l=0 To linecount-1
			a=ReadInt(f)
			b=ReadInt(f)
		Next
	Next



Next

;Point Entities
entitycount=ReadInt(f)
;DebugLog entitycount+" entities"
For n=1 To entitycount
visgroup=ReadInt(f); used to be flags, but wasn't really used
group=ReadInt(f)
properties$=readstringn(f)
x#=ReadFloat(f)
y#=ReadFloat(f)
z#=ReadFloat(f)
entity=CreatePivot(map)
NameEntity entity,properties
PositionEntity entity,x,y,z
Next

;Free textures
For n=0 To BankSize(lightmapbank)-1 Step 4
FreeTexture PeekInt(lightmapbank,n)
Next
FreeBank lightmapbank
For n=0 To BankSize(texturebank)-1 Step 8
FreeBank PeekInt(texturebank,n)
FreeTexture PeekInt(texturebank,n+4)
Next
FreeBank texturebank

CloseFile f
Return map
End Function

;Read a null-terminated string
Function ReadStringN$(f,maxlength=0)
Repeat
ch=ReadByte(f)
If ch=0 Return t$
If maxlength
If Len(t$)=maxlength Return t$+Chr(ch)
EndIf
t$=t$+Chr$(ch)
Forever
End Function

;Return a loaded texture
Function RetrieveTexture(file$,bank)
For n=0 To BankSize(bank)-1 Step 8
namebank=PeekInt(bank,n)
s$=""
For b=0 To BankSize(namebank)-1
s=s+Chr(PeekByte(namebank,b))
Next
If s=file Return PeekInt(bank,n+4)
Next
ResizeBank bank,BankSize(bank)+8
namebank=CreateBank(Len(file))
For b=0 To BankSize(namebank)-1
PokeByte namebank,b,Asc(Mid(file,b+1))
Next
;DebugLog "Loading texture "+Chr(34)+CurrentDir()+file+Chr(34)
PokeInt bank,BankSize(bank)-8,namebank
texture=LoadTexture(file)
If Not texture DebugLog "Failed to load texture "+Chr(34)+CurrentDir()+file+Chr(34)
PokeInt bank,BankSize(bank)-4,texture
Return texture
End Function

;Get the file part of a file path
Function FileName$(file$,ext=1)
file=Replace(file,"/","\")
Repeat
p=Instr(file,"\")
If p
file=Right(file,Len(file)-p)
Else
Exit
EndIf
Forever
If Not ext
p=Instr(file,".")
If p file=Left(file,p-1)
EndIf
Return file
End Function

;Get the directory of a file path
Function FileDir$(file$)
file=Replace(file,"/","\")
oldp=1
Repeat
p=Instr(file,"\",oldp)
If p
oldp=p+1
Else
file=Left(file,oldp-1)
Exit
EndIf
Forever
Return file
End Function

;Parsing function
Function Piece$(s$,entry,char$=" ")
While Instr(s,char+char)
s=Replace(s,char+char,char)
Wend
For n=1 To entry-1
p=Instr(s,char)
s=Right(s,Len(s)-p)
Next
p=Instr(s,char)
If p<1
a$=s
Else
a=Left(s,p-1)
EndIf
Return a
End Function

;Function for retrieving entity properties
;[ "light"=KeyValue(entity,"classname") ]
Function KeyValue$(entity,key$)
properties$=EntityName(entity)
key$=Lower(key)
Repeat
p=Instr(properties,Chr(10))
If p test$=(Left(properties,p-1)) Else test=properties
testkey$=Piece(test,1,"=")
testkey=Trim(testkey)
testkey=Replace(testkey,Chr(34),"")
testkey=Lower(testkey)
If testkey=key
value$=Piece(test,2,"=")
value$=Trim(value$)
value$=Replace(value$,Chr(34),"")
Return value
EndIf
If Not p Return
properties=Right(properties,Len(properties)-p)
Forever
End Function

Comments

Chris C2004
forgot to mention the level/entity editor this
code works with is cartography shop.


Code Archives Forum