diff --git "a/.github/ISSUE_TEMPLATE/add-new-project--\360\237\223\232.md" "b/.github/ISSUE_TEMPLATE/add-new-project--\360\237\223\232.md" new file mode 100644 index 000000000..bb196aaea --- /dev/null +++ "b/.github/ISSUE_TEMPLATE/add-new-project--\360\237\223\232.md" @@ -0,0 +1,27 @@ +--- +name: "Add New Project \U0001F4DA" +about: Requesting for the new project to contribute in this repository. +title: "\U0001F4C3: " +labels: '' +assignees: '' + +--- + +๐Ÿ”ด Title : +๐Ÿ”ด Tech stack : +๐Ÿ”ด Objective : +๐Ÿ”ด Summary : +๐Ÿ“ธ Screenshots + + +*********************************************************************** + +โœ… Details to Include When Taking the Issue: +Name : +Participant Role (Specify the Open Source Program name, e.g., GSSOC, Hacktoberfest, etc.): + +*********************************************************************** + +Happy Contributing! ๐Ÿš€ + +Wishing you all the best on your open source journey. Enjoy! ๐Ÿ˜Ž diff --git "a/.github/ISSUE_TEMPLATE/bug-report-\360\237\220\233.md" "b/.github/ISSUE_TEMPLATE/bug-report-\360\237\220\233.md" new file mode 100644 index 000000000..4cf2af144 --- /dev/null +++ "b/.github/ISSUE_TEMPLATE/bug-report-\360\237\220\233.md" @@ -0,0 +1,29 @@ +--- +name: "Bug Report \U0001F41B" +about: Reporting for any bug in the project +title: "\U0001F41E : " +labels: '' +assignees: '' + +--- + +:red_circle: **Title** : +:red_circle: **Bug** : +:red_circle: **Changes** : + + +### Screenshots ๐Ÿ“ท + + + +************************************************************ + +โœ… Details to Include When Taking the Issue: +Name : +Participant Role (Specify the Open Source Program name, e.g., GSSOC, Hacktoberfest, etc.): + +*********************************************************************** + +Happy Contributing! ๐Ÿš€ + +Wishing you all the best on your open source journey. Enjoy! ๐Ÿ˜Ž diff --git "a/.github/ISSUE_TEMPLATE/code-enhancement-\360\237\223\235-.md" "b/.github/ISSUE_TEMPLATE/code-enhancement-\360\237\223\235-.md" new file mode 100644 index 000000000..2393d8514 --- /dev/null +++ "b/.github/ISSUE_TEMPLATE/code-enhancement-\360\237\223\235-.md" @@ -0,0 +1,28 @@ +--- +name: "Code enhancement \U0001F4DD " +about: Improving any styling or function of the existing project +title: "\U0001F9D1โ€\U0001F4BB : " +labels: '' +assignees: '' + +--- + +:red_circle: **Title** : +:red_circle: **Enhancement Aim** : +:red_circle: **Changes** : + + +### Screenshots ๐Ÿ“ท + + + +********************************************************************** +โœ… Details to Include When Taking the Issue: +Name : +Participant Role (Specify the Open Source Program name, e.g., GSSOC, Hacktoberfest, etc.): + +*********************************************************************** + +Happy Contributing! ๐Ÿš€ + +Wishing you all the best on your open source journey. Enjoy! ๐Ÿ˜Ž diff --git a/assets/image/Password-manager.png b/assets/image/Password-manager.png new file mode 100644 index 000000000..eff82af36 Binary files /dev/null and b/assets/image/Password-manager.png differ diff --git a/assets/image/doodle.png b/assets/image/doodle.png new file mode 100644 index 000000000..7c41e56eb Binary files /dev/null and b/assets/image/doodle.png differ diff --git a/index.html b/index.html index f62c8e903..8ee191787 100644 --- a/index.html +++ b/index.html @@ -38,7 +38,7 @@

Open Projects

- +
@@ -49,7 +49,7 @@

Generate Gradient

- +
@@ -60,7 +60,7 @@

Counter

- +
@@ -71,7 +71,7 @@

Rating System

- +
@@ -82,7 +82,7 @@

Love Calculator

- +
@@ -93,7 +93,7 @@

Planets

- +
@@ -104,7 +104,7 @@

Storybazzi

- +
@@ -116,7 +116,7 @@

8 Puzzle

- +
@@ -128,7 +128,7 @@

Calculator

- +
@@ -139,7 +139,7 @@

Snake Game

- +
@@ -150,7 +150,7 @@

Password Generator

- +
@@ -161,7 +161,7 @@

Meme Generator

- +
@@ -173,7 +173,7 @@

Memory Tiles

- +
@@ -185,7 +185,7 @@

Random User Generator

- +
@@ -197,7 +197,7 @@

Ping Pong Game

- +
@@ -208,7 +208,7 @@

Todo List

- +
link tree icon
@@ -219,7 +219,7 @@

Linktree Clone

- +
link tree icon
@@ -231,7 +231,7 @@

Tic Tac Toe

- +
number guessing
@@ -242,7 +242,7 @@

Guess my Number

- +
BMI CALCULATOR
@@ -253,7 +253,7 @@

BMI Calculator

- +
number guessing
@@ -264,7 +264,7 @@

Stop Watch

- +
number guessing
@@ -276,7 +276,7 @@

Live Clock

- +
Sudoku Solver
@@ -288,7 +288,7 @@

Sudoku

- +
Simon Game
@@ -299,7 +299,7 @@

Simon Game

- +
Drum
@@ -310,7 +310,7 @@

Drum Kit

- +
wordle logo
@@ -325,7 +325,7 @@

Wordle Game

-
+
@@ -339,7 +339,7 @@

Sudoku Game

-
+
Text to Speech logo
@@ -350,7 +350,7 @@

Text to Speech

- +
Image Generator logo
@@ -364,7 +364,7 @@

Image Generator

-
+
@@ -376,7 +376,7 @@

Github Profile Viewer

- +
Typing test logo @@ -388,7 +388,7 @@

Typing Speed Test

- +
Rolling Triumph
@@ -402,7 +402,7 @@

Rolling Triumph

-
+
link tree icon
@@ -412,7 +412,7 @@

Connect-4-Dot

Connect dots and win the game.

-
+
@@ -422,7 +422,18 @@

Weather

Check weather

-
+ +
+ +
+
+

Password manager

+

+ Manage your passwords +

+
+
+
@@ -433,7 +444,7 @@

Dictionary

- +
@@ -444,7 +455,7 @@

Currency Convertor

- +
trivia
@@ -455,7 +466,7 @@

TRIVIA

- +
wordle logo
@@ -465,7 +476,7 @@

GeoQuest

Explore the World, One Challenge at a Time!

- +
magic8ball
@@ -476,7 +487,7 @@

Magic 8 Ball

- +
Rock paper scissor icon
@@ -486,6 +497,16 @@

Rock Paper Scissors

Choose your move Tie!

+
+
+ +
+
+

Password manager

+

+ Manage your passwords +

+
@@ -519,6 +540,17 @@

Among Us

Find who is imposter.

+
+ +
+ Doodle Jump +
+
+

Doodle Jump

+

+ Enjoy and Jump. +

+
diff --git a/projects/CAR RACE/README.md b/projects/CAR RACE/README.md new file mode 100644 index 000000000..73c447bc8 --- /dev/null +++ b/projects/CAR RACE/README.md @@ -0,0 +1,13 @@ +Description ๐Ÿ“ƒ + +It is a 3D racing game using HTML, CSS, and JavaScript. It sets up event listeners for keyboard input, initializes game variables and objects, and updates the game state in a loop. The game involves driving a car on a road,avoiding obstacles and other cars, and trying to complete laps as quickly as possible. The code also includes functionality for displaying a high score table and playing sound effects. + +The code sets the background color, font family, and height of the body. It also defines the styles for the top UI elements such as the time, score, and lap counters. Additionally, it sets the styles for the tachometer at the bottom of the screen. + +It has all the styles for a game interface, including the positioning and appearance of various elements such as the road, hero character, clouds, and high score display. It also includes animations for blinking text and transitions for opacity and timing. + +functionalities ๐ŸŽฎ It is basically a normal race game where we see a screen in front of us and instructions below the screen describing about how to play the game.It has all the sounds which a race game should have. The race begins on a track where there are multiple cars and we have to race against them. When we come infront of any other car our car's speed becomes zero and the car honks. + +How to play? ๐Ÿ•น๏ธ + +To begin we have to press 'c' and to accelerate the car we have to press 'up' arrow and to deaccelerate the car we have to press 'down' arrow. To move aside we have to press 'right' arrow and and 'left' arrow respectively to move right and left. To mute the sounds we have to press 'm'. \ No newline at end of file diff --git a/projects/CAR RACE/images/1icon.png b/projects/CAR RACE/images/1icon.png new file mode 100644 index 000000000..821142c96 Binary files /dev/null and b/projects/CAR RACE/images/1icon.png differ diff --git a/projects/CAR RACE/images/car04.png b/projects/CAR RACE/images/car04.png new file mode 100644 index 000000000..b6dcc4a03 Binary files /dev/null and b/projects/CAR RACE/images/car04.png differ diff --git a/projects/CAR RACE/images/cloud.jpg b/projects/CAR RACE/images/cloud.jpg new file mode 100644 index 000000000..36d931761 Binary files /dev/null and b/projects/CAR RACE/images/cloud.jpg differ diff --git a/projects/CAR RACE/images/finish.png b/projects/CAR RACE/images/finish.png new file mode 100644 index 000000000..925b7568a Binary files /dev/null and b/projects/CAR RACE/images/finish.png differ diff --git a/projects/CAR RACE/images/hero.png b/projects/CAR RACE/images/hero.png new file mode 100644 index 000000000..70ee2936a Binary files /dev/null and b/projects/CAR RACE/images/hero.png differ diff --git a/projects/CAR RACE/images/icon.png b/projects/CAR RACE/images/icon.png new file mode 100644 index 000000000..490cf6c20 Binary files /dev/null and b/projects/CAR RACE/images/icon.png differ diff --git a/projects/CAR RACE/images/tree.png b/projects/CAR RACE/images/tree.png new file mode 100644 index 000000000..a8efcfcd3 Binary files /dev/null and b/projects/CAR RACE/images/tree.png differ diff --git a/projects/CAR RACE/index.html b/projects/CAR RACE/index.html new file mode 100644 index 000000000..60c9b1ab1 --- /dev/null +++ b/projects/CAR RACE/index.html @@ -0,0 +1,64 @@ + + + + + + Dash + + + + + + + + + + + +
+
+
+
+
+
+ +
+ 0 + 0 + 0'00"000 + 0 +
+ +
+

Dash

+

