From 296d5fff8f0c1abe433a313fdadcf181f8cc4777 Mon Sep 17 00:00:00 2001
From: Evan Pratten <ewpratten@gmail.com>
Date: Sat, 24 Apr 2021 16:48:16 -0400
Subject: [PATCH 01/16] checking for stun gun use

---
 src/logic/ingame/playerlogic.rs | 4 ++--
 src/player.rs                   | 6 +++++-
 2 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/src/logic/ingame/playerlogic.rs b/src/logic/ingame/playerlogic.rs
index 5a1ace8..86891ba 100644
--- a/src/logic/ingame/playerlogic.rs
+++ b/src/logic/ingame/playerlogic.rs
@@ -81,7 +81,7 @@ pub fn update_player_movement(
     }
 
     // Move the player in their direction
-    let speed_multiplier;
+    let mut speed_multiplier;
     if user_request_boost && game_core.player.boost_percent >= 0.0 {
         // Set the speed multiplier
         speed_multiplier = BOOST_PLAYER_SPEED as f32;
@@ -128,7 +128,7 @@ pub fn update_player_movement(
 
     // Handle flippers doing a speed increase
     if game_core.player.inventory.flippers.is_some() {
-        let speed_multiplier = speed_multiplier * game_core.player.inventory.flippers.as_ref().unwrap().speed_increase;
+        speed_multiplier = speed_multiplier * game_core.player.inventory.flippers.as_ref().unwrap().speed_increase;
     }
 
     // Update the player's breath
diff --git a/src/player.rs b/src/player.rs
index 265686b..cb49896 100644
--- a/src/player.rs
+++ b/src/player.rs
@@ -83,6 +83,10 @@ impl Player {
         }
     }
 
+    pub fn is_stun_gun_active(&self) -> bool {
+        return self.attacking_timer != 0.0 && self.inventory.stun_gun.is_some();
+    }
+
     /// Calculate how far the player is
     pub fn calculate_depth_percent(&self, world: &World) -> f32 {
         let dist_from_player_to_end = self.position.distance_to(world.end_position);
@@ -134,7 +138,7 @@ impl Player {
         );
 
         // Calculate AOE ring
-        if self.attacking_timer != 0.0 && self.inventory.stun_gun.is_some() {
+        if self.is_stun_gun_active() {
             let aoe_ring = calculate_linear_slide( self.attacking_timer / self.inventory.stun_gun.as_ref().unwrap().duration) as f32;
             self.attacking_timer = (self.attacking_timer - dt).max(0.0);
 

From a3d79a5ebc9f816df4b772bcbd569e053ede7109 Mon Sep 17 00:00:00 2001
From: Evan Pratten <ewpratten@gmail.com>
Date: Sat, 24 Apr 2021 17:02:37 -0400
Subject: [PATCH 02/16] jellyfish rendering

---
 assets/img/enemies/jelly.json   |  66 ++++++++++++++++++++++++++++++++
 assets/img/enemies/jelly.png    | Bin 0 -> 354 bytes
 assets/worlds/mainworld.json    |   8 ++++
 src/entities/enemy/base.rs      |   8 ++--
 src/entities/enemy/jellyfish.rs |  33 ++++++++++++++++
 src/entities/enemy/mod.rs       |   3 +-
 src/logic/ingame/mod.rs         |  10 ++---
 src/world.rs                    |   6 ++-
 8 files changed, 122 insertions(+), 12 deletions(-)
 create mode 100644 assets/img/enemies/jelly.json
 create mode 100644 assets/img/enemies/jelly.png
 create mode 100644 src/entities/enemy/jellyfish.rs

diff --git a/assets/img/enemies/jelly.json b/assets/img/enemies/jelly.json
new file mode 100644
index 0000000..2f02023
--- /dev/null
+++ b/assets/img/enemies/jelly.json
@@ -0,0 +1,66 @@
+{ "frames": {
+   "Sprite-0001 0.": {
+    "frame": { "x": 0, "y": 0, "w": 10, "h": 10 },
+    "rotated": false,
+    "trimmed": false,
+    "spriteSourceSize": { "x": 0, "y": 0, "w": 10, "h": 10 },
+    "sourceSize": { "w": 10, "h": 10 },
+    "duration": 300
+   },
+   "Sprite-0001 1.": {
+    "frame": { "x": 10, "y": 0, "w": 10, "h": 10 },
+    "rotated": false,
+    "trimmed": false,
+    "spriteSourceSize": { "x": 0, "y": 0, "w": 10, "h": 10 },
+    "sourceSize": { "w": 10, "h": 10 },
+    "duration": 300
+   },
+   "Sprite-0001 2.": {
+    "frame": { "x": 20, "y": 0, "w": 10, "h": 10 },
+    "rotated": false,
+    "trimmed": false,
+    "spriteSourceSize": { "x": 0, "y": 0, "w": 10, "h": 10 },
+    "sourceSize": { "w": 10, "h": 10 },
+    "duration": 300
+   },
+   "Sprite-0001 3.": {
+    "frame": { "x": 30, "y": 0, "w": 10, "h": 10 },
+    "rotated": false,
+    "trimmed": false,
+    "spriteSourceSize": { "x": 0, "y": 0, "w": 10, "h": 10 },
+    "sourceSize": { "w": 10, "h": 10 },
+    "duration": 300
+   },
+   "Sprite-0001 4.": {
+    "frame": { "x": 40, "y": 0, "w": 10, "h": 10 },
+    "rotated": false,
+    "trimmed": false,
+    "spriteSourceSize": { "x": 0, "y": 0, "w": 10, "h": 10 },
+    "sourceSize": { "w": 10, "h": 10 },
+    "duration": 300
+   },
+   "Sprite-0001 5.": {
+    "frame": { "x": 50, "y": 0, "w": 10, "h": 10 },
+    "rotated": false,
+    "trimmed": false,
+    "spriteSourceSize": { "x": 0, "y": 0, "w": 10, "h": 10 },
+    "sourceSize": { "w": 10, "h": 10 },
+    "duration": 300
+   }
+ },
+ "meta": {
+  "app": "http://www.aseprite.org/",
+  "version": "1.2.27-x64",
+  "image": "jelly.png",
+  "format": "RGBA8888",
+  "size": { "w": 60, "h": 10 },
+  "scale": "1",
+  "frameTags": [
+  ],
+  "layers": [
+   { "name": "Layer 1", "opacity": 255, "blendMode": "normal" }
+  ],
+  "slices": [
+  ]
+ }
+}
diff --git a/assets/img/enemies/jelly.png b/assets/img/enemies/jelly.png
new file mode 100644
index 0000000000000000000000000000000000000000..8e670f2a30a7a8436e587bd332cdc851e126ee5e
GIT binary patch
literal 354
zcmV-o0iFJdP)<h;3K|Lk000e1NJLTq002Ay000UI1^@s6=-)lU00001b5ch_0Itp)
z=>Px$97#k$R7i={l(7ziFc5|dad08Vk+3;A5Js68op>Q0ffsUOWWrII*@$!F;^<Py
zPwmlbb@3A8)qef%E<ywGN6}S%i|f2j3s=X+NBE1vU-&Zhee>}J252GFi*q==pdJLv
zsv9-&>3M#<eESP^C~D#@9>C@~9P&{UpVa>J5d^zh7a~)`;y}h>DPK6jyGwEqLI@Df
zzhQ7VwZ`V=hJAcfzz~bv#W%mhvK$8lWH}D996y8{4jJV1+@-D>;tIKuvH9kIczVY3
zIxS>54%EeA<8a@^>1Vigk*A&jjxR)LP2kFPRo|L;A0Mu}s&9|?eX_=Ie8$Vkba4=u
z7@3=#wsX`iPdR+%AUC;#*c#!Sw>61=mw_>V19Wju^>eqxApigX07*qoM6N<$g5V6D
AsQ>@~

literal 0
HcmV?d00001

