]> git.seodisparate.com - LudumDare47_StuckInALoop/commitdiff
Impl moving from room to room
authorStephen Seo <seo.disparate@gmail.com>
Sun, 4 Oct 2020 03:14:46 +0000 (12:14 +0900)
committerStephen Seo <seo.disparate@gmail.com>
Sun, 4 Oct 2020 03:14:46 +0000 (12:14 +0900)
Added doors and interactables

resources/door.png [new file with mode: 0644]
src/door.rs [new file with mode: 0644]
src/interactable.rs [new file with mode: 0644]
src/main.rs
src/scenes/mainscene.rs

diff --git a/resources/door.png b/resources/door.png
new file mode 100644 (file)
index 0000000..6e04c7c
Binary files /dev/null and b/resources/door.png differ
diff --git a/src/door.rs b/src/door.rs
new file mode 100644 (file)
index 0000000..eb7258b
--- /dev/null
@@ -0,0 +1,78 @@
+use ggez::graphics::{self, DrawParam, Image, Rect};
+use ggez::{Context, GameResult};
+
+const DEFAULT_RADIUS: f32 = 70f32;
+
+pub struct Door {
+    is_open: bool,
+    x: f32,
+    y: f32,
+    id: usize,
+    enter_radius: f32,
+}
+
+impl Door {
+    pub fn new(is_open: bool, x: f32, y: f32, id: usize) -> Self {
+        Door {
+            is_open,
+            x,
+            y,
+            id,
+            enter_radius: DEFAULT_RADIUS,
+        }
+    }
+
+    pub fn draw(&self, ctx: &mut Context, door_image: &Image) -> GameResult<()> {
+        if self.is_open {
+            graphics::draw(
+                ctx,
+                door_image,
+                DrawParam::new()
+                    .src(Rect::new(0f32, 0.8f32, 1f32, 0.2f32))
+                    .dest([self.x, self.y]),
+            )?;
+        } else {
+            graphics::draw(ctx, door_image, DrawParam::new().dest([self.x, self.y]))?;
+        }
+        Ok(())
+    }
+
+    pub fn get_open(&self) -> bool {
+        self.is_open
+    }
+
+    pub fn set_open(&mut self, is_open: bool) {
+        self.is_open = is_open;
+    }
+
+    pub fn toggle_open(&mut self) -> bool {
+        self.is_open = !self.is_open;
+        self.is_open
+    }
+
+    pub fn get_id(&self) -> usize {
+        self.id
+    }
+
+    pub fn is_within_range(&self, x: f32, y: f32) -> bool {
+        let a = (self.x + 96f32 / 2f32) - x;
+        let b = (self.y + 80f32) - y;
+        (a * a + b * b).sqrt() <= self.enter_radius
+    }
+
+    pub fn get_x(&self) -> f32 {
+        self.x
+    }
+
+    pub fn get_y(&self) -> f32 {
+        self.y
+    }
+
+    pub fn get_center_x(&self) -> f32 {
+        self.x + 96f32 / 2f32
+    }
+
+    pub fn get_center_y(&self) -> f32 {
+        self.y + 80f32
+    }
+}
diff --git a/src/interactable.rs b/src/interactable.rs
new file mode 100644 (file)
index 0000000..a7c78fe
--- /dev/null
@@ -0,0 +1,73 @@
+use ggez::graphics::{self, Color, DrawMode, DrawParam, Mesh, Rect};
+use ggez::{Context, GameResult};
+
+const DEFAULT_RADIUS: f32 = 70f32;
+
+#[derive(Copy, Clone, PartialEq)]
+pub enum InteractableType {
+    Door(usize),
+}
+
+pub struct Interactable {
+    itype: InteractableType,
+    x: f32,
+    y: f32,
+    radius: f32,
+}
+
+impl Interactable {
+    pub fn new(itype: InteractableType, x: f32, y: f32) -> Self {
+        Self {
+            itype,
+            x,
+            y,
+            radius: DEFAULT_RADIUS,
+        }
+    }
+
+    pub fn is_within_range(&self, x: f32, y: f32) -> bool {
+        let a = self.x - x;
+        let b = self.y - y;
+        (a * a + b * b).sqrt() <= self.radius
+    }
+
+    pub fn get_type(&self) -> InteractableType {
+        self.itype
+    }
+
+    pub fn get_radius(&mut self) -> f32 {
+        self.radius
+    }
+
+    pub fn set_radius(&mut self, radius: f32) {
+        self.radius = radius;
+    }
+
+    pub fn get_x(&self) -> f32 {
+        self.x
+    }
+
+    pub fn get_y(&self) -> f32 {
+        self.y
+    }
+
+    pub fn draw(&self, ctx: &mut Context) -> GameResult<()> {
+        match self.itype {
+            InteractableType::Door(_) => {
+                let panel_mesh = Mesh::new_rectangle(
+                    ctx,
+                    DrawMode::fill(),
+                    Rect::new(0f32, 0f32, 14f32, 16f32),
+                    Color::from_rgb(0x16, 0x9c, 0xd8),
+                )?;
+                graphics::draw(
+                    ctx,
+                    &panel_mesh,
+                    DrawParam::new().dest([self.x - 7f32, self.y - 8f32]),
+                )?;
+            }
+        }
+
+        Ok(())
+    }
+}
index 1d519338134102076610adb86bd4de1d9efab24e..795c423ccf75ba54f0ac5fe5f696679b046e87e9 100644 (file)
@@ -1,4 +1,6 @@
+mod door;
 mod game;