+ +
+
+
+ +
+ Cinsert coin + Mmute + <>move + <>accelerate +
+ + + + + + \ No newline at end of file diff --git a/projects/CAR RACE/script.js b/projects/CAR RACE/script.js new file mode 100644 index 000000000..ea1eb66a3 --- /dev/null +++ b/projects/CAR RACE/script.js @@ -0,0 +1,720 @@ +const ASSETS = { + COLOR: { + TAR: ["#959298", "#9c9a9d"], + RUMBLE: ["#959298", "#f5f2f6"], + GRASS: ["#eedccd", "#e6d4c5"], + }, + + IMAGE: { + TREE: { + src: "images/tree.png", + width: 132, + height: 192, + }, + + HERO: { + src: "images/hero.png", + width: 110, + height: 56, + }, + + CAR: { + src: "images/car04.png", + width: 50, + height: 36, + }, + + FINISH: { + src: "images/finish.png", + width: 339, + height: 180, + offset: -0.5, + }, + + SKY: { + src: "images/cloud.jpg", + }, + }, + + AUDIO: { + theme: + "https://s3-us-west-2.amazonaws.com/s.cdpn.io/155629/theme.mp3", + engine: + "https://s3-us-west-2.amazonaws.com/s.cdpn.io/155629/engine.wav", + honk: "https://s3-us-west-2.amazonaws.com/s.cdpn.io/155629/honk.wav", + beep: "https://s3-us-west-2.amazonaws.com/s.cdpn.io/155629/beep.wav", + }, + }; + + // ------------------------------------------------------------ + // helper functions + // ------------------------------------------------------------ + + Number.prototype.pad = function (numZeros, char = 0) { + let n = Math.abs(this); + let zeros = Math.max(0, numZeros - Math.floor(n).toString().length); + let zeroString = Math.pow(10, zeros) + .toString() + .substr(1) + .replace(0, char); + return zeroString + n; + }; + + Number.prototype.clamp = function (min, max) { + return Math.max(min, Math.min(this, max)); + }; + + const timestamp = (_) => new Date().getTime(); + const accelerate = (v, accel, dt) => v + accel * dt; + const isCollide = (x1, w1, x2, w2) => (x1 - x2) ** 2 <= (w2 + w1) ** 2; + + function getRand(min, max) { + return (Math.random() * (max - min) + min) | 0; + } + + function randomProperty(obj) { + let keys = Object.keys(obj); + return obj[keys[(keys.length * Math.random()) << 0]]; + } + + function drawQuad(element, layer, color, x1, y1, w1, x2, y2, w2) { + element.style.zIndex = layer; + element.style.background = color; + element.style.top = y2 + `px`; + element.style.left = x1 - w1 / 2 - w1 + `px`; + element.style.width = w1 * 3 + `px`; + element.style.height = y1 - y2 + `px`; + + let leftOffset = w1 + x2 - x1 + Math.abs(w2 / 2 - w1 / 2); + element.style.clipPath = `polygon(${leftOffset}px 0, ${ + leftOffset + w2 + }px 0, 66.66% 100%, 33.33% 100%)`; + } + + const KEYS = {}; + const keyUpdate = (e) => { + KEYS[e.code] = e.type === `keydown`; + e.preventDefault(); + }; + addEventListener(`keydown`, keyUpdate); + addEventListener(`keyup`, keyUpdate); + + function sleep(ms) { + return new Promise(function (resolve, reject) { + setTimeout((_) => resolve(), ms); + }); + } + + // ------------------------------------------------------------ + // objects + // ------------------------------------------------------------ + + class Line { + constructor() { + this.x = 0; + this.y = 0; + this.z = 0; + + this.X = 0; + this.Y = 0; + this.W = 0; + + this.curve = 0; + this.scale = 0; + + this.elements = []; + this.special = null; + } + + project(camX, camY, camZ) { + this.scale = camD / (this.z - camZ); + this.X = (1 + this.scale * (this.x - camX)) * halfWidth; + this.Y = Math.ceil(((1 - this.scale * (this.y - camY)) * height) / 2); + this.W = this.scale * roadW * halfWidth; + } + + clearSprites() { + for (let e of this.elements) e.style.background = "transparent"; + } + + drawSprite(depth, layer, sprite, offset) { + let destX = this.X + this.scale * halfWidth * offset; + let destY = this.Y + 4; + let destW = (sprite.width * this.W) / 265; + let destH = (sprite.height * this.W) / 265; + + destX += destW * offset; + destY += destH * -1; + + let obj = layer instanceof Element ? layer : this.elements[layer + 6]; + obj.style.background = `url('${sprite.src}') no-repeat`; + obj.style.backgroundSize = `${destW}px ${destH}px`; + obj.style.left = destX + `px`; + obj.style.top = destY + `px`; + obj.style.width = destW + `px`; + obj.style.height = destH + `px`; + obj.style.zIndex = depth; + } + } + + class Car { + constructor(pos, type, lane) { + this.pos = pos; + this.type = type; + this.lane = lane; + + var element = document.createElement("div"); + road.appendChild(element); + this.element = element; + } + } + + class Audio { + constructor() { + this.audioCtx = new AudioContext(); + + // volume + this.destination = this.audioCtx.createGain(); + this.volume = 1; + this.destination.connect(this.audioCtx.destination); + + this.files = {}; + + let _self = this; + this.load(ASSETS.AUDIO.theme, "theme", function (key) { + let source = _self.audioCtx.createBufferSource(); + source.buffer = _self.files[key]; + + let gainNode = _self.audioCtx.createGain(); + gainNode.gain.value = 0.6; + source.connect(gainNode); + gainNode.connect(_self.destination); + + source.loop = true; + source.start(0); + }); + } + + get volume() { + return this.destination.gain.value; + } + + set volume(level) { + this.destination.gain.value = level; + } + + play(key, pitch) { + if (this.files[key]) { + let source = this.audioCtx.createBufferSource(); + source.buffer = this.files[key]; + source.connect(this.destination); + if (pitch) source.detune.value = pitch; + source.start(0); + } else this.load(key, () => this.play(key)); + } + + load(src, key, callback) { + let _self = this; + let request = new XMLHttpRequest(); + request.open("GET", src, true); + request.responseType = "arraybuffer"; + request.onload = function () { + _self.audioCtx.decodeAudioData( + request.response, + function (beatportBuffer) { + _self.files[key] = beatportBuffer; + callback(key); + }, + function () {} + ); + }; + request.send(); + } + } + + // ------------------------------------------------------------ + // global varriables + // ------------------------------------------------------------ + + const highscores = []; + + const width = 800; + const halfWidth = width / 2; + const height = 500; + const roadW = 4000; + const segL = 200; + const camD = 0.2; + const H = 1500; + const N = 70; + + const maxSpeed = 200; + const accel = 38; + const breaking = -80; + const decel = -40; + const maxOffSpeed = 40; + const offDecel = -70; + const enemy_speed = 8; + const hitSpeed = 20; + + const LANE = { + A: -2.3, + B: -0.5, + C: 1.2, + }; + + const mapLength = 15000; + + // loop + let then = timestamp(); + const targetFrameRate = 1000 / 25; // in ms + + let audio; + + // game + let inGame, + start, + playerX, + speed, + scoreVal, + pos, + cloudOffset, + sectionProg, + mapIndex, + countDown; + let lines = []; + let cars = []; + + // ------------------------------------------------------------ + // map + // ------------------------------------------------------------ + + function getFun(val) { + return (i) => val; + } + + function genMap() { + let map = []; + + for (var i = 0; i < mapLength; i += getRand(0, 50)) { + let section = { + from: i, + to: (i = i + getRand(300, 600)), + }; + + let randHeight = getRand(-5, 5); + let randCurve = getRand(5, 30) * (Math.random() >= 0.5 ? 1 : -1); + let randInterval = getRand(20, 40); + + if (Math.random() > 0.9) + Object.assign(section, { + curve: (_) => randCurve, + height: (_) => randHeight, + }); + else if (Math.random() > 0.8) + Object.assign(section, { + curve: (_) => 0, + height: (i) => Math.sin(i / randInterval) * 1000, + }); + else if (Math.random() > 0.8) + Object.assign(section, { + curve: (_) => 0, + height: (_) => randHeight, + }); + else + Object.assign(section, { + curve: (_) => randCurve, + height: (_) => 0, + }); + + map.push(section); + } + + map.push({ + from: i, + to: i + N, + curve: (_) => 0, + height: (_) => 0, + special: ASSETS.IMAGE.FINISH, + }); + map.push({ from: Infinity }); + return map; + } + + let map = genMap(); + + // ------------------------------------------------------------ + // additional controls + // ------------------------------------------------------------ + + addEventListener(`keyup`, function (e) { + if (e.code === "KeyM") { + e.preventDefault(); + + audio.volume = audio.volume === 0 ? 1 : 0; + return; + } + + if (e.code === "KeyC") { + e.preventDefault(); + + if (inGame) return; + + sleep(0) + .then((_) => { + text.classList.remove("blink"); + text.innerText = 3; + audio.play("beep"); + return sleep(1000); + }) + .then((_) => { + text.innerText = 2; + audio.play("beep"); + return sleep(1000); + }) + .then((_) => { + reset(); + + home.style.display = "none"; + + road.style.opacity = 1; + hero.style.display = "block"; + hud.style.display = "block"; + + audio.play("beep", 500); + + inGame = true; + }); + + return; + } + + if (e.code === "Escape") { + e.preventDefault(); + + reset(); + } + }); + + // ------------------------------------------------------------ + // game loop + // ------------------------------------------------------------ + + function update(step) { + // prepare this iteration + pos += speed; + while (pos >= N * segL) pos -= N * segL; + while (pos < 0) pos += N * segL; + + var startPos = (pos / segL) | 0; + let endPos = (startPos + N - 1) % N; + + scoreVal += speed * step; + countDown -= step; + + // left / right position + playerX -= (lines[startPos].curve / 5000) * step * speed; + + if (KEYS.ArrowRight) + (hero.style.backgroundPosition = "-220px 0"), + (playerX += 0.007 * step * speed); + else if (KEYS.ArrowLeft) + (hero.style.backgroundPosition = "0 0"), + (playerX -= 0.007 * step * speed); + else hero.style.backgroundPosition = "-110px 0"; + + playerX = playerX.clamp(-3, 3); + + // speed + + if (inGame && KEYS.ArrowUp) speed = accelerate(speed, accel, step); + else if (KEYS.ArrowDown) speed = accelerate(speed, breaking, step); + else speed = accelerate(speed, decel, step); + + if (Math.abs(playerX) > 0.55 && speed >= maxOffSpeed) { + speed = accelerate(speed, offDecel, step); + } + + speed = speed.clamp(0, maxSpeed); + + // update map + let current = map[mapIndex]; + let use = current.from < scoreVal && current.to > scoreVal; + if (use) sectionProg += speed * step; + lines[endPos].curve = use ? current.curve(sectionProg) : 0; + lines[endPos].y = use ? current.height(sectionProg) : 0; + lines[endPos].special = null; + + if (current.to <= scoreVal) { + mapIndex++; + sectionProg = 0; + + lines[endPos].special = map[mapIndex].special; + } + + // win / lose + UI + + if (!inGame) { + speed = accelerate(speed, breaking, step); + speed = speed.clamp(0, maxSpeed); + } else if (countDown <= 0 || lines[startPos].special) { + tacho.style.display = "none"; + + home.style.display = "block"; + road.style.opacity = 0.4; + text.innerText = "INSERT COIN"; + + highscores.push(lap.innerText); + highscores.sort(); + updateHighscore(); + + inGame = false; + } else { + time.innerText = (countDown | 0).pad(3); + score.innerText = (scoreVal | 0).pad(8); + tacho.innerText = speed | 0; + + let cT = new Date(timestamp() - start); + lap.innerText = `${cT.getMinutes()}'${cT.getSeconds().pad(2)}"${cT + .getMilliseconds() + .pad(3)}`; + } + + // sound + if (speed > 0) audio.play("engine", speed * 4); + + // draw cloud + cloud.style.backgroundPosition = `${ + (cloudOffset -= lines[startPos].curve * step * speed * 0.13) | 0 + }px 0`; + + // other cars + for (let car of cars) { + car.pos = (car.pos + enemy_speed * step) % N; + + // respawn + if ((car.pos | 0) === endPos) { + if (speed < 30) car.pos = startPos; + else car.pos = endPos - 2; + car.lane = randomProperty(LANE); + } + + // collision + const offsetRatio = 5; + if ( + (car.pos | 0) === startPos && + isCollide(playerX * offsetRatio + LANE.B, 0.5, car.lane, 0.5) + ) { + speed = Math.min(hitSpeed, speed); + if (inGame) audio.play("honk"); + } + } + + // draw road + let maxy = height; + let camH = H + lines[startPos].y; + let x = 0; + let dx = 0; + + for (let n = startPos; n < startPos + N; n++) { + let l = lines[n % N]; + let level = N * 2 - n; + + // update view + l.project( + playerX * roadW - x, + camH, + startPos * segL - (n >= N ? N * segL : 0) + ); + x += dx; + dx += l.curve; + + // clear assets + l.clearSprites(); + + // first draw section assets + if (n % 10 === 0) l.drawSprite(level, 0, ASSETS.IMAGE.TREE, -2); + if ((n + 5) % 10 === 0) + l.drawSprite(level, 0, ASSETS.IMAGE.TREE, 1.3); + + if (l.special) + l.drawSprite(level, 0, l.special, l.special.offset || 0); + + for (let car of cars) + if ((car.pos | 0) === n % N) + l.drawSprite(level, car.element, car.type, car.lane); + + // update road + + if (l.Y >= maxy) continue; + maxy = l.Y; + + let even = ((n / 2) | 0) % 2; + let grass = ASSETS.COLOR.GRASS[even * 1]; + let rumble = ASSETS.COLOR.RUMBLE[even * 1]; + let tar = ASSETS.COLOR.TAR[even * 1]; + + let p = lines[(n - 1) % N]; + + drawQuad( + l.elements[0], + level, + grass, + width / 4, + p.Y, + halfWidth + 2, + width / 4, + l.Y, + halfWidth + ); + drawQuad( + l.elements[1], + level, + grass, + (width / 4) * 3, + p.Y, + halfWidth + 2, + (width / 4) * 3, + l.Y, + halfWidth + ); + + drawQuad( + l.elements[2], + level, + rumble, + p.X, + p.Y, + p.W * 1.15, + l.X, + l.Y, + l.W * 1.15 + ); + drawQuad(l.elements[3], level, tar, p.X, p.Y, p.W, l.X, l.Y, l.W); + + if (!even) { + drawQuad( + l.elements[4], + level, + ASSETS.COLOR.RUMBLE[1], + p.X, + p.Y, + p.W * 0.4, + l.X, + l.Y, + l.W * 0.4 + ); + drawQuad( + l.elements[5], + level, + tar, + p.X, + p.Y, + p.W * 0.35, + l.X, + l.Y, + l.W * 0.35 + ); + } + } + } + + // ------------------------------------------------------------ + // init + // ------------------------------------------------------------ + + function reset() { + inGame = false; + + start = timestamp(); + countDown = map[map.length - 2].to / 130 + 10; + + playerX = 0; + speed = 0; + scoreVal = 0; + + pos = 0; + cloudOffset = 0; + sectionProg = 0; + mapIndex = 0; + + for (let line of lines) line.curve = line.y = 0; + + text.innerText = "INSERT COIN"; + text.classList.add("blink"); + + road.style.opacity = 0.4; + hud.style.display = "none"; + home.style.display = "block"; + tacho.style.display = "block"; + } + + function updateHighscore() { + let hN = Math.min(12, highscores.length); + for (let i = 0; i < hN; i++) { + highscore.children[i].innerHTML = `${(i + 1).pad(2, " ")}. ${ + highscores[i] + }`; + } + } + + function init() { + game.style.width = width + "px"; + game.style.height = height + "px"; + + hero.style.top = height - 80 + "px"; + hero.style.left = halfWidth - ASSETS.IMAGE.HERO.width / 2 + "px"; + hero.style.background = `url(${ASSETS.IMAGE.HERO.src})`; + hero.style.width = `${ASSETS.IMAGE.HERO.width}px`; + hero.style.height = `${ASSETS.IMAGE.HERO.height}px`; + + cloud.style.backgroundImage = `url(${ASSETS.IMAGE.SKY.src})`; + + audio = new Audio(); + Object.keys(ASSETS.AUDIO).forEach((key) => + audio.load(ASSETS.AUDIO[key], key, (_) => 0) + ); + + cars.push(new Car(0, ASSETS.IMAGE.CAR, LANE.C)); + cars.push(new Car(10, ASSETS.IMAGE.CAR, LANE.B)); + cars.push(new Car(20, ASSETS.IMAGE.CAR, LANE.C)); + cars.push(new Car(35, ASSETS.IMAGE.CAR, LANE.C)); + cars.push(new Car(50, ASSETS.IMAGE.CAR, LANE.A)); + cars.push(new Car(60, ASSETS.IMAGE.CAR, LANE.B)); + cars.push(new Car(70, ASSETS.IMAGE.CAR, LANE.A)); + + for (let i = 0; i < N; i++) { + var line = new Line(); + line.z = i * segL + 270; + + for (let j = 0; j < 6 + 2; j++) { + var element = document.createElement("div"); + road.appendChild(element); + line.elements.push(element); + } + + lines.push(line); + } + + for (let i = 0; i < 12; i++) { + var element = document.createElement("p"); + highscore.appendChild(element); + } + updateHighscore(); + + reset(); + + // START GAME LOOP + (function loop() { + requestAnimationFrame(loop); + + let now = timestamp(); + let delta = now - then; + + if (delta > targetFrameRate) { + then = now - (delta % targetFrameRate); + update(delta / 1000); + } + })(); + } + + init(); \ No newline at end of file diff --git a/projects/CAR RACE/style.css b/projects/CAR RACE/style.css new file mode 100644 index 000000000..9e85c3e71 --- /dev/null +++ b/projects/CAR RACE/style.css @@ -0,0 +1,207 @@ +body { + background: #222; + font-family: "Press Start 2P", monospace; + font-smooth: never; + height: 98vh; + border: 1px solid rgb(22, 252, 233); + align-items: center; + justify-content: center; + display: flex; + overflow-y: hidden; + } + + /* UI */ + .topUI { + position: absolute; + z-index: 1000; /* need this cause clip-path changes stack context */ + transform: translate(-50%, 25px); + text-shadow: -2px 0 black, 0 2px black, 2px 0 black, 0 -2px black; + letter-spacing: 2px; + color: #fff; + font-size: 17px; + } + .topUI::before { + display: inline-block; + height: 17px; + padding: 1px 2px; + line-height: 19px; + font-size: 17px; + background: #fff; + text-shadow: none; + font-weight: 900; + letter-spacing: 0; + border-radius: 6px; + margin-right: 30px; + border: 2px solid #7dd8c9; + } + #time { + left: 13%; + color: #f4f430; + } + #time::before { + content: "TIME"; + color: #f57214; + } + #score { + left: 45%; + } + #score::before { + content: "SCORE"; + color: #a61a9d; + } + #lap { + left: 88%; + width: 45%; + } + #lap::before { + content: "LAP"; + color: #0082df; + } + + #tacho { + position: absolute; + text-align: right; + width: 23%; + bottom: 5%; + z-index: 2000; + color: #e62e13; + text-shadow: -2px 0 black, 0 2px black, 2px 0 black, 0 -2px black; + letter-spacing: 2px; + font-size: 23px; + } + #tacho::after { + content: "km/h"; + color: #fab453; + font-size: 18px; + margin-left: 5px; + } + + /* + road + */ + + .container{ + border: 2px solid rgb(0, 247, 255); + width: fit-content; + display: flex; + flex-direction: column; + align-items: center; + } + + #game { + position: relative; + margin: 0 auto; + overflow: hidden; + background: #222; + user-select: none; + transition: opacity 10s; + border: 1px solid white; + } + #road { + transition: opacity 2s; + transition-timing-function: steps(8, end); + } + #road * { + position: absolute; + image-rendering: pixelated; + } + #hero { + background-repeat: no-repeat; + background-position: -110px 0; + z-index: 2000; + transform: scale(1.4); + } + #cloud { + background-size: auto 100%; + width: 100%; + height: 57%; + } + + + /* + home + */ + #road { + position: absolute; + width: 100%; + height: 100%; + } + + #home { + position: absolute; + color: #fff; + width: 100%; + height: 100%; + + z-index: 1000; /* need this cause clip-path changes stack context */ + } + + #highscore { + position: absolute; + width: 100%; + height: 20%; + bottom: 0; + column-count: 3; + column-fill: auto; + } + + #highscore * { + color: #9e95a8; + margin: 0 0 6px 27px; + } + + h1 { + position: absolute; + left: 50%; + top: 25%; + transform: translate(-50%, -50%); + font-size: 5em; + + background: -webkit-linear-gradient(#25d8b1, #e2bbf0); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + } + + #text { + position: absolute; + left: 50%; + top: 50%; + transform: translate(-50%, -50%); + font-size: 1.2em; + color: #d9bbf3; + text-shadow: 0 0 black, 0 2px black, 2px 0 black, 0 0 black; + } + + .blink { + animation: blinker 2s steps(4, end) infinite; + } + @keyframes blinker { + 50% { + opacity: 0; + } + } + + /* + Guide + */ + #controls { + width: fit-content; + color: #868686; + font-size: 13px; + line-height: 13px; + margin: 10px; + text-align: center; + } + #controls > span { + margin-left: 20px; + } + #controls > span > span { + border: 2px solid #868686; + border-radius: 5px; + padding: 7px; + margin-right: 10px; + display: inline-block; + } + #controls > span:last-child > span { + transform: rotate(90deg); + } \ No newline at end of file diff --git a/projects/Doodle Jump/doodlejump.css b/projects/Doodle Jump/doodlejump.css new file mode 100644 index 000000000..1650b9763 --- /dev/null +++ b/projects/Doodle Jump/doodlejump.css @@ -0,0 +1,8 @@ +body { + text-align: center; +} + +#board { + /* background-color: green; */ + background-image: url("./doodlejumpbg.png"); +} \ No newline at end of file diff --git a/projects/Doodle Jump/doodlejump.js b/projects/Doodle Jump/doodlejump.js new file mode 100644 index 000000000..79dda7c39 --- /dev/null +++ b/projects/Doodle Jump/doodlejump.js @@ -0,0 +1,217 @@ +//board +let board; +let boardWidth = 360; +let boardHeight = 576; +let context; + +//doodler +let doodlerWidth = 46; +let doodlerHeight = 46; +let doodlerX = boardWidth/2 - doodlerWidth/2; +let doodlerY = boardHeight*7/8 - doodlerHeight; +let doodlerRightImg; +let doodlerLeftImg; + +let doodler = { + img : null, + x : doodlerX, + y : doodlerY, + width : doodlerWidth, + height : doodlerHeight +} + +//physics +let velocityX = 0; +let velocityY = 0; //doodler jump speed +let initialVelocityY = -8; //starting velocity Y +let gravity = 0.4; + +//platforms +let platformArray = []; +let platformWidth = 60; +let platformHeight = 18; +let platformImg; + +let score = 0; +let maxScore = 0; +let gameOver = false; + +window.onload = function() { + board = document.getElementById("board"); + board.height = boardHeight; + board.width = boardWidth; + context = board.getContext("2d"); //used for drawing on the board + + //draw doodler + // context.fillStyle = "green"; + // context.fillRect(doodler.x, doodler.y, doodler.width, doodler.height); + + //load images + doodlerRightImg = new Image(); + doodlerRightImg.src = "./doodler-right.png"; + doodler.img = doodlerRightImg; + doodlerRightImg.onload = function() { + context.drawImage(doodler.img, doodler.x, doodler.y, doodler.width, doodler.height); + } + + doodlerLeftImg = new Image(); + doodlerLeftImg.src = "./doodler-left.png"; + + platformImg = new Image(); + platformImg.src = "./platform.png"; + + velocityY = initialVelocityY; + placePlatforms(); + requestAnimationFrame(update); + document.addEventListener("keydown", moveDoodler); +} + +function update() { + requestAnimationFrame(update); + if (gameOver) { + return; + } + context.clearRect(0, 0, board.width, board.height); + + //doodler + doodler.x += velocityX; + if (doodler.x > boardWidth) { + doodler.x = 0; + } + else if (doodler.x + doodler.width < 0) { + doodler.x = boardWidth; + } + + velocityY += gravity; + doodler.y += velocityY; + if (doodler.y > board.height) { + gameOver = true; + } + context.drawImage(doodler.img, doodler.x, doodler.y, doodler.width, doodler.height); + + //platforms + for (let i = 0; i < platformArray.length; i++) { + let platform = platformArray[i]; + if (velocityY < 0 && doodler.y < boardHeight*3/4) { + platform.y -= initialVelocityY; //slide platform down + } + if (detectCollision(doodler, platform) && velocityY >= 0) { + velocityY = initialVelocityY; //jump + } + context.drawImage(platform.img, platform.x, platform.y, platform.width, platform.height); + } + + // clear platforms and add new platform + while (platformArray.length > 0 && platformArray[0].y >= boardHeight) { + platformArray.shift(); //removes first element from the array + newPlatform(); //replace with new platform on top + } + + //score + updateScore(); + context.fillStyle = "black"; + context.font = "16px sans-serif"; + context.fillText(score, 5, 20); + + if (gameOver) { + context.fillText("Game Over: Press 'Space' to Restart", boardWidth/7, boardHeight*7/8); + } +} + +function moveDoodler(e) { + if (e.code == "ArrowRight" || e.code == "KeyD") { //move right + velocityX = 4; + doodler.img = doodlerRightImg; + } + else if (e.code == "ArrowLeft" || e.code == "KeyA") { //move left + velocityX = -4; + doodler.img = doodlerLeftImg; + } + else if (e.code == "Space" && gameOver) { + //reset + doodler = { + img : doodlerRightImg, + x : doodlerX, + y : doodlerY, + width : doodlerWidth, + height : doodlerHeight + } + + velocityX = 0; + velocityY = initialVelocityY; + score = 0; + maxScore = 0; + gameOver = false; + placePlatforms(); + } +} + +function placePlatforms() { + platformArray = []; + + //starting platforms + let platform = { + img : platformImg, + x : boardWidth/2, + y : boardHeight - 50, + width : platformWidth, + height : platformHeight + } + + platformArray.push(platform); + + // platform = { + // img : platformImg, + // x : boardWidth/2, + // y : boardHeight - 150, + // width : platformWidth, + // height : platformHeight + // } + // platformArray.push(platform); + + for (let i = 0; i < 6; i++) { + let randomX = Math.floor(Math.random() * boardWidth*3/4); //(0-1) * boardWidth*3/4 + let platform = { + img : platformImg, + x : randomX, + y : boardHeight - 75*i - 150, + width : platformWidth, + height : platformHeight + } + + platformArray.push(platform); + } +} + +function newPlatform() { + let randomX = Math.floor(Math.random() * boardWidth*3/4); //(0-1) * boardWidth*3/4 + let platform = { + img : platformImg, + x : randomX, + y : -platformHeight, + width : platformWidth, + height : platformHeight + } + + platformArray.push(platform); +} + +function detectCollision(a, b) { + return a.x < b.x + b.width && //a's top left corner doesn't reach b's top right corner + a.x + a.width > b.x && //a's top right corner passes b's top left corner + a.y < b.y + b.height && //a's top left corner doesn't reach b's bottom left corner + a.y + a.height > b.y; //a's bottom left corner passes b's top left corner +} + +function updateScore() { + let points = Math.floor(50*Math.random()); //(0-1) *50 --> (0-50) + if (velocityY < 0) { //negative going up + maxScore += points; + if (score < maxScore) { + score = maxScore; + } + } + else if (velocityY >= 0) { + maxScore -= points; + } +} \ No newline at end of file diff --git a/projects/Doodle Jump/doodlejumpbg.png b/projects/Doodle Jump/doodlejumpbg.png new file mode 100644 index 000000000..27f83cc8f Binary files /dev/null and b/projects/Doodle Jump/doodlejumpbg.png differ diff --git a/projects/Doodle Jump/doodler-left.png b/projects/Doodle Jump/doodler-left.png new file mode 100644 index 000000000..542fe52df Binary files /dev/null and b/projects/Doodle Jump/doodler-left.png differ diff --git a/projects/Doodle Jump/doodler-right.png b/projects/Doodle Jump/doodler-right.png new file mode 100644 index 000000000..7c41e56eb Binary files /dev/null and b/projects/Doodle Jump/doodler-right.png differ diff --git a/projects/Doodle Jump/index.html b/projects/Doodle Jump/index.html new file mode 100644 index 000000000..a8b3bdb1c --- /dev/null +++ b/projects/Doodle Jump/index.html @@ -0,0 +1,13 @@ + + + + + + Doodle Jump + + + + + + + \ No newline at end of file diff --git a/projects/Doodle Jump/platform-broken.png b/projects/Doodle Jump/platform-broken.png new file mode 100644 index 000000000..8d91cc0c1 Binary files /dev/null and b/projects/Doodle Jump/platform-broken.png differ diff --git a/projects/Doodle Jump/platform.png b/projects/Doodle Jump/platform.png new file mode 100644 index 000000000..2424948dd Binary files /dev/null and b/projects/Doodle Jump/platform.png differ diff --git a/projects/Drag-and-Drop/README.md b/projects/Drag-and-Drop/README.md new file mode 100644 index 000000000..671273017 --- /dev/null +++ b/projects/Drag-and-Drop/README.md @@ -0,0 +1,101 @@ +# Dynamic To-Do List Application with Drag-and-Drop Functionality + +## Table of Contents +- [Project Overview](#project-overview) +- [Features](#features) +- [Objectives](#objectives) +- [Requirements](#requirements) +- [Technical Notes](#technical-notes) +- [Installation](#installation) +- [Usage](#usage) +- [Code Structure](#code-structure) +- [Contributing](#contributing) +- [License](#license) + +## Project Overview +The Dynamic To-Do List application is designed to help users manage their tasks efficiently. This project implements drag-and-drop functionality for reordering task cards, allowing users to prioritize tasks intuitively. The application also persists the task order using localStorage, ensuring that usersโ€™ preferences are retained even after a page refresh. + +## Project Demonstration +- For a visual demonstration, you can watch the [video tutorial](./media/drag-and-drop.mp4) that walks through the drag-and-drop functionality. + +## Features +- **Drag-and-Drop Functionality**: Users can click and drag task cards to reorder them within the same column. +- **Visual Feedback**: Provides immediate visual feedback during drag-and-drop actions, including highlighting the target position. +- **Persistent Order**: The updated order of tasks is saved in localStorage, preserving changes between sessions. + +## Objectives +- Users should be able to drag a task card and drop it at a new position within the same column. +- The order of the tasks should update visually and in the data model. +- The new task order should persist even after a page refresh by storing the updated list in localStorage. + +## Requirements +- Implement drag-and-drop functionality using the HTML5 Drag and Drop API. +- Create visual feedback for users, such as highlighting the target position while dragging. +- Update the task order in the data model when the user drops a task card in a new position. +- Store the updated task list in localStorage so that the order persists between sessions. + +## Technical Notes +### Use the following events to handle drag-and-drop behavior: +- **dragstart**: Triggered when a drag operation starts; set the data being dragged. +- **dragover**: Triggered when an item is dragged over a valid drop target; prevent default behavior to allow dropping. +- **drop**: Triggered when the item is dropped; reorder the task cards based on the drop position. + +### Visual Effects: +- Change the opacity of the dragged item to indicate it's being dragged. +- Highlight the target position using a placeholder or border to show where the task card will be dropped. + +### Data Model Update: +- After a drop event, update the tasks array to reflect the new order in JavaScript. +- Ensure the updated order is immediately reflected in the HTML view. + +### Persistence with localStorage: +- Save the updated tasks array to localStorage after a drop event. +- On page load, read the task order from localStorage to display tasks in the saved order. + +## Installation +To get started with the Dynamic To-Do List application: + +### Clone the Repository: +```bash +git clone https://github.com/iamrahulmahato/master-web-development.git +``` + +### Navigate to the Project Directory: +```bash +cd projects/Drag-and-Drop +``` + +### Open the index.html file in your browser to view the application. + +## Usage +- **Reordering Tasks**: Click and drag any task card to reorder it as needed. +- **Refreshing the Page**: The order of tasks will persist even after refreshing the page. + +## Code Structure +- **index.html**: The main HTML file containing the structure of the application. +- **style.css**: Contains styles for the task cards and visual feedback during dragging. +- **script.js**: JavaScript file implementing the drag-and-drop functionality and localStorage handling. + +## Example Code Snippet +Hereโ€™s a simplified example of how drag-and-drop is implemented: +```javascript +// Drag event handlers +function dragStart() { + dragStartIndex = +this.closest('li').getAttribute('data-index'); +} + +function drop() { + const dragEndIndex = +this.getAttribute('data-index'); + swapItems(dragStartIndex, dragEndIndex); +} +``` + +## Contributing +Contributions are welcome! If you'd like to contribute to the project, please fork the repository and create a pull request. + +### Guidelines +- Ensure your code is well-documented and follows the projectโ€™s coding standards. +- Include tests for new features, if applicable. +- Update the README with details of changes to the project structure or any additional information. +*** +### Give a star โญ๏ธ if this project helped you! diff --git a/projects/Drag-and-Drop/index.html b/projects/Drag-and-Drop/index.html new file mode 100644 index 000000000..91a537b28 --- /dev/null +++ b/projects/Drag-and-Drop/index.html @@ -0,0 +1,30 @@ + + + + + + + + + + + + + Drag and Drop To-Do List + + +
+

