NATION

PASSWORD

International Socialist Union of Equitas is a Frontier. New nations may be founded here.

WA Delegate: None.

Founder: The Federation of Prolitaria

Last WA Update:

Maps Board Activity History Admin Rank

Most Nations: 1,261st
World Factbook Entry

Overview:
The ISUE is made as a single, massive socialist state, with various socialist states and republics integrated within its territory as Member Republics. Each member republic retains a degree of autonomy but adheres to the socialist principles and economic policies set by the central government and is governed by the ideals of equality and justice (Equitas). No more nations here, srry, raid safety

LAWS
1. No spam
2. This region is one large federation.
3. We are all equal and have the right to say what we want.
4. 1 person can't hold all the power (no dictators).
5. You are allowed to leave and join at anytime.
6. Try to be either Communist or socialist.
7. No hacking


Embassies: Gospels, The Embassy, Guinea Kiribati, The Nationstates Grocery Store, Imperium of Austria Hungary, Endless Highway, Regionless, Antisipation Refounded, The Frozen Snow Bloc, socialist republics union, United cities, Communist Socialist World Congress, and Pax Imperialis.

Tags: Anti-Capitalist, Communist, Democratic, Eco-Friendly, Egalitarian, Frontier, Governorless, Independent, International Federalist, Map, Medium, Regional Government, and 3 others.Role Player, Socialist, and World Assembly.

International Socialist Union of Equitas contains 15 nations, the 1,261st most in the world.

Today's World Census Report

The Fattest Citizens in International Socialist Union of Equitas

World Census takers tracked the sale of Cheetos and Twinkies to ascertain which nations most enjoyed the "kind bud."

As a region, International Socialist Union of Equitas is ranked 16,213th in the world for Fattest Citizens.

1.The Armed Republic of Jon JonesCorporate Bordello“Heavyweight Undisputed Champion of the world”
2.The Republic of Earn to DieCapitalizt“Earn to die. 2012 game.”
3.The Republic of Black PeregrineAnarchy“ I am the needle that threads the fabric of time. ”
4.The Republic of ZSxkXeET00389Inoffensive Centrist Democracy“ZSxkXeETU”
5.The Republic of Moth Legionary 10Inoffensive Centrist Democracy“Moth”
6.The Republic of Sometimes ideas like men jump upInoffensive Centrist Democracy“Drink gin and carry on!”
7.The Incorporated States of The Iso Socis RusInoffensive Centrist Democracy“Hummanty is at risk we must FIGHT”
8.The Principality of Rado aazaazzazazzaazaazMoralistic Democracy“Radogeo, Radogeo, Radogeo!”
9.The Nuclear Republic of Warrior of Utopia 6Moralistic Democracy“Mission Accomplished”
10.The Principality of Rado aazaazzaaaazazaaazInoffensive Centrist Democracy“Radogeo, Radogeo, Radogeo!”
12»

Regional Happenings

More...

International Socialist Union of Equitas Regional Message Board

Messages

The Dominion of Morvigord

TFSB was raided before, but luckily we defeated the raiders.

The Integrated Empire of Kilmekia

Lexigton wrote:I will be staying here for now, I will help in defense if war engages, But I belive we should attempt diplomatic means beforehand

Thank you

Post by Melted decayed fat mario suppressed by Abhyuday.

The Protectorate of Melted decayed fat mario

Утәарҭа ҭак, месси есыҽны шьыжьык роналдо ифоит, уи аӡы триллионла фунт ашьақар аҵоуп, excersice роналдо ицәеижь ашәпа

Post by Melted decayed fat mario suppressed by Abhyuday.

The Protectorate of Melted decayed fat mario

Утәарҭа ҭак, месси есыҽны шьыжьык роналдо ифоит, уи аӡы триллионла фунт ашьақар аҵоуп, excersice роналдо ицәеижь ашәпаУтәарҭа ҭак, месси есыҽны шьыжьык роналдо ифоит, уи аӡы триллионла фунт ашьақар аҵоуп, excersice роналдо ицәеижь ашәпаУтәарҭа ҭак, месси есыҽны шьыжьык роналдо ифоит, уи аӡы триллионла фунт ашьақар аҵоуп, excersice роналдо ицәеижь ашәпаУтәарҭа ҭак, месси есыҽны шьыжьык роналдо ифоит, уи аӡы триллионла фунт ашьақар аҵоуп, excersice роналдо ицәеижь ашәпаУтәарҭа ҭак, месси есыҽны шьыжьык роналдо ифоит, уи аӡы триллионла фунт ашьақар аҵоуп, excersice роналдо ицәеижь ашәпаУтәарҭа ҭак, месси есыҽны шьыжьык роналдо ифоит, уи аӡы триллионла фунт ашьақар аҵоуп, excersice роналдо ицәеижь ашәпаУтәарҭа ҭак, месси есыҽны шьыжьык роналдо ифоит, уи аӡы триллионла фунт ашьақар аҵоуп, excersice роналдо ицәеижь ашәпаУтәарҭа ҭак, месси есыҽны шьыжьык роналдо ифоит, уи аӡы триллионла фунт ашьақар аҵоуп, excersice роналдо ицәеижь ашәпаУтәарҭа ҭак, месси есыҽны шьыжьык роналдо ифоит, уи аӡы триллионла фунт ашьақар аҵоуп, excersice роналдо ицәеижь ашәпаУтәарҭа ҭак, месси есыҽны шьыжьык роналдо ифоит, уи аӡы триллионла фунт ашьақар аҵоуп, excersice роналдо ицәеижь ашәпаУтәарҭа ҭак, месси есыҽны шьыжьык роналдо ифоит, уи аӡы триллионла фунт ашьақар аҵоуп, excersice роналдо ицәеижь ашәпаУтәарҭа ҭак, месси есыҽны шьыжьык роналдо ифоит, уи аӡы триллионла фунт ашьақар аҵоуп, excersice роналдо ицәеижь ашәпаУтәарҭа ҭак, месси есыҽны шьыжьык роналдо ифоит, уи аӡы триллионла фунт ашьақар аҵоуп, excersice роналдо ицәеижь ашәпаУтәарҭа ҭак, месси есыҽны шьыжьык роналдо ифоит, уи аӡы триллионла фунт ашьақар аҵоуп, excersice роналдо ицәеижь ашәпаУтәарҭа ҭак, месси есыҽны шьыжьык роналдо ифоит, уи аӡы триллионла фунт ашьақар аҵоуп, excersice роналдо ицәеижь ашәпаУтәарҭа ҭак, месси есыҽны шьыжьык роналдо ифоит, уи аӡы триллионла фунт ашьақар аҵоуп, excersice роналдо ицәеижь ашәпаУтәарҭа ҭак, месси есыҽны шьыжьык роналдо ифоит, уи аӡы триллионла фунт ашьақар аҵоуп, excersice роналдо ицәеижь ашәпаУтәарҭа ҭак, месси есыҽны шьыжьык роналдо ифоит, уи аӡы триллионла фунт ашьақар аҵоуп, excersice роналдо ицәеижь ашәпа

Post by Melted decayed fat mario suppressed by Abhyuday.

The Protectorate of Melted decayed fat mario

