Skip to content

YoYoGames/pfb-MiniMap

Repository files navigation

UI Minimap System

Table of Contents


Please Note

Minimap has been created to be contained within a UI Layer. If the Minimap is not within a UI Layer, the code will remove the Minimap and show_message() that the Minimap is not within a UI Layer.

Minimap has been created on the assumption that there will only be a single Minimap within the room.

Minimap only supports Tile layer and Asset layers being used in the Minimap variable definition minimap_layers

Introduction

The Minimap Prefab is a flexible, zoom-capable minimap that will display, in real-time, specified tile and asset layers within the minimap UI Layer, as well as individual object types with an associated sprite representation.
It uses a FlexPanel to control the size and position of the minimap, supports dynamic zoom levels, tracks objects with custom markers, and efficiently renders large rooms using surface-based sprite caching to limit the frequency of map regeneration.

Key Features

  • Dynamic zoom with configurable min/max bounds
  • Focus tracking (centers on a specified object like the player)
  • Object marker system with customizable scaling behavior
  • Handles rooms exceeding surface size limits
  • Aspect ratio preservation
  • Window resize support

Objects

objMinimap

The main controller object that manages the minimap display, zoom behavior, and object marker rendering.
Within the create event, if objMinimap is not contained within a UI Layer, it will remove itself.

Variable Definitions

  • minimap_layers: Comma-separated string of layer names to render
    • Default: A Tile Layer and as Asset Layer
    • Only supports the use of Tile layers and Asset layers; all others will be ignored
  • focusObject: Object to center the minimap on
    • Default: objPlayer
  • zoomPercent: Percentage that the zoom_level value should change by (used for objMinus and objPlus)
    • Default: 10
  • minZoom: Minimum allowed zoom level
    • Default: 0.25 (Show an area no more than 4x the size of the window)
  • maxZoom: Maximum allowed zoom level
    • Default: 1 (Show an an area no less than the size of the window)

Other Object Variables

  • flex_panel: Reference to the FlexPanel node containing the minimap display area
  • trackedObjects: Array of structs defining which objects to track on the minimap
    • Each entry: { object: object_index, marker: sprite_index, baseScale: real, changeWithZoom: bool }
    • Default: None
  • zoom_level: Current zoom level (1 = window size, 2 = 200% zoom in, 0.5 = 50% zoom out)
    • Default: 1
  • map: Reference to the objSurface instance that handles sprite generation
  • minimap_width: Calculated width of the minimap display area (stored for objSurface to access)
  • minimap_height: Calculated height of the minimap display area (stored for objSurface to access)
    • Default: objPlayer

Functions

find_containing_flexpanel(_node, _instance_id)

Recursively searches the flexpanel node hierarchy to find the node that contains the specified instance.

Parameters:

  • _node (FlexPanelNode): The flexpanel node to search within
  • _instance_id (instance ID): The instance ID to search for

Returns: The flexpanel node containing the instance, or undefined if not found

addTrackedObject(_object, _marker, _defaultScale, _changeWithZoom)

Adds an object type to track on the minimap with a custom marker sprite.

Parameters:

  • _object (object index): The object type to track (e.g., objEnemy)
  • _marker (sprite index): The sprite to display as the marker
  • _defaultScale (real): Base scale multiplier for the marker sprite (combined with 0.1 base multiplier)
  • _changeWithZoom (bool): Whether the marker should scale with zoom level (true) or remain constant size (false)

Example:

// Track all enemies with a red dot marker
// using a sprite at a scale of 1 (0.1 with base multiplier)
// shown at this scale regardless of the zoom_level
objMinimap.addTrackedObject(objEnemy, sprMarkerRed, 1, false);

// Track collectibles with a star marker
// using a sprite at a scale of 1.5 (0.15 with base multiplier)
// scaling accordingly when the map is zoomed in/out
objMinimap.addTrackedObject(objCollectable, sprMarkerStar, 1.5, true);