+mod interactable;
 mod player;
 mod scenes;
 
index 532f49f824b14eb694533329d4646e88106aac0c..79cf0c7ba642cc1ff621d08c669b07ef43b305e7 100644 (file)
@@ -10,6 +10,8 @@ use ggez::timer::delta;
 use ggez::{Context, GameResult};
 
 use super::Scene;
+use crate::door::Door;
+use crate::interactable::{Interactable, InteractableType};
 use crate::player::Player;
 
 const DARKNESS_PAN_RATE: f32 = 40f32;
@@ -30,6 +32,7 @@ enum State {
 
 enum Room {
     StasisPod,
+    LeftOfPod,
 }
 
 enum WalkingState {
@@ -57,6 +60,11 @@ pub struct MainScene {
     index: usize,
     room: Room,
     walking_state: WalkingState,
+    door_image: Image,
+    interactables: Vec<Interactable>,
+    interact_text: Text,
+    doors: Vec<Door>,
+    door_text: Text,
 }
 
 impl MainScene {
@@ -64,8 +72,12 @@ impl MainScene {
         let mut music = Source::new(ctx, "/music00.ogg").unwrap();
         music.set_repeat(true);
         //        music.play().unwrap();
-        let mut current_text = Text::new("".to_owned());
+        let mut current_text = Text::new("");
         current_text.set_font(font, Scale::uniform(26f32));
+        let mut interact_text = Text::new("[E] or Left Click to Interact");
+        interact_text.set_font(font, Scale::uniform(20f32));
+        let mut door_text = Text::new("[W] or Right Click to enter door");
+        door_text.set_font(font, Scale::uniform(20f32));
         Self {
             font,
             player,
@@ -85,12 +97,105 @@ impl MainScene {
             index: 0usize,
             room: Room::StasisPod,
             walking_state: WalkingState::Standing,
+            door_image: Image::new(ctx, "/door.png").unwrap(),
+            interactables: Vec::new(),
+            interact_text,
+            doors: Vec::new(),
+            door_text,
         }
     }
 
     pub fn new_boxed(ctx: &mut Context, font: Font, player: Rc<RefCell<Player>>) -> Box<Self> {
         Box::new(Self::new(ctx, font, player))
     }
+
+    fn init_room(&mut self) {
+        match self.room {
+            Room::StasisPod => {
+                self.current_text = Text::new("A and D or Left and Right or Left Click to move");
+                self.current_text.set_font(self.font, Scale::uniform(26f32));
+                self.darkness_yoffset = -300f32;
+                self.interactables.clear();
+                self.doors.clear();
+            }
+            Room::LeftOfPod => {
+                self.current_text = Text::new("");
+                self.current_text.set_font(self.font, Scale::uniform(26f32));
+                self.interactables.clear();
+                self.interactables.push(Interactable::new(
+                    InteractableType::Door(0),
+                    430f32,
+                    450f32,
+                ));
+                self.darkness_yoffset = -300f32;
+                self.doors.clear();
+                self.doors
+                    .push(Door::new(false, 300f32, 600f32 - 160f32 - 50f32, 0));
+            }
+        }
+    }
+
+    fn draw_room_arrows(&mut self, ctx: &mut Context) -> GameResult<()> {
+        let mut draw_left = false;
+        let mut draw_right = false;
+        match self.room {
+            Room::StasisPod => {
+                draw_left = true;
+            }
+            Room::LeftOfPod => {
+                draw_right = true;
+            }
+        }
+
+        if draw_left {
+            let mesh = Mesh::from_triangles(
+                ctx,
+                &[[32f32, 0f32], [32f32, 32f32], [0f32, 16f32]],
+                graphics::WHITE,
+            )?;
+            graphics::draw(ctx, &mesh, DrawParam::new().dest([32f32, 530f32]))?;
+        }
+        if draw_right {
+            let mesh = Mesh::from_triangles(
+                ctx,
+                &[[0f32, 0f32], [32f32, 16f32], [0f32, 32f32]],
+                graphics::WHITE,
+            )?;
+            graphics::draw(ctx, &mesh, DrawParam::new().dest([800f32 - 64f32, 530f32]))?;
+        }
+
+        Ok(())
+    }
+
+    fn check_exit_left(&mut self) {
+        match self.room {
+            Room::StasisPod => {
+                self.room = Room::LeftOfPod;
+                self.player.borrow_mut().x = 800f32 - 70f32;
+                self.init_room();
+            }
+            Room::LeftOfPod => (),
+        }
+    }
+
+    fn check_exit_right(&mut self) {
+        match self.room {
+            Room::StasisPod => (),
+            Room::LeftOfPod => {
+                self.room = Room::StasisPod;
+                self.player.borrow_mut().x = 70f32;
+                self.init_room();
+            }
+        }
+    }
+
+    fn use_interactable(&mut self, itype: InteractableType) {
+        match itype {
+            InteractableType::Door(id) => {
+                self.doors[id].toggle_open();
+            }
+        }
+    }
 }
 
 impl EventHandler for MainScene {
@@ -147,37 +252,43 @@ impl EventHandler for MainScene {
                 } else if self.timer <= 0f32 {
                     self.state = State::Investigate;
                     self.music.play()?;
+                    self.init_room();
                 }
             }
             State::Investigate => {
-                let mut player = self.player.borrow_mut();
                 match self.walking_state {
                     WalkingState::Standing => {
-                        player.set_walking(false);
+                        self.player.borrow_mut().set_walking(false);
                     }
                     WalkingState::Left => {
-                        player.x -= dt * PLAYER_MOVEMENT_SPEED;
-                        if player.x <= 0f32 {
-                            player.x = 0f32;
+                        self.player.borrow_mut().x -= dt * PLAYER_MOVEMENT_SPEED;
+                        if self.player.borrow().x <= 0f32 {
+                            self.player.borrow_mut().x = 0f32;
                             self.walking_state = WalkingState::Standing;
-                            player.set_walking(false);
+                            self.player.borrow_mut().set_walking(false);
+                            self.check_exit_left();
                         } else {
-                            player.set_walking(true);
-                            player.set_xflip(true);
+                            self.player.borrow_mut().set_walking(true);
+                            self.player.borrow_mut().set_xflip(true);
                         }
                     }
                     WalkingState::Right => {
-                        player.x += dt * PLAYER_MOVEMENT_SPEED;
-                        if player.x + 64f32 >= 800f32 {
-                            player.x = 800f32 - 64f32;
+                        self.player.borrow_mut().x += dt * PLAYER_MOVEMENT_SPEED;
+                        if self.player.borrow().x + 64f32 >= 800f32 {
+                            self.player.borrow_mut().x = 800f32 - 64f32;
                             self.walking_state = WalkingState::Standing;
-                            player.set_walking(false);
+                            self.player.borrow_mut().set_walking(false);
+                            self.check_exit_right();
                         } else {
-                            player.set_walking(true);
-                            player.set_xflip(false);
+                            self.player.borrow_mut().set_walking(true);
+                            self.player.borrow_mut().set_xflip(false);
                         }
                     }
                 }
+                match self.room {
+                    Room::StasisPod => (),
+                    Room::LeftOfPod => (),
+                }
             }
         }
         self.player.borrow_mut().update(ctx)?;
@@ -229,6 +340,13 @@ impl EventHandler for MainScene {
                             DrawParam::new().dest([600f32, 170f32]).rotation(0.7f32),
                         )?;
                     }
+                    Room::LeftOfPod => {}
+                }
+                for door in &self.doors {
+                    door.draw(ctx, &self.door_image)?;
+                }
+                for interactable in &self.interactables {
+                    interactable.draw(ctx)?;
                 }
                 self.player.borrow_mut().draw(ctx)?;
             }
@@ -250,7 +368,56 @@ impl EventHandler for MainScene {
                 )?;
             }
             State::GetOutOfPod => (),