diff --git a/assets/worlds/mainworld.json b/assets/worlds/mainworld.json
index 40d085e..c5c7288 100644
--- a/assets/worlds/mainworld.json
+++ b/assets/worlds/mainworld.json
@@ -9,5 +9,13 @@
     },
     "fish": [
         {"x":49,"y":801},{"x":570,"y":594},{"x":761,"y":186},{"x":760,"y":940},{"x":241,"y":32},{"x":501,"y":18},{"x":487,"y":37},{"x":802,"y":849},{"x":864,"y":43},{"x":544,"y":886},{"x":987,"y":710},{"x":949,"y":404},{"x":694,"y":32},{"x":364,"y":899},{"x":26,"y":849},{"x":253,"y":627},{"x":39,"y":547},{"x":307,"y":730},{"x":133,"y":967},{"x":861,"y":76},{"x":199,"y":229},{"x":617,"y":532},{"x":391,"y":388},{"x":491,"y":816},{"x":539,"y":243},{"x":222,"y":288},{"x":81,"y":784},{"x":432,"y":830},{"x":741,"y":737},{"x":426,"y":480},{"x":591,"y":437},{"x":903,"y":380},{"x":653,"y":349},{"x":684,"y":235},{"x":797,"y":438},{"x":546,"y":615},{"x":497,"y":523},{"x":406,"y":468},{"x":173,"y":183},{"x":641,"y":187},{"x":517,"y":294},{"x":527,"y":650},{"x":962,"y":237},{"x":25,"y":868},{"x":16,"y":369},{"x":434,"y":712},{"x":632,"y":315},{"x":172,"y":421},{"x":450,"y":53},{"x":731,"y":220},{"x":532,"y":467},{"x":816,"y":497},{"x":948,"y":539},{"x":467,"y":829},{"x":533,"y":809},{"x":146,"y":989},{"x":850,"y":245},{"x":989,"y":214},{"x":203,"y":354},{"x":466,"y":611},{"x":382,"y":376},{"x":111,"y":148},{"x":411,"y":77},{"x":124,"y":418},{"x":154,"y":611},{"x":56,"y":732},{"x":800,"y":488},{"x":851,"y":668},{"x":240,"y":220},{"x":1000,"y":62},{"x":95,"y":784},{"x":700,"y":428},{"x":735,"y":517},{"x":259,"y":843},{"x":647,"y":268},{"x":668,"y":823},{"x":198,"y":241},{"x":243,"y":422},{"x":838,"y":433},{"x":642,"y":97},{"x":563,"y":974},{"x":386,"y":548},{"x":646,"y":482},{"x":691,"y":794},{"x":167,"y":485},{"x":978,"y":622},{"x":845,"y":431},{"x":529,"y":719},{"x":963,"y":145},{"x":6,"y":412},{"x":381,"y":830},{"x":918,"y":118},{"x":915,"y":27},{"x":618,"y":262},{"x":250,"y":635},{"x":100,"y":500},{"x":442,"y":321},{"x":769,"y":767},{"x":714,"y":204},{"x":506,"y":872},{"x":575,"y":178},{"x":256,"y":411},{"x":921,"y":617},{"x":971,"y":214},{"x":726,"y":702},{"x":103,"y":450},{"x":501,"y":134},{"x":265,"y":993},{"x":31,"y":63},{"x":502,"y":448},{"x":46,"y":457},{"x":809,"y":184},{"x":763,"y":962},{"x":632,"y":873},{"x":916,"y":761},{"x":710,"y":720},{"x":873,"y":222},{"x":256,"y":861},{"x":246,"y":482},{"x":390,"y":812},{"x":28,"y":247},{"x":516,"y":523},{"x":869,"y":43},{"x":680,"y":740},{"x":406,"y":65},{"x":657,"y":196},{"x":692,"y":635},{"x":97,"y":993},{"x":616,"y":490},{"x":515,"y":955},{"x":412,"y":502},{"x":743,"y":565},{"x":16,"y":499},{"x":324,"y":582},{"x":871,"y":62},{"x":128,"y":476},{"x":716,"y":525},{"x":627,"y":2},{"x":730,"y":913},{"x":704,"y":522},{"x":242,"y":934},{"x":172,"y":277},{"x":651,"y":948},{"x":349,"y":263},{"x":731,"y":967},{"x":382,"y":762},{"x":217,"y":15},{"x":49,"y":25},{"x":583,"y":110},{"x":700,"y":620},{"x":230,"y":537},{"x":285,"y":978},{"x":4,"y":791},{"x":939,"y":866},{"x":371,"y":342},{"x":759,"y":870},{"x":892,"y":103},{"x":57,"y":129},{"x":233,"y":383},{"x":171,"y":472},{"x":173,"y":842},{"x":516,"y":464},{"x":407,"y":458},{"x":963,"y":231},{"x":526,"y":253},{"x":815,"y":857},{"x":175,"y":909},{"x":993,"y":255},{"x":129,"y":390},{"x":76,"y":997},{"x":833,"y":174},{"x":501,"y":396},{"x":897,"y":218},{"x":876,"y":601},{"x":41,"y":165},{"x":993,"y":473},{"x":606,"y":308},{"x":831,"y":382},{"x":517,"y":828},{"x":984,"y":26},{"x":286,"y":712},{"x":422,"y":311},{"x":448,"y":103},{"x":260,"y":229},{"x":5,"y":738},{"x":283,"y":346},{"x":744,"y":463},{"x":634,"y":719},{"x":446,"y":977},{"x":220,"y":89},{"x":745,"y":866},{"x":851,"y":860},{"x":369,"y":940},{"x":828,"y":577},{"x":350,"y":337},{"x":334,"y":378},{"x":203,"y":248},{"x":665,"y":788},{"x":334,"y":927},{"x":307,"y":764},{"x":500,"y":763},{"x":613,"y":843},{"x":384,"y":253},{"x":956,"y":569},{"x":846,"y":137},{"x":105,"y":728},{"x":686,"y":226},{"x":657,"y":52},{"x":592,"y":433},{"x":997,"y":820},{"x":746,"y":389},{"x":405,"y":448},{"x":973,"y":19},{"x":538,"y":518},{"x":790,"y":275},{"x":633,"y":738},{"x":128,"y":484},{"x":603,"y":371},{"x":932,"y":21},{"x":582,"y":445},{"x":438,"y":793},{"x":963,"y":69},{"x":158,"y":263},{"x":988,"y":297},{"x":249,"y":227},{"x":245,"y":466},{"x":131,"y":495},{"x":620,"y":266},{"x":505,"y":384},{"x":813,"y":647},{"x":113,"y":66},{"x":757,"y":10},{"x":2,"y":707},{"x":540,"y":140},{"x":562,"y":691},{"x":484,"y":433},{"x":859,"y":455},{"x":248,"y":117},{"x":36,"y":432},{"x":798,"y":754},{"x":611,"y":291},{"x":664,"y":770},{"x":299,"y":788},{"x":433,"y":920},{"x":540,"y":739},{"x":201,"y":829},{"x":972,"y":362},{"x":811,"y":120},{"x":941,"y":670},{"x":186,"y":448},{"x":549,"y":611},{"x":206,"y":387},{"x":973,"y":437},{"x":700,"y":709},{"x":472,"y":243},{"x":971,"y":518},{"x":184,"y":540},{"x":271,"y":257},{"x":290,"y":895},{"x":546,"y":7},{"x":256,"y":542},{"x":418,"y":553},{"x":816,"y":875},{"x":908,"y":547},{"x":315,"y":354},{"x":266,"y":471},{"x":242,"y":88},{"x":785,"y":52},{"x":497,"y":47},{"x":466,"y":279},{"x":750,"y":690},{"x":329,"y":296},{"x":545,"y":715},{"x":508,"y":562},{"x":993,"y":467},{"x":703,"y":733},{"x":824,"y":11},{"x":419,"y":337},{"x":393,"y":229},{"x":898,"y":261},{"x":264,"y":708},{"x":711,"y":768},{"x":568,"y":409},{"x":473,"y":342},{"x":329,"y":53},{"x":95,"y":815},{"x":783,"y":977},{"x":48,"y":551},{"x":635,"y":931},{"x":653,"y":86},{"x":9,"y":153},{"x":955,"y":660},{"x":480,"y":716},{"x":936,"y":622},{"x":607,"y":221},{"x":423,"y":545},{"x":507,"y":668},{"x":676,"y":957},{"x":253,"y":515},{"x":327,"y":495},{"x":965,"y":808},{"x":2,"y":807},{"x":276,"y":199},{"x":584,"y":75},{"x":770,"y":51},{"x":667,"y":717},{"x":944,"y":913},{"x":982,"y":977},{"x":618,"y":482},{"x":372,"y":545},{"x":507,"y":518},{"x":604,"y":492},{"x":772,"y":730},{"x":350,"y":141},{"x":783,"y":437},{"x":282,"y":714},{"x":269,"y":691},{"x":991,"y":386},{"x":234,"y":196},{"x":908,"y":635},{"x":785,"y":340},{"x":125,"y":712},{"x":466,"y":210},{"x":280,"y":185},{"x":995,"y":466},{"x":589,"y":258},{"x":700,"y":120},{"x":855,"y":323},{"x":690,"y":355},{"x":755,"y":353},{"x":378,"y":970},{"x":865,"y":270},{"x":220,"y":62},{"x":685,"y":848},{"x":670,"y":907},{"x":710,"y":671},{"x":209,"y":68},{"x":642,"y":470},{"x":104,"y":642},{"x":631,"y":328},{"x":898,"y":424},{"x":909,"y":427},{"x":189,"y":141},{"x":259,"y":993},{"x":332,"y":791},{"x":842,"y":778},{"x":63,"y":390},{"x":146,"y":895},{"x":230,"y":274},{"x":316,"y":447},{"x":603,"y":59},{"x":377,"y":841},{"x":602,"y":119},{"x":728,"y":557},{"x":395,"y":514},{"x":379,"y":754},{"x":822,"y":840},{"x":860,"y":478},{"x":695,"y":360},{"x":156,"y":784},{"x":241,"y":353},{"x":195,"y":199},{"x":284,"y":110},{"x":484,"y":966},{"x":889,"y":370},{"x":246,"y":684},{"x":710,"y":345},{"x":382,"y":635},{"x":447,"y":948},{"x":741,"y":274},{"x":224,"y":883},{"x":99,"y":37},{"x":472,"y":803},{"x":141,"y":397},{"x":371,"y":602},{"x":7,"y":482},{"x":184,"y":990},{"x":555,"y":313},{"x":573,"y":886},{"x":167,"y":365},{"x":810,"y":721},{"x":958,"y":767},{"x":891,"y":561},{"x":314,"y":987},{"x":156,"y":95},{"x":349,"y":542},{"x":775,"y":35},{"x":121,"y":655},{"x":311,"y":242},{"x":534,"y":135},{"x":71,"y":134},{"x":367,"y":896},{"x":447,"y":524},{"x":120,"y":421},{"x":878,"y":398},{"x":469,"y":822},{"x":483,"y":966},{"x":240,"y":880},{"x":759,"y":980},{"x":531,"y":759},{"x":395,"y":118},{"x":354,"y":360},{"x":173,"y":924},{"x":550,"y":958},{"x":888,"y":379},{"x":244,"y":448},{"x":999,"y":554},{"x":941,"y":455},{"x":798,"y":916},{"x":134,"y":123},{"x":90,"y":440},{"x":923,"y":263},{"x":405,"y":595},{"x":194,"y":387},{"x":370,"y":697},{"x":943,"y":888},{"x":607,"y":336},{"x":168,"y":105},{"x":874,"y":66},{"x":675,"y":50},{"x":601,"y":242},{"x":925,"y":728},{"x":643,"y":609},{"x":769,"y":713},{"x":410,"y":913},{"x":153,"y":776},{"x":775,"y":949},{"x":184,"y":93},{"x":624,"y":632},{"x":899,"y":804},{"x":909,"y":327},{"x":371,"y":510},{"x":663,"y":415},{"x":337,"y":542},{"x":248,"y":104},{"x":925,"y":450},{"x":310,"y":925},{"x":4,"y":550},{"x":559,"y":652},{"x":671,"y":296},{"x":414,"y":60},{"x":972,"y":505},{"x":221,"y":147},{"x":318,"y":592},{"x":861,"y":656},{"x":258,"y":675},{"x":565,"y":390},{"x":703,"y":236},{"x":227,"y":76},{"x":989,"y":252},{"x":924,"y":419},{"x":983,"y":971},{"x":795,"y":244},{"x":256,"y":498},{"x":517,"y":674},{"x":89,"y":197},{"x":366,"y":234},{"x":41,"y":952},{"x":487,"y":981},{"x":939,"y":922},{"x":384,"y":315},{"x":958,"y":57},{"x":499,"y":152},{"x":716,"y":167},{"x":167,"y":301},{"x":781,"y":964},{"x":101,"y":215},{"x":605,"y":396},{"x":31,"y":973},{"x":128,"y":831},{"x":685,"y":701},{"x":150,"y":507},{"x":663,"y":77},{"x":792,"y":561},{"x":398,"y":281},{"x":168,"y":936},{"x":8,"y":266},{"x":19,"y":723},{"x":377,"y":975},{"x":68,"y":114},{"x":191,"y":784},{"x":94,"y":222},{"x":986,"y":578},{"x":474,"y":160},{"x":936,"y":945},{"x":603,"y":778},{"x":105,"y":845},{"x":955,"y":583},{"x":832,"y":905},{"x":264,"y":132},{"x":219,"y":747},{"x":515,"y":562},{"x":178,"y":198},{"x":999,"y":1},{"x":470,"y":345},{"x":450,"y":490},{"x":967,"y":306},{"x":257,"y":360},{"x":632,"y":26},{"x":916,"y":382},{"x":631,"y":194},{"x":492,"y":235},{"x":479,"y":373},{"x":887,"y":154},{"x":65,"y":181},{"x":956,"y":879},{"x":567,"y":578},{"x":718,"y":617},{"x":464,"y":243},{"x":545,"y":410},{"x":923,"y":340},{"x":978,"y":716},{"x":277,"y":261},{"x":462,"y":600},{"x":687,"y":507}
+    ],
+    "jellyfish": [
+        {
+            "position": {
+                "x": 300,
+                "y": 100
+            }
+        }
     ]
 }
\ No newline at end of file
diff --git a/src/entities/enemy/base.rs b/src/entities/enemy/base.rs
index c330af7..04937e6 100644
--- a/src/entities/enemy/base.rs
+++ b/src/entities/enemy/base.rs
@@ -1,7 +1,9 @@
+use raylib::prelude::*;
 
+use crate::player::Player;
 
 pub trait EnemyBase {
-    fn render();
-    fn handle_logic();
-    fn handle_getting_attacked();
+    fn render(&self, context_2d: &mut RaylibMode2D<RaylibDrawHandle>);
+    fn handle_logic(&mut self, player: &mut Player, dt: f64);
+    fn handle_getting_attacked(&mut self);
 }