removeTrackedObject(_object)

Removes all tracking entries for the specified object type from the minimap. Safe to call even if the object type is not currently being tracked.

Parameters:

  • _object (object index): The object type to stop tracking (e.g., objEnemy)

Example:

// Stop tracking enemies (e.g. when all enemies are defeated)
if (instance_exists(objMinimap)) {
    objMinimap.removeTrackedObject(objEnemy);
}

Events

Create Event

Initializes the minimap system:

  • Sets initial GUI size to match window dimensions
  • Validates that the object is on a UI layer
  • Initializes trackedObjects array to empty
  • Sets default zoom_level to 1
  • Creates the objSurface instance for sprite generation

Step Begin Event

Updates GUI size when the window is resized, ensuring the FlexPanel layout recalculates correctly.

Draw Event

Main rendering logic with detailed inline comments explaining coordinate transformations:

  1. Gets FlexPanel layout dimensions - Retrieves the calculated position and size of the minimap panel
  2. Calculates view area - Determines what portion of the room should be visible based on zoom level and window size
  3. Enforces minimum zoom - Prevents zooming out beyond the room boundaries
  4. Centers on focus object - If focusObject exists, centers the view on the first instance
  5. Clamps view to room bounds - Ensures the view doesn't go outside the room
  6. Maintains aspect ratio - Calculates minimap dimensions to fit the panel while preserving aspect ratio
  7. Stores minimap dimensions - Saves minimap_width and minimap_height as instance variables for objSurface to access
  8. Manages sprite regeneration - Checks if the sprite needs regenerating for any of the following reasons:
    • Sprite doesn't exist
    • Zoom level changed
    • View moved outside the cached sprite area (with margin buffer)
  9. Draws the minimap sprite - Uses scissor rectangles to clip the sprite to the panel bounds (includes detailed scale and position calculation comments)
  10. Draws object markers - Loops through trackedObjects and draws markers for visible instances at their corresponding minimap positions (with coordinate transformation explanation)

objSurface

Helper object that handles surface-based sprite generation and caching for the minimap. This object is created by objMinimap and should not be placed directly in rooms.

Object Variables

  • current_zoom: Stored zoom level used for the current sprite
  • map_sprite: The cached sprite containing the rendered map
  • sprite_view_x, sprite_view_y: Room coordinates where the cached sprite starts
  • sprite_view_width, sprite_view_height: Room dimensions covered by the cached sprite
  • parentObject: Reference to the objMinimap instance (set during creation)
  • minimap_layers: Comma-separated layer names to render (passed from parent)

Functions

regenerate_sprite(_view_x, _view_y, _view_width, _view_height)

Regenerates the minimap sprite for a specific view area at the current zoom level. Creates a sprite from the specified layers and stores it in map_sprite. Uses tiled rendering for large areas to prevent exceeding surface size limits.

Parameters:

  • _view_x, _view_y (real): Top-left corner of the render area in room coordinates (includes margin)
  • _view_width, _view_height (real): Size of the render area (includes margin)

Note: Zoom level and panel dimensions are accessed from the parent objMinimap instance via parentObject.zoom_level, parentObject.minimap_width, and parentObject.minimap_height.

How it works:

  1. Gets parent data - Retrieves zoom level and panel dimensions from the parent objMinimap instance
  2. Frees old sprite - Deletes the previous sprite if it exists to prevent memory leaks
  3. Stores view area - Saves the view coordinates and dimensions for later reference
  4. Calculates surface size - Creates a surface based on panel dimensions with a 2x multiplier for margins (includes detailed comments on why fixed surface size is used)
  5. Calculates scale factors - Determines how much to scale room content to fit the surface
  6. Parses layer names - Splits the comma-separated minimap_layers string
  7. Determines rendering method:
    • Tiled rendering: If view area exceeds 10,000 pixels in either dimension (includes comments on tile index calculations)
      • Divides the room into tiles of MAX_SURFACE_SIZE
      • Renders each tile at 1:1 scale to a temporary surface
      • Tiles are then scaled and positioned on the final surface (with coordinate transformation comments)
    • Direct rendering: For smaller areas, renders the entire view to a temporary surface at 1:1 scale, then scales it to the final surface
  8. Renders layers - Calls render_layers() to draw tilemaps and sprite elements
  9. Creates sprite from surface - Converts the final surface to a sprite and stores it in map_sprite
  10. Frees surfaces - Cleans up all surfaces to prevent memory leaks

