Kapitel 41 · Doom 3

ÜBERWACHUNGSKAMERAS

Autor: Fragpoint
Downloads: Beispielmap 34 und neue_camcontrol.gui

Sicher habt Ihr Euch auch schon einmal gefragt, wie diese Überwachungskameras funktionieren, zwischen denen der Spieler über ein Display hin- und herschalten kann. Zunächst brauchen wir ein Model, das unseren Bildschirm darstellt, auf dem wir zum Einen die Kameras anwählen und zum Anderen die aktuelle Aufzeichnung sehen können. Erstellt dazu ein "func -> func_static" und ordnet diesem das Model "models -> mapobjects -> cpu -> smallguimonitor.lwo" zu.

image320.jpg

Ich habe diesen übrigens im 2. Stockwerk platziert, bei dem unser Aufzug ankommt. Falls das Model bei Euch nicht richtig angezeigt wird, könnt Ihr entweder die Map speichern und neu laden, oder die Leertaste drücken. Das Objekt wird dann dupliziert und richtig dargestellt. Somit hätten wir das Model für unser Display schon einmal. Jetzt benötigen wir noch die Überwachungskameras selbst. Dazu erstellen wir ein "func -> func_securitycam".

image321.jpg

Diese wird als kleiner Würfel mit einem Pfeil dargestellt. Optisch wäre dieses Entity im Spiel jedoch nicht sichtbar, so dass wir dem Entity noch ein Model zuordnen, nämlich das "models -> mapobjects -> camera -> camera01.ase". Komischerweise sind dort nicht alle Verzeichnisse alphabetisch geordnet, so dass sich das Camera-Verzeichnis ziemlich am Ende der Liste befindet.

image322.jpg

Auch hier gilt wieder der Trick mit der Leertaste, falls das Model nicht korrekt angezeigt wird.

image323.jpg

Da man über unser Display insgesamt sechs Überwachungskameras anwählen kann, wollen wir genauso viele der Kameras in unserer Testmap platzieren. Ich habe hierzu welche im Pinky- (1x), Lava- (1x), Teleporter- (1x), Spiegel- (1x) und Aufzugraum (2x) gesetzt. Leider sind die Kamera-Models noch nicht richtig ausgerichtet, so dass wir diese über die Rotate-Funktion (R-Taste) anpassen. Denn es bringt ja nichts, wenn das Kamera-Model nach oben zur Decke gerichtet ist, aber eigentlich ein Bild vom Fußboden zeigt. Das wirkt unglaubwürdig. Deshalb müssen diese entsprechend ausgerichtet werden.

image324.jpg

So, nun wären sowohl die Kameras als auch das Überwachungsdisplay vorhanden, doch leider werden uns dort noch keine Bilder gezeigt. Leute, die die letzten Tutorials durchgearbeitet haben, werden sich sicher denken, dass man dem Monitor nun nur noch ein GUI als Display zuordnen muss. Das ist in diesem Fall leider falsch! Wir müssen uns deshalb eine andere Methode ausdenken.

Geht dazu zum Überwachungsmonitor (nicht markieren) und erstellt einen neuen Brush, aus dem Ihr einen "Patch -> Simple Patch Mesh" und anschließend ein "func -> func_static" macht. Vergrößert/Verkleinert diesen Patch nun so, dass er in den linken Monitor unseres Models passt. Ggf. müsst Ihr ihn auch etwas drehen. Beachtet unbedingt, dass "View -> Show -> Show Curves" aktiviert sein muss, da der Patch sonst unsichtbar wird, wenn Ihr ihn abwählt. Es kann sein, dass diese Option zwar aktiviert erscheint, es aber in Wirklichkeit nicht ist. Checkt das am besten noch mal.
Achtet darauf, dass dieser Patch nicht im Model aber ganz knapp über dessen Oberfläche ist. Wählt dazu am besten ein ganz feines Grid (0.125) aus.

image325.jpg

Belegt diesen Patch nun mit der Textur "textures -> common -> entitygui". Die Textur sollte schön mittig ausgerichtet sein, so dass wir die Taste S (geht auch bei Patches) und anschließend den Fit-Button drücken. Es kann sein, dass die Schrift nun noch spiegelverkehrt dargestellt wird. Dazu können wir noch im Surface-Inspektor Flip Y oder Flip X drücken.