Drag and Drop To-Do List

+

Drag items into their corresponding spots

+ + + + + + + +
+ + + + diff --git a/projects/Drag-and-Drop/media/drag-and-drop.mp4 b/projects/Drag-and-Drop/media/drag-and-drop.mp4 new file mode 100644 index 000000000..655fde50d Binary files /dev/null and b/projects/Drag-and-Drop/media/drag-and-drop.mp4 differ diff --git a/projects/Drag-and-Drop/script.js b/projects/Drag-and-Drop/script.js new file mode 100644 index 000000000..1b44f97e1 --- /dev/null +++ b/projects/Drag-and-Drop/script.js @@ -0,0 +1,188 @@ +const draggableList = document.getElementById('draggable-list'); +const checkButton = document.getElementById('check'); +const hintButton = document.getElementById('hint'); + +// Predefined correct order of tasks for validation +const correctOrder = [ + 'Make a list of 100+ JavaScript Projects', + 'Learn React', + 'Learn Node.js', + 'Learn Express.js', + 'Learn MongoDB', + 'Learn Python', + 'Learn Django', + 'Learn Flutter', + 'Learn Dart', + 'Learn Java' +]; + +let listItems = []; +let dragStartIndex; +let isHintShown = false; // State to track whether hint is displayed + +// List of tasks as a simple array of strings to be rendered +let todoListItems = [ + 'Make a list of 100+ JavaScript Projects', + 'Learn React', + 'Learn Node.js', + 'Learn Express.js', + 'Learn MongoDB', + 'Learn Python', + 'Learn Django', + 'Learn Flutter', + 'Learn Dart', + 'Learn Java' +]; + +// Function to create the list and render it to the DOM +function createList() { + draggableList.innerHTML = ''; // Clear previous content + listItems = []; + + todoListItems + .map((task, index) => ({ task, index })) + .forEach(({ task, index }) => { + const listItem = document.createElement('li'); + listItem.setAttribute('data-index', index); + listItem.draggable = true; + + listItem.innerHTML = ` + ${index + 1} +
+

