scroll-game

Scroll Game:Dark Run

We'll show you how to use just HTML, CSS, and JavaScript to create a captivating scrolling game. You may create a dynamic game that engages players and highlights your web development abilities with just a few lines of code."

  1. Improves knowledge of the foundational concepts of JavaScript, such as DOM manipulation, event management, and animations.
  2. studying the fundamentals of game design, including state management, scoring schemes, and collision detection.
  3. gaining expertise in the setup of HTML elements and the application of CSS styling to produce aesthetically pleasing user interfaces.
  4. making a concrete project that you can include in a portfolio to show prospective employers that you have real-world experience.

How to Design:

Make a basic HTML page that has containers for the game's elements (obstacles, hero, etc.).


The game elements will be styled using CSS to make sure they are aesthetically pleasing and placed properly.


To handle the moving, leaping, collision detection, and scoring aspects of the game, write JavaScript.


Check the game frequently for glitches and performance problems, and fix anything that needs fixing.To improve gameplay, add more elements like power-ups, more obstacles, or music effects.


			<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>CodePen -  Scroll Game: Dark Run</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css"><link rel="stylesheet" href="./style.css">

</head>
<body>
<!-- partial:index.partial.html -->
<body>

	<link rel="preload" href="https://drive.google.com/thumbnail?id=1LfRNG8pJK8F0lYtXH9tfGT70l4IW-66S&sz=w1000" as="image">
	<link rel="preload" href="https://drive.google.com/thumbnail?id=1oxPBLaiwJR1QzOrLC4Z_dt5nFl56RzoN&sz=w1000" as="image">
	<link rel="preload" href="https://drive.google.com/thumbnail?id=1tbtI6RBfVzPV8TbA-Ww44E5Dz5_Ek3m0&sz=w1000" as="image">
	<link rel="preload" href="https://drive.google.com/thumbnail?id=1eIBkrLk1cMlnsLETX1sLeqOc0On0D2R2&sz=w1000" as="image">

	<div class="start screen">
		<div class="main-title row d-flex justify-content-center align-items-center">
			<div class="col-12">
				<div class="d-flex justify-content-center">
					<h1>Scroll Game: Dark Run</h1>
				</div>
			</div>
			<div class="col-12">
				<div class="d-flex justify-content-center">
					<p>A Horizontal Scrolling Journey Through the Darkness to Find Home. Scroll to Start.</p>

				</div>
			</div>
			<div class="col-12 mt-5">
				<div class="d-flex justify-content-center">
					<div class="mouse-scroll">
						<div class="mouse">
							<div class="wheel"></div>
						</div>
						<div class="arrow-left"></div>
						<div class="arrow-right"></div>
					</div>
				</div>
			</div>
		</div>
	</div>

	<div class="win screen">
		<div class="main-title row d-flex justify-content-center align-items-center">
			<div class="col-12">
				<div class="d-flex justify-content-center">
					<h1>Congratulations!</h1>
				</div>
			</div>
			<div class="col-12">
				<div class="d-flex justify-content-center">
					<p>You arrived home alive.</p>

				</div>
			</div>
			<div class="col-12 mt-3 mb-4">
				<div class="d-flex justify-content-center">
					<button class="btn btn-light restartButton">Restart</button>
				</div>
			</div>
			<div class="col-12 scores">
				<div class="d-flex justify-content-center">
					<p>Time: <span class="chronometer">00:00</span></p>
				</div>
			</div>
			<div class="col-12">
				<div class="d-flex justify-content-center">
					<p>Best Time: <span class="highestScore">00:00</span></p>
				</div>
			</div>
		</div>
	</div>

	<div class="game-over screen">
		<div class="main-title row d-flex justify-content-center align-items-center">
			<div class="col-12">
				<div class="d-flex justify-content-center">
					<h1>Game Over</h1>
				</div>
			</div>

			<div class="col-12">
				<div class="d-flex justify-content-center">
					<p>You're Dead.</p>
				</div>
			</div>
			<div class="col-12">
				<div class="d-flex justify-content-center">
					<button class="btn btn-light restartButton">Restart</button>
				</div>
			</div>

		</div>
	</div>

	<div id="gameContainer">

		<div id="left-wall" class="obstacle" style="left: -100px; bottom: 0;"></div>
		<div id="hero"></div>
		<img src="https://drive.google.com/thumbnail?id=16xQ76yQgLy6N1Z0ERHa8I4Wluq2OGreF&sz=w1000" class="object sign">
		<div class="trees">
			<img src="https://drive.google.com/thumbnail?id=1SSZ8Gl9nSo96RhvWDNlxsaYSWUFQu6h4&sz=w1000" class="object tree">
			<img src="https://drive.google.com/thumbnail?id=1LItLexgTPQ9Fno_TgPMJIZb0StcqxgD6&sz=w1000" class="object tree">
			<img src="https://drive.google.com/thumbnail?id=1iQRUmpRWMGjesukrLxJXxQvkAehk_k8P&sz=w1000" class="object tree">
			<img src="https://drive.google.com/thumbnail?id=1o-QjWIBLe95xX303qKG6zE1NitfCrgUT&sz=w2000" class="object tree silhouette">
			<img src="https://drive.google.com/thumbnail?id=1o-QjWIBLe95xX303qKG6zE1NitfCrgUT&sz=w2000" class="object tree silhouette">

			<div src="https://drive.google.com/thumbnail?id=1VTozcNB0JwK3K8PpFjzCkxOCwzOfDEU7&sz=w1000" class="obstacle spider silhouette"></div>

		</div>
		<div class="object house">
			<div class="chimney">
				<div class="smoke"></div>
				<div class="smoke"></div>
				<div class="smoke"></div>
				<div class="smoke"></div>
				<div class="smoke"></div>
				<div class="smoke"></div>
				<div class="smoke"></div>
			</div>
		</div>

		<div class="hammers">
			<div class="obstacle hammer" style="left: 1500px"></div>
			<div class="obstacle hammer" style="left: 1600px"></div>
			<div class="obstacle hammer" style="left: 1700px"></div>
			<div class="obstacle hammer" style="left: 4000px"></div>
			<div class="obstacle hammer" style="left: 4100px"></div>
			<div class="obstacle hammer" style="left: 4200px"></div>
			<div class="obstacle hammer" style="left: 4300px"></div>
			<div class="obstacle hammer" style="left: 4400px"></div>
			<div class="obstacle hammer" style="left: 7700px"></div>
		</div>
		<div class="saws">
			<div class="obstacle saw" style="left: 2600px; "></div>
			<div class="obstacle saw" style="left: 5500px; "></div>
		</div>
		<div class="bushes">
			<div class="bush silhouette" style="left: 3500px; bottom: 0;"></div>
			<div class="bush silhouette" style="left: 5200px; bottom: 0;"></div>
			<div class="bush silhouette" style="left: 6000px; bottom: 0;"></div>
			<div class="bush silhouette" style="left: 6500px; bottom: 0;"></div>
			<div class="bush silhouette" style="left: 6800px; bottom: 0;"></div>
		</div>
		<div class="birds">
			<div class="obstacle bird" style="left: 700px; top: 40%;"></div>
			<div class="obstacle bird" style="left: 500px; top: 50%;"></div>
			<div class="obstacle bird" style="left: 100px; top: 60%;"></div>
			<div class="obstacle bird" style="left: 200px; top: 75%;"></div>
		</div>
		<div id="finishLine" style="left: 10000px"></div>
		<div class="floor" style="left: 0; bottom: 0;"></div>
		<div id="top" style="left: 0; bottom: 0;"></div>
	</div>
	<div id="scores">
		<p>Time: <span id="chronometer">00:00</span></p>
		<p class="bestTime">Best Time: <span id="highestScore">00:00</span></p>
	</div>