image326.jpg

Als nächstes müssen wir diesem Patch noch das passende GUI zuweisen, so dass dem Spieler später eine Kamera-Auswahl angezeigt wird. Wir nehmen dazu das GUI "guis -> cameras -> alphalabs2_camcontrol.gui".

image327.jpg

Somit wäre der Auswahl-Monitor fertig. Nun benötigen wir noch die eigentliche Anzeige. Geht hier wieder genauso vor, indem ihr einen "Patch -> Simple Patch Mesh..." erstellt und diesen zu einem "func -> func_static" macht. Platziert hier den Patch direkt über dem rechten Monitor unseres Models und belegt ihn mit der Textur "textures -> cameraimg1".

image328.jpg

Ihr müsst übrigens nicht unbedingt einen Patch verwenden, sondern könnt auch einen ganz normalen Brush verwenden. Diese darf jedoch nur auf der Vorderseite mit der Textur "textures -> cameraimg1" belegt sein, alle anderen Seiten müssen die Textur "nodraw" haben. Auch diesem Patch weisen wir ein GUI zu, nämlich "guis -> cameras -> alphalabs2_camera.gui". Über dieses werden später die jeweiligen Kamerabilder angezeigt. Nun müssen wir aber noch eine Veränderung bei den Befehlen vornehmen. Bei Euch steht sicher unter name so etwas Ähnliches wie "func_static_5542". Bei dem Name-Befehl müssen wir jedoch eine andere Eintragung vornehmen:

image329.jpg

Dabei ändert sich auch automatisch der Wert, der beim Befehl model eingetragen ist. Als nächstes müssen wir noch angeben, mit welcher Kamera der Monitor automatisch zuerst verbunden sein soll. Hierzu geben wir folgendes ein:

cameraTarget	cam6

Anschließend geben wir noch ein, welche Kamera im Display angezeigt werden soll, wenn in der Liste auf dem linken Monitor der 1., 2., 3., 4., 5. oder 6. Punkt ausgewählt wurde.

gui_parm1	1
gui_parm2	2
gui_parm3	3
gui_parm4	4
gui_parm5	5
gui_parm6	6

Wählt Ihr also auf dem linken Monitor die erste Kamera aus der Liste aus (gui_parm1), wird im rechten Monitor das Bild der Kamera 1 (cam1) gezeigt. Als nächstes wollen wir festlegen, wie weit die Kamera schwenken darf. Dies erfolgt in Gradangaben. Da wir mit den Kameras den ganzen Raum überblicken, und somit 180 Grad schwenken lassen wollen, tragen wir bei allen folgenden Befehl ein:

sweepAngle	180

Momentan würde das Bild noch direkt aus der Kamera heraus aufgenommen werden, so dass man unter Umständen Teilbereich der Wand mit in die Aufnahme bekommt. Damit der Aufnahmepunkt etwas vor der Kamera sitzt, geben wir noch folgendes ein:

Bei Kameras mit Blickrichtung Norden:

viewOffset	0 30 0

Bei Kameras mit Blickrichtung Süden:
viewOffset	0 -30 0

Bei Kameras mit Blickrichtung Osten:
viewOffset	30 0 0

Bei Kameras mit Blickrichtung Westen:
viewOffset	-30 0 0

Falls Euch die Geschwindigkeit der Kameras beim Schwenken noch etwas zu schnell ist, könnt Ihr dies über folgenden Befehl regulieren:

sweepSpeed	10

Schauen wir uns die einzelnen Eintragungen bei einer beliebigen Kamera noch einmal an:

image330.jpg

Und hier noch mal die ganzen Befehle für das Kamera-Entity:

KEY: name
VALUE: cam1, cam2, etc.
Hier kann man den Namen der Kamera eintragen. Es sollte sich dabei um den fortlaufend nummerierten Namen cam handeln. Die Namen müssen identisch mit den Eintragungen bei den einzelnen Kameras sein.

KEY: sweepAngle
VALUE: Zahlenwerte (0-360)
Gibt an, in welchem Winkel die Kamera hin- und herschwenkt. Umso größer der Winkel, umso schneller schwenkt die Kamera.

KEY: health
VALUE: Zahlenwerte
Hier könnt Ihr angeben, ob die Kamera zerstörbar ist und wie viel sie aushält (Lebenspunkte).

