public JumpTester2() { sprite = new Sprite("Link.png", null, Alignments.Bottom); sprite.Position = new vec2(400, 600); textArray = new SpriteText[7]; for (int i = 0; i < textArray.Length; i++) { textArray[i] = new SpriteText("Default"); textArray[i].Position = new vec2(20, 20 * (i + 1)); } jumpSpeed = DefaultJumpSpeed; gravity = DefaultGravityReset; gravityReset = gravity; gravityLimit = DefaultGravityLimit; gravityAcceleration = DefaultGravityAcceleration; onGround = true; MessageSystem.Subscribe(this, CoreMessageTypes.Keyboard, (messageType, data, dt) => { ProcessKeyboard((KeyboardData)data); }); }
public SpriteBatch() { const int BufferCapacity = 30000; const int IndexCapacity = 3000; buffer = new PrimitiveBuffer(BufferCapacity, IndexCapacity); GLUtilities.AllocateBuffers(BufferCapacity, IndexCapacity, out bufferId, out indexBufferId, GL_DYNAMIC_DRAW); // These two shaders (owned by the sprite batch) can be completed here (in terms of binding a buffer). // External shaders are bound when first applied. spriteShader = new Shader(); spriteShader.Attach(ShaderTypes.Vertex, "Sprite.vert"); spriteShader.Attach(ShaderTypes.Fragment, "Sprite.frag"); spriteShader.AddAttribute <float>(2, GL_FLOAT); spriteShader.AddAttribute <float>(2, GL_FLOAT); spriteShader.AddAttribute <byte>(4, GL_UNSIGNED_BYTE, false, true); spriteShader.CreateProgram(); spriteShader.Bind(bufferId, indexBufferId); primitiveShader = new Shader(); primitiveShader.Attach(ShaderTypes.Vertex, "Primitives2D.vert"); primitiveShader.Attach(ShaderTypes.Fragment, "Primitives.frag"); primitiveShader.CreateProgram(); primitiveShader.AddAttribute <float>(2, GL_FLOAT); primitiveShader.AddAttribute <byte>(4, GL_UNSIGNED_BYTE, false, true); primitiveShader.Bind(bufferId, indexBufferId); MessageSystem.Subscribe(this, CoreMessageTypes.ResizeWindow, (messageType, data, dt) => { OnResize(); }); }
public RopeTester() { const float Length = 36; const float Damping = 0.95f; const float Gravity = 20; vec2[] points = new vec2[18]; for (int i = 0; i < points.Length; i++) { points[i] = new vec2(60, 120) + new vec2(Length * i * 1.25f, 0); } rope = new VerletRope2D(points, Length, Damping, Gravity); MessageSystem.Subscribe(this, CoreMessageTypes.Mouse, (messageType, data, dt) => { var mouse = (MouseData)data; if (mouse.Query(GLFW_MOUSE_BUTTON_LEFT, InputStates.PressedThisFrame)) { var array = rope.Points; var index = new Random().Next(array.Length - 2) + 1; array[index].Position += new vec2(0, 20); } }); }
public PlayerController(PlayerCharacter player, PlayerData playerData, PlayerControls controls, ControlSettings settings, AbstractController[] controllers) { this.player = player; this.playerData = playerData; this.controls = controls; this.settings = settings; aerialController = (AerialController)controllers[PlayerCharacter.ControllerIndexes.Air]; groundController = (GroundController)controllers[PlayerCharacter.ControllerIndexes.Ground]; platformController = (PlatformController)controllers[PlayerCharacter.ControllerIndexes.Platform]; wallController = (WallController)controllers[PlayerCharacter.ControllerIndexes.Wall]; ladderController = (LadderController)controllers[PlayerCharacter.ControllerIndexes.Ladder]; // TODO: Make this class reloadable. // Create buffers. var accessor = Properties.Access(); var grab = accessor.GetFloat("player.grab.buffer"); var ascend = accessor.GetFloat("player.ascend.buffer"); // Actual values for requiresHold on each buffer are set when control settings are applied. attackBuffer = new InputBuffer(false, controls.Attack); grabBuffer = new InputBuffer(grab, false, controls.Grab); ascendBuffer = new InputBuffer(ascend, false, controls.Jump); ascendBuffer.RequiredChords = controls.Ascend; settings.ApplyEvent += OnApply; MessageSystem.Subscribe(this, CoreMessageTypes.Input, (messageType, data, dt) => { ProcessInput((FullInputData)data, dt); }); }
public Terminal() { colors = new Color[4]; commands = new Dictionary <string, CommandProcessor>(); font = ContentCache.GetFont("Terminal"); currentLine = new SpriteText(font); lines = new List <SpriteText>(); oldCommands = new List <string>(); charWidth = font.Measure("A").x; storedIndex = -1; var accessor = Properties.Access(this); padding = accessor.GetInt("terminal.padding", this, false); textProcessor = new TextProcessor(); textProcessor.Submit = Submit; AddDefaultCommands(); MessageSystem.Subscribe(this, CoreMessageTypes.ResizeWindow, (messageType, data, dt) => { // The terminal is always resized to fit the window width. Width = ((ivec2)data).x; }); MessageSystem.Subscribe(this, CoreMessageTypes.Keyboard, (messageType, data, dt) => { ProcessKeyboard((KeyboardData)data); }); }
protected Game(string title) { Properties.Reload(); glfwInit(); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 4); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); IntPtr address = glfwCreateWindow(Resolution.WindowWidth, Resolution.WindowHeight, title, IntPtr.Zero, IntPtr.Zero); if (address == IntPtr.Zero) { glfwTerminate(); return; } window = new Window(title, 800, 600, address); inputProcessor = new InputProcessor(); glfwMakeContextCurrent(address); glfwSetKeyCallback(address, keyCallback); glfwSetCursorPosCallback(address, cursorPositionCallback); glfwSetMouseButtonCallback(address, mouseButtonCallback); MessageSystem.Subscribe(this, CoreMessageTypes.Exit, (messageType, data, dt) => { OnExit(); }); }
public Canvas() { elements = new List <CanvasElement>(); MessageSystem.Subscribe(this, CoreMessageTypes.ResizeWindow, (messageType, data, dt) => { elements.ForEach(PlaceElement); }); }
public Camera3D() { Orientation = quat.Identity; MessageSystem.Subscribe(this, CoreMessageTypes.ResizeRender, (messageType, data, dt) => { RecomputeProjection(); }); }
public void Load(Canvas canvas) { inventoryScreen = new InventoryScreen(); inventoryScreen.IsVisible = false; canvas.Add(inventoryScreen); MessageSystem.Subscribe(this, CoreMessageTypes.Input, (messageType, data, dt) => { ProcessInput((FullInputData)data); }); }
public Canvas() { elements = new List <CanvasElement>(); renderTargetUsers = new List <IRenderTargetUser2D>(); IsVisible = true; MessageSystem.Subscribe(this, CoreMessageTypes.ResizeWindow, (messageType, data, dt) => { elements.ForEach(e => e.Location = ComputePlacement(e)); }); }
public Player() { controls = new PlayerControls(); skillsUnlocked = new bool[Utilities.EnumCount <PlayerSkills>()]; skillsEnabled = new bool[skillsUnlocked.Length]; MessageSystem.Subscribe(this, CoreMessageTypes.Input, (messageType, data, dt) => { ProcessInput((FullInputData)data); }); }
public CharacterControlTester() { const int Padding = 10; const int WallX = 800; const int WallY = 150; playerCircle = new Circle(30); playerCircle.Position = Resolution.WindowDimensions / 2; staticCircles = new List <Circle>(); staticCircles.Add(new Circle(100) { Position = new vec2(200) }); staticCircles.Add(new Circle(80) { Position = new vec2(290, 310) }); staticCircles.Add(new Circle(250) { Position = new vec2(950, 600) }); vec2[] linePoints = { new vec2(Padding), new vec2(WallX, Padding), new vec2(WallX, WallY), new vec2(Resolution.WindowWidth - Padding,WallY), new vec2(Resolution.WindowWidth - Padding,Resolution.WindowHeight - Padding), new vec2(Padding, Resolution.WindowHeight - Padding) }; staticLines = new List <Line2D>(); for (int i = 0; i < linePoints.Length; i++) { vec2 p1 = linePoints[i]; vec2 p2 = i == linePoints.Length - 1 ? linePoints[0] : linePoints[i + 1]; staticLines.Add(new Line2D(p1, p2)); } staticRectangles = new List <Rectangle>(); staticRectangles.Add(new Rectangle(40, Resolution.WindowHeight - 40, 80)); staticRectangles.Add(new Rectangle(620, 180, 150, 100)); staticRectangles.Add(new Rectangle(810, 440, 100)); MessageSystem.Subscribe(this, CoreMessageTypes.Keyboard, (messageType, data, dt) => { ProcessKeyboard((KeyboardData)data, dt); }); }
public MainGame() : base("Zeldo") { glClearColor(0, 0, 0, 1); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glPrimitiveRestartIndex(Constants.RestartIndex); glfwSetInputMode(window.Address, GLFW_CURSOR, GLFW_CURSOR_DISABLED); Language.Reload(Languages.English); canvas = new Canvas(); sb = new SpriteBatch(); mainTarget = new RenderTarget(Resolution.RenderWidth, Resolution.RenderHeight, RenderTargetFlags.Color | RenderTargetFlags.Depth); mainSprite = new Sprite(mainTarget, null, Alignments.Left | Alignments.Top); mainSprite.Mods = SpriteModifiers.FlipVertical; // The first loop is created manually. Others are created via gamestate messages. currentState = Gamestates.Gameplay; nextState = currentState; activeLoop = CreateLoop(currentState); MessageSystem.Subscribe(this, CoreMessageTypes.Keyboard, (messageType, data, dt) => { ProcessKeyboard((KeyboardData)data); }); MessageSystem.Subscribe(this, CoreMessageTypes.ResizeWindow, (messageType, data, dt) => { mainSprite.ScaleTo(Resolution.WindowWidth, Resolution.WindowHeight); }); MessageSystem.Subscribe(this, CustomMessageTypes.Gamestate, (messageType, data, dt) => { var state = (Gamestates)data; Debug.Assert(state != Gamestates.Splash, "Can't transition to the splash loop."); // This implementation means that if multiple gamestate messages are sent on a single frame, the last // state will take priority (although that should never happen in practice). if (state != currentState) { nextState = state; } }); // Calling this function here is required to ensure that all classes receive initial resize messages. MessageSystem.ProcessChanges(); MessageSystem.Send(CoreMessageTypes.ResizeRender, Resolution.RenderDimensions); MessageSystem.Send(CoreMessageTypes.ResizeWindow, Resolution.WindowDimensions); }
public FollowView(Camera3D camera, PlayerCharacter player, ControlSettings settings) : base(camera) { this.player = player; this.settings = settings; player.FollowView = this; Properties.Access(this); MessageSystem.Subscribe(this, CoreMessageTypes.Input, (messageType, data, dt) => { ProcessInput((FullInputData)data); }); }
protected Game3D(string title, Dictionary <TLoopType, Type> loops, TLoopType loopType, int updateTick = 60, int renderTick = 60) : base(title, loops, loopType, updateTick, renderTick) { renderer = new MasterRenderer3D(camera); activeLoop = CreateLoop(loopType); mainTarget = new RenderTarget(Resolution.RenderWidth, Resolution.RenderHeight, RenderTargetFlags.Color | RenderTargetFlags.Depth); mainSprite = new Sprite(mainTarget, Alignments.Left | Alignments.Top); mainSprite.Mods = SpriteModifiers.FlipVertical; MessageSystem.Subscribe(this, CoreMessageTypes.ResizeWindow, data => { mainSprite.ScaleTo(Resolution.WindowWidth, Resolution.WindowHeight, false); }); }
public Player() : base(EntityTypes.Player) { LoadAnimations("PlayerAnimations.json"); PlayAnimation("Idle"); playerData = new PlayerData(); Body = PhysicsFactory.CreateRectangle(PlayerWidth, PlayerHeight, Units.Pixels, BodyType.Dynamic, this); Body.Friction = 0; Body.ManuallyControlled = true; Body.MaximumSpeed = new Vector2(PhysicsConvert.ToMeters(playerData.MaxSpeed), float.PositiveInfinity); idle = true; MessageSystem.Subscribe(MessageTypes.Keyboard, this); MessageSystem.Subscribe(MessageTypes.Mouse, this); }
public Canvas() { elements = new List <CanvasElement>(); renderTargetUsers = new HashSet <IRenderTargetUser2D>(); IsDrawEnabled = true; MessageSystem.Subscribe(this, (int)CoreMessageTypes.ResizeWindow, data => { elements.ForEach(e => { if (e.Anchor != Anchors.None) { e.SetPosition(ComputePlacement(e), false); } }); }); }
public Camera3D() { var flags = new Flags <TransformFlags>(TransformFlags.None); position = new RenderPosition3DField(flags); orientation = new RenderOrientationField(flags); OrthoWidth = 16; OrthoHeight = 9; NearPlane = 0.1f; FarPlane = 1000; fov = Constants.PiOverTwo; MessageSystem.Subscribe(this, (int)CoreMessageTypes.ResizeRender, data => { RecomputeProjection(); }); }
public PhysicsTester() { Body2D staticBox = new Body2D(new Rectangle(300, 75), null); staticBox.Position = new vec2(400, 300); staticBox.IsStatic = true; Body2D dynamicBox = new Body2D(new Capsule(60, 20), null); dynamicBox.Position = new vec2(400, 150); world = new World2D(); world.Add(staticBox); world.Add(dynamicBox); MessageSystem.Subscribe(this, CoreMessageTypes.Keyboard, (messageType, data, dt) => { ProcessKeyboard((KeyboardData)data); }); }
public ShadowMapVisualizer(RenderTarget shadowMapTarget) { Shader shader = new Shader(); shader.Attach(ShaderTypes.Vertex, "Sprite.vert"); shader.Attach(ShaderTypes.Fragment, "ShadowMapVisualization.frag"); shader.AddAttribute <float>(2, GL_FLOAT); shader.AddAttribute <float>(2, GL_FLOAT); shader.AddAttribute <byte>(4, GL_UNSIGNED_BYTE, true); shader.CreateProgram(); sprite = new Sprite(shadowMapTarget, null, Alignments.Left | Alignments.Bottom); sprite.Shader = shader; DisplaySize = DefaultSize; MessageSystem.Subscribe(this, CoreMessageTypes.ResizeWindow, (messageType, data, dt) => { sprite.Position = new vec2(0, Resolution.WindowHeight); }); }
public Terminal(Primitive <bool> isPauseToggled) { this.isPauseToggled = isPauseToggled; commands = new SortedDictionary <string, Command>(); autocomplete = new Autocomplete(); font = ContentCache.GetFont("Debug"); currentLine = new SpriteText(font); suggestionText = new SpriteText(font); lines = new List <SpriteText>(); history = new List <string>(); charWidth = font.Measure("A").x; storedIndex = -1; insertBounds = new Bounds2D(charWidth, font.Size); var accessor = Properties.Access(); padding = accessor.GetInt("terminal.padding"); historyLimit = accessor.GetInt("terminal.history.limit"); Height = accessor.GetInt("terminal.default.height"); Anchor = Anchors.Left | Anchors.Top; IsDrawEnabled = false; colors = new Color[5]; textProcessor = new TextProcessor(); textProcessor.RepeatDelay = accessor.GetFloat("terminal.repeat.delay"); textProcessor.RepeatRate = accessor.GetFloat("terminal.repeat.rate"); textProcessor.Submit = Submit; AddDefaultCommands(); MessageSystem.Subscribe(this, (int)CoreMessageTypes.ResizeWindow, data => { // The terminal is always resized to fit the window width. Width = ((ivec2)data).x; }); InputProcessor.Add(this, 10); }
public ShadowMapVisualizer(RenderTarget shadowMapTarget) { Shader shader = new Shader(); shader.Attach(ShaderTypes.Vertex, "Sprite.vert"); shader.Attach(ShaderTypes.Fragment, "ShadowMapVisualization.frag"); shader.AddAttribute <float>(2, GL_FLOAT); shader.AddAttribute <float>(2, GL_FLOAT); shader.AddAttribute <byte>(4, GL_UNSIGNED_BYTE, true); shader.Initialize(); sprite = new Sprite(shadowMapTarget, Alignments.Left | Alignments.Bottom); sprite.Shader = shader; //sprite.Color = Color.Yellow; DisplaySize = DefaultSize; MessageSystem.Subscribe(this, (int)CoreMessageTypes.ResizeWindow, data => { sprite.Position.SetValue(new vec2(0, Resolution.WindowHeight), false); }); }
public RopeTester() { const int Segments = 12; const int Length = 30; rope = new VerletRope(Segments, Length); rope.Position = new vec2(400, 300); models = new Model[Segments]; Batch = new ModelBatch(1000000, 100000); for (int i = 0; i < Segments; i++) { Model model = new Model("Chain.obj"); models[i] = model; Batch.Add(model); } MessageSystem.Subscribe(this, CoreMessageTypes.Mouse, (messageType, data, dt) => { ProcessMouse((MouseData)data); }); }
public MainGame() : base("Dungeon") { sb = new SpriteBatch(); camera = new Camera3D(); camera.IsOrthographic = true; camera.Orientation *= quat.FromAxisAngle(0, vec3.UnitX); camera.Position = new vec3(0, 0, 1) * camera.Orientation; mainTarget = new RenderTarget(Resolution.RenderWidth, Resolution.RenderHeight, RenderTargetFlags.Color | RenderTargetFlags.Depth); mainSprite = new Sprite(mainTarget, null, Alignments.Left | Alignments.Top); mainSprite.Mods = SpriteModifiers.FlipVertical; Player player = new Player(); player.UnlockSkill(PlayerSkills.Jump); scene = new Scene(); scene.Camera = camera; scene.Add(player); scene.ModelBatch.LightDirection = Utilities.Normalize(new vec3(1, -0.2f, 0)); renderTargetUsers = new List <IRenderTargetUser>(); renderTargetUsers.Add(scene.ModelBatch); physicsTester = new PhysicsTester(); MessageSystem.Subscribe(this, CoreMessageTypes.ResizeWindow, (messageType, data, dt) => { mainSprite.ScaleTo(Resolution.WindowWidth, Resolution.WindowHeight); }); MessageSystem.ProcessChanges(); MessageSystem.Send(CoreMessageTypes.ResizeRender, Resolution.RenderDimensions); MessageSystem.Send(CoreMessageTypes.ResizeWindow, Resolution.WindowDimensions); }
protected Game(string title, Dictionary <TLoopType, Type> loops, TLoopType loopType, int updateTick = 60, int renderTick = 60) { Debug.Assert(updateTick > 0, "Update tick must be positive."); Debug.Assert(renderTick > 0, "Render tick must be positive."); Debug.Assert(loops.ContainsKey(loopType), $"Can't launch into loop type '{loopType}' (no associated " + "class provided)."); Debug.Assert(loops.Values.All(t => typeof(TLoop).IsAssignableFrom(t)), "Invalid type in loop map (all " + $"types must extend {typeof(TLoop).FullName})."); this.loops = loops; dtUpdate = 1f / updateTick; dtRender = 1f / renderTick; RenderTick = renderTick; DeltaTime.Value = dtUpdate; glfwInit(); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 4); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); var address = glfwCreateWindow(Resolution.WindowWidth, Resolution.WindowHeight, title, IntPtr.Zero, IntPtr.Zero); if (address == IntPtr.Zero) { glfwTerminate(); return; } window = new Window(Resolution.WindowWidth, Resolution.WindowHeight, address); inputProcessor = InputProcessor.Instance; // TODO: Is glfwSetInputMode(window, GLFW_LOCK_KEY_MODS, GLFW_TRUE) needed? (see the GLFW input guide) glfwMakeContextCurrent(address); glfwSetKeyCallback(address, keyCallback); glfwSetCursorPosCallback(address, cursorPositionCallback); glfwSetMouseButtonCallback(address, mouseButtonCallback); glfwSetWindowFocusCallback(address, focusCallback); glClearColor(0, 0, 0, 1); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glPrimitiveRestartIndex(Constants.PrimitiveRestartIndex); camera = new TCamera(); canvas = new Canvas(); sb = new SpriteBatch(); isPauseToggled = new Primitive <bool>(); // The loop itself is created via a call to CreateLoop from parent constructors. currentLoopType = loopType; nextLoopType = loopType; MessageSystem.Subscribe(this, CoreMessageTypes.Exit, data => { glfwSetWindowShouldClose(window.Address, 1); }); MessageSystem.Subscribe(this, CoreMessageTypes.Gamestate, data => { nextLoopType = (TLoopType)data; }); MessageSystem.Send(CoreMessageTypes.ResizeRender, Resolution.RenderDimensions); MessageSystem.Send(CoreMessageTypes.ResizeWindow, Resolution.WindowDimensions); }
protected override void RegisterForClassifierEvent(MessageSystem messageSystem, Classifier classifier) { messageSystem.Subscribe<ClassToInterfaceEvent>(classifier, OnClassToInterfaceChanged); messageSystem.Subscribe<InterfaceToClassEvent>(classifier, OnInterfaceToClassChanged); }
public JumpTester() { sprites = new Sprite[4]; for (int i = 0; i < sprites.Length; i++) { sprites[i] = new Sprite("Link.png", null, Alignments.Bottom) { Position = new vec2(160 + 160 * i, 600) }; } timer = new SingleTimer(t => { if (falling) { timer.Elapsed = 0; timer.Duration = JumpDuration; //timer.Paused = true; //onGround = true; falling = false; foreach (Sprite sprite in sprites) { sprite.Y = Resolution.WindowHeight; } return; } timer.Elapsed = t; timer.Duration = FallDuration; falling = true; }, JumpDuration); timer.Tick = progress => { if (falling) { float quadratic = QuadraticIn(progress); float cubic = CubicIn(progress); foreach (Sprite sprite in sprites) { sprite.Y = Resolution.WindowHeight - JumpHeight + JumpHeight * quadratic; } return; } float[] tArray = { QuadraticOut(progress), CubicOut(progress), QuarticOut(progress), QuinticOut(progress) }; for (int i = 0; i < sprites.Length; i++) { sprites[i].Y = Resolution.WindowHeight - JumpHeight * tArray[i]; } }; //timer.Paused = true; //onGround = true; MessageSystem.Subscribe(this, CoreMessageTypes.Keyboard, (messageType, data, dt) => { ProcessKeyboard((KeyboardData)data); }); }
public override void Initialize() { CollisionSystem system = new CollisionSystemSAP(); system.UseTriangleMeshNormal = true; // TODO: Should damping factors be left in their default states? (they were changed while adding kinematic bodies) world = new World(system); world.Gravity = new JVector(0, -PhysicsConstants.Gravity, 0); world.SetDampingFactors(1, 1); world.Events.ContactCreated += OnContact; space = new Space(); scene = new Scene { Camera = camera, Canvas = canvas, Space = space, World = world }; var stats = new StatisticsDisplay(); stats.Anchor = Alignments.Left | Alignments.Top; stats.Offset = new ivec2(10); stats.IsVisible = false; canvas.Clear(); canvas.Load("Canvas.json"); canvas.Add(stats); //canvas.Add(new RopeTester()); spawnHelper = new SpawnHelper(scene); // TODO: Load settings from a file. ControlSettings settings = new ControlSettings(); settings.MouseSensitivity = 50; // TODO: Set player position from a save slot. PlayerCharacter player = new PlayerCharacter(settings); player.Equip(new Sword(player)); player.Unlock(PlayerSkills.Grab); player.Unlock(PlayerSkills.Jump); player.Unlock(PlayerSkills.DoubleJump); player.Unlock(PlayerSkills.WallJump); //player.Unlock(PlayerSkills.Ascend); player.Unlock(PlayerSkills.Block); player.Unlock(PlayerSkills.Parry); player.Equip(new Sword(player)); // TODO: Load fragments from a save slot. scene.Add(player); var fragment = scene.LoadFragment("Demo.json"); //var fragment = scene.LoadFragment("Windmill.json"); player.Position = fragment.Origin + fragment.Spawn; CreateDebugCubes(); camera.Attach(new FollowView(camera, player, settings)); // TODO: Initialize renderer settings from a configuration file (based on user settings). // TODO: Set light color and direction based on time of day and weather. var renderer = scene.Renderer; renderer.Light.Direction = Utilities.Normalize(new vec3(-2, -0.75f, 2)); renderTargetUsers3D.Add(renderer); // Create visualizers. spaceVisualizer = new SpaceVisualizer(camera, space); jitterVisualizer = new JitterVisualizer(camera, world); jitterVisualizer.IsEnabled = true; MessageSystem.Subscribe(this, CoreMessageTypes.Keyboard, (messageType, data, dt) => { ProcessKeyboard((KeyboardData)data); }); }