</body>
<!-- partial -->
  <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script><script  src="./script.js"></script>

</body>
</html>

            
	

			@import url("https://fonts.googleapis.com/css2?family=Anton&display=swap");

body {
	margin: 0;
	overflow: hidden;
	font-family: "Anton", sans-serif;
}

#gameContainer {
	position: relative;
	width: 100%;
	height: 100vh;
	background: linear-gradient(to bottom, #87ceeb, #ffffff); /* sky background */
	overflow: hidden;
	background: url("https://drive.google.com/thumbnail?id=1_wfqi7bSM_iKIMx1sLNrS6aSx259sGrx&sz=w2000");
	background-repeat: no-repeat;
	background-size: cover;
	background-position: center center;
}

#left-wall {
	position: absolute;
	width: 2000px;
	height: calc(50% - 200px);
	margin-left: -2000px;
	background-color: black !important;
	top: calc(50% + 200px);
}
#left-wall::before {
	content: "";
	position: absolute;
	top: -400px;
	left: 0;
	width: 100%;
	height: 400px;
	background: url("https://drive.google.com/thumbnail?id=1o-QjWIBLe95xX303qKG6zE1NitfCrgUT&sz=w2000")
		no-repeat;
	background-size: cover;
	background-position: bottom right;
	margin-left: 200px;
}