KEY: scanFov
VALUE: Zahlenwerte
Reichweite in der die Kamera aufnimmt.

KEY: scanDist
VALUE: Zahlenwerte
Hier wird die Reichweite der Kamera angegeben.

KEY: flipAxis
VALUE: Zahlenwerte
Hierdurch wird der Kamera gesagt, dass sie alles aufnehmen soll, was hinter ihr liegt (also entgegen der eigentlichen Blickrichtung).

KEY: modelAxis
VALUE: Zahlenwerte
Hier kann man festlegen, über welche Achse sich das Kamera-Model drehen soll.

KEY: sightTime
VALUE: Zahlenwerte in Sekunden
Hier wird die Zeit in Sekunden eingetragen, die die Kamera benötigt, bis sie einen Spieler wahrnimmt und sich auf diesen ausrichtet.

KEY: sightResume
VALUE: Zahlenwerte in Sekunden
Hier wird die Zeit in Sekunden eingetragen, die die Kamera benötigt, um den Spieler neu anzuvisieren.

KEY: sweepSpeed
VALUE: Zahlenwerte
Hier die Geschwindigkeit angegeben, mit der die Kamera eine Schwenkbewegung vollzieht.

KEY: sweepWait
VALUE: Zahlenwerte
Hier kann eingetragen werden, wie lange die Kamera warten soll, bis sie nach einer vollendeten Schwenkung wieder in die andere Richtung zurückdreht.

KEY: wait
VALUE: Zahlenwerte
Wartezeit der Kamera, bis sie nach einem Alarm erneut auf die Suche nach dem Spieler geht.

KEY: viewOffset
VALUE: Zahlenwerte (X-, Y- und Z-Achse)
Hier könnt Ihr festlegen, ob die Aufnahme direkt aus der Kamera heraus erfolgen soll, oder ob dies über einen vorgelagerten Punkt geschieht.

Nun schauen wir noch einmal kurz unseren Überwachungsmonitor an:

image331.jpg

Ist schon mal sehr schön. Jetzt haben wir aber noch das Problem, dass in der Auswahlliste des linken Monitors komische Raumbezeichnungen erscheinen, die nicht zu unserer Map passen. Wir müssen dazu zunächst aus der Datei pak000.pk4 das Verzeichnis GUIS in den Base-Ordner unserer Doom3-Installation entpacken. Anschließend öffnen wir dort die Datei "…/base/guis/cameras/alphalabs2_camcontrol.gui".

image332.jpg

Wie Ihr Euch sicher erinnert, haben wir dem linken Monitor dieses GUI zugeordnet. Verwendet zum Öffnen dieser Datei unbedingte Notepad, also einen reinen Texteditor, und kein anderes Programm, sonst könnten Fehler beim Speichern auftreten. Den Inhalt der GUI-Datei habe ich unten aufgeführt. Änderungen nehmt ihr bitte NUR beim rot markierten Text vor, der für die Namensanzeige zuständig ist:

