diff --git a/assets/ewpratten/prp_cupIcon/prp_cupIcon.xcf b/assets/ewpratten/prp_cupIcon/prp_cupIcon.xcf
new file mode 100644
index 00000000..e8225560
Binary files /dev/null and b/assets/ewpratten/prp_cupIcon/prp_cupIcon.xcf differ
diff --git a/game/dist/assets/prp/prp_cupIcon/prp_cupIcon.png b/game/dist/assets/prp/prp_cupIcon/prp_cupIcon.png
new file mode 100644
index 00000000..fe5a3911
Binary files /dev/null and b/game/dist/assets/prp/prp_cupIcon/prp_cupIcon.png differ
diff --git a/game/game_logic/src/rendering/utilities/map_render.rs b/game/game_logic/src/rendering/utilities/map_render.rs
index b552a889..93708e60 100644
--- a/game/game_logic/src/rendering/utilities/map_render.rs
+++ b/game/game_logic/src/rendering/utilities/map_render.rs
@@ -80,6 +80,7 @@ pub struct MapRenderer {
     tile_textures: HashMap<PathBuf, Texture2D>,
     world_objects: WorldObjectPackage,
     world_end: na::Vector2<i32>,
+    cup_icon: Texture2D,
 }
 
 impl MapRenderer {
@@ -101,6 +102,14 @@ impl MapRenderer {
         let mut loader = Loader::with_cache(ProgramDataTileCache::new());
         let map = loader.load_tmx_map_from(data.as_slice(), tmx_path)?;
 
+        // Load the cup icon
+        let cup_icon = load_texture_from_internal_data(
+            raylib,
+            raylib_thread,
+            "assets/prp/prp_cupIcon/prp_cupIcon.png",
+        )
+        .unwrap();
+
         // Iterate over all images in the map
         let mut tile_textures = HashMap::new();
         for tileset in map.tilesets() {
@@ -132,6 +141,7 @@ impl MapRenderer {
             tile_textures,
             world_objects,
             world_end,
+            cup_icon,
         })
     }
 
@@ -490,79 +500,99 @@ impl MapRenderer {
         // Convert the position to a tile position
         let tile_x = (position.x / 128.0).floor() as i32;
         let tile_y = ((position.y * -1.0) / 128.0).floor() as i32;
-        debug!("Tile x: {}, y: {}", tile_x, tile_y);
+        // debug!("Tile x: {}, y: {}", tile_x, tile_y);
 
         // Check if the tile is inside the win zone
         tile_x == self.world_end.x && tile_y == self.world_end.y
     }
 
-    // /// Used to modify the player's velocity based on the effects of the world
-    // pub fn effect_velocity_with_collisions(
-    //     &self,
-    //     player_position: na::Vector2<f32>,
-    //     player_velocity: na::Vector2<f32>,
-    // ) -> na::Vector2<f32> {
-    //     // If the player is not moving, we don't need to do anything
-    //     if player_velocity.norm() == 0.0 {
-    //         return player_velocity;
-    //     }
+    pub fn get_screenspace_vector_to_win_zone(
+        &self,
+        draw: &mut RaylibDrawHandle,
+        screen_center: na::Vector2<f32>,
+        camera: &Camera2D,
+    ) -> na::Vector2<f32> {
+        let win_zone_position_world_space = Vector2::new(
+            self.world_end.x as f32 * 128.0,
+            (self.world_end.y as f32 * -1.0) * 128.0,
+        );
+        let win_zone_position_screenspace =
+            draw.get_world_to_screen2D(win_zone_position_world_space, camera);
+        na::Vector2::new(
+            win_zone_position_screenspace.x - screen_center.x,
+            win_zone_position_screenspace.y - screen_center.y,
+        )
+    }
 
-    //     // Get the velocity unit vector
-    //     let player_velocity_unit_vector = player_velocity.normalize();
+    pub fn render_hud_endgoal_arrow(
+        &self,
+        draw: &mut RaylibDrawHandle,
+        player_position: na::Vector2<f32>,
+        camera: &Camera2D,
+    ) {
+        // Get the center of the screen
+        let screen_center = na::Vector2::new(
+            draw.get_screen_width() as f32 / 2.0,
+            draw.get_screen_height() as f32 / 2.0,
+        );
 
-    //     // Find the position 1 pixel infront of the player
-    //     let player_position_1_pixel_infront = player_position + player_velocity_unit_vector;
-    //     let next_player_position = player_position + player_velocity;
+        // Get the vector to the win zone
+        let vector_to_win_zone =
+            self.get_screenspace_vector_to_win_zone(draw, screen_center, camera);
+        let unit_vector_to_win_zone = vector_to_win_zone.normalize();
 
-    //     // Check if this is in the collision zone of any objects
-    //     for obj_ref in &self.world_objects.object_references {
-    //         // Filter out anything more than 1000 pixels away
-    //         if (obj_ref.position - player_position).norm() > 1000.0 {
-    //             continue;
-    //         }
+        // Get the screenspace position of the win zone
+        let win_zone_position_screenspace = draw.get_world_to_screen2D(
+            Vector2::new(
+                self.world_end.x as f32 * 128.0,
+                (self.world_end.y as f32 * -1.0) * 128.0,
+            ),
+            camera,
+        );
 
-    //         // Get the object definition
-    //         let object_key =  obj_ref.into_key();
-    //         let obj_def = self
-    //             .world_objects
-    //             .object_definitions
-    //             .get(&object_key)
-    //             .unwrap();
+        // If the win zone is inside the camera's view, don't render the arrow
+        if !(win_zone_position_screenspace.x < 0.0
+            || win_zone_position_screenspace.x > draw.get_screen_width() as f32
+            || win_zone_position_screenspace.y < 0.0
+            || win_zone_position_screenspace.y > draw.get_screen_height() as f32)
+        {
+            return;
+        }
 
-    //         // Check if the player is about to be in a collision zone
-    //         for collider in &obj_def.physics_colliders {
-    //             // Handle a radius collider vs a size collider
-    //             if let Some(radius) = collider.radius {
-    //                 // Check if we are about to collide with the circle
-    //                 if (next_player_position - obj_ref.position).norm() < radius {
-    //                     // Get the angle from the player to the center of the collider
-    //                     let angle_to_center =
-    //                         (obj_ref.position - player_position).angle(&na::Vector2::new(0.0, 0.0));
-    //                     if angle_to_center.abs() <= std::f32::consts::FRAC_PI_2 {
-    //                         // Apply the inverse of the velocity to the player
-    //                         return na::Vector2::zeros();
-    //                     }
-    //                 }
-    //             } else if let Some(size) = collider.size {
-    //                 // TODO: make this work for regular and rotated objects
-    //             }
-    //         }
-    //     }
+        // // Draw the line
+        // draw.draw_line(
+        //     screen_center.x as i32,
+        //     screen_center.y as i32,
+        //     (win_zone_position_screenspace.x + unit_vector_to_win_zone.x * 32.0) as i32,
+        //     (win_zone_position_screenspace.y + unit_vector_to_win_zone.y * 32.0) as i32,
+        //     Color::RED,
+        // );
 
-    //     // Check if the player is about to leave the map
-    //     let mut player_velocity = player_velocity;
-    //     if next_player_position.x < 0.0 {
-    //         player_velocity.x = 0.0;
-    //     } else if next_player_position.x > self.map.width as f32 * 128.0 {
-    //         player_velocity.x = 0.0;
-    //     }
-    //     if next_player_position.y > 0.0 {
-    //         player_velocity.y = 0.0;
-    //     } else if next_player_position.y < self.map.height as f32 * -128.0 {
-    //         player_velocity.y = 0.0;
-    //     }
+        // // Define the screen rect
+        // let screen_rect = Rectangle {
+        //     x: 0.0,
+        //     y: 0.0,
+        //     width: draw.get_screen_width() as f32,
+        //     height: draw.get_screen_height() as f32,
+        // };
 
-    //     // If we got here, the player is not in a collision zone
-    //     player_velocity
-    // }
+        // Find the intersection of the line and the screen edge
+        let intersect = unit_vector_to_win_zone * (draw.get_screen_height() as f32 / 2.0);
+
+        // Render the cup icon
+        draw.draw_texture(
+            &self.cup_icon,
+            (screen_center.x + intersect.x) as i32 - self.cup_icon.width as i32 / 2,
+            (screen_center.y + intersect.y) as i32 - self.cup_icon.height as i32 / 2,
+            Color::WHITE,
+        );
+
+        // Render a circle where the line meets the screen edge
+        draw.draw_circle_lines(
+            (screen_center.x + intersect.x) as i32,
+            (screen_center.y + intersect.y) as i32,
+            16.0,
+            Color::BLACK,
+        );
+    }
 }
diff --git a/game/game_logic/src/scenes/player_interaction.rs b/game/game_logic/src/scenes/player_interaction.rs
index 41374b14..29188e87 100644
--- a/game/game_logic/src/scenes/player_interaction.rs
+++ b/game/game_logic/src/scenes/player_interaction.rs
@@ -212,14 +212,18 @@ impl PlayableScene {
             );
         }
 
-        draw.draw_rectangle(draw.get_screen_width() / 2 - 225, 0, 450, 40, Color::WHITE);
-        draw.draw_text(
-            "Unregistered HyperCam 2",
-            draw.get_screen_width() / 2 - 215,
-            0,
-            32,
-            Color::BLACK,
-        );
+        // Draw the hint arrow
+        self.world_map
+            .render_hud_endgoal_arrow(draw, self.player.position, &self.camera);
+
+        // draw.draw_rectangle(draw.get_screen_width() / 2 - 225, 0, 450, 40, Color::WHITE);
+        // draw.draw_text(
+        //     "Unregistered HyperCam 2",
+        //     draw.get_screen_width() / 2 - 215,
+        //     0,
+        //     32,
+        //     Color::BLACK,
+        // );
     }
 
     // Physics