.tree {
	position: absolute;
	z-index: 0;
	bottom: 0;
}

.sign {
	position: absolute;
	z-index: 0;
	height: 100px;
	top: calc(50% + 110px);
	left: 500px;
}

#hero {
	position: fixed;
	width: 32px;
	height: 44px;
	background-repeat: no-repeat;
	top: calc(50% + 200px);
	left: 10%;
	transform: translate(-50%, -50%);
	margin-top: -20px;
	z-index: 99;
}

.spider {
	position: absolute;
	width: 105px;
	height: 50px;
	background-repeat: no-repeat;
	top: calc(50% + 175px);
	left: 7700px;
	transform: translate(-50%, -50%);
	transition: top 0.2s;
	margin-top: -20px;
	z-index: 99;
	background-position: 0 0;
	background-image: url("https://drive.google.com/thumbnail?id=1VTozcNB0JwK3K8PpFjzCkxOCwzOfDEU7&sz=w1000");
	background-size: 840px 50px; /* Size of the complete sprite */
	animation: spider 0.3s steps(8) infinite, spiderWalk 17s linear infinite;
}

@keyframes spider {
	from {
		background-position: 0 0;
	}
	to {
		background-position: -840px 0;
	}
}

@keyframes spiderWalk {
	0% {
		transform: translateX(2000px) translateY(100%) rotate(5deg); /* Start underground */
	}
	5% {
		transform: translateX(1800px) translateY(0) rotate(0deg); /* Coming out with inclination */
	}
	10% {
		transform: translateX(1600px) translateY(0) rotate(0deg); /* Leveling out */
	}
	40% {
		transform: translateX(400px) translateY(0) rotate(0deg); /* Walking straight to 0px */
	}
	45% {
		transform: translateX(200px) translateY(0) rotate(0deg); /* Walking straight to 0px */
	}
	50% {
		transform: translateX(0px) translateY(100%) rotate(5deg); /* Walking straight to 0px */
	}

	100% {
		transform: translateX(0px) translateY(100%) rotate(-5deg); /* Hold position for the pause */
	}
}

/* Idle state */
#hero.idle-right {
	background-image: url("https://drive.google.com/thumbnail?id=1LfRNG8pJK8F0lYtXH9tfGT70l4IW-66S&sz=w1000");
	background-position: 0 0;
}

/* Idle state */
#hero.idle-left {
	background-image: url("https://drive.google.com/thumbnail?id=1oxPBLaiwJR1QzOrLC4Z_dt5nFl56RzoN&sz=w1000");
	background-position: 0 0;
}

/* Running right */
#hero.running-right {
	background-image: url("https://drive.google.com/thumbnail?id=1tbtI6RBfVzPV8TbA-Ww44E5Dz5_Ek3m0&sz=w1000 ");
	animation: runRight 0.7s steps(6) infinite;
}

@keyframes runRight {
	from {
		background-position: 0 0;
	}
	to {
		background-position: -192px 0;
	}
}