${task}

+ + +
+ `; + + listItems.push(listItem); + draggableList.appendChild(listItem); + }); + + addEventListeners(); +} + +// Add drag and drop event listeners +function addEventListeners() { + const draggables = document.querySelectorAll('.draggable'); + const dragListItems = document.querySelectorAll('.draggable-list li'); + + draggables.forEach((draggable) => { + draggable.addEventListener('dragstart', dragStart); + }); + + dragListItems.forEach((item) => { + item.addEventListener('dragover', dragOver); + item.addEventListener('drop', drop); + item.addEventListener('dragenter', dragEnter); + item.addEventListener('dragleave', dragLeave); + }); +} + +// Drag event handlers +/** + * Handles the drag start event. + * Sets the dragStartIndex to the index of the closest 'li' element. + * + * @this {HTMLElement} The element that triggered the drag start event. + */ + +function dragStart() { + dragStartIndex = +this.closest('li').getAttribute('data-index'); +} + +function dragEnter(e) { + e.preventDefault(); + this.classList.add('over'); +} + +function dragLeave() { + this.classList.remove('over'); +} + +function dragOver(e) { + e.preventDefault(); +} + +function drop() { + const dragEndIndex = +this.getAttribute('data-index'); + swapItems(dragStartIndex, dragEndIndex); + + this.classList.remove('over'); +} + +// Swap list items +function swapItems(fromIndex, toIndex) { + const itemOne = listItems[fromIndex].querySelector('.draggable'); + const itemTwo = listItems[toIndex].querySelector('.draggable'); + + listItems[fromIndex].appendChild(itemTwo); + listItems[toIndex].appendChild(itemOne); + + updateTaskOrderInArray(); +} + +// Update the order in the tasks array and save to localStorage +function updateTaskOrderInArray() { + todoListItems = listItems.map((item) => item.querySelector('.task-name').innerText); + localStorage.setItem('todoListItems', JSON.stringify(todoListItems)); +} + +// Load items from localStorage if available +function loadItemsFromLocalStorage() { + const storedItems = JSON.parse(localStorage.getItem('todoListItems')); + if (storedItems) { + todoListItems = storedItems; + } +} + +function checkOrder() { + let allCorrect = true; // Variable to track if all items are in correct position + + listItems.forEach((listItem, index) => { + const taskName = listItem.querySelector('.task-name').innerText; + + // Remove any existing styles from previous checks + listItem.classList.remove('correct', 'incorrect'); + + // Check if the current task is in the correct position + if (taskName === correctOrder[index]) { + listItem.classList.add('correct'); + } else { + listItem.classList.add('incorrect'); + allCorrect = false; // Set to false if any item is incorrect + } + }); + + // Alert message if all items are in the correct position + if (allCorrect) { + alert("Congratulations! All items are in the correct position."); + } + } + + +// Show or hide the hint when the hint button is clicked +function toggleHint() { + isHintShown = !isHintShown; + + // Update button text based on the current state + hintButton.innerText = isHintShown ? 'Hide Hint' : 'Show Hint'; + + // Show or hide the correct order hints based on the state + listItems.forEach((listItem) => { + const hintElement = listItem.querySelector('.hint'); + if (isHintShown) { + hintElement.style.display = 'block'; // Show hint + } else { + hintElement.style.display = 'none'; // Hide hint + } + }); +} + +// Event listeners for buttons +checkButton.addEventListener('click', checkOrder); +hintButton.addEventListener('click', toggleHint); + +// Initial setup +loadItemsFromLocalStorage(); +createList(); diff --git a/projects/Drag-and-Drop/style.css b/projects/Drag-and-Drop/style.css new file mode 100644 index 000000000..ffe02c9bf --- /dev/null +++ b/projects/Drag-and-Drop/style.css @@ -0,0 +1,96 @@ +body { + font-family: Arial, sans-serif; + background-color: #f7f7f7; + padding: 20px; + } + + h1 { + text-align: center; + margin-bottom: 14px; + font-size: 20px; + color: #007bff; + } + + ul { + list-style-type: none; + padding: 0; + } + + li { + margin: 10px 0; + padding: 15px; + border: 1px solid #ccc; + border-radius: 5px; + cursor: pointer; + transition: transform 0.3s ease, box-shadow 0.3s ease; + } + + li:hover { + background-color: #e3f2fd; + } + +/* Styles for correct and incorrect list items */ +li.correct { + border: 2px solid #4caf50; + background-color: #e8f5e9; +} + +li.incorrect { + border: 2px solid #f44336; + background-color: #ffebee; +} + + /* Hover effect when the card is being dragged */ + li.over { + transform: scale(1.05); + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); + background-color: #609ba3; + } + + .hint { + font-size: 12px; + color: #555; + margin-left: 10px; + } + + .draggable { + display: flex; + justify-content: space-between; + align-items: center; + transition: background-color 0.3s ease; + } + + .number { + font-weight: bold; + margin-right: 10px; + } + + .check-btn, + .hint-btn { + display: block; + margin: 20px auto; + padding: 10px 20px; + background-color: #007bff; + color: white; + border: none; + cursor: pointer; + border-radius: 5px; + } + + .check-btn:hover, + .hint-btn:hover { + background-color: #0056b3; + } + + /* Add media query for larger screens */ + @media screen and (min-width: 768px) { + body { + display: flex; + justify-content: center; + } + main { + width: 50%; + margin: auto; + } + } + \ No newline at end of file diff --git a/projects/Fruit Slicer/index.html b/projects/Fruit Slicer/index.html new file mode 100644 index 000000000..564fdcad5 --- /dev/null +++ b/projects/Fruit Slicer/index.html @@ -0,0 +1,43 @@ + + + + Fruit Slicer Game + + + + + + +
+
+ Slice Fruits +
+
+
+
+ 0
+
+
+
+ Are you ready for the ultimate slice action ?
+ Fruit logo +
+ +
+
+ Start Game +
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/projects/Fruit Slicer/script.js b/projects/Fruit Slicer/script.js new file mode 100644 index 000000000..f26764e0a --- /dev/null +++ b/projects/Fruit Slicer/script.js @@ -0,0 +1,134 @@ +var playing = false; +var score; +var trialsleft; +var step;//for random steps +var action;//for settime interval +var fruits = ['1','2','3','4','5','6','7','8','9','10'];//for fruits + +$(function(){ + //click on start or reset button + $('#front').show(); + $("#startReset").click(function () { + if(playing == true){ + //if we are playing + location.reload();//reload page + }else{ + //if we are not playing from before + $('#front').hide(); + $('#score').show(); + playing = true; + //set score to 0 + score = 0; + $("#scoreValue").html(score); + + //show trials left box + + $('#trialsleft').show(); + trialsleft=3; + addhearts(); + + //hide game over box + $('#gameOver').hide(); + + //change button to reset game + $('#startReset').html('Reset Game') + + + //start action + startAction(); + } + }); + //slice a fruit + $("#fruit1").mouseover(function () { + score++;// increase score + $("#scoreValue").html(score); + + //play sound + $("#slicesound")[0].play(); + + //stop fruit + clearInterval(action); + + //hide fruit + $('#fruit1').hide("explode",500);//slice fruit + + //send new fruit + setTimeout(startAction,500); + }); + + + //functions + + //addhearts + function addhearts() { + $('#trialsleft').empty(); + for(i = 0 ; i < trialsleft ; i++){ + $('#trialsleft').append(''); + } + } + + //start action + function startAction(){ + //generate random fruit + $('#fruit1').show(); + + //choose random fruit + chooseRandom(); + //random position + $('#fruit1').css({ + 'left': Math.round(550 * Math.random()), + 'top': -50 + }); + //generate random step + step=1 + Math.round(5 * Math.random());//change steps + //descend fruits down by 10ms + action = setInterval(function(){ + //move fruit by one step + $('#fruit1').css('top', $('#fruit1').position().top + step); + + //check if the fruit is too low + if($('#fruit1').position().top > $('#fruitcontainer').height()-50){ + //yes it is low + // check trails left + if(trialsleft > 1){ + //generate a fruit + $("#fruit1").show(); + //choose random fruit + chooseRandom(); + //random position + $('#fruit1').css({ + 'left': Math.round(550 * Math.random()), + 'top': -50 + }); + //generate random step + step= 1 + Math.round(5 * Math.random());//change steps + + //reduce trials by one + trialsleft--; + //populate trails left box by one + addhearts(); + + }else{ + //game over + playing=false;//we are ot playing any more + $("#score").hide(); + $('#startreset').html('Start Game'); + $('#gameOver').show(); + $('#gameOver').html('

Game Over!

Your score is '+ score + '

'); + $('#trialsleft').hide(); + stopAction();//stops Action + } + } + },10); + } + + //choose random fruits + function chooseRandom(){ + $('#fruit1').attr('src','https://raw.githubusercontent.com/Saumya-07/Fruit-Slicer/master/images/' + fruits[Math.round(9*Math.random())]+'.png'); + } + // Stop Action + function stopAction(){ + clearInterval(action); + $('#fruit1').hide(); + } +}); \ No newline at end of file diff --git a/projects/Fruit Slicer/styles.css b/projects/Fruit Slicer/styles.css new file mode 100644 index 000000000..d3443b39f --- /dev/null +++ b/projects/Fruit Slicer/styles.css @@ -0,0 +1,128 @@ +html{ + height: 100%; + background: radial-gradient(circle,#fff,rgb(189, 182, 182)); + background-image: url(https://raw.githubusercontent.com/Saumya-07/Fruit-Slicer/master/images/bg3%20-%20Copy.jpg); + background-size: cover; + font-family: cursive, sans-serif; +} +#container{ + width: 750px; + height: 600px; + margin: 10px auto; + padding: 20px; + border-radius: 10px; + position: relative; +} + +#front{ + font-size: 40px; + color: #d3901d; + width: 650px; + height: 450px; + padding: 10px; + margin: 30px auto 20px auto; + z-index: 2; + display: none; +} +#front img{ + width: 280px; +} +#instructions{ + width: 450px; + height: 50px; + margin: 10px auto; + font-size: 30px; + + background-color:#d3901d; + color: #2e1d11; + text-align: center; + line-height: 50px; + border-radius: 20px; + box-shadow: 0px 4px 0px 0px #775012; +} +#fruitcontainer{ + background: url(https://raw.githubusercontent.com/Saumya-07/Fruit-Slicer/master/images/wood-bg2.jpg) ; + background-size: cover; + width: 650px; + height: 450px; + padding: 10px; + margin: 30px auto 20px auto; + background-color: white; + color: black; + text-align: center; + font-family: cursive,sans-serif; + overflow: hidden; + border-radius: 20px; + box-shadow: 0px 4px 0px 0px #4b4b4e; + position: relative; +} + +.fruit{ + display: none; + position: absolute; +} +#score{ + display: none; +} +.scoreDisplay{ + z-index: 1; + display: flex; + background-color: transparent; + color: #888e61; + position: absolute; + font-size: 30px; + justify-items: center; +} + +#score img{ + width: 40px; + align-items: center; + padding-right: 5px; +} +#trialsleft{ + margin-top: 7px; + display: flex; + position: absolute; + left:550px; + background-color:transparent; + z-index: 1; +} +.life{ + width: 30px; + padding-right: 5px; +} + +#startReset{ + position: relative; + width: 90px; + padding: 10px; + margin: 0 auto; + + cursor: pointer; + text-align: center; + background-color:#8d8315; + box-shadow: 0px 4px 0px 0px #5c5619; + border-radius: 5px; + transition: all .2s; +} +#startReset:active{ + background-color: #69620c; + box-shadow: 0px 0px #5c5619; + top: 4px; + color: white; +} + +#gameOver{ + box-sizing: border-box; + width: 500px; + height: 300px; + background: transparent; + color:#d3901d; + text-transform: upperCase; + text-align: center; + font-size: 3em; + position: absolute; + top: 170px; + left: 150px; + z-index: 2; +} \ No newline at end of file diff --git a/projects/Password manager/R.jpg b/projects/Password manager/R.jpg new file mode 100644 index 000000000..6dadd684e Binary files /dev/null and b/projects/Password manager/R.jpg differ diff --git a/projects/Password manager/copy.svg b/projects/Password manager/copy.svg new file mode 100644 index 000000000..c144368d6 --- /dev/null +++ b/projects/Password manager/copy.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/projects/Password manager/esf.jpg b/projects/Password manager/esf.jpg new file mode 100644 index 000000000..d58a70d82 Binary files /dev/null and b/projects/Password manager/esf.jpg differ diff --git a/projects/Password manager/index.html b/projects/Password manager/index.html new file mode 100644 index 000000000..c8207ed8c --- /dev/null +++ b/projects/Password manager/index.html @@ -0,0 +1,59 @@ + + + + + + + + PassX - Your Personal Password Manager + + + + + +
+

Password Manager

+

We're thrilled to have you here. Your digital life contains a myriad of passwords, and we know how + challenging it can be to manage them all. That's why we're here to make it easy for you.

+

Your Passwords (Copied!)

+ + + + + + + + +
WebsiteUsernamePasswordDelete
+ +

Add a Password

+
+ + + + +

+ + + + +

+ + + + +
+ + +
+
+ + + + \ No newline at end of file diff --git a/projects/Password manager/script.js b/projects/Password manager/script.js new file mode 100644 index 000000000..ac0a46158 --- /dev/null +++ b/projects/Password manager/script.js @@ -0,0 +1,96 @@ +function maskPassword(pass){ + let str = "" + for (let index = 0; index < pass.length; index++) { + str += "*" + } + return str +} + +function copyText(txt) { + navigator.clipboard.writeText(txt).then( + () => { + /* clipboard successfully set */ + document.getElementById("alert").style.display = "inline" + setTimeout(() => { + document.getElementById("alert").style.display = "none" + }, 2000); + + }, + () => { + /* clipboard write failed */ + alert("Clipboard copying failed") + }, + ); + } + +const deletePassword = (website)=>{ + let data = localStorage.getItem("passwords") + let arr = JSON.parse(data); + arrUpdated = arr.filter((e)=>{ + return e.website != website + }) + localStorage.setItem("passwords", JSON.stringify(arrUpdated)) + alert(`Successfully deleted ${website}'s password`) + showPasswords() + +} + +// Logic to fill the table +const showPasswords = () => { + let tb = document.querySelector("table") + let data = localStorage.getItem("passwords") + if (data == null || JSON.parse(data).length == 0) { + tb.innerHTML = "No Data To Show" + } + else { + tb.innerHTML = ` + Website + Username + Password + Delete + ` + let arr = JSON.parse(data); + let str = "" + for (let index = 0; index < arr.length; index++) { + const element = arr[index]; + + str += ` + ${element.website} Copy Button + + ${element.username} Copy Button + + ${maskPassword(element.password)} Copy Button + + + ` + } + tb.innerHTML = tb.innerHTML + str + + } + website.value = "" + username.value = "" + password.value = "" +} + +console.log("Working"); +showPasswords() +document.querySelector(".btn").addEventListener("click", (e) => { + e.preventDefault() + console.log("Clicked....") + console.log(username.value, password.value) + let passwords = localStorage.getItem("passwords") + console.log(passwords) + if (passwords == null) { + let json = [] + json.push({website: website.value, username: username.value, password: password.value }) + alert("Password Saved"); + localStorage.setItem("passwords", JSON.stringify(json)) + } + else { + let json = JSON.parse(localStorage.getItem("passwords")) + json.push({ website: website.value, username: username.value, password: password.value }) + alert("Password Saved"); + localStorage.setItem("passwords", JSON.stringify(json)) + } + showPasswords() +}) \ No newline at end of file diff --git a/projects/Password manager/style.css b/projects/Password manager/style.css new file mode 100644 index 000000000..37b56e0b0 --- /dev/null +++ b/projects/Password manager/style.css @@ -0,0 +1,90 @@ +@import url('https://fonts.googleapis.com/css2?family=Noto+Sans:ital,wght@0,700;1,300&family=Poppins:wght@300;400;600&display=swap'); +body{ + background-image: url(esf.jpg); +} +* { + margin: 0; + padding: 0; + font-family: 'Noto Sans', sans-serif; + font-family: 'Poppins', sans-serif; +} + +nav { + background-color: black; + color: white; + padding: 12px 3px; + display: flex; + justify-content: space-between; +} + +.logo{ + margin: 0 23px; + font-weight: 800; + font-size: 25px; + cursor: pointer; +} + +ul { + display: flex; + margin: 0 23px; + align-items: center; +} + +ul > li { + list-style: none; + margin: 0 13px; + cursor: pointer; +} + +ul > li:hover{ + color: white; + +} + +table, td, tr{ + border: 2px solid black; + border-collapse: collapse; + padding: 5px 13px; +} + +.container { + max-width: 80vw; + margin: 23px auto; +} + +h1, h2, h3 { + margin: 23px 0; +} + +.btn{ + padding: 8px 17px; + background: black; + color: white; + font-weight: 900; + border: 2px solid gray; + border-radius: 8px; + margin: 25px 0; + cursor: pointer; +} + +.btnsm{ + padding: 8px 17px; + background: black; + color: white; + font-weight: 900; + border: 2px solid gray; + border-radius: 8px; + cursor: pointer; +} + +img{ + cursor: pointer; + position: relative; + bottom: 7px; + width: 15px; + height: 13px; +} + +#alert{ + display: none; +} \ No newline at end of file diff --git a/projects/githubProfileViewer/index.html b/projects/githubProfileViewer/index.html index 96843cfaf..34669bd7a 100644 --- a/projects/githubProfileViewer/index.html +++ b/projects/githubProfileViewer/index.html @@ -3,7 +3,7 @@ - Document + Github Profile Viewer @@ -14,4 +14,4 @@ - \ No newline at end of file + diff --git a/projects/minecraft/array.js b/projects/minecraft/array.js new file mode 100644 index 000000000..e69de29bb diff --git a/projects/minecraft/assets/images/bgimg.jpg b/projects/minecraft/assets/images/bgimg.jpg new file mode 100644 index 000000000..867423c8d Binary files /dev/null and b/projects/minecraft/assets/images/bgimg.jpg differ diff --git a/projects/minecraft/assets/images/blocks/Cursors/coal.cur b/projects/minecraft/assets/images/blocks/Cursors/coal.cur new file mode 100644 index 000000000..9d51374df Binary files /dev/null and b/projects/minecraft/assets/images/blocks/Cursors/coal.cur differ diff --git a/projects/minecraft/assets/images/blocks/Cursors/diamond.cur b/projects/minecraft/assets/images/blocks/Cursors/diamond.cur new file mode 100644 index 000000000..f3c56037f Binary files /dev/null and b/projects/minecraft/assets/images/blocks/Cursors/diamond.cur differ diff --git a/projects/minecraft/assets/images/blocks/Cursors/grass.cur b/projects/minecraft/assets/images/blocks/Cursors/grass.cur new file mode 100644 index 000000000..2b17976fd Binary files /dev/null and b/projects/minecraft/assets/images/blocks/Cursors/grass.cur differ diff --git a/projects/minecraft/assets/images/blocks/Cursors/hatchet.cur b/projects/minecraft/assets/images/blocks/Cursors/hatchet.cur new file mode 100644 index 000000000..4dbbd0896 Binary files /dev/null and b/projects/minecraft/assets/images/blocks/Cursors/hatchet.cur differ diff --git a/projects/minecraft/assets/images/blocks/Cursors/leaves.cur b/projects/minecraft/assets/images/blocks/Cursors/leaves.cur new file mode 100644 index 000000000..043e24be3 Binary files /dev/null and b/projects/minecraft/assets/images/blocks/Cursors/leaves.cur differ diff --git a/projects/minecraft/assets/images/blocks/Cursors/pickaxe.cur b/projects/minecraft/assets/images/blocks/Cursors/pickaxe.cur new file mode 100644 index 000000000..8c9051d4f Binary files /dev/null and b/projects/minecraft/assets/images/blocks/Cursors/pickaxe.cur differ diff --git a/projects/minecraft/assets/images/blocks/Cursors/ruby.cur b/projects/minecraft/assets/images/blocks/Cursors/ruby.cur new file mode 100644 index 000000000..80ed4c48d Binary files /dev/null and b/projects/minecraft/assets/images/blocks/Cursors/ruby.cur differ diff --git a/projects/minecraft/assets/images/blocks/Cursors/shovel.cur b/projects/minecraft/assets/images/blocks/Cursors/shovel.cur new file mode 100644 index 000000000..a547666d4 Binary files /dev/null and b/projects/minecraft/assets/images/blocks/Cursors/shovel.cur differ diff --git a/projects/minecraft/assets/images/blocks/Cursors/stone.cur b/projects/minecraft/assets/images/blocks/Cursors/stone.cur new file mode 100644 index 000000000..11905afe8 Binary files /dev/null and b/projects/minecraft/assets/images/blocks/Cursors/stone.cur differ diff --git a/projects/minecraft/assets/images/blocks/Cursors/tree.cur b/projects/minecraft/assets/images/blocks/Cursors/tree.cur new file mode 100644 index 000000000..24d6c2fc6 Binary files /dev/null and b/projects/minecraft/assets/images/blocks/Cursors/tree.cur differ diff --git a/projects/minecraft/assets/images/blocks/coal.png b/projects/minecraft/assets/images/blocks/coal.png new file mode 100644 index 000000000..e18b5311b Binary files /dev/null and b/projects/minecraft/assets/images/blocks/coal.png differ diff --git a/projects/minecraft/assets/images/blocks/diamond.png b/projects/minecraft/assets/images/blocks/diamond.png new file mode 100644 index 000000000..5248fdc7a Binary files /dev/null and b/projects/minecraft/assets/images/blocks/diamond.png differ diff --git a/projects/minecraft/assets/images/blocks/grass.png b/projects/minecraft/assets/images/blocks/grass.png new file mode 100644 index 000000000..987c3e04b Binary files /dev/null and b/projects/minecraft/assets/images/blocks/grass.png differ diff --git a/projects/minecraft/assets/images/blocks/hatchet.png b/projects/minecraft/assets/images/blocks/hatchet.png new file mode 100644 index 000000000..04c592494 Binary files /dev/null and b/projects/minecraft/assets/images/blocks/hatchet.png differ diff --git a/projects/minecraft/assets/images/blocks/leaves.png b/projects/minecraft/assets/images/blocks/leaves.png new file mode 100644 index 000000000..79b677fea Binary files /dev/null and b/projects/minecraft/assets/images/blocks/leaves.png differ diff --git a/projects/minecraft/assets/images/blocks/pickaxe.png b/projects/minecraft/assets/images/blocks/pickaxe.png new file mode 100644 index 000000000..c088508d6 Binary files /dev/null and b/projects/minecraft/assets/images/blocks/pickaxe.png differ diff --git a/projects/minecraft/assets/images/blocks/ruby.png b/projects/minecraft/assets/images/blocks/ruby.png new file mode 100644 index 000000000..48ce06bc6 Binary files /dev/null and b/projects/minecraft/assets/images/blocks/ruby.png differ diff --git a/projects/minecraft/assets/images/blocks/shovel.png b/projects/minecraft/assets/images/blocks/shovel.png new file mode 100644 index 000000000..0e74e8f45 Binary files /dev/null and b/projects/minecraft/assets/images/blocks/shovel.png differ diff --git a/projects/minecraft/assets/images/blocks/stone.png b/projects/minecraft/assets/images/blocks/stone.png new file mode 100644 index 000000000..3cf1fa34b Binary files /dev/null and b/projects/minecraft/assets/images/blocks/stone.png differ diff --git a/projects/minecraft/assets/images/blocks/tree.png b/projects/minecraft/assets/images/blocks/tree.png new file mode 100644 index 000000000..988af327f Binary files /dev/null and b/projects/minecraft/assets/images/blocks/tree.png differ diff --git a/projects/minecraft/assets/images/chevleft.png b/projects/minecraft/assets/images/chevleft.png new file mode 100644 index 000000000..83f0211e2 Binary files /dev/null and b/projects/minecraft/assets/images/chevleft.png differ diff --git a/projects/minecraft/assets/images/chevright.png b/projects/minecraft/assets/images/chevright.png new file mode 100644 index 000000000..ef9d2ad01 Binary files /dev/null and b/projects/minecraft/assets/images/chevright.png differ diff --git a/projects/minecraft/assets/images/logo.png.png b/projects/minecraft/assets/images/logo.png.png new file mode 100644 index 000000000..d77ebe8da Binary files /dev/null and b/projects/minecraft/assets/images/logo.png.png differ diff --git a/projects/minecraft/assets/sounds/boulders.mp3 b/projects/minecraft/assets/sounds/boulders.mp3 new file mode 100644 index 000000000..f89503141 Binary files /dev/null and b/projects/minecraft/assets/sounds/boulders.mp3 differ diff --git a/projects/minecraft/assets/sounds/minecraftclick.mp3 b/projects/minecraft/assets/sounds/minecraftclick.mp3 new file mode 100644 index 000000000..f41ae8c2e Binary files /dev/null and b/projects/minecraft/assets/sounds/minecraftclick.mp3 differ diff --git a/projects/minecraft/assets/style/animations.css b/projects/minecraft/assets/style/animations.css new file mode 100644 index 000000000..a1261f005 --- /dev/null +++ b/projects/minecraft/assets/style/animations.css @@ -0,0 +1,99 @@ +@keyframes jello { + 0% { + transform: scale3d(1, 1, 1); + } + + 30% { + transform: scale3d(1.25, 0.75, 1); + } + + 40% { + transform: scale3d(0.75, 1.25, 1); + } + + 50% { + transform: scale3d(1.15, 0.85, 1); + } + + 65% { + transform: scale3d(0.95, 1.05, 1); + } + + 75% { + transform: scale3d(1.05, 0.95, 1); + } + + 100% { + transform: scale3d(1, 1, 1); + } +} +@keyframes bouncein { + 0% { + animation-timing-function: ease-in; + opacity: 0; + transform: translateY(-250px); + } + + 38% { + animation-timing-function: ease-out; + opacity: 1; + transform: translateY(0); + } + + 55% { + animation-timing-function: ease-in; + transform: translateY(-65px); + } + + 72% { + animation-timing-function: ease-out; + transform: translateY(0); + } + + 81% { + animation-timing-function: ease-in; + transform: translateY(-28px); + } + + 90% { + animation-timing-function: ease-out; + transform: translateY(0); + } + + 95% { + animation-timing-function: ease-in; + transform: translateY(-8px); + } + + 100% { + animation-timing-function: ease-out; + transform: translateY(0); + } +} +@keyframes pulse { + 0% { + animation-timing-function: ease-out; + transform: scale(1); + transform-origin: center center; + } + + 10% { + animation-timing-function: ease-in; + transform: scale(0.91); + } + + 17% { + animation-timing-function: ease-out; + transform: scale(0.98); + } + + 33% { + animation-timing-function: ease-in; + transform: scale(0.87); + } + + 45% { + animation-timing-function: ease-out; + transform: scale(1); + } +} diff --git a/projects/minecraft/assets/style/game.css b/projects/minecraft/assets/style/game.css new file mode 100644 index 000000000..796195a36 --- /dev/null +++ b/projects/minecraft/assets/style/game.css @@ -0,0 +1,257 @@ +@import url('/assets/style/reset.css'); +@import url('/assets/style/animations.css'); +/* //animations */ + +.bounce { + animation: bouncein 1s ease 0s 1 normal forwards; +} + +.pulse { + animation: pulse 1s ease-in-out 0s 1 normal forwards; +} + +body { + height: 100vh; + width: 100wv; + + padding-bottom: 10vh; + background-color: black; +} + +#section { + display: flex; + justify-content: space-around; + flex-direction: column; + align-items: center; + height: 90vh; + background: black; +} +#gamegrid { + display: grid; + width: fit-content; + grid-template-columns: repeat(5, 1fr); + grid-template-rows: repeat(5, 1fr); + grid-column-gap: 0px; + grid-row-gap: 0px; + width: 100%; + height: 90vmin; +} +.tile { + opacity: 1; + transition: 0.5s; +} +.tile:hover { + border: 1px solid white; +} + +.leaves { + background: url('/assets/images/blocks/leaves.png') center center/cover + no-repeat; +} +.ruby { + background: url('/assets/images/blocks/ruby.png') center center/cover + no-repeat; +} +.coal { + background: url('/assets/images/blocks/coal.png') center center/cover + no-repeat; +} +.diamond { + background: url('/assets/images/blocks/diamond.png') center center/cover + no-repeat; +} +.stone { + background: url('/assets/images/blocks/stone.png') center center/cover + no-repeat; +} +.grass { + background: url('/assets/images/blocks/grass.png') center center/cover + no-repeat; +} +.tree { + background: url('/assets/images/blocks/tree.png') center center/cover + no-repeat; +} +.sky { + background-color: skyblue; +} +.playercontrols { + display: flex; + align-items: center; + height: 10vmin; + width: 100vw; +} + +.tools { + display: flex; + justify-self: end; + justify-content: end; + flex-grow: 0; +} +.buttons { + display: flex; + flex-grow: 1; + justify-content: center; +} +.inventory { + display: flex; + justify-self: start; + justify-content: start; +} +@media only screen and (max-width: 600px) { + #section { + display: flex; + /* justify-content: space-around; */ + flex-direction: column; + /* flex-flow: column-reverse; */ + align-items: center; + height: fit-content; + background: black; + } + + #gamegrid { + display: grid; + width: fit-content; + grid-template-columns: repeat(5, 1fr); + grid-template-rows: repeat(5, 1fr); + grid-column-gap: 0px; + grid-row-gap: 0px; + width: 100%; + height: 90vmin; + } + + .playercontrols { + display: flex; + flex-direction: column; + height: 10vmin; + width: 100vw; + } + .tools { + display: flex; + justify-content: end; + flex-grow: 0; + } + .buttons { + display: flex; + justify-content: center; + } + .inventory { + display: flex; + justify-content: start; + } +} +#shovel div { + width: 10vmin; + height: 10vmin; + background-color: white; + background: url('/assets/images/blocks/shovel.png') center center/contain; +} +#hatchet div { + width: 10vmin; + height: 10vmin; + background-color: white; + background: url('/assets/images/blocks/hatchet.png') center center/contain; +} +#pickaxe div { + width: 10vmin; + height: 10vmin; + background-color: white; + background: url('/assets/images/blocks/pickaxe.png') center center/contain; +} + +#leaves-inv div { + width: 10vmin; + height: 10vmin; + background-color: white; + background: url('/assets/images/blocks/leaves.png'); +} +#grass-inv div { + width: 10vmin; + height: 10vmin; + background-color: white; + background: url('/assets/images/blocks/grass.png'); +} +#tree-inv div { + width: 10vmin; + height: 10vmin; + background-color: white; + background: url('/assets/images/blocks/tree.png'); +} +#stone-inv div { + width: 10vmin; + height: 10vmin; + background-color: white; + background: url('/assets/images/blocks/stone.png'); +} +#coal-inv div { + width: 10vmin; + height: 10vmin; + background-color: white; + background: url('/assets/images/blocks/coal.png'); +} +#ruby-inv div { + width: 10vmin; + height: 10vmin; + background-color: white; + background: url('/assets/images/blocks/ruby.png'); +} +#diamond-inv div { + width: 10vmin; + height: 10vmin; + background-color: white; + background: url('/assets/images/blocks/diamond.png'); +} +.control-shadow { + transition: 1s; + -webkit-box-shadow: inset 0px 0px 0px 2px black; + -moz-box-shadow: inset 0px 0px 0px 2px black; + box-shadow: inset 0px 0px 0px 2px black; +} +.control-shadow:hover { + -webkit-box-shadow: inset 0px 0px 0px 2px yellow; + -moz-box-shadow: inset 0px 0px 0px 2px yellow; + box-shadow: inset 0px 0px 0px 2px yellow; + cursor: grab; +} +.control-shadow:active { + cursor: grabbing; +} +.control-active { + -webkit-box-shadow: inset 0px 0px 0px 2px yellow; + -moz-box-shadow: inset 0px 0px 0px 2px yellow; + box-shadow: inset 0px 0px 0px 2px yellow; +} +.inv-txt { + color: yellow; + text-align: center; + font-size: 1rem; + font-weight: bold; +} +.btn { + transition: 1s; + display: flex; + color: black; + align-items: center; + cursor: pointer; + height: fit-content; + font-size: 2.5vmin; + font-weight: bold; + padding: 0.5rem; + border-radius: 1rem; + background-color: rgba(255, 255, 255, 0.5); +} +.btn:hover { + box-shadow: 2px 2px 0 rgba(233, 217, 0, 0.5), + 2px -2px 0 rgba(233, 217, 0, 0.5), -2px 2px 0 rgba(233, 217, 0, 0.5), + -2px -2px 0 rgba(233, 217, 0, 0.5), 2px 0px 0 rgba(233, 217, 0, 0.5), + 0px 2px 0 rgba(233, 217, 0, 0.5), -2px 0px 0 rgba(233, 217, 0, 0.5), + 0px -2px 0 rgba(233, 217, 0, 0.5); + text-shadow: 2px 2px 0 rgba(233, 217, 0, 0.5), + 2px -2px 0 rgba(233, 217, 0, 0.5), -2px 2px 0 rgba(233, 217, 0, 0.5), + -2px -2px 0 rgba(233, 217, 0, 0.5), 2px 0px 0 rgba(233, 217, 0, 0.5), + 0px 2px 0 rgba(233, 217, 0, 0.5), -2px 0px 0 rgba(233, 217, 0, 0.5), + 0px -2px 0 rgba(233, 217, 0, 0.5); +} +.hidden { + display: none; +} diff --git a/projects/minecraft/assets/style/reset.css b/projects/minecraft/assets/style/reset.css new file mode 100644 index 000000000..40ff518d2 --- /dev/null +++ b/projects/minecraft/assets/style/reset.css @@ -0,0 +1,6 @@ +body { + padding: 0; + margin: 0; + box-sizing: border-box; + font-size: 62.5%; +} diff --git a/projects/minecraft/assets/style/style.css b/projects/minecraft/assets/style/style.css new file mode 100644 index 000000000..7fc13b155 --- /dev/null +++ b/projects/minecraft/assets/style/style.css @@ -0,0 +1,159 @@ +@import url('/assets/style/reset.css'); +@import url('/assets/style/animations.css'); + +body { + height: 100vh; + width: 100wv; + padding-top: 5vh; + background-color: black; +} + +/* Loader */ +#loader { + display: flex; + justify-content: center; + align-items: center; +} +.loader { + border: 16px solid #f3f3f3; + border-radius: 50%; + border-top: 16px solid #3498db; + width: 120px; + height: 120px; + -webkit-animation: spin 2s linear infinite; /* Safari */ + animation: spin 2s linear infinite; +} + +/* Safari */ +@-webkit-keyframes spin { + 0% { + -webkit-transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(360deg); + } +} + +@keyframes spin { + 0% { + transform: rotate(0deg); + } + 100% { + transform: rotate(360deg); + } +} + +/* */ + +#section { + display: flex; + justify-content: space-around; + flex-direction: column; + align-items: center; + height: 90vh; + background: url('/assets/images/bgimg.jpg') center center/cover no-repeat; +} +.logo { + width: 40vw; +} + +.buttons { + display: flex; + justify-content: center; + align-items: center; + background-color: rgba(0, 0, 0, 0.5); + border-radius: 1rem; + color: white; + box-shadow: 2px 2px 0 black, 2px -2px 0 black, -2px 2px 0 black, + -2px -2px 0 black, 2px 0px 0 black, 0px 2px 0 black, -2px 0px 0 black, + 0px -2px 0 black; +} +.buttons i { + font-size: 5vmin; + text-shadow: 2px 2px 0 black, 2px -2px 0 black, -2px 2px 0 black, + -2px -2px 0 black, 2px 0px 0 black, 0px 2px 0 black, -2px 0px 0 black, + 0px -2px 0 black; + transition: 1s; +} +.buttons i:hover { + color: #ffffff; + text-shadow: 2px 2px 0 rgba(233, 217, 0, 0.5), + 2px -2px 0 rgba(233, 217, 0, 0.5), -2px 2px 0 rgba(233, 217, 0, 0.5), + -2px -2px 0 rgba(233, 217, 0, 0.5), 2px 0px 0 rgba(233, 217, 0, 0.5), + 0px 2px 0 rgba(233, 217, 0, 0.5), -2px 0px 0 rgba(233, 217, 0, 0.5), + 0px -2px 0 rgba(233, 217, 0, 0.5); +} +.buttons h1 { + margin: 0 3vmin; + font-size: 7vmin; + text-shadow: 2px 2px 0 black, 2px -2px 0 black, -2px 2px 0 black, + -2px -2px 0 black, 2px 0px 0 black, 0px 2px 0 black, -2px 0px 0 black, + 0px -2px 0 black; +} +#widthcontainer, +#heightcontainer { + display: flex; + align-items: center; + + padding: 0 4vmin; +} +#startBtn, +#sandboxBtn { + transition: 1s; + display: flex; + color: black; + align-items: center; + cursor: pointer; + height: fit-content; + font-size: 2.5vmin; + font-weight: bold; + padding: 0.5rem; + border-radius: 1rem; + background-color: rgba(255, 255, 255, 0.5); + /* text-shadow: 2px 2px 0 rgba(255, 255, 255, 0.5), + 2px -2px 0 rgba(255, 255, 255, 0.5), -2px 2px 0 rgba(255, 255, 255, 0.5), + -2px -2px 0 rgba(255, 255, 255, 0.5), 2px 0px 0 rgba(255, 255, 255, 0.5), + 0px 2px 0 rgba(255, 255, 255, 0.5), -2px 0px 0 rgba(255, 255, 255, 0.5), + 0px -2px 0 rgba(255, 255, 255, 0.5); */ +} +#startBtn:hover, +#sandboxBtn:hover { + box-shadow: 2px 2px 0 rgba(233, 217, 0, 0.5), + 2px -2px 0 rgba(233, 217, 0, 0.5), -2px 2px 0 rgba(233, 217, 0, 0.5), + -2px -2px 0 rgba(233, 217, 0, 0.5), 2px 0px 0 rgba(233, 217, 0, 0.5), + 0px 2px 0 rgba(233, 217, 0, 0.5), -2px 0px 0 rgba(233, 217, 0, 0.5), + 0px -2px 0 rgba(233, 217, 0, 0.5); + text-shadow: 2px 2px 0 rgba(233, 217, 0, 0.5), + 2px -2px 0 rgba(233, 217, 0, 0.5), -2px 2px 0 rgba(233, 217, 0, 0.5), + -2px -2px 0 rgba(233, 217, 0, 0.5), 2px 0px 0 rgba(233, 217, 0, 0.5), + 0px 2px 0 rgba(233, 217, 0, 0.5), -2px 0px 0 rgba(233, 217, 0, 0.5), + 0px -2px 0 rgba(233, 217, 0, 0.5); +} +.jello { + animation: jello 1s ease 0s 1 normal forwards; +} +.selectionBox { + display: flex; + flex-direction: column; + align-items: center; +} +.selectionBox > h1 { + color: white; + font-size: 2vmin; + text-shadow: 2px 2px 0 black, 2px -2px 0 black, -2px 2px 0 black, + -2px -2px 0 black, 2px 0px 0 black, 0px 2px 0 black, -2px 0px 0 black, + 0px -2px 0 black; +} +.gameintro { + flex-direction: column; +} +.toolname { + color: yellow !important; + font-weight: bold; +} +.skybluetxt { + color: skyblue; +} +#selbox1 { + margin-bottom: 5vh; +} diff --git a/projects/minecraft/game.html b/projects/minecraft/game.html new file mode 100644 index 000000000..96c2597c4 --- /dev/null +++ b/projects/minecraft/game.html @@ -0,0 +1,64 @@ + + + + + + + + + "Minecraft" | Play + + + + + +
+
+ +
+
+
+
+
0
+
+
+
0
+
+
+
0
+
+
+
0
+
+
+
0
+
+
+
0
+
+
+
0
+
+
+
+ + + + + +
+
+
+
+
+
+
+
+
+
+
+
+
+ + + \ No newline at end of file diff --git a/projects/minecraft/index.html b/projects/minecraft/index.html new file mode 100644 index 000000000..98a9b8862 --- /dev/null +++ b/projects/minecraft/index.html @@ -0,0 +1,55 @@ + + + + + + + + Minecraft | Menu + + + + + + + + + + +
+ +
+
+
+
+
+