\ No newline at end of file
diff --git a/src/entities/enemy/jellyfish.rs b/src/entities/enemy/jellyfish.rs
new file mode 100644
index 0000000..496387f
--- /dev/null
+++ b/src/entities/enemy/jellyfish.rs
@@ -0,0 +1,33 @@
+use super::base::EnemyBase;
+use raylib::prelude::*;
+use serde::{Deserialize, Serialize};
+use crate::player::Player;
+
+#[derive(Debug, Serialize, Deserialize, Default, Clone)]
+pub struct JellyFish {
+    pub position: Vector2,
+
+    #[serde(skip)]
+    pub stunned_timer: f64
+}
+
+impl JellyFish {
+    
+
+}
+
+impl EnemyBase for JellyFish {
+    fn render(&self, context_2d: &mut raylib::prelude::RaylibMode2D<raylib::prelude::RaylibDrawHandle>) {
+        
+        // TODO
+        context_2d.draw_circle_v(self.position, 5.0, Color::RED);
+    }
+
+    fn handle_logic(&mut self, player: &mut Player, dt: f64) {
+        todo!()
+    }
+
+    fn handle_getting_attacked(&mut self) {
+        todo!()
+    }
+}
\ No newline at end of file
diff --git a/src/entities/enemy/mod.rs b/src/entities/enemy/mod.rs
index 307b359..ea64b37 100644
--- a/src/entities/enemy/mod.rs
+++ b/src/entities/enemy/mod.rs
@@ -1 +1,2 @@
-pub mod base;
\ No newline at end of file
+pub mod base;
+pub mod jellyfish;
\ No newline at end of file
diff --git a/src/logic/ingame/mod.rs b/src/logic/ingame/mod.rs
index 50fe9d7..26e69b0 100644
--- a/src/logic/ingame/mod.rs
+++ b/src/logic/ingame/mod.rs
@@ -3,11 +3,7 @@ mod playerlogic;
 
 use raylib::prelude::*;
 
-use crate::{
-    gamecore::{GameCore, GameState},
-    lib::wrappers::audio::player::AudioPlayer,
-    pallette::{SKY, WATER},
-};
+use crate::{entities::enemy::base::EnemyBase, gamecore::{GameCore, GameState}, lib::wrappers::audio::player::AudioPlayer, pallette::{SKY, WATER}};
 
 use super::screen::Screen;
 
@@ -124,9 +120,11 @@ impl Screen for InGameScreen {
                 fish.update_position(&mut game_core.player, dt, &fish_clone);
                 fish.render(&mut context_2d);
             }
+            for jellyfish in game_core.world.jellyfish.iter() {
+                jellyfish.render(&mut context_2d);
+            }
 
             // Render Player
-            // playerlogic::render_player(&mut context_2d, game_core);
             game_core.player.render(&mut context_2d, &mut game_core.resources, dt);
         }
 
diff --git a/src/world.rs b/src/world.rs
index 1f344fe..91441b6 100644
--- a/src/world.rs
+++ b/src/world.rs
@@ -5,7 +5,7 @@ use serde::{Deserialize, Serialize};
 use std::io::Read;
 use failure::Error;
 
