Skip to main content

Tile Movement System

Hyperscape uses a discrete tile-based movement system inspired by RuneScape. The world is divided into tiles, and entities move one tile at a time in sync with server ticks.
The tile system lives in packages/shared/src/systems/shared/movement/TileSystem.ts.

Core Constants

Hyperscape uses 2x OSRS speed for a snappier modern feel while keeping the tick-based system. OSRS uses 1 tile/tick walk, 2 tiles/tick run.

Tile Coordinates

Tiles use integer coordinates on the X-Z plane. Height (Y) comes from terrain.

World ↔ Tile Conversion


Movement State

Each entity with movement has a TileMovementState:

Previous Tile (OSRS Follow Mechanic)


Distance Functions

Manhattan Distance

Used for simple distance checks:

Chebyshev Distance

The actual “tile distance” for diagonal movement:

Adjacency Functions

8-Direction Adjacency

Cardinal-Only Adjacency


Performance Improvements (February 2026)

Immediate Move Processing

Bypasses ActionQueue for instant response to player clicks (eliminates 0-600ms latency)

Pathfinding Rate Limit

Raised from 5/sec to 15/sec to match tile movement limiter

BFS Iterations

Increased from 2000 to 8000 (~44 tile radius vs ~22 tile)

Path Continuation

Seamless long-distance movement with automatic re-pathfinding when BFS limit reached
Skating Fix: Server-side pre-computation + client-side path appending eliminates stop-lurch at segment boundaries Multi-Click Feel: Optimistic target pivoting + pending move queue ensures last click always reaches server Per-Frame Allocation Elimination: Pre-allocated buffers and squared distance comparisons in hot paths

Path Continuation for Long-Distance Movement

When a click exceeds the BFS iteration limit (~44 tiles), the system automatically continues pathfinding. New fields added to TileMovementState:
How It Works:
1

Initial Click

Player clicks far destination (60 tiles away). BFS runs for 8000 iterations, finds partial path to tile 44. Sets requestedDestination = (60, 60) and lastPathPartial = true
2

Path Continuation

When player reaches end of partial path, system automatically re-pathfinds from tile 44 toward original destination (60, 60). Finds next segment (tiles 44-88 or until destination). Continues until destination reached or unreachable.
3

Seamless Movement

Client receives isContinuation: true flag and appends new path without resetting interpolator. No stop-lurch at segment boundaries.
Server-Side Pre-Computation: Sends next segment 1 tick early to eliminate RTT/2 idle gap at segment boundaries. Client-Side Path Appending: Appends new path segments without resetting interpolator for continuous movement.

Pathfinding

BFS Pathfinder (OSRS “Smartpathing”)

Breaking Change (PR #886): Player movement now uses BFS as the primary pathfinder instead of naive diagonal-first. This is a significant change that affects all player movement and combat positioning.
Hyperscape uses BFS (Breadth-First Search) as the primary pathfinding algorithm for all player movement, matching OSRS “smartpathing”:
OSRS Accuracy: Player movement uses BFS (“smartpathing”) which finds optimal paths around obstacles. NPC chase movement uses naive diagonal pathing, which enables safespotting mechanics.

Multi-Destination BFS for Combat

Combat movement uses findPathToAny() to find the shortest path to any valid attack tile:
Benefits:
  • Naturally selects the closest reachable attack position
  • No need to pre-pick a “best” tile then pathfind to it
  • Terminates as soon as any valid tile is reached
  • Handles obstacles and blocked tiles automatically
Example:

Line of Sight for Ranged/Magic

Ranged and magic attacks now require line of sight to prevent attacking through walls:
Collision Mask:
Usage in Combat:
Breaking Change: Ranged and magic attacks now require line of sight. You cannot attack through walls even if the target is within Chebyshev range.

Valid Combat Tile Generation

The tile system provides helpers to generate all valid attack positions:
Example: Ranged Combat Positioning
Example: Melee Combat Positioning

Combat Positioning

Melee Range

OSRS Accuracy: Standard melee (range 1) requires cardinal adjacency only. You cannot attack diagonally without a halberd (range 2).

Combat Movement Algorithm

Combat movement now uses multi-destination BFS instead of pre-selecting a single “best” tile:
Advantages:
  • Optimal pathing: Always finds the shortest path to a valid attack position
  • Obstacle handling: Automatically routes around walls and blocked tiles
  • Natural selection: Closest reachable tile is chosen without heuristics
  • Line of sight: Ranged/magic tiles pre-filtered for LoS before pathfinding

Naive Diagonal Pathing (NPCs Only)

NPC chase movement uses naive diagonal pathing to enable safespotting:
Safespotting: The naive diagonal pathing used by NPCs allows players to position themselves where mobs cannot reach them, matching OSRS mechanics. Players use BFS which finds optimal paths, while mobs use naive pathing which can be exploited.

NPC Step-Out

When an NPC is on the same tile as its target, it must step out before attacking.

Resource Interaction

Multi-Tile Resources

Large resources (like trees) span multiple tiles. Players can interact from any adjacent tile.

Cardinal-Only Interaction

For consistent face direction during resource gathering:

Collision System

Hyperscape uses a unified CollisionMatrix for OSRS-accurate tile-based collision. The system handles static objects (trees, rocks, stations), entities (players, NPCs), and terrain (water, slopes).

CollisionMatrix Architecture

The collision system uses zone-based storage for optimal memory and performance:
Zone-Based Storage:
  • World divided into 8×8 tile zones
  • Each zone = Int32Array[64] = 256 bytes
  • 1000×1000 tile world = ~4MB memory
  • Lazy allocation (zones created on first write)

Collision Flags

Tiles use bitmask flags for efficient collision queries:

Usage Examples

Multi-Tile Footprints

Stations and large resources can occupy multiple tiles:
Footprints are centered on the entity position, not corner-based. A 2×2 station at (10,10) occupies tiles (9,9) through (10,10).

Entity Occupancy

The EntityOccupancyMap tracks which tiles are occupied by entities and delegates to CollisionMatrix for unified storage:
Entity moves are atomic - old tiles are freed and new tiles occupied in a single operation. Delta optimization ensures only changed tiles are updated.

Zero-Allocation Helpers

For performance in hot paths, use pre-allocated buffers:

Context Menu Integration

Walk Here

Players can right-click terrain to open a context menu with “Walk here”:
Context Menu Types: The system distinguishes between entity types and special cases:
The “Walk here” option only appears when right-clicking terrain. Entity interactions show entity-specific actions instead.

Client Interpolation

The client smoothly interpolates entity positions between server ticks.