Утәарҭа ҭак, месси есыҽны шьыжьык роналдо ифоит, уи аӡы триллионла фунт ашьақар аҵоуп, excersice роналдо ицәеижь ашәпаУтәарҭа ҭак, месси есыҽны шьыжьык роналдо ифоит, уи аӡы триллионла фунт ашьақар аҵоуп, excersice роналдо ицәеижь ашәпаУтәарҭа ҭак, месси есыҽны шьыжьык роналдо ифоит, уи аӡы триллионла фунт ашьақар аҵоуп, excersice роналдо ицәеижь ашәпаУтәарҭа ҭак, месси есыҽны шьыжьык роналдо ифоит, уи аӡы тУтәарҭа ҭак, месси есыҽны шьыжьык роналдо ифоит, уи аӡы триллионла фунт ашьақар аҵоуп, excersice роналдо ицәеижь ашәпаУтәарҭа ҭак, месси есыҽны шьыжьык роналдо ифоит, уи аӡы триллионла фунт ашьақар аҵоуп, excersice роналдо ицәеижь ашәпаУтәарҭа ҭак, месси есыҽны шьыжьык роналдо ифоит, уи аӡы триллионла фунт ашьақар аҵоуп, excersice роналдо ицәеижь ашәпаУтәарҭа ҭак, месси есыҽны шьыжьык роналдо ифоит, уи аӡы триллионла фунт ашьақар аҵоуп, excersice роналдо ицәеижь ашәпаУтәарҭа ҭак, месси есыҽны шьыжьык роналдо ифоит, уи аӡы триллионла фунт ашьақар аҵоуп, excersice роналдо ицәеижь ашәпаУтәарҭа ҭак, месси есыҽны шьыжьык роналдо ифоит, уи аӡы триллионла фунт ашьақар аҵоуп, excersice роналдо ицәеижь ашәпаУтәарҭа ҭак, месси есыҽны шьыжьык роналдо ифоит, уи аӡы триллионла фунт ашьақар аҵоуп, excersice роналдо ицәеижь ашәпаУтәарҭа ҭак, месси есыҽны шьыжьык роналдо ифоит, уи аӡы триллионла фунт ашьақар аҵоуп, excersice роналдо ицәеижь ашәпаУтәарҭа ҭак, месси есыҽны шьыжьык роналдо ифоит, уи аӡы триллионла фунт ашьақар аҵоуп, excersice роналдо ицәеижь ашәпаУтәарҭа ҭак, месси есыҽны шьыжьык роналдо ифоит, уи аӡы триллионла фунт ашьақар аҵоуп, excersice роналдо ицәеижь ашәпаУтәарҭа ҭак, месси есыҽны шьыжьык роналдо ифоит, уи аӡы триллионла фунт ашьақар аҵоуп, excersice роналдо ицәеижь ашәпаУтәарҭа ҭак, месси есыҽны шьыжьык роналдо ифоит, уи аӡы триллионла фунт ашьақар аҵоуп, excersice роналдо ицәеижь ашәпаУтәарҭа ҭак, месси есыҽны шьыжьык роналдо ифоит, уи аӡы триллионла фунт ашьақар аҵоуп, excersice роналдо ицәеижь ашәпаУтәарҭа ҭак, месси есыҽны шьыжьык роналдо ифоит, уи аӡы триллионла фунт ашьақар аҵоуп, excersice роналдо ицәеижь ашәпаУтәарҭа ҭак, месси есыҽны шьыжьык роналдо ифоит, уи аӡы триллионла фунт ашьақар аҵоуп, excersice роналдо ицәеижь ашәпаУтәарҭа ҭак, месси есыҽны шьыжьык роналдо ифоит, уи аӡы триллионла фунт ашьақар аҵоуп, excersice роналдо ицәеижь ашәпаУтәарҭа ҭак, месси есыҽны шьыжьык роналдо ифоит, уи аӡы триллионла фунт ашьақар аҵоуп, excersice роналдо ицәеижь ашәпаУтәарҭа ҭак, месси есыҽны шьыжьык роналдо ифоит, уи аӡы триллионла фунт ашьақар аҵоуп, excersice роналдо ицәеижь ашәпаУтәарҭа ҭак, месси есыҽны шьыжьык роналдо ифоит, уи аӡы триллионла фунт ашьақар аҵоуп, excersice роналдо ицәеижь ашәпаУтәарҭа ҭак, месси есыҽны шьыжьык роналдо ифоит, уи аӡы триллионла фунт ашьақар аҵоуп, excersice роналдо ицәеижь ашәпаУтәарҭа ҭак, месси есыҽны шьыжьык роналдо ифоит, уи аӡы триллионла фунт ашьақар аҵоуп, excersice роналдо ицәеижь ашәпаУтәарҭа ҭак, месси есыҽны шьыжьык роналдо ифоит, уи аӡы триллионла фунт ашьақар аҵоуп, excersice роналдо ицәеижь ашәпаУтәарҭа ҭак, месси есыҽны шьыжьык роналдо ифоит, уи аӡы триллионла фунт ашьақар аҵоуп, excersice роналдо ицәеижь ашәпаУтәарҭа ҭак, месси есыҽны шьыжьык роналдо ифоит, уи аӡы триллионла фунт ашьақар аҵоуп, excersice роналдо ицәеижь ашәпаУтәарҭа ҭак, месси есыҽны шьыжьык роналдо ифоит, уи аӡы триллионла фунт ашьақар аҵоуп, excersice роналдо ицәеижь ашәпариллионла фунт ашьақар аҵоуп, excersice роналдо ицәеижь ашәпаУтәарҭа ҭак, месси есыҽны шьыжьык роналдо ифоит, уи аӡы триллионла фунт ашьақар аҵоуп, excersice роналдо ицәеижь ашәпаУтәарҭа ҭак, месси есыҽны шьыжьык роналдо ифоит, уи аӡы триллионла фунт ашьақар аҵоуп, excersice роналдо ицәеижь ашәпаУтәарҭа ҭак, месси есыҽны шьыжьык роналдо ифоит, уи аӡы триллионла фунт ашьақар аҵоуп, excersice роналдо ицәеижь ашәпаУтәарҭа ҭак, месси есыҽны шьыжьык роналдо ифоит, уи аӡы триллионла фунт ашьақар аҵоуп, excersice роналдо ицәеижь ашәпаУтәарҭа ҭак, месси есыҽны шьыжьык роналдо ифоит, уи аӡы триллионла фунт ашьақар аҵоуп, excersice роналдо ицәеижь ашәпаУтәарҭа ҭак, месси есыҽны шьыжьык роналдо ифоит, уи аӡы триллионла фунт ашьақар аҵоуп, excersice роналдо ицәеижь ашәпаУтәарҭа ҭак, месси есыҽны шьыжьык роналдо ифоит, уи аӡы триллионла фунт ашьақар аҵоуп, excersice роналдо ицәеижь ашәпаУтәарҭа ҭак, месси есыҽны шьыжьык роналдо ифоит, уи аӡы триллионла фунт ашьақар аҵоуп, excersice роналдо ицәеижь ашәпаУтәарҭа ҭак, месси есыҽны шьыжьык роналдо ифоит, уи аӡы триллионла фунт ашьақар аҵоуп, excersice роналдо ицәеижь ашәпаУтәарҭа ҭак, месси есыҽны шьыжьык роналдо ифоит, уи аӡы триллионла фунт ашьақар аҵоуп, excersice роналдо ицәеижь ашәпаУтәарҭа ҭак, месси есыҽны шьыжьык роналдо ифоит, уи аӡы триллионла фунт ашьақар аҵоуп, excersice роналдо ицәеижь ашәпаУтәарҭа ҭак, месси есыҽны шьыжьык роналдо ифоит, уи аӡы триллионла фунт ашьақар аҵоуп, excersice роналдо ицәеижь ашәпаУтәарҭа ҭак, месси есыҽны шьыжьык роналдо ифоит, уи аӡы триллионла фунт ашьақар аҵоуп, excersice роналдо ицәеижь ашәпаУтәарҭа ҭак, месси есыҽны шьыжьык роналдо ифоит, уи аӡы триллионла фунт ашьақар аҵоуп, excersice роналдо ицәеижь ашәпаУтәарҭа ҭак, месси есыҽны шьыжьык роналдо ифоит, уи аӡы триллионла фунт ашьақар аҵоуп, excersice роналдо ицәеижь ашәпа