-            State::Investigate => (),
+            State::Investigate => {
+                match self.room {
+                    Room::StasisPod => {
+                        graphics::draw(
+                            ctx,
+                            &self.current_text,
+                            DrawParam::new()
+                                .dest([100f32, 100f32])
+                                .color(graphics::WHITE),
+                        )?;
+                    }
+                    Room::LeftOfPod => {
+                        for interactable in &self.interactables {
+                            if interactable.is_within_range(
+                                self.player.borrow().x + 32f32,
+                                self.player.borrow().y + 64f32,
+                            ) {
+                                let text_offset = (self.interact_text.width(ctx) / 2) as f32;
+                                graphics::draw(
+                                    ctx,
+                                    &self.interact_text,
+                                    DrawParam::new().dest([
+                                        interactable.get_x() - text_offset,
+                                        interactable.get_y() - 50f32,
+                                    ]),
+                                )?;
+                            }
+                        }
+                        for door in &self.doors {
+                            if door.is_within_range(
+                                self.player.borrow().x + 32f32,
+                                self.player.borrow().y + 64f32,
+                            ) && door.get_open()
+                            {
+                                let text_offset = (self.door_text.width(ctx) / 2) as f32;
+                                graphics::draw(
+                                    ctx,
+                                    &self.door_text,
+                                    DrawParam::new().dest([
+                                        door.get_center_x() - text_offset,
+                                        door.get_y() - 15f32,
+                                    ]),
+                                )?;
+                            }
+                        }
+                    }
+                }
+
+                self.draw_room_arrows(ctx)?;
+            }
         }
 
         Ok(())