A little bit about the game

+

You can harvest all tiles for materials except the "sky" tiles + using the according tools:

+

Hatchet: Leaves & Trees | Pickaxe: Coal + , Ruby , Diamond & Stone | Shovel: Grass

+

You can then take the materials from your inventory and place them on any unoccupied tile

+

In the sandbox you will start off with a blank map and lots of materials to your disposal

+
+
+
+

Select Map Size

+
+
+ +

24

+ +
+ + +
+ +

24

+ +
+
+
+
+ + + \ No newline at end of file diff --git a/projects/minecraft/modules/game.js b/projects/minecraft/modules/game.js new file mode 100644 index 000000000..92ad85fce --- /dev/null +++ b/projects/minecraft/modules/game.js @@ -0,0 +1,255 @@ +//imports +import { buildPlayerBoard } from "./gridGenerator.js" +import { inventory } from "./gridGenerator.js" +//initialize board +buildPlayerBoard() +document.addEventListener('DOMContentLoaded', function () { + updateUI() + +}, false); +//dom elements +const leavesAmt = document.querySelector('#leaves-amt'); +const grassAmt = document.querySelector('#grass-amt'); +const treeAmt = document.querySelector('#tree-amt'); +const stoneAmt = document.querySelector('#stone-amt'); +const coalAmt = document.querySelector('#coal-amt'); +const rubyAmt = document.querySelector('#ruby-amt'); +const diamondAmt = document.querySelector('#diamond-amt'); +const pickaxe = document.querySelector('#pickaxe'); +const hatchet = document.querySelector('#hatchet'); +const shovel = document.querySelector('#shovel'); +const invblocks = document.querySelectorAll('.control-shadow') +const body = document.querySelector('body') +const gamegrid = document.querySelector('#gamegrid') +//buttons +export const restartBtn = document.querySelector('#restartBtn') +const menuBtn = document.querySelector('#menuBtn') +const nvmBtn = document.querySelector('#nvmBtn') +export const resetBtn = document.querySelector('#resetBtn') + +//Inventory listeners +restartBtn.addEventListener('click', (e) => { + e.target.classList.add('hidden') + resetBtn.classList.remove('hidden') + menuBtn.classList.remove('hidden') + nvmBtn.classList.remove('hidden') +}) +nvmBtn.addEventListener('click', (e) => { + e.target.classList.add('hidden') + resetBtn.classList.add('hidden') + menuBtn.classList.add('hidden') + restartBtn.classList.remove('hidden') +}) +menuBtn.addEventListener('click', () => { + location.href = './' +}) +resetBtn.addEventListener('click', (e) => { + e.target.classList.add('hidden') + menuBtn.classList.add('hidden') + nvmBtn.classList.add('hidden') + restartBtn.classList.add('hidden') + resetBtn.disabled = true + resetWorld() +}) + +function resetWorld() { //resets our world and inventory on the current configuration without going back to menu. + let inv = JSON.parse(localStorage.getItem('inv')); + inventory.coal = inv.coal + inventory.ruby = inv.ruby + inventory.stone = inv.stone + inventory.tree = inv.tree + inventory.diamond = inv.diamond + inventory.grass = inv.grass + inventory.leaves = inv.leaves + updateUI() + gamegrid.innerHTML = '' + buildPlayerBoard() +} + +//UI Listeners +leavesAmt.addEventListener('click', (e) => { + if (inventory.leaves > 0) { + resetTools() + e.target.classList.add('control-active') + body.style.cursor = `url('/assets/images/blocks/Cursors/leaves.cur') , auto` + setTool('leaves') + } +}) +grassAmt.addEventListener('click', (e) => { + if (inventory.grass > 0) { + resetTools() + body.style.cursor = `url('/assets/images/blocks/Cursors/grass.cur') , auto` + e.target.classList.add('control-active') + setTool('grass') + } +}) +treeAmt.addEventListener('click', (e) => { + if (inventory.tree > 0) { + resetTools() + body.style.cursor = `url('/assets/images/blocks/Cursors/tree.cur') , auto` + e.target.classList.add('control-active') + setTool('tree') + } +}) +stoneAmt.addEventListener('click', (e) => { + if (inventory.stone > 0) { + resetTools() + body.style.cursor = `url('/assets/images/blocks/Cursors/stone.cur') , auto` + e.target.classList.add('control-active') + setTool('stone') + } +}) +coalAmt.addEventListener('click', (e) => { + if (inventory.coal > 0) { + resetTools() + body.style.cursor = `url('/assets/images/blocks/Cursors/coal.cur') , auto` + e.target.classList.add('control-active') + setTool('coal') + } +}) +rubyAmt.addEventListener('click', (e) => { + if (inventory.ruby > 0) { + resetTools() + body.style.cursor = `url('/assets/images/blocks/Cursors/ruby.cur') , auto` + e.target.classList.add('control-active') + setTool('ruby') + } +}) +diamondAmt.addEventListener('click', (e) => { + if (inventory.diamond > 0) { + resetTools() + body.style.cursor = `url('/assets/images/blocks/Cursors/diamond.cur') , auto` + e.target.classList.add('control-active') + setTool('diamond') + } +}) +pickaxe.addEventListener('click', (e) => { + resetTools() + body.style.cursor = `url('/assets/images/blocks/Cursors/pickaxe.cur') , auto` + e.target.classList.add('control-active') + setTool('pickaxe') +}) +hatchet.addEventListener('click', (e) => { + resetTools() + body.style.cursor = `url('/assets/images/blocks/Cursors/hatchet.cur') , auto` + e.target.classList.add('control-active') + setTool('hatchet') +}) +shovel.addEventListener('click', (e) => { + resetTools() + body.style.cursor = `url('/assets/images/blocks/Cursors/shovel.cur') , auto` + e.target.classList.add('control-active') + setTool('shovel') +}) + +function setTool(tool) {//sets our current tool variable's value so we can identify what were clicking with + inventory.currentTool = tool; +} + + +export function clickTile(e) {//holds our tile "harvesting" logic + let tool = inventory.currentTool; + let classList = e.target.classList + let tileId = e.target.id.split('x') + tileId[1]-- + let nextTileAbove = document.querySelector(`#${tileId.join('x')}`) + if (classList.contains('leaves') && tool === 'hatchet' && nextTileAbove.classList.contains('sky')) { + classList.remove('leaves') + classList.add('sky') + leavesAmt.classList.add('pulse') + inventory.leaves += 1 + } else if (classList.contains('ruby') && tool === 'pickaxe' && nextTileAbove.classList.contains('sky')) { + classList.remove('ruby') + classList.add('sky') + rubyAmt.classList.add('pulse') + inventory.ruby += 1 + } else if (classList.contains('diamond') && tool === 'pickaxe' && nextTileAbove.classList.contains('sky')) { + classList.remove('diamond') + classList.add('sky') + diamondAmt.classList.add('pulse') + inventory.diamond += 1 + } else if (classList.contains('coal') && tool === 'pickaxe' && nextTileAbove.classList.contains('sky')) { + classList.remove('coal') + classList.add('sky') + coalAmt.classList.add('pulse') + inventory.coal += 1 + } else if (classList.contains('tree') && tool === 'hatchet' && nextTileAbove.classList.contains('sky')) { + classList.remove('tree') + classList.add('sky') + treeAmt.classList.add('pulse') + inventory.tree += 1 + } else if (classList.contains('grass') && tool === 'shovel' && nextTileAbove.classList.contains('sky')) { + classList.remove('grass') + classList.add('sky') + grassAmt.classList.add('pulse') + inventory.grass += 1 + } else if (classList.contains('stone') && tool === 'pickaxe' && nextTileAbove.classList.contains('sky')) { + classList.remove('stone') + classList.add('sky') + stoneAmt.classList.add('pulse') + inventory.stone += 1 + } else if (classList.contains('sky') && nextTileAbove != null) { + layTile(e) + } + updateUI() +} + +function layTile(e) {//holds our tile "laying" logic + let classList = e.target.classList + let currentTool = inventory.currentTool + if (currentTool === 'leaves' && inventory.leaves > 0) { + classList.add('leaves') + classList.remove('sky') + inventory.leaves-- + + } else if (currentTool === 'ruby' && inventory.ruby > 0) { + classList.add('ruby') + classList.remove('sky') + inventory.ruby-- + + } else if (currentTool === 'diamond' && inventory.diamond > 0) { + classList.add('diamond') + classList.remove('sky') + inventory.diamond-- + + } else if (currentTool === 'coal' && inventory.coal > 0) { + classList.add('coal') + classList.remove('sky') + inventory.coal-- + + } else if (currentTool === 'grass' && inventory.grass > 0) { + classList.add('grass') + classList.remove('sky') + inventory.grass-- + + } else if (currentTool === 'tree' && inventory.tree > 0) { + classList.add('tree') + classList.remove('sky') + inventory.tree-- + + } else if (currentTool === 'stone' && inventory.stone > 0) { + classList.add('stone') + classList.remove('sky') + inventory.stone-- + + } +} + +function resetTools() {//sets all tools to "unactive" visually + invblocks.forEach(element => { + element.classList.remove('control-active') + }) +} + +function updateUI() { // updates our UI + invblocks.forEach(element => { + setTimeout(() => { element.classList.remove('pulse') }, 500) + }) + leavesAmt.innerHTML = inventory.leaves + grassAmt.innerHTML = inventory.grass + treeAmt.innerHTML = inventory.tree + stoneAmt.innerHTML = inventory.stone + coalAmt.innerHTML = inventory.coal + rubyAmt.innerHTML = inventory.ruby + diamondAmt.innerHTML = inventory.diamond +} \ No newline at end of file diff --git a/projects/minecraft/modules/gridGenerator.js b/projects/minecraft/modules/gridGenerator.js new file mode 100644 index 000000000..e4671e53d --- /dev/null +++ b/projects/minecraft/modules/gridGenerator.js @@ -0,0 +1,63 @@ +import { clickTile, resetBtn, restartBtn } from "./game.js"; + +let matrixBoard = JSON.parse(localStorage.getItem('map')); // pulls out the map generated earlier by tileGenerator.js + +export let inventory = JSON.parse(localStorage.getItem('inv')); +const grid = document.querySelector('#gamegrid') +const rocks = document.querySelector('#rocksSound') + +export function buildPlayerBoard() { // laying the "bricks" + rocks.play() + let tileDelay = 0 // just a delay counter for our setTimeout "drop" animation. + grid.style.gridTemplateRows = `repeat(${matrixBoard.length},1fr)` //sets our grid rows + grid.style.gridTemplateColumns = `repeat(${matrixBoard[0].length},1fr)` //sets our grid columns + matrixBoard.forEach((rows, ridx) => { // starts laying the bricks by reading our matrixBoard and making descisions + rows.forEach((col, cidx) => { + let tile = document.createElement('div') + tile.classList.add('tile') + switch (col) { + case 'leaves': + tile.classList.add('leaves') + break; + case 'ruby': + tile.classList.add('ruby') + break; + case 'diamond': + tile.classList.add('diamond') + break; + case 'coal': + tile.classList.add('coal') + break; + case 'tree': + tile.classList.add('tree') + break; + case 'grass': + tile.classList.add('grass') + break; + case 'stone': + tile.classList.add('stone') + break; + case 'sky': + tile.classList.add('sky') + break; + default: + break; + } + tileDelay += 10 + setTimeout(() => { + grid.appendChild(tile) + tile.classList.add('bounce') + tile.id = `x${ridx}x${cidx}` // sets an id , so we can later use it to identify if there is a block or sky tile above us + tile.addEventListener('click', (e) => { // adding an event listener to each individual tile. + clickTile(e) + }) + + }, tileDelay) + }) + }) + setTimeout(() => { //stops our falling rocks sfx , and brings out our game menu buttons + rocks.pause() + restartBtn.classList.remove('hidden') + resetBtn.disabled = false + }, tileDelay) +} \ No newline at end of file diff --git a/projects/minecraft/modules/index.js b/projects/minecraft/modules/index.js new file mode 100644 index 000000000..cdbe65156 --- /dev/null +++ b/projects/minecraft/modules/index.js @@ -0,0 +1,136 @@ +//////////////Load manager +import { generateArray } from "./tileGenerator.js"; +document.onreadystatechange = function () { + if (document.readyState !== "complete") { + document.querySelector("body").style.display = "none"; + document.querySelector("#loader").style.visibility = "visible"; + } else { + document.querySelector("#loader").style.display = "none"; + document.querySelector("body").style.display = ""; + } +}; +//Game Board size vars +let height = 24; +let width = 24; +//Sounds +const clickSound = document.querySelector('#clickSound'); +//html elements +let arrows = document.querySelectorAll(".arrow"); +let widthEl = document.querySelector('#Width'); +let heightEl = document.querySelector('#Height') +let decWidth = document.querySelector('#decWidth') +let incWidth = document.querySelector('#incWidth') +let decHeight = document.querySelector('#decHeight') +let incHeight = document.querySelector('#incHeight') +const startBtn = document.querySelector('#startBtn'); +const sandboxBtn = document.querySelector('#sandboxBtn') +//Event Listeners +arrows.forEach(element => { // add a sound event listener on click for each Chevron + element.addEventListener('click', function (e) { + clickSound.play() + }) +}) + +decWidth.addEventListener('click', () => { + modSize('decWidth') +}) + +incWidth.addEventListener('click', () => { + modSize('incWidth') +}) + +decHeight.addEventListener('click', () => { + modSize('decHeight') +}) + +incHeight.addEventListener('click', () => { + modSize('incHeight') +}) + +startBtn.addEventListener('click', () => {//our start button which initiates an empty inventory and stores it in localStorage + generateArray(width, height, 'normal') + location.href = '/game.html' + let inventory = { + currentTool: 0, + leaves: 0, + ruby: 0, + diamond: 0, + coal: 0, + tree: 0, + grass: 0, + stone: 0 + } + + localStorage.setItem('inv', JSON.stringify(inventory)) +}) +sandboxBtn.addEventListener('click', () => {//our sandbox button which initiates a full inventory and stores it in localStorage + generateArray(width, height, 'sandbox') + location.href = '/game.html' + let inventory = { + currentTool: 999, + leaves: 999, + ruby: 999, + diamond: 999, + coal: 999, + tree: 999, + grass: 999, + stone: 999 + } + localStorage.setItem('inv', JSON.stringify(inventory)) +}) + + + +function modSize(params) { //Updates the board size values to be used later as arguments in our gridGenerator function. + switch (params) { + case 'decWidth': + if (width > 10) { + width-- + } + updateNums('left'); + break; + case 'incWidth': + if (width < 40) { + width++ + } + updateNums('left'); + break; + case 'decHeight': + if (height > 10) { + height-- + } + updateNums('right'); + break; + case 'incHeight': + if (height < 40) { + height++ + } + updateNums('right'); + break; + default: + break; + } + +} +function updateNums(side) { //Updates the Numbers on board size selection box + switch (side) { + case 'left': + widthEl.innerHTML = width + widthEl.classList.toggle('jello') + break; + case 'right': + heightEl.innerHTML = height + heightEl.classList.toggle('jello') + break; + default: + break; + } + setTimeout(() => { + widthEl.classList.remove('jello') + heightEl.classList.remove('jello') + }, 500) + +} + + + diff --git a/projects/minecraft/modules/tileGenerator.js b/projects/minecraft/modules/tileGenerator.js new file mode 100644 index 000000000..4b5ebdc0d --- /dev/null +++ b/projects/minecraft/modules/tileGenerator.js @@ -0,0 +1,88 @@ +let result = [] //initiates a new array to hold our generated Grid + +export function fillArray(width, height) {// filles the array above with arrays full of 0's according to the user's width and height selection + let tempres = [] + for (let i = 0; i < height; i++) { + let zeroArr = new Array(width).fill(0) + tempres.push(zeroArr) + + } + result = tempres +} + +export function generateArray(width, height, mode) { //generates a randomized map by my algorithm , takes 3 parameters width , height , and gamemode. + fillArray(width, height) + if (mode === 'normal') {//if user has chosen normal mode starts generation of world + let maxTrees = Math.floor(width * 0.3) - 2 // defines the maximum amount of trees considering map size + let currentLayer = 4 // holds the current layer of map construction sky is 4 , leaves are 3 , trees are 2 etc.. + for (let row = 0; row < height; row++) { // starts iterating over the "result" arrays + for (let col = 0; col < width; col++) { // iterates inside the current array + if (row < height * 0.2) { // lays down the sky on 20% mapsize + result[row][col] = 'sky' + + } else if (row < height * 0.4) { // lays down leaves on 40% mapsize + currentLayer = 3 + let roll = Math.floor(Math.random() * 16) + 1 + if (result[row][col] == 0 && roll < 8 && currentLayer == 3 && maxTrees > 0) { + result[row][col] = 'leaves' + result[row][col + 1] = 'leaves' + result[row][col + 2] = 'leaves' + maxTrees-- + } + else if (result[row - 1][col] === 'leaves' && result[row][col] == 0) { + result[row][col] = 'leaves' + result[row][col + 1] = 'leaves' + result[row][col + 2] = 'leaves' + } else if (result[row][col] == 0) { + result[row][col] = 'sky' + } + } else if (row < height * 0.7) {//lays down tree trunks in the middle the right position , using some logic. + if (result[row - 1][col + 1] === 'leaves' && result[row][col] == 0) { + result[row][col] = 'sky' + result[row][col + 1] = 'sky' + result[row][col + 2] = 'tree' + } else if (result[row - 1][col + 1] === 'tree' && result[row][col] == 0) { + result[row][col] = 'sky' + result[row][col + 1] = 'tree' + result[row][col + 2] = 'sky' + } else if (result[row][col] === 0) { + result[row][col] = 'sky' + } + } else if (row < height * 1) { // lays a layer of grass and continues on from the next layer to lay materials randomly + let roll2 = Math.floor(Math.random() * 4) + 1 + if (result[row - 1][col] === 'sky' && result[row][col] == 0) { + result[row].fill('grass') + } else if (result[row][col] == 0) { + switch (roll2) { + case 1: + result[row][col] = 'diamond' + break; + case 2: + result[row][col] = 'stone' + break; + case 3: + result[row][col] = 'coal' + break; + case 4: + result[row][col] = 'ruby' + break; + + default: + break; + } + + } + } + + } + } + } else if (mode === 'sandbox') { // in sandbox mode generates an empy map according to users mapsize selection + for (let row = 0; row < height; row++) { + for (let col = 0; col < width; col++) { + + result[row][col] = 'sky' + } + } + } + localStorage.setItem('map', JSON.stringify(result)) +} \ No newline at end of file