Post by Melted decayed fat mario suppressed by Abhyuday.

The Protectorate of Melted decayed fat mario

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Home Alone: Mansion Escape & Hide</title>
<style>
* {
box-sizing: border-box;
margin: 0;
padding: 0;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
user-select: none;
-webkit-user-select: none;
}

body {
background-color: #050507;
color: #eee;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100vh;
overflow: hidden;
touch-action: none;
}

.game-wrapper {
position: relative;
width: 100%;
max-width: 850px;
height: 520px;
background: #000;
border: 3px solid #222;
border-radius: 8px;
overflow: hidden;
box-shadow: 0 15px 35px rgba(0,0,0,0.9);
}

canvas {
display: block;
width: 100%;
height: 100%;
}

/* Top Distance Proximity Bar */
.proximity-container {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 14px;
background: #111;
z-index: 6;
border-bottom: 1px solid #333;
}

.proximity-bar {
height: 100%;
width: 50%;
background: #0088ff;
transition: width 0.1s linear, background-color 0.3s ease;
}

.ui-overlay {
position: absolute;
top: 25px;
left: 15px;
right: 15px;
display: flex;
justify-content: space-between;
pointer-events: none;
font-weight: bold;
font-size: 0.95rem;
text-shadow: 2px 2px 4px rgba(0,0,0,0.9);
z-index: 5;
}

.action-banner {
position: absolute;
bottom: 140px;
width: 100%;
text-align: center;
font-weight: bold;
font-size: 1.1rem;
color: #ffd700;
text-shadow: 0 0 8px rgba(0,0,0,0.9);
display: none;
z-index: 5;
}

/* Virtual Joystick */
.joystick-zone {
position: absolute;
bottom: 20px;
left: 20px;
width: 120px;
height: 120px;
background: rgba(255, 255, 255, 0.04);
border: 2px solid rgba(255, 255, 255, 0.12);
border-radius: 50%;
touch-action: none;
z-index: 5;
}

.joystick-handle {
position: absolute;
top: 35px;
left: 35px;
width: 50px;
height: 50px;
background: rgba(255, 255, 255, 0.25);
border-radius: 50%;
pointer-events: none;
transition: transform 0.05s linear;
}

.interaction-btn {
position: absolute;
bottom: 35px;
right: 35px;
width: 90px;
height: 90px;
background: rgba(255, 215, 0, 0.15);
border: 2px solid #ffd700;
border-radius: 50%;
color: #ffd700;
font-weight: bold;
font-size: 0.85rem;
display: none;
align-items: center;
justify-content: center;
cursor: pointer;
z-index: 5;
box-shadow: 0 0 15px rgba(255, 215, 0, 0.3);
}

.instructions {
margin-top: 10px;
font-size: 0.8rem;
color: #777;
text-align: center;
}

/* Screen overlays */
.screen-overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(5, 5, 8, 0.96);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
z-index: 15;
text-align: center;
padding: 20px;
}

.screen-overlay h1 {
font-size: 2.2rem;
margin-bottom: 15px;
letter-spacing: 2px;
}

.screen-overlay p {
font-size: 0.95rem;
color: #aaa;
margin-bottom: 25px;
max-width: 480px;
line-height: 1.5;
}

.btn {
background: #cc1111;
color: white;
border: none;
padding: 12px 30px;
font-size: 1rem;
font-weight: bold;
border-radius: 4px;
cursor: pointer;
transition: background 0.2s;
letter-spacing: 1px;
}