@@ -270,10 +437,22 @@ impl EventHandler for MainScene {
             State::GetOutOfPod => (),
             State::Investigate => {
                 if button == MouseButton::Left {
-                    let player = self.player.borrow();
-                    if player.x > x {
+                    let mut itype: Option<InteractableType> = None;
+                    for interactable in &self.interactables {
+                        if interactable.is_within_range(
+                            self.player.borrow().x + 32f32,
+                            self.player.borrow().y + 64f32,
+                        ) && interactable.is_within_range(x, y)
+                        {
+                            itype = Some(interactable.get_type());
+                            break;
+                        }
+                    }
+                    if let Some(it) = itype {
+                        self.use_interactable(it);
+                    } else if self.player.borrow().x > x {
                         self.walking_state = WalkingState::Left;
-                    } else if player.x + 64f32 < x {
+                    } else if self.player.borrow().x + 64f32 < x {
                         self.walking_state = WalkingState::Right;
                     }
                 }
@@ -322,6 +501,20 @@ impl EventHandler for MainScene {
                     if self.player.borrow().x + 64f32 < 800f32 {
                         self.walking_state = WalkingState::Right;
                     }
+                } else if keycode == KeyCode::E {
+                    let mut itype: Option<InteractableType> = None;
+                    for interactable in &self.interactables {
+                        if interactable.is_within_range(
+                            self.player.borrow().x + 32f32,
+                            self.player.borrow().y + 64f32,
+                        ) {
+                            itype = Some(interactable.get_type());
+                            break;
+                        }
+                    }
+                    if let Some(it) = itype {
+                        self.use_interactable(it);
+                    }
                 }
             }
         }