/* Running left */
#hero.running-left {
	background-image: url("https://drive.google.com/thumbnail?id=1eIBkrLk1cMlnsLETX1sLeqOc0On0D2R2&sz=w1000");
	animation: runLeft 0.7s steps(6) infinite;
}

@keyframes runLeft {
	from {
		background-position: 0 0;
	}
	to {
		background-position: -192px 0;
	}
}

#hero.jump {
	animation: jump 0.5s ease-in-out;
}

@keyframes jump {
	0% {
		top: 70%;
	}
	50% {
		top: 50%;
	}
	100% {
		top: 70%;
	}
}

.obstacle {
	position: absolute;
	z-index: 2;
}

@keyframes MoveUpDown {
	0%,
	100% {
		bottom: calc(50% + 300px);
	}
	50% {
		bottom: calc(50% - 210px);
	}
}

@keyframes fly {
	0% {
		background-position: 0 0;
	}
	100% {
		background-position: 0 -400px;
	}
}

@keyframes flyHorizontal {
	0% {
		margin-left: 10000px;
	}
	100% {
		margin-left: -10000px;
	}
}

@keyframes flyVertical {
	0%,
	100% {
		top: calc(50% - 120px);
	}
	50% {
		top: calc(50% + 120px);
	}
}

.bird {
	position: absolute;
	width: 50px;
	height: 50px;
	background-image: url("https://drive.google.com/thumbnail?id=1K16UgPDBTbXXAfocdgRWqftFMMG7SVkg&sz=w1000");
	background-size: cover;
}

.bird:nth-child(1) {
	animation: flyHorizontal 30s linear infinite,
		flyVertical 3s ease-in-out infinite, fly 0.5s steps(8) infinite;
}

.bird:nth-child(2) {
	animation: flyHorizontal 24s linear infinite,
		flyVertical 2s ease-in-out infinite, fly 0.3s steps(8) infinite;
}

.bird:nth-child(3) {
	animation: flyHorizontal 22s linear infinite,
		flyVertical 2.5s ease-in-out infinite, fly 0.2s steps(8) infinite;
}

.bird:nth-child(4) {
	animation: flyHorizontal 18s linear infinite,
		flyVertical 5s ease-in-out infinite, fly 1s steps(8) infinite;
}

.hammer {
	background-color: red;
	width: 100px;
	height: 100%;
	animation: MoveUpDown 2s cubic-bezier(0.95, 0.05, 0.795, 0.035) infinite;
	background: url("https://drive.google.com/thumbnail?id=1oaSfaQ9lH9kJ74WGJZOQzBFnBZL6JWXP&sz=w100")
		repeat-y;
	z-index: 0;
	bottom: 0;
}

#finishLine {
	position: absolute;
	width: 200px;
	height: 100%;
	top: 0;
}

#scores {
	position: fixed;
	top: 40px;
	left: 10px;
	font-size: 24px;
	color: #fff;
}

#restartButton {
	padding: 10px 20px;
	font-size: 16px;
}

.floor {
	position: absolute;
	width: 20000px;
	height: calc(50% - 200px);
	background-color: black;
	margin-left: -5000px;
	z-index: 999;
}

.floor::before {
	content: "";
	position: absolute;
	top: -40px;
	left: 0;
	width: 100%;
	height: 40px;
	background: url("https://drive.google.com/thumbnail?id=1Y6CL6Tk9y2uLa2qMXWgVKaEpo9GaZB71&sz=w10000")
		repeat-x;
}

#top {
	background: black;
	position: fixed;
	top: 0;
	height: calc(50% - 200px);
	width: 100vw;
	z-index: 0;
}

.saw {
	height: 200px;
	width: 200px;
	background-color: #bbb;
	border-radius: 50%;
	top: calc(50% + 300px);
	background: url("https://drive.google.com/thumbnail?id=1Ilr8beBalsgBA-QcCSeBpisfhJwj5kUi&sz=w1000");
	background-size: cover;
	z-index: 0;
}

.saw:nth-child(1) {
	animation: saw 5s ease-in-out infinite;
}