render_layers(_layer_names, _offset_x, _offset_y, _bound_width, _bound_height)

Helper function that renders tilemaps and sprite elements from the specified layers to the current surface target.

Parameters:

  • _layer_names (array of strings): Array of layer name strings to render
  • _offset_x, _offset_y (real): Offset to apply when rendering (for positioning tiles)
  • _bound_width, _bound_height (real): Boundaries for culling sprites outside the visible area

Note: This function renders to the current surface target, so surface_set_target() must be called before using this function.

Events

Create Event

Initializes sprite tracking variables and defines the regenerate_sprite() and render_layers() functions. The initial sprite is generated during the first Draw call from the parent objMinimap.


objPlus

Zoom-in button object.

Events

Left Mouse Pressed Event

When clicked, increases the minimap's zoom level:

  • Multiplies zoom_level by (100 + zoomPercent) / 100
  • Clamps the result between minZoom and maxZoom
  • The sprite regenerates automatically in the next draw event

Properties (set via UI layer creation code):

  • zoomPercent (real): Percentage to increase zoom (e.g., 10 for 10% increase per click)

objMinus

Zoom-out button object.

Events

Left Mouse Pressed Event

When clicked, decreases the minimap's zoom level:

  • Multiplies zoom_level by (100 - zoomPercent) / 100
  • Clamps the result between minZoom and maxZoom
  • The sprite regenerates automatically in the next draw event

Properties (set via UI layer creation code):

  • zoomPercent (real): Percentage to decrease zoom (e.g., 10 for 10% decrease per click)

objExampleUsage

Example object demonstrating how to programmatically add tracked objects to the minimap. This object is included in the MinimapRoom as a reference implementation.

Properties

  • minimapInstance: Reference to the objMinimap instance
    • Set via the room's instance creation code

Events

Create Event

Demonstrates adding multiple object types to be tracked on the minimap using the addTrackedObject() function:

Example Code:

// Adds `objItem` with `sprItemMinimap` marker at 4x base scale, scaling with zoom
minimapInstance.addTrackedObject(objItem, sprItemMinimap, 4, true);
// Adds `objPlayer` with `sprPlayerMinimap` marker at 3x base scale, not scaling with zoom
minimapInstance.addTrackedObject(objPlayer, sprPlayerMinimap, 3, false);

Example Usage

Basic Setup

  1. Add the UI layer to your room:

    • Include the minimap FlexPanel layout from the roomui
    • The layer should contain the "Minimap" FlexPanel with a child "Map" node
  2. Configure the UI layer's creation code:

// Set which layers should be rendered on the minimap
minimap_layers = "Tiles_Ground,Tiles_Walls,Instances";

// Set the object to focus on (usually the player)
focusObject = objPlayer;

// Set zoom limits
minZoom = 0.5;  // Can zoom out to 50% (see more of the room)
maxZoom = 3;    // Can zoom in to 300% (see less, more detail)

// Set zoom button behavior
zoomPercent = 10;  // 10% zoom change per click
  1. Track objects on the minimap (optional):
// In objMinimap's Create event or room creation code:
// Parameters: object, marker sprite, base scale, scale with zoom

// Enemy markers that don't scale with zoom
objMinimap.addTrackedObject(objEnemy, sprMarkerEnemy, 1, false);

// Collectible markers that scale with zoom at 1.2x size
objMinimap.addTrackedObject(objCollectable, sprMarkerCollectable, 1.2, true);