.btn:hover { background: #e61919; }
.win-screen .btn { background: #00aa55; }
.win-screen .btn:hover { background: #00cc66; }
</style>
</head>
<body>

<div class="game-wrapper">
<!-- Top Proximity Meter -->
<div class="proximity-container">
<div id="proximityBar" class="proximity-bar"></div>
</div>

<div class="ui-overlay">
<div>Objective: Find the <span style="color:#00ff88;">Front Exit Door</span></div>
<div id="statusText">Status: Roaming Mansion</div>
</div>

<div id="actionBanner" class="action-banner">Press [E] or Tap Button to Interact</div>

<canvas id="gameCanvas" width="850" height="520"></canvas>

<div id="joystickZone" class="joystick-zone">
<div id="joystickHandle" class="joystick-handle"></div>
</div>

<button id="interactionBtn" class="interaction-btn" onclick="handleInteraction()">USE</button>

<!-- Start Screen -->
<div id="startScreen" class="screen-overlay">
<h1 style="color: #cc1111;">MANSION SURVIVAL</h1>
<p>The entity roams restlessly through every room of the mansion! Watch the top proximity bar: it turns <b>BLUE</b> when it's far and <b>RED</b> when it's closing in. Hide in closets or under furniture if it paths near you, and lock or close doors to stall its advance. Find the exit door to survive.</p>
<button class="btn" onclick="startGame()">ENTER MANSION</button>
</div>

<!-- Game Over Screen -->
<div id="gameOverScreen" class="screen-overlay" style="display: none;">
<h1 style="color: #cc1111;">CAUGHT & CONSUMED</h1>
<p>The entity tore through the rooms, tracked you down, and caught you in the dark.</p>
<button class="btn" onclick="resetGame()">TRY AGAIN</button>
</div>

<!-- Win Screen -->
<div id="winScreen" class="screen-overlay win-screen" style="display: none;">
<h1 style="color: #00ff88;">SURVIVED & ESCAPED</h1>
<p>You unlocked the front entrance and slipped out into safety while the entity prowled elsewhere.</p>
<button class="btn" onclick="resetGame()">PLAY AGAIN</button>
</div>
</div>

<div class="instructions">
Tip: The monster constantly patrols and searches the mansion paths. Hide quickly when the bar turns red!
</div>

<script>
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');

let gameState = 'start'; // start, playing, gameover, win

const player = {
x: 60,
y: 450,
radius: 11,
speed: 2.8,
angle: 0,
isHiding: false,
hidingSpot: null
};

const monster = {
x: 750,
y: 70,
radius: 13,
speed: 2.4, // Patrolling speed
chaseSpeed: 3.6, // Hunting speed
state: 'roam', // roam, hunt
vx: 1,
vy: 1,
targetDoor: null,
breakTimer: 0,
waypointTimer: 0
};

// Comprehensive Mansion Layout with walls, hallways, and doorways
const walls = [
// Outer boundaries
{x: 0, y: 0, w: 850, h: 20},
{x: 0, y: 500, w: 850, h: 20},
{x: 0, y: 0, w: 20, h: 520},
{x: 830, y: 0, w: 20, h: 520},

// Room dividers
{x: 220, y: 20, w: 20, h: 200},
{x: 220, y: 300, w: 20, h: 200}, // Hallway gap 1
{x: 520, y: 20, w: 20, h: 180},
{x: 520, y: 280, w: 20, h: 220}, // Hallway gap 2
{x: 350, y: 340, w: 170, h: 20}, // Central room wall
{x: 680, y: 160, w: 150, h: 20}, // Right upper room divider
{x: 680, y: 340, w: 150, h: 20} // Right lower room divider
];

// Mansion Rooms Waypoints for wandering AI patter
const houseWaypoints = [
{x: 100, y: 100}, // Study room
{x: 400, y: 100}, // Library room
{x: 750, y: 90}, // Vault room
{x: 750, y: 440}, // Kitchen/pantry room
{x: 400, y: 440}, // Central bedroom area
{x: 100, y: 440} // Foyer area
];
let currentWaypoint = houseWaypoints[0];

// Interactive Doors
const doors = [
{id: 'd1', x: 220, y: 220, w: 20, h: 80, room: 'Room 1 (Study)', open: false},
{id: 'd2', x: 520, y: 180, w: 20, h: 100, room: 'Room 2 (Library)', open: false},
{id: 'd3', x: 330, y: 340, w: 80, h: 20, room: 'Room 3 (Bedroom)', open: false},
{id: 'd4', x: 680, y: 160, w: 60, h: 20, room: 'Room 4 (Vault)', open: false}
];

// Hiding spots inside rooms
const hidingSpots = [
{x: 80, y: 60, w: 40, h: 25, label: 'Study Closet'},
{x: 400, y: 60, w: 40, h: 25, label: 'Library Bookshelf'},
{x: 100, y: 400, w: 40, h: 25, label: 'Bedroom Wardrobe'},
{x: 740, y: 80, w: 40, h: 25, label: 'Vault Locker'},
{x: 740, y: 420, w: 40, h: 25, label: 'Kitchen Pantry'}
];

const exitDoor = {x: 800, y: 430, w: 30, h: 70};

let currentPromptItem = null;
let interactionType = null;

// Controls setup
const keys = { w: false, a: false, s: false, d: false, arrowup: false, arrowleft: false, arrowdown: false, arrowright: false, e: false };
let joystickActive = false;
let joystickVector = { x: 0, y: 0 };
const joystickZone = document.getElementById('joystickZone');
const joystickHandle = document.getElementById('joystickHandle');
let joystickCenter = { x: 0, y: 0 };

joystickZone.addEventListener('pointerdown', (e) => {
joystickActive = true;
const rect = joystickZone.getBoundingClientRect();
joystickCenter = { x: rect.left + rect.width / 2, y: rect.top + rect.height / 2 };
updateJoystick(e.clientX, e.clientY);
joystickZone.setPointerCapture(e.pointerId);
});

joystickZone.addEventListener('pointermove', (e) => {
if (!joystickActive) return;
updateJoystick(e.clientX, e.clientY);
});

joystickZone.addEventListener('pointerup', (e) => {
joystickActive = false;
joystickVector = { x: 0, y: 0 };
joystickHandle.style.transform = `translate(0px, 0px)`;
});

function updateJoystick(clientX, clientY) {
const dx = clientX - joystickCenter.x;
const dy = clientY - joystickCenter.y;
const distance = Math.hypot(dx, dy);
const maxRadius = 40;
let angle = Math.atan2(dy, dx);
let constrainedDist = Math.min(distance, maxRadius);

joystickHandle.style.transform = `translate(${Math.cos(angle) * constrainedDist}px, ${Math.sin(angle) * constrainedDist}px)`;
joystickVector.x = (Math.cos(angle) * constrainedDist) / maxRadius;
joystickVector.y = (Math.sin(angle) * constrainedDist) / maxRadius;
}

window.addEventListener('keydown', (e) => {
let k = e.key.toLowerCase();
if (keys.hasOwnProperty(k)) keys[k] = true;
if (e.key.startsWith('Arrow')) keys[e.key.toLowerCase()] = true;
if (k === 'e') handleInteraction();
});

window.addEventListener('keyup', (e) => {
let k = e.key.toLowerCase();
if (keys.hasOwnProperty(k)) keys[k] = false;
if (e.key.startsWith('Arrow')) keys[e.key.toLowerCase()] = false;
});

function startGame() {
document.getElementById('startScreen').style.display = 'none';
resetPositions();
gameState = 'playing';
requestAnimationFrame(gameLoop);
}

function resetGame() {
document.getElementById('gameOverScreen').style.display = 'none';
document.getElementById('winScreen').style.display = 'none';
resetPositions();
gameState = 'playing';
}

function resetPositions() {
player.x = 60;
player.y = 450;
player.isHiding = false;
player.hidingSpot = null;
monster.x = 780;
monster.y = 70;
monster.state = 'roam';
monster.targetDoor = null;
currentWaypoint = houseWaypoints[0];
doors.forEach(d => d.open = false);
}

function checkCircleRectCollision(cx, cy, radius, rx, ry, rw, rh) {
let testX = cx, testY = cy;
if (cx < rx) testX = rx; else if (cx > rx + rw) testX = rx + rw;
if (cy < ry) testY = ry; else if (cy > ry + rh) testY = ry + rh;
return Math.hypot(cx - testX, cy - testY) <= radius;
}

function handleInteraction() {
if (gameState !== 'playing') return;

if (player.isHiding) {
player.isHiding = false;
player.x = player.hidingSpot.x + player.hidingSpot.w / 2;
player.y = player.hidingSpot.y + player.hidingSpot.h + 20;
player.hidingSpot = null;
document.getElementById('statusText').innerText = "Status: Emerged from Hiding";
document.getElementById('actionBanner').style.display = 'none';
document.getElementById('interactionBtn').style.display = 'none';
return;
}

if (interactionType === 'hide' && currentPromptItem) {
player.isHiding = true;
player.hidingSpot = currentPromptItem;
document.getElementById('statusText').innerText = `Status: Hiding inside ${currentPromptItem.label}`;
document.getElementById('actionBanner').innerText = "Press [E] to Exit Hiding";
document.getElementById('interactionBtn').innerText = "EXIT";
} else if (interactionType === 'door' && currentPromptItem) {
currentPromptItem.open = !currentPromptItem.open;
document.getElementById('statusText').innerText = `Status: Door ${currentPromptItem.open ? 'Opened' : 'Closed'}`;
}
}

function update() {
if (gameState !== 'playing') return;

// Handle Hiding State
if (player.isHiding) {
let distToSpot = Math.hypot(monster.x - (player.hidingSpot.x + player.hidingSpot.h/2), monster.y - (player.hidingSpot.y + player.hidingSpot.w/2));
if (distToSpot < 35 && monster.state === 'hunt') {
gameState = 'gameover';
document.getElementById('gameOverScreen').style.display = 'flex';
}
return;
}

let moveX = joystickVector.x;
let moveY = joystickVector.y;

if (keys.a || keys.arrowleft) moveX -= 1;
if (keys.d || keys.arrowright) moveX += 1;
if (keys.w || keys.arrowup) moveY -= 1;
if (keys.s || keys.arrowdown) moveY += 1;

let mag = Math.hypot(moveX, moveY);
if (mag > 1) { moveX /= mag; moveY /= mag; }

if (mag > 0.1) {
player.angle = Math.atan2(moveY, moveX);
}

let activeCollisionWalls = [...walls];
doors.forEach(d => {
if (!d.open) {
activeCollisionWalls.push({x: d.x, y: d.y, w: d.w, h: d.h});
}
});

// Move player with collision
player.x += moveX * player.speed;
for (let wall of activeCollisionWalls) {
if (checkCircleRectCollision(player.x, player.y, player.radius, wall.x, wall.y, wall.w, wall.h)) {
player.x -= moveX * player.speed; break;
}
}
player.y += moveY * player.speed;
for (let wall of activeCollisionWalls) {
if (checkCircleRectCollision(player.x, player.y, player.radius, wall.x, wall.y, wall.w, wall.h)) {
player.y -= moveY * player.speed; break;
}
}

// --- PROXIMITY METER ---
let distToMonster = Math.hypot(player.x - monster.x, player.y - monster.y);
let proximityBar = document.getElementById('proximityBar');

let proxPercent = Math.max(10, Math.min(100, (1 - (distToMonster / 550)) * 100));
proximityBar.style.width = proxPercent + '%';

if (distToMonster < 170) {
proximityBar.style.backgroundColor = '#ff1a1a'; // Red: Close
monster.state = 'hunt';
} else {
proximityBar.style.backgroundColor = '#0088ff'; // Blue: Far
monster.state = 'roam';
}

// --- MONSTER MOVEMENT & PATROL AI ---
if (monster.state === 'hunt') {
// Chase player directly across the house
let angle = Math.atan2(player.y - monster.y, player.x - monster.x);
let step = monster.chaseSpeed;

monster.x += Math.cos(angle) * step;
for (let wall of walls) {
if (checkCircleRectCollision(monster.x, monster.y, monster.radius, wall.x, wall.y, wall.w, wall.h)) {
monster.x -= Math.cos(angle) * step; break;
}
}
monster.y += Math.sin(angle) * step;
for (let wall of walls) {
if (checkCircleRectCollision(monster.x, monster.y, monster.radius, wall.x, wall.y, wall.w, wall.h)) {
monster.y -= Math.sin(angle) * step; break;
}
}
} else {
// Roam around the house dynamically by walking through waypoints across rooms
let angle = Math.atan2(currentWaypoint.y - monster.y, currentWaypoint.x - monster.x);
let step = monster.speed;

monster.x += Math.cos(angle) * step;
monster.y += Math.sin(angle) * step;

// When close to current waypoint, pick a new random room waypoint
if (Math.hypot(currentWaypoint.x - monster.x, currentWaypoint.y - monster.y) < 25) {
let nextIdx = Math.floor(Math.random() * houseWaypoints.length);
currentWaypoint = houseWaypoints[nextIdx];
}
}

// Monster door breakdown mechanism
for (let d of doors) {
if (!d.open && checkCircleRectCollision(monster.x, monster.y, monster.radius, d.x, d.y, d.w, d.h)) {
monster.targetDoor = d;
monster.breakTimer += 1;
if (monster.breakTimer > 75) {
d.open = true;
monster.breakTimer = 0;
monster.targetDoor = null;
}
break;
}
}

// Collision check with monster (Death)
if (distToMonster < player.radius + monster.radius) {
gameState = 'gameover';
document.getElementById('gameOverScreen').style.display = 'flex';
}

// Exit door check (Win)
if (player.x >= exitDoor.x && player.x <= exitDoor.x + exitDoor.w &&
player.y >= exitDoor.y && player.y <= exitDoor.y + exitDoor.h) {
gameState = 'win';
document.getElementById('winScreen').style.display = 'flex';
}

// --- INTERACTION DETECTION ---
currentPromptItem = null;
interactionType = null;
const actionBanner = document.getElementById('actionBanner');
const interactionBtn = document.getElementById('interactionBtn');

for (let hs of hidingSpots) {
if (Math.hypot(player.x - (hs.x + hs.w/2), player.y - (hs.y + hs.h/2)) < 35) {
currentPromptItem = hs;
interactionType = 'hide';
actionBanner.innerText = `Press [E] to Hide in ${hs.label}`;
actionBanner.style.display = 'block';
interactionBtn.style.display = 'flex';
interactionBtn.innerText = 'HIDE';
return;
}
}

for (let d of doors) {
if (Math.hypot(player.x - (d.x + d.w/2), player.y - (d.y + d.h/2)) < 40) {
currentPromptItem = d;
interactionType = 'door';
actionBanner.innerText = `Press [E] to ${d.open ? 'Close' : 'Open'} Door`;
actionBanner.style.display = 'block';
interactionBtn.style.display = 'flex';
interactionBtn.innerText = d.open ? 'CLOSE' : 'OPEN';
return;
}
}

actionBanner.style.display = 'none';
interactionBtn.style.display = 'none';
}

function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);

// Floor background
ctx.fillStyle = '#101014';
ctx.fillRect(0, 0, canvas.width, canvas.height);

// Draw Exit Door
ctx.fillStyle = '#00331a';
ctx.fillRect(exitDoor.x, exitDoor.y, exitDoor.w, exitDoor.h);
ctx.fillStyle = '#00ff88';
ctx.fillRect(exitDoor.x + 3, exitDoor.y + 3, exitDoor.w - 6, exitDoor.h - 6);
ctx.fillStyle = '#000';
ctx.font = 'bold 9px sans-serif';
ctx.fillText("EXIT", exitDoor.x + 3, exitDoor.y + 40);

// Draw Hiding Spots
ctx.fillStyle = '#332211';
for (let hs of hidingSpots) {
ctx.fillRect(hs.x, hs.y, hs.w, hs.h);
ctx.strokeStyle = '#553311';
ctx.strokeRect(hs.x, hs.y, hs.w, hs.h);
}

// Draw Walls
ctx.fillStyle = '#222230';
for (let wall of walls) {
ctx.fillRect(wall.x, wall.y, wall.w, wall.h);
ctx.strokeStyle = '#15151f';
ctx.strokeRect(wall.x, wall.y, wall.w, wall.h);
}

// Draw Doors
for (let d of doors) {
if (d.open) {
ctx.fillStyle = 'rgba(50, 50, 70, 0.4)';
ctx.fillRect(d.x, d.y, d.w, d.h);
} else {
ctx.fillStyle = '#664422';
ctx.fillRect(d.x, d.y, d.w, d.h);
ctx.strokeStyle = '#332211';
ctx.strokeRect(d.x, d.y, d.w, d.h);
}
}

// Draw Player
if (!player.isHiding) {
ctx.save();
ctx.translate(player.x, player.y);
ctx.beginPath();
ctx.arc(0, 0, player.radius, 0, Math.PI * 2);
ctx.fillStyle = '#3498db';
ctx.fill();
ctx.lineWidth = 2;
ctx.strokeStyle = '#fff';
ctx.stroke();
ctx.restore();
}

// Draw Monster (roams across rooms seamlessly)
ctx.save();
ctx.translate(monster.x, monster.y);
ctx.beginPath();
ctx.arc(0, 0, monster.radius, 0, Math.PI * 2);
ctx.fillStyle = '#111';
ctx.fill();
ctx.lineWidth = 2;
ctx.strokeStyle = '#aa0000';
ctx.stroke();

// Glowing red eyes
ctx.fillStyle = '#ff0000';
ctx.beginPath();
ctx.arc(-4, -2, 2.5, 0, Math.PI * 2);
ctx.arc(4, -2, 2.5, 0, Math.PI * 2);
ctx.fill();
ctx.restore();

// Darkness vignette lighting
let gradient = ctx.createRadialGradient(player.x, player.y, 40, player.x, player.y, 280);
gradient.addColorStop(0, 'rgba(0,0,0,0)');
gradient.addColorStop(1, 'rgba(0,0,0,0.9)');
ctx.fillStyle = gradient;
ctx.fillRect(0, 0, canvas.width, canvas.height);
}

function gameLoop() {
if (gameState === 'playing') {
update();
draw();
requestAnimationFrame(gameLoop);
}
}
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Home Alone: Mansion Escape & Hide</title>
<style>
* {
box-sizing: border-box;
margin: 0;
padding: 0;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
user-select: none;
-webkit-user-select: none;
}

body {
background-color: #050507;
color: #eee;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100vh;
overflow: hidden;
touch-action: none;
}

.game-wrapper {
position: relative;
width: 100%;
max-width: 850px;
height: 520px;
background: #000;
border: 3px solid #222;
border-radius: 8px;
overflow: hidden;
box-shadow: 0 15px 35px rgba(0,0,0,0.9);
}

canvas {
display: block;
width: 100%;
height: 100%;
}

/* Top Distance Proximity Bar */
.proximity-container {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 14px;
background: #111;
z-index: 6;
border-bottom: 1px solid #333;
}

.proximity-bar {
height: 100%;
width: 50%;
background: #0088ff;
transition: width 0.1s linear, background-color 0.3s ease;
}

.ui-overlay {
position: absolute;
top: 25px;
left: 15px;
right: 15px;
display: flex;
justify-content: space-between;
pointer-events: none;
font-weight: bold;
font-size: 0.95rem;
text-shadow: 2px 2px 4px rgba(0,0,0,0.9);
z-index: 5;
}

.action-banner {
position: absolute;
bottom: 140px;
width: 100%;
text-align: center;
font-weight: bold;
font-size: 1.1rem;
color: #ffd700;
text-shadow: 0 0 8px rgba(0,0,0,0.9);
display: none;
z-index: 5;
}

/* Virtual Joystick */
.joystick-zone {
position: absolute;
bottom: 20px;
left: 20px;
width: 120px;
height: 120px;
background: rgba(255, 255, 255, 0.04);
border: 2px solid rgba(255, 255, 255, 0.12);
border-radius: 50%;
touch-action: none;
z-index: 5;
}

.joystick-handle {
position: absolute;
top: 35px;
left: 35px;
width: 50px;
height: 50px;
background: rgba(255, 255, 255, 0.25);
border-radius: 50%;
pointer-events: none;
transition: transform 0.05s linear;
}

.interaction-btn {
position: absolute;
bottom: 35px;
right: 35px;
width: 90px;
height: 90px;
background: rgba(255, 215, 0, 0.15);
border: 2px solid #ffd700;
border-radius: 50%;
color: #ffd700;
font-weight: bold;
font-size: 0.85rem;
display: none;
align-items: center;
justify-content: center;
cursor: pointer;
z-index: 5;
box-shadow: 0 0 15px rgba(255, 215, 0, 0.3);
}

.instructions {
margin-top: 10px;
font-size: 0.8rem;
color: #777;
text-align: center;
}

/* Screen overlays */
.screen-overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(5, 5, 8, 0.96);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
z-index: 15;
text-align: center;
padding: 20px;
}

