Olympe Engine 2.0
2D Game Engine with ECS Architecture
Loading...
Searching...
No Matches
ECS_Systems_Camera.cpp
Go to the documentation of this file.
1/*
2Olympe Engine V2 - 2025
3Nicolas Chereau
4nchereau@gmail.com
5
6This file is part of Olympe Engine V2.
7
8CameraSystem Implementation: Full implementation of the camera system including
9input processing, target following, smooth zoom/rotation, and camera effects.
10
11*/
12
13#include "ECS_Systems.h"
14#include "ECS_Components.h"
15#include "ECS_Register.h"
16#include "World.h"
17#include "GameEngine.h"
21#include "system/system_utils.h"
23#include <cmath>
24#include <random>
25
26#undef min
27#undef max
28
29// Random number generator for shake effect
30static std::random_device rd;
31static std::mt19937 gen(rd());
32static std::uniform_real_distribution<float> shakeDist(-1.0f, 1.0f);
33
34//-------------------------------------------------------------
36{
37 // Camera system requires at minimum the Camera_data component
39
40 SYSTEM_LOG << "CameraSystem initialized\n";
41}
42
43//-------------------------------------------------------------
45{
46 SYSTEM_LOG << "CameraSystem destroyed\n";
47}
48
49//-------------------------------------------------------------
51{
52 // Early return if no entities
53 if (m_entities.empty())
54 return;
55
56 float dt = GameEngine::fDt;
57
58 // Process all camera entities
59 for (EntityID entity : m_entities)
60 {
61 try
62 {
63 // 1. Update input (read keyboard/joystick and calculate direction/zoom/rotation)
64 UpdateCameraInput(entity, dt);
65
66 // 2. Update target following
67 UpdateCameraFollow(entity, dt);
68
69 // 3. Update zoom (smooth interpolation)
70 UpdateCameraZoom(entity, dt);
71
72 // 4. Update rotation (smooth interpolation)
73 UpdateCameraRotation(entity, dt);
74
75 // 5. Update shake effect
76 UpdateCameraShake(entity, dt);
77
78 // 6. Apply bounds constraints
79 ApplyCameraBounds(entity);
80 }
81 catch (const std::exception& e)
82 {
83 std::cerr << "CameraSystem Error for Entity " << entity << ": " << e.what() << "\n";
84 }
85 }
86}
87
88//-------------------------------------------------------------
90{
91 // Viewport updates could be handled here if needed
92 // For now, viewport management is delegated to RenderingSystem
93}
94
95//-------------------------------------------------------------
97{
98 // Check if camera already exists for this player
99 auto it = m_playerCameras.find(playerID);
100 if (it != m_playerCameras.end())
101 {
102 SYSTEM_LOG << "Camera already exists for player " << playerID << "\n";
103 return it->second;
104 }
105
106 // Create new entity
108
109 // Add Camera_data with default values
112 //cam.playerEntityID =
114 cam.position = Vector(0.f, 0.f, 0.f);
115 cam.zoom = 1.0f;
116 cam.targetZoom = 1.0f;
117 cam.currentZoomLevelIndex = 3; // Initialize to 1.0 (index 3)
118 cam.rotation = 0.0f;
119 cam.targetRotation = 0.0f;
120 cam.currentRotationLevel = 0; // Initialize to 0° (level 0)
121 cam.controlMode = CameraControlMode::Mode_Free;
122 cam.isActive = true;
123
124 // Get viewport for this player
125 SDL_FRect viewportRect;
126 if (ViewportManager::Get().GetViewRectForPlayer(playerID, viewportRect))
127 {
128 cam.viewportRect = viewportRect;
129 }
130 else
131 {
132 // Default to full screen if no specific viewport
133 cam.viewportRect = { 0.f, 0.f, (float)GameEngine::screenWidth, (float)GameEngine::screenHeight }; // default full screen
134 }
135
136 // Add CameraTarget_data
138 target.followTarget = false;
139 target.smoothFactor = 5.0f;
140 target.allowManualControl = true;
141 target.manualControlDecay = 2.0f;
142
143 // Add CameraEffects_data
145 effects.isShaking = false;
146 effects.shakeIntensity = 0.0f;
147 effects.shakeDuration = 0.0f;
148 effects.shakeTimeRemaining = 0.0f;
149
150 // Add CameraBounds_data
152 bounds.useBounds = false;
153 bounds.clampToViewport = true;
154
155 // Add CameraInputBinding_data
158 binding.useKeyboard = bindToKeyboard;
159
160 // Bind to keyboard if requested
161 if (bindToKeyboard)
162 {
164 }
165
166 // Register in player camera map
168
169 SYSTEM_LOG << "Created camera for player " << playerID << " (Entity " << cameraEntity << ")\n";
170
171 return cameraEntity;
172}
173
174//-------------------------------------------------------------
176{
177 auto it = m_playerCameras.find(playerID);
178 if (it != m_playerCameras.end())
179 {
180 World::Get().DestroyEntity(it->second);
181 m_playerCameras.erase(it);
182 SYSTEM_LOG << "Removed camera for player " << playerID << "\n";
183 }
184}
185
186//-------------------------------------------------------------
188{
189 auto it = m_playerCameras.find(playerID);
190 if (it != m_playerCameras.end())
191 {
192 return it->second;
193 }
194 return INVALID_ENTITY_ID;
195}
196
197//-------------------------------------------------------------
199{
201 return;
202
204 binding.useKeyboard = true;
205 // Note: playerId is preserved from camera creation; not overwritten here
206
208
209 SYSTEM_LOG << "Bound camera " << cameraEntity << " to keyboard\n";
210}
211
212//-------------------------------------------------------------
214{
216 return;
217
219 binding.useKeyboard = false;
220 binding.playerId = playerID;
221 binding.joystickId = joystickId;
222
223 SYSTEM_LOG << "Bound camera " << cameraEntity << " to joystick " << joystickId << " (Player " << playerID << ")\n";
224}
225
226//-------------------------------------------------------------
237
238//-------------------------------------------------------------
240{
242 return;
243
245 target.targetEntityID = targetEntity;
246 target.followTarget = true;
247
248 // Switch to follow mode
250 {
253 }
254
255 SYSTEM_LOG << "Camera " << cameraEntity << " now following entity " << targetEntity << "\n";
256}
257
258//-------------------------------------------------------------
277
278//-------------------------------------------------------------
280{
282 return;
283
285
286 // Reset input state
287 binding.inputDirection = Vector(0.f, 0.f, 0.f);
288 binding.rotationInput = 0.0f;
289 binding.zoomInput = 0.0f;
290 binding.resetRequested = false;
291
292 // Process input based on binding type
293 if (binding.useKeyboard)
294 {
296 }
297 else
298 {
300 }
301
302 // Apply input to camera
304 return;
305
307
308 // Apply manual movement (taking rotation into account)
309 if (binding.inputDirection.x != 0.0f || binding.inputDirection.y != 0.0f)
310 {
311 // Rotate input direction by camera rotation
312 float rotRad = cam.rotation * (float)(k_PI / 180.0);
313 float cosRot = std::cos(rotRad);
314 float sinRot = std::sin(rotRad);
315
316 float rotatedX = binding.inputDirection.x * cosRot - binding.inputDirection.y * sinRot;
317 float rotatedY = binding.inputDirection.x * sinRot + binding.inputDirection.y * cosRot;
318
319 cam.controlOffset.x += rotatedX * cam.manualMoveSpeed * dt;
320 cam.controlOffset.y += rotatedY * cam.manualMoveSpeed * dt;
321 }
322
323 // Apply zoom input with discrete levels
324 if (binding.zoomInput != 0.0f)
325 {
326 if (binding.zoomInput > 0.0f)
327 {
328 // Zoom in: go to next level
329 if (cam.currentZoomLevelIndex < (int)Camera_data::ZOOM_LEVEL_COUNT - 1)
330 {
331 cam.currentZoomLevelIndex++;
332 cam.targetZoom = Camera_data::ZOOM_LEVELS[cam.currentZoomLevelIndex];
333 SYSTEM_LOG << "Zoom in to level " << cam.targetZoom << "\n";
334 }
335 }
336 else
337 {
338 // Zoom out: go to previous level
339 if (cam.currentZoomLevelIndex > 0)
340 {
341 cam.currentZoomLevelIndex--;
342 cam.targetZoom = Camera_data::ZOOM_LEVELS[cam.currentZoomLevelIndex];
343 SYSTEM_LOG << "Zoom out to level " << cam.targetZoom << "\n";
344 }
345 }
346 }
347
348 // Apply rotation input with discrete levels (15° steps)
349 if (binding.rotationInput != 0.0f)
350 {
351 if (binding.rotationInput > 0.0f)
352 {
353 // Rotate clockwise (+15°)
354 cam.currentRotationLevel = (cam.currentRotationLevel + 1) % Camera_data::ROTATION_LEVELS;
355 cam.targetRotation = Camera_data::GetRotationFromLevel(cam.currentRotationLevel);
356 SYSTEM_LOG << "Rotate clockwise to " << cam.targetRotation << "°\n";
357 }
358 else
359 {
360 // Rotate counter-clockwise (-15°)
361 cam.currentRotationLevel = (cam.currentRotationLevel - 1 + Camera_data::ROTATION_LEVELS) % Camera_data::ROTATION_LEVELS;
362 cam.targetRotation = Camera_data::GetRotationFromLevel(cam.currentRotationLevel);
363 SYSTEM_LOG << "Rotate counter-clockwise to " << cam.targetRotation << "°\n";
364 }
365 }
366
367 // Handle reset
368 if (binding.resetRequested)
369 {
370 ResetCameraControls(entity);
371 }
372}
373
374//-------------------------------------------------------------
376{
378
379 // Directional input
380 Vector direction(0.f, 0.f, 0.f);
381
382 // Check diagonal keys FIRST (they combine up/down with left/right)
383 if (kb.IsKeyHeld(binding.key_up_left))
384 {
385 direction.x = -1.0f;
386 direction.y = -1.0f;
387 }
388 else if (kb.IsKeyHeld(binding.key_up_right))
389 {
390 direction.x = 1.0f;
391 direction.y = -1.0f;
392 }
393 else if (kb.IsKeyHeld(binding.key_down_left))
394 {
395 direction.x = -1.0f;
396 direction.y = 1.0f;
397 }
398 else if (kb.IsKeyHeld(binding.key_down_right))
399 {
400 direction.x = 1.0f;
401 direction.y = 1.0f;
402 }
403 else
404 {
405 // Cardinal directions (only if no diagonal is pressed)
406 if (kb.IsKeyHeld(binding.key_up))
407 direction.y -= 1.0f;
408 if (kb.IsKeyHeld(binding.key_down))
409 direction.y += 1.0f;
410 if (kb.IsKeyHeld(binding.key_left))
411 direction.x -= 1.0f;
412 if (kb.IsKeyHeld(binding.key_right))
413 direction.x += 1.0f;
414 }
415
416 // Normalize diagonal movement to prevent faster diagonal speed
417 if (direction.x != 0.0f && direction.y != 0.0f)
418 {
419 float length = std::sqrt(direction.x * direction.x + direction.y * direction.y);
420 direction.x /= length;
421 direction.y /= length;
422 }
423
424 const float fcameraspeed = 300.0f ; // Can be adjusted or made configurable
425 binding.inputDirection = direction * fcameraspeed * GameEngine::fDt;
426
427 // Rotation input with key press (not held) for discrete steps
428 if (kb.IsKeyPressed(binding.key_rotate_left))
429 binding.rotationInput = -1.0f;
430 if (kb.IsKeyPressed(binding.key_rotate_right))
431 binding.rotationInput = 1.0f;
432
433 // Zoom input with discrete levels (use IsKeyPressed for single-step)
434 if (kb.IsKeyPressed(binding.key_zoom_in))
435 binding.zoomInput = 1.0f;
436 if (kb.IsKeyPressed(binding.key_zoom_out))
437 binding.zoomInput = -1.0f;
438
439 // Reset input
440 if (kb.IsKeyPressed(binding.key_reset))
441 {
442 binding.resetRequested = true;
443 SYSTEM_LOG << "Camera reset requested (numpad 5)\n";
444 }
445}
446
447//-------------------------------------------------------------
449{
451
452 if (!joy.IsJoystickConnected(binding.joystickId))
453 return;
454
455 // Read right stick axes for camera movement
456 float axisX = joy.GetAxis(binding.joystickId, binding.axis_horizontal);
457 float axisY = joy.GetAxis(binding.joystickId, binding.axis_vertical);
458
459 // Apply deadzone
460 axisX = this->ApplyDeadzone(axisX, binding.deadzone);
461 axisY = this->ApplyDeadzone(axisY, binding.deadzone);
462
463 binding.inputDirection = Vector(axisX, axisY, 0.f);
464
465 // Read triggers for rotation with edge detection (for discrete steps)
466 float leftTrigger = joy.GetAxis(binding.joystickId, binding.trigger_left);
467 float rightTrigger = joy.GetAxis(binding.joystickId, binding.trigger_right);
468
469 bool leftTriggerPressed = (leftTrigger > binding.triggerThreshold);
470 bool rightTriggerPressed = (rightTrigger > binding.triggerThreshold);
471
472 // Only register rotation input on trigger press (not hold) for discrete steps
473 if (leftTriggerPressed && !binding.prevLeftTriggerPressed)
474 binding.rotationInput = -1.0f;
475 if (rightTriggerPressed && !binding.prevRightTriggerPressed)
476 binding.rotationInput = 1.0f;
477
478 // Update previous trigger state for next frame
479 binding.prevLeftTriggerPressed = leftTriggerPressed;
480 binding.prevRightTriggerPressed = rightTriggerPressed;
481
482 // Reset button
483 if (joy.IsButtonPressed(binding.joystickId, binding.button_reset))
484 {
485 binding.resetRequested = true;
486 SYSTEM_LOG << "Camera reset requested (joystick button " << binding.button_reset << ")\n";
487 }
488}
489
490//-------------------------------------------------------------
491float CameraSystem::ApplyDeadzone(float value, float deadzone)
492{
493 if (std::abs(value) < deadzone)
494 return 0.0f;
495
496 // Rescale from deadzone to 1.0
497 float sign = (value > 0.0f) ? 1.0f : -1.0f;
498 float magnitude = std::abs(value);
499 return sign * ((magnitude - deadzone) / (1.0f - deadzone));
500}
501
502//-------------------------------------------------------------
504{
506 return;
507
509
510 if (!target.followTarget)
511 return;
512
513 if (!World::Get().HasComponent<Camera_data>(entity))
514 return;
515
517
518 // Get target position
519 Vector targetPos(0.f, 0.f, 0.f);
520 bool hasValidTarget = false;
521
522 // Try ECS entity first
523 if (target.targetEntityID != INVALID_ENTITY_ID)
524 {
525 if (World::Get().HasComponent<Position_data>(target.targetEntityID))
526 {
529 hasValidTarget = true;
530 }
531 }
532
533 if (!hasValidTarget)
534 return;
535
536 // Apply follow offset
537 targetPos += target.followOffset;
538
539 // Smooth follow based on control mode
540 if (cam.controlMode == CameraControlMode::Mode_Follow)
541 {
542 // Strict follow: blend to target and reset manual offset
543 cam.position = vBlend(targetPos, cam.position, target.smoothFactor);
544
545 // Reset control offset
546 cam.controlOffset = Vector(0.f, 0.f, 0.f);
547 }
548 else if (cam.controlMode == CameraControlMode::Mode_FollowWithControl)
549 {
550 // Follow with manual control: blend to target but keep manual offset
551 cam.position = vBlend(targetPos, cam.position, target.smoothFactor);
552
553 // Decay manual control offset back towards zero if allowed
554 if (target.allowManualControl && target.manualControlDecay > 0.0f)
555 {
556 Vector desiredOffset = Vector(0.f, 0.f, 0.f);
557 cam.controlOffset = vBlend(desiredOffset, cam.controlOffset, target.manualControlDecay);
558
559 // Snap to zero when very close
560 if (cam.controlOffset.Length() < 0.1f)
561 {
562 cam.controlOffset = Vector(0.f, 0.f, 0.f);
563 }
564 }
565 }
566}
567
568//-------------------------------------------------------------
570{
572 return;
573
575
576 // Smooth interpolation towards target zoom
577 if (std::abs(cam.zoom - cam.targetZoom) > 0.01f)
578 {
579 cam.zoom += (cam.targetZoom - cam.zoom) * cam.zoomSpeed * dt;
580 }
581 else
582 {
583 // Snap when very close
584 cam.zoom = cam.targetZoom;
585 }
586}
587
588//-------------------------------------------------------------
590{
592 return;
593
595
596 // Handle wrap-around for rotation (shortest path)
597 float diff = cam.targetRotation - cam.rotation;
598
599 // Normalize difference to -180 to 180
600 while (diff > 180.0f) diff -= 360.0f;
601 while (diff < -180.0f) diff += 360.0f;
602
603 // Smooth interpolation towards target rotation
604 if (std::abs(diff) > 1.0f)
605 {
606 cam.rotation += diff * cam.rotationSpeed * dt;
607
608 // Wrap rotation to -360 to 360
609 while (cam.rotation > 360.0f) cam.rotation -= 360.0f;
610 while (cam.rotation < -360.0f) cam.rotation += 360.0f;
611 }
612 else
613 {
614 // Snap when very close
615 cam.rotation = cam.targetRotation;
616 }
617}
618
619//-------------------------------------------------------------
621{
623 return;
624
626
627 if (!effects.isShaking)
628 {
629 effects.shakeOffset = Vector(0.f, 0.f, 0.f);
630 return;
631 }
632
633 // Decrement shake time
634 effects.shakeTimeRemaining -= dt;
635
636 if (effects.shakeTimeRemaining <= 0.0f)
637 {
638 // Shake ended
639 effects.isShaking = false;
640 effects.shakeOffset = Vector(0.f, 0.f, 0.f);
641 effects.shakeTimeRemaining = 0.0f;
642 }
643 else
644 {
645 // Generate random shake offset
646 float randomX = shakeDist(gen) * effects.shakeIntensity;
647 float randomY = shakeDist(gen) * effects.shakeIntensity;
648 effects.shakeOffset = Vector(randomX, randomY, 0.f);
649 }
650}
651
652//-------------------------------------------------------------
654{
656 return;
657
659
660 if (!bounds.useBounds)
661 return;
662
663 if (!World::Get().HasComponent<Camera_data>(entity))
664 return;
665
667
668 // Calculate effective camera position (position + control offset)
669 Vector effectivePos = cam.position + cam.controlOffset;
670
671 if (bounds.clampToViewport)
672 {
673 // Clamp so that viewport stays within bounds
674 float halfViewW = cam.viewportRect.w / (2.0f * cam.zoom);
675 float halfViewH = cam.viewportRect.h / (2.0f * cam.zoom);
676
677 float minX = bounds.boundingBox.x + halfViewW;
678 float maxX = bounds.boundingBox.x + bounds.boundingBox.w - halfViewW;
679 float minY = bounds.boundingBox.y + halfViewH;
680 float maxY = bounds.boundingBox.y + bounds.boundingBox.h - halfViewH;
681
682 effectivePos.x = max(minX, std::min(maxX, effectivePos.x));
683 effectivePos.y = max(minY, std::min(maxY, effectivePos.y));
684 }
685 else
686 {
687 // Simple clamping of camera center
688 effectivePos.x = max(bounds.boundingBox.x, min(bounds.boundingBox.x + bounds.boundingBox.w, effectivePos.x));
689 effectivePos.y = std::max(bounds.boundingBox.y, min(bounds.boundingBox.y + bounds.boundingBox.h, effectivePos.y));
690 }
691
692 // Update control offset to reflect clamped position
693 cam.controlOffset = effectivePos - cam.position;
694}
695
696//-------------------------------------------------------------
698{
700 return;
701
703
704 // Reset all manual controls
705 cam.controlOffset = Vector(0.f, 0.f, 0.f);
706
707 // Reset zoom to 1.0 (index 3) using discrete levels
708 cam.currentZoomLevelIndex = 3; // Index 3 = 1.0
709 cam.zoom = 1.0f;
710 cam.targetZoom = 1.0f;
711
712 // Reset rotation to 0° (level 0) using discrete levels
713 cam.currentRotationLevel = 0;
714 cam.rotation = 0.0f;
715 cam.targetRotation = 0.0f;
716
717 // If camera has a target, re-enable following
719 {
721
722 if (target.targetEntityID != INVALID_ENTITY_ID)
723 {
724 // Re-enable target following
725 target.followTarget = true;
726 SYSTEM_LOG << "Camera " << entity << " resuming target follow\n";
727 }
728 }
729
730 // If in free mode, also reset position to origin
731 if (cam.controlMode == CameraControlMode::Mode_Free)
732 {
733 cam.position = Vector(0.f, 0.f, 0.f);
734 }
735
736 // Clear camera shake if active
738 {
740 effects.isShaking = false;
741 effects.shakeOffset = Vector(0.f, 0.f, 0.f);
742 effects.shakeTimeRemaining = 0.0f;
743 }
744
745 SYSTEM_LOG << "Camera " << entity << " controls reset (zoom=1.0, rotation=0.0, following="
746 << (World::Get().HasComponent<CameraTarget_data>(entity) &&
747 World::Get().GetComponent<CameraTarget_data>(entity).followTarget ? "true" : "false") << ")\n";
748}
749
750//-------------------------------------------------------------
752{
753 // Find the closest zoom level to current targetZoom and update index
754 int closestIndex = 0;
755 float minDiff = std::abs(Camera_data::ZOOM_LEVELS[0] - cam.targetZoom);
756
757 for (size_t i = 1; i < Camera_data::ZOOM_LEVEL_COUNT; i++)
758 {
759 float diff = std::abs(Camera_data::ZOOM_LEVELS[i] - cam.targetZoom);
760 if (diff < minDiff)
761 {
762 minDiff = diff;
763 closestIndex = static_cast<int>(i);
764 }
765 }
766
767 cam.currentZoomLevelIndex = closestIndex;
768}
769
770//-------------------------------------------------------------
772{
773 // Find camera for this player
774 auto it = m_playerCameras.find(playerID);
775 if (it == m_playerCameras.end())
776 return;
777
778 EntityID cameraEntity = it->second;
779
781 return;
782
784
785 SDL_Rect viewportRect = {
786 static_cast<int>(cam.viewportRect.x),
787 static_cast<int>(cam.viewportRect.y),
788 static_cast<int>(cam.viewportRect.w),
789 static_cast<int>(cam.viewportRect.h)
790 };
791
792 // Set viewport and clip rect for this camera
793 // NOTE: Caller is responsible for resetting clip rect with SDL_SetRenderClipRect(renderer, nullptr)
794 SDL_SetRenderViewport(renderer, &viewportRect);
795 SDL_SetRenderClipRect(renderer, &viewportRect);
796}
797
798//-------------------------------------------------------------
800{
801 // All camera events are now in the Camera domain
802 // Extract playerID from message
803 short playerID = -1;
804 if (msg.param1 >= 0)
805 playerID = static_cast<short>(msg.param1);
806
807 // Find or create camera for this player
810 {
811 // Auto-create ECS camera if event targets a player without one
812 camEntity = CreateCameraForPlayer(playerID, (playerID == -1)); // keyboard if -1
813 SYSTEM_LOG << "Auto-created ECS camera for player " << playerID << " (event-driven)\n";
814 }
815
817 return;
818
820
821 switch (msg.msg_type)
822 {
825 {
826 cam.position.x = msg.param1;
827 cam.position.y = msg.param2;
828 break;
829 }
831 {
832 cam.targetZoom = msg.param1;
833 cam.targetZoom = std::max(cam.minZoom, std::min(cam.maxZoom, cam.targetZoom));
834 // Sync discrete zoom level index to match programmatic zoom
836 break;
837 }
839 {
840 cam.targetRotation = msg.param1;
841 break;
842 }
844 {
846 break;
847 }
850 break;
853 break;
856 break;
858 {
859 if (msg.targetUid != INVALID_ENTITY_ID && World::Get().IsEntityValid(msg.targetUid))
860 {
862 }
863 break;
864 }
866 {
868 break;
869 }
871 {
873 {
875 effects.isShaking = true;
876 effects.shakeIntensity = msg.param1; // intensity
877 effects.shakeDuration = msg.param2; // duration
878 effects.shakeTimeRemaining = msg.param2;
879 }
880 break;
881 }
882 default:
883 break;
884 }
885}
Core ECS component definitions.
@ CameraType_Isometric
ComponentTypeID GetComponentTypeID_Static()
Definition ECS_Entity.h:56
std::uint64_t EntityID
Definition ECS_Entity.h:21
const EntityID INVALID_ENTITY_ID
Definition ECS_Entity.h:23
static std::uniform_real_distribution< float > shakeDist(-1.0f, 1.0f)
static std::mt19937 gen(rd())
static std::random_device rd
Core game engine class.
static SDL_Renderer * renderer
World and ECS Manager for Olympe Engine.
void BindCameraToJoystick(EntityID cameraEntity, short playerID, SDL_JoystickID joystickId)
EntityID GetCameraEntityForPlayer(short playerID)
EntityID CreateCameraForPlayer(short playerID, bool bindToKeyboard=false)
void BindCameraToKeyboard(EntityID cameraEntity)
void ProcessJoystickInput(EntityID entity, CameraInputBinding_data &binding)
void UpdateCameraFollow(EntityID entity, float dt)
void ClearCameraTarget(EntityID cameraEntity)
virtual void Process() override
void OnEvent(const Message &msg)
void ApplyCameraBounds(EntityID entity)
float ApplyDeadzone(float value, float deadzone)
void ApplyCameraToRenderer(SDL_Renderer *renderer, short playerID)
void SetCameraTarget_ECS(EntityID cameraEntity, EntityID targetEntity)
void UpdateCameraRotation(EntityID entity, float dt)
void ProcessKeyboardInput(EntityID entity, CameraInputBinding_data &binding)
void SyncZoomLevelIndex(Camera_data &cam)
void UnbindCameraKeyboard(EntityID cameraEntity)
std::unordered_map< short, EntityID > m_playerCameras
void ResetCameraControls(EntityID entity)
virtual void Render() override
void UpdateCameraInput(EntityID entity, float dt)
void RemoveCameraForPlayer(short playerID)
EntityID m_defaultKeyboardCamera
void UpdateCameraShake(EntityID entity, float dt)
void UpdateCameraZoom(EntityID entity, float dt)
std::set< EntityID > m_entities
Definition ECS_Systems.h:42
ComponentSignature requiredSignature
Definition ECS_Systems.h:39
static int screenWidth
Screen width in pixels.
Definition GameEngine.h:123
static float fDt
Delta time between frames in seconds.
Definition GameEngine.h:120
static int screenHeight
Screen height in pixels.
Definition GameEngine.h:126
static JoystickManager & Get()
static KeyboardManager & Get()
float y
Definition vector.h:27
float x
Definition vector.h:27
static ViewportManager & Get()
static World & Get()
Get singleton instance (short form)
Definition World.h:232
T & AddComponent(EntityID entity, Args &&... args)
Definition World.h:393
bool HasComponent(EntityID entity) const
Definition World.h:451
bool IsEntityValid(EntityID entity) const
Definition World.h:376
T & GetComponent(EntityID entity)
Definition World.h:438
EntityID CreateEntity()
Definition World.cpp:225
void DestroyEntity(EntityID entity)
Definition World.cpp:255
static constexpr int ROTATION_LEVELS
static constexpr float ZOOM_LEVELS[]
CameraControlMode controlMode
Vector controlOffset
static constexpr float GetRotationFromLevel(int level)
static constexpr size_t ZOOM_LEVEL_COUNT
Position component for spatial location.
Vector position
2D/3D position vector
@ Olympe_EventType_Camera_Mode_2D
@ Olympe_EventType_Camera_RotateTo
@ Olympe_EventType_Camera_Teleport
@ Olympe_EventType_Camera_MoveToPosition
@ Olympe_EventType_Camera_ZoomTo
@ Olympe_EventType_Camera_Mode_2_5D
@ Olympe_EventType_Camera_Reset
@ Olympe_EventType_Camera_Target_Unfollow
@ Olympe_EventType_Camera_Target_Follow
@ Olympe_EventType_Camera_Mode_Isometric
@ Olympe_EventType_Camera_Shake
constexpr double k_PI
#define SYSTEM_LOG
Vector vBlend(Vector &_v1, Vector &_v2, float _fc)
Definition vector.cpp:36