.saw:nth-child(2) {
	animation: saw 6s ease-in-out infinite;
	filter: invert(100%) brightness(10%);
}

@keyframes saw {
	0%,
	100% {
		top: calc(50% + 300px);
		transform: rotate(0deg);
	}
	50% {
		top: calc(50% + 100px);
		transform: rotate(360deg);
	}
}

.bush,
.monster {
	position: absolute;
	z-index: 0;
	width: 200px;
	height: 100%;
	background: green;
	top: calc(50% + 140px);
	background-color: lightgreen;
	transition: background-color 1s ease; /* Smooth transition for background color */
	background-repeat: no-repeat;
	background-size: contain;
	transition: margin-top 1s;
}

.silhouette,
.object {
	position: absolute;
}

.bush {
	background: url("https://drive.google.com/thumbnail?id=1ECNZf1tZIfmNy_GZB0jghoDIDlTMl1Pf&sz=w1000");
	background-position: top center;
	margin-top: -20px;
}

.monster {
	background: url("https://drive.google.com/thumbnail?id=1UO-UFCQlbSN46NPyDLS8Bf6-WMfbz8lS&sz=w1000");
	margin-top: -120px;
}

#hero.invert {
	filter: invert(100%) brightness(20%);
	transition: filter 1s;
}

.tree:nth-child(1) {
	height: 400px;
	top: calc(50% - 200px);
	left: 800px;
}

.tree:nth-child(2) {
	height: 200px;
	top: calc(50% - 0px);
	left: 2000px;
}

.tree:nth-child(3) {
	height: 200px;
	top: calc(50% - 0px);
	left: 3000px;
}

.tree:nth-child(4) {
	height: 390px;
	top: calc(50% - 180px);
	left: 5000px;
}

.tree:nth-child(5) {
	height: 390px;
	top: calc(50% - 180px);
	left: 6000px;
}

.house {
	height: 200px;
	top: calc(50% - 0px);
	left: 10000px;
	margin-left: -140px;
}

.obstacle.hammer:nth-child(1),
.obstacle.hammer:nth-child(4) {
	animation: MoveUpDown 3s cubic-bezier(0.95, 0.05, 0.795, 0.035) infinite;
}

.obstacle.hammer:nth-child(2),
.obstacle.hammer:nth-child(5) {
	animation: MoveUpDown 4s cubic-bezier(0.95, 0.05, 0.795, 0.035) infinite;
}

.obstacle.hammer:nth-child(3),
.obstacle.hammer:nth-child(6) {
	animation: MoveUpDown 5s cubic-bezier(0.95, 0.05, 0.795, 0.035) infinite;
}

.obstacle.hammer:nth-child(7) {
	animation: MoveUpDown 6s cubic-bezier(0.95, 0.05, 0.795, 0.035) infinite;
}

.obstacle.hammer:nth-child(8) {
	animation: MoveUpDown 7s cubic-bezier(0.95, 0.05, 0.795, 0.035) infinite;
}

.house {
	position: absolute;
	height: 200px;
	width: 270px;
	top: calc(50% - 0px);
	left: 10000px;
	margin-left: -140px;
	background-image: url("https://drive.google.com/thumbnail?id=1mXa7h5cIQorJ-8IJEf0wrCbLT2daz-2C&sz=w1000");
	background-size: cover;
	background-repeat: no-repeat;
	animation: lights 3s infinite;
}

/* Smoke animation */
@keyframes lights {
	0% {
		filter: brightness(110%);
	}
	25% {
		filter: brightness(90%);
	}
	30% {
		filter: brightness(100%);
	}
	80% {
		filter: brightness(95%);
	}
	100% {
		filter: brightness(110%);
	}
}

.chimney {
	position: absolute;
	width: 15px;
	height: 60px;
	top: 1px;
	left: 176px;
}

.smoke {
	position: absolute;
	bottom: 50%;
	left: 50%;
	width: 20px;
	height: 100px;
	background-color: rgba(0, 0, 0, 0.3);
	border-radius: 50%;
	animation: smoke 3s infinite;
	opacity: 0.5;
	filter: blur(20px);
}