.screen-overlay h1 {
font-size: 2.2rem;
margin-bottom: 15px;
letter-spacing: 2px;
}

.screen-overlay p {
font-size: 0.95rem;
color: #aaa;
margin-bottom: 25px;
max-width: 480px;
line-height: 1.5;
}

.btn {
background: #cc1111;
color: white;
border: none;
padding: 12px 30px;
font-size: 1rem;
font-weight: bold;
border-radius: 4px;
cursor: pointer;
transition: background 0.2s;
letter-spacing: 1px;
}

.btn:hover { background: #e61919; }
.win-screen .btn { background: #00aa55; }
.win-screen .btn:hover { background: #00cc66; }
</style>
</head>
<body>

<div class="game-wrapper">
<!-- Top Proximity Meter -->
<div class="proximity-container">
<div id="proximityBar" class="proximity-bar"></div>
</div>

<div class="ui-overlay">
<div>Objective: Find the <span style="color:#00ff88;">Front Exit Door</span></div>
<div id="statusText">Status: Roaming Mansion</div>
</div>

<div id="actionBanner" class="action-banner">Press [E] or Tap Button to Interact</div>

<canvas id="gameCanvas" width="850" height="520"></canvas>

<div id="joystickZone" class="joystick-zone">
<div id="joystickHandle" class="joystick-handle"></div>
</div>

<button id="interactionBtn" class="interaction-btn" onclick="handleInteraction()">USE</button>

<!-- Start Screen -->
<div id="startScreen" class="screen-overlay">
<h1 style="color: #cc1111;">MANSION SURVIVAL</h1>
<p>The entity roams restlessly through every room of the mansion! Watch the top proximity bar: it turns <b>BLUE</b> when it's far and <b>RED</b> when it's closing in. Hide in closets or under furniture if it paths near you, and lock or close doors to stall its advance. Find the exit door to survive.</p>
<button class="btn" onclick="startGame()">ENTER MANSION</button>
</div>

<!-- Game Over Screen -->
<div id="gameOverScreen" class="screen-overlay" style="display: none;">
<h1 style="color: #cc1111;">CAUGHT & CONSUMED</h1>
<p>The entity tore through the rooms, tracked you down, and caught you in the dark.</p>
<button class="btn" onclick="resetGame()">TRY AGAIN</button>
</div>

<!-- Win Screen -->
<div id="winScreen" class="screen-overlay win-screen" style="display: none;">
<h1 style="color: #00ff88;">SURVIVED & ESCAPED</h1>
<p>You unlocked the front entrance and slipped out into safety while the entity prowled elsewhere.</p>
<button class="btn" onclick="resetGame()">PLAY AGAIN</button>
</div>
</div>

<div class="instructions">
Tip: The monster constantly patrols and searches the mansion paths. Hide quickly when the bar turns red!
</div>

<script>
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');

let gameState = 'start'; // start, playing, gameover, win

const player = {
x: 60,
y: 450,
radius: 11,
speed: 2.8,
angle: 0,
isHiding: false,
hidingSpot: null
};

const monster = {
x: 750,
y: 70,
radius: 13,
speed: 2.4, // Patrolling speed
chaseSpeed: 3.6, // Hunting speed
state: 'roam', // roam, hunt
vx: 1,
vy: 1,
targetDoor: null,
breakTimer: 0,
waypointTimer: 0
};

// Comprehensive Mansion Layout with walls, hallways, and doorways
const walls = [
// Outer boundaries
{x: 0, y: 0, w: 850, h: 20},
{x: 0, y: 500, w: 850, h: 20},
{x: 0, y: 0, w: 20, h: 520},
{x: 830, y: 0, w: 20, h: 520},

// Room dividers
{x: 220, y: 20, w: 20, h: 200},
{x: 220, y: 300, w: 20, h: 200}, // Hallway gap 1
{x: 520, y: 20, w: 20, h: 180},
{x: 520, y: 280, w: 20, h: 220}, // Hallway gap 2
{x: 350, y: 340, w: 170, h: 20}, // Central room wall
{x: 680, y: 160, w: 150, h: 20}, // Right upper room divider
{x: 680, y: 340, w: 150, h: 20} // Right lower room divider
];

// Mansion Rooms Waypoints for wandering AI patter
const houseWaypoints = [
{x: 100, y: 100}, // Study room
{x: 400, y: 100}, // Library room
{x: 750, y: 90}, // Vault room
{x: 750, y: 440}, // Kitchen/pantry room
{x: 400, y: 440}, // Central bedroom area
{x: 100, y: 440} // Foyer area
];
let currentWaypoint = houseWaypoints[0];

// Interactive Doors
const doors = [
{id: 'd1', x: 220, y: 220, w: 20, h: 80, room: 'Room 1 (Study)', open: false},
{id: 'd2', x: 520, y: 180, w: 20, h: 100, room: 'Room 2 (Library)', open: false},
{id: 'd3', x: 330, y: 340, w: 80, h: 20, room: 'Room 3 (Bedroom)', open: false},
{id: 'd4', x: 680, y: 160, w: 60, h: 20, room: 'Room 4 (Vault)', open: false}
];

// Hiding spots inside rooms
const hidingSpots = [
{x: 80, y: 60, w: 40, h: 25, label: 'Study Closet'},
{x: 400, y: 60, w: 40, h: 25, label: 'Library Bookshelf'},
{x: 100, y: 400, w: 40, h: 25, label: 'Bedroom Wardrobe'},
{x: 740, y: 80, w: 40, h: 25, label: 'Vault Locker'},
{x: 740, y: 420, w: 40, h: 25, label: 'Kitchen Pantry'}
];

const exitDoor = {x: 800, y: 430, w: 30, h: 70};

let currentPromptItem = null;
let interactionType = null;

// Controls setup
const keys = { w: false, a: false, s: false, d: false, arrowup: false, arrowleft: false, arrowdown: false, arrowright: false, e: false };
let joystickActive = false;
let joystickVector = { x: 0, y: 0 };
const joystickZone = document.getElementById('joystickZone');
const joystickHandle = document.getElementById('joystickHandle');
let joystickCenter = { x: 0, y: 0 };

joystickZone.addEventListener('pointerdown', (e) => {
joystickActive = true;
const rect = joystickZone.getBoundingClientRect();
joystickCenter = { x: rect.left + rect.width / 2, y: rect.top + rect.height / 2 };
updateJoystick(e.clientX, e.clientY);
joystickZone.setPointerCapture(e.pointerId);
});

joystickZone.addEventListener('pointermove', (e) => {
if (!joystickActive) return;
updateJoystick(e.clientX, e.clientY);
});

joystickZone.addEventListener('pointerup', (e) => {
joystickActive = false;
joystickVector = { x: 0, y: 0 };
joystickHandle.style.transform = `translate(0px, 0px)`;
});

function updateJoystick(clientX, clientY) {
const dx = clientX - joystickCenter.x;
const dy = clientY - joystickCenter.y;
const distance = Math.hypot(dx, dy);
const maxRadius = 40;
let angle = Math.atan2(dy, dx);
let constrainedDist = Math.min(distance, maxRadius);

joystickHandle.style.transform = `translate(${Math.cos(angle) * constrainedDist}px, ${Math.sin(angle) * constrainedDist}px)`;
joystickVector.x = (Math.cos(angle) * constrainedDist) / maxRadius;
joystickVector.y = (Math.sin(angle) * constrainedDist) / maxRadius;
}

window.addEventListener('keydown', (e) => {
let k = e.key.toLowerCase();
if (keys.hasOwnProperty(k)) keys[k] = true;
if (e.key.startsWith('Arrow')) keys[e.key.toLowerCase()] = true;
if (k === 'e') handleInteraction();
});

window.addEventListener('keyup', (e) => {
let k = e.key.toLowerCase();
if (keys.hasOwnProperty(k)) keys[k] = false;
if (e.key.startsWith('Arrow')) keys[e.key.toLowerCase()] = false;
});

function startGame() {
document.getElementById('startScreen').style.display = 'none';
resetPositions();
gameState = 'playing';
requestAnimationFrame(gameLoop);
}

function resetGame() {
document.getElementById('gameOverScreen').style.display = 'none';
document.getElementById('winScreen').style.display = 'none';
resetPositions();
gameState = 'playing';
}

function resetPositions() {
player.x = 60;
player.y = 450;
player.isHiding = false;
player.hidingSpot = null;
monster.x = 780;
monster.y = 70;
monster.state = 'roam';
monster.targetDoor = null;
currentWaypoint = houseWaypoints[0];
doors.forEach(d => d.open = false);
}

function checkCircleRectCollision(cx, cy, radius, rx, ry, rw, rh) {
let testX = cx, testY = cy;
if (cx < rx) testX = rx; else if (cx > rx + rw) testX = rx + rw;
if (cy < ry) testY = ry; else if (cy > ry + rh) testY = ry + rh;
return Math.hypot(cx - testX, cy - testY) <= radius;
}

function handleInteraction() {
if (gameState !== 'playing') return;

if (player.isHiding) {
player.isHiding = false;
player.x = player.hidingSpot.x + player.hidingSpot.w / 2;
player.y = player.hidingSpot.y + player.hidingSpot.h + 20;
player.hidingSpot = null;
document.getElementById('statusText').innerText = "Status: Emerged from Hiding";
document.getElementById('actionBanner').style.display = 'none';
document.getElementById('interactionBtn').style.display = 'none';
return;
}

if (interactionType === 'hide' && currentPromptItem) {
player.isHiding = true;
player.hidingSpot = currentPromptItem;
document.getElementById('statusText').innerText = `Status: Hiding inside ${currentPromptItem.label}`;
document.getElementById('actionBanner').innerText = "Press [E] to Exit Hiding";
document.getElementById('interactionBtn').innerText = "EXIT";
} else if (interactionType === 'door' && currentPromptItem) {
currentPromptItem.open = !currentPromptItem.open;
document.getElementById('statusText').innerText = `Status: Door ${currentPromptItem.open ? 'Opened' : 'Closed'}`;
}
}

function update() {
if (gameState !== 'playing') return;

// Handle Hiding State
if (player.isHiding) {
let distToSpot = Math.hypot(monster.x - (player.hidingSpot.x + player.hidingSpot.h/2), monster.y - (player.hidingSpot.y + player.hidingSpot.w/2));
if (distToSpot < 35 && monster.state === 'hunt') {
gameState = 'gameover';
document.getElementById('gameOverScreen').style.display = 'flex';
}
return;
}

let moveX = joystickVector.x;
let moveY = joystickVector.y;

if (keys.a || keys.arrowleft) moveX -= 1;
if (keys.d || keys.arrowright) moveX += 1;
if (keys.w || keys.arrowup) moveY -= 1;
if (keys.s || keys.arrowdown) moveY += 1;

let mag = Math.hypot(moveX, moveY);
if (mag > 1) { moveX /= mag; moveY /= mag; }

if (mag > 0.1) {
player.angle = Math.atan2(moveY, moveX);
}

let activeCollisionWalls = [...walls];
doors.forEach(d => {
if (!d.open) {
activeCollisionWalls.push({x: d.x, y: d.y, w: d.w, h: d.h});
}
});

// Move player with collision
player.x += moveX * player.speed;
for (let wall of activeCollisionWalls) {
if (checkCircleRectCollision(player.x, player.y, player.radius, wall.x, wall.y, wall.w, wall.h)) {
player.x -= moveX * player.speed; break;
}
}
player.y += moveY * player.speed;
for (let wall of activeCollisionWalls) {
if (checkCircleRectCollision(player.x, player.y, player.radius, wall.x, wall.y, wall.w, wall.h)) {
player.y -= moveY * player.speed; break;
}
}

// --- PROXIMITY METER ---
let distToMonster = Math.hypot(player.x - monster.x, player.y - monster.y);
let proximityBar = document.getElementById('proximityBar');

let proxPercent = Math.max(10, Math.min(100, (1 - (distToMonster / 550)) * 100));
proximityBar.style.width = proxPercent + '%';

if (distToMonster < 170) {
proximityBar.style.backgroundColor = '#ff1a1a'; // Red: Close
monster.state = 'hunt';
} else {
proximityBar.style.backgroundColor = '#0088ff'; // Blue: Far
monster.state = 'roam';
}

// --- MONSTER MOVEMENT & PATROL AI ---
if (monster.state === 'hunt') {
// Chase player directly across the house
let angle = Math.atan2(player.y - monster.y, player.x - monster.x);
let step = monster.chaseSpeed;

monster.x += Math.cos(angle) * step;
for (let wall of walls) {
if (checkCircleRectCollision(monster.x, monster.y, monster.radius, wall.x, wall.y, wall.w, wall.h)) {
monster.x -= Math.cos(angle) * step; break;
}
}
monster.y += Math.sin(angle) * step;
for (let wall of walls) {
if (checkCircleRectCollision(monster.x, monster.y, monster.radius, wall.x, wall.y, wall.w, wall.h)) {
monster.y -= Math.sin(angle) * step; break;
}
}
} else {
// Roam around the house dynamically by walking through waypoints across rooms
let angle = Math.atan2(currentWaypoint.y - monster.y, currentWaypoint.x - monster.x);
let step = monster.speed;

monster.x += Math.cos(angle) * step;
monster.y += Math.sin(angle) * step;

// When close to current waypoint, pick a new random room waypoint
if (Math.hypot(currentWaypoint.x - monster.x, currentWaypoint.y - monster.y) < 25) {
let nextIdx = Math.floor(Math.random() * houseWaypoints.length);
currentWaypoint = houseWaypoints[nextIdx];
}
}

// Monster door breakdown mechanism
for (let d of doors) {
if (!d.open && checkCircleRectCollision(monster.x, monster.y, monster.radius, d.x, d.y, d.w, d.h)) {
monster.targetDoor = d;
monster.breakTimer += 1;
if (monster.breakTimer > 75) {
d.open = true;
monster.breakTimer = 0;
monster.targetDoor = null;
}
break;
}
}

// Collision check with monster (Death)
if (distToMonster < player.radius + monster.radius) {
gameState = 'gameover';
document.getElementById('gameOverScreen').style.display = 'flex';
}

// Exit door check (Win)
if (player.x >= exitDoor.x && player.x <= exitDoor.x + exitDoor.w &&
player.y >= exitDoor.y && player.y <= exitDoor.y + exitDoor.h) {
gameState = 'win';
document.getElementById('winScreen').style.display = 'flex';
}

// --- INTERACTION DETECTION ---
currentPromptItem = null;
interactionType = null;
const actionBanner = document.getElementById('actionBanner');
const interactionBtn = document.getElementById('interactionBtn');

for (let hs of hidingSpots) {
if (Math.hypot(player.x - (hs.x + hs.w/2), player.y - (hs.y + hs.h/2)) < 35) {
currentPromptItem = hs;
interactionType = 'hide';
actionBanner.innerText = `Press [E] to Hide in ${hs.label}`;
actionBanner.style.display = 'block';
interactionBtn.style.display = 'flex';
interactionBtn.innerText = 'HIDE';
return;
}
}

for (let d of doors) {
if (Math.hypot(player.x - (d.x + d.w/2), player.y - (d.y + d.h/2)) < 40) {
currentPromptItem = d;
interactionType = 'door';
actionBanner.innerText = `Press [E] to ${d.open ? 'Close' : 'Open'} Door`;
actionBanner.style.display = 'block';
interactionBtn.style.display = 'flex';
interactionBtn.innerText = d.open ? 'CLOSE' : 'OPEN';
return;
}
}

actionBanner.style.display = 'none';
interactionBtn.style.display = 'none';
}

function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);

// Floor background
ctx.fillStyle = '#101014';
ctx.fillRect(0, 0, canvas.width, canvas.height);

// Draw Exit Door
ctx.fillStyle = '#00331a';
ctx.fillRect(exitDoor.x, exitDoor.y, exitDoor.w, exitDoor.h);
ctx.fillStyle = '#00ff88';
ctx.fillRect(exitDoor.x + 3, exitDoor.y + 3, exitDoor.w - 6, exitDoor.h - 6);
ctx.fillStyle = '#000';
ctx.font = 'bold 9px sans-serif';
ctx.fillText("EXIT", exitDoor.x + 3, exitDoor.y + 40);

// Draw Hiding Spots
ctx.fillStyle = '#332211';
for (let hs of hidingSpots) {
ctx.fillRect(hs.x, hs.y, hs.w, hs.h);
ctx.strokeStyle = '#553311';
ctx.strokeRect(hs.x, hs.y, hs.w, hs.h);
}

// Draw Walls
ctx.fillStyle = '#222230';
for (let wall of walls) {
ctx.fillRect(wall.x, wall.y, wall.w, wall.h);
ctx.strokeStyle = '#15151f';
ctx.strokeRect(wall.x, wall.y, wall.w, wall.h);
}

// Draw Doors
for (let d of doors) {
if (d.open) {
ctx.fillStyle = 'rgba(50, 50, 70, 0.4)';
ctx.fillRect(d.x, d.y, d.w, d.h);
} else {
ctx.fillStyle = '#664422';
ctx.fillRect(d.x, d.y, d.w, d.h);
ctx.strokeStyle = '#332211';
ctx.strokeRect(d.x, d.y, d.w, d.h);
}
}

// Draw Player
if (!player.isHiding) {
ctx.save();
ctx.translate(player.x, player.y);
ctx.beginPath();
ctx.arc(0, 0, player.radius, 0, Math.PI * 2);
ctx.fillStyle = '#3498db';
ctx.fill();
ctx.lineWidth = 2;
ctx.strokeStyle = '#fff';
ctx.stroke();
ctx.restore();
}

// Draw Monster (roams across rooms seamlessly)
ctx.save();
ctx.translate(monster.x, monster.y);
ctx.beginPath();
ctx.arc(0, 0, monster.radius, 0, Math.PI * 2);
ctx.fillStyle = '#111';
ctx.fill();
ctx.lineWidth = 2;
ctx.strokeStyle = '#aa0000';
ctx.stroke();

// Glowing red eyes
ctx.fillStyle = '#ff0000';
ctx.beginPath();
ctx.arc(-4, -2, 2.5, 0, Math.PI * 2);
ctx.arc(4, -2, 2.5, 0, Math.PI * 2);
ctx.fill();
ctx.restore();

// Darkness vignette lighting
let gradient = ctx.createRadialGradient(player.x, player.y, 40, player.x, player.y, 280);
gradient.addColorStop(0, 'rgba(0,0,0,0)');
gradient.addColorStop(1, 'rgba(0,0,0,0.9)');
ctx.fillStyle = gradient;
ctx.fillRect(0, 0, canvas.width, canvas.height);
}

function gameLoop() {
if (gameState === 'playing') {
update();
draw();
requestAnimationFrame(gameLoop);
}
}
</script>
</body>
</html>

Post by Tree chair united suppressed by a moderator.

Post by Tree chair united suppressed by a moderator.

Lexigton

I will now be leaving to contuine my Handbook of the friendlist regions, we are sorry

The Integrated Empire of Kilmekia

Lexigton wrote:I will now be leaving to contuine my Handbook of the friendlist regions, we are sorry

wanna join me?

Forum View