windowDef Desktop {
	rect		0 ,0 ,640 ,480
	backcolor 0, 0, 0, 0

	onDeactivate {
			set "Button1::forecolor" "0.7 0.58 0.4 0.6" ;
			set "Button2::forecolor" "0.7 0.58 0.4 0.6" ; 
			set "Button3::forecolor" "0.7 0.58 0.4 0.6" ; 
			set "Button4::forecolor" "0.7 0.58 0.4 0.6" ; 
			set "Button5::forecolor" "0.7 0.58 0.4 0.6" ; 
			set "Button6::forecolor" "0.7 0.58 0.4 0.6" ; 
	} 


	windowDef Background {
		rect		0, 0, 640, 480
		background	"guis/assets/camera/bga"
		matcolor	1 ,0.8, 0.7, 0.7 
		visible		1
	}

	windowDef Background2 {
		rect		0, 0, 640, 480
		background	"guis/assets/camera/bgc"
		matcolor	1, 1, 1, 0.7
		visible		0
	}

	windowDef Bglow {
		rect 0, 0, 640, 480
		background	"guis/assets/cpuserver/bglow.tga"
		visible 1
		matcolor 1, 0.8, 0.4, 0.04
	}


	windowDef TriFlash{
		rect		12, 8, 92, 70
		background	"guis/assets/camera/triflash"
		matcolor	1, 1, 1, 0.5
		visible		1

		onTime 0 {
			transition "matcolor" "1 1 1 0.5" "1 1 1 0.1" "1000" ;
		}
		onTime 2000 {
			resetTime "0" ;
		}
	}

	windowDef Text1 {
		rect		180, 24, 500, 70
		text		"#str_00254"
		textscale	0.81
		forecolor	0.7, 0.58, 0.4, 1
	}

	windowDef Text2 {
		rect		71, 81, 510, 70
		text		"#str_00255"
		textalign	2
		textscale	0.6
		forecolor	0, 0, 0, 0.5
		visible		1
	}

	windowDef BackgroundGlow {
		rect		0, 0, 640, 480
		background	"gui/camera/bgglow"
		matcolor	1 ,1, 0, 1 
		visible		1
	}

	windowDef ButtonSelect {
		rect		107, 139, 508, 45
		background	"guis/assets/camera/blueselect"
		matcolor	1, 1, 1, 0.35
		visible 	0
	}

	windowDef Button1 {
		rect		122, 139, 500, 70
		[COLOR=Red][B]text		"Kamera1"[/B][/COLOR]
		textscale	0.6
		forecolor	0.7, 0.58, 0.4, 0.6
		cursor		1

		onMouseEnter {
			set	"forecolor" "0.7 0.58 0.4 1" ; 
		} 
		onMouseExit {
			set	"forecolor" "0.7 0.58 0.4 0.6" ; 
		} 
		onAction {
			resetTime "AnimButton1" "0" ;
			set	"cmd" "setkeyval guicam gui_parm1 1 ; setkeyval guicam cameraTarget cam1 ; play guisounds_click" ; 
		} 
	}

	windowDef Button2 {
		rect		122, 193, 500, 70
		[COLOR=Red][B]text		"Kamera2"[/B][/COLOR]
		textscale	0.6
		forecolor	0.7, 0.58, 0.4, 0.6
		cursor		1

		onMouseEnter {
			set	"forecolor" "0.7 0.58 0.4 1" ; 
		} 
		onMouseExit {
			set	"forecolor" "0.7 0.58 0.4 0.6" ; 
		} 
		onAction {
			resetTime "AnimButton2" "0" ;
			set	"cmd" "setkeyval guicam gui_parm1 2 ; setkeyval guicam cameraTarget cam2 ; play guisounds_click" ; 
		} 
	}

	windowDef Button3 {
		rect		122, 245, 500, 70
		[COLOR=Red][B]text		"Kamera3"[/B][/COLOR]
		textscale	0.6
		forecolor	0.7, 0.58, 0.4, 0.6
		cursor		1

		onMouseEnter {
			set	"forecolor" "0.7 0.58 0.4 1" ; 
		} 
		onMouseExit {
			set	"forecolor" "0.7 0.58 0.4 0.6" ; 
		} 
		onAction {
			resetTime "AnimButton3" "0" ;
			set	"cmd" "setkeyval guicam gui_parm1 3 ; setkeyval guicam cameraTarget cam3 ; play guisounds_click" ; 
		} 
	}

	windowDef Button4 {
		rect		122, 298, 500, 70
		[COLOR=Red][B]text		"Kamera4"[/B][/COLOR]
		textscale	0.6
		forecolor	0.7, 0.58, 0.4, 0.6
		cursor		1

		onMouseEnter {
			set	"forecolor" "0.7 0.58 0.4 1" ; 
		} 
		onMouseExit {
			set	"forecolor" "0.7 0.58 0.4 0.6" ; 
		} 
		onAction {
			resetTime "AnimButton4" "0" ;
			set	"cmd" "setkeyval guicam gui_parm1 4 ; setkeyval guicam cameraTarget cam4 ; play guisounds_click" ; 
		} 
	}

	windowDef Button5 {
		rect		122, 350, 500, 70
		[COLOR=Red][B]text		"Kamera5"[/B][/COLOR]
		textscale	0.6
		forecolor	0.7, 0.58, 0.4, 0.6
		cursor		1

		onMouseEnter {
			set	"forecolor" "0.7 0.58 0.4 1" ; 
		} 
		onMouseExit {
			set	"forecolor" "0.7 0.58 0.4 0.6" ; 
		} 
		onAction {
			resetTime "AnimButton5" "0" ;
			set	"cmd" "setkeyval guicam gui_parm1 5 ; setkeyval guicam cameraTarget cam5 ; play guisounds_click" ; 
		} 
	}

	windowDef Button6 {
		rect		122, 404, 500, 70
		[COLOR=Red][B]text		"Kamera6"[/B][/COLOR]
		textscale	0.6
		forecolor	0.7, 0.58, 0.4, 0.6
		cursor		1

		onMouseEnter {
			set	"forecolor" "0.7 0.58 0.4 1" ; 
		} 
		onMouseExit {
			set	"forecolor" "0.7 0.58 0.4 0.6" ; 
		} 
		onAction {
			resetTime "AnimButton6" "0" ;
			set	"cmd" "setkeyval guicam gui_parm1 6 ; setkeyval guicam cameraTarget cam6 ; play guisounds_click" ; 
		} 
	}

	windowDef CamIcon1 {
		rect		33, 152, 48, 21
		background	"guis/assets/camera/camcon1"
		matcolor	0.7, 1, 0.8, 0
		visible 	1
	}

	windowDef CamIcon2 {
		rect		33, 207, 48, 21
		background	"guis/assets/camera/camcon2"
		matcolor	0.7, 1, 0.8, 0
		visible 	1
	}

	windowDef CamIcon3 {
		rect		33, 257, 48, 21
		background	"guis/assets/camera/camcon1"
		matcolor	0.7, 1, 0.8, 0
		visible 	1
	}

	windowDef CamIcon4 {
		rect		33, 309, 48, 21
		background	"guis/assets/camera/camcon1"
		matcolor	0.7, 1, 0.8, 0
		visible 	1
	}

	windowDef CamIcon5 {
		rect		33, 362, 48, 21
		background	"guis/assets/camera/camcon1"
		matcolor	0.7, 1, 0.8, 0
		visible 	1
	}

	windowDef CamIcon6 {
		rect		33, 415, 48, 21
		background	"guis/assets/camera/camcon1"
		matcolor	0.7, 1, 0.8, 0
		visible 	1
	}

	windowDef Reflect {
		rect		0 ,-20 ,-640 ,470 
		matcolor	1 ,1 ,1 ,0.2 
		visible		1
		background	"gui/reflect1"
	}

	windowDef OuterGlowBar {
		rect	0 ,0 ,-640 ,480 
		background	"gui/outerglowbar"
		matcolor	1 ,0.7 , 0.5 ,1 
		visible	1
	}

//ANIMATION

	windowDef CamIconAnim {

		onTime 200 {
			set "CamIcon1::matcolor" "0.7 1 0.8 0.3" ;
		}		
		onTime 400 {
			set "CamIcon2::matcolor" "0.7 1 0.8 0.3" ;
			transition "CamIcon1::matcolor" "0.7 1 0.8 0.3" "0.7 1 0.8 0.1" "600" ;
		}
		onTime 600 {
			set "CamIcon3::matcolor" "0.7 1 0.8 0.3" ;
			transition "CamIcon2::matcolor" "0.7 1 0.8 0.3" "0.7 1 0.8 0.1" "600" ;
		}
		onTime 800 {
			set "CamIcon4::matcolor" "0.7 1 0.8 0.3" ;
			transition "CamIcon3::matcolor" "0.7 1 0.8 0.3" "0.7 1 0.8 0.1" "600" ;
		}
		onTime 1000 {
			set "CamIcon5::matcolor" "0.7 1 0.8 0.3" ;
			transition "CamIcon4::matcolor" "0.7 1 0.8 0.3" "0.7 1 0.8 0.1" "600" ;
		}
		onTime 1200 {
			set "CamIcon6::matcolor" "0.7 1 0.8 0.3" ;
			transition "CamIcon5::matcolor" "0.7 1 0.8 0.3" "0.7 1 0.8 0.1" "600" ;
		}
		onTime 1400 {
			transition "CamIcon6::matcolor" "0.7 1 0.8 0.3" "0.7 1 0.8 0.1" "600" ;
		}
		onTime 2000 {
			resetTime "0" ;
		}
	}


	windowDef AnimButton1 {
		notime 1
		
		onTime 0 {
			set "ButtonSelect::visible" "0" ;
			set "text2::visible" "0" ;
		}
		onTime 50 {
			set "ButtonSelect::rect" "107 139 508 45" ;
			set "ButtonSelect::visible" "1" ;
			set "text2::text" "#str_00255" ;
			set "text2::visible" "1" ;	
		}
		onTime 100 {
			set "ButtonSelect::visible" "0" ;	
		}
		onTime 150 {
			set "ButtonSelect::visible" "1" ;	
		}
	}

	windowDef AnimButton2 {
		notime 1
		
		onTime 0 {
			set "ButtonSelect::visible" "0" ;
			set "text2::visible" "0" ;
		}
		onTime 50 {
			set "ButtonSelect::rect" "107 194 508 43" ;
			set "ButtonSelect::visible" "1" ;
			set "text2::text" "#str_00255" ;
			set "text2::visible" "1" ;	
		}
		onTime 100 {
			set "ButtonSelect::visible" "0" ;	
		}
		onTime 150 {
			set "ButtonSelect::visible" "1" ;	
		}
	}

	windowDef AnimButton3 {
		notime 1
		
		onTime 0 {
			set "ButtonSelect::visible" "0" ;
			set "text2::visible" "0" ;
		}
		onTime 50 {
			set "ButtonSelect::rect" "107 246 508 43" ;
			set "ButtonSelect::visible" "1" ;
			set "text2::text" "#str_00255" ;
			set "text2::visible" "1" ;	
		}
		onTime 100 {
			set "ButtonSelect::visible" "0" ;	
		}
		onTime 150 {
			set "ButtonSelect::visible" "1" ;	
		}
	}

	windowDef AnimButton4 {
		notime 1
		
		onTime 0 {
			set "ButtonSelect::visible" "0" ;
			set "text2::visible" "0" ;
		}
		onTime 50 {
			set "ButtonSelect::rect" "107 299 508 43" ;
			set "ButtonSelect::visible" "1" ;
			set "text2::text" "#str_00255" ;
			set "text2::visible" "1" ;	
		}
		onTime 100 {
			set "ButtonSelect::visible" "0" ;	
		}
		onTime 150 {
			set "ButtonSelect::visible" "1" ;	
		}
	}

	windowDef AnimButton5 {
		notime 1
		
		onTime 0 {
			set "ButtonSelect::visible" "0" ;
			set "text2::visible" "0" ;
		}
		onTime 50 {
			set "ButtonSelect::rect" "107 351 508 43" ;
			set "ButtonSelect::visible" "1" ;	
			set "text2::text" "#str_00255" ;
			set "text2::visible" "1" ;
		}
		onTime 100 {
			set "ButtonSelect::visible" "0" ;	
		}
		onTime 150 {
			set "ButtonSelect::visible" "1" ;	
		}
	}

	windowDef AnimButton6 {
		notime 1
		
		onTime 0 {
			set "ButtonSelect::visible" "0" ;
			set "text2::visible" "0" ;
		}
		onTime 50 {
			set "ButtonSelect::rect" "107 405 508 44" ;
			set "ButtonSelect::visible" "1" ;	
			set "text2::text" "#str_00255" ;
			set "text2::visible" "1" ;
		}
		onTime 100 {
			set "ButtonSelect::visible" "0" ;	
		}
		onTime 150 {
			set "ButtonSelect::visible" "1" ;	
		}
	}
}

Natürlich könnt Ihr auch andere Raum-/Kamerabezeichnung eintragen. Anschließend speichert ihr die Datei UNBEDINGT unter einem neuen Dateinamen ab. In unserem Fall verwenden wir den Namen "neue_camcontrol.gui". Achtet darauf, dass bei Dateityp "Alle Dateien" aktiviert ist.

image333.jpg

Würdet Ihr die Datei nicht unter einem neuen Namen abspeichern, würden die neuen Bezeichnungen der Kameras auch bei der Original-Map von ID angezeigt werden. Das würde sicherlich einige Spieler sehr stören. Jetzt haben wir es fast geschafft. Wir müssen lediglich noch kurz den linken Monitor markieren und dort bei GUI den neuen Dateinamen eintragen.

image334.jpg

So schaut es dann im Spiel aus:

image335.jpg

Wir haben fertig =) und können uns bald dem nächsten Tutorial widmen.