<html lang="en"><head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Pac-Man Game</title>
<script src="https://cdn.tailwindcss.com"></script>
<style>
body {
background-color: #1a1a2e;
font-family: 'Arial Rounded MT Bold', 'Arial', sans-serif;
overflow: hidden;
}
.game-container {
position: relative;
margin: 0 auto;
background-color: #000;
border-radius: 8px;
box-shadow: 0 0 30px rgba(255, 255, 0, 0.3);
}
.cell {
position: absolute;
box-sizing: border-box;
}
.wall {
background-color: #0f3460;
border: 2px solid #16213e;
}
.dot {
background-color: transparent;
display: flex;
justify-content: center;
align-items: center;
}
.dot::after {
content: "";
width: 30%;
height: 30%;
background-color: #f9f871;
border-radius: 50%;
}
.power-pellet {
background-color: transparent;
display: flex;
justify-content: center;
align-items: center;
}
.power-pellet::after {
content: "";
width: 60%;
height: 60%;
background-color: #f9f871;
border-radius: 50%;
animation: pulse 1s infinite alternate;
}
@keyframes pulse {
from { transform: scale(0.8); opacity: 0.8; }
to { transform: scale(1.2); opacity: 1; }
}
.pacman {
position: absolute;
border-radius: 50%;
background-color: #ffff00;
clip-path: polygon(0 0, 100% 50%, 0 100%, 0 0);
transform-origin: right center;
transition: transform 0.2s linear;
}
.ghost {
position: absolute;
border-radius: 50% 50% 0 0;
transition: transform 0.3s linear;
}
.ghost::after {
content: "";
position: absolute;
bottom: -25%;
left: 0;
width: 100%;
height: 25%;
background-color: inherit;
clip-path: polygon(0 0, 25% 100%, 50% 0, 75% 100%, 100% 0, 100% 100%, 0 100%);
}
.ghost-eyes {
position: absolute;
width: 100%;
height: 40%;
top: 25%;
display: flex;
justify-content: space-around;
align-items: center;
}
.ghost-eye {
width: 30%;
height: 70%;
background-color: white;
border-radius: 50%;
position: relative;
}
.ghost-eye::after {
content: "";
position: absolute;
width: 50%;
height: 50%;
background-color: #0f3460;
border-radius: 50%;
top: 25%;
left: 25%;
}
.frightened {
background-color: #2d46b9 !important;
}
.frightened .ghost-eye::after {
background-color: white;
}
.score-display {
font-size: 1.5rem;
color: #f9f871;
text-shadow: 0 0 5px #ffff00;
}
.game-over-overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.8);
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
z-index: 100;
color: #f9f871;
font-size: 2rem;
text-shadow: 0 0 10px #ffff00;
opacity: 0;
pointer-events: none;
transition: opacity 0.5s;
}
.game-over-overlay.visible {
opacity: 1;
pointer-events: all;
}
.btn {
background-color: #e94560;
color: white;
border: none;
padding: 10px 20px;
border-radius: 5px;
font-size: 1rem;
cursor: pointer;
margin-top: 20px;
transition: all 0.2s;
}
.btn:hover {
background-color: #ff6b81;
transform: scale(1.05);
}
.controls {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: 1fr 1fr 1fr;
gap: 5px;
width: 180px;
height: 180px;
margin-top: 20px;
}
.control-btn {
background-color: #0f3460;
border: 2px solid #16213e;
border-radius: 10px;
display: flex;
justify-content: center;
align-items: center;
color: #f9f871;
font-size: 1.5rem;
cursor: pointer;
user-select: none;
transition: all 0.2s;
}
.control-btn:hover {
background-color: #16213e;
transform: scale(1.05);
}
.control-btn:active {
transform: scale(0.95);
background-color: #e94560;
}
.up-btn {
grid-column: 2;
grid-row: 1;
}
.left-btn {
grid-column: 1;
grid-row: 2;
}
.down-btn {
grid-column: 2;
grid-row: 3;
}
.right-btn {
grid-column: 3;
grid-row: 2;
}
.lives-display {
display: flex;
gap: 10px;
margin-top: 10px;
}
.life {
width: 20px;
height: 20px;
background-color: #ffff00;
border-radius: 50%;
clip-path: polygon(0 0, 100% 50%, 0 100%, 0 0);
}
.level-display {
font-size: 1.2rem;
color: #f9f871;
margin-top: 5px;
}
.copy-code-btn {
position: fixed;
bottom: 20px;
right: 20px;
background-color: #0f3460;
color: #f9f871;
border: 2px solid #16213e;
border-radius: 10px;
padding: 10px 15px;
font-size: 1rem;
cursor: pointer;
z-index: 1000;
display: flex;
align-items: center;
gap: 8px;
transition: all 0.3s;
}
.copy-code-btn:hover {
background-color: #16213e;
transform: scale(1.05);
}
.copy-code-btn:active {
transform: scale(0.95);
}
.copy-icon {
width: 16px;
height: 16px;
}
.tooltip {
position: absolute;
bottom: 100%;
right: 0;
background-color: #0f3460;
color: #f9f871;
padding: 5px 10px;
border-radius: 5px;
font-size: 0.8rem;
opacity: 0;
transition: opacity 0.3s;
pointer-events: none;
margin-bottom: 5px;
white-space: nowrap;
}
.copy-code-btn:hover .tooltip {
opacity: 1;
}
.code-modal {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.8);
display: flex;
justify-content: center;
align-items: center;
z-index: 2000;
opacity: 0;
pointer-events: none;
transition: opacity 0.3s;
}
.code-modal.visible {
opacity: 1;
pointer-events: all;
}
.code-container {
background-color: #1a1a2e;
border: 2px solid #16213e;
border-radius: 10px;
width: 80%;
max-width: 800px;
max-height: 80vh;
display: flex;
flex-direction: column;
overflow: hidden;
}
.code-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px 15px;
background-color: #0f3460;
color: #f9f871;
}
.code-content {
padding: 15px;
overflow-y: auto;
max-height: calc(80vh - 50px);
color: #f9f871;
font-family: monospace;
white-space: pre-wrap;
font-size: 0.9rem;
}
.close-btn {
background: none;
border: none;
color: #f9f871;
font-size: 1.5rem;
cursor: pointer;
}
.copy-btn {
background-color: #e94560;
color: white;
border: none;
padding: 5px 10px;
border-radius: 5px;
cursor: pointer;
font-size: 0.9rem;
transition: all 0.2s;
}
.copy-btn:hover {
background-color: #ff6b81;
}
@media (max-width: 768px) {
.game-container {
width: 90vw !important;
height: 90vw !important;
}
.controls {
width: 150px;
height: 150px;
}
.copy-code-btn {
bottom: 10px;
right: 10px;
padding: 8px 12px;
font-size: 0.9rem;
}
.code-container {
width: 95%;
}
}
</style>
<style>*, ::before, ::after{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgb(59 130 246 / 0.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgb(59 130 246 / 0.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }/* ! tailwindcss v3.4.16 | MIT License | https://tailwindcss.com */*,::after,::before{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}::after,::before{--tw-content:''}:host,html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;tab-size:4;font-family:ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}.mb-2{margin-bottom:0.5rem}.mt-2{margin-top:0.5rem}.flex{display:flex}.min-h-screen{min-height:100vh}.w-full{width:100%}.max-w-md{max-width:28rem}.flex-col{flex-direction:column}.items-center{align-items:center}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.p-4{padding:1rem}.text-center{text-align:center}.text-4xl{font-size:2.25rem;line-height:2.5rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.font-bold{font-weight:700}.text-yellow-300{--tw-text-opacity:1;color:rgb(253 224 71 / var(--tw-text-opacity, 1))}</style></head>
<body class="min-h-screen flex flex-col items-center justify-center p-4">
<h1 class="text-4xl font-bold text-yellow-300 mb-2 text-center">PAC-MAN</h1>
<div class="flex justify-between w-full max-w-md mb-2">
<div class="score-display">Score: <span id="score">60</span></div>
<div class="level-display">Level: <span id="level">1</span></div>
</div>
<div class="lives-display" id="lives-display"><div class="life"></div><div class="life"></div></div>
<div class="game-container" id="game-container" style="width: 450px; height: 450px;">
<div class="game-over-overlay" id="game-over">
<div>GAME OVER</div>
<div class="text-xl mt-2">Final Score: <span id="final-score">60</span></div>
<button class="btn" id="restart-btn">Play Again</button>
</div>
<div class="cell wall" style="width: 30px; height: 30px; left: 0px; top: 0px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 30px; top: 0px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 60px; top: 0px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 90px; top: 0px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 120px; top: 0px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 150px; top: 0px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 180px; top: 0px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 210px; top: 0px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 240px; top: 0px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 270px; top: 0px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 300px; top: 0px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 330px; top: 0px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 360px; top: 0px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 390px; top: 0px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 420px; top: 0px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 0px; top: 30px;"></div><div class="cell dot" data-x="1" data-y="1" style="width: 30px; height: 30px; left: 30px; top: 30px;"></div><div class="cell dot" data-x="2" data-y="1" style="width: 30px; height: 30px; left: 60px; top: 30px;"></div><div class="cell dot" data-x="3" data-y="1" style="width: 30px; height: 30px; left: 90px; top: 30px;"></div><div class="cell dot" data-x="4" data-y="1" style="width: 30px; height: 30px; left: 120px; top: 30px;"></div><div class="cell dot" data-x="5" data-y="1" style="width: 30px; height: 30px; left: 150px; top: 30px;"></div><div class="cell dot" data-x="6" data-y="1" style="width: 30px; height: 30px; left: 180px; top: 30px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 210px; top: 30px;"></div><div class="cell dot" data-x="8" data-y="1" style="width: 30px; height: 30px; left: 240px; top: 30px;"></div><div class="cell dot" data-x="9" data-y="1" style="width: 30px; height: 30px; left: 270px; top: 30px;"></div><div class="cell dot" data-x="10" data-y="1" style="width: 30px; height: 30px; left: 300px; top: 30px;"></div><div class="cell dot" data-x="11" data-y="1" style="width: 30px; height: 30px; left: 330px; top: 30px;"></div><div class="cell dot" data-x="12" data-y="1" style="width: 30px; height: 30px; left: 360px; top: 30px;"></div><div class="cell dot" data-x="13" data-y="1" style="width: 30px; height: 30px; left: 390px; top: 30px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 420px; top: 30px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 0px; top: 60px;"></div><div class="cell dot" data-x="1" data-y="2" style="width: 30px; height: 30px; left: 30px; top: 60px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 60px; top: 60px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 90px; top: 60px;"></div><div class="cell dot" data-x="4" data-y="2" style="width: 30px; height: 30px; left: 120px; top: 60px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 150px; top: 60px;"></div><div class="cell dot" data-x="6" data-y="2" style="width: 30px; height: 30px; left: 180px; top: 60px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 210px; top: 60px;"></div><div class="cell dot" data-x="8" data-y="2" style="width: 30px; height: 30px; left: 240px; top: 60px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 270px; top: 60px;"></div><div class="cell dot" data-x="10" data-y="2" style="width: 30px; height: 30px; left: 300px; top: 60px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 330px; top: 60px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 360px; top: 60px;"></div><div class="cell dot" data-x="13" data-y="2" style="width: 30px; height: 30px; left: 390px; top: 60px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 420px; top: 60px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 0px; top: 90px;"></div><div class="cell power-pellet" data-x="1" data-y="3" style="width: 30px; height: 30px; left: 30px; top: 90px;"></div><div class="cell dot" data-x="2" data-y="3" style="width: 30px; height: 30px; left: 60px; top: 90px;"></div><div class="cell dot" data-x="3" data-y="3" style="width: 30px; height: 30px; left: 90px; top: 90px;"></div><div class="cell dot" data-x="4" data-y="3" style="width: 30px; height: 30px; left: 120px; top: 90px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 150px; top: 90px;"></div><div class="cell dot" data-x="6" data-y="3" style="width: 30px; height: 30px; left: 180px; top: 90px;"></div><div class="cell dot" data-x="7" data-y="3" style="width: 30px; height: 30px; left: 210px; top: 90px;"></div><div class="cell dot" data-x="8" data-y="3" style="width: 30px; height: 30px; left: 240px; top: 90px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 270px; top: 90px;"></div><div class="cell dot" data-x="10" data-y="3" style="width: 30px; height: 30px; left: 300px; top: 90px;"></div><div class="cell dot" data-x="11" data-y="3" style="width: 30px; height: 30px; left: 330px; top: 90px;"></div><div class="cell dot" data-x="12" data-y="3" style="width: 30px; height: 30px; left: 360px; top: 90px;"></div><div class="cell power-pellet" data-x="13" data-y="3" style="width: 30px; height: 30px; left: 390px; top: 90px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 420px; top: 90px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 0px; top: 120px;"></div><div class="cell dot" data-x="1" data-y="4" style="width: 30px; height: 30px; left: 30px; top: 120px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 60px; top: 120px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 90px; top: 120px;"></div><div class="cell dot" data-x="4" data-y="4" style="width: 30px; height: 30px; left: 120px; top: 120px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 150px; top: 120px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 180px; top: 120px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 210px; top: 120px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 240px; top: 120px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 270px; top: 120px;"></div><div class="cell dot" data-x="10" data-y="4" style="width: 30px; height: 30px; left: 300px; top: 120px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 330px; top: 120px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 360px; top: 120px;"></div><div class="cell dot" data-x="13" data-y="4" style="width: 30px; height: 30px; left: 390px; top: 120px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 420px; top: 120px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 0px; top: 150px;"></div><div class="cell dot" data-x="1" data-y="5" style="width: 30px; height: 30px; left: 30px; top: 150px;"></div><div class="cell dot" data-x="2" data-y="5" style="width: 30px; height: 30px; left: 60px; top: 150px;"></div><div class="cell dot" data-x="3" data-y="5" style="width: 30px; height: 30px; left: 90px; top: 150px;"></div><div class="cell dot" data-x="4" data-y="5" style="width: 30px; height: 30px; left: 120px; top: 150px;"></div><div class="cell dot" data-x="5" data-y="5" style="width: 30px; height: 30px; left: 150px; top: 150px;"></div><div class="cell dot" data-x="6" data-y="5" style="width: 30px; height: 30px; left: 180px; top: 150px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 210px; top: 150px;"></div><div class="cell dot" data-x="8" data-y="5" style="width: 30px; height: 30px; left: 240px; top: 150px;"></div><div class="cell dot" data-x="9" data-y="5" style="width: 30px; height: 30px; left: 270px; top: 150px;"></div><div class="cell dot" data-x="10" data-y="5" style="width: 30px; height: 30px; left: 300px; top: 150px;"></div><div class="cell dot" data-x="11" data-y="5" style="width: 30px; height: 30px; left: 330px; top: 150px;"></div><div class="cell dot" data-x="12" data-y="5" style="width: 30px; height: 30px; left: 360px; top: 150px;"></div><div class="cell dot" data-x="13" data-y="5" style="width: 30px; height: 30px; left: 390px; top: 150px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 420px; top: 150px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 0px; top: 180px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 30px; top: 180px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 60px; top: 180px;"></div><div class="cell dot" data-x="3" data-y="6" style="width: 30px; height: 30px; left: 90px; top: 180px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 120px; top: 180px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 150px; top: 180px;"></div><div class="cell dot" data-x="6" data-y="6" style="width: 30px; height: 30px; left: 180px; top: 180px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 210px; top: 180px;"></div><div class="cell dot" data-x="8" data-y="6" style="width: 30px; height: 30px; left: 240px; top: 180px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 270px; top: 180px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 300px; top: 180px;"></div><div class="cell dot" data-x="11" data-y="6" style="width: 30px; height: 30px; left: 330px; top: 180px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 360px; top: 180px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 390px; top: 180px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 420px; top: 180px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 0px; top: 210px;"></div><div class="cell" style="width: 30px; height: 30px; left: 30px; top: 210px;"></div><div class="cell dot" data-x="2" data-y="7" style="width: 30px; height: 30px; left: 60px; top: 210px;"></div><div class="cell dot" data-x="3" data-y="7" style="width: 30px; height: 30px; left: 90px; top: 210px;"></div><div class="cell dot" data-x="4" data-y="7" style="width: 30px; height: 30px; left: 120px; top: 210px;"></div><div class="cell dot" data-x="5" data-y="7" style="width: 30px; height: 30px; left: 150px; top: 210px;"></div><div class="cell dot" data-x="6" data-y="7" style="width: 30px; height: 30px; left: 180px; top: 210px;"></div><div class="cell" style="width: 30px; height: 30px; left: 210px; top: 210px;"></div><div class="cell dot" data-x="8" data-y="7" style="width: 30px; height: 30px; left: 240px; top: 210px;"></div><div class="cell dot" data-x="9" data-y="7" style="width: 30px; height: 30px; left: 270px; top: 210px;"></div><div class="cell dot" data-x="10" data-y="7" style="width: 30px; height: 30px; left: 300px; top: 210px;"></div><div class="cell dot" data-x="11" data-y="7" style="width: 30px; height: 30px; left: 330px; top: 210px;"></div><div class="cell dot" data-x="12" data-y="7" style="width: 30px; height: 30px; left: 360px; top: 210px;"></div><div class="cell" style="width: 30px; height: 30px; left: 390px; top: 210px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 420px; top: 210px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 0px; top: 240px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 30px; top: 240px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 60px; top: 240px;"></div><div class="cell dot" data-x="3" data-y="8" style="width: 30px; height: 30px; left: 90px; top: 240px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 120px; top: 240px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 150px; top: 240px;"></div><div class="cell dot" data-x="6" data-y="8" style="width: 30px; height: 30px; left: 180px; top: 240px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 210px; top: 240px;"></div><div class="cell dot" data-x="8" data-y="8" style="width: 30px; height: 30px; left: 240px; top: 240px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 270px; top: 240px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 300px; top: 240px;"></div><div class="cell dot" data-x="11" data-y="8" style="width: 30px; height: 30px; left: 330px; top: 240px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 360px; top: 240px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 390px; top: 240px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 420px; top: 240px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 0px; top: 270px;"></div><div class="cell dot" data-x="1" data-y="9" style="width: 30px; height: 30px; left: 30px; top: 270px;"></div><div class="cell dot" data-x="2" data-y="9" style="width: 30px; height: 30px; left: 60px; top: 270px;"></div><div class="cell dot" data-x="3" data-y="9" style="width: 30px; height: 30px; left: 90px; top: 270px;"></div><div class="cell dot" data-x="4" data-y="9" style="width: 30px; height: 30px; left: 120px; top: 270px;"></div><div class="cell dot" data-x="5" data-y="9" style="width: 30px; height: 30px; left: 150px; top: 270px;"></div><div class="cell dot" data-x="6" data-y="9" style="width: 30px; height: 30px; left: 180px; top: 270px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 210px; top: 270px;"></div><div class="cell" data-x="8" data-y="9" style="width: 30px; height: 30px; left: 240px; top: 270px;"></div><div class="cell" data-x="9" data-y="9" style="width: 30px; height: 30px; left: 270px; top: 270px;"></div><div class="cell" data-x="10" data-y="9" style="width: 30px; height: 30px; left: 300px; top: 270px;"></div><div class="cell" data-x="11" data-y="9" style="width: 30px; height: 30px; left: 330px; top: 270px;"></div><div class="cell" data-x="12" data-y="9" style="width: 30px; height: 30px; left: 360px; top: 270px;"></div><div class="cell" data-x="13" data-y="9" style="width: 30px; height: 30px; left: 390px; top: 270px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 420px; top: 270px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 0px; top: 300px;"></div><div class="cell dot" data-x="1" data-y="10" style="width: 30px; height: 30px; left: 30px; top: 300px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 60px; top: 300px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 90px; top: 300px;"></div><div class="cell dot" data-x="4" data-y="10" style="width: 30px; height: 30px; left: 120px; top: 300px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 150px; top: 300px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 180px; top: 300px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 210px; top: 300px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 240px; top: 300px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 270px; top: 300px;"></div><div class="cell dot" data-x="10" data-y="10" style="width: 30px; height: 30px; left: 300px; top: 300px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 330px; top: 300px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 360px; top: 300px;"></div><div class="cell dot" data-x="13" data-y="10" style="width: 30px; height: 30px; left: 390px; top: 300px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 420px; top: 300px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 0px; top: 330px;"></div><div class="cell power-pellet" data-x="1" data-y="11" style="width: 30px; height: 30px; left: 30px; top: 330px;"></div><div class="cell dot" data-x="2" data-y="11" style="width: 30px; height: 30px; left: 60px; top: 330px;"></div><div class="cell dot" data-x="3" data-y="11" style="width: 30px; height: 30px; left: 90px; top: 330px;"></div><div class="cell dot" data-x="4" data-y="11" style="width: 30px; height: 30px; left: 120px; top: 330px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 150px; top: 330px;"></div><div class="cell dot" data-x="6" data-y="11" style="width: 30px; height: 30px; left: 180px; top: 330px;"></div><div class="cell dot" data-x="7" data-y="11" style="width: 30px; height: 30px; left: 210px; top: 330px;"></div><div class="cell dot" data-x="8" data-y="11" style="width: 30px; height: 30px; left: 240px; top: 330px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 270px; top: 330px;"></div><div class="cell dot" data-x="10" data-y="11" style="width: 30px; height: 30px; left: 300px; top: 330px;"></div><div class="cell dot" data-x="11" data-y="11" style="width: 30px; height: 30px; left: 330px; top: 330px;"></div><div class="cell dot" data-x="12" data-y="11" style="width: 30px; height: 30px; left: 360px; top: 330px;"></div><div class="cell power-pellet" data-x="13" data-y="11" style="width: 30px; height: 30px; left: 390px; top: 330px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 420px; top: 330px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 0px; top: 360px;"></div><div class="cell dot" data-x="1" data-y="12" style="width: 30px; height: 30px; left: 30px; top: 360px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 60px; top: 360px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 90px; top: 360px;"></div><div class="cell dot" data-x="4" data-y="12" style="width: 30px; height: 30px; left: 120px; top: 360px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 150px; top: 360px;"></div><div class="cell dot" data-x="6" data-y="12" style="width: 30px; height: 30px; left: 180px; top: 360px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 210px; top: 360px;"></div><div class="cell dot" data-x="8" data-y="12" style="width: 30px; height: 30px; left: 240px; top: 360px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 270px; top: 360px;"></div><div class="cell dot" data-x="10" data-y="12" style="width: 30px; height: 30px; left: 300px; top: 360px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 330px; top: 360px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 360px; top: 360px;"></div><div class="cell dot" data-x="13" data-y="12" style="width: 30px; height: 30px; left: 390px; top: 360px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 420px; top: 360px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 0px; top: 390px;"></div><div class="cell dot" data-x="1" data-y="13" style="width: 30px; height: 30px; left: 30px; top: 390px;"></div><div class="cell dot" data-x="2" data-y="13" style="width: 30px; height: 30px; left: 60px; top: 390px;"></div><div class="cell dot" data-x="3" data-y="13" style="width: 30px; height: 30px; left: 90px; top: 390px;"></div><div class="cell dot" data-x="4" data-y="13" style="width: 30px; height: 30px; left: 120px; top: 390px;"></div><div class="cell dot" data-x="5" data-y="13" style="width: 30px; height: 30px; left: 150px; top: 390px;"></div><div class="cell dot" data-x="6" data-y="13" style="width: 30px; height: 30px; left: 180px; top: 390px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 210px; top: 390px;"></div><div class="cell dot" data-x="8" data-y="13" style="width: 30px; height: 30px; left: 240px; top: 390px;"></div><div class="cell dot" data-x="9" data-y="13" style="width: 30px; height: 30px; left: 270px; top: 390px;"></div><div class="cell dot" data-x="10" data-y="13" style="width: 30px; height: 30px; left: 300px; top: 390px;"></div><div class="cell dot" data-x="11" data-y="13" style="width: 30px; height: 30px; left: 330px; top: 390px;"></div><div class="cell dot" data-x="12" data-y="13" style="width: 30px; height: 30px; left: 360px; top: 390px;"></div><div class="cell dot" data-x="13" data-y="13" style="width: 30px; height: 30px; left: 390px; top: 390px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 420px; top: 390px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 0px; top: 420px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 30px; top: 420px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 60px; top: 420px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 90px; top: 420px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 120px; top: 420px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 150px; top: 420px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 180px; top: 420px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 210px; top: 420px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 240px; top: 420px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 270px; top: 420px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 300px; top: 420px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 330px; top: 420px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 360px; top: 420px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 390px; top: 420px;"></div><div class="cell wall" style="width: 30px; height: 30px; left: 420px; top: 420px;"></div><div id="pacman" class="pacman" data-x="7" data-y="9" data-direction="right" data-next-direction="right" style="width: 30px; height: 30px; left: 210px; top: 270px; transform: rotate(0deg); clip-path: polygon(0px 0px, 100% 0px, 100% 100%, 0px 100%);"></div><div class="ghost" data-x="6" data-y="7" data-direction="up" data-base-color="#e94560" style="width: 30px; height: 30px; background-color: rgb(233, 69, 96); left: 180px; top: 210px;"><div class="ghost-eyes"><div class="ghost-eye"></div><div class="ghost-eye"></div></div></div><div class="ghost" data-x="7" data-y="7" data-direction="down" data-base-color="#0ead69" style="width: 30px; height: 30px; background-color: rgb(14, 173, 105); left: 210px; top: 210px;"><div class="ghost-eyes"><div class="ghost-eye"></div><div class="ghost-eye"></div></div></div><div class="ghost" data-x="8" data-y="7" data-direction="down" data-base-color="#00b4d8" style="width: 30px; height: 30px; background-color: rgb(0, 180, 216); left: 240px; top: 210px;"><div class="ghost-eyes"><div class="ghost-eye"></div><div class="ghost-eye"></div></div></div><div class="ghost" data-x="7" data-y="6" data-direction="left" data-base-color="#ff9e00" style="width: 30px; height: 30px; background-color: rgb(255, 158, 0); left: 210px; top: 180px;"><div class="ghost-eyes"><div class="ghost-eye"></div><div class="ghost-eye"></div></div></div></div>
<div class="controls">
<div class="control-btn up-btn" id="up-btn">↑</div>
<div class="control-btn left-btn" id="left-btn">←</div>
<div class="control-btn down-btn" id="down-btn">↓</div>
<div class="control-btn right-btn" id="right-btn">→</div>
</div>
<!-- Copy Code Button -->
<button class="copy-code-btn" id="copy-code-btn">
<svg class="copy-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
<path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>
</svg>
Get Code
<span class="tooltip">Click to view and copy code</span>
</button>
<!-- Code Modal -->
<div class="code-modal" id="code-modal">
<div class="code-container">
<div class="code-header">
<div>Pac-Man Game Code</div>
<div>
<button class="copy-btn" id="modal-copy-btn">Copy All</button>
<button class="close-btn" id="close-modal-btn">×</button>
</div>
</div>
<div class="code-content" id="code-content"></div>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', () => {
// Game configuration
const CELL_SIZE = 30;
const GRID_WIDTH = 15;
const GRID_HEIGHT = 15;
const PACMAN_SPEED = 250; // ms per cell (slower)
const GHOST_SPEED = 350; // ms per cell (slower)
const FRIGHTENED_TIME = 10000; // ms (longer)
const FRIGHTENED_SPEED = 450; // ms per cell (even slower when frightened)
const INITIAL_LIVES = 3;
// Game state
let score = 0;
let level = 1;
let lives = INITIAL_LIVES;
let gameRunning = true;
let powerPelletActive = false;
let powerPelletTimer = null;
let dotsCollected = 0;
let totalDots = 0;
let pacmanMouthOpen = true;
let pacmanMouthInterval;
// Initialize game container size
const gameContainer = document.getElementById('game-container');
gameContainer.style.width = `${CELL_SIZE * GRID_WIDTH}px`;
gameContainer.style.height = `${CELL_SIZE * GRID_HEIGHT}px`;
// Define the maze layout
// 0: empty (dot), 1: wall, 2: power pellet, 3: empty (no dot)
const maze = [
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1],
[1, 2, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 2, 1],
[1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1],
[1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1],
[1, 3, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 3, 1],
[1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1],
[1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1],
[1, 2, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 2, 1],
[1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
];
// Create the maze
function createMaze() {
for (let y = 0; y < GRID_HEIGHT; y++) {
for (let x = 0; x < GRID_WIDTH; x++) {
const cell = document.createElement('div');
cell.className = 'cell';
cell.style.width = `${CELL_SIZE}px`;
cell.style.height = `${CELL_SIZE}px`;
cell.style.left = `${x * CELL_SIZE}px`;
cell.style.top = `${y * CELL_SIZE}px`;
if (maze[y][x] === 1) {
cell.classList.add('wall');
} else if (maze[y][x] === 0) {
cell.classList.add('dot');
cell.dataset.x = x;
cell.dataset.y = y;
totalDots++;
} else if (maze[y][x] === 2) {
cell.classList.add('power-pellet');
cell.dataset.x = x;
cell.dataset.y = y;
totalDots++;
}
gameContainer.appendChild(cell);
}
}
}
// Create Pac-Man
function createPacman() {
const pacman = document.createElement('div');
pacman.id = 'pacman';
pacman.className = 'pacman';
pacman.style.width = `${CELL_SIZE}px`;
pacman.style.height = `${CELL_SIZE}px`;
// Start position
const startX = 7;
const startY = 9;
pacman.style.left = `${startX * CELL_SIZE}px`;
pacman.style.top = `${startY * CELL_SIZE}px`;
pacman.dataset.x = startX;
pacman.dataset.y = startY;
pacman.dataset.direction = 'right';
pacman.dataset.nextDirection = 'right';
gameContainer.appendChild(pacman);
// Animation for Pac-Man's mouth
pacmanMouthInterval = setInterval(() => {
if (!gameRunning) return;
pacmanMouthOpen = !pacmanMouthOpen;
if (pacmanMouthOpen) {
pacman.style.clipPath = 'polygon(0 0, 100% 50%, 0 100%, 0 0)';
} else {
pacman.style.clipPath = 'polygon(0 0, 100% 0, 100% 100%, 0 100%)';
}
}, 300); // Slower mouth animation
return pacman;
}
// Create ghosts
function createGhosts() {
const ghostColors = ['#e94560', '#0ead69', '#00b4d8', '#ff9e00'];
const ghosts = [];
// Ghost starting positions
const positions = [
{ x: 6, y: 7 },
{ x: 7, y: 7 },
{ x: 8, y: 7 },
{ x: 7, y: 6 }
];
for (let i = 0; i < 4; i++) {
const ghost = document.createElement('div');
ghost.className = 'ghost';
ghost.style.width = `${CELL_SIZE}px`;
ghost.style.height = `${CELL_SIZE}px`;
ghost.style.backgroundColor = ghostColors[i];
ghost.style.left = `${positions[i].x * CELL_SIZE}px`;
ghost.style.top = `${positions[i].y * CELL_SIZE}px`;
ghost.dataset.x = positions[i].x;
ghost.dataset.y = positions[i].y;
ghost.dataset.direction = ['up', 'down', 'left', 'right'][Math.floor(Math.random() * 4)];
ghost.dataset.baseColor = ghostColors[i];
// Add ghost eyes
const eyes = document.createElement('div');
eyes.className = 'ghost-eyes';
const leftEye = document.createElement('div');
leftEye.className = 'ghost-eye';
const rightEye = document.createElement('div');
rightEye.className = 'ghost-eye';
eyes.appendChild(leftEye);
eyes.appendChild(rightEye);
ghost.appendChild(eyes);
gameContainer.appendChild(ghost);
ghosts.push(ghost);
}
return ghosts;
}
// Create lives display
function createLivesDisplay() {
const livesDisplay = document.getElementById('lives-display');
livesDisplay.innerHTML = '';
for (let i = 0; i < lives; i++) {
const life = document.createElement('div');
life.className = 'life';
livesDisplay.appendChild(life);
}
}
// Move Pac-Man
function movePacman() {
if (!gameRunning) return;
const pacman = document.getElementById('pacman');
const x = parseInt(pacman.dataset.x);
const y = parseInt(pacman.dataset.y);
const direction = pacman.dataset.direction;
const nextDirection = pacman.dataset.nextDirection;
// Try to change direction if requested
if (nextDirection !== direction) {
let canChangeDirection = false;
let newX = x;
let newY = y;
switch (nextDirection) {
case 'up':
newY = y - 1;
break;
case 'down':
newY = y + 1;
break;
case 'left':
newX = x - 1;
break;
case 'right':
newX = x + 1;
break;
}
if (newX >= 0 && newX < GRID_WIDTH && newY >= 0 && newY < GRID_HEIGHT && maze[newY][newX] !== 1) {
pacman.dataset.direction = nextDirection;
canChangeDirection = true;
}
}
// Move in current direction
let newX = x;
let newY = y;
switch (pacman.dataset.direction) {
case 'up':
newY = y - 1;
pacman.style.transform = 'rotate(-90deg)';
break;
case 'down':
newY = y + 1;
pacman.style.transform = 'rotate(90deg)';
break;
case 'left':
newX = x - 1;
pacman.style.transform = 'rotate(180deg)';
break;
case 'right':
newX = x + 1;
pacman.style.transform = 'rotate(0deg)';
break;
}
// Check if the new position is valid (not a wall)
if (newX >= 0 && newX < GRID_WIDTH && newY >= 0 && newY < GRID_HEIGHT && maze[newY][newX] !== 1) {
pacman.dataset.x = newX;
pacman.dataset.y = newY;
pacman.style.left = `${newX * CELL_SIZE}px`;
pacman.style.top = `${newY * CELL_SIZE}px`;
// Check for dot collision
checkDotCollision(newX, newY);
// Check for ghost collision
checkGhostCollision();
}
setTimeout(movePacman, PACMAN_SPEED);
}
// Move ghosts
function moveGhosts() {
if (!gameRunning) return;
const ghosts = document.querySelectorAll('.ghost');
const pacman = document.getElementById('pacman');
const pacmanX = parseInt(pacman.dataset.x);
const pacmanY = parseInt(pacman.dataset.y);
ghosts.forEach(ghost => {
const x = parseInt(ghost.dataset.x);
const y = parseInt(ghost.dataset.y);
let direction = ghost.dataset.direction;
// Determine possible directions (not walls)
const possibleDirections = [];
if (y > 0 && maze[y-1][x] !== 1) possibleDirections.push('up');
if (y < GRID_HEIGHT - 1 && maze[y+1][x] !== 1) possibleDirections.push('down');
if (x > 0 && maze[y][x-1] !== 1) possibleDirections.push('left');
if (x < GRID_WIDTH - 1 && maze[y][x+1] !== 1) possibleDirections.push('right');
// Remove opposite direction to avoid back-and-forth movement
const oppositeDirections = {
'up': 'down',
'down': 'up',
'left': 'right',
'right': 'left'
};
const filteredDirections = possibleDirections.filter(dir =>
dir !== oppositeDirections[direction] || possibleDirections.length === 1
);
// Choose a direction based on game state
if (powerPelletActive) {
// Run away from Pac-Man when frightened
direction = getDirectionAwayFromPacman(x, y, pacmanX, pacmanY, filteredDirections);
} else {
// 60% chance to move towards Pac-Man, 40% random (less aggressive)
if (Math.random() < 0.6) {
direction = getDirectionTowardsPacman(x, y, pacmanX, pacmanY, filteredDirections);
} else {
direction = getRandomDirection(filteredDirections);
}
}
ghost.dataset.direction = direction;
// Move ghost
let newX = x;
let newY = y;
switch (direction) {
case 'up':
newY = y - 1;
break;
case 'down':
newY = y + 1;
break;
case 'left':
newX = x - 1;
break;
case 'right':
newX = x + 1;
break;
}
ghost.dataset.x = newX;
ghost.dataset.y = newY;
ghost.style.left = `${newX * CELL_SIZE}px`;
ghost.style.top = `${newY * CELL_SIZE}px`;
});
// Check for ghost collision after all ghosts have moved
checkGhostCollision();
setTimeout(moveGhosts, powerPelletActive ? FRIGHTENED_SPEED : GHOST_SPEED);
}
// Get random direction
function getRandomDirection(directions) {
return directions[Math.floor(Math.random() * directions.length)];
}
// Get direction towards Pac-Man
function getDirectionTowardsPacman(ghostX, ghostY, pacmanX, pacmanY, possibleDirections) {
// Calculate horizontal and vertical distance
const horizontalDist = pacmanX - ghostX;
const verticalDist = pacmanY - ghostY;
// Determine preferred directions based on distance
let preferredDirections = [];
if (Math.abs(horizontalDist) > Math.abs(verticalDist)) {
// Prefer horizontal movement
if (horizontalDist > 0 && possibleDirections.includes('right')) {
preferredDirections.push('right');
} else if (horizontalDist < 0 && possibleDirections.includes('left')) {
preferredDirections.push('left');
}
if (verticalDist > 0 && possibleDirections.includes('down')) {
preferredDirections.push('down');
} else if (verticalDist < 0 && possibleDirections.includes('up')) {
preferredDirections.push('up');
}
} else {
// Prefer vertical movement
if (verticalDist > 0 && possibleDirections.includes('down')) {
preferredDirections.push('down');
} else if (verticalDist < 0 && possibleDirections.includes('up')) {
preferredDirections.push('up');
}
if (horizontalDist > 0 && possibleDirections.includes('right')) {
preferredDirections.push('right');
} else if (horizontalDist < 0 && possibleDirections.includes('left')) {
preferredDirections.push('left');
}
}
// If we have preferred directions, choose one randomly
if (preferredDirections.length > 0) {
return preferredDirections[Math.floor(Math.random() * preferredDirections.length)];
}
// Fallback to any possible direction
return getRandomDirection(possibleDirections);
}
// Get direction away from Pac-Man
function getDirectionAwayFromPacman(ghostX, ghostY, pacmanX, pacmanY, possibleDirections) {
// Calculate horizontal and vertical distance
const horizontalDist = pacmanX - ghostX;
const verticalDist = pacmanY - ghostY;
// Determine preferred directions based on distance (opposite of towards)
let preferredDirections = [];
if (Math.abs(horizontalDist) > Math.abs(verticalDist)) {
// Prefer horizontal movement away
if (horizontalDist < 0 && possibleDirections.includes('right')) {
preferredDirections.push('right');
} else if (horizontalDist > 0 && possibleDirections.includes('left')) {
preferredDirections.push('left');
}
if (verticalDist < 0 && possibleDirections.includes('down')) {
preferredDirections.push('down');
} else if (verticalDist > 0 && possibleDirections.includes('up')) {
preferredDirections.push('up');
}
} else {
// Prefer vertical movement away
if (verticalDist < 0 && possibleDirections.includes('down')) {
preferredDirections.push('down');
} else if (verticalDist > 0 && possibleDirections.includes('up')) {
preferredDirections.push('up');
}
if (horizontalDist < 0 && possibleDirections.includes('right')) {
preferredDirections.push('right');
} else if (horizontalDist > 0 && possibleDirections.includes('left')) {
preferredDirections.push('left');
}
}
// If we have preferred directions, choose one randomly
if (preferredDirections.length > 0) {
return preferredDirections[Math.floor(Math.random() * preferredDirections.length)];
}
// Fallback to any possible direction
return getRandomDirection(possibleDirections);
}
// Check for dot collision
function checkDotCollision(x, y) {
const dot = document.querySelector(`.dot[data-x="${x}"][data-y="${y}"]`);
if (dot) {
dot.classList.remove('dot');
updateScore(10);
dotsCollected++;
}
const powerPellet = document.querySelector(`.power-pellet[data-x="${x}"][data-y="${y}"]`);
if (powerPellet) {
powerPellet.classList.remove('power-pellet');
activatePowerPellet();
updateScore(50);
dotsCollected++;
}
// Check if all dots are collected
if (dotsCollected >= totalDots) {
levelComplete();
}
}
// Activate power pellet
function activatePowerPellet() {
powerPelletActive = true;
const ghosts = document.querySelectorAll('.ghost');
ghosts.forEach(ghost => {
ghost.classList.add('frightened');
});
// Clear existing timer if there is one
if (powerPelletTimer) {
clearTimeout(powerPelletTimer);
}
// Set timer to deactivate power pellet
powerPelletTimer = setTimeout(() => {
powerPelletActive = false;
ghosts.forEach(ghost => {
ghost.classList.remove('frightened');
});
}, FRIGHTENED_TIME);
}
// Check for ghost collision
function checkGhostCollision() {
if (!gameRunning) return;
const pacman = document.getElementById('pacman');
const pacmanX = parseInt(pacman.dataset.x);
const pacmanY = parseInt(pacman.dataset.y);
const ghosts = document.querySelectorAll('.ghost');
ghosts.forEach(ghost => {
const ghostX = parseInt(ghost.dataset.x);
const ghostY = parseInt(ghost.dataset.y);
if (pacmanX === ghostX && pacmanY === ghostY) {
if (powerPelletActive) {
// Pac-Man eats the ghost
resetGhost(ghost);
updateScore(200);
} else {
// Ghost catches Pac-Man
loseLife();
}
}
});
}
// Reset ghost position
function resetGhost(ghost) {
const startPositions = [
{ x: 6, y: 7 },
{ x: 7, y: 7 },
{ x: 8, y: 7 },
{ x: 7, y: 6 }
];
const position = startPositions[Math.floor(Math.random() * startPositions.length)];
ghost.dataset.x = position.x;
ghost.dataset.y = position.y;
ghost.style.left = `${position.x * CELL_SIZE}px`;
ghost.style.top = `${position.y * CELL_SIZE}px`;
}
// Update score
function updateScore(points) {
score += points;
document.getElementById('score').textContent = score;
document.getElementById('final-score').textContent = score;
}
// Lose a life
function loseLife() {
lives--;
createLivesDisplay();
if (lives <= 0) {
gameOver(false);
return;
}
// Reset positions
resetPositions();
// Brief pause before continuing
gameRunning = false;
setTimeout(() => {
gameRunning = true;
}, 1000);
}
// Reset positions after losing a life
function resetPositions() {
const pacman = document.getElementById('pacman');
// Reset Pac-Man
pacman.dataset.x = 7;
pacman.dataset.y = 9;
pacman.style.left = `${7 * CELL_SIZE}px`;
pacman.style.top = `${9 * CELL_SIZE}px`;
pacman.dataset.direction = 'right';
pacman.dataset.nextDirection = 'right';
pacman.style.transform = 'rotate(0deg)';
// Reset ghosts
const ghosts = document.querySelectorAll('.ghost');
const startPositions = [
{ x: 6, y: 7 },
{ x: 7, y: 7 },
{ x: 8, y: 7 },
{ x: 7, y: 6 }
];
ghosts.forEach((ghost, i) => {
ghost.classList.remove('frightened');
ghost.style.backgroundColor = ghost.dataset.baseColor;
ghost.dataset.x = startPositions[i].x;
ghost.dataset.y = startPositions[i].y;
ghost.style.left = `${startPositions[i].x * CELL_SIZE}px`;
ghost.style.top = `${startPositions[i].y * CELL_SIZE}px`;
ghost.dataset.direction = ['up', 'down', 'left', 'right'][Math.floor(Math.random() * 4)];
});
// Deactivate power pellet
powerPelletActive = false;
if (powerPelletTimer) {
clearTimeout(powerPelletTimer);
}
}
// Level complete
function levelComplete() {
gameRunning = false;
// Show level complete message
const levelCompleteMsg = document.createElement('div');
levelCompleteMsg.className = 'game-over-overlay visible';
levelCompleteMsg.innerHTML = `
<div>LEVEL COMPLETE!</div>
<div class="text-xl mt-2">Score: ${score}</div>
`;
gameContainer.appendChild(levelCompleteMsg);
// Start next level after delay
setTimeout(() => {
level++;
document.getElementById('level').textContent = level;
gameContainer.removeChild(levelCompleteMsg);
// Reset game for next level
resetGame();
gameRunning = true;
}, 2000);
}
// Reset game for next level
function resetGame() {
// Clear the game container
while (gameContainer.firstChild) {
if (gameContainer.firstChild.id === 'game-over') {
gameContainer.firstChild.classList.remove('visible');
break;
}
gameContainer.removeChild(gameContainer.firstChild);
}
// Reset dots collected
dotsCollected = 0;
totalDots = 0;
// Create new maze
createMaze();
// Create Pac-Man and ghosts
const pacman = createPacman();
const ghosts = createGhosts();
// Deactivate power pellet
powerPelletActive = false;
if (powerPelletTimer) {
clearTimeout(powerPelletTimer);
}
}
// Game over
function gameOver(win) {
gameRunning = false;
// Clear intervals
clearInterval(pacmanMouthInterval);
const gameOverOverlay = document.getElementById('game-over');
gameOverOverlay.classList.add('visible');
if (win) {
gameOverOverlay.querySelector('div').textContent = 'YOU WIN!';
}
}
// Restart game
function restartGame() {
// Reset game state
score = 0;
level = 1;
lives = INITIAL_LIVES;
gameRunning = true;
powerPelletActive = false;
dotsCollected = 0;
totalDots = 0;
// Update displays
document.getElementById('score').textContent = '0';
document.getElementById('level').textContent = '1';
createLivesDisplay();
// Hide game over overlay
document.getElementById('game-over').classList.remove('visible');
// Reset game
resetGame();
// Restart Pac-Man mouth animation
pacmanMouthInterval = setInterval(() => {
if (!gameRunning) return;
pacmanMouthOpen = !pacmanMouthOpen;
const pacman = document.getElementById('pacman');
if (pacmanMouthOpen) {
pacman.style.clipPath = 'polygon(0 0, 100% 50%, 0 100%, 0 0)';
} else {
pacman.style.clipPath = 'polygon(0 0, 100% 0, 100% 100%, 0 100%)';
}
}, 300);
// Start movement
setTimeout(movePacman, PACMAN_SPEED);
setTimeout(moveGhosts, GHOST_SPEED);
}
// Initialize game
function initGame() {
createMaze();
createPacman();
createGhosts();
createLivesDisplay();
// Start movement
setTimeout(movePacman, PACMAN_SPEED);
setTimeout(moveGhosts, GHOST_SPEED);
// Keyboard controls
document.addEventListener('keydown', (e) => {
if (!gameRunning) return;
const pacman = document.getElementById('pacman');
switch (e.key) {
case 'ArrowUp':
pacman.dataset.nextDirection = 'up';
break;
case 'ArrowDown':
pacman.dataset.nextDirection = 'down';
break;
case 'ArrowLeft':
pacman.dataset.nextDirection = 'left';
break;
case 'ArrowRight':
pacman.dataset.nextDirection = 'right';
break;
}
});
// Touch controls
document.getElementById('up-btn').addEventListener('click', () => {
if (gameRunning) document.getElementById('pacman').dataset.nextDirection = 'up';
});
document.getElementById('down-btn').addEventListener('click', () => {
if (gameRunning) document.getElementById('pacman').dataset.nextDirection = 'down';
});
document.getElementById('left-btn').addEventListener('click', () => {
if (gameRunning) document.getElementById('pacman').dataset.nextDirection = 'left';
});
document.getElementById('right-btn').addEventListener('click', () => {
if (gameRunning) document.getElementById('pacman').dataset.nextDirection = 'right';
});
// Restart button
document.getElementById('restart-btn').addEventListener('click', restartGame);
}
// Start the game
initGame();
// Code copy functionality
const copyCodeBtn = document.getElementById('copy-code-btn');
const codeModal = document.getElementById('code-modal');
const closeModalBtn = document.getElementById('close-modal-btn');
const modalCopyBtn = document.getElementById('modal-copy-btn');
const codeContent = document.getElementById('code-content');
// Get the full HTML code
function getFullCode() {
return document.documentElement.outerHTML;
}
// Show code modal
copyCodeBtn.addEventListener('click', () => {
codeContent.textContent = getFullCode();
codeModal.classList.add('visible');
});
// Close code modal
closeModalBtn.addEventListener('click', () => {
codeModal.classList.remove('visible');
});
// Copy code to clipboard
modalCopyBtn.addEventListener('click', () => {
const code = getFullCode();
navigator.clipboard.writeText(code).then(() => {
modalCopyBtn.textContent = 'Copied!';
setTimeout(() => {
modalCopyBtn.textContent = 'Copy All';
}, 2000);
}).catch(err => {
console.error('Failed to copy: ', err);
modalCopyBtn.textContent = 'Failed to copy';
setTimeout(() => {
modalCopyBtn.textContent = 'Copy All';
}, 2000);
});
});
// Close modal when clicking outside
codeModal.addEventListener('click', (e) => {
if (e.target === codeModal) {
codeModal.classList.remove('visible');
}
});
});
</script>
<script>(function(){function c(){var b=a.contentDocument||a.contentWindow.document;if(b){var d=b.createElement('script');d.innerHTML="window.__CF$cv$params={r:'94ae61820420f1f8',t:'MTc0OTExMjk5MS4wMDAwMDA='};var a=document.createElement('script');a.nonce='';a.src='/cdn-cgi/challenge-platform/scripts/jsd/main.js';document.getElementsByTagName('head')[0].appendChild(a);";b.getElementsByTagName('head')[0].appendChild(d)}}if(document.body){var a=document.createElement('iframe');a.height=1;a.width=1;a.style.position='absolute';a.style.top=0;a.style.left=0;a.style.border='none';a.style.visibility='hidden';document.body.appendChild(a);if('loading'!==document.readyState)c();else if(window.addEventListener)document.addEventListener('DOMContentLoaded',c);else{var e=document.onreadystatechange||function(){};document.onreadystatechange=function(b){e(b);'loading'!==document.readyState&&(document.onreadystatechange=e,c())}}}})();</script><iframe height="1" width="1" style="position: absolute; top: 0px; left: 0px; border: none; visibility: hidden;"></iframe>
</body></html>