-use crate::entities::fish::FishEntity;
+use crate::entities::{enemy::jellyfish::JellyFish, fish::FishEntity};
 
 #[derive(Debug, Serialize, Deserialize, Clone)]
 pub struct World {
@@ -19,7 +19,9 @@ pub struct World {
     pub fish: Vec<FishEntity>,
 
     #[serde(skip)]
-    pub colliders: Vec<Rectangle>
+    pub colliders: Vec<Rectangle>,
+
+    pub jellyfish: Vec<JellyFish>
 }
 
 impl World {

From c0d147681bb826647e450fdb451ccc5be5d80063 Mon Sep 17 00:00:00 2001
From: Evan Pratten <ewpratten@gmail.com>
Date: Sat, 24 Apr 2021 17:06:13 -0400
Subject: [PATCH 03/16] handle attacking the jellyfish

---
 src/logic/ingame/playerlogic.rs |  2 +-
 src/player.rs                   | 13 +++++++++++--
 2 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/src/logic/ingame/playerlogic.rs b/src/logic/ingame/playerlogic.rs
index 86891ba..4d3106e 100644
--- a/src/logic/ingame/playerlogic.rs
+++ b/src/logic/ingame/playerlogic.rs
@@ -77,7 +77,7 @@ pub fn update_player_movement(
     let user_request_action = draw_handle.is_mouse_button_pressed(MouseButton::MOUSE_RIGHT_BUTTON);
 
     if user_request_action {
-        game_core.player.begin_attack();
+        game_core.player.begin_attack(&mut game_core.world);
     }
 
     // Move the player in their direction
diff --git a/src/player.rs b/src/player.rs
index cb49896..479bd03 100644
--- a/src/player.rs
+++ b/src/player.rs
@@ -1,6 +1,6 @@
 use raylib::prelude::*;
 use serde::{Serialize, Deserialize};
-use crate::{gamecore::{GameCore, GameProgress}, items::{AirBag, Flashlight, Flippers, StunGun}, lib::utils::{calculate_linear_slide}, pallette::{TRANSLUCENT_WHITE_64, TRANSLUCENT_WHITE_96}, resources::GlobalResources, world::World};
+use crate::{entities::enemy::base::EnemyBase, gamecore::{GameCore, GameProgress}, items::{AirBag, Flashlight, Flippers, StunGun}, lib::utils::{calculate_linear_slide}, pallette::{TRANSLUCENT_WHITE_64, TRANSLUCENT_WHITE_96}, resources::GlobalResources, world::World};
 
 const AOE_RING_MAX_RADIUS: f32 = 60.0;
 const STUN_ATTACK_TIME: f64 = 0.75;
@@ -77,9 +77,18 @@ impl Player {
     }
 
     /// Try to attack with the stun gun
-    pub fn begin_attack(&mut self) {
+    pub fn begin_attack(&mut self, world: &mut World) {
         if self.inventory.stun_gun.is_some() && self.stun_timer == 0.0 {
             self.attacking_timer = self.inventory.stun_gun.as_ref().unwrap().duration;
+
+            // Stun everything in reach 
+            let stun_reach = self.inventory.stun_gun.as_ref().unwrap().range;
+
+            for jellyfish in world.jellyfish.iter_mut() {
+                if jellyfish.position.distance_to(self.position).abs() <= stun_reach {
+                    jellyfish.handle_getting_attacked();
+                }
+            }
         }
     }
 

From a453d16d1dc2a635892d81e9c9bef30753e57b37 Mon Sep 17 00:00:00 2001
From: rsninja722 <jnick722547@gmail.com>
Date: Sat, 24 Apr 2021 17:08:17 -0400
Subject: [PATCH 04/16] jelly enemy

---
 assets/img/enemies/jelly.aseprite   | Bin 0 -> 3368 bytes
 assets/img/enemies/jelly.json       |  66 +++++++++++++
 assets/img/enemies/jelly.png        | Bin 0 -> 354 bytes
 assets/img/enemies/jellyAttack.json | 138 ++++++++++++++++++++++++++++
 assets/img/enemies/jellyAttack.png  | Bin 0 -> 358 bytes
 5 files changed, 204 insertions(+)
 create mode 100644 assets/img/enemies/jelly.aseprite
 create mode 100644 assets/img/enemies/jelly.json
 create mode 100644 assets/img/enemies/jelly.png
 create mode 100644 assets/img/enemies/jellyAttack.json
 create mode 100644 assets/img/enemies/jellyAttack.png

diff --git a/assets/img/enemies/jelly.aseprite b/assets/img/enemies/jelly.aseprite
new file mode 100644
index 0000000000000000000000000000000000000000..ef41716319a1248cd149f9475b32b0d963fa7d75
GIT binary patch
literal 3368
zcmdPkWng%)l%GKa2o)F@85kH&05Jjp#Xy1#0zgO$(8k2T@arQd*j7%U1!6$Vt^l?Y
z$+}xWwxogrR74(02F(1=z@VgH0wi5EY=C5%r6G{)53>f6_Y2j4<jn<XK=R$;SwQml
zCo>>9^JxH(%-UxFB+aMf0ZH#neIOa+tpX&CY%GDKy?qIgG)QOylF@k&fn@UR|3EVS
z>=Ph)`t~0n`5y=v7-p~C4kTOZ+JR(dRu+(q3=0C1Wlmi{a*dG@kh~e53?#2t?*fwj
z)4hOXSH8jjET9KiK;f<cWB@$@^a0TMK(_-O4s<op$w2o49Sd|R(3wCt0v!l+9nfh&
zcL5y*bP>=wAh-Pg4|E042|)XSmIG}DS_`xjXd%!xpjGl9n-qY-4F^CcFt9WDBvz&t
zDH!3GHiSqs!}S7vj-=aI56EFv0Ae8g54VGhfs3JHPIBt6${D31!OZnb+AJ9g9&U(^
z2CHUdU;{#gY7PcYkm`hnhRLGge9FmeDh(?C1iKz)O?bLaa{u4Xb!;v9FZR`Usqh^O
z*m(Gb#B7T*awSqX=kB=jFiBXb`6FXdZkMGQ*k~r8!R#nTvx1FwXs|wiSWW5j4TfDZ
zcD74qG<(Z1xH5_c&IRiF^^pmj3PG+X%{%c}y~By_9g_x??}A-{R}@dj8`u37o^2&i
z>-_z1u!^NYTbJyyXM8hcc3JMoDB1ovs9UeUyH{Ih!cB(2)-KCY#|_Jny9`cq%-}Q!
z%2%YNIan5AMM>ve3>@Heo{(S>S@_hz?o7k7XR|)up6~EWS;#H09+ccnD(7TveBqpU
z_{}lb!#4~X&bWv7`|_G?y>aH~QhA2snNw$4fs-?O7UBfvY*6lmWFeym3@3_iTzPoe
z`-Dx>*@lzM44Y+ymd^rviQH@y1Gbl%rNZM$?%~V~(QCUbM_op2Njen54AdO>^^x4H
z69r9Y>?m~=8>FsEfMy+|v<4=P|H>lrZbH^IXMeo)pJ5^NucPha)w-5V{KAJ6cISbr
zqBHL4%DaVQ<)&9Lxc9egbpo3V$~nljAgm&AU@f25?wfLeDdEwHPdjcLd7&!aa7N*n
zjMG1busIT?3>%**EoK6?1jzRptWcn0y*jCVBV#&mmt`i@YfKDGNcAc|13$P>IKcPL
zhJSX4bC&|cOVuUvvu!lX4!v=>=6u2@=*pu_%@W&%9`k!0njYh@YOcZ88;4lu_Uq2k
z;5AP=qnx6)^~+@8_#;o4f$hsn#YvNe25SgZLPG#ZA%%blgD@ln_(37SafoHgM4k^b
zy;oT%TBcN%%!>JZ;p`%lo(o?mC(E6Y-En47s7=uAGl33v3Z`}&RxVfBJ7IG9NmKs$
zw>f9FuA6^n6Kj0k;dFDuR~$F{bIdpXVu*-n>V5;Xa8Ra+V0efyqJ)SLI7Al6+^Li^
zo5*!6AjQn^RmMv{F9yBxi--0$oAS76fxR!US?J|oA0%|{$u!p+M;JEoX)T-y_A9wH
I2o2Le0AqL8{{R30

literal 0
HcmV?d00001

diff --git a/assets/img/enemies/jelly.json b/assets/img/enemies/jelly.json
new file mode 100644
index 0000000..2f02023
--- /dev/null
+++ b/assets/img/enemies/jelly.json
@@ -0,0 +1,66 @@
+{ "frames": {
+   "Sprite-0001 0.": {
+    "frame": { "x": 0, "y": 0, "w": 10, "h": 10 },
+    "rotated": false,
+    "trimmed": false,
+    "spriteSourceSize": { "x": 0, "y": 0, "w": 10, "h": 10 },
+    "sourceSize": { "w": 10, "h": 10 },
+    "duration": 300
+   },
+   "Sprite-0001 1.": {
+    "frame": { "x": 10, "y": 0, "w": 10, "h": 10 },
+    "rotated": false,
+    "trimmed": false,
+    "spriteSourceSize": { "x": 0, "y": 0, "w": 10, "h": 10 },
+    "sourceSize": { "w": 10, "h": 10 },
+    "duration": 300
+   },
+   "Sprite-0001 2.": {
+    "frame": { "x": 20, "y": 0, "w": 10, "h": 10 },
+    "rotated": false,
+    "trimmed": false,
+    "spriteSourceSize": { "x": 0, "y": 0, "w": 10, "h": 10 },
+    "sourceSize": { "w": 10, "h": 10 },
+    "duration": 300
+   },
+   "Sprite-0001 3.": {
+    "frame": { "x": 30, "y": 0, "w": 10, "h": 10 },
+    "rotated": false,
+    "trimmed": false,
+    "spriteSourceSize": { "x": 0, "y": 0, "w": 10, "h": 10 },
+    "sourceSize": { "w": 10, "h": 10 },
+    "duration": 300
+   },
+   "Sprite-0001 4.": {
+    "frame": { "x": 40, "y": 0, "w": 10, "h": 10 },
+    "rotated": false,
+    "trimmed": false,
+    "spriteSourceSize": { "x": 0, "y": 0, "w": 10, "h": 10 },
+    "sourceSize": { "w": 10, "h": 10 },
+    "duration": 300
+   },
+   "Sprite-0001 5.": {
+    "frame": { "x": 50, "y": 0, "w": 10, "h": 10 },
+    "rotated": false,
+    "trimmed": false,
+    "spriteSourceSize": { "x": 0, "y": 0, "w": 10, "h": 10 },
+    "sourceSize": { "w": 10, "h": 10 },
+    "duration": 300
+   }
+ },
+ "meta": {
+  "app": "http://www.aseprite.org/",
+  "version": "1.2.27-x64",
+  "image": "jelly.png",
+  "format": "RGBA8888",
+  "size": { "w": 60, "h": 10 },
+  "scale": "1",
+  "frameTags": [
+  ],
+  "layers": [
+   { "name": "Layer 1", "opacity": 255, "blendMode": "normal" }
+  ],
+  "slices": [
+  ]
+ }
+}
diff --git a/assets/img/enemies/jelly.png b/assets/img/enemies/jelly.png
new file mode 100644
index 0000000000000000000000000000000000000000..8e670f2a30a7a8436e587bd332cdc851e126ee5e
GIT binary patch
literal 354
zcmV-o0iFJdP)<h;3K|Lk000e1NJLTq002Ay000UI1^@s6=-)lU00001b5ch_0Itp)
z=>Px$97#k$R7i={l(7ziFc5|dad08Vk+3;A5Js68op>Q0ffsUOWWrII*@$!F;^<Py
zPwmlbb@3A8)qef%E<ywGN6}S%i|f2j3s=X+NBE1vU-&Zhee>}J252GFi*q==pdJLv
zsv9-&>3M#<eESP^C~D#@9>C@~9P&{UpVa>J5d^zh7a~)`;y}h>DPK6jyGwEqLI@Df
zzhQ7VwZ`V=hJAcfzz~bv#W%mhvK$8lWH}D996y8{4jJV1+@-D>;tIKuvH9kIczVY3
zIxS>54%EeA<8a@^>1Vigk*A&jjxR)LP2kFPRo|L;A0Mu}s&9|?eX_=Ie8$Vkba4=u
z7@3=#wsX`iPdR+%AUC;#*c#!Sw>61=mw_>V19Wju^>eqxApigX07*qoM6N<$g5V6D
AsQ>@~

literal 0
HcmV?d00001

diff --git a/assets/img/enemies/jellyAttack.json b/assets/img/enemies/jellyAttack.json
new file mode 100644
index 0000000..3e97d87
--- /dev/null
+++ b/assets/img/enemies/jellyAttack.json
@@ -0,0 +1,138 @@
+{ "frames": {
+   "jelly 0.aseprite": {
+    "frame": { "x": 0, "y": 0, "w": 20, "h": 20 },
+    "rotated": false,
+    "trimmed": false,
+    "spriteSourceSize": { "x": 0, "y": 0, "w": 20, "h": 20 },
+    "sourceSize": { "w": 20, "h": 20 },
+    "duration": 200
+   },
+   "jelly 1.aseprite": {
+    "frame": { "x": 20, "y": 0, "w": 20, "h": 20 },
+    "rotated": false,
+    "trimmed": false,
+    "spriteSourceSize": { "x": 0, "y": 0, "w": 20, "h": 20 },
+    "sourceSize": { "w": 20, "h": 20 },
+    "duration": 200
+   },
+   "jelly 2.aseprite": {
+    "frame": { "x": 40, "y": 0, "w": 20, "h": 20 },
+    "rotated": false,
+    "trimmed": false,
+    "spriteSourceSize": { "x": 0, "y": 0, "w": 20, "h": 20 },
+    "sourceSize": { "w": 20, "h": 20 },
+    "duration": 200
+   },
+   "jelly 3.aseprite": {
+    "frame": { "x": 60, "y": 0, "w": 20, "h": 20 },
+    "rotated": false,
+    "trimmed": false,
+    "spriteSourceSize": { "x": 0, "y": 0, "w": 20, "h": 20 },
+    "sourceSize": { "w": 20, "h": 20 },
+    "duration": 200
+   },
+   "jelly 4.aseprite": {
+    "frame": { "x": 80, "y": 0, "w": 20, "h": 20 },
+    "rotated": false,
+    "trimmed": false,
+    "spriteSourceSize": { "x": 0, "y": 0, "w": 20, "h": 20 },
+    "sourceSize": { "w": 20, "h": 20 },
+    "duration": 200
+   },
+   "jelly 5.aseprite": {
+    "frame": { "x": 100, "y": 0, "w": 20, "h": 20 },
+    "rotated": false,
+    "trimmed": false,
+    "spriteSourceSize": { "x": 0, "y": 0, "w": 20, "h": 20 },
+    "sourceSize": { "w": 20, "h": 20 },
+    "duration": 200
+   },
+   "jelly 6.aseprite": {
+    "frame": { "x": 120, "y": 0, "w": 20, "h": 20 },
+    "rotated": false,
+    "trimmed": false,
+    "spriteSourceSize": { "x": 0, "y": 0, "w": 20, "h": 20 },
+    "sourceSize": { "w": 20, "h": 20 },
+    "duration": 200
+   },
+   "jelly 7.aseprite": {
+    "frame": { "x": 140, "y": 0, "w": 20, "h": 20 },
+    "rotated": false,
+    "trimmed": false,
+    "spriteSourceSize": { "x": 0, "y": 0, "w": 20, "h": 20 },
+    "sourceSize": { "w": 20, "h": 20 },
+    "duration": 200
+   },
+   "jelly 8.aseprite": {
+    "frame": { "x": 160, "y": 0, "w": 20, "h": 20 },
+    "rotated": false,
+    "trimmed": false,
+    "spriteSourceSize": { "x": 0, "y": 0, "w": 20, "h": 20 },
+    "sourceSize": { "w": 20, "h": 20 },
+    "duration": 200
+   },
+   "jelly 9.aseprite": {
+    "frame": { "x": 180, "y": 0, "w": 20, "h": 20 },
+    "rotated": false,
+    "trimmed": false,
+    "spriteSourceSize": { "x": 0, "y": 0, "w": 20, "h": 20 },
+    "sourceSize": { "w": 20, "h": 20 },
+    "duration": 200
+   },
+   "jelly 10.aseprite": {
+    "frame": { "x": 200, "y": 0, "w": 20, "h": 20 },
+    "rotated": false,
+    "trimmed": false,
+    "spriteSourceSize": { "x": 0, "y": 0, "w": 20, "h": 20 },
+    "sourceSize": { "w": 20, "h": 20 },
+    "duration": 200
+   },
+   "jelly 11.aseprite": {
+    "frame": { "x": 220, "y": 0, "w": 20, "h": 20 },
+    "rotated": false,
+    "trimmed": false,
+    "spriteSourceSize": { "x": 0, "y": 0, "w": 20, "h": 20 },
+    "sourceSize": { "w": 20, "h": 20 },
+    "duration": 200
+   },
+   "jelly 12.aseprite": {
+    "frame": { "x": 240, "y": 0, "w": 20, "h": 20 },
+    "rotated": false,
+    "trimmed": false,
+    "spriteSourceSize": { "x": 0, "y": 0, "w": 20, "h": 20 },
+    "sourceSize": { "w": 20, "h": 20 },
+    "duration": 200
+   },
+   "jelly 13.aseprite": {
+    "frame": { "x": 260, "y": 0, "w": 20, "h": 20 },
+    "rotated": false,
+    "trimmed": false,
+    "spriteSourceSize": { "x": 0, "y": 0, "w": 20, "h": 20 },
+    "sourceSize": { "w": 20, "h": 20 },
+    "duration": 200
+   },
+   "jelly 14.aseprite": {
+    "frame": { "x": 280, "y": 0, "w": 20, "h": 20 },
+    "rotated": false,
+    "trimmed": false,
+    "spriteSourceSize": { "x": 0, "y": 0, "w": 20, "h": 20 },
+    "sourceSize": { "w": 20, "h": 20 },
+    "duration": 200
+   }
+ },
+ "meta": {
+  "app": "http://www.aseprite.org/",
+  "version": "1.2.27-x64",
+  "image": "jellyAttack.png",
+  "format": "RGBA8888",
+  "size": { "w": 300, "h": 20 },
+  "scale": "1",
+  "frameTags": [
+  ],
+  "layers": [
+   { "name": "Layer 3", "opacity": 255, "blendMode": "normal" }
+  ],
+  "slices": [
+  ]
+ }
+}
diff --git a/assets/img/enemies/jellyAttack.png b/assets/img/enemies/jellyAttack.png
new file mode 100644
index 0000000000000000000000000000000000000000..2fd06a88df736ee0080d7d564752ed1d6cc6ca8d
GIT binary patch
literal 358
zcmV-s0h#`ZP)<h;3K|Lk000e1NJLTq00Arj000yS1^@s6HzNQ600001b5ch_0Itp)
z=>Px$AW1|)RCt{2+d&S(AP@ymPuY8UKli<cD-&aC3(T~DzPDD|fc(M~Z#Up)J=W#^
zSeJY6`v54m7hKtaCLrNYL?-**caPc?GC;N3E!^v~8G%%D?b7y2+5!f*HJMu{ct)K{
zxWFH2neeZmdH?QFkY(1PwyvK+_`!g-wqv!EwPdAr6fC9N!dlY?&siNp8{^Plq`=*)
ztrpY%)~3Dj9};<zlS?oRW^YxcbFZh*=VH7DVIcbR5a}<ozm44qbn3W_&Gn*h>%Q$^
zY76cFRU+r7YT7#Eux9oNc)<!2$O^5Nm0RR3zVZSP5(%xWYXKCAoLaAG>+_h5qZ&Z5
zNNBXKz7+I<OO^irFjB8l>jF~j)x285s`YK800VgQ1V?0AWW=x;d;kCd07*qoM6N<$
Ef_hM+wg3PC

literal 0
HcmV?d00001


From 0aef4804fdc08aac46ad9d91933368e2d3721cc4 Mon Sep 17 00:00:00 2001
From: Evan Pratten <ewpratten@gmail.com>
Date: Sat, 24 Apr 2021 17:12:40 -0400
Subject: [PATCH 05/16] jelly animation

---
 src/entities/enemy/base.rs      |  4 ++--
 src/entities/enemy/jellyfish.rs | 11 +++++++----
 src/logic/ingame/mod.rs         |  2 +-
 src/resources.rs                | 14 +++++++++++++-
 4 files changed, 23 insertions(+), 8 deletions(-)

diff --git a/src/entities/enemy/base.rs b/src/entities/enemy/base.rs
index 04937e6..4fd751f 100644
--- a/src/entities/enemy/base.rs
+++ b/src/entities/enemy/base.rs
@@ -1,9 +1,9 @@
 use raylib::prelude::*;
 
-use crate::player::Player;
+use crate::{player::Player, resources::GlobalResources};
 
 pub trait EnemyBase {
-    fn render(&self, context_2d: &mut RaylibMode2D<RaylibDrawHandle>);
+    fn render(&self, context_2d: &mut RaylibMode2D<RaylibDrawHandle>, resources: &mut GlobalResources);
     fn handle_logic(&mut self, player: &mut Player, dt: f64);
     fn handle_getting_attacked(&mut self);
 }
\ No newline at end of file
diff --git a/src/entities/enemy/jellyfish.rs b/src/entities/enemy/jellyfish.rs
index 496387f..dbb1af2 100644
--- a/src/entities/enemy/jellyfish.rs
+++ b/src/entities/enemy/jellyfish.rs
@@ -1,7 +1,7 @@
 use super::base::EnemyBase;
 use raylib::prelude::*;
 use serde::{Deserialize, Serialize};
-use crate::player::Player;
+use crate::{player::Player, resources::GlobalResources};
 
 #[derive(Debug, Serialize, Deserialize, Default, Clone)]
 pub struct JellyFish {
@@ -17,10 +17,13 @@ impl JellyFish {
 }
 
 impl EnemyBase for JellyFish {
-    fn render(&self, context_2d: &mut raylib::prelude::RaylibMode2D<raylib::prelude::RaylibDrawHandle>) {
+    fn render(&self, context_2d: &mut raylib::prelude::RaylibMode2D<raylib::prelude::RaylibDrawHandle>, resources: &mut GlobalResources) {
+
+        // Render the jellyfish
+        resources.jellyfish_animation_regular.draw(context_2d, self.position, 0.0);
         
-        // TODO
-        context_2d.draw_circle_v(self.position, 5.0, Color::RED);
+        // // TODO
+        // context_2d.draw_circle_v(self.position, 5.0, Color::RED);
     }
 
     fn handle_logic(&mut self, player: &mut Player, dt: f64) {
diff --git a/src/logic/ingame/mod.rs b/src/logic/ingame/mod.rs
index 26e69b0..ccc51ed 100644
--- a/src/logic/ingame/mod.rs
+++ b/src/logic/ingame/mod.rs
@@ -121,7 +121,7 @@ impl Screen for InGameScreen {
                 fish.render(&mut context_2d);
             }
             for jellyfish in game_core.world.jellyfish.iter() {
-                jellyfish.render(&mut context_2d);
+                jellyfish.render(&mut context_2d, &mut game_core.resources);
             }
 
             // Render Player
diff --git a/src/resources.rs b/src/resources.rs
index b88c5a4..be40c14 100644
--- a/src/resources.rs
+++ b/src/resources.rs
@@ -18,7 +18,10 @@ pub struct GlobalResources {
     pub player_animation_boost: FrameAnimationWrapper,
 
     // Cave
-    pub cave_mid_layer: Texture2D
+    pub cave_mid_layer: Texture2D,
+
+    // Enemies
+    pub jellyfish_animation_regular: FrameAnimationWrapper
 }
 
 impl GlobalResources {
@@ -63,6 +66,15 @@ impl GlobalResources {
                 &thread,
                 &Image::load_image("./assets/img/map/cave.png")?,
             )?,
+            jellyfish_animation_regular: FrameAnimationWrapper::new(
+                raylib.load_texture_from_image(
+                    &thread,
+                    &Image::load_image("./assets/img/enemies/jelly.png")?,
+                )?,
+                Vector2 { x: 10.0, y: 10.0 },
+                6,
+                4,
+            ),
         })
     }
 }

From 9e0a8df2598b88ae9fdd0e3c4a4b4241b5deddf0 Mon Sep 17 00:00:00 2001
From: Evan Pratten <ewpratten@gmail.com>
Date: Sat, 24 Apr 2021 17:15:28 -0400
Subject: [PATCH 06/16] jelly movement

---
 src/entities/enemy/jellyfish.rs | 31 +++++++++++++++++++------------
 1 file changed, 19 insertions(+), 12 deletions(-)

diff --git a/src/entities/enemy/jellyfish.rs b/src/entities/enemy/jellyfish.rs
index dbb1af2..72f7061 100644
--- a/src/entities/enemy/jellyfish.rs
+++ b/src/entities/enemy/jellyfish.rs
@@ -1,29 +1,36 @@
 use super::base::EnemyBase;
+use crate::{player::Player, resources::GlobalResources};
 use raylib::prelude::*;
 use serde::{Deserialize, Serialize};
-use crate::{player::Player, resources::GlobalResources};
 
 #[derive(Debug, Serialize, Deserialize, Default, Clone)]
 pub struct JellyFish {
     pub position: Vector2,
 
     #[serde(skip)]
-    pub stunned_timer: f64
+    pub stunned_timer: f64,
 }
 
-impl JellyFish {
-    
-
-}
+impl JellyFish {}
 
 impl EnemyBase for JellyFish {
-    fn render(&self, context_2d: &mut raylib::prelude::RaylibMode2D<raylib::prelude::RaylibDrawHandle>, resources: &mut GlobalResources) {
+    fn render(
+        &self,
+        context_2d: &mut raylib::prelude::RaylibMode2D<raylib::prelude::RaylibDrawHandle>,
+        resources: &mut GlobalResources,
+    ) {
+        // Simple sine position
+        let v_trans = context_2d.get_time().sin();
 
         // Render the jellyfish
-        resources.jellyfish_animation_regular.draw(context_2d, self.position, 0.0);
-        
-        // // TODO
-        // context_2d.draw_circle_v(self.position, 5.0, Color::RED);
+        resources.jellyfish_animation_regular.draw(
+            context_2d,
+            Vector2 {
+                x: self.position.x,
+                y: self.position.y+ (2.0 * v_trans as f32),
+            },
+            0.0,
+        );
     }
 
     fn handle_logic(&mut self, player: &mut Player, dt: f64) {
@@ -33,4 +40,4 @@ impl EnemyBase for JellyFish {
     fn handle_getting_attacked(&mut self) {
         todo!()
     }
-}
\ No newline at end of file
+}

From 707543cf55a3f24bf32cca894740477c1ac00511 Mon Sep 17 00:00:00 2001
From: Evan Pratten <ewpratten@gmail.com>
Date: Sat, 24 Apr 2021 17:26:47 -0400
Subject: [PATCH 07/16] jelly

---
 src/entities/enemy/base.rs      |  2 +-
 src/entities/enemy/jellyfish.rs | 24 +++++++++++++++++++++---
 src/lib/wrappers/animation.rs   |  2 +-
 src/logic/ingame/mod.rs         |  2 +-
 src/resources.rs                | 12 +++++++++++-
 5 files changed, 35 insertions(+), 7 deletions(-)

diff --git a/src/entities/enemy/base.rs b/src/entities/enemy/base.rs
index 4fd751f..83f7af2 100644
--- a/src/entities/enemy/base.rs
+++ b/src/entities/enemy/base.rs
@@ -3,7 +3,7 @@ use raylib::prelude::*;
 use crate::{player::Player, resources::GlobalResources};
 
 pub trait EnemyBase {
-    fn render(&self, context_2d: &mut RaylibMode2D<RaylibDrawHandle>, resources: &mut GlobalResources);
+    fn render(&mut self, context_2d: &mut RaylibMode2D<RaylibDrawHandle>, resources: &mut GlobalResources);
     fn handle_logic(&mut self, player: &mut Player, dt: f64);
     fn handle_getting_attacked(&mut self);
 }
\ No newline at end of file
diff --git a/src/entities/enemy/jellyfish.rs b/src/entities/enemy/jellyfish.rs
index 72f7061..a657b3b 100644
--- a/src/entities/enemy/jellyfish.rs
+++ b/src/entities/enemy/jellyfish.rs
@@ -9,13 +9,16 @@ pub struct JellyFish {
 
     #[serde(skip)]
     pub stunned_timer: f64,
+
+    #[serde(skip)]
+    pub do_stun_player: bool
 }
 
 impl JellyFish {}
 
 impl EnemyBase for JellyFish {
     fn render(
-        &self,
+        &mut self,
         context_2d: &mut raylib::prelude::RaylibMode2D<raylib::prelude::RaylibDrawHandle>,
         resources: &mut GlobalResources,
     ) {
@@ -27,14 +30,29 @@ impl EnemyBase for JellyFish {
             context_2d,
             Vector2 {
                 x: self.position.x,
-                y: self.position.y+ (2.0 * v_trans as f32),
+                y: self.position.y + (2.0 * v_trans as f32),
             },
             0.0,
         );
+        resources.jellyfish_animation_attack.draw(
+            context_2d,
+            Vector2 {
+                x: self.position.x
+                    ,
+                y: self.position.y + (2.0 * v_trans as f32)
+                    ,
+            },
+            0.0,
+        );
+        self.do_stun_player = resources.jellyfish_animation_attack.get_current_frame_id(context_2d) == 13;
     }
 
     fn handle_logic(&mut self, player: &mut Player, dt: f64) {
-        todo!()
+        
+        // Handle stunning the player
+        if self.do_stun_player {
+            
+        }
     }
 
     fn handle_getting_attacked(&mut self) {
diff --git a/src/lib/wrappers/animation.rs b/src/lib/wrappers/animation.rs
index 053cf2b..163b70b 100644
--- a/src/lib/wrappers/animation.rs
+++ b/src/lib/wrappers/animation.rs
@@ -2,7 +2,7 @@ use raylib::{core::color::Color, math::{Rectangle, Vector2}, prelude::{RaylibDra
 
 /// A wrapper around an animation spritesheet
 pub struct FrameAnimationWrapper {
-    sprite_sheet: Texture2D,
+    pub sprite_sheet: Texture2D,
     size: Vector2,
     frame_count: u32,
     frames_per_second: u8,
diff --git a/src/logic/ingame/mod.rs b/src/logic/ingame/mod.rs
index ccc51ed..469d761 100644
--- a/src/logic/ingame/mod.rs
+++ b/src/logic/ingame/mod.rs
@@ -120,7 +120,7 @@ impl Screen for InGameScreen {
                 fish.update_position(&mut game_core.player, dt, &fish_clone);
                 fish.render(&mut context_2d);
             }
-            for jellyfish in game_core.world.jellyfish.iter() {
+            for jellyfish in game_core.world.jellyfish.iter_mut() {
                 jellyfish.render(&mut context_2d, &mut game_core.resources);
             }
 
diff --git a/src/resources.rs b/src/resources.rs
index be40c14..8b8459d 100644
--- a/src/resources.rs
+++ b/src/resources.rs
@@ -21,7 +21,8 @@ pub struct GlobalResources {
     pub cave_mid_layer: Texture2D,
 
     // Enemies
-    pub jellyfish_animation_regular: FrameAnimationWrapper
+    pub jellyfish_animation_regular: FrameAnimationWrapper,
+    pub jellyfish_animation_attack: FrameAnimationWrapper,
 }
 
 impl GlobalResources {
@@ -75,6 +76,15 @@ impl GlobalResources {
                 6,
                 4,
             ),
+            jellyfish_animation_attack: FrameAnimationWrapper::new(
+                raylib.load_texture_from_image(
+                    &thread,
+                    &Image::load_image("./assets/img/enemies/jellyAttack.png")?,
+                )?,
+                Vector2 { x: 20.0, y: 20.0 },
+                15,
+                4,
+            ),
         })
     }
 }

From e7ac70074c88227157bf4eb72932c9dd8d1d500d Mon Sep 17 00:00:00 2001
From: rsninja722 <jnick722547@gmail.com>
Date: Sat, 24 Apr 2021 17:33:53 -0400
Subject: [PATCH 08/16] no more stuck

---
 src/logic/ingame/playerlogic.rs | 45 ++++++++++++++++++++-------------
 src/player.rs                   |  5 +++-
 2 files changed, 32 insertions(+), 18 deletions(-)

diff --git a/src/logic/ingame/playerlogic.rs b/src/logic/ingame/playerlogic.rs
index 6446ec5..622c20f 100644
--- a/src/logic/ingame/playerlogic.rs
+++ b/src/logic/ingame/playerlogic.rs
@@ -5,13 +5,13 @@ use crate::{
     pallette::{TRANSLUCENT_WHITE_128, TRANSLUCENT_WHITE_64, TRANSLUCENT_WHITE_96},
 };
 
-const NORMAL_PLAYER_SPEED: i32 = 3;
+const NORMAL_PLAYER_SPEED: i32 = 1;
 const BOOST_PLAYER_SPEED: i32 = NORMAL_PLAYER_SPEED * 2;
 const CAMERA_FOLLOW_SPEED: f32 = 0.7;
 const TURN_SPEED: f32 = 0.15;
 const BOOST_DECREASE_PER_SECOND: f32 = 0.65;
 const BOOST_REGEN_PER_SECOND: f32 = 0.25;
-const BREATH_DECREASE_PER_SECOND: f32 = 0.01;
+const BREATH_DECREASE_PER_SECOND: f32 = 0.02;
 
 pub fn update_player_movement(
     draw_handle: &mut RaylibDrawHandle,
@@ -127,25 +127,36 @@ pub fn update_player_movement(
         (game_core.player.breath_percent - BREATH_DECREASE_PER_SECOND * dt as f32).clamp(0.0, 1.0);
 
     // Only do this if the mouse is far enough away
-    let player_real_movement = game_core.player.direction * speed_multiplier;
+    let mut player_real_movement = game_core.player.direction * speed_multiplier;
     if raw_movement_direction.distance_to(Vector2::zero()) > game_core.player.size.y / 2.0 {
-        game_core.player.is_moving = true;
-        game_core.player.position += player_real_movement;
 
-        // Check for any collisions
-        for collider in game_core.world.colliders.iter() {
-            if game_core.player.collides_with_rec(collider) {
-                game_core.player.is_moving = false;
-                break;
+        if game_core.player.is_moving {
+            // move in x
+            game_core.player.position.x += player_real_movement.x;
+
+            // Check for any collisions
+            for collider in game_core.world.colliders.iter() {
+                if game_core.player.collides_with_rec(collider) {
+                    
+                    game_core.player.position.x -= player_real_movement.x;
+                    player_real_movement.x = 0.0;
+                    break;
+                }
+            }
+            
+            // move in y
+            game_core.player.position.y += player_real_movement.y;
+
+            // Check for any collisions
+            for collider in game_core.world.colliders.iter() {
+                if game_core.player.collides_with_rec(collider) {
+                    game_core.player.position.y -= player_real_movement.y;
+                    player_real_movement.y = 0.0;
+                    break;
+                }
             }
         }
-
-        if !game_core.player.is_moving {
-            game_core.player.position -= player_real_movement;
-        }
-    } else {
-        game_core.player.is_moving = false;
-    }
+    } 
 
     // Move the camera to follow the player
     let direction_from_cam_to_player =
diff --git a/src/player.rs b/src/player.rs
index 01c5343..707e677 100644
--- a/src/player.rs
+++ b/src/player.rs
@@ -7,6 +7,7 @@ pub struct Player {
     pub position: Vector2,
     pub direction: Vector2,
     pub size: Vector2,
+    pub radius: f32,
     pub coins: u32,
     pub boost_percent: f32,
     pub breath_percent: f32,
@@ -21,6 +22,8 @@ impl Player {
             boost_percent: 1.0,
             size: Vector2 { x: 11.0, y: 21.0 },
             breath_percent: 1.0,
+            is_moving: true,
+            radius: 4.5,
             position: spawn.clone(),
             ..Default::default()
         }
@@ -54,6 +57,6 @@ impl Player {
         //     || rectangle.check_collision_point_rec(top_right_corner)
         //     || rectangle.check_collision_point_rec(bottom_left_corner);
 
-        return rectangle.check_collision_circle_rec(self.position, (self.size.y * 0.5) / 2.0);
+        return rectangle.check_collision_circle_rec(self.position, self.radius);
     }
 }

From 09b2752d780963b320acbd9769737c268e3ac545 Mon Sep 17 00:00:00 2001
From: Evan Pratten <ewpratten@gmail.com>
Date: Sat, 24 Apr 2021 18:10:27 -0400
Subject: [PATCH 09/16] stun check

---
 src/entities/enemy/jellyfish.rs | 18 ++++++++----------
 1 file changed, 8 insertions(+), 10 deletions(-)

diff --git a/src/entities/enemy/jellyfish.rs b/src/entities/enemy/jellyfish.rs
index a657b3b..cf6ca10 100644
--- a/src/entities/enemy/jellyfish.rs
+++ b/src/entities/enemy/jellyfish.rs
@@ -11,7 +11,7 @@ pub struct JellyFish {
     pub stunned_timer: f64,
 
     #[serde(skip)]
-    pub do_stun_player: bool
+    pub do_stun_player: bool,
 }
 
 impl JellyFish {}
@@ -37,22 +37,20 @@ impl EnemyBase for JellyFish {
         resources.jellyfish_animation_attack.draw(
             context_2d,
             Vector2 {
-                x: self.position.x
-                    ,
-                y: self.position.y + (2.0 * v_trans as f32)
-                    ,
+                x: self.position.x,
+                y: self.position.y + (2.0 * v_trans as f32),
             },
             0.0,
         );
-        self.do_stun_player = resources.jellyfish_animation_attack.get_current_frame_id(context_2d) == 13;
+        self.do_stun_player = resources
+            .jellyfish_animation_attack
+            .get_current_frame_id(context_2d)
+            == 13;
     }
 
     fn handle_logic(&mut self, player: &mut Player, dt: f64) {
-        
         // Handle stunning the player
-        if self.do_stun_player {
-            
-        }
+        if self.do_stun_player {}
     }
 
     fn handle_getting_attacked(&mut self) {

From 9493baedf54a6b0ad609fafb40e1613a5cc56201 Mon Sep 17 00:00:00 2001
From: Evan Pratten <ewpratten@gmail.com>
Date: Sat, 24 Apr 2021 18:28:27 -0400
Subject: [PATCH 10/16] stun the jellyfish

---
 src/entities/enemy/base.rs      | 11 +++--
 src/entities/enemy/jellyfish.rs | 71 +++++++++++++++++++++++----------
 src/items.rs                    |  4 +-
 src/logic/ingame/mod.rs         | 21 +++++-----
 src/pallette.rs                 |  7 ++++
 src/player.rs                   | 32 ++++++++++++---
 6 files changed, 104 insertions(+), 42 deletions(-)

diff --git a/src/entities/enemy/base.rs b/src/entities/enemy/base.rs
index 83f7af2..d5c3f68 100644
--- a/src/entities/enemy/base.rs
+++ b/src/entities/enemy/base.rs
@@ -3,7 +3,12 @@ use raylib::prelude::*;
 use crate::{player::Player, resources::GlobalResources};
 
 pub trait EnemyBase {
-    fn render(&mut self, context_2d: &mut RaylibMode2D<RaylibDrawHandle>, resources: &mut GlobalResources);
+    fn render(
+        &mut self,
+        context_2d: &mut RaylibMode2D<RaylibDrawHandle>,
+        resources: &mut GlobalResources,
+        dt: f64,
+    );
     fn handle_logic(&mut self, player: &mut Player, dt: f64);
-    fn handle_getting_attacked(&mut self);
-}
\ No newline at end of file
+    fn handle_getting_attacked(&mut self, stun_duration: f64);
+}
diff --git a/src/entities/enemy/jellyfish.rs b/src/entities/enemy/jellyfish.rs
index cf6ca10..74a79e5 100644
--- a/src/entities/enemy/jellyfish.rs
+++ b/src/entities/enemy/jellyfish.rs
@@ -1,5 +1,8 @@
 use super::base::EnemyBase;
-use crate::{player::Player, resources::GlobalResources};
+use crate::{
+    lib::utils::calculate_linear_slide, pallette::TRANSLUCENT_RED_64, player::Player,
+    resources::GlobalResources,
+};
 use raylib::prelude::*;
 use serde::{Deserialize, Serialize};
 
@@ -9,6 +12,8 @@ pub struct JellyFish {
 
     #[serde(skip)]
     pub stunned_timer: f64,
+    #[serde(skip)]
+    pub max_stunned_time: f64,
 
     #[serde(skip)]
     pub do_stun_player: bool,
@@ -21,31 +26,51 @@ impl EnemyBase for JellyFish {
         &mut self,
         context_2d: &mut raylib::prelude::RaylibMode2D<raylib::prelude::RaylibDrawHandle>,
         resources: &mut GlobalResources,
+        dt: f64
     ) {
+        let is_jelly_stunned = self.stunned_timer != 0.0;
+
         // Simple sine position
-        let v_trans = context_2d.get_time().sin();
+        let v_trans = if is_jelly_stunned {
+            0.0
+        } else {
+            context_2d.get_time().sin()
+        };
+        let trans_pose = Vector2 {
+            x: self.position.x,
+            y: self.position.y + (2.0 * v_trans as f32),
+        };
+
+        // Render the stun ring
+        if self.max_stunned_time > 0.0 && self.stunned_timer > 0.0 {
+            let stun_ring_radius =
+                calculate_linear_slide(self.stunned_timer / self.max_stunned_time);
+            context_2d.draw_circle_v(
+                trans_pose,
+                stun_ring_radius as f32 * 20.0,
+                TRANSLUCENT_RED_64,
+            );
+            self.stunned_timer -= dt;
+        }
 
         // Render the jellyfish
-        resources.jellyfish_animation_regular.draw(
-            context_2d,
-            Vector2 {
-                x: self.position.x,
-                y: self.position.y + (2.0 * v_trans as f32),
-            },
-            0.0,
-        );
-        resources.jellyfish_animation_attack.draw(
-            context_2d,
-            Vector2 {
-                x: self.position.x,
-                y: self.position.y + (2.0 * v_trans as f32),
-            },
-            0.0,
-        );
-        self.do_stun_player = resources
+        resources
+            .jellyfish_animation_regular
+            .draw(context_2d, trans_pose, 0.0);
+
+        // Only do stun loop if not stunned
+        if !is_jelly_stunned {
+            resources
+                .jellyfish_animation_attack
+                .draw(context_2d, trans_pose, 0.0);
+        }
+
+        // Check if the jelly is in stun mode
+        self.do_stun_player = (resources
             .jellyfish_animation_attack
             .get_current_frame_id(context_2d)
-            == 13;
+            == 13)
+            && !is_jelly_stunned;
     }
 
     fn handle_logic(&mut self, player: &mut Player, dt: f64) {
@@ -53,7 +78,9 @@ impl EnemyBase for JellyFish {
         if self.do_stun_player {}
     }
 
-    fn handle_getting_attacked(&mut self) {
-        todo!()
+    fn handle_getting_attacked(&mut self, stun_duration: f64) {
+        println!("Attack");
+        self.stunned_timer = stun_duration;
+        self.max_stunned_time = stun_duration;
     }
 }
diff --git a/src/items.rs b/src/items.rs
index 60d99a3..90ae94d 100644
--- a/src/items.rs
+++ b/src/items.rs
@@ -10,13 +10,13 @@ impl StunGun {
     pub fn lvl1() -> Self {
         Self {
             range: 30.0,
-            duration: 0.5,
+            duration: 0.75,
         }
     }
     pub fn lvl2() -> Self {
         Self {
             range: 60.0,
-            duration: 0.75,
+            duration: 1.25,
         }
     }
 }
diff --git a/src/logic/ingame/mod.rs b/src/logic/ingame/mod.rs
index 469d761..f3b6cb8 100644
--- a/src/logic/ingame/mod.rs
+++ b/src/logic/ingame/mod.rs
@@ -3,7 +3,12 @@ mod playerlogic;
 
 use raylib::prelude::*;
 
-use crate::{entities::enemy::base::EnemyBase, gamecore::{GameCore, GameState}, lib::wrappers::audio::player::AudioPlayer, pallette::{SKY, WATER}};
+use crate::{
+    entities::enemy::base::EnemyBase,
+    gamecore::{GameCore, GameState},
+    lib::wrappers::audio::player::AudioPlayer,
+    pallette::{SKY, WATER},
+};
 
 use super::screen::Screen;
 
@@ -64,11 +69,7 @@ impl InGameScreen {
     ) {
         // Render every collider
         for collider in game_core.world.colliders.iter() {
-            context_2d.draw_rectangle_lines_ex(
-                collider,
-                1,
-                Color::RED,
-            );
+            context_2d.draw_rectangle_lines_ex(collider, 1, Color::RED);
         }
     }
 }
@@ -110,7 +111,7 @@ impl Screen for InGameScreen {
 
             // Render the world
             self.render_world(&mut context_2d, game_core);
-            if game_core.show_simple_debug_info{
+            if game_core.show_simple_debug_info {
                 self.render_colliders(&mut context_2d, game_core);
             }
 
@@ -121,11 +122,13 @@ impl Screen for InGameScreen {
                 fish.render(&mut context_2d);
             }
             for jellyfish in game_core.world.jellyfish.iter_mut() {
-                jellyfish.render(&mut context_2d, &mut game_core.resources);
+                jellyfish.render(&mut context_2d, &mut game_core.resources, dt);
             }
 
             // Render Player
-            game_core.player.render(&mut context_2d, &mut game_core.resources, dt);
+            game_core
+                .player
+                .render(&mut context_2d, &mut game_core.resources, dt);
         }
 
         // Render the hud
diff --git a/src/pallette.rs b/src/pallette.rs
index 5d675ca..b6cb182 100644
--- a/src/pallette.rs
+++ b/src/pallette.rs
@@ -33,4 +33,11 @@ pub const WATER: Color = Color {
     g: 66,
     b: 143,
     a: 255
+};
+
+pub const TRANSLUCENT_RED_64: Color = Color {
+    r: 230,
+    g: 41,
+    b: 55,
+    a: 64,
 };
\ No newline at end of file
diff --git a/src/player.rs b/src/player.rs
index d2335bf..cafded3 100644
--- a/src/player.rs
+++ b/src/player.rs
@@ -1,6 +1,14 @@
+use crate::{
+    entities::enemy::base::EnemyBase,
+    gamecore::{GameCore, GameProgress},
+    items::{AirBag, Flashlight, Flippers, StunGun},
+    lib::utils::calculate_linear_slide,
+    pallette::{TRANSLUCENT_WHITE_64, TRANSLUCENT_WHITE_96},
+    resources::GlobalResources,
+    world::World,
+};
 use raylib::prelude::*;
-use serde::{Serialize, Deserialize};
-use crate::{entities::enemy::base::EnemyBase, gamecore::{GameCore, GameProgress}, items::{AirBag, Flashlight, Flippers, StunGun}, lib::utils::{calculate_linear_slide}, pallette::{TRANSLUCENT_WHITE_64, TRANSLUCENT_WHITE_96}, resources::GlobalResources, world::World};
+use serde::{Deserialize, Serialize};
 
 const AOE_RING_MAX_RADIUS: f32 = 60.0;
 const STUN_ATTACK_TIME: f64 = 0.75;
@@ -10,7 +18,16 @@ pub struct PlayerInventory {
     pub stun_gun: Option<StunGun>,
     pub air_bag: Option<AirBag>,
     pub flashlight: Option<Flashlight>,
-    pub flippers: Option<Flippers>
+    pub flippers: Option<Flippers>,
+}
+
+impl PlayerInventory {
+    pub fn new() -> Self {
+        Self {
+            stun_gun: Some(StunGun::lvl1()), //TMP
+            ..Default::default()
+        }
+    }
 }
 
 #[derive(Debug, Default)]
@@ -39,6 +56,7 @@ impl Player {
             is_moving: true,
             radius: 4.5,
             position: spawn.clone(),
+            inventory: PlayerInventory::new(),
             ..Default::default()
         }
     }
@@ -84,12 +102,12 @@ impl Player {
         if self.inventory.stun_gun.is_some() && self.stun_timer == 0.0 {
             self.attacking_timer = self.inventory.stun_gun.as_ref().unwrap().duration;
 
-            // Stun everything in reach 
+            // Stun everything in reach
             let stun_reach = self.inventory.stun_gun.as_ref().unwrap().range;
 
             for jellyfish in world.jellyfish.iter_mut() {
                 if jellyfish.position.distance_to(self.position).abs() <= stun_reach {
-                    jellyfish.handle_getting_attacked();
+                    jellyfish.handle_getting_attacked(self.attacking_timer);
                 }
             }
         }
@@ -151,7 +169,9 @@ impl Player {
 
         // Calculate AOE ring
         if self.is_stun_gun_active() {
-            let aoe_ring = calculate_linear_slide( self.attacking_timer / self.inventory.stun_gun.as_ref().unwrap().duration) as f32;
+            let aoe_ring = calculate_linear_slide(
+                self.attacking_timer / self.inventory.stun_gun.as_ref().unwrap().duration,
+            ) as f32;
             self.attacking_timer = (self.attacking_timer - dt).max(0.0);
 
             // Render attack AOE

From 99e7e02d0c045ae75be8810221f6d974887ca787 Mon Sep 17 00:00:00 2001
From: Evan Pratten <ewpratten@gmail.com>
Date: Sat, 24 Apr 2021 18:32:08 -0400
Subject: [PATCH 11/16] Better AOE animation

---
 src/player.rs | 27 ++++++++++++++++++---------
 1 file changed, 18 insertions(+), 9 deletions(-)

diff --git a/src/player.rs b/src/player.rs
index cafded3..341d70e 100644
--- a/src/player.rs
+++ b/src/player.rs
@@ -169,18 +169,27 @@ impl Player {
 
         // Calculate AOE ring
         if self.is_stun_gun_active() {
-            let aoe_ring = calculate_linear_slide(
-                self.attacking_timer / self.inventory.stun_gun.as_ref().unwrap().duration,
-            ) as f32;
+            let animation_progression =
+                self.attacking_timer / self.inventory.stun_gun.as_ref().unwrap().duration;
+            let aoe_ring = calculate_linear_slide(animation_progression) as f32;
             self.attacking_timer = (self.attacking_timer - dt).max(0.0);
 
             // Render attack AOE
-            context_2d.draw_circle_lines(
-                self.position.x as i32,
-                self.position.y as i32,
-                self.inventory.stun_gun.as_ref().unwrap().range * aoe_ring,
-                TRANSLUCENT_WHITE_64,
-            );
+            if animation_progression <= 0.5 {
+                context_2d.draw_circle_lines(
+                    self.position.x as i32,
+                    self.position.y as i32,
+                    self.inventory.stun_gun.as_ref().unwrap().range * aoe_ring,
+                    TRANSLUCENT_WHITE_64,
+                );
+            } else {
+                context_2d.draw_circle_lines(
+                    self.position.x as i32,
+                    self.position.y as i32,
+                    self.inventory.stun_gun.as_ref().unwrap().range,
+                    TRANSLUCENT_WHITE_64.fade(aoe_ring),
+                );
+            }
         }
 
         // Render the player based on what is happening

From 91482353836a308cc19d4c9f2a6a25f1f68a70de Mon Sep 17 00:00:00 2001
From: Evan Pratten <ewpratten@gmail.com>
Date: Sat, 24 Apr 2021 18:45:13 -0400
Subject: [PATCH 12/16] jelly can stun player

---
 src/entities/enemy/jellyfish.rs | 20 +++++++++++++-------
 src/logic/ingame/mod.rs         |  1 +
 2 files changed, 14 insertions(+), 7 deletions(-)

diff --git a/src/entities/enemy/jellyfish.rs b/src/entities/enemy/jellyfish.rs
index 74a79e5..4ddad72 100644
--- a/src/entities/enemy/jellyfish.rs
+++ b/src/entities/enemy/jellyfish.rs
@@ -6,6 +6,9 @@ use crate::{
 use raylib::prelude::*;
 use serde::{Deserialize, Serialize};
 
+const JELLYFISH_STUN_DURATION: f64 = 0.75;
+const JELLYFISH_STUN_REACH: f32 = 20.0;
+
 #[derive(Debug, Serialize, Deserialize, Default, Clone)]
 pub struct JellyFish {
     pub position: Vector2,
@@ -26,9 +29,9 @@ impl EnemyBase for JellyFish {
         &mut self,
         context_2d: &mut raylib::prelude::RaylibMode2D<raylib::prelude::RaylibDrawHandle>,
         resources: &mut GlobalResources,
-        dt: f64
+        dt: f64,
     ) {
-        let is_jelly_stunned = self.stunned_timer != 0.0;
+        let is_jelly_stunned = self.stunned_timer > 0.0;
 
         // Simple sine position
         let v_trans = if is_jelly_stunned {
@@ -43,12 +46,12 @@ impl EnemyBase for JellyFish {
 
         // Render the stun ring
         if self.max_stunned_time > 0.0 && self.stunned_timer > 0.0 {
-            let stun_ring_radius =
+            let stun_ring_alpha =
                 calculate_linear_slide(self.stunned_timer / self.max_stunned_time);
             context_2d.draw_circle_v(
                 trans_pose,
-                stun_ring_radius as f32 * 20.0,
-                TRANSLUCENT_RED_64,
+                JELLYFISH_STUN_REACH,
+                TRANSLUCENT_RED_64.fade(0.55 * stun_ring_alpha as f32),
             );
             self.stunned_timer -= dt;
         }
@@ -75,11 +78,14 @@ impl EnemyBase for JellyFish {
 
     fn handle_logic(&mut self, player: &mut Player, dt: f64) {
         // Handle stunning the player
-        if self.do_stun_player {}
+        if self.do_stun_player {
+            if self.position.distance_to(player.position).abs() <= JELLYFISH_STUN_REACH {
+                player.set_stun_seconds(JELLYFISH_STUN_DURATION);
+            }
+        }
     }
 
     fn handle_getting_attacked(&mut self, stun_duration: f64) {
-        println!("Attack");
         self.stunned_timer = stun_duration;
         self.max_stunned_time = stun_duration;
     }
diff --git a/src/logic/ingame/mod.rs b/src/logic/ingame/mod.rs
index f3b6cb8..a9a75c0 100644
--- a/src/logic/ingame/mod.rs
+++ b/src/logic/ingame/mod.rs
@@ -122,6 +122,7 @@ impl Screen for InGameScreen {
                 fish.render(&mut context_2d);
             }
             for jellyfish in game_core.world.jellyfish.iter_mut() {
+                jellyfish.handle_logic(&mut game_core.player, dt);
                 jellyfish.render(&mut context_2d, &mut game_core.resources, dt);
             }
 

From 0659780b3d414ab28f8894707b8a74eea6044904 Mon Sep 17 00:00:00 2001
From: Evan Pratten <ewpratten@gmail.com>
Date: Sat, 24 Apr 2021 18:46:13 -0400
Subject: [PATCH 13/16] load stunned animation

---
 assets/img/character/stunned.json |  50 ++++++++++++++++++++++++++++++
 assets/img/character/stunned.png  | Bin 0 -> 841 bytes
 2 files changed, 50 insertions(+)
 create mode 100644 assets/img/character/stunned.json
 create mode 100644 assets/img/character/stunned.png

diff --git a/assets/img/character/stunned.json b/assets/img/character/stunned.json
new file mode 100644
index 0000000..5d29dfc
--- /dev/null
+++ b/assets/img/character/stunned.json
@@ -0,0 +1,50 @@
+{ "frames": {
+   "walk1 0.png": {
+    "frame": { "x": 0, "y": 0, "w": 12, "h": 22 },
+    "rotated": false,
+    "trimmed": false,
+    "spriteSourceSize": { "x": 0, "y": 0, "w": 12, "h": 22 },
+    "sourceSize": { "w": 12, "h": 22 },
+    "duration": 200
+   },
+   "walk1 1.png": {
+    "frame": { "x": 12, "y": 0, "w": 12, "h": 22 },
+    "rotated": false,
+    "trimmed": false,
+    "spriteSourceSize": { "x": 0, "y": 0, "w": 12, "h": 22 },
+    "sourceSize": { "w": 12, "h": 22 },
+    "duration": 200
+   },
+   "walk1 2.png": {
+    "frame": { "x": 24, "y": 0, "w": 12, "h": 22 },
+    "rotated": false,
+    "trimmed": false,
+    "spriteSourceSize": { "x": 0, "y": 0, "w": 12, "h": 22 },
+    "sourceSize": { "w": 12, "h": 22 },
+    "duration": 200
+   },
+   "walk1 3.png": {
+    "frame": { "x": 36, "y": 0, "w": 12, "h": 22 },
+    "rotated": false,
+    "trimmed": false,
+    "spriteSourceSize": { "x": 0, "y": 0, "w": 12, "h": 22 },
+    "sourceSize": { "w": 12, "h": 22 },
+    "duration": 200
+   }
+ },
+ "meta": {
+  "app": "http://www.aseprite.org/",
+  "version": "1.2.27-x64",
+  "image": "stunned.png",
+  "format": "RGBA8888",
+  "size": { "w": 48, "h": 22 },
+  "scale": "1",
+  "frameTags": [
+  ],
+  "layers": [
+   { "name": "Layer", "opacity": 255, "blendMode": "normal" }
+  ],
+  "slices": [
+  ]
+ }
+}
diff --git a/assets/img/character/stunned.png b/assets/img/character/stunned.png
new file mode 100644
index 0000000000000000000000000000000000000000..986e8f0a3b0273c2b4307dfeb19c162b6780fb6e
GIT binary patch
literal 841
zcmV-P1GfB$P)<h;3K|Lk000e1NJLTq001xm000&U1^@s6hW8(=00001b5ch_0Itp)
z=>Px&14%?dR9J=8mrrQZP#nj<iON9MfFPL&4s5o03FKfYjM<9^WguNAYzX4m#iJ-=
z!gf%`F597cP;Y{G5#|J)yA*ewMK-oWA?z@lRSH&{i%>--BF{tiV&2P3`Z92^9~45~
z=llKr-k<!E0*5>ldhz!D8!|LItN_4bIX4FY9q%Tl=r|n<^8A?Sp2$DWBWVtmzX<@N
z1FO@c1FO@2df!Ky$0d#{RMtZ_hZ>jY$j1vXv@{mWxjDKk?ZVK~kz=BX#PKpYRKS}}
z%CwO(Z6=AKrSZvp;O|Jg#8Jfz%?>MumWH9FL;kXbM%_~Z@62Buy{G8)JW{630LNRs
zi4sJGIcX_LH8Q*kcxN5}P|$$B4gi2%tsQIh??SKVAv`_>&HL@KE9Es3EL0errqRC}
zU%f;Q<{4--UFe-7u&Xs<_MH7qO-_EkG-VenglG4R88#TQ8oO8_JS&sKE>;LLfk%&@
z_@b5a8adsi`(sXP2eK?RPom-3c0Bbz%8Mw(7sQ{%`OGBn0YHIe_f{+NyvzFgJJO{I
zd8$z<OuK{o;}runnlAKuJ|qUjtJY|`p`#P@7x7Uc<F5jM+r5mGX=CDQAN0<Vkg40f
z47YnZWJXsls)*pjW@u?|*V+`F)L#Vv+Cueu9$0GOi}TDEI;BnM^*p}YCew|sFWmGl
zmRfL1n+y-ItH*RE2|kIx3IJ9nOQtr8zW9W33aigca7vrVjSu?wX}h&DS#qZ5+`p9?
zJRjnNXPWmH@xe&q&vYR=t8dO%<i-bmAqtxCdxY}TILM3M2XXv<{h0|o-F^+HwS%AA
z7V|J~HOJ;fFEh&XLA%gF@Cx8<S!H8gxpM6W0lXGTg}*L8oaeuT;&{<Y{!d=vMRv6o
zYIj@BG2tX$EWC_e9Z^vte~~7sKNicmxjQrc#L8reU9FLo@*1%+Sz=|fgpTtGqS&ZN
zqLF3&e_(Wl?P`rQnlA3%zU4!ejdkIyld${I$gu3!D7-BSzP95EO2QtL|DlV&cgcxa
TDc<|)00000NkvXXu0mjfD5R0t

literal 0
HcmV?d00001


From 54ff1c79316135db0db0e8707189d1850e2f7fdd Mon Sep 17 00:00:00 2001
From: Evan Pratten <ewpratten@gmail.com>
Date: Sat, 24 Apr 2021 18:54:23 -0400
Subject: [PATCH 14/16] finished stun system

---
 src/logic/ingame/playerlogic.rs |  8 ++++++--
 src/player.rs                   | 14 ++++++++++++--
 src/resources.rs                | 10 ++++++++++
 3 files changed, 28 insertions(+), 4 deletions(-)

diff --git a/src/logic/ingame/playerlogic.rs b/src/logic/ingame/playerlogic.rs
index d9ca234..cdb261d 100644
--- a/src/logic/ingame/playerlogic.rs
+++ b/src/logic/ingame/playerlogic.rs
@@ -65,7 +65,9 @@ pub fn update_player_movement(
     }
 
     // set angle
-    game_core.player.direction = Vector2::new(f32::cos(player_angle), f32::sin(player_angle));
+    if !game_core.player.is_stunned() {
+        game_core.player.direction = Vector2::new(f32::cos(player_angle), f32::sin(player_angle));
+    }
 
     // In the case the player is in "null", just jump the camera to them
     if game_core.player.position == Vector2::zero() {
@@ -145,7 +147,9 @@ pub fn update_player_movement(
     // Only do this if the mouse is far enough away
     let player_stunned = game_core.player.stun_timer > 0.0;
     let mut player_real_movement = game_core.player.direction * speed_multiplier;
-    if raw_movement_direction.distance_to(Vector2::zero()) > game_core.player.size.y / 2.0 {
+    if raw_movement_direction.distance_to(Vector2::zero()) > game_core.player.size.y / 2.0
+        && !game_core.player.is_stunned()
+    {
         if game_core.player.is_moving {
             // move in x
             game_core.player.position.x += player_real_movement.x;
diff --git a/src/player.rs b/src/player.rs
index 341d70e..efcb5ea 100644
--- a/src/player.rs
+++ b/src/player.rs
@@ -99,7 +99,7 @@ impl Player {
 
     /// Try to attack with the stun gun
     pub fn begin_attack(&mut self, world: &mut World) {
-        if self.inventory.stun_gun.is_some() && self.stun_timer == 0.0 {
+        if self.inventory.stun_gun.is_some() && !self.is_stunned() {
             self.attacking_timer = self.inventory.stun_gun.as_ref().unwrap().duration;
 
             // Stun everything in reach
@@ -117,6 +117,10 @@ impl Player {
         return self.attacking_timer != 0.0 && self.inventory.stun_gun.is_some();
     }
 
+    pub fn is_stunned(&self) -> bool {
+        return self.stun_timer > 0.0;
+    }
+
     /// Calculate how far the player is
     pub fn calculate_depth_percent(&self, world: &World) -> f32 {
         let dist_from_player_to_end = self.position.distance_to(world.end_position);
@@ -193,7 +197,13 @@ impl Player {
         }
 
         // Render the player based on what is happening
-        if self.is_boost_charging {
+        if self.is_stunned() {
+            resources.player_animation_stunned.draw(
+                context_2d,
+                self.position,
+                player_rotation.to_degrees() - 90.0,
+            );
+        } else if self.is_boost_charging {
             resources.player_animation_boost_charge.draw(
                 context_2d,
                 self.position,
diff --git a/src/resources.rs b/src/resources.rs
index 8b8459d..51d115c 100644
--- a/src/resources.rs
+++ b/src/resources.rs
@@ -16,6 +16,7 @@ pub struct GlobalResources {
     pub player_animation_regular: FrameAnimationWrapper,
     pub player_animation_boost_charge: FrameAnimationWrapper,
     pub player_animation_boost: FrameAnimationWrapper,
+    pub player_animation_stunned: FrameAnimationWrapper,
 
     // Cave
     pub cave_mid_layer: Texture2D,
@@ -63,6 +64,15 @@ impl GlobalResources {
                 21,
                 30,
             ),
+            player_animation_stunned: FrameAnimationWrapper::new(
+                raylib.load_texture_from_image(
+                    &thread,
+                    &Image::load_image("./assets/img/character/stunned.png")?,
+                )?,
+                Vector2 { x: 12.0, y: 22.0 },
+                4,
+                100 / 8,
+            ),
             cave_mid_layer: raylib.load_texture_from_image(
                 &thread,
                 &Image::load_image("./assets/img/map/cave.png")?,

From f9957f57ea96a02692dc3125a6dd2755def27d72 Mon Sep 17 00:00:00 2001
From: Evan Pratten <ewpratten@gmail.com>
Date: Sat, 24 Apr 2021 18:58:20 -0400
Subject: [PATCH 15/16] reverse stun animation

---
 src/player.rs | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/player.rs b/src/player.rs
index efcb5ea..0d30883 100644
--- a/src/player.rs
+++ b/src/player.rs
@@ -179,12 +179,12 @@ impl Player {
             self.attacking_timer = (self.attacking_timer - dt).max(0.0);
 
             // Render attack AOE
-            if animation_progression <= 0.5 {
+            if animation_progression >= 0.5 {
                 context_2d.draw_circle_lines(
                     self.position.x as i32,
                     self.position.y as i32,
                     self.inventory.stun_gun.as_ref().unwrap().range * aoe_ring,
-                    TRANSLUCENT_WHITE_64,
+                    TRANSLUCENT_WHITE_64.fade(aoe_ring),
                 );
             } else {
                 context_2d.draw_circle_lines(

From 81126975a122082b8b1cb88885d678808a87270c Mon Sep 17 00:00:00 2001
From: Evan Pratten <ewpratten@gmail.com>
Date: Sat, 24 Apr 2021 19:02:03 -0400
Subject: [PATCH 16/16] fix fish render layer

---
 src/logic/ingame/mod.rs | 17 ++++++++++-------
 1 file changed, 10 insertions(+), 7 deletions(-)

diff --git a/src/logic/ingame/mod.rs b/src/logic/ingame/mod.rs
index a9a75c0..7c04afc 100644
--- a/src/logic/ingame/mod.rs
+++ b/src/logic/ingame/mod.rs
@@ -32,6 +32,7 @@ impl InGameScreen {
         &mut self,
         context_2d: &mut RaylibMode2D<RaylibDrawHandle>,
         game_core: &mut GameCore,
+        dt: f64
     ) {
         // Build source bounds
         let source_bounds = Rectangle {
@@ -50,6 +51,13 @@ impl InGameScreen {
         // Clear the background
         context_2d.draw_rectangle_rec(world_bounds, WATER);
 
+        // Render fish
+        let fish_clone = game_core.world.fish.clone();
+        for fish in game_core.world.fish.iter_mut() {
+            fish.update_position(&mut game_core.player, dt, &fish_clone);
+            fish.render(context_2d);
+        }
+
         // Render the world texture
         context_2d.draw_texture_rec(
             &game_core.resources.cave_mid_layer,
@@ -107,20 +115,15 @@ impl Screen for InGameScreen {
 
         // Open a 2D context
         {
-            let mut context_2d = draw_handle.begin_mode2D(game_core.master_camera);
+            let mut context_2d = draw_handle.begin_mode2D(game_core.master_camera);            
 
             // Render the world
-            self.render_world(&mut context_2d, game_core);
+            self.render_world(&mut context_2d, game_core, dt);
             if game_core.show_simple_debug_info {
                 self.render_colliders(&mut context_2d, game_core);
             }
 
             // Render entities
-            let fish_clone = game_core.world.fish.clone();
-            for fish in game_core.world.fish.iter_mut() {
-                fish.update_position(&mut game_core.player, dt, &fish_clone);
-                fish.render(&mut context_2d);
-            }
             for jellyfish in game_core.world.jellyfish.iter_mut() {
                 jellyfish.handle_logic(&mut game_core.player, dt);
                 jellyfish.render(&mut context_2d, &mut game_core.resources, dt);