From d87fcb104e19cad852000f10db1c1aa36ea4f525 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 18 Nov 2025 12:27:22 +0000 Subject: [PATCH] Add Unity port of AI for Oceans Complete migration of the JavaScript/React web app to Unity engine: Core Systems: - GameManager singleton for state management - SceneController for mode/scene transitions - Event-driven architecture for UI updates Classification System: - NaiveKNNClassifier replacing TensorFlow KNN - NaiveSVMClassifier for word modes - Simple attribute-based classification (no ML dependencies) Fish Generation: - Procedural fish generation with 19 bodies, 18 eyes, 15 mouths - Color tinting system for sprite components - FishRenderer for sprite assembly Animation: - FishAnimator with bobbing (sine wave) motion - S-curve easing for scanning pauses - Smooth scene transitions UI Components: - TrainingUI with Yes/No buttons - PredictionUI with colored confidence frames - PondUI for results visualization - WordSelectionUI for short/long modes - GuideUI with typing text effect - MainMenuUI for mode selection - ConfirmationDialog component - AIBot with expression states Audio: - SoundManager with category-based playback - Support for yes/no/sort sounds All 5 game modes supported: - Fish vs Trash - Creatures vs Trash Demo - Creatures vs Trash - Short (6 adjectives) - Long (15 adjectives) Assets copied from original project to Unity sprite/audio folders. --- Unity/AIForOceans/Assets/Audio/no/no_1.mp3 | Bin 0 -> 2524 bytes Unity/AIForOceans/Assets/Audio/no/no_10.mp3 | Bin 0 -> 2524 bytes Unity/AIForOceans/Assets/Audio/no/no_2.mp3 | Bin 0 -> 2524 bytes Unity/AIForOceans/Assets/Audio/no/no_3.mp3 | Bin 0 -> 2524 bytes Unity/AIForOceans/Assets/Audio/no/no_4.mp3 | Bin 0 -> 1948 bytes Unity/AIForOceans/Assets/Audio/no/no_5.mp3 | Bin 0 -> 2524 bytes Unity/AIForOceans/Assets/Audio/no/no_6.mp3 | Bin 0 -> 2524 bytes Unity/AIForOceans/Assets/Audio/no/no_7.mp3 | Bin 0 -> 2524 bytes Unity/AIForOceans/Assets/Audio/no/no_8.mp3 | Bin 0 -> 2524 bytes Unity/AIForOceans/Assets/Audio/no/no_9.mp3 | Bin 0 -> 2524 bytes .../Assets/Audio/other/other_1.mp3 | Bin 0 -> 4252 bytes .../Assets/Audio/other/other_2.mp3 | Bin 0 -> 5404 bytes .../Assets/Audio/other/other_3.mp3 | Bin 0 -> 5404 bytes .../Assets/Audio/other/other_4.mp3 | Bin 0 -> 5404 bytes .../Assets/Audio/sortno/sortno_1.mp3 | Bin 0 -> 3100 bytes .../Assets/Audio/sortyes/sortyes_1.mp3 | Bin 0 -> 10588 bytes .../Assets/Audio/sortyes/sortyes_2.mp3 | Bin 0 -> 6556 bytes .../Assets/Audio/sortyes/sortyes_3.mp3 | Bin 0 -> 8860 bytes Unity/AIForOceans/Assets/Audio/yes/yes_1.mp3 | Bin 0 -> 2524 bytes Unity/AIForOceans/Assets/Audio/yes/yes_10.mp3 | Bin 0 -> 2524 bytes Unity/AIForOceans/Assets/Audio/yes/yes_2.mp3 | Bin 0 -> 2524 bytes Unity/AIForOceans/Assets/Audio/yes/yes_3.mp3 | Bin 0 -> 2524 bytes Unity/AIForOceans/Assets/Audio/yes/yes_4.mp3 | Bin 0 -> 2524 bytes Unity/AIForOceans/Assets/Audio/yes/yes_5.mp3 | Bin 0 -> 3100 bytes Unity/AIForOceans/Assets/Audio/yes/yes_6.mp3 | Bin 0 -> 2524 bytes Unity/AIForOceans/Assets/Audio/yes/yes_7.mp3 | Bin 0 -> 2524 bytes Unity/AIForOceans/Assets/Audio/yes/yes_8.mp3 | Bin 0 -> 2524 bytes Unity/AIForOceans/Assets/Audio/yes/yes_9.mp3 | Bin 0 -> 2524 bytes .../Assets/Scripts/AIForOceans.asmdef | 16 + .../Assets/Scripts/Animation/FishAnimator.cs | 165 ++++++ .../Assets/Scripts/Animation/FishRenderer.cs | 160 +++++ .../Assets/Scripts/Audio/SoundManager.cs | 219 +++++++ .../Assets/Scripts/Classification/ITrainer.cs | 33 ++ .../Classification/NaiveKNNClassifier.cs | 138 +++++ .../Classification/NaiveSVMClassifier.cs | 247 ++++++++ .../Assets/Scripts/Core/GameConstants.cs | 109 ++++ .../Assets/Scripts/Core/GameInitializer.cs | 52 ++ .../Assets/Scripts/Core/GameManager.cs | 256 ++++++++ .../Assets/Scripts/Core/GameState.cs | 93 +++ .../Assets/Scripts/Core/SceneController.cs | 168 ++++++ .../Assets/Scripts/Data/CreatureRenderer.cs | 80 +++ .../Assets/Scripts/Data/OceanGenerator.cs | 143 +++++ .../Assets/Scripts/Data/OceanObjectData.cs | 219 +++++++ .../Scenes/PredictionSceneController.cs | 199 +++++++ .../Scripts/Scenes/TrainingSceneController.cs | 186 ++++++ Unity/AIForOceans/Assets/Scripts/UI/AIBot.cs | 153 +++++ .../Assets/Scripts/UI/ConfirmationDialog.cs | 133 +++++ .../Assets/Scripts/UI/GameButton.cs | 166 ++++++ .../AIForOceans/Assets/Scripts/UI/GuideUI.cs | 229 ++++++++ .../Assets/Scripts/UI/MainMenuUI.cs | 121 ++++ Unity/AIForOceans/Assets/Scripts/UI/PondUI.cs | 218 +++++++ .../Assets/Scripts/UI/PredictionUI.cs | 146 +++++ .../Assets/Scripts/UI/TrainingUI.cs | 144 +++++ .../Assets/Scripts/UI/WordSelectionUI.cs | 132 +++++ .../Assets/Scripts/Utils/BackgroundManager.cs | 81 +++ .../Assets/Scripts/Utils/Localization.cs | 136 +++++ .../Assets/Scripts/Utils/ScreenScaler.cs | 63 ++ .../Assets/Sprites/Creatures/Crab.png | Bin 0 -> 3586 bytes .../Assets/Sprites/Creatures/Dolphin.png | Bin 0 -> 1743 bytes .../Assets/Sprites/Creatures/Jellyfish.png | Bin 0 -> 2785 bytes .../Assets/Sprites/Creatures/Octopus.png | Bin 0 -> 5390 bytes .../Assets/Sprites/Creatures/Otter.png | Bin 0 -> 2312 bytes .../Assets/Sprites/Creatures/Seahorse.png | Bin 0 -> 2292 bytes .../Assets/Sprites/Creatures/Snail.png | Bin 0 -> 2043 bytes .../Assets/Sprites/Creatures/Starfish.png | Bin 0 -> 2342 bytes .../Assets/Sprites/Creatures/Turtle.png | Bin 0 -> 2317 bytes .../Assets/Sprites/Creatures/Whale.png | Bin 0 -> 1931 bytes .../Assets/Sprites/Fish/body/circle_1.png | Bin 0 -> 689 bytes .../Assets/Sprites/Fish/body/circle_2.png | Bin 0 -> 646 bytes .../Assets/Sprites/Fish/body/diamond1.png | Bin 0 -> 474 bytes .../Assets/Sprites/Fish/body/other_1.png | Bin 0 -> 712 bytes .../Assets/Sprites/Fish/body/other_2.png | Bin 0 -> 680 bytes .../Assets/Sprites/Fish/body/other_3.png | Bin 0 -> 872 bytes .../Assets/Sprites/Fish/body/other_4.png | Bin 0 -> 839 bytes .../Assets/Sprites/Fish/body/other_5.png | Bin 0 -> 817 bytes .../Assets/Sprites/Fish/body/oval_1.png | Bin 0 -> 745 bytes .../Assets/Sprites/Fish/body/oval_2.png | Bin 0 -> 547 bytes .../Assets/Sprites/Fish/body/oval_4.png | Bin 0 -> 670 bytes .../Assets/Sprites/Fish/body/rectangle_1.png | Bin 0 -> 252 bytes .../Assets/Sprites/Fish/body/rectangle_2.png | Bin 0 -> 524 bytes .../Assets/Sprites/Fish/body/rectangle_3.png | Bin 0 -> 340 bytes .../Assets/Sprites/Fish/body/s1.png | Bin 0 -> 815 bytes .../Assets/Sprites/Fish/body/star1.png | Bin 0 -> 1147 bytes .../Assets/Sprites/Fish/body/triangle2.png | Bin 0 -> 695 bytes .../Assets/Sprites/Fish/body/triangle3.png | Bin 0 -> 775 bytes .../Assets/Sprites/Fish/body/triangle_1.png | Bin 0 -> 825 bytes .../Sprites/Fish/dorsalFin/dorsal_fin_1.png | Bin 0 -> 285 bytes .../Sprites/Fish/dorsalFin/dorsal_fin_10.png | Bin 0 -> 366 bytes .../Sprites/Fish/dorsalFin/dorsal_fin_11.png | Bin 0 -> 246 bytes .../Sprites/Fish/dorsalFin/dorsal_fin_12.png | Bin 0 -> 496 bytes .../Sprites/Fish/dorsalFin/dorsal_fin_13.png | Bin 0 -> 259 bytes .../Sprites/Fish/dorsalFin/dorsal_fin_14.png | Bin 0 -> 307 bytes .../Sprites/Fish/dorsalFin/dorsal_fin_15.png | Bin 0 -> 350 bytes .../Sprites/Fish/dorsalFin/dorsal_fin_16.png | Bin 0 -> 291 bytes .../Sprites/Fish/dorsalFin/dorsal_fin_17.png | Bin 0 -> 372 bytes .../Sprites/Fish/dorsalFin/dorsal_fin_2.png | Bin 0 -> 391 bytes .../Sprites/Fish/dorsalFin/dorsal_fin_3.png | Bin 0 -> 386 bytes .../Sprites/Fish/dorsalFin/dorsal_fin_4.png | Bin 0 -> 287 bytes .../Sprites/Fish/dorsalFin/dorsal_fin_5.png | Bin 0 -> 424 bytes .../Sprites/Fish/dorsalFin/dorsal_fin_6.png | Bin 0 -> 411 bytes .../Sprites/Fish/dorsalFin/dorsal_fin_7.png | Bin 0 -> 272 bytes .../Sprites/Fish/dorsalFin/dorsal_fin_8.png | Bin 0 -> 223 bytes .../Sprites/Fish/dorsalFin/dorsal_fin_9.png | Bin 0 -> 430 bytes .../Sprites/Fish/eyes/eyebrow_raise_1.png | Bin 0 -> 419 bytes .../Assets/Sprites/Fish/eyes/eyes1.png | Bin 0 -> 311 bytes .../Assets/Sprites/Fish/eyes/eyes10.png | Bin 0 -> 445 bytes .../Assets/Sprites/Fish/eyes/eyes11.png | Bin 0 -> 387 bytes .../Assets/Sprites/Fish/eyes/eyes13.png | Bin 0 -> 305 bytes .../Assets/Sprites/Fish/eyes/eyes14.png | Bin 0 -> 190 bytes .../Assets/Sprites/Fish/eyes/eyes16.png | Bin 0 -> 472 bytes .../Assets/Sprites/Fish/eyes/eyes17.png | Bin 0 -> 427 bytes .../Assets/Sprites/Fish/eyes/eyes18.png | Bin 0 -> 547 bytes .../Assets/Sprites/Fish/eyes/eyes19.png | Bin 0 -> 628 bytes .../Assets/Sprites/Fish/eyes/eyes2.png | Bin 0 -> 148 bytes .../Assets/Sprites/Fish/eyes/eyes3.png | Bin 0 -> 286 bytes .../Assets/Sprites/Fish/eyes/eyes4.png | Bin 0 -> 477 bytes .../Assets/Sprites/Fish/eyes/eyes5.png | Bin 0 -> 346 bytes .../Assets/Sprites/Fish/eyes/eyes6.png | Bin 0 -> 469 bytes .../Assets/Sprites/Fish/eyes/eyes7.png | Bin 0 -> 318 bytes .../Assets/Sprites/Fish/eyes/eyes9.png | Bin 0 -> 485 bytes .../Sprites/Fish/guideFish/guideFish1.png | Bin 0 -> 2460 bytes .../Assets/Sprites/Fish/mouth/mouth1.png | Bin 0 -> 213 bytes .../Assets/Sprites/Fish/mouth/mouth10.png | Bin 0 -> 400 bytes .../Assets/Sprites/Fish/mouth/mouth11.png | Bin 0 -> 348 bytes .../Assets/Sprites/Fish/mouth/mouth12.png | Bin 0 -> 282 bytes .../Assets/Sprites/Fish/mouth/mouth13.png | Bin 0 -> 361 bytes .../Assets/Sprites/Fish/mouth/mouth15.png | Bin 0 -> 159 bytes .../Assets/Sprites/Fish/mouth/mouth17.png | Bin 0 -> 407 bytes .../Assets/Sprites/Fish/mouth/mouth2.png | Bin 0 -> 662 bytes .../Assets/Sprites/Fish/mouth/mouth3.png | Bin 0 -> 404 bytes .../Assets/Sprites/Fish/mouth/mouth4.png | Bin 0 -> 520 bytes .../Assets/Sprites/Fish/mouth/mouth5.png | Bin 0 -> 250 bytes .../Assets/Sprites/Fish/mouth/mouth6.png | Bin 0 -> 373 bytes .../Assets/Sprites/Fish/mouth/mouth7.png | Bin 0 -> 815 bytes .../Assets/Sprites/Fish/mouth/mouth8.png | Bin 0 -> 539 bytes .../Assets/Sprites/Fish/mouth/mouth9.png | Bin 0 -> 245 bytes .../Fish/pectoralFin/pectoral_fin_1.png | Bin 0 -> 238 bytes .../Fish/pectoralFin/pectoral_fin_10.png | Bin 0 -> 222 bytes .../Fish/pectoralFin/pectoral_fin_11.png | Bin 0 -> 313 bytes .../Fish/pectoralFin/pectoral_fin_12.png | Bin 0 -> 238 bytes .../Fish/pectoralFin/pectoral_fin_13.png | Bin 0 -> 221 bytes .../Fish/pectoralFin/pectoral_fin_14.png | Bin 0 -> 276 bytes .../Fish/pectoralFin/pectoral_fin_15.png | Bin 0 -> 287 bytes .../Fish/pectoralFin/pectoral_fin_16.png | Bin 0 -> 231 bytes .../Fish/pectoralFin/pectoral_fin_17.png | Bin 0 -> 234 bytes .../Fish/pectoralFin/pectoral_fin_2.png | Bin 0 -> 240 bytes .../Fish/pectoralFin/pectoral_fin_3.png | Bin 0 -> 193 bytes .../Fish/pectoralFin/pectoral_fin_4.png | Bin 0 -> 275 bytes .../Fish/pectoralFin/pectoral_fin_5.png | Bin 0 -> 311 bytes .../Fish/pectoralFin/pectoral_fin_6.png | Bin 0 -> 246 bytes .../Fish/pectoralFin/pectoral_fin_7.png | Bin 0 -> 259 bytes .../Fish/pectoralFin/pectoral_fin_8.png | Bin 0 -> 196 bytes .../Fish/pectoralFin/pectoral_fin_9.png | Bin 0 -> 406 bytes .../Assets/Sprites/Fish/scales/scales10.png | Bin 0 -> 143 bytes .../Assets/Sprites/Fish/scales/scales11.png | Bin 0 -> 220 bytes .../Assets/Sprites/Fish/scales/scales12.png | Bin 0 -> 430 bytes .../Assets/Sprites/Fish/scales/scales5.png | Bin 0 -> 189 bytes .../Assets/Sprites/Fish/scales/scales6.png | Bin 0 -> 224 bytes .../Assets/Sprites/Fish/scales/scales7.png | Bin 0 -> 243 bytes .../Assets/Sprites/Fish/scales/scales8.png | Bin 0 -> 192 bytes .../Assets/Sprites/Fish/scales/scales9.png | Bin 0 -> 182 bytes .../Assets/Sprites/Fish/tailFin/tail_1.png | Bin 0 -> 420 bytes .../Assets/Sprites/Fish/tailFin/tail_10.png | Bin 0 -> 402 bytes .../Assets/Sprites/Fish/tailFin/tail_11.png | Bin 0 -> 279 bytes .../Assets/Sprites/Fish/tailFin/tail_12.png | Bin 0 -> 402 bytes .../Assets/Sprites/Fish/tailFin/tail_13.png | Bin 0 -> 294 bytes .../Assets/Sprites/Fish/tailFin/tail_14.png | Bin 0 -> 317 bytes .../Assets/Sprites/Fish/tailFin/tail_15.png | Bin 0 -> 353 bytes .../Assets/Sprites/Fish/tailFin/tail_16.png | Bin 0 -> 386 bytes .../Assets/Sprites/Fish/tailFin/tail_17.png | Bin 0 -> 396 bytes .../Assets/Sprites/Fish/tailFin/tail_2.png | Bin 0 -> 330 bytes .../Assets/Sprites/Fish/tailFin/tail_3.png | Bin 0 -> 347 bytes .../Assets/Sprites/Fish/tailFin/tail_4.png | Bin 0 -> 548 bytes .../Assets/Sprites/Fish/tailFin/tail_5.png | Bin 0 -> 290 bytes .../Assets/Sprites/Fish/tailFin/tail_6.png | Bin 0 -> 298 bytes .../Assets/Sprites/Fish/tailFin/tail_7.png | Bin 0 -> 364 bytes .../Assets/Sprites/Fish/tailFin/tail_8.png | Bin 0 -> 385 bytes .../Assets/Sprites/Fish/tailFin/tail_9.png | Bin 0 -> 275 bytes .../Assets/Sprites/Trash/Trash_6pack.png | Bin 0 -> 3000 bytes .../Assets/Sprites/Trash/Trash_Apple.png | Bin 0 -> 2485 bytes .../Assets/Sprites/Trash/Trash_Banana.png | Bin 0 -> 1850 bytes .../Assets/Sprites/Trash/Trash_Battery.png | Bin 0 -> 388 bytes .../Assets/Sprites/Trash/Trash_Bottle.png | Bin 0 -> 1028 bytes .../Assets/Sprites/Trash/Trash_Bulb.png | Bin 0 -> 2200 bytes .../Assets/Sprites/Trash/Trash_Can.png | Bin 0 -> 3379 bytes .../Assets/Sprites/Trash/Trash_Coffee.png | Bin 0 -> 1584 bytes .../Assets/Sprites/Trash/Trash_Fork.png | Bin 0 -> 1196 bytes .../Assets/Sprites/Trash/Trash_Laundry.png | Bin 0 -> 1445 bytes .../Assets/Sprites/Trash/Trash_Sock.png | Bin 0 -> 1239 bytes .../Assets/Sprites/Trash/Trash_Soda.png | Bin 0 -> 947 bytes .../Assets/Sprites/Trash/Trash_Tire.png | Bin 0 -> 4964 bytes .../Assets/Sprites/Trash/Trash_Wing.png | Bin 0 -> 1609 bytes .../Assets/Sprites/UI/ai-bot-body.png | Bin 0 -> 10545 bytes .../Assets/Sprites/UI/ai-bot-closed.png | Bin 0 -> 8416 bytes .../Assets/Sprites/UI/ai-bot-head.png | Bin 0 -> 2097 bytes .../Assets/Sprites/UI/ai-bot-no.png | Bin 0 -> 10915 bytes .../Assets/Sprites/UI/ai-bot-yes.png | Bin 0 -> 11619 bytes .../Assets/Sprites/UI/arrow-down.png | Bin 0 -> 667 bytes .../Assets/Sprites/UI/ban-icon.png | Bin 0 -> 714 bytes .../Sprites/UI/blue-prediction-frame.png | Bin 0 -> 11308 bytes .../Assets/Sprites/UI/blue-scanner.png | Bin 0 -> 144331 bytes .../Assets/Sprites/UI/bottle-large.png | Bin 0 -> 1660 bytes .../Assets/Sprites/UI/can-large.png | Bin 0 -> 5174 bytes .../Assets/Sprites/UI/checkmark-icon.png | Bin 0 -> 580 bytes .../Sprites/UI/green-prediction-frame.png | Bin 0 -> 11917 bytes .../Assets/Sprites/UI/green-scanner.png | Bin 0 -> 150340 bytes .../Assets/Sprites/UI/lab-background.png | Bin 0 -> 314581 bytes .../Assets/Sprites/UI/polaroid-frame.png | Bin 0 -> 7783 bytes .../Assets/Sprites/UI/polaroid-icon.png | Bin 0 -> 140 bytes .../Assets/Sprites/UI/question-icon.png | Bin 0 -> 3104 bytes .../Sprites/UI/red-prediction-frame.png | Bin 0 -> 7871 bytes .../Assets/Sprites/UI/red-scanner.png | Bin 0 -> 150330 bytes .../Assets/Sprites/UI/seahorse-large.png | Bin 0 -> 4399 bytes .../Assets/Sprites/UI/snail-large.png | Bin 0 -> 20946 bytes .../Assets/Sprites/UI/turtle-large.png | Bin 0 -> 4404 bytes .../Assets/Sprites/UI/water-background.png | Bin 0 -> 371364 bytes .../ProjectSettings/ProjectSettings.asset | 556 ++++++++++++++++++ Unity/AIForOceans/README.md | 145 +++++ 218 files changed, 4906 insertions(+) create mode 100755 Unity/AIForOceans/Assets/Audio/no/no_1.mp3 create mode 100755 Unity/AIForOceans/Assets/Audio/no/no_10.mp3 create mode 100755 Unity/AIForOceans/Assets/Audio/no/no_2.mp3 create mode 100755 Unity/AIForOceans/Assets/Audio/no/no_3.mp3 create mode 100755 Unity/AIForOceans/Assets/Audio/no/no_4.mp3 create mode 100755 Unity/AIForOceans/Assets/Audio/no/no_5.mp3 create mode 100755 Unity/AIForOceans/Assets/Audio/no/no_6.mp3 create mode 100755 Unity/AIForOceans/Assets/Audio/no/no_7.mp3 create mode 100755 Unity/AIForOceans/Assets/Audio/no/no_8.mp3 create mode 100755 Unity/AIForOceans/Assets/Audio/no/no_9.mp3 create mode 100755 Unity/AIForOceans/Assets/Audio/other/other_1.mp3 create mode 100755 Unity/AIForOceans/Assets/Audio/other/other_2.mp3 create mode 100755 Unity/AIForOceans/Assets/Audio/other/other_3.mp3 create mode 100755 Unity/AIForOceans/Assets/Audio/other/other_4.mp3 create mode 100644 Unity/AIForOceans/Assets/Audio/sortno/sortno_1.mp3 create mode 100644 Unity/AIForOceans/Assets/Audio/sortyes/sortyes_1.mp3 create mode 100644 Unity/AIForOceans/Assets/Audio/sortyes/sortyes_2.mp3 create mode 100644 Unity/AIForOceans/Assets/Audio/sortyes/sortyes_3.mp3 create mode 100755 Unity/AIForOceans/Assets/Audio/yes/yes_1.mp3 create mode 100755 Unity/AIForOceans/Assets/Audio/yes/yes_10.mp3 create mode 100755 Unity/AIForOceans/Assets/Audio/yes/yes_2.mp3 create mode 100755 Unity/AIForOceans/Assets/Audio/yes/yes_3.mp3 create mode 100755 Unity/AIForOceans/Assets/Audio/yes/yes_4.mp3 create mode 100755 Unity/AIForOceans/Assets/Audio/yes/yes_5.mp3 create mode 100755 Unity/AIForOceans/Assets/Audio/yes/yes_6.mp3 create mode 100755 Unity/AIForOceans/Assets/Audio/yes/yes_7.mp3 create mode 100755 Unity/AIForOceans/Assets/Audio/yes/yes_8.mp3 create mode 100755 Unity/AIForOceans/Assets/Audio/yes/yes_9.mp3 create mode 100644 Unity/AIForOceans/Assets/Scripts/AIForOceans.asmdef create mode 100644 Unity/AIForOceans/Assets/Scripts/Animation/FishAnimator.cs create mode 100644 Unity/AIForOceans/Assets/Scripts/Animation/FishRenderer.cs create mode 100644 Unity/AIForOceans/Assets/Scripts/Audio/SoundManager.cs create mode 100644 Unity/AIForOceans/Assets/Scripts/Classification/ITrainer.cs create mode 100644 Unity/AIForOceans/Assets/Scripts/Classification/NaiveKNNClassifier.cs create mode 100644 Unity/AIForOceans/Assets/Scripts/Classification/NaiveSVMClassifier.cs create mode 100644 Unity/AIForOceans/Assets/Scripts/Core/GameConstants.cs create mode 100644 Unity/AIForOceans/Assets/Scripts/Core/GameInitializer.cs create mode 100644 Unity/AIForOceans/Assets/Scripts/Core/GameManager.cs create mode 100644 Unity/AIForOceans/Assets/Scripts/Core/GameState.cs create mode 100644 Unity/AIForOceans/Assets/Scripts/Core/SceneController.cs create mode 100644 Unity/AIForOceans/Assets/Scripts/Data/CreatureRenderer.cs create mode 100644 Unity/AIForOceans/Assets/Scripts/Data/OceanGenerator.cs create mode 100644 Unity/AIForOceans/Assets/Scripts/Data/OceanObjectData.cs create mode 100644 Unity/AIForOceans/Assets/Scripts/Scenes/PredictionSceneController.cs create mode 100644 Unity/AIForOceans/Assets/Scripts/Scenes/TrainingSceneController.cs create mode 100644 Unity/AIForOceans/Assets/Scripts/UI/AIBot.cs create mode 100644 Unity/AIForOceans/Assets/Scripts/UI/ConfirmationDialog.cs create mode 100644 Unity/AIForOceans/Assets/Scripts/UI/GameButton.cs create mode 100644 Unity/AIForOceans/Assets/Scripts/UI/GuideUI.cs create mode 100644 Unity/AIForOceans/Assets/Scripts/UI/MainMenuUI.cs create mode 100644 Unity/AIForOceans/Assets/Scripts/UI/PondUI.cs create mode 100644 Unity/AIForOceans/Assets/Scripts/UI/PredictionUI.cs create mode 100644 Unity/AIForOceans/Assets/Scripts/UI/TrainingUI.cs create mode 100644 Unity/AIForOceans/Assets/Scripts/UI/WordSelectionUI.cs create mode 100644 Unity/AIForOceans/Assets/Scripts/Utils/BackgroundManager.cs create mode 100644 Unity/AIForOceans/Assets/Scripts/Utils/Localization.cs create mode 100644 Unity/AIForOceans/Assets/Scripts/Utils/ScreenScaler.cs create mode 100644 Unity/AIForOceans/Assets/Sprites/Creatures/Crab.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Creatures/Dolphin.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Creatures/Jellyfish.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Creatures/Octopus.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Creatures/Otter.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Creatures/Seahorse.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Creatures/Snail.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Creatures/Starfish.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Creatures/Turtle.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Creatures/Whale.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/body/circle_1.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/body/circle_2.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/body/diamond1.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/body/other_1.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/body/other_2.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/body/other_3.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/body/other_4.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/body/other_5.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/body/oval_1.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/body/oval_2.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/body/oval_4.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/body/rectangle_1.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/body/rectangle_2.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/body/rectangle_3.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/body/s1.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/body/star1.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/body/triangle2.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/body/triangle3.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/body/triangle_1.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/dorsalFin/dorsal_fin_1.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/dorsalFin/dorsal_fin_10.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/dorsalFin/dorsal_fin_11.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/dorsalFin/dorsal_fin_12.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/dorsalFin/dorsal_fin_13.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/dorsalFin/dorsal_fin_14.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/dorsalFin/dorsal_fin_15.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/dorsalFin/dorsal_fin_16.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/dorsalFin/dorsal_fin_17.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/dorsalFin/dorsal_fin_2.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/dorsalFin/dorsal_fin_3.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/dorsalFin/dorsal_fin_4.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/dorsalFin/dorsal_fin_5.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/dorsalFin/dorsal_fin_6.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/dorsalFin/dorsal_fin_7.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/dorsalFin/dorsal_fin_8.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/dorsalFin/dorsal_fin_9.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/eyes/eyebrow_raise_1.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/eyes/eyes1.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/eyes/eyes10.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/eyes/eyes11.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/eyes/eyes13.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/eyes/eyes14.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/eyes/eyes16.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/eyes/eyes17.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/eyes/eyes18.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/eyes/eyes19.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/eyes/eyes2.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/eyes/eyes3.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/eyes/eyes4.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/eyes/eyes5.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/eyes/eyes6.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/eyes/eyes7.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/eyes/eyes9.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/guideFish/guideFish1.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/mouth/mouth1.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/mouth/mouth10.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/mouth/mouth11.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/mouth/mouth12.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/mouth/mouth13.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/mouth/mouth15.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/mouth/mouth17.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/mouth/mouth2.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/mouth/mouth3.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/mouth/mouth4.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/mouth/mouth5.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/mouth/mouth6.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/mouth/mouth7.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/mouth/mouth8.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/mouth/mouth9.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/pectoralFin/pectoral_fin_1.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/pectoralFin/pectoral_fin_10.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/pectoralFin/pectoral_fin_11.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/pectoralFin/pectoral_fin_12.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/pectoralFin/pectoral_fin_13.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/pectoralFin/pectoral_fin_14.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/pectoralFin/pectoral_fin_15.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/pectoralFin/pectoral_fin_16.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/pectoralFin/pectoral_fin_17.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/pectoralFin/pectoral_fin_2.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/pectoralFin/pectoral_fin_3.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/pectoralFin/pectoral_fin_4.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/pectoralFin/pectoral_fin_5.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/pectoralFin/pectoral_fin_6.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/pectoralFin/pectoral_fin_7.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/pectoralFin/pectoral_fin_8.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/pectoralFin/pectoral_fin_9.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/scales/scales10.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/scales/scales11.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/scales/scales12.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/scales/scales5.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/scales/scales6.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/scales/scales7.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/scales/scales8.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/scales/scales9.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/tailFin/tail_1.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/tailFin/tail_10.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/tailFin/tail_11.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/tailFin/tail_12.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/tailFin/tail_13.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/tailFin/tail_14.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/tailFin/tail_15.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/tailFin/tail_16.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/tailFin/tail_17.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/tailFin/tail_2.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/tailFin/tail_3.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/tailFin/tail_4.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/tailFin/tail_5.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/tailFin/tail_6.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/tailFin/tail_7.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/tailFin/tail_8.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Fish/tailFin/tail_9.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Trash/Trash_6pack.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Trash/Trash_Apple.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Trash/Trash_Banana.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Trash/Trash_Battery.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Trash/Trash_Bottle.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Trash/Trash_Bulb.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Trash/Trash_Can.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Trash/Trash_Coffee.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Trash/Trash_Fork.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Trash/Trash_Laundry.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Trash/Trash_Sock.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Trash/Trash_Soda.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Trash/Trash_Tire.png create mode 100644 Unity/AIForOceans/Assets/Sprites/Trash/Trash_Wing.png create mode 100644 Unity/AIForOceans/Assets/Sprites/UI/ai-bot-body.png create mode 100644 Unity/AIForOceans/Assets/Sprites/UI/ai-bot-closed.png create mode 100644 Unity/AIForOceans/Assets/Sprites/UI/ai-bot-head.png create mode 100644 Unity/AIForOceans/Assets/Sprites/UI/ai-bot-no.png create mode 100644 Unity/AIForOceans/Assets/Sprites/UI/ai-bot-yes.png create mode 100644 Unity/AIForOceans/Assets/Sprites/UI/arrow-down.png create mode 100644 Unity/AIForOceans/Assets/Sprites/UI/ban-icon.png create mode 100644 Unity/AIForOceans/Assets/Sprites/UI/blue-prediction-frame.png create mode 100644 Unity/AIForOceans/Assets/Sprites/UI/blue-scanner.png create mode 100644 Unity/AIForOceans/Assets/Sprites/UI/bottle-large.png create mode 100644 Unity/AIForOceans/Assets/Sprites/UI/can-large.png create mode 100644 Unity/AIForOceans/Assets/Sprites/UI/checkmark-icon.png create mode 100644 Unity/AIForOceans/Assets/Sprites/UI/green-prediction-frame.png create mode 100644 Unity/AIForOceans/Assets/Sprites/UI/green-scanner.png create mode 100644 Unity/AIForOceans/Assets/Sprites/UI/lab-background.png create mode 100644 Unity/AIForOceans/Assets/Sprites/UI/polaroid-frame.png create mode 100644 Unity/AIForOceans/Assets/Sprites/UI/polaroid-icon.png create mode 100644 Unity/AIForOceans/Assets/Sprites/UI/question-icon.png create mode 100644 Unity/AIForOceans/Assets/Sprites/UI/red-prediction-frame.png create mode 100644 Unity/AIForOceans/Assets/Sprites/UI/red-scanner.png create mode 100644 Unity/AIForOceans/Assets/Sprites/UI/seahorse-large.png create mode 100644 Unity/AIForOceans/Assets/Sprites/UI/snail-large.png create mode 100644 Unity/AIForOceans/Assets/Sprites/UI/turtle-large.png create mode 100644 Unity/AIForOceans/Assets/Sprites/UI/water-background.png create mode 100644 Unity/AIForOceans/ProjectSettings/ProjectSettings.asset create mode 100644 Unity/AIForOceans/README.md diff --git a/Unity/AIForOceans/Assets/Audio/no/no_1.mp3 b/Unity/AIForOceans/Assets/Audio/no/no_1.mp3 new file mode 100755 index 0000000000000000000000000000000000000000..375e976d0c0c686327b3224848518c4b55bf430a GIT binary patch literal 2524 zcmeZtF=l1}fuImiUsoV4%)r3-|DPd)34;}b0fQlsGy#$!E{-8UNpY~G5m>^KK^G`t z2qujfoc(=$feN^Q3R3gZ|NmoP`2X+!?=37qF}%PtFD)OafFFo~?%-r#2qgqo5d!}S z0ia!0K90Vw#(I|K3XHoz?$ZIe;*xyt z0MFblF3A&`9yc;Ib~-L-`6m(iqkeitgF%cyM4gI7jC_E7gq^be!4LleFVs5xP54>< zp}z6Jg8~Z~K6WOC1_cHlg-(^@tZUjEV_Nt*88~fyeR_Q^D!lWtKgMu4hJ%r@i-{{) zwBUn=fQY-^W7dZAI|^PujhL*rb#YRY$<@Z?u{WoN{WlR2RtPmJUiClx|CtV+V{JY% z4hktpoAT(Jp5HPBf#g@mb?3O zSlAs8r2nr=`v3ns*n!MImpTZrFfg_Vs?2z>b;1Yj35^dG7}ZyldwVZJD+ULYN6C?TXF*2W^FKez1wKj{bx;0DO}6^O5uvikr3zb#Bn$6F6L@%V-%hs&k{9ro_eBHg5Y1?mtt{;~HD z=Hi?kHhcTghK3gwJpbRHiU0raDKK5Ku6%sz`tQAJo(#--jJ{g}!%G)zmisJq+mP+D zH5UsLDE$aBusECh=K;%@j zf3Mze`C6$z@th6ABh5vxb(@M9+fUsr*V%pV|NnnwYOjmSkIntCNl(mI0qEGRHkDET z%a@!~U`Rcnxvfj<-4?Ord&$vh3b)b|9U4MI^W(Nzc6~i{U-fdur+rl!X^JyF*JS2I zd}S?6h@O4i?xFOQQ_FO{6wl?$WpPd09DeQ$*Oj{=hSA)z{_o}Q#(tZ(UiFjZ@dg=J zli1V^ehvmdqxGInufG5P|G6V~^YVUN-Y4dI=;RWno{4MsPn^ISarVWecd6%Q7^rTo zITLIha>vxB-}O<{mG|?t7pLuzKDf$j(!wIA*&+Iz0kh>)e#G=?WL|gwXjK?2>!tZ% zZ}Gv7>Wn4X-VN(B}?@Zt_a@+RL%|SHTe3AFg z=~f8`rd|DP=<_zX;L0ak@y_hveKqTPXFbSgTdC#MdXg(QV2`R(PQ~PhMHUN}$I2gh zdDN#=V|mjz{r`_{pT54kSv+D}-0E`HH}QXy-fg{pFJbQuEhE*4?EmwgPK6cZgsKfP zN literal 0 HcmV?d00001 diff --git a/Unity/AIForOceans/Assets/Audio/no/no_10.mp3 b/Unity/AIForOceans/Assets/Audio/no/no_10.mp3 new file mode 100755 index 0000000000000000000000000000000000000000..8378b2d236ba917d3c8cc792eb1f5457697b9005 GIT binary patch literal 2524 zcmeZtF=l1}fuImiUsoV4%)r3-|DPd)34;}b0fQlsGy#$!E{-8UNpY~G5m>^KK^G`t z2qujfoc(=$feN^Q3R3gZ|NmoP`2X+!?=37qF}%PtFD)OafFFo~?%-r#2qgqo5d!}S z0ia!0K90Vw#(I|K3XHoz?$ZJK%;bOy`|ef-h65mX=&ZSF1(FyA0~Z32^uz40=RY-( zfg$th$xmw(7=%(T`tN+%z~nPa^SiA9!$hVh^10U=6xdv(1X7qLxP1=lWpd|GO}uIy zKYt1X4@1Hp`z<1d_T|+V@BR}My!-!4{Y62+|1JIx1%>3=F z4h=~hGT)yb{7}c){NRrR|NIU{gE|hG4rcj(@$C1NSWnp9UeDmb(_x};f>ojS*-|N% zJ^`=8tIGD09~2)H$8OUlP))=xCzv6Yx7nfNX4KhwG##s3?Bgz&>%bf7_jflbPBLh>dlue>L^ z+RM@#O|o_*wJ|0rBt-FstoArHA&G~rVFHujLWaD~W2_4p*sn159b49{Q^AwXm#vd(qV7g@bH0uWggQ=p(*@$yj<6Ju%)ZHAkQ+V8M z&IAYqwoC@4A3+A@*E&9a`3?-Vshyo?Uodd@%(}iOy@9cCa@6;p4-9!5-#N`(;h7y7 zy8k~@Q0UGzyQ5|vpLBFtx%b^yp(~D>Jhj;#zwVW3e$6$ZUsFovEV*a>Eb4q&^}UeU z`^}>w3(SNiB4;yROi;34=cB`+GXM7$g~s`0C?`Iu~59*sdW%lu!(~_uYm28;d3c@p#cnvMOWozgtD>g1 zg=;RY4qbI)SIf`0*&j3f*LL_XjyA0p&ktR*zLc|bcEHqA&kr9Ae6S+JMMj6W{zuv7 zrG6(G7*uBFu2W!`q#&g6xl`ysf}rlq>08$o^?Pzg$~!zW3UqlfSJp2e;EL(2(5$V| z;sNt**VgHBe%;9VB|B|>(%V;Cr@mWgXq+XqGv-HymW?PcM{{fA`u}{_N><(!g_X>N z>H*rzgVK*H{|8{v1B^)y1_oYWj4}ez5+E1IG-+U9V8QE(!Q&OY&K#AbO$dZIx&u=R Nt-yrl|M-ob0sxSw1+V}B literal 0 HcmV?d00001 diff --git a/Unity/AIForOceans/Assets/Audio/no/no_2.mp3 b/Unity/AIForOceans/Assets/Audio/no/no_2.mp3 new file mode 100755 index 0000000000000000000000000000000000000000..6977fd9a529a7558bcadd7fcf38c9b59656882c4 GIT binary patch literal 2524 zcmeZtF=l1}fuImiUsoV4%)r3-|DPd)34;}b0fQlsGy#$!E{-8UNpY~G5m>^KK^G`t z2qujfoc(=$feN^Q3R3gZ|NmoP`2X+!?=37qF}%PtFD)OafFFo~?%-r#2qgqo5d!}S z0ia!0K90Vw#(I|K3XHoz?$ZJK%;bOy+pAUvh65mXOqJl-2$C2D0~Z32^uru09u}&S zz?Hq|)u|;tjDaq{19#qHVA7bMWp3@jz`-WF;&xtO#9Aq{D}f9P%(U|pr|mLv0fKTM zC;>5;`GElB3*3w%gAX4*1Jf*nLq%MPDCAl2NQOg@+1@)y zzSdjw_W#>66cRQUKM1S;YXfzNg#;TggJv)-D_pyzqf;P2>}3C+6@1=eJkHXM#{@b= zr4)PEwp2x5FnDy}tewt0dq#JLtQH2(OBp9_weYMEFj(ktph;uRwF^uFk{M!5 zCaoJoRj>G==fI>bNj>h>*SMu*$I_2&Ew`T+lB6oh!w*NO3 z7*xDoy!|2vP83*iFsulVIM&ke#A1T1H5IjreD)$DZ8}WfGEN3?P&b3({^`A+N;YLGYi;#+!(v(P}?!fIVGz9$3{WJL#9V}aPdSpKl&^G zqtNLjUqa7G!+A27mDerGRQmY-nNyko4;M2tqr(FOpu-p#csL)JJlP{9&M;AqVcCIu z?jQClBr^Wsl4WRGz_a}WuZ&Db^8Cit6)et-vn?2oH;63%r<|}$^OSSETK|8^R-I#=rD^;B|99=a(tXNnxgoF|eyz7aLWGTtsqsJp*ggs21DPi) zO!OF)Y#4nT_w+xkayZ2NLBxuY)j=}x%{k1{S==P|+=T?HQFElpzq}=nhWwv>_%m J|Hp6e6aa3n)inSB literal 0 HcmV?d00001 diff --git a/Unity/AIForOceans/Assets/Audio/no/no_3.mp3 b/Unity/AIForOceans/Assets/Audio/no/no_3.mp3 new file mode 100755 index 0000000000000000000000000000000000000000..356a17e218b356d661e5f5555c97fe3910f7fe2c GIT binary patch literal 2524 zcmeZtF=l1}fuImiUsoV4%)r3-|DPd)34;}b0fQlsGy#$!E{-8UNpY~G5m>^KK^G`t z2qujfoc(=$feN^Q3R3gZ|NmoP`2X+!?=37qF}%PtFD)OafFFo~?%-r#2qgqo5d!}S z0ia!0K90Vw#(I|K3XHoz?$hCAU@$qL!eQFVz;FQMj)l*H3qTU1VBkUkl75)(b6gFz zN#KfpD79*N4`cAuUVqD13_?X4S3b9OU;-vNmy>!&rROkDXySL|aFc%|pvUfVChPn6 zGdA{rY;0`)_sQ8GK79E8jEc&Ca&q!N+xveo{$ogSV3d<%NN-=l@SmTdqyUm)9xyOe zeqfOO!N6gEfF%LsZ;{SPv0dgC?20UMO#(gkM-*cCI%iyc|9(bA{f~-@%KtJp_3iEL z`wc#P23lqRnP2_`^B;y24NNvR4Cnbh82`yJym$yP`v3#O=LZbd9~cDc8#oRyF!LB3 z1|kjthC>a;JVi%1eebp|-K=qt-DI9*GJ^nvfjK8v=$YgRGH$F48xk(@Cms+}Vwj-8 z$j-vp)YZDMD~hor@pI?Yj1R|}jqEt5OpHyu=HT8qv4gAp>aLClPdYdc9Ce)Z=T+_l zmqG!~7U2mhs*PJcC*PX*UyA9eq|oD@j59pz|NmU&v3b>2?O*%*=G(+%!_(ssyl?FlcXkyAKQ=9% z>Cc1nnUp&kd=%z1D(djA@|ky~|HlP!jT6&llHC$g>;In(a-AExGXCoSFLN`kuGET5 z2RiO;+%_YI1O`U4Cz}jJR77&Pd5)Gw{+c$R8X?5C~tk|g8cD2z~%g#^R-WFQj|M=Y1m08QqJ$~;WJ-dDhsF&t$*xzMzZ#o8 zIi;Ms(~#3-v8}!RR`VwQwa%i~-UNr8J8N2f<>teap?{-Rr%U?&3w!@G>}|vFwqnwze>$>HW`ADF$~Hso_O!QKS2QrUeA&{r@2L2vm#My2H|^ltEgPoN$=0E> zQM$!Iu_B@^pj}buifXmdwM}0va~IEfwbPHgOsX}d+4yKyxc}#%!ljIjGkm>WCN39w zWNfFUrPJ&!!ny6~?%XT|hKIJgit9JJ{@E27T$;0vdEN2QP9?`h+&XR#c{t+46sIVj zaM{WkcV_FFy?oIb&#l%4H{ESp7^!gPW7O2kf3D2QbVx`O4!Wq4dDNokd{TQ2KG?|G>bI2`maY7#MgJfVCSCEdg?YOp^u%1{S=w54;!fI&V~xwjmJW R=nhONv;q^F|Km4$3IO3&9(n)( literal 0 HcmV?d00001 diff --git a/Unity/AIForOceans/Assets/Audio/no/no_4.mp3 b/Unity/AIForOceans/Assets/Audio/no/no_4.mp3 new file mode 100755 index 0000000000000000000000000000000000000000..e1a783a03ca845c48749cf781adbc102f63099f8 GIT binary patch literal 1948 zcmeZtF=l1}fuImiUsoV4%)r3-|DPd)34;}b0fQlsGy#$!E{-8UNpY~G5m>^KK^G`t z2qujfoc(=$feN^Q3R3gZ|NmoP`2X+!?=37qF}%PtFD)OafFFpN7#P?NFf@<~{*w%V zc3Js2`nnqHS(+;_?gDZdbfg&=Ob)29Y-wd+H~@0Ty<6c;Ac;{ha3KImKg@PU=VcQa z7}AeLK3=21AhhPJ|IW7!OrbMZez)Dgz_6{MQ}Oh^m@Th!92zAjFgfi>;qcIHOyM@@ z;x#H}e#;@k)^I_DVFAN|81eS!_nI1i?AWn;_uhZ+-o2ap|Np0V?_U1@yGThX{QrLz z?(X>lObj#Z0~Gk@|JRWCBhP;D`yTFets1f`=dvX-o5+&d-v{LK(kNp-o5<)w~mg^ z`2T+d^z>>RIG7UtIyBhT|5=dyp+=tl{s)I=0Rk+HoP6xejRzhSSjhN@GPE!lEMdPa zXt+W@J+5HV1*v3@u3y zS)Or;a4BuwTl3e!gNau>S^sKp;dEu|j&rh7H{Q>mZ~W(lownwz9$>z?v*gsV@|A^a zomJbGgR+s`^B?7GFBWx{z234yLSy;A?>{AkI-3>8rzVf=MnxpeIIQ&OxU} zm$2>Y=da*oa9s2z_1DIAMo-cUB@Zu-mi_$sS^Zr0qp8M$^Z)<myYF01y2W&_Q(Idgv1%(pH;%cpouE%unW-pDQe`^@w1LaMrtlpE+~p z`^;mDT$W!AtvB6&W|pgL<;*XI%89J372#h*VdYooD4u<)DE{2#yRQvkvR BRjvR4 literal 0 HcmV?d00001 diff --git a/Unity/AIForOceans/Assets/Audio/no/no_5.mp3 b/Unity/AIForOceans/Assets/Audio/no/no_5.mp3 new file mode 100755 index 0000000000000000000000000000000000000000..f4c2f5a87a7ac04ebb9d558e65cac0a2ebf6f0d8 GIT binary patch literal 2524 zcmeZtF=l1}fuImiUsoV4%)r3-|DPd)34;}b0fQlsGy#$!E{-8UNpY~G5m>^KK^G`t z2qujfoc(=$feN^Q3R3gZ|NmoP`2X+!?=37qF}%PtFD)OafFFo~?%-r#2qgqo5d!}S z0ia!0K90Vw#(I|K3XHoz?$hCAU@$qL!fxBjz;FQM4)>q^pwJiv0~i93^ux4{Eh1MX zfh+XDY2GD0j3F7H{dc}%VCt32{BG+2a$Vp5FOzEeN){{-;E~W{WMp!4zCWX);?ME+ zJvNMY`FR+AJbb`pzpz36X9LIY|Ht_c*w{Z{Y~TMzPOiSOeLpy@9AIGJ0b=(C2Fd>q z7~~if7#NtW|6lU_WO=En!NDM52MY_QB!6Av!^fZHFRz?N}g9rS| zs)ZMVE1Eu?Ii<16H?5iRw1GM2sj!lyCjxBzjw*>koa||kVzThbl(v-a_frI5if(qLK zhb=-0tCT+<$Z}*WFtAbNR&7X}by@Pl+n2@io36}YSf+7uRZ)TJoaf@2lcSHzfzppC z151drZ+^A{N4H1j+P5i;z7OV$oKd;JxkvcX%$8Y=i{VnB{xGCY_--q z&lMN<=i}bC-``8uzPGWjEZ+Oa?$=36r7o{&*RM4IovW7@Eyc`yNMKV0o8(%)|`9Cp6$LDxpc~<`|Hz; zC8yk689mK9Ut8w9RrHrDbKmTi^1d0jwLIML+}S%HH)dPqthx|2cY1oOzJ6WBy~DM? zcU}8FPkztNd;jF?H(Qq!*Sx*;?}dPF0b{eGs_vz1$IPxbdMj>EWjmpfDp( zr7`x<3s)T>l|XHV6_UzMF`_P$OgbGj*gP(&3T+6T=&~rxjnng>pF5{Yrt+bLNlzv& zPHI&1@_7AtnvTum)b766^3#10U+-6Y_ge##|GWP)=xg0fScy)k{vci+lzue%KQJ(4 z0wa-wfq_>6n4N)W36Kk9nlvylu;4X~`cA@Y-KgZ?3V{$ucVJ4P6`0WcAHUI40E>nc A_y7O^ literal 0 HcmV?d00001 diff --git a/Unity/AIForOceans/Assets/Audio/no/no_6.mp3 b/Unity/AIForOceans/Assets/Audio/no/no_6.mp3 new file mode 100755 index 0000000000000000000000000000000000000000..de5a023232a32671c5efb5c4b718ad3711967c4c GIT binary patch literal 2524 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 literal 0 HcmV?d00001 diff --git a/Unity/AIForOceans/Assets/Audio/no/no_8.mp3 b/Unity/AIForOceans/Assets/Audio/no/no_8.mp3 new file mode 100755 index 0000000000000000000000000000000000000000..4ee4e973913d0bd1fdba01d46ee2a2ea605abaf9 GIT binary patch literal 2524 zcmeZtF=l1}fuImiUsoV4%)r3-|DPd)34;}b0fQlsGy#$!E{-8UNpY~G5m>^KK^G`t z2qujfoc(=$feN^Q3R3gZ|NmoP`2X+!?=37qF}%PtFD)OafFFo~?%-r#2qgqo5d!}S z0ia!0K90Vw#(I|K3XHoz?$c3WU@$qL!rs@)z;FQMj!!&YMIeb$FmNFNNk7c2!v3-e z2N)6-WjR^sg`p6e!jIac2fsfmsQpm$XNR492jibb zjSLQkN7xM<1e#=aA7N-ax4`j&gFpdugkJaF&J#Bo6xdRw1ymST`p>iTkU9R<;fn0> z{eM0sJTQ=m%JE_InQ8L=pi#o_2Q%t5Y8^W!7_uLJr^mlvxcPna^QQ+t{BhuaD#F3U z*r#CG#Lyz}^qvBXSt%1=6GQV389p}V#sd!u6a;`FoiUZC|JVZsz8Mt`T>IQOPlzS9 z+|lqf;9;{`U%6Z}s7+{Qo5A84U915L%&rb!_(bNgiYugSyivU%dBZ|>W|95|4kGMD(AkFDg9jQ^j~4RD9`w zuS4F205P2;EA7cktVFH;M+i;N{eL}U^8c?NEM$1tLGE)<06OoYmZW^|0S8%w4-KL< zJ;D=o4s-4Zn3N#FQyTZ#FK8)`sxeQZyP*iz0tdFP#uqZ07F>D`CzCgPcQ~Ht#K)#7 z&mdsJ!^NT{tUlqufd>b~Sr`-&P8{8l;&AnWfi!oT^3utE_4h27$h7wcNf_<_cT!?1 zHw(-2rT?WG?k-rM6LF*@T-~EYtMuOnRlVE)*IiWq|9W?|l)@2D?r9g|r)#kl6*lWw z7#Eg92lkQfXag6`BX?ZqYCsE%zhDCv4?^i1@B*`f{gluqd zSaxiwsT+e>d-sRUhm~70DyEdhrCw0j67-naxo1P4zm1sWOqDLN8B$6N%b3I^nv7h; zg*4OK*;+OnYjv6aLMld8++XBaqR-u|b!qSJ89ir7h!A3TX$as_5NGk*DYVL#>-5LO~%oIcU~m25#r0KO!GaJY-_yWvy@YLLf@B zuyNtB2zT{)+&pI{xpMpP3Ni#Ua`!k&Dsgv;Y(CuV6p`$-$omVgo>2Glu4IE{d0WGc z%kw3Rn+$X~nHM=|unKTDsmFAN%C)9GJLS7+>&)BWLOv)IR*n;@HOP?%r5`>14-5>M zz@*Q?z`zU40*pYk1jq$4O&S;&Sn!%lOUL20cvNyQgg}U+J20it3QTDJkKgDi0Ntka ALI3~& literal 0 HcmV?d00001 diff --git a/Unity/AIForOceans/Assets/Audio/no/no_9.mp3 b/Unity/AIForOceans/Assets/Audio/no/no_9.mp3 new file mode 100755 index 0000000000000000000000000000000000000000..1f4c2dbd72076550cef6cf1a65e98bcc39c0bb06 GIT binary patch literal 2524 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 literal 0 HcmV?d00001 diff --git a/Unity/AIForOceans/Assets/Audio/other/other_2.mp3 b/Unity/AIForOceans/Assets/Audio/other/other_2.mp3 new file mode 100755 index 0000000000000000000000000000000000000000..e8f7a12633f2a764e087a29c85006c9da6af9474 GIT binary patch literal 5404 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 literal 0 HcmV?d00001 diff --git a/Unity/AIForOceans/Assets/Audio/sortno/sortno_1.mp3 b/Unity/AIForOceans/Assets/Audio/sortno/sortno_1.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..57ee4828792fa2a4de35f78e7d9aa2a040abc6ff GIT binary patch literal 3100 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 Y{(sW~7V3Y3{Qj>&CY;3;{vXKs50ZXisQ>@~ literal 0 HcmV?d00001 diff --git a/Unity/AIForOceans/Assets/Audio/sortyes/sortyes_2.mp3 b/Unity/AIForOceans/Assets/Audio/sortyes/sortyes_2.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..d09b48e96ae4fee07c2e9b91256a4e5bfe440c94 GIT binary patch literal 6556 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ȋgRzJ&>>J^sFIM z7cSpe?1(0RdqrQu8tttI(cF{o{VKB~%v3WSXUh}POt?3PE^1yqJwL-Fl{ImOG(;E> zfuE5kmdMmSb-2$Tp^+v|N1t7GizJ`a2`b&Ru={>ne@~UBlu@|&t4;+A^P*^8rMj!L zm`qZH#@d$1+R$F8_f3}E*|_rHdl&Ss9WA_jcYn9Jq&JZiX-=V;3Q)wU?Pf1l>=j-e zr}FLWYm1MI&-*vepAUelF@pdl48-p)<-6tJ%|yi{80W$;O2wti;m9jM1<_!0e9Z19 zl*fpI6dxE*PCHc9cly{lVh6IW!`ZHlQY(OXlih^59t|g?!(Knk6|r_rQSqU<&GI;Z z>+E!)6u-fx)XDcA*&q%{`lzxw@Sa(Z?&qVCTH?OYWv>qN-4DCNfBeyiO?xidZF0%s znK@+MKV7P(C0Ae`k zwyJZ;Lkfpm$lGit2wyC6$glyr1Vsu$3+Xp2CwgVY*n9K>n8TH;sI4}5Bk{R$4K=C9x+9o zK+asu1sZ-XW*7Re~%7kNd&Ve?=;UEw$LP}vZQ&oD+EYe z)g})o{ThF#`=~w0!qp^O+S-FP*w?nI#I>(T+U;%E;M%W~{5uw8f%UodhaO)Ix2HSo zZPX68X|-FItxW3t_ipE{Fy%#N^d}EwSuI28%0i!-1)HhXPnD!7 zyM3CQbFOd(l}>Iduq zKzG&lyGsPqg({j0Xq+X91k%4~lDv$f7~PTT(H-y{)i)Bd6^oHFOYkft_S{yq6%$H$ zr^gal+_#3JXD)Q4fzbCA;BBR1#St#Uw^5(!<0`!+Wg9jGcpq#}|M5o_8u?WDve&#$ z-p$o7KA|2cCSnz(!L7c*ZT7sf8hB>d;mHYk<0QFhChKYuGV&-LPGp;+>}g{aEVkFII%~M!>;U>Gv@a0?=)4R={^7+)&5yLK*?N=7&)v{?cT|4{GXN$WC8a6;ghy*vaJ->z zZV3PS;FC@=Ax4) zcVpK(qAkX!NFWmjFu;Z4GxMNkT=gXoE@B4no3}Zm44#K`4NvOWpDT>_xX|Ktn-aLE zxqwRbNm~4fyp@n)pLdJYb}BsvRfOm<6fnKY%*c$JP(Ds50sxwhuGxC3Re|Q@Xt&co zkwcP<8&1H~ZHNeSbFvK7whKflR&02_y4PpE^IDH4S%OAl8tG-}^2Z-ND1KG6@7tVQ zo=x9OZYUbXXxPC}y(Stl#Oc_yC_DzPqcD`9Lk_wmUS_UeXn2K@LyRX!(x^unsc5O7 zDfHj(%BK!>9SS0JonOc0vfzq9I3@D=ksnfAT7hP43A9a`*um@3wx1Wo`htpF@(1$4 z-v>6cD6|skk|Xd%D_U2QwTsKnstNyCz8S{@l?$O7j+KNUPQiZ8#LVBy~ zyRe=FZELhHZyZc!2GJ?dUj>)J!UyT zW(=qFw8+2p!bP`%qFQ!5HRd=pe7s*R{O!VN-;LKf{8u7K&p?mcOTdshM!p0tOcz7| zQHiooF-|b+DU-=Duo#yi=AKk7<#9v4UIwd|m^I;M2WMS8zF?DLPD)TL&vf=@{e66T z)N9^Y=_xb%swY3l2PA+R{{Glm-FU*dKWo4g;zVB-O#@zZ1T+Pb8wJ^&*(G3h|v-NVi<;xNcLt zmMCZR%kW(G3C<4<60#Ck;+@!fmqjo?7}uQ&=9IBk;IPAEXD#2xKmNqxz~g*c--vQ~ z)|X3j1F2B7eTB>h2_xN>X-?vGnMCMuXYo5!yh6DSH*i&}SBJC5?dbIA;7^ua>o4>Y zA>A)9>b6IL9f%7aBGxYoSm}D5yI#eu#cx`rbEXTvsH1iKnOYP=9b9MR!_z2DC24ov z8bM9P<`N#$tTJS{V?YVDKKV;(Q;`#Gb~R2Lj?W=4o) zZ)>oSzHfb2DuG4(2AEn)Q$UKU{Nd1H_G+Ab{x(RK0X*H^s!Bv$S*$(GW);F zAAdeGZA(a8m=IFPbG@RS<>Gepv_XHmqXCH1eGCTxkbhjA|7w!|W77Wz|F^DysfPBc PDgRxNaO8h}b=rRb?@^Eo literal 0 HcmV?d00001 diff --git a/Unity/AIForOceans/Assets/Audio/yes/yes_1.mp3 b/Unity/AIForOceans/Assets/Audio/yes/yes_1.mp3 new file mode 100755 index 0000000000000000000000000000000000000000..4d4c2cc32b054ca4c40521caf1c21a334ae31060 GIT binary patch literal 2524 zcmeHIX;4#F7`=H(6as1l1Vqs&$fCkP5==AQ9NHuwV;PkKj=ydwWGxP47dFQ+LeDlpY@3L%2 zXfOvSE{ko8yww3f!3uLg1~gy>%#oD{wg9dTgNu+_^CWSeummOuZ9cyef%W%nHd25? z3iwC8VFduN0{&QqLB4$vtfK;7q+l8HAbltU;Jgru7XrKx5G|SmgKbMPwWJVGwR8P# zUJU?QqK~D-0w9^|!^?bM*BtQ`|K9{Y`v<+=tX+453>?_8viV{iP^-FbU6ThO7foRh zNdkZpU#7mKu-^(#KeZ|#XQY;rY;5m@hANg>-X}hByfe^SmYhE8yQX5y^zc|z|GMFk zV-M`Zo}^zgwvTu>5hne4W~LsVo~@(2orsW6teKb;i3m@r1SJTF4A#C}{vii{7f7I$ z!I);@dwdLDZ^zI}%hFTN?mDH5Bqi4E0S?t^mB)`=efDCzdrL`Z+c}!-hEi}%ZotF5 z8AQVAygcm5jI>^k9KPLm$)_+W9M*E{Q$9h7>NqDsP>!4Z{bxfAQAAsWMu}v8RBapz z8Ti)FHJRoioa>!awuKyuYn4-X2s(hpuKAM_VsOb>7z3;cCr=uwn^opn#Y6(K8_lc3 zGS0zJS1s3Hz@{uu)a6eKJXNsajxLM0?v~sJcuAn9Cq#`WX^AsMYHgjx?qYLh#-M)l zc@HEkGq7BK(PLAmUDEzXutM>oba}~&`3%i;m}#pnMn_5{93>>!&pM_XlkUdmC1;!H zMAp_{I9u4dD%<|ZgQ(~`7HpSzI)SBff=*35yhwY9>ZLZh3bZeJJLihy-%Xbrqd;}~Vv>mS3 z2)<#`08fnbp6WF2o9`+V0!pUam?ejbZS0+oRC0ckCr;+QkCi626?>@XpG#`i(UB07 zP)b2_{?Py!Z*I@_{UYe(>+H+-IDo@q?XF1#IA!Ba6mvQXg|>c+$`^69vEdM4ip(H? zul6@pDWk8h>8C&VsmP{-eC2`%m1JE$*ebx1RohE|Uiys{*2>-a^#kN0G z8dhX*>kJtbtrKJm5nmI+k3);%hS3ag#SDjRISo89!_Bz^2iJ9W@mR)rvknRQ2Y1@k z`3d5@#3}c1!j&1_;?uU-xQ>pF=*x=H!26v=Q$Id+=z|>vZ?dtIe!XHo={aXY`YAeN zh_75oY8gSl_iLF3fPnm`Rb&9zv-G8Ruc~~`f&{H++*gA%3@l5KSX<;tgAz!Xsadsud?GaXIig^tK>r;nnUAjlJ)+)N5+4j1G{!zeUORLTUs#?GK7Q{04VAM0BWf$%4BiV!`?C@ ze!|k+BL@6NQ>w_TBSL^WAlrb)EC%Zg9GQ6i*yUY25}psMEhUEQ81C9-^sUul{t5aS z3!ce{iA&jg=EZ8$Gh&*79b7exeU2YEw7>RI&pUD!yE}UCsAV(sF2Y&wF}eHo)CgcU zmmK#9+K95yON)5JjKrSUynblUnWsyXaci`{~E+PpyuQJ~+t+-@_GQmo7>0e^d&WGAnrL`eMkwyhFEP*|I|I1?G^C>HW_z<{ zQLbxMuC#4dvBZ8-o2Jv8JmDe09y3w>{rHZY*89 z0>F299t(y#o#ngEw! QhdAZGLP|9J<)hR82B=%o^Z)<= literal 0 HcmV?d00001 diff --git a/Unity/AIForOceans/Assets/Audio/yes/yes_10.mp3 b/Unity/AIForOceans/Assets/Audio/yes/yes_10.mp3 new file mode 100755 index 0000000000000000000000000000000000000000..7f16f99c27707aa0610987dd4a331b5d09040a91 GIT binary patch literal 2524 zcmeZtF=l1}fuImiUsoV4%)r3-|DPd)34;}b0fQlsG-5Dg2yt-?0ZNL4C5^xmmJGT; zX+tn+#Nh1j>kCxC1yqolm;V1B1H=D+|9@{`0gB-To_T5cKn46j40H!414Aewu!<1) zPY3|*vhs2Cbv4$rG*@8U1#+LBA_IfT0TtH0tqcqYK<+qs?rsA}ViXKq2td*gvx8XZ zTb=~245m|i7xpj)1u_TjJk`MDrI2NA8Nd+qAh^lq$)r2Fckdo;axZo|+-+dY(J?FU z-Me?s7#I`<1r#JI>VYf<1~xe$fHLd~m<<@1`GEi=fXt{%017ZAx3~9$7(6yMe;a_b zGC#fSIZ$9B!^h6tcwm8n00Xmx5Thc~^?Qtrvlu7yu@%@_gzvp3Vj=tU&z&AVrYV~R z%wLx9&Szz4d?B%*CYE7>g4CTR7N>_j4d)*j7#v`@!xNOov_L?dm(NqiR^fsKpG@L3 zjcF&7qi+AW;`6dA_1*G+%L5H6yXS40TYlTO%nRlrS1sTF z|KA#rYaRfd#l_6Xz+l*@AS9q$`#?Z)fuzBMbmq&g)prw}8}H9Qd*Z+YO>aZyy6Fx# zKLl{dHFmKdy}-%Dxb}pCi=M;@o`1^BJPf=Cj;bYSF)|ihcrx+uC0@pchsPw7I&-F( zuHE13a&E@5xL5VBN`={H?0oHcy>`p>l(+l;|Bj2-GBjGq=lT2bPWLXURn`Chzhd~L zAZWnEAkx6d)1$=O-lHbrlsUhP*;!e0X|G@@Ba07At?O_H?YV#T$U?pU}!!e zm3%IML9o^{=;yKqCjFIK@g^4-cAr!^SS-7Wvq|~G0*{4`#sWJW<(d*s9y;;XZ3DZM z@|1=HEn<&8GP=4?-pcmXuF<~mjPli&b=r^Ss4Di!6$_p`TmRZAM&30zC~Z|(T-%-Q z1$)Jc1y*nSC!4YQRs{2j2A2aI3_%PmMg|>bat1RJIhWOG@bdI5n`YvAg+ z#Ig4(lUdJ{tx)6WKh&ty%5ui(Axjl!vpTo(R;dFr8GS*_Oajr}M_5JW{H{n}`Ni`0 zxIusT(jV))3Z}GKRGx8HH~qhsv!GVg*K^j&$SUa~y{0dbXPnmE{!zMUeP#lKN8^nJ z1s1$aN^7qEOR+y*s}~Y@=d{~ot$7B?EbZlq)<&!r7MlVtCK;(O;d{3!Vv_c==iSfV zM8q1I8~vQQ)4Ft~{}DZ~ zhckKxtB=@*{oPJQH%l@W*Z*a?Tz(-o-;k+GPDMlrSSIH#V3^3f(cwXX6pL%*>OUvy z`+mi&SiEyuuUe>0!ZA+1cZbSSxC#nW7A`uH;_o4QH)W$r_}TN~XK!rSm6DhG*|_jn zkg9;Tp14of{m;TlG0SH2mxPvt^?x>qI>s|a=;N^{^{Kidk@`Qh8!Lpi8*t6gO{^Dd zdAjMvMYsRIIG4R&u-DpVh0%+F5+>)UC5KqqfhA&0Ot0?_1cloKx2;7w+Y<(q7Q@ z-~t1q%G+kCxC1yqolm;V1B1H=D+|9@{`0gB-To_T5cKn46j40H!414Aewu!<1) zPY3|*vhs2Cbv4$rG*@8U1#+JbBLjoU0Tm9$RtAOxAa}Ig6LJPgjDmp+0Z95`P8W*! z%ag#B^~l?PVGm&DAaumJ)CkS;KTx$(e*0t*>Fc4meH4h(z`|0tvwoMXzHy!2|n zhr+W076w%f{YjaNZVDu}*)cq7kTl%GR;<`^;=m>z9u-z*E5`#FpV*AW7y>lf)zsY@ z3@U!qEK{Gm&XDDXRAa)+i#HserMYtys?FHsIfX6b#*5SQ^~`it1onkwmRw}%y>t9` z{MFJ|m%sUKxwo~}*S$9MFZ2Ab_5b~0j$&hMXkd^%{KMfy;vAN{>fWp6CODpXz`@`Z z5U+CCb(6wjo*KrZ3`WTnJkOjtCpM-?NO*9ul{7b8e8Q8a!>}Nb&&RKqA>rePpFaN9 zF-e>oOqmW|Uc904%$YucN4|zBlQnoQZoD|%E+!|+L$PMXrI(91rFZs!+rR4d)#Y#I zX70`UHLLH}>R;^kum1m=3Jfsj76+yV2bUDa)`Z>t@;^7H|{h!*Ic~G~Q=fs{_@vTcl6Y{u%V%(ZmOq|%ossHz~#L-8W0!}QA4!in) zQtP8wc6&=#k+3fN|0kF=UT)NTlxF0~Hl5Bo;Y1qp03cXx$!?W;#4mbf1VQPnz8u*p9Z78 z*+TEsl2xjNQW!t@DXio5uUpQ*plVtEbpk`>ysPmSm7-ia{AA{u_)TZ}~j@b9AikQ5TSy#J# z)r}oBU*8ro&6S`dVafVZFl?mxa*2L zR>2BuLM1_8%ylxtmq+1At SIJyH<3a!9|=KuJOo&o^1XR}iP literal 0 HcmV?d00001 diff --git a/Unity/AIForOceans/Assets/Audio/yes/yes_3.mp3 b/Unity/AIForOceans/Assets/Audio/yes/yes_3.mp3 new file mode 100755 index 0000000000000000000000000000000000000000..95d78457c9f8c3b57396d0d5052658bb926b4667 GIT binary patch literal 2524 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%0A8DB3vZ{hyUN82W25U7oWI z?aCG-hdze-oU5d$5|AZmi!hO~T*s-teNCYild)d?F7GN4Q0|oH<$AYT8fjF$t@VBo zYk7=?wPcu;UxJ|bFJ39@$GrFh&Bjf40}jQD?Uj#<03RSk@H551{elkwYBjcZqu9RG z*3*d0H6m+kVb09h25wzhfvIV}&Jh=@2^#I7xxlU31hY(zm=<&!yav00$c~%y%%YdO z*Lp^jNN9-hV4LJp)J&a@=`{u)^sePZatUGn2ZL;Bs7>`j6%eEdU)b>qd+VXNl(8nK zftAxht>q6Y@I(#i1<6CB5Mo-pT+bDq4G}f2i;)4uw8o^+|N7f<-SoTu?J~fn`ofj+ NttdI5>>FR9{9h~4CR6|b literal 0 HcmV?d00001 diff --git a/Unity/AIForOceans/Assets/Audio/yes/yes_5.mp3 b/Unity/AIForOceans/Assets/Audio/yes/yes_5.mp3 new file mode 100755 index 0000000000000000000000000000000000000000..3ff711ef70cf7bf589c265aeb0c3de1f019fdb8c GIT binary patch literal 3100 zcmeZtF=l1}fuImiUsoV4%)r3-|DPd)34;}b0fQlsG-5Dk2yt-?0ZNL4C5^xmmJGT; zX+tn+#Nh1j>kCxC1yqolm;V1B1H=D+|9@{`0gB-To_T5cKn46j3{=bQz~F!bG~faU zaDo500MITgA4gwTV?9fA1;$+<_vrz>ZE`?`!=sgf;Q+`T;UAS{KoX;1;6ebBewa6j z2ma-4U@CKZWxsF(LqN>c=$*X`Ox&|pmm4l%P@Bpi$RNPzdpZzEYLvSGf%m=dd#~>| z|J>xDz|bI2k|M>?aC@A!O z@B7mCXa78yz`>xvA}h((q-dCUuwjCa&7Oh}A3lI=H2~6-F#fPHHy(IUU?Icj;s8vp zZEnBgGi;jjzR$}3lE3`z_q2~6gLG|8*cv1S8aqxN6g84qc;wi$o2!ge=(yT*Oz`i_?3T*dGN$8*{f32S!%Mtp`BqN2KRSc-ZCnNeN6{ zS+|Pc_%H-AvIdo|V&GCxSmn3Xfid7g1fQE=;|bOq>{5*iJQtNFZqnHjvUJ9D?-jaR zB2}hkZM#{rIy&mB%C^XoqdET#O>Mn;j$9Q9jnXtWQd=`|v&tmDUp?MyUj~#+s!~(E z9u&IR<*3U1b<2L~bZ$B-tGT$ag`qlIV^Lefug5E{?kvd)I5k=FSf0kLs3}6zOLTuY zBvs_~yl7zJYR+z0cwmD}k23QF?hSmVOb(KZT$NKIGgf*V>P-)b&e-Isb2WF<%dl-* zUwP(idf9dJUs6`pRLRa&8mqPhrKR{rDyMm>%>61cJ^IpumnvU;yw`he$(XTZ^4BZ( zT_>7FEM97oXVAc4@-D>XsO};8irfEvd6cS}H=5VYJrEGAwdcWJW`h!uZQQyHDG5o< z42KMin4LGpX^M9rJ1ir$qgqKb$bH3?8$TZxJv3X)5}d7;V0E(S;j1h?h35LZCIVSm z*P3|aujS3GHM#6ty>iOQnJXuUdMG?&JysjM>Y2r@l7~OIOU;_!+l6K}{o1kaz#wtQ zRZym6VslbpIAA0x+1MQ596ROzq=uv}!<{uAQm=K3ZwWn;-r&jPiiQvxz?Yj&i?>P|fII{eHD&PJ)G zuU7Vllld2z3hF5=R#RmOjMDw@aVBSh3x}ngRnVp2#s58i+GRv|m6k5rQvd(-6Q7qG zW0vLE3MbF-oc!3JM6~5#(EckAfHpHIq$n})Fe^@+Az{j5dei@>YCGR~?brWu-_+a{ zDB6G2Wl2ih(P`e|zEh?%rRgkWJa_$cTk55oGJRWX&NR#rT%jMl_>Y;vFXlj@M_fip z0j{Ep?tkeyc8bNJdE(=xx~f+8U-~CMYi(H`9;NO6|Ia>`bF)QHr5(O#X4x{+&Y0aX z!bep5uOF=D3>^goLI9M0rt$+z{7hifaWF9ODgYA?DE)w95}1A(fNdVUMvMkE-ryPT Uk|B=nz?4EOFroQBexs)V0F?s+^Z)<= literal 0 HcmV?d00001 diff --git a/Unity/AIForOceans/Assets/Audio/yes/yes_6.mp3 b/Unity/AIForOceans/Assets/Audio/yes/yes_6.mp3 new file mode 100755 index 0000000000000000000000000000000000000000..b66727d8df848a6120d429918b058d0e1d203454 GIT binary patch literal 2524 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 literal 0 HcmV?d00001 diff --git a/Unity/AIForOceans/Assets/Audio/yes/yes_8.mp3 b/Unity/AIForOceans/Assets/Audio/yes/yes_8.mp3 new file mode 100755 index 0000000000000000000000000000000000000000..41c6fead879ef459b9c22a695108f2fec59028f3 GIT binary patch literal 2524 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 + /// Handles fish animation - bobbing, movement, scanning pause + /// Mirrors the original renderer.js animation logic + /// + public class FishAnimator : MonoBehaviour + { + [Header("Animation Settings")] + public float bobAmplitude = 10f; + public float bobFrequency = 2f; + public float moveSpeed = 100f; + + [Header("Scan Settings")] + public bool isPaused = false; + public float scanPauseDuration = 1.5f; + + // Internal state + private float startTime; + private float pauseStartTime; + private float totalPauseTime; + private Vector2 startPosition; + private float bobPhase; + + // S-curve animation for scanning + private bool isScanning = false; + private float scanStartTime; + private float scanProgress; + + private void Start() + { + startTime = Time.time; + startPosition = transform.position; + } + + /// + /// Initialize with ocean object data + /// + public void Initialize(OceanObjectData data) + { + bobPhase = data.bobPhase; + moveSpeed = data.speed; + startPosition = data.position; + transform.position = startPosition; + } + + private void Update() + { + if (!isPaused) + { + UpdateMovement(); + } + + UpdateBobbing(); + + if (isScanning) + { + UpdateScanAnimation(); + } + } + + /// + /// Update horizontal movement + /// + private void UpdateMovement() + { + float elapsed = Time.time - startTime - totalPauseTime; + float xOffset = elapsed * moveSpeed; + + Vector2 pos = transform.position; + pos.x = startPosition.x + xOffset; + transform.position = pos; + } + + /// + /// Update bobbing animation (sine wave) + /// + private void UpdateBobbing() + { + float time = Time.time; + float bobOffset = Mathf.Sin(time * bobFrequency + bobPhase) * bobAmplitude; + + Vector2 pos = transform.position; + pos.y = startPosition.y + bobOffset; + transform.position = pos; + } + + /// + /// Start pause for scanning + /// + public void StartScan() + { + isPaused = true; + pauseStartTime = Time.time; + isScanning = true; + scanStartTime = Time.time; + scanProgress = 0f; + } + + /// + /// End scanning and resume movement + /// + public void EndScan() + { + isPaused = false; + totalPauseTime += Time.time - pauseStartTime; + isScanning = false; + } + + /// + /// Update scanning S-curve animation + /// + private void UpdateScanAnimation() + { + float elapsed = Time.time - scanStartTime; + scanProgress = Mathf.Clamp01(elapsed / scanPauseDuration); + + // S-curve easing: slow at start and end, fast in middle + float easedProgress = SCurve(scanProgress); + + // Can be used to animate scan overlay or other effects + // The original uses this to pause fish in center while AI analyzes + } + + /// + /// S-curve (sigmoid-like) easing function + /// + public static float SCurve(float t) + { + // Hermite interpolation (smooth step) + return t * t * (3f - 2f * t); + } + + /// + /// More pronounced S-curve + /// + public static float SCurveSteep(float t) + { + // Quintic smooth step + return t * t * t * (t * (t * 6f - 15f) + 10f); + } + + /// + /// Check if fish has moved off screen + /// + public bool IsOffScreen(float screenWidth) + { + return transform.position.x > screenWidth + 100f; + } + + /// + /// Reset to start position + /// + public void Reset() + { + startTime = Time.time; + totalPauseTime = 0f; + transform.position = startPosition; + isPaused = false; + isScanning = false; + } + } +} diff --git a/Unity/AIForOceans/Assets/Scripts/Animation/FishRenderer.cs b/Unity/AIForOceans/Assets/Scripts/Animation/FishRenderer.cs new file mode 100644 index 00000000..ff05bd33 --- /dev/null +++ b/Unity/AIForOceans/Assets/Scripts/Animation/FishRenderer.cs @@ -0,0 +1,160 @@ +using UnityEngine; + +namespace AIForOceans +{ + /// + /// Renders a procedurally generated fish from sprite components + /// + public class FishRenderer : MonoBehaviour + { + [Header("Sprite Renderers")] + public SpriteRenderer bodyRenderer; + public SpriteRenderer eyesRenderer; + public SpriteRenderer mouthRenderer; + public SpriteRenderer dorsalFinRenderer; + public SpriteRenderer pectoralFinFrontRenderer; + public SpriteRenderer pectoralFinBackRenderer; + public SpriteRenderer tailFinRenderer; + public SpriteRenderer scalesRenderer; + + [Header("Sprite Arrays (set in inspector or load from Resources)")] + public Sprite[] bodySprites; + public Sprite[] eyesSprites; + public Sprite[] mouthSprites; + public Sprite[] dorsalFinSprites; + public Sprite[] pectoralFinSprites; + public Sprite[] tailFinSprites; + public Sprite[] scalesSprites; + + // Current fish data + private OceanObjectData currentData; + + /// + /// Set up the fish visual from data + /// + public void SetupFish(OceanObjectData data) + { + currentData = data; + + if (data.objectType != GameConstants.OceanObjectType.Fish) + { + Debug.LogWarning("FishRenderer.SetupFish called with non-fish object"); + return; + } + + // Set sprites + SetSpriteIfValid(bodyRenderer, bodySprites, data.bodyIndex); + SetSpriteIfValid(eyesRenderer, eyesSprites, data.eyesIndex); + SetSpriteIfValid(mouthRenderer, mouthSprites, data.mouthIndex); + SetSpriteIfValid(dorsalFinRenderer, dorsalFinSprites, data.dorsalFinIndex); + SetSpriteIfValid(pectoralFinFrontRenderer, pectoralFinSprites, data.pectoralFinIndex); + SetSpriteIfValid(pectoralFinBackRenderer, pectoralFinSprites, data.pectoralFinIndex); + SetSpriteIfValid(tailFinRenderer, tailFinSprites, data.tailFinIndex); + SetSpriteIfValid(scalesRenderer, scalesSprites, data.scalesIndex); + + // Apply colors + ApplyColors(data); + } + + /// + /// Set sprite if index is valid + /// + private void SetSpriteIfValid(SpriteRenderer renderer, Sprite[] sprites, int index) + { + if (renderer == null || sprites == null || sprites.Length == 0) + return; + + int safeIndex = Mathf.Clamp(index, 0, sprites.Length - 1); + renderer.sprite = sprites[safeIndex]; + } + + /// + /// Apply color tinting to fish parts + /// + private void ApplyColors(OceanObjectData data) + { + // Body uses primary color + if (bodyRenderer != null) + bodyRenderer.color = data.primaryColor; + + // Scales use secondary color + if (scalesRenderer != null) + scalesRenderer.color = data.secondaryColor; + + // Fins use fin color + Color finColor = data.finColor; + if (dorsalFinRenderer != null) + dorsalFinRenderer.color = finColor; + if (pectoralFinFrontRenderer != null) + pectoralFinFrontRenderer.color = finColor; + if (pectoralFinBackRenderer != null) + pectoralFinBackRenderer.color = finColor; + if (tailFinRenderer != null) + tailFinRenderer.color = finColor; + + // Eyes and mouth stay neutral (white/original) + if (eyesRenderer != null) + eyesRenderer.color = Color.white; + if (mouthRenderer != null) + mouthRenderer.color = Color.white; + } + + /// + /// Set sorting order for all parts + /// + public void SetSortingOrder(int baseOrder) + { + // Back to front ordering + if (tailFinRenderer != null) + tailFinRenderer.sortingOrder = baseOrder; + if (pectoralFinBackRenderer != null) + pectoralFinBackRenderer.sortingOrder = baseOrder + 1; + if (dorsalFinRenderer != null) + dorsalFinRenderer.sortingOrder = baseOrder + 2; + if (bodyRenderer != null) + bodyRenderer.sortingOrder = baseOrder + 3; + if (scalesRenderer != null) + scalesRenderer.sortingOrder = baseOrder + 4; + if (pectoralFinFrontRenderer != null) + pectoralFinFrontRenderer.sortingOrder = baseOrder + 5; + if (eyesRenderer != null) + eyesRenderer.sortingOrder = baseOrder + 6; + if (mouthRenderer != null) + mouthRenderer.sortingOrder = baseOrder + 7; + } + + /// + /// Flip the fish horizontally + /// + public void SetFlipped(bool flipped) + { + Vector3 scale = transform.localScale; + scale.x = flipped ? -Mathf.Abs(scale.x) : Mathf.Abs(scale.x); + transform.localScale = scale; + } + + /// + /// Show/hide the fish + /// + public void SetVisible(bool visible) + { + gameObject.SetActive(visible); + } + + /// + /// Apply a highlight effect (for selection) + /// + public void SetHighlighted(bool highlighted) + { + float brightness = highlighted ? 1.2f : 1f; + + // Brighten all parts slightly + if (bodyRenderer != null) + { + Color c = currentData.primaryColor * brightness; + c.a = 1f; + bodyRenderer.color = c; + } + } + } +} diff --git a/Unity/AIForOceans/Assets/Scripts/Audio/SoundManager.cs b/Unity/AIForOceans/Assets/Scripts/Audio/SoundManager.cs new file mode 100644 index 00000000..1ee54196 --- /dev/null +++ b/Unity/AIForOceans/Assets/Scripts/Audio/SoundManager.cs @@ -0,0 +1,219 @@ +using System.Collections.Generic; +using UnityEngine; + +namespace AIForOceans +{ + /// + /// Manages all game audio - sound effects and music + /// + public class SoundManager : MonoBehaviour + { + public static SoundManager Instance { get; private set; } + + [Header("Audio Sources")] + public AudioSource sfxSource; + public AudioSource musicSource; + + [Header("Sound Clips")] + public AudioClip[] yesClips; + public AudioClip[] noClips; + public AudioClip[] sortYesClips; + public AudioClip[] sortNoClips; + public AudioClip buttonClick; + public AudioClip scanSound; + public AudioClip resultSound; + + [Header("Settings")] + [Range(0f, 1f)] + public float sfxVolume = 1f; + [Range(0f, 1f)] + public float musicVolume = 0.5f; + + private Dictionary soundCategories; + + private void Awake() + { + // Singleton + if (Instance != null && Instance != this) + { + Destroy(gameObject); + return; + } + Instance = this; + DontDestroyOnLoad(gameObject); + + // Set up audio sources if not assigned + if (sfxSource == null) + { + sfxSource = gameObject.AddComponent(); + sfxSource.playOnAwake = false; + } + + if (musicSource == null) + { + musicSource = gameObject.AddComponent(); + musicSource.playOnAwake = false; + musicSource.loop = true; + } + + // Organize sounds into categories + soundCategories = new Dictionary + { + { "yes", yesClips }, + { "no", noClips }, + { "sortyes", sortYesClips }, + { "sortno", sortNoClips } + }; + } + + /// + /// Play a random sound from a category + /// + public void PlayRandomFromCategory(string category) + { + if (soundCategories.TryGetValue(category.ToLower(), out AudioClip[] clips)) + { + if (clips != null && clips.Length > 0) + { + int index = Random.Range(0, clips.Length); + PlaySFX(clips[index]); + } + } + } + + /// + /// Play a specific sound effect + /// + public void PlaySFX(AudioClip clip) + { + if (clip != null && sfxSource != null) + { + sfxSource.PlayOneShot(clip, sfxVolume); + } + } + + /// + /// Play button click sound + /// + public void PlayButtonClick() + { + PlaySFX(buttonClick); + } + + /// + /// Play yes training sound + /// + public void PlayYes() + { + PlayRandomFromCategory("yes"); + } + + /// + /// Play no training sound + /// + public void PlayNo() + { + PlayRandomFromCategory("no"); + } + + /// + /// Play sort yes sound (during prediction) + /// + public void PlaySortYes() + { + PlayRandomFromCategory("sortyes"); + } + + /// + /// Play sort no sound (during prediction) + /// + public void PlaySortNo() + { + PlayRandomFromCategory("sortno"); + } + + /// + /// Play scan/analyze sound + /// + public void PlayScan() + { + PlaySFX(scanSound); + } + + /// + /// Play result reveal sound + /// + public void PlayResult() + { + PlaySFX(resultSound); + } + + /// + /// Set SFX volume + /// + public void SetSFXVolume(float volume) + { + sfxVolume = Mathf.Clamp01(volume); + } + + /// + /// Set music volume + /// + public void SetMusicVolume(float volume) + { + musicVolume = Mathf.Clamp01(volume); + if (musicSource != null) + { + musicSource.volume = musicVolume; + } + } + + /// + /// Play background music + /// + public void PlayMusic(AudioClip music) + { + if (musicSource != null && music != null) + { + musicSource.clip = music; + musicSource.volume = musicVolume; + musicSource.Play(); + } + } + + /// + /// Stop background music + /// + public void StopMusic() + { + if (musicSource != null) + { + musicSource.Stop(); + } + } + + /// + /// Fade out music over time + /// + public void FadeOutMusic(float duration) + { + StartCoroutine(FadeOutCoroutine(duration)); + } + + private System.Collections.IEnumerator FadeOutCoroutine(float duration) + { + float startVolume = musicSource.volume; + float elapsed = 0f; + + while (elapsed < duration) + { + elapsed += Time.deltaTime; + musicSource.volume = Mathf.Lerp(startVolume, 0f, elapsed / duration); + yield return null; + } + + musicSource.Stop(); + musicSource.volume = startVolume; + } + } +} diff --git a/Unity/AIForOceans/Assets/Scripts/Classification/ITrainer.cs b/Unity/AIForOceans/Assets/Scripts/Classification/ITrainer.cs new file mode 100644 index 00000000..61e37840 --- /dev/null +++ b/Unity/AIForOceans/Assets/Scripts/Classification/ITrainer.cs @@ -0,0 +1,33 @@ +namespace AIForOceans +{ + /// + /// Interface for all classifiers (naive implementations) + /// + public interface ITrainer + { + /// + /// Add a training example + /// + void AddExample(OceanObjectData data, GameConstants.ClassLabel label); + + /// + /// Train the model (optional for some classifiers) + /// + void Train(); + + /// + /// Make a prediction + /// + (bool prediction, float confidence) Predict(OceanObjectData data); + + /// + /// Get count of examples for a class + /// + int GetExampleCount(GameConstants.ClassLabel label); + + /// + /// Clear all training data + /// + void ClearAll(); + } +} diff --git a/Unity/AIForOceans/Assets/Scripts/Classification/NaiveKNNClassifier.cs b/Unity/AIForOceans/Assets/Scripts/Classification/NaiveKNNClassifier.cs new file mode 100644 index 00000000..2796e6f5 --- /dev/null +++ b/Unity/AIForOceans/Assets/Scripts/Classification/NaiveKNNClassifier.cs @@ -0,0 +1,138 @@ +using System.Collections.Generic; +using System.Linq; +using UnityEngine; + +namespace AIForOceans +{ + /// + /// Naive K-Nearest Neighbors classifier using attribute matching + /// Replaces TensorFlow.js KNN without actual ML + /// + public class NaiveKNNClassifier : ITrainer + { + private List yesExamples = new List(); + private List noExamples = new List(); + private int k = 3; // Number of neighbors to consider + + private struct TrainingExample + { + public OceanObjectData data; + public float[] features; + } + + public void AddExample(OceanObjectData data, GameConstants.ClassLabel label) + { + var example = new TrainingExample + { + data = data, + features = data.ToFeatureVector() + }; + + if (label == GameConstants.ClassLabel.Yes) + { + yesExamples.Add(example); + } + else + { + noExamples.Add(example); + } + } + + public void Train() + { + // KNN doesn't need explicit training - it's instance-based + } + + public (bool prediction, float confidence) Predict(OceanObjectData data) + { + if (yesExamples.Count == 0 && noExamples.Count == 0) + { + return (true, 0.5f); // No training data, random guess + } + + float[] queryFeatures = data.ToFeatureVector(); + + // Calculate distances to all examples + var distances = new List<(float distance, bool isYes)>(); + + foreach (var example in yesExamples) + { + float dist = CalculateDistance(queryFeatures, example.features); + distances.Add((dist, true)); + } + + foreach (var example in noExamples) + { + float dist = CalculateDistance(queryFeatures, example.features); + distances.Add((dist, false)); + } + + // Sort by distance and take k nearest + var nearest = distances + .OrderBy(d => d.distance) + .Take(Mathf.Min(k, distances.Count)) + .ToList(); + + // Count votes + int yesVotes = nearest.Count(n => n.isYes); + int noVotes = nearest.Count - yesVotes; + + bool prediction = yesVotes >= noVotes; + float confidence = Mathf.Max(yesVotes, noVotes) / (float)nearest.Count; + + // Adjust confidence based on distance + if (nearest.Count > 0) + { + float avgDistance = nearest.Average(n => n.distance); + // Lower distance = higher confidence + confidence *= Mathf.Clamp01(1f - avgDistance); + } + + return (prediction, confidence); + } + + /// + /// Calculate Euclidean distance between feature vectors + /// + private float CalculateDistance(float[] a, float[] b) + { + if (a.Length != b.Length) + { + // Handle different vector lengths + int minLen = Mathf.Min(a.Length, b.Length); + float sum = 0; + for (int i = 0; i < minLen; i++) + { + sum += Mathf.Pow(a[i] - b[i], 2); + } + return Mathf.Sqrt(sum); + } + + float distance = 0; + for (int i = 0; i < a.Length; i++) + { + distance += Mathf.Pow(a[i] - b[i], 2); + } + return Mathf.Sqrt(distance); + } + + public int GetExampleCount(GameConstants.ClassLabel label) + { + return label == GameConstants.ClassLabel.Yes ? yesExamples.Count : noExamples.Count; + } + + public void ClearAll() + { + yesExamples.Clear(); + noExamples.Clear(); + } + + /// + /// Set the number of neighbors to consider + /// + public void SetK(int newK) + { + k = Mathf.Max(1, newK); + } + } +} diff --git a/Unity/AIForOceans/Assets/Scripts/Classification/NaiveSVMClassifier.cs b/Unity/AIForOceans/Assets/Scripts/Classification/NaiveSVMClassifier.cs new file mode 100644 index 00000000..d4fc8297 --- /dev/null +++ b/Unity/AIForOceans/Assets/Scripts/Classification/NaiveSVMClassifier.cs @@ -0,0 +1,247 @@ +using System.Collections.Generic; +using System.Linq; +using UnityEngine; + +namespace AIForOceans +{ + /// + /// Naive SVM-like classifier using weighted attribute matching + /// Replaces TensorFlow SVM without actual ML + /// Used for word modes (short/long) where we classify by attributes + /// + public class NaiveSVMClassifier : ITrainer + { + private List yesExamples = new List(); + private List noExamples = new List(); + + // Learned weights for each feature (after training) + private float[] featureWeights; + private float bias = 0f; + private bool isTrained = false; + + private struct TrainingExample + { + public OceanObjectData data; + public float[] features; + } + + public void AddExample(OceanObjectData data, GameConstants.ClassLabel label) + { + var example = new TrainingExample + { + data = data, + features = data.ToFeatureVector() + }; + + if (label == GameConstants.ClassLabel.Yes) + { + yesExamples.Add(example); + } + else + { + noExamples.Add(example); + } + + isTrained = false; // Need to retrain + } + + /// + /// Train the classifier by computing feature weights + /// This is a simplified version - real SVM uses optimization + /// + public void Train() + { + if (yesExamples.Count == 0 || noExamples.Count == 0) + { + // Can't train without both classes + isTrained = false; + return; + } + + int featureCount = yesExamples[0].features.Length; + featureWeights = new float[featureCount]; + + // Calculate mean feature values for each class + float[] yesMean = CalculateMean(yesExamples); + float[] noMean = CalculateMean(noExamples); + + // Weights are the difference between means + // Features that differ more between classes get higher weight + for (int i = 0; i < featureCount; i++) + { + featureWeights[i] = yesMean[i] - noMean[i]; + } + + // Normalize weights + float weightSum = featureWeights.Sum(w => Mathf.Abs(w)); + if (weightSum > 0) + { + for (int i = 0; i < featureCount; i++) + { + featureWeights[i] /= weightSum; + } + } + + // Calculate bias as the midpoint + float yesScore = CalculateScore(yesMean); + float noScore = CalculateScore(noMean); + bias = -(yesScore + noScore) / 2f; + + isTrained = true; + } + + public (bool prediction, float confidence) Predict(OceanObjectData data) + { + if (!isTrained) + { + // Fall back to simple similarity if not trained + return PredictBySimilarity(data); + } + + float[] features = data.ToFeatureVector(); + float score = CalculateScore(features) + bias; + + // Positive score = Yes, Negative score = No + bool prediction = score >= 0; + + // Confidence based on distance from decision boundary + float confidence = Mathf.Clamp01(Mathf.Abs(score) * 2f); + + return (prediction, confidence); + } + + /// + /// Calculate weighted score for features + /// + private float CalculateScore(float[] features) + { + float score = 0; + int len = Mathf.Min(features.Length, featureWeights.Length); + + for (int i = 0; i < len; i++) + { + score += features[i] * featureWeights[i]; + } + + return score; + } + + /// + /// Calculate mean feature vector + /// + private float[] CalculateMean(List examples) + { + if (examples.Count == 0) + return new float[0]; + + int featureCount = examples[0].features.Length; + float[] mean = new float[featureCount]; + + foreach (var example in examples) + { + for (int i = 0; i < featureCount; i++) + { + mean[i] += example.features[i]; + } + } + + for (int i = 0; i < featureCount; i++) + { + mean[i] /= examples.Count; + } + + return mean; + } + + /// + /// Fallback prediction using simple similarity + /// + private (bool prediction, float confidence) PredictBySimilarity(OceanObjectData data) + { + if (yesExamples.Count == 0 && noExamples.Count == 0) + { + return (true, 0.5f); + } + + float[] queryFeatures = data.ToFeatureVector(); + + float yesAvgDist = yesExamples.Count > 0 + ? yesExamples.Average(e => CalculateDistance(queryFeatures, e.features)) + : float.MaxValue; + + float noAvgDist = noExamples.Count > 0 + ? noExamples.Average(e => CalculateDistance(queryFeatures, e.features)) + : float.MaxValue; + + bool prediction = yesAvgDist <= noAvgDist; + float totalDist = yesAvgDist + noAvgDist; + float confidence = totalDist > 0 + ? Mathf.Abs(yesAvgDist - noAvgDist) / totalDist + : 0.5f; + + return (prediction, confidence); + } + + /// + /// Calculate Euclidean distance + /// + private float CalculateDistance(float[] a, float[] b) + { + int minLen = Mathf.Min(a.Length, b.Length); + float sum = 0; + + for (int i = 0; i < minLen; i++) + { + sum += Mathf.Pow(a[i] - b[i], 2); + } + + return Mathf.Sqrt(sum); + } + + public int GetExampleCount(GameConstants.ClassLabel label) + { + return label == GameConstants.ClassLabel.Yes ? yesExamples.Count : noExamples.Count; + } + + public void ClearAll() + { + yesExamples.Clear(); + noExamples.Clear(); + featureWeights = null; + bias = 0f; + isTrained = false; + } + + /// + /// Get feature weights for visualization (like original SVM) + /// + public float[] GetFeatureWeights() + { + return featureWeights ?? new float[0]; + } + + /// + /// Get feature importance for a specific prediction + /// + public Dictionary GetFeatureImportance() + { + if (featureWeights == null) + return new Dictionary(); + + var importance = new Dictionary + { + { "body", Mathf.Abs(featureWeights[0]) }, + { "eyes", Mathf.Abs(featureWeights[1]) }, + { "mouth", Mathf.Abs(featureWeights[2]) }, + { "dorsalFin", Mathf.Abs(featureWeights[3]) }, + { "pectoralFin", Mathf.Abs(featureWeights[4]) }, + { "tailFin", Mathf.Abs(featureWeights[5]) }, + { "primaryColor", (Mathf.Abs(featureWeights[6]) + Mathf.Abs(featureWeights[7]) + Mathf.Abs(featureWeights[8])) / 3f }, + { "secondaryColor", (Mathf.Abs(featureWeights[9]) + Mathf.Abs(featureWeights[10]) + Mathf.Abs(featureWeights[11])) / 3f }, + { "finColor", (Mathf.Abs(featureWeights[12]) + Mathf.Abs(featureWeights[13]) + Mathf.Abs(featureWeights[14])) / 3f } + }; + + return importance; + } + } +} diff --git a/Unity/AIForOceans/Assets/Scripts/Core/GameConstants.cs b/Unity/AIForOceans/Assets/Scripts/Core/GameConstants.cs new file mode 100644 index 00000000..9a9082e7 --- /dev/null +++ b/Unity/AIForOceans/Assets/Scripts/Core/GameConstants.cs @@ -0,0 +1,109 @@ +using UnityEngine; + +namespace AIForOceans +{ + /// + /// Game-wide constants matching the original JavaScript implementation + /// + public static class GameConstants + { + // App Modes (Game Levels) + public enum AppMode + { + FishVTrash, // Basic fish vs trash classification + CreaturesVTrashDemo, // Demo showing AI bias + CreaturesVTrash, // Fish + creatures vs trash + Short, // 6 adjectives, SVM + Long // 15 adjectives, SVM + } + + // Scene/Mode states + public enum GameScene + { + Loading, + Words, + Training, + Predicting, + Pond, + IntermediateLoading + } + + // Object types in the ocean + public enum OceanObjectType + { + Fish, + Creature, + Trash + } + + // Classification labels + public enum ClassLabel + { + Yes = 1, + No = 0 + } + + // Fish component counts (matching original) + public const int BODY_COUNT = 19; + public const int EYES_COUNT = 18; + public const int MOUTH_COUNT = 15; + public const int DORSAL_FIN_COUNT = 17; + public const int PECTORAL_FIN_COUNT = 17; + public const int TAIL_FIN_COUNT = 17; + + // Creature types + public static readonly string[] CREATURE_TYPES = new string[] + { + "Crab", "Dolphin", "Jellyfish", "Octopus", "Otter", + "Seahorse", "Snail", "Starfish", "Turtle", "Whale" + }; + + // Trash types + public static readonly string[] TRASH_TYPES = new string[] + { + "6-pack-rings", "Apple", "Banana", "Battery", "Bottle", + "Bulb", "Can", "Coffee", "Fork", "Laundry", "Sock", + "Soda", "Tire", "Wing" + }; + + // Word choices for Short mode (6 adjectives) + public static readonly string[] SHORT_WORDS = new string[] + { + "blue", "orange", "striped", "spotted", "long", "round" + }; + + // Word choices for Long mode (15 adjectives) + public static readonly string[] LONG_WORDS = new string[] + { + "blue", "orange", "striped", "spotted", "long", "round", + "green", "purple", "scary", "friendly", "big", "small", + "fast", "slow", "colorful" + }; + + // Animation constants + public const float BOB_AMPLITUDE = 10f; + public const float BOB_FREQUENCY = 2f; + public const float FISH_SPEED = 100f; + public const float SCAN_PAUSE_DURATION = 1.5f; + + // Training counts per mode + public const int FISH_V_TRASH_TRAINING_COUNT = 6; + public const int CREATURES_V_TRASH_TRAINING_COUNT = 8; + public const int SHORT_TRAINING_COUNT = 30; + public const int LONG_TRAINING_COUNT = 100; + + // UI constants + public const float CANVAS_WIDTH = 400f; + public const float CANVAS_HEIGHT = 400f; + public const float UI_SCALE_FACTOR = 1f; + + // Prediction confidence thresholds + public const float HIGH_CONFIDENCE_THRESHOLD = 0.7f; + public const float LOW_CONFIDENCE_THRESHOLD = 0.3f; + + // Colors for prediction frames + public static readonly Color GREEN_FRAME = new Color(0.2f, 0.8f, 0.2f); // Correct/Yes + public static readonly Color RED_FRAME = new Color(0.8f, 0.2f, 0.2f); // Wrong/No + public static readonly Color BLUE_FRAME = new Color(0.2f, 0.4f, 0.8f); // Uncertain + } +} diff --git a/Unity/AIForOceans/Assets/Scripts/Core/GameInitializer.cs b/Unity/AIForOceans/Assets/Scripts/Core/GameInitializer.cs new file mode 100644 index 00000000..78a313f3 --- /dev/null +++ b/Unity/AIForOceans/Assets/Scripts/Core/GameInitializer.cs @@ -0,0 +1,52 @@ +using UnityEngine; + +namespace AIForOceans +{ + /// + /// Initializes the game on startup + /// + public class GameInitializer : MonoBehaviour + { + [Header("Managers")] + public GameObject gameManagerPrefab; + public GameObject soundManagerPrefab; + public GameObject localizationPrefab; + + [Header("Initial Settings")] + public GameConstants.AppMode defaultMode = GameConstants.AppMode.FishVTrash; + public bool autoStartGame = false; + + private void Awake() + { + // Ensure managers exist + EnsureManagerExists(gameManagerPrefab); + EnsureManagerExists(soundManagerPrefab); + EnsureManagerExists(localizationPrefab); + } + + private void Start() + { + if (autoStartGame && GameManager.Instance != null) + { + GameManager.Instance.StartGame(defaultMode); + } + } + + private void EnsureManagerExists(GameObject prefab) where T : MonoBehaviour + { + if (FindFirstObjectByType() == null) + { + if (prefab != null) + { + Instantiate(prefab); + } + else + { + // Create empty manager + var obj = new GameObject(typeof(T).Name); + obj.AddComponent(); + } + } + } + } +} diff --git a/Unity/AIForOceans/Assets/Scripts/Core/GameManager.cs b/Unity/AIForOceans/Assets/Scripts/Core/GameManager.cs new file mode 100644 index 00000000..8e3929be --- /dev/null +++ b/Unity/AIForOceans/Assets/Scripts/Core/GameManager.cs @@ -0,0 +1,256 @@ +using System; +using UnityEngine; + +namespace AIForOceans +{ + /// + /// Main game manager singleton - handles state and scene transitions + /// + public class GameManager : MonoBehaviour + { + public static GameManager Instance { get; private set; } + + // Events for state changes + public event Action OnSceneChanged; + public event Action OnStateChanged; + public event Action OnTrainingExampleAdded; + public event Action OnPredictionMade; + + // Current game state + public GameState State { get; private set; } + + // Scene controller reference + private SceneController sceneController; + + private void Awake() + { + // Singleton pattern + if (Instance != null && Instance != this) + { + Destroy(gameObject); + return; + } + Instance = this; + DontDestroyOnLoad(gameObject); + + // Initialize state + State = new GameState(); + } + + private void Start() + { + sceneController = GetComponent(); + if (sceneController == null) + { + sceneController = gameObject.AddComponent(); + } + } + + /// + /// Start a new game with the specified mode + /// + public void StartGame(GameConstants.AppMode mode) + { + State.Reset(); + State.appMode = mode; + State.totalTrainingCount = State.GetTrainingCountForMode(); + + // Initialize appropriate trainer + InitializeTrainer(); + + // Generate initial fish data + GenerateFishData(); + + // Start with loading or words scene + if (mode == GameConstants.AppMode.Short || mode == GameConstants.AppMode.Long) + { + ChangeScene(GameConstants.GameScene.Words); + } + else if (mode == GameConstants.AppMode.CreaturesVTrashDemo) + { + // Demo skips training + ChangeScene(GameConstants.GameScene.Predicting); + } + else + { + ChangeScene(GameConstants.GameScene.Training); + } + + OnStateChanged?.Invoke(State); + } + + /// + /// Initialize the appropriate trainer for current mode + /// + private void InitializeTrainer() + { + if (State.appMode == GameConstants.AppMode.Short || + State.appMode == GameConstants.AppMode.Long) + { + State.trainer = new NaiveSVMClassifier(); + } + else + { + State.trainer = new NaiveKNNClassifier(); + } + } + + /// + /// Generate fish/objects for the current mode + /// + private void GenerateFishData() + { + State.fishData.Clear(); + + int count = State.totalTrainingCount + 20; // Training + prediction items + + bool includeFish = true; + bool includeCreatures = State.appMode == GameConstants.AppMode.CreaturesVTrash || + State.appMode == GameConstants.AppMode.CreaturesVTrashDemo; + bool includeTrash = State.appMode != GameConstants.AppMode.Short && + State.appMode != GameConstants.AppMode.Long; + + var generator = new OceanGenerator(); + State.fishData = generator.GenerateOcean(count, includeFish, includeCreatures, includeTrash); + } + + /// + /// Change to a new scene + /// + public void ChangeScene(GameConstants.GameScene newScene) + { + State.currentScene = newScene; + OnSceneChanged?.Invoke(newScene); + OnStateChanged?.Invoke(State); + } + + /// + /// Add a training example + /// + public void AddTrainingExample(OceanObjectData data, bool isYes) + { + State.trainer.AddExample(data, isYes ? GameConstants.ClassLabel.Yes : GameConstants.ClassLabel.No); + State.trainingIndex++; + + OnTrainingExampleAdded?.Invoke(data, isYes); + OnStateChanged?.Invoke(State); + + // Check if training is complete + if (State.trainingIndex >= State.totalTrainingCount) + { + OnTrainingComplete(); + } + } + + /// + /// Called when training is complete + /// + private void OnTrainingComplete() + { + // Train the model (for SVM) + State.trainer.Train(); + + // Move to prediction phase + if (State.appMode == GameConstants.AppMode.Short || + State.appMode == GameConstants.AppMode.Long) + { + ChangeScene(GameConstants.GameScene.IntermediateLoading); + } + else + { + ChangeScene(GameConstants.GameScene.Predicting); + } + } + + /// + /// Make a prediction on an object + /// + public PredictionResult MakePrediction(OceanObjectData data) + { + var (prediction, confidence) = State.trainer.Predict(data); + var result = new PredictionResult(data, prediction, confidence); + + // Determine if correct based on mode + result.isCorrect = DetermineCorrectness(data, prediction); + + State.pondResults.Add(result); + OnPredictionMade?.Invoke(result); + + return result; + } + + /// + /// Determine if a prediction is correct + /// + private bool DetermineCorrectness(OceanObjectData data, bool prediction) + { + switch (State.appMode) + { + case GameConstants.AppMode.FishVTrash: + // Yes = Fish, No = Trash + bool isFishOrCreature = data.objectType != GameConstants.OceanObjectType.Trash; + return prediction == isFishOrCreature; + + case GameConstants.AppMode.CreaturesVTrash: + case GameConstants.AppMode.CreaturesVTrashDemo: + // Yes = Fish/Creature, No = Trash + bool isNotTrash = data.objectType != GameConstants.OceanObjectType.Trash; + return prediction == isNotTrash; + + case GameConstants.AppMode.Short: + case GameConstants.AppMode.Long: + // Subjective - based on selected word + // This would need attribute checking + return true; // Simplified for now + + default: + return true; + } + } + + /// + /// Select a word for Short/Long modes + /// + public void SelectWord(string word) + { + State.selectedWord = word; + ChangeScene(GameConstants.GameScene.Training); + OnStateChanged?.Invoke(State); + } + + /// + /// Move to pond/results scene + /// + public void ShowResults() + { + ChangeScene(GameConstants.GameScene.Pond); + } + + /// + /// Select a fish in the pond to view details + /// + public void SelectPondFish(OceanObjectData fish) + { + State.selectedPondFish = fish; + OnStateChanged?.Invoke(State); + } + + /// + /// Toggle guide visibility + /// + public void ToggleGuide(bool show) + { + State.guideShowing = show; + OnStateChanged?.Invoke(State); + } + + /// + /// Advance to next guide + /// + public void NextGuide() + { + State.guideIndex++; + OnStateChanged?.Invoke(State); + } + } +} diff --git a/Unity/AIForOceans/Assets/Scripts/Core/GameState.cs b/Unity/AIForOceans/Assets/Scripts/Core/GameState.cs new file mode 100644 index 00000000..8e2e1755 --- /dev/null +++ b/Unity/AIForOceans/Assets/Scripts/Core/GameState.cs @@ -0,0 +1,93 @@ +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace AIForOceans +{ + /// + /// Central game state - mirrors the original state.js + /// + [Serializable] + public class GameState + { + // Current mode and scene + public GameConstants.AppMode appMode = GameConstants.AppMode.FishVTrash; + public GameConstants.GameScene currentScene = GameConstants.GameScene.Loading; + + // Training state + public int trainingIndex = 0; + public int totalTrainingCount = 0; + public string selectedWord = ""; + + // Fish/object data + public List fishData = new List(); + public List pondResults = new List(); + + // Animation state + public bool isRunning = false; + public bool isPaused = false; + public float currentTime = 0f; + + // UI state + public bool guideShowing = false; + public int guideIndex = 0; + public OceanObjectData selectedPondFish = null; + + // Trainer reference (set at runtime) + [NonSerialized] + public ITrainer trainer; + + /// + /// Reset state for a new game + /// + public void Reset() + { + trainingIndex = 0; + fishData.Clear(); + pondResults.Clear(); + isRunning = false; + isPaused = false; + currentTime = 0f; + guideShowing = false; + guideIndex = 0; + selectedPondFish = null; + trainer?.ClearAll(); + } + + /// + /// Get training count for current mode + /// + public int GetTrainingCountForMode() + { + return appMode switch + { + GameConstants.AppMode.FishVTrash => GameConstants.FISH_V_TRASH_TRAINING_COUNT, + GameConstants.AppMode.CreaturesVTrashDemo => 0, // No training in demo + GameConstants.AppMode.CreaturesVTrash => GameConstants.CREATURES_V_TRASH_TRAINING_COUNT, + GameConstants.AppMode.Short => GameConstants.SHORT_TRAINING_COUNT, + GameConstants.AppMode.Long => GameConstants.LONG_TRAINING_COUNT, + _ => 6 + }; + } + } + + /// + /// Result of a prediction + /// + [Serializable] + public class PredictionResult + { + public OceanObjectData objectData; + public bool prediction; + public float confidence; + public bool isCorrect; + + public PredictionResult(OceanObjectData data, bool pred, float conf) + { + objectData = data; + prediction = pred; + confidence = conf; + isCorrect = false; // Set based on context + } + } +} diff --git a/Unity/AIForOceans/Assets/Scripts/Core/SceneController.cs b/Unity/AIForOceans/Assets/Scripts/Core/SceneController.cs new file mode 100644 index 00000000..d885dde6 --- /dev/null +++ b/Unity/AIForOceans/Assets/Scripts/Core/SceneController.cs @@ -0,0 +1,168 @@ +using System; +using System.Collections; +using UnityEngine; + +namespace AIForOceans +{ + /// + /// Handles scene/mode transitions and UI management + /// + public class SceneController : MonoBehaviour + { + // References to scene UI containers (set in inspector or found at runtime) + public GameObject loadingUI; + public GameObject wordsUI; + public GameObject trainingUI; + public GameObject predictingUI; + public GameObject pondUI; + public GameObject intermediateLoadingUI; + + // Current active scene + private GameConstants.GameScene currentScene; + + private void Start() + { + // Subscribe to scene changes + if (GameManager.Instance != null) + { + GameManager.Instance.OnSceneChanged += HandleSceneChange; + } + } + + private void OnDestroy() + { + if (GameManager.Instance != null) + { + GameManager.Instance.OnSceneChanged -= HandleSceneChange; + } + } + + /// + /// Handle scene change events + /// + private void HandleSceneChange(GameConstants.GameScene newScene) + { + StartCoroutine(TransitionToScene(newScene)); + } + + /// + /// Transition to a new scene with optional fade + /// + private IEnumerator TransitionToScene(GameConstants.GameScene newScene) + { + // Hide current scene + HideAllScenes(); + + // Small delay for transition effect + yield return new WaitForSeconds(0.1f); + + // Show new scene + currentScene = newScene; + ShowScene(newScene); + + // Initialize scene-specific logic + InitializeScene(newScene); + } + + /// + /// Hide all scene UIs + /// + private void HideAllScenes() + { + SetActiveIfNotNull(loadingUI, false); + SetActiveIfNotNull(wordsUI, false); + SetActiveIfNotNull(trainingUI, false); + SetActiveIfNotNull(predictingUI, false); + SetActiveIfNotNull(pondUI, false); + SetActiveIfNotNull(intermediateLoadingUI, false); + } + + /// + /// Show specific scene UI + /// + private void ShowScene(GameConstants.GameScene scene) + { + switch (scene) + { + case GameConstants.GameScene.Loading: + SetActiveIfNotNull(loadingUI, true); + break; + case GameConstants.GameScene.Words: + SetActiveIfNotNull(wordsUI, true); + break; + case GameConstants.GameScene.Training: + SetActiveIfNotNull(trainingUI, true); + break; + case GameConstants.GameScene.Predicting: + SetActiveIfNotNull(predictingUI, true); + break; + case GameConstants.GameScene.Pond: + SetActiveIfNotNull(pondUI, true); + break; + case GameConstants.GameScene.IntermediateLoading: + SetActiveIfNotNull(intermediateLoadingUI, true); + break; + } + } + + /// + /// Initialize scene-specific behavior + /// + private void InitializeScene(GameConstants.GameScene scene) + { + switch (scene) + { + case GameConstants.GameScene.Loading: + StartCoroutine(HandleLoading()); + break; + case GameConstants.GameScene.IntermediateLoading: + StartCoroutine(HandleIntermediateLoading()); + break; + case GameConstants.GameScene.Predicting: + // Start prediction animation + break; + } + } + + /// + /// Handle initial loading + /// + private IEnumerator HandleLoading() + { + // Simulate asset loading + yield return new WaitForSeconds(1f); + + // Move to next appropriate scene + var state = GameManager.Instance.State; + if (state.appMode == GameConstants.AppMode.Short || + state.appMode == GameConstants.AppMode.Long) + { + GameManager.Instance.ChangeScene(GameConstants.GameScene.Words); + } + else + { + GameManager.Instance.ChangeScene(GameConstants.GameScene.Training); + } + } + + /// + /// Handle intermediate loading (SVM training) + /// + private IEnumerator HandleIntermediateLoading() + { + // Show loading while "training" happens + yield return new WaitForSeconds(1.5f); + + // Move to prediction + GameManager.Instance.ChangeScene(GameConstants.GameScene.Predicting); + } + + private void SetActiveIfNotNull(GameObject obj, bool active) + { + if (obj != null) + { + obj.SetActive(active); + } + } + } +} diff --git a/Unity/AIForOceans/Assets/Scripts/Data/CreatureRenderer.cs b/Unity/AIForOceans/Assets/Scripts/Data/CreatureRenderer.cs new file mode 100644 index 00000000..5bf8237e --- /dev/null +++ b/Unity/AIForOceans/Assets/Scripts/Data/CreatureRenderer.cs @@ -0,0 +1,80 @@ +using UnityEngine; + +namespace AIForOceans +{ + /// + /// Renders sea creatures and trash items (single sprite) + /// + public class CreatureRenderer : MonoBehaviour + { + [Header("Sprite Renderer")] + public SpriteRenderer spriteRenderer; + + [Header("Creature Sprites")] + public Sprite[] creatureSprites; // Index matches CREATURE_TYPES + public Sprite[] trashSprites; // Index matches TRASH_TYPES + + private OceanObjectData currentData; + + /// + /// Set up the visual from data + /// + public void Setup(OceanObjectData data) + { + currentData = data; + + if (spriteRenderer == null) + { + spriteRenderer = GetComponent(); + } + + if (spriteRenderer == null) return; + + if (data.objectType == GameConstants.OceanObjectType.Creature) + { + SetCreatureSprite(data.subType); + } + else if (data.objectType == GameConstants.OceanObjectType.Trash) + { + SetTrashSprite(data.subType); + } + } + + private void SetCreatureSprite(string creatureType) + { + int index = System.Array.IndexOf(GameConstants.CREATURE_TYPES, creatureType); + if (index >= 0 && creatureSprites != null && index < creatureSprites.Length) + { + spriteRenderer.sprite = creatureSprites[index]; + } + } + + private void SetTrashSprite(string trashType) + { + int index = System.Array.IndexOf(GameConstants.TRASH_TYPES, trashType); + if (index >= 0 && trashSprites != null && index < trashSprites.Length) + { + spriteRenderer.sprite = trashSprites[index]; + } + } + + /// + /// Set visibility + /// + public void SetVisible(bool visible) + { + gameObject.SetActive(visible); + } + + /// + /// Set sorting order + /// + public void SetSortingOrder(int order) + { + if (spriteRenderer != null) + { + spriteRenderer.sortingOrder = order; + } + } + } +} diff --git a/Unity/AIForOceans/Assets/Scripts/Data/OceanGenerator.cs b/Unity/AIForOceans/Assets/Scripts/Data/OceanGenerator.cs new file mode 100644 index 00000000..b34b96cf --- /dev/null +++ b/Unity/AIForOceans/Assets/Scripts/Data/OceanGenerator.cs @@ -0,0 +1,143 @@ +using System.Collections.Generic; +using UnityEngine; + +namespace AIForOceans +{ + /// + /// Generates random ocean objects for the game + /// + public class OceanGenerator + { + /// + /// Generate a collection of ocean objects + /// + public List GenerateOcean( + int count, + bool includeFish = true, + bool includeCreatures = false, + bool includeTrash = true) + { + var objects = new List(); + + for (int i = 0; i < count; i++) + { + OceanObjectData obj = GenerateRandomObject(i, includeFish, includeCreatures, includeTrash); + objects.Add(obj); + } + + // Shuffle the list + ShuffleList(objects); + + return objects; + } + + /// + /// Generate a single random object based on allowed types + /// + private OceanObjectData GenerateRandomObject( + int id, + bool includeFish, + bool includeCreatures, + bool includeTrash) + { + // Build list of possible types + var possibleTypes = new List(); + + if (includeFish) + possibleTypes.Add(GameConstants.OceanObjectType.Fish); + if (includeCreatures) + possibleTypes.Add(GameConstants.OceanObjectType.Creature); + if (includeTrash) + possibleTypes.Add(GameConstants.OceanObjectType.Trash); + + if (possibleTypes.Count == 0) + { + // Default to fish if nothing selected + return OceanObjectData.CreateRandomFish(id); + } + + // Weight fish higher for better game balance + if (includeFish && (includeCreatures || includeTrash)) + { + // 60% fish, rest split between others + float roll = Random.value; + if (roll < 0.6f) + { + return OceanObjectData.CreateRandomFish(id); + } + else if (includeCreatures && includeTrash) + { + if (roll < 0.8f) + return OceanObjectData.CreateCreature(id); + else + return OceanObjectData.CreateTrash(id); + } + else if (includeCreatures) + { + return OceanObjectData.CreateCreature(id); + } + else + { + return OceanObjectData.CreateTrash(id); + } + } + + // Equal distribution + var selectedType = possibleTypes[Random.Range(0, possibleTypes.Count)]; + + return selectedType switch + { + GameConstants.OceanObjectType.Fish => OceanObjectData.CreateRandomFish(id), + GameConstants.OceanObjectType.Creature => OceanObjectData.CreateCreature(id), + GameConstants.OceanObjectType.Trash => OceanObjectData.CreateTrash(id), + _ => OceanObjectData.CreateRandomFish(id) + }; + } + + /// + /// Generate objects specifically for training + /// + public List GenerateTrainingSet( + int count, + GameConstants.AppMode mode) + { + bool includeFish = true; + bool includeCreatures = mode == GameConstants.AppMode.CreaturesVTrash || + mode == GameConstants.AppMode.CreaturesVTrashDemo; + bool includeTrash = mode != GameConstants.AppMode.Short && + mode != GameConstants.AppMode.Long; + + // For word modes, only fish + if (mode == GameConstants.AppMode.Short || mode == GameConstants.AppMode.Long) + { + includeCreatures = false; + includeTrash = false; + } + + return GenerateOcean(count, includeFish, includeCreatures, includeTrash); + } + + /// + /// Generate objects for prediction phase + /// + public List GeneratePredictionSet( + int count, + GameConstants.AppMode mode) + { + // Similar to training but may have different distribution + return GenerateTrainingSet(count, mode); + } + + /// + /// Fisher-Yates shuffle + /// + private void ShuffleList(List list) + { + for (int i = list.Count - 1; i > 0; i--) + { + int j = Random.Range(0, i + 1); + (list[i], list[j]) = (list[j], list[i]); + } + } + } +} diff --git a/Unity/AIForOceans/Assets/Scripts/Data/OceanObjectData.cs b/Unity/AIForOceans/Assets/Scripts/Data/OceanObjectData.cs new file mode 100644 index 00000000..1506b767 --- /dev/null +++ b/Unity/AIForOceans/Assets/Scripts/Data/OceanObjectData.cs @@ -0,0 +1,219 @@ +using System; +using UnityEngine; + +namespace AIForOceans +{ + /// + /// Data structure for any ocean object (fish, creature, trash) + /// + [Serializable] + public class OceanObjectData + { + // Basic info + public int id; + public GameConstants.OceanObjectType objectType; + public string name; + + // Fish-specific components (indices into sprite arrays) + public int bodyIndex; + public int eyesIndex; + public int mouthIndex; + public int dorsalFinIndex; + public int pectoralFinIndex; + public int tailFinIndex; + public int scalesIndex; + + // Colors + public Color primaryColor; + public Color secondaryColor; + public Color finColor; + + // For creatures/trash - the specific type name + public string subType; + + // Position and animation + public Vector2 position; + public float bobPhase; + public float speed; + + // Classification label (set during training) + public GameConstants.ClassLabel? label; + + /// + /// Create a random fish + /// + public static OceanObjectData CreateRandomFish(int id) + { + var fish = new OceanObjectData + { + id = id, + objectType = GameConstants.OceanObjectType.Fish, + name = $"Fish_{id}", + + // Random component indices + bodyIndex = UnityEngine.Random.Range(0, GameConstants.BODY_COUNT), + eyesIndex = UnityEngine.Random.Range(0, GameConstants.EYES_COUNT), + mouthIndex = UnityEngine.Random.Range(0, GameConstants.MOUTH_COUNT), + dorsalFinIndex = UnityEngine.Random.Range(0, GameConstants.DORSAL_FIN_COUNT), + pectoralFinIndex = UnityEngine.Random.Range(0, GameConstants.PECTORAL_FIN_COUNT), + tailFinIndex = UnityEngine.Random.Range(0, GameConstants.TAIL_FIN_COUNT), + scalesIndex = UnityEngine.Random.Range(0, 3), // Fewer scale options + + // Random colors + primaryColor = GetRandomFishColor(), + secondaryColor = GetRandomFishColor(), + finColor = GetRandomFishColor(), + + // Animation + bobPhase = UnityEngine.Random.Range(0f, Mathf.PI * 2f), + speed = GameConstants.FISH_SPEED * UnityEngine.Random.Range(0.8f, 1.2f) + }; + + return fish; + } + + /// + /// Create a creature + /// + public static OceanObjectData CreateCreature(int id, string creatureType = null) + { + if (string.IsNullOrEmpty(creatureType)) + { + int index = UnityEngine.Random.Range(0, GameConstants.CREATURE_TYPES.Length); + creatureType = GameConstants.CREATURE_TYPES[index]; + } + + return new OceanObjectData + { + id = id, + objectType = GameConstants.OceanObjectType.Creature, + name = creatureType, + subType = creatureType, + bobPhase = UnityEngine.Random.Range(0f, Mathf.PI * 2f), + speed = GameConstants.FISH_SPEED * UnityEngine.Random.Range(0.6f, 1.0f) + }; + } + + /// + /// Create trash + /// + public static OceanObjectData CreateTrash(int id, string trashType = null) + { + if (string.IsNullOrEmpty(trashType)) + { + int index = UnityEngine.Random.Range(0, GameConstants.TRASH_TYPES.Length); + trashType = GameConstants.TRASH_TYPES[index]; + } + + return new OceanObjectData + { + id = id, + objectType = GameConstants.OceanObjectType.Trash, + name = trashType, + subType = trashType, + bobPhase = UnityEngine.Random.Range(0f, Mathf.PI * 2f), + speed = GameConstants.FISH_SPEED * UnityEngine.Random.Range(0.4f, 0.8f) + }; + } + + /// + /// Get a random fish-appropriate color + /// + private static Color GetRandomFishColor() + { + // Predefined fish color palettes + Color[] fishColors = new Color[] + { + new Color(0.2f, 0.6f, 1.0f), // Blue + new Color(1.0f, 0.6f, 0.2f), // Orange + new Color(0.2f, 0.8f, 0.4f), // Green + new Color(0.8f, 0.2f, 0.8f), // Purple + new Color(1.0f, 1.0f, 0.2f), // Yellow + new Color(1.0f, 0.4f, 0.4f), // Red/Pink + new Color(0.4f, 0.8f, 0.8f), // Cyan + new Color(0.6f, 0.4f, 0.2f), // Brown + }; + + return fishColors[UnityEngine.Random.Range(0, fishColors.Length)]; + } + + /// + /// Convert to feature vector for classification + /// + public float[] ToFeatureVector() + { + if (objectType == GameConstants.OceanObjectType.Fish) + { + // Feature vector includes all fish attributes + return new float[] + { + bodyIndex / (float)GameConstants.BODY_COUNT, + eyesIndex / (float)GameConstants.EYES_COUNT, + mouthIndex / (float)GameConstants.MOUTH_COUNT, + dorsalFinIndex / (float)GameConstants.DORSAL_FIN_COUNT, + pectoralFinIndex / (float)GameConstants.PECTORAL_FIN_COUNT, + tailFinIndex / (float)GameConstants.TAIL_FIN_COUNT, + primaryColor.r, + primaryColor.g, + primaryColor.b, + secondaryColor.r, + secondaryColor.g, + secondaryColor.b, + finColor.r, + finColor.g, + finColor.b + }; + } + else + { + // For creatures/trash, use a simpler encoding + float typeValue = objectType == GameConstants.OceanObjectType.Creature ? 0.5f : 1.0f; + return new float[] { typeValue, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + } + } + + /// + /// Check if fish has a specific attribute (for word modes) + /// + public bool HasAttribute(string attribute) + { + if (objectType != GameConstants.OceanObjectType.Fish) + return false; + + attribute = attribute.ToLower(); + + return attribute switch + { + "blue" => IsColorDominant(Color.blue), + "orange" => IsColorDominant(new Color(1f, 0.5f, 0f)), + "green" => IsColorDominant(Color.green), + "purple" => IsColorDominant(new Color(0.5f, 0f, 0.5f)), + "yellow" => IsColorDominant(Color.yellow), + "red" => IsColorDominant(Color.red), + "striped" => scalesIndex == 1, + "spotted" => scalesIndex == 2, + "long" => bodyIndex >= GameConstants.BODY_COUNT / 2, + "round" => bodyIndex < GameConstants.BODY_COUNT / 2, + "big" => bodyIndex >= GameConstants.BODY_COUNT * 2 / 3, + "small" => bodyIndex < GameConstants.BODY_COUNT / 3, + _ => false + }; + } + + private bool IsColorDominant(Color targetColor) + { + float threshold = 0.4f; + return ColorDistance(primaryColor, targetColor) < threshold || + ColorDistance(secondaryColor, targetColor) < threshold; + } + + private float ColorDistance(Color a, Color b) + { + return Mathf.Sqrt( + Mathf.Pow(a.r - b.r, 2) + + Mathf.Pow(a.g - b.g, 2) + + Mathf.Pow(a.b - b.b, 2) + ); + } + } +} diff --git a/Unity/AIForOceans/Assets/Scripts/Scenes/PredictionSceneController.cs b/Unity/AIForOceans/Assets/Scripts/Scenes/PredictionSceneController.cs new file mode 100644 index 00000000..bda47818 --- /dev/null +++ b/Unity/AIForOceans/Assets/Scripts/Scenes/PredictionSceneController.cs @@ -0,0 +1,199 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +namespace AIForOceans +{ + /// + /// Controls the prediction scene flow + /// + public class PredictionSceneController : MonoBehaviour + { + [Header("References")] + public FishRenderer fishRenderer; + public FishAnimator fishAnimator; + public AIBot aiBot; + public PredictionUI predictionUI; + + [Header("Animation Settings")] + public Vector2 spawnPosition = new Vector2(-200f, 0f); + public Vector2 scanPosition = new Vector2(0f, 0f); + public Vector2 exitPosition = new Vector2(200f, 0f); + public float swimSpeed = 100f; + public float scanDuration = 1.5f; + public float delayBetweenFish = 0.5f; + + [Header("Prediction Settings")] + public int fishToPredictCount = 20; + + private Queue fishQueue; + private bool isRunning = false; + private int predictedCount = 0; + + private void OnEnable() + { + StartPredictions(); + } + + private void OnDisable() + { + StopPredictions(); + } + + /// + /// Start the prediction sequence + /// + public void StartPredictions() + { + if (isRunning) return; + + var state = GameManager.Instance.State; + + // Get fish for prediction (skip training fish) + fishQueue = new Queue(); + int startIndex = state.totalTrainingCount; + + for (int i = startIndex; i < state.fishData.Count && i < startIndex + fishToPredictCount; i++) + { + fishQueue.Enqueue(state.fishData[i]); + } + + predictedCount = 0; + isRunning = true; + + StartCoroutine(RunPredictionLoop()); + } + + /// + /// Stop predictions + /// + public void StopPredictions() + { + isRunning = false; + StopAllCoroutines(); + } + + /// + /// Main prediction loop + /// + private IEnumerator RunPredictionLoop() + { + while (isRunning && fishQueue.Count > 0) + { + OceanObjectData fish = fishQueue.Dequeue(); + yield return StartCoroutine(ProcessFish(fish)); + yield return new WaitForSeconds(delayBetweenFish); + } + + // All predictions complete + isRunning = false; + OnAllPredictionsComplete(); + } + + /// + /// Process a single fish through prediction + /// + private IEnumerator ProcessFish(OceanObjectData fish) + { + // Set up fish visual + if (fishRenderer != null && fish.objectType == GameConstants.OceanObjectType.Fish) + { + fishRenderer.SetupFish(fish); + } + + // Swim in from left + yield return StartCoroutine(SwimTo(spawnPosition, scanPosition, 1f)); + + // AI scans the fish + if (aiBot != null) + { + aiBot.SetExpression(AIBot.Expression.Scanning); + } + + if (predictionUI != null) + { + predictionUI.ShowScanning(); + } + + // Play scan sound + if (SoundManager.Instance != null) + { + SoundManager.Instance.PlayScan(); + } + + // Wait for scan + yield return new WaitForSeconds(scanDuration); + + // Make prediction + PredictionResult result = GameManager.Instance.MakePrediction(fish); + predictedCount++; + + // AI reacts + if (aiBot != null) + { + aiBot.SetExpression(result.prediction ? AIBot.Expression.Yes : AIBot.Expression.No); + } + + // Brief pause to show result + yield return new WaitForSeconds(0.5f); + + // Swim out + yield return StartCoroutine(SwimTo(scanPosition, exitPosition, 0.5f)); + } + + /// + /// Animate swimming from one position to another + /// + private IEnumerator SwimTo(Vector2 from, Vector2 to, float duration) + { + if (fishRenderer == null) yield break; + + Transform fishTransform = fishRenderer.transform; + fishTransform.position = from; + + float elapsed = 0f; + + while (elapsed < duration) + { + elapsed += Time.deltaTime; + float t = FishAnimator.SCurve(elapsed / duration); + fishTransform.position = Vector2.Lerp(from, to, t); + yield return null; + } + + fishTransform.position = to; + } + + /// + /// Called when all predictions are complete + /// + private void OnAllPredictionsComplete() + { + // Hide prediction UI + if (predictionUI != null) + { + predictionUI.Hide(); + } + + // Move to pond scene + GameManager.Instance.ShowResults(); + } + + /// + /// Skip to results immediately + /// + public void SkipToResults() + { + StopPredictions(); + + // Make remaining predictions instantly + while (fishQueue != null && fishQueue.Count > 0) + { + OceanObjectData fish = fishQueue.Dequeue(); + GameManager.Instance.MakePrediction(fish); + } + + OnAllPredictionsComplete(); + } + } +} diff --git a/Unity/AIForOceans/Assets/Scripts/Scenes/TrainingSceneController.cs b/Unity/AIForOceans/Assets/Scripts/Scenes/TrainingSceneController.cs new file mode 100644 index 00000000..547e2f41 --- /dev/null +++ b/Unity/AIForOceans/Assets/Scripts/Scenes/TrainingSceneController.cs @@ -0,0 +1,186 @@ +using System.Collections; +using UnityEngine; + +namespace AIForOceans +{ + /// + /// Controls the training scene flow + /// + public class TrainingSceneController : MonoBehaviour + { + [Header("References")] + public FishRenderer currentFishRenderer; + public FishAnimator currentFishAnimator; + public AIBot aiBot; + public TrainingUI trainingUI; + + [Header("Spawn Settings")] + public Vector2 spawnPosition = new Vector2(-200f, 0f); + public Vector2 centerPosition = new Vector2(0f, 0f); + public float fishEnterDuration = 1f; + + private OceanObjectData currentFish; + private bool isAnimating = false; + + private void OnEnable() + { + // Subscribe to events + if (GameManager.Instance != null) + { + GameManager.Instance.OnTrainingExampleAdded += OnExampleAdded; + } + + // Show first fish + ShowNextFish(); + } + + private void OnDisable() + { + if (GameManager.Instance != null) + { + GameManager.Instance.OnTrainingExampleAdded -= OnExampleAdded; + } + } + + /// + /// Show the next fish in the training sequence + /// + private void ShowNextFish() + { + var state = GameManager.Instance.State; + + if (state.trainingIndex >= state.fishData.Count) + { + Debug.LogWarning("No more fish to show"); + return; + } + + currentFish = state.fishData[state.trainingIndex]; + + // Set up the fish renderer + if (currentFishRenderer != null) + { + if (currentFish.objectType == GameConstants.OceanObjectType.Fish) + { + currentFishRenderer.SetupFish(currentFish); + } + // For creatures/trash, would need different rendering + } + + // Animate fish entering + StartCoroutine(AnimateFishEnter()); + } + + /// + /// Animate fish swimming in from left + /// + private IEnumerator AnimateFishEnter() + { + isAnimating = true; + + if (currentFishRenderer == null) + { + isAnimating = false; + yield break; + } + + Transform fishTransform = currentFishRenderer.transform; + fishTransform.position = spawnPosition; + + float elapsed = 0f; + + while (elapsed < fishEnterDuration) + { + elapsed += Time.deltaTime; + float t = elapsed / fishEnterDuration; + + // Ease in-out + float easedT = FishAnimator.SCurve(t); + + fishTransform.position = Vector2.Lerp(spawnPosition, centerPosition, easedT); + yield return null; + } + + fishTransform.position = centerPosition; + isAnimating = false; + + // AI bot looks at fish + if (aiBot != null) + { + aiBot.SetExpression(AIBot.Expression.Thinking); + } + } + + /// + /// Called when user labels current fish + /// + private void OnExampleAdded(OceanObjectData data, bool isYes) + { + // AI bot reacts + if (aiBot != null) + { + aiBot.SetExpression(isYes ? AIBot.Expression.Yes : AIBot.Expression.No); + } + + // Animate fish exit and show next + StartCoroutine(AnimateFishExitAndShowNext(isYes)); + } + + /// + /// Animate fish exiting and bring in next + /// + private IEnumerator AnimateFishExitAndShowNext(bool wasYes) + { + if (currentFishRenderer == null) + yield break; + + isAnimating = true; + + Transform fishTransform = currentFishRenderer.transform; + Vector2 exitPosition = new Vector2(200f, 0f); + + float elapsed = 0f; + float exitDuration = 0.5f; + + while (elapsed < exitDuration) + { + elapsed += Time.deltaTime; + float t = elapsed / exitDuration; + float easedT = FishAnimator.SCurve(t); + + fishTransform.position = Vector2.Lerp(centerPosition, exitPosition, easedT); + yield return null; + } + + // Brief pause + yield return new WaitForSeconds(0.2f); + + // Check if more fish to show + var state = GameManager.Instance.State; + if (state.trainingIndex < state.totalTrainingCount && + state.trainingIndex < state.fishData.Count) + { + ShowNextFish(); + } + + isAnimating = false; + } + + /// + /// Skip current animation (for fast users) + /// + public void SkipAnimation() + { + if (isAnimating) + { + StopAllCoroutines(); + isAnimating = false; + + if (currentFishRenderer != null) + { + currentFishRenderer.transform.position = centerPosition; + } + } + } + } +} diff --git a/Unity/AIForOceans/Assets/Scripts/UI/AIBot.cs b/Unity/AIForOceans/Assets/Scripts/UI/AIBot.cs new file mode 100644 index 00000000..60cdfe78 --- /dev/null +++ b/Unity/AIForOceans/Assets/Scripts/UI/AIBot.cs @@ -0,0 +1,153 @@ +using System.Collections; +using UnityEngine; +using UnityEngine.UI; + +namespace AIForOceans +{ + /// + /// AI Bot character with different expression states + /// + public class AIBot : MonoBehaviour + { + public enum Expression + { + Neutral, + Thinking, + Yes, + No, + Scanning, + Closed + } + + [Header("Sprite References")] + public Image bodyImage; + public Image headImage; + public Image expressionImage; + public Image scanOverlayImage; + + [Header("Expression Sprites")] + public Sprite neutralSprite; + public Sprite thinkingSprite; + public Sprite yesSprite; + public Sprite noSprite; + public Sprite scanningSprite; + public Sprite closedSprite; + + [Header("Animation")] + public float expressionDuration = 1f; + public float bobAmplitude = 5f; + public float bobFrequency = 1f; + + private Expression currentExpression = Expression.Neutral; + private Coroutine expressionCoroutine; + private Vector3 basePosition; + + private void Start() + { + basePosition = transform.position; + SetExpression(Expression.Neutral); + + // Hide scan overlay initially + if (scanOverlayImage != null) + { + scanOverlayImage.enabled = false; + } + } + + private void Update() + { + // Gentle bobbing animation + float bobOffset = Mathf.Sin(Time.time * bobFrequency) * bobAmplitude; + transform.position = basePosition + new Vector3(0f, bobOffset, 0f); + } + + /// + /// Set the bot's expression + /// + public void SetExpression(Expression expression) + { + currentExpression = expression; + + // Update expression sprite + if (expressionImage != null) + { + expressionImage.sprite = expression switch + { + Expression.Neutral => neutralSprite, + Expression.Thinking => thinkingSprite, + Expression.Yes => yesSprite, + Expression.No => noSprite, + Expression.Scanning => scanningSprite, + Expression.Closed => closedSprite, + _ => neutralSprite + }; + } + + // Show/hide scan overlay + if (scanOverlayImage != null) + { + scanOverlayImage.enabled = expression == Expression.Scanning; + } + + // Auto-return to neutral for reactions + if (expression == Expression.Yes || expression == Expression.No) + { + if (expressionCoroutine != null) + { + StopCoroutine(expressionCoroutine); + } + expressionCoroutine = StartCoroutine(ReturnToNeutral()); + } + } + + /// + /// Return to neutral after showing expression + /// + private IEnumerator ReturnToNeutral() + { + yield return new WaitForSeconds(expressionDuration); + + if (currentExpression == Expression.Yes || currentExpression == Expression.No) + { + SetExpression(Expression.Neutral); + } + } + + /// + /// Play a celebration animation + /// + public void Celebrate() + { + StartCoroutine(CelebrationAnimation()); + } + + private IEnumerator CelebrationAnimation() + { + SetExpression(Expression.Yes); + + // Bounce animation + float duration = 0.5f; + float elapsed = 0f; + Vector3 startPos = basePosition; + + while (elapsed < duration) + { + elapsed += Time.deltaTime; + float t = elapsed / duration; + float bounce = Mathf.Sin(t * Mathf.PI * 3) * 10f * (1f - t); + transform.position = startPos + new Vector3(0f, bounce, 0f); + yield return null; + } + + transform.position = startPos; + } + + /// + /// Get current expression + /// + public Expression GetExpression() + { + return currentExpression; + } + } +} diff --git a/Unity/AIForOceans/Assets/Scripts/UI/ConfirmationDialog.cs b/Unity/AIForOceans/Assets/Scripts/UI/ConfirmationDialog.cs new file mode 100644 index 00000000..65e72637 --- /dev/null +++ b/Unity/AIForOceans/Assets/Scripts/UI/ConfirmationDialog.cs @@ -0,0 +1,133 @@ +using System; +using UnityEngine; +using UnityEngine.UI; +using TMPro; + +namespace AIForOceans +{ + /// + /// Reusable confirmation dialog + /// + public class ConfirmationDialog : MonoBehaviour + { + [Header("UI Elements")] + public GameObject dialogPanel; + public TextMeshProUGUI titleText; + public TextMeshProUGUI messageText; + public Button confirmButton; + public Button cancelButton; + public TextMeshProUGUI confirmButtonText; + public TextMeshProUGUI cancelButtonText; + + // Callbacks + private Action onConfirm; + private Action onCancel; + + private void Start() + { + // Set up button listeners + if (confirmButton != null) + { + confirmButton.onClick.AddListener(OnConfirmClicked); + } + + if (cancelButton != null) + { + cancelButton.onClick.AddListener(OnCancelClicked); + } + + // Hide by default + Hide(); + } + + /// + /// Show the dialog with custom content + /// + public void Show( + string title, + string message, + string confirmText = "OK", + string cancelText = "Cancel", + Action onConfirmCallback = null, + Action onCancelCallback = null) + { + if (dialogPanel != null) + { + dialogPanel.SetActive(true); + } + + if (titleText != null) + { + titleText.text = title; + } + + if (messageText != null) + { + messageText.text = message; + } + + if (confirmButtonText != null) + { + confirmButtonText.text = confirmText; + } + + if (cancelButtonText != null) + { + cancelButtonText.text = cancelText; + } + + onConfirm = onConfirmCallback; + onCancel = onCancelCallback; + + // Show/hide cancel button based on callback + if (cancelButton != null) + { + cancelButton.gameObject.SetActive(onCancel != null || !string.IsNullOrEmpty(cancelText)); + } + } + + /// + /// Show a simple alert (OK only) + /// + public void ShowAlert(string title, string message, Action onOk = null) + { + Show(title, message, "OK", "", onOk, null); + } + + /// + /// Hide the dialog + /// + public void Hide() + { + if (dialogPanel != null) + { + dialogPanel.SetActive(false); + } + + onConfirm = null; + onCancel = null; + } + + private void OnConfirmClicked() + { + if (SoundManager.Instance != null) + { + SoundManager.Instance.PlayButtonClick(); + } + + onConfirm?.Invoke(); + Hide(); + } + + private void OnCancelClicked() + { + if (SoundManager.Instance != null) + { + SoundManager.Instance.PlayButtonClick(); + } + + onCancel?.Invoke(); + Hide(); + } + } +} diff --git a/Unity/AIForOceans/Assets/Scripts/UI/GameButton.cs b/Unity/AIForOceans/Assets/Scripts/UI/GameButton.cs new file mode 100644 index 00000000..b16ea7b5 --- /dev/null +++ b/Unity/AIForOceans/Assets/Scripts/UI/GameButton.cs @@ -0,0 +1,166 @@ +using System; +using UnityEngine; +using UnityEngine.UI; +using UnityEngine.EventSystems; + +namespace AIForOceans +{ + /// + /// Custom button with states and feedback + /// + public class GameButton : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler, IPointerDownHandler, IPointerUpHandler + { + [Header("Button Settings")] + public string buttonId; + public bool playSound = true; + + [Header("Visual Settings")] + public Color normalColor = Color.white; + public Color hoverColor = new Color(0.9f, 0.9f, 0.9f); + public Color pressedColor = new Color(0.7f, 0.7f, 0.7f); + public Color disabledColor = new Color(0.5f, 0.5f, 0.5f, 0.5f); + + [Header("Animation")] + public float scaleOnPress = 0.95f; + public float animationSpeed = 10f; + + // Events + public event Action OnClicked; + public event Action OnPressed; + public event Action OnReleased; + + // Components + private Image image; + private Button button; + private RectTransform rectTransform; + + // State + private bool isHovered = false; + private bool isPressed = false; + private bool isInteractable = true; + private Vector3 originalScale; + private Vector3 targetScale; + + private void Awake() + { + image = GetComponent(); + button = GetComponent