// Player marker at default size, no zoom scaling
objMinimap.addTrackedObject(objPlayer, sprMarkerPlayer, 1, false);

Advanced: Dynamic Marker Addition

// Add tracking for a new object type at runtime
if (instance_exists(objMinimap)) {
    with (objMinimap) {
        // Boss marker at 1.5x size that scales with zoom
        addTrackedObject(objBoss, sprMarkerBoss, 1.5, true);
    }
}

Controlling Zoom Programmatically

// Set zoom level directly
if (instance_exists(objMinimap)) {
    objMinimap.zoom_level = 2;  // 200% zoom
}

// Gradually adjust zoom
if (instance_exists(objMinimap)) {
    objMinimap.zoom_level = lerp(objMinimap.zoom_level, target_zoom, 0.1);
}

Technical Details

Performance Optimization

  • Margin-based regeneration: The sprite is rendered with a 50% margin on each side, reducing regeneration frequency as the view moves
  • Fixed surface size: Surface size is based on panel dimensions (with margin multiplier), not view area, preventing constant sprite recreation during zoom
  • Surface size capping: Surfaces are limited to 10,000 pixels per dimension to stay within hardware limits
  • Tiled rendering: Large rooms are automatically divided into tiles to prevent exceeding surface size limits
  • Sprite caching: The rendered map is stored as a sprite, avoiding surface recreation every frame
  • Culling: Sprite elements are only rendered if they're within the visible bounds

Zoom Behavior

  • zoom_level = 1: View shows an area equal to the window size
  • zoom_level = 2: View shows half the window area (200% zoom, more detail)
  • zoom_level = 0.5: View shows twice the window area (50% zoom, wider view)
  • Minimum zoom is automatically enforced to prevent showing more than the room boundaries

Marker Rendering

  • Markers use a base scale multiplier of 0.1 (to scale down room-sized sprites for minimap display)
  • This is combined with the baseScale parameter from addTrackedObject()
  • If changeWithZoom is true, markers also scale with the current zoom level
  • Final marker scale formula: 0.1 * baseScale * (changeWithZoom ? zoom_level : 1)
  • Only markers within the visible view area are drawn
  • Marker positions are calculated by mapping room coordinates to minimap screen coordinates (with detailed inline comments explaining the transformation)

Coordinate Transformations

The code includes comprehensive inline comments explaining all coordinate transformations:

  • Room coordinates to sprite pixels
  • Sprite pixels to screen pixels
  • Room coordinates to minimap screen position
  • Tile positioning in tiled rendering mode

These comments include step-by-step breakdowns to help understand the complex math involved.


Troubleshooting

Minimap appears blank:

  • Verify minimap_layers contains valid layer names
  • Ensure layers contain visible content (tilemaps or sprite elements)
  • Check that the FlexPanel node "Map" exists in the UI layer
  • Verify the minimap object is on a UI layer (the system will show an error if not)

Markers not appearing:

  • Confirm objects are within the visible view area
  • Verify marker sprites are assigned and valid
  • Ensure trackedObjects array contains the object types
  • Check that instances of the tracked objects exist in the room

Zoom buttons not working:

  • Check that minZoom, maxZoom, and zoomPercent are set in the UI layer creation code
  • Verify objMinimap instance exists in the room
  • Ensure the buttons are on the same UI layer as the minimap

Performance issues:

  • Reduce the number of layers in minimap_layers
  • Increase the margin factor to reduce regeneration frequency (modify regenMargin in objMinimap's Variable Definition'/Draw)
  • Optimize the room by removing unnecessary sprite elements from minimap layers
  • Consider using simpler tile layers instead of many sprite elements

Sprite appears stretched or incorrectly sized:

  • This can happen if margins hit room boundaries - this is expected behavior
  • The sprite scale will automatically adjust to compensate
  • Check inline comments in Draw_0.gml for detailed explanation of scale calculations

About

MiniMap Prefab

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors