<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">

<title>Indian Train Simulator</title>

<style>
*{
box-sizing:border-box;
-webkit-tap-highlight-color:transparent;
}

body{
margin:0;
overflow:hidden;
background:#111;
font-family:Arial,sans-serif;
color:white;
touch-action:none;
}

canvas{
position:fixed;
inset:0;
width:100%;
height:100%;
}

#hud{
position:fixed;
top:8px;
left:8px;
right:8px;
display:flex;
justify-content:space-between;
pointer-events:none;
}

.panel{
background:rgba(0,0,0,.78);
padding:9px 11px;
border-radius:13px;
border:1px solid #555;
}

.title{
font-weight:bold;
font-size:14px;
}

.info{
font-size:12px;
margin-top:4px;
}

#signalBox{
text-align:center;
min-width:85px;
}

#signalLight{
width:24px;
height:24px;
border-radius:50%;
margin:4px auto;
}

#station{
position:fixed;
top:105px;
left:50%;
transform:translateX(-50%);
background:rgba(0,0,0,.75);
padding:8px 14px;
border-radius:20px;
font-size:12px;
white-space:nowrap;
}

#speedBox{
position:fixed;
bottom:160px;
left:50%;
transform:translateX(-50%);
width:105px;
height:105px;
border-radius:50%;
background:rgba(0,0,0,.8);
border:4px solid #777;
display:flex;
flex-direction:column;
align-items:center;
justify-content:center;
}

#speed{
font-size:32px;
font-weight:bold;
}

#kmh{
font-size:11px;
}

#controls{
position:fixed;
bottom:7px;
left:7px;
right:7px;
display:grid;
grid-template-columns:repeat(4,1fr);
gap:6px;
}

button{
min-height:53px;
border:1px solid #555;
border-radius:13px;
background:rgba(20,20,20,.94);
color:white;
font-size:11px;
font-weight:bold;
}

button:active{
transform:scale(.94);
background:#444;
}

.green{
background:#075b25;
}

.red{
background:#720d0d;
}

.blue{
background:#064b72;
}

.yellow{
background:#705900;
}

#message{
position:fixed;
left:50%;
top:48%;
transform:translate(-50%,-50%);
background:rgba(0,0,0,.8);
padding:10px 18px;
border-radius:15px;
display:none;
font-weight:bold;
}

@media(max-width:400px){
button{
font-size:10px;
min-height:50px;
}
}
</style>
</head>

<body>

<canvas id="game"></canvas>

<div id="hud">

<div class="panel">

<div class="title">
🇮🇳 INDIAN TRAIN SIMULATOR
</div>

<div class="info">
Speed: <span id="speed">0</span> km/h
</div>

<div class="info">
Throttle: <span id="throttle">0</span>/8
</div>

<div class="info">
Brake: <span id="brake">0</span>%
</div>

<div class="info">
Time: <span id="time">06:00</span>
</div>

</div>

<div class="panel" id="signalBox">

SIGNAL

<div id="signalLight"></div>

<div id="signalText">
GREEN
</div>

</div>

</div>

<div id="station">
NEXT: Jaipur Junction
</div>

<div id="speedBox">

<div id="speed">0</div>

<div id="kmh">
KM/H
</div>

</div>

<div id="message"></div>

<div id="controls">

<button class="green"
onclick="throttleUp()">
THROTTLE +
</button>

<button
onclick="throttleDown()">
THROTTLE −
</button>

<button class="red"
onclick="brakeUp()">
BRAKE +
</button>

<button
onclick="brakeDown()">
BRAKE −
</button>

<button class="yellow"
onclick="horn()">
📯 HORN
</button>

<button class="blue"
onclick="togglePoints()">
🛤️ POINTS
</button>

<button
onclick="toggleRain()">
🌧️ RAIN
</button>

<button
onclick="toggleLights()">
💡 LIGHT
</button>

<button
onclick="toggleCab()">
👨‍✈️ CAB
</button>

<button
onclick="toggleTime()">
☀️/🌙 TIME
</button>

<button
onclick="toggleDoors()">
🚪 DOORS
</button>

<button
onclick="resetTrain()">
↻ RESET
</button>

</div>

<script>

const canvas=document.getElementById("game");
const ctx=canvas.getContext("2d");

function resize(){
canvas.width=innerWidth;
canvas.height=innerHeight;
}

resize();
addEventListener("resize",resize);


/* =====================
TRAIN
===================== */

let throttle=0;
let brake=0;
let speed=0;
let distance=0;

let direction=1;

let headlight=true;
let rain=false;
let cab=false;
let night=false;
let doors=false;
let points=false;

let hornTimer=0;

let gameTime=6*60;


/* =====================
STATIONS
===================== */

const stations=[
"Jaipur Junction",
"Gandhi Nagar Jaipur",
"Durgapura",
"Sanganer",
"Phulera Junction",
"Ajmer Junction",
"Kishangarh",
"Beawar"
];

let stationIndex=0;
let stationDistance=5;


/* =====================
AI TRAINS
===================== */

let trains=[
{
distance:7,
speed:65,
type:"EXPRESS"
},
{
distance:13,
speed:80,
type:"PASSENGER"
}
];


/* =====================
CONTROLS
===================== */

function throttleUp(){

if(throttle<8)
throttle++;

}

function throttleDown(){

if(throttle>0)
throttle--;

}

function brakeUp(){

brake=Math.min(100,brake+10);

}

function brakeDown(){

brake=Math.max(0,brake-10);

}

function horn(){

hornTimer=35;

if(navigator.vibrate)
navigator.vibrate([100,70,160]);

}

function toggleLights(){

headlight=!headlight;

showMessage(
headlight ? "HEADLIGHT ON" : "HEADLIGHT OFF"
);

}

function toggleRain(){

rain=!rain;

showMessage(
rain ? "RAIN ON 🌧️" : "RAIN OFF"
);

}

function toggleCab(){

cab=!cab;

showMessage(
cab ? "CAB VIEW" : "EXTERNAL VIEW"
);

}

function toggleTime(){

night=!night;

showMessage(
night ? "NIGHT MODE 🌙" : "DAY MODE ☀️"
);

}

function toggleDoors(){

doors=!doors;

showMessage(
doors ? "DOORS OPEN" : "DOORS CLOSED"
);

}

function togglePoints(){

points=!points;

showMessage(
points ? "TRACK 2 SELECTED" : "TRACK 1 SELECTED"
);

}

function resetTrain(){

throttle=0;
brake=100;
speed=0;
distance=0;

setTimeout(()=>{
brake=0;
},800);

}


/* =====================
MESSAGE
===================== */

let messageTimer=0;

function showMessage(text){

const m=document.getElementById("message");

m.innerText=text;
m.style.display="block";

messageTimer=90;

}


/* =====================
KEYBOARD
===================== */

document.addEventListener("keydown",e=>{

if(e.key==="ArrowUp")
throttleUp();

if(e.key==="ArrowDown")
throttleDown();

if(e.key===" ")
brakeUp();

if(e.key==="h")
horn();

});


/* =====================
PHYSICS
===================== */

function updatePhysics(){

let power=throttle*.055;

let braking=(brake/100)*.30;

let resistance=.015;

speed+=power;
speed-=braking;
speed-=resistance;

if(speed<0)
speed=0;

if(speed>160)
speed=160;

distance+=speed/3600;

stationDistance-=speed/3600;

if(stationDistance<=0){

stationIndex++;

if(stationIndex>=stations.length)
stationIndex=0;

stationDistance=
5+Math.random()*8;

showMessage(
"NEXT STATION: "+
stations[stationIndex]
);

}


/* AI */

for(let train of trains){

train.distance-=train.speed/3600;

if(train.distance<0){

train.distance=
8+Math.random()*15;

train.speed=
45+Math.random()*70;

}

}


/* TIME */

gameTime+=1/60;

if(gameTime>=24*60)
gameTime=0;

hornTimer--;

if(messageTimer>0){

messageTimer--;

if(messageTimer===0)
document.getElementById("message")
.style.display="none";

}

}


/* =====================
SIGNALS
===================== */

let signal="GREEN";

function updateSignal(){

let nearest=999;

for(let train of trains){

if(train.distance>0 &&
train.distance<nearest)

nearest=train.distance;

}

if(nearest<2.5){

signal="RED";

}
else if(nearest<5){

signal="YELLOW";

}
else{

signal="GREEN";

}

}


/* =====================
HUD
===================== */

function updateHUD(){

document.querySelectorAll("#speed")
.forEach(e=>{
e.innerText=Math.round(speed);
});

document.getElementById("throttle")
.innerText=throttle;

document.getElementById("brake")
.innerText=Math.round(brake);

document.getElementById("station")
.innerText=
"NEXT: "+
stations[stationIndex]+
"  |  "+
stationDistance.toFixed(1)+
" km";

let hour=Math.floor(gameTime/60);
let min=Math.floor(gameTime%60);

document.getElementById("time")
.innerText=
String(hour).padStart(2,"0")+
":"+
String(min).padStart(2,"0");


let light=
document.getElementById("signalLight");

let text=
document.getElementById("signalText");

if(signal==="RED"){

light.style.background="red";
light.style.boxShadow="0 0 18px red";

text.innerText="RED — STOP";

}

else if(signal==="YELLOW"){

light.style.background="yellow";
light.style.boxShadow="0 0 18px yellow";

text.innerText="YELLOW — CAUTION";

}

else{

light.style.background="lime";
light.style.boxShadow="0 0 18px lime";

text.innerText="GREEN — PROCEED";

}

}


/* =====================
DRAW
===================== */

function draw(){

const w=canvas.width;
const h=canvas.height;

ctx.clearRect(0,0,w,h);


/* SKY */

let sky;

if(night){

sky=ctx.createLinearGradient(
0,0,0,h*.6
);

sky.addColorStop(0,"#071326");
sky.addColorStop(1,"#26384b");

}
else{

sky=ctx.createLinearGradient(
0,0,0,h*.6
);

sky.addColorStop(0,"#48a2df");
sky.addColorStop(1,"#dff7ff");

}

ctx.fillStyle=sky;
ctx.fillRect(0,0,w,h*.6);


/* SUN / MOON */

ctx.fillStyle=night
?"#eeeecc"
:"#fff1a0";

ctx.beginPath();

ctx.arc(
w*.82,
h*.15,
34,
0,
Math.PI*2
);

ctx.fill();


/* LAND */

ctx.fillStyle=
night ? "#172d20" : "#397532";

ctx.fillRect(
0,
h*.52,
w,
h*.48
);


/* HILLS */

ctx.fillStyle=
night ? "#203a32" : "#557d5d";

ctx.beginPath();

ctx.moveTo(0,h*.53);

for(let x=0;x<=w;x+=60){

let y=
h*.43+
Math.sin(x*.008)*35+
Math.sin(x*.019)*18;

ctx.lineTo(x,y);

}

ctx.lineTo(w,h*.55);
ctx.lineTo(0,h*.55);

ctx.closePath();

ctx.fill();


/* TRACK */

const horizon=h*.48;

ctx.fillStyle="#51463e";

ctx.beginPath();

ctx.moveTo(w*.47,horizon);
ctx.lineTo(w*.53,horizon);
ctx.lineTo(w*.96,h);
ctx.lineTo(w*.04,h);
ctx.closePath();

ctx.fill();


/* SECOND TRACK */

if(points){

ctx.strokeStyle="#777";
ctx.lineWidth=5;

ctx.beginPath();

ctx.moveTo(w*.50,horizon);
ctx.lineTo(w*.78,h);

ctx.stroke();

}


/* RAILS */

ctx.strokeStyle="#c8c8c8";
ctx.lineWidth=7;

ctx.beginPath();

ctx.moveTo(w*.47,horizon);
ctx.lineTo(w*.34,h);

ctx.stroke();

ctx.beginPath();

ctx.moveTo(w*.53,horizon);
ctx.lineTo(w*.66,h);

ctx.stroke();


/* SLEEPERS */

ctx.strokeStyle="#332822";
ctx.lineWidth=5;

for(let i=0;i<27;i++){

let p=i/27;

let y=
horizon+
(h-horizon)*p;

let width=
15+w*.42*p;

ctx.beginPath();

ctx.moveTo(
w/2-width,
y
);

ctx.lineTo(
w/2+width,
y
);

ctx.stroke();

}


/* PLATFORM */

drawPlatform(w,h);


/* SIGNAL */

drawSignal(w,h);


/* AI TRAINS */

for(let train of trains){

drawTrain(
w,
h,
train.distance
);

}


/* CAB */

if(cab){

drawCab(w,h);

}
else{

drawFrontTrain(w,h);

}


/* RAIN */

if(rain){

drawRain(w,h);

}

}


/* =====================
PLATFORM
===================== */

function drawPlatform(w,h){

ctx.fillStyle=
night ? "#303030" : "#777";

ctx.beginPath();

ctx.moveTo(w*.60,h*.53);
ctx.lineTo(w*.70,h*.53);
ctx.lineTo(w*.94,h);
ctx.lineTo(w*.78,h);

ctx.closePath();

ctx.fill();


/* platform edge */

ctx.strokeStyle="#ddd";
ctx.lineWidth=4;

ctx.beginPath();

ctx.moveTo(w*.62,h*.56);
ctx.lineTo(w*.90,h);

ctx.stroke();


/* station roof */

ctx.fillStyle="#333";

ctx.fillRect(
w*.63,
h*.46,
w*.18,
8
);

}


/* =====================
SIGNAL
===================== */

function drawSignal(w,h){

let x=w*.72;

ctx.strokeStyle="#222";
ctx.lineWidth=5;

ctx.beginPath();

ctx.moveTo(x,h*.49);
ctx.lineTo(x,h*.25);

ctx.stroke();

ctx.fillStyle="#111";

ctx.fillRect(
x-17,
h*.19,
34,
62
);

ctx.fillStyle=
signal==="RED"
?"red":
signal==="YELLOW"
?"yellow":
"lime";

ctx.beginPath();

ctx.arc(
x,
h*.22,
10,
0,
Math.PI*2
);

ctx.fill();

}


/* =====================
AI TRAIN
===================== */

function drawTrain(w,h,d){

if(d>20)
return;

let p=1-d/20;

let y=
h*.46+
p*h*.35;

let scale=.22+p*.78;

let tw=90*scale;
let th=145*scale;

let x=
points
?w*.63
:w/2;


/* coaches */

for(let i=0;i<4;i++){

let yy=y-(i*th*.42);

ctx.fillStyle=
i===0 ? "#d2d2d2" : "#bdbdbd";

ctx.fillRect(
x-tw/2,
yy-th/2,
tw,
th
);

ctx.fillStyle="#174f80";

ctx.fillRect(
x-tw/2,
yy-th*.12,
tw,
th*.12
);

ctx.fillStyle="#17242c";

ctx.fillRect(
x-tw*.32,
yy-th*.34,
tw*.22,
th*.10
);

ctx.fillRect(
x+tw*.10,
yy-th*.34,
tw*.22,
th*.10
);

}

}


/* =====================
PLAYER FRONT
===================== */

function drawFrontTrain(w,h){

ctx.fillStyle="#161616";

ctx.fillRect(
w*.22,
h*.79,
w*.56,
h*.21
);

ctx.fillStyle="#222";

ctx.fillRect(
w*.27,
h*.74,
w*.46,
h*.10
);

ctx.fillStyle=
headlight
?"#8bd4ee"
:"#263c47";

ctx.fillRect(
w*.32,
h*.77,
w*.14,
h*.055
);

ctx.fillRect(
w*.54,
h*.77,
w*.14,
h*.055
);

if(headlight){

ctx.fillStyle="#fff";

ctx.beginPath();

ctx.arc(
w/2,
h*.91,
10,
0,
Math.PI*2
);

ctx.fill();

}

}


/* =====================
CAB VIEW
===================== */

function drawCab(w,h){

/* dashboard */

ctx.fillStyle="#101010";

ctx.fillRect(
0,
h*.78,
w,
h*.22
);


/* front windows */

ctx.fillStyle=
night
?"#172d42"
:"#6caec8";

ctx.fillRect(
w*.16,
h*.57,
w*.30,
h*.20
);

ctx.fillRect(
w*.54,
h*.57,
w*.30,
h*.20
);


/* pillar */

ctx.fillStyle="#111";

ctx.fillRect(
w*.47,
h*.55,
w*.06,
h*.24
);


/* controls */

ctx.fillStyle="#222";

ctx.fillRect(
w*.20,
h*.83,
w*.60,
h*.15
);


/* meters */

ctx.fillStyle="#050505";

ctx.beginPath();

ctx.arc(
w*.31,
h*.88,
27,
0,
Math.PI*2
);

ctx.fill();

ctx.beginPath();

ctx.arc(
w*.69,
h*.88,
27,
0,
Math.PI*2
);

ctx.fill();


/* throttle lever */

ctx.fillStyle="#777";

ctx.fillRect(
w*.48,
h*.82,
8,
45
);


/* station platform view */

if(doors){

ctx.fillStyle="#aaa";

ctx.fillRect(
w*.05,
h*.67,
w*.12,
h*.10
);

ctx.fillRect(
w*.83,
h*.67,
w*.12,
h*.10
);

}


/* horn */

if(hornTimer>0){

ctx.fillStyle="#fff";
ctx.font="bold 28px Arial";
ctx.textAlign="center";

ctx.fillText(
"📯 HOOOON!",
w/2,
h*.50
);

}

}


/* =====================
RAIN
===================== */

function drawRain(w,h){

ctx.strokeStyle="rgba(220,240,255,.55)";
ctx.lineWidth=1.5;

for(let i=0;i<160;i++){

let x=
(i*83+
distance*400)%w;

let y=
(i*47+
distance*900)%h;

ctx.beginPath();

ctx.moveTo(x,y);

ctx.lineTo(
x-5,
y+18
);

ctx.stroke();

}

}


/* =====================
LOOP
===================== */

function loop(){

updatePhysics();

updateSignal();

updateHUD();

draw();

requestAnimationFrame(loop);

}

loop();

</script>

</body>
</html>