.smoke:nth-child(2) {
	animation-delay: 0.5s;
}

.smoke:nth-child(3) {
	animation-delay: 1s;
}
.smoke:nth-child(4) {
	animation-delay: 1.5s;
}
.smoke:nth-child(5) {
	animation-delay: 2s;
}
.smoke:nth-child(6) {
	animation-delay: 2.5s;
}
.smoke:nth-child(7) {
	animation-delay: 3s;
}

/* Smoke animation */
@keyframes smoke {
	0% {
		transform: translate(-50%, 0) scale(0.5);
		opacity: 0.2;
	}
	25% {
		transform: translate(-60%, -30px) scale(0.7);
		opacity: 0.4;
	}
	50% {
		transform: translate(-70%, -60px) scale(1);
		opacity: 0.4;
	}
	75% {
		transform: translate(-80%, -90px) scale(1.2);
		opacity: 0.4;
	}
	100% {
		transform: translate(-90%, -120px) scale(1.5);
		opacity: 0;
	}
}

.screen {
	position: fixed;
	left: 0;
	z-index: 9999;
	width: 100%;
	height: 100%;
	background-color: rgba(0, 0, 0, 0.6);
	padding: 80px;
}

.screen h1 {
	font-size: 5rem;
	color: black;
	text-align: center;
	color: #fff;
}

.screen p {
	color: #ccc;
	font-size: 1rem;
	text-align: center;
}

.main-title {
	height: 100%;
	flex-direction: column;
}

.mouse-scroll {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 10px;
}

.mouse {
	width: 48px;
	height: 80px;
	border: 4px solid #fff;
	border-radius: 24px;
	display: flex;
	justify-content: center;
	align-items: start;
}

.wheel {
	width: 8px;
	height: 16px;
	background-color: #fff;
	border-radius: 4px;
	animation: scroll 1s infinite;
	margin-top: 8px;
}

/* Scroll animation */
@keyframes scroll {
	0% {
		transform: translateY(0);
	}

	50% {
		transform: translateY(8px);
	}

	100% {
		transform: translateY(0);
	}
}

.arrow-right {
	width: 10px;
	height: 10px;
	border-right: 4px solid #fff;
	border-bottom: 4px solid #fff;
	transform: rotate(-45deg);
	margin-top: -24px;
	margin-left: 80px;
}

.arrow-left {
	width: 10px;
	height: 10px;
	border-right: 4px solid #fff;
	border-bottom: 4px solid #fff;
	transform: rotate(135deg);
	margin-top: -52px;
	margin-left: -80px;
}

.game-over,
.win,
.bestTime {
	display: none;
}

#scores p,
.scores p {
	margin: 0;
}

.btn {
	padding: 8px 24px;
	font-size: 1.3rem;
}

@media only screen and (max-width: 600px) {
	.screen h1 {
		font-size: 2.2rem;
	}
	.screen p {
		color: #ccc;
		font-size: 1rem;
	}
	.screen {
		width: 100vw;
	}
}
            
        

		$(document).ready(function () {
			const hero = $("#hero");
			const obstacles = $(".obstacle");
			const bush = $(".bush");
			const floor = $(".floor");
			const object = $(".object"); // Changed to plural for clarity
			const finishLine = $("#finishLine");
			let gameRunning = true;
			let timerStarted = false;
			let startTime, intervalId;
			let highestScore = 0;
			const scrollSpeed = 20; // Increased speed for scrolling
			let isJumping = false;
			let lastScrollTime = 0;
			let isRunningRight = false;
			let isRunningLeft = false;
			let lastDirection = "idle-right"; // Start with idle-right
			let touchStartX = 0;
			let touchStartY = 0;
		
			function setHeroState(state) {
				hero.removeClass("idle-right idle-left running-right running-left");
				hero.addClass(state);
			}
		
			function handleIdleState() {
				if (lastDirection === "running-right") {
					setHeroState("idle-right");
				} else if (lastDirection === "running-left") {
					setHeroState("idle-left");
				} else {
					setHeroState("idle-right");
				}
			}
		
			setHeroState("idle-left");
		
			function startTimer() {
				startTime = Date.now();
				intervalId = setInterval(updateTimer, 100);
			}
		
			function updateTimer() {
				const now = Date.now();
				const elapsed = now - startTime;
		
				const minutes = Math.floor(elapsed / (1000 * 60));
				const seconds = Math.floor((elapsed % (1000 * 60)) / 1000);
				const milliseconds = Math.floor((elapsed % 1000) / 100);
		
				$("#chronometer, .chronometer").text("" + pad(minutes, 2) + ":" + pad(seconds, 2));
			}
		
			function pad(number, length) {
				return number.toString().padStart(length, "0");
			}
		
			// Handle scrolling for both mouse wheel and touch events
			function handleScroll(scrollDirection) {
				$(".start").fadeOut();
		
				const now = Date.now();
				if (!gameRunning || now - lastScrollTime < 16) return; // Limit to 60 fps
				lastScrollTime = now;
		
				if (!timerStarted) {
					startTimer();
					timerStarted = true;
				}
		
				if (scrollDirection < 0 && !isRunningRight) {
					isRunningRight = true;
					isRunningLeft = false;
					lastDirection = "running-right";
					setHeroState("running-right");
				} else if (scrollDirection > 0 && !isRunningLeft) {
					isRunningLeft = true;
					isRunningRight = false;
					lastDirection = "running-left";
					setHeroState("running-left");
				}
		
				// Reset to idle state immediately when scrolling stops
				clearTimeout(hero.data("scrollTimeout"));
				hero.data(
					"scrollTimeout",
					setTimeout(() => {
						isRunningRight = false;
						isRunningLeft = false;
						handleIdleState();
					}, 200)
				); // Adjust the delay as needed
		
				requestAnimationFrame(() => {
					$(".obstacle, .bush, .floor, .object, #finishLine").each(function () {
						const left = parseInt($(this).css("left"));
						$(this).css("left", left - scrollDirection * scrollSpeed + "px");
					});
					checkWin();
					checkHeroSilhouetteOverlap();
				});
			}
		
			$(window).on("mousewheel DOMMouseScroll", function (e) {
				const delta = e.originalEvent.wheelDelta || -e.originalEvent.detail;
				const scrollDirection = delta < 0 ? 1 : -1;
				handleScroll(scrollDirection);
			});
		
			// Handle touch events for scrolling
			$(document).on("touchstart", function (e) {
				touchStartX = e.originalEvent.touches[0].pageX;
				touchStartY = e.originalEvent.touches[0].pageY;
			});
		
			$(document).on("touchmove", function (e) {
				const touchEndX = e.originalEvent.touches[0].pageX;
				const touchEndY = e.originalEvent.touches[0].pageY;
				const deltaX = touchEndX - touchStartX;
				const deltaY = touchEndY - touchStartY;
		
				if (Math.abs(deltaX) > Math.abs(deltaY)) {
					const scrollDirection = deltaX < 0 ? 1 : -1;
					handleScroll(scrollDirection);
				}
			});
		
			// Handle Arrow Up key and touch events for jumping
			$(document).keydown(function (e) {
				if (!gameRunning || isJumping) return;
		
				if (e.key === "ArrowUp") {
					handleJump();
				}
			});
		
			$(document).on("touchstart", function (e) {
				const touchEndY = e.originalEvent.touches[0].pageY;
		
				if (touchStartY - touchEndY > 50) {
					// Swipe up detected
					handleJump();
				}
			});
		
			function handleJump() {
				if (!gameRunning || isJumping) return;
		
				isJumping = true;
				hero.addClass("jump");
				setTimeout(() => {
					hero.removeClass("jump");
					isJumping = false;
				}, 500); // Duration of the jump
			}
		
			function checkCollision() {
				const tolerance = 10;
				const heroPos = hero[0].getBoundingClientRect();
		
				$(".obstacle").each(function () {
					const obstaclePos = this.getBoundingClientRect();
		
					if (
						!(
							heroPos.right < obstaclePos.left + tolerance ||
							heroPos.left > obstaclePos.right - tolerance ||
							heroPos.bottom < obstaclePos.top ||
							heroPos.top > obstaclePos.bottom
						)
					) {
						gameOver();
					}
				});
			}
		
			setInterval(checkCollision, 100);
		
			function checkWin() {
				const heroPos = hero[0].getBoundingClientRect();
				const finishPos = finishLine[0].getBoundingClientRect();
		
				if (
					!(
						heroPos.right < finishPos.left ||
						heroPos.left > finishPos.right ||
						heroPos.bottom < finishPos.top ||
						heroPos.top > finishPos.bottom
					)
				) {
					gameWin();
				}
			}
		
			function gameOver() {
				if (!gameRunning) return;
				gameRunning = false;
				clearInterval(intervalId);
				$(".start").fadeOut();
				$(".game-over").fadeIn();
			}
		
			function gameWin() {
				if (!gameRunning) return;
				gameRunning = false;
				clearInterval(intervalId);
				const now = Date.now();
				const elapsed = now - startTime;
				if (elapsed < highestScore || highestScore === 0) {
					highestScore = elapsed;
					const minutes = Math.floor(highestScore / (1000 * 60));
					const seconds = Math.floor((highestScore % (1000 * 60)) / 1000);
					const milliseconds = Math.floor((highestScore % 1000) / 10);
					$("#highestScore, .highestScore").text(
						"" + pad(minutes, 2) + ":" + pad(seconds, 2)
					);
				}
				$(".win").fadeIn();
				$(".bestTime").fadeIn();
			}
		
			$(".restartButton").click(function () {
				resetGame();
				$(".game-over, .win").fadeOut();
			});
		
			function resetGame() {
				gameRunning = true;
				timerStarted = false;
				clearInterval(intervalId);
				$("#chronometer, .chronometer").text("00:00");
		
				// Reset hero position
				hero.css("top", "calc(50% + 200px)");
				hero.removeClass("invert");
		
				// Reset obstacles, bush, floor, and finish line positions
				$(".obstacle, .bush, .floor, .object, #finishLine").each(function () {
					$(this).css("left", $(this).data("initialLeft"));
				});
			}
		
			// Store initial positions
			$(".obstacle, .bush, .floor, .object, #finishLine").each(function () {
				$(this).data("initialLeft", $(this).css("left"));
			});
		
			// Loop through each .bush element
			$(".bush").each(function (index) {
				var $bush = $(this);
		
				function toggleObstacle() {
					$bush.toggleClass("obstacle monster");
					setTimeout(
						toggleObstacle,
						$bush.hasClass("obstacle monster")
							? getToggleTime(index, true)
							: getToggleTime(index, false)
					);
				}
		
				toggleObstacle();
			});
		
			// Function to get the toggle time based on the index and class status
			function getToggleTime(index, isObstacle) {
				// Define the toggle times for each nth-child
				var toggleTimes = [
					[3000, 4000], // nth-child(1)
					[4000, 5000], // nth-child(2)...
					[5000, 6500],
					[3500, 4000],
					[6000, 7000]
				];
		
				// Return the appropriate time based on the index and class status
				return isObstacle ? toggleTimes[index][0] : toggleTimes[index][1];
			}
		
			function checkHeroSilhouetteOverlap() {
				const heroPos = hero[0].getBoundingClientRect();
				let heroInFrontOfEyes = false;
		
				$(".silhouette").each(function () {
					const bushPos = this.getBoundingClientRect();
		
					if (
						!(
							heroPos.right < bushPos.left ||
							heroPos.left > bushPos.right ||
							heroPos.bottom < bushPos.top ||
							heroPos.top > bushPos.bottom
						)
					) {
						heroInFrontOfEyes = true;
					}
				});
		
				if (heroInFrontOfEyes) {
					hero.addClass("invert");
				} else {
					hero.removeClass("invert");
				}
			}
		});
		
    


Leave Comments

FOLLOW US