diff --git a/.github/workflows/gh-pages.yml b/.github/workflows/gh-pages.yml new file mode 100644 index 0000000..dc2415f --- /dev/null +++ b/.github/workflows/gh-pages.yml @@ -0,0 +1,22 @@ +name: Github Pages + +on: + push: + branches: + - main +jobs: + deploy: + runs-on: ubuntu-20.04 + concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + steps: + - uses: actions/checkout@v2 + with: + submodules: true # Fetch Hugo themes (true OR recursive) + fetch-depth: 0 # Fetch all history for .GitInfo and .Lastmod + - name: Deploy + uses: peaceiris/actions-gh-pages@v3 + if: ${{ github.ref == 'refs/heads/main' }} + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_dir: ./ \ No newline at end of file diff --git a/Assignment Project SE.pdf b/Assignment Project SE.pdf deleted file mode 100644 index 93e50c1..0000000 Binary files a/Assignment Project SE.pdf and /dev/null differ diff --git a/README.md b/README.md new file mode 100644 index 0000000..380f411 --- /dev/null +++ b/README.md @@ -0,0 +1,12 @@ +# se-be1-kelompok5 + +link: +https://rg-km.github.io/se-be1-kelompok5//snake-game/index.html + +Anggota: +- Rachmat Agung Ananda (BE2279833) +- Syaddad Auliarahman (BE2170681) +- Rahma Khairun'nisa Nailah (BE2064986) +- Muhammad Abid Fajar (BE2219863) + +![image](https://user-images.githubusercontent.com/69112136/158063830-0991ee93-36d4-4827-955e-126e412d5775.png) diff --git a/index.html b/index.html new file mode 100644 index 0000000..21b3e9f --- /dev/null +++ b/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/snake-game/assets/NaikLevel.mp3 b/snake-game/assets/NaikLevel.mp3 new file mode 100644 index 0000000..32b2d77 Binary files /dev/null and b/snake-game/assets/NaikLevel.mp3 differ diff --git a/snake-game/assets/apple.png b/snake-game/assets/apple.png new file mode 100644 index 0000000..47c6b57 Binary files /dev/null and b/snake-game/assets/apple.png differ diff --git a/snake-game/assets/body.png b/snake-game/assets/body.png new file mode 100644 index 0000000..312a52b Binary files /dev/null and b/snake-game/assets/body.png differ diff --git a/snake-game/assets/dummy.txt b/snake-game/assets/dummy.txt deleted file mode 100644 index e69de29..0000000 diff --git a/snake-game/assets/game-over.wav b/snake-game/assets/game-over.wav new file mode 100644 index 0000000..047b030 Binary files /dev/null and b/snake-game/assets/game-over.wav differ diff --git a/snake-game/assets/head.png b/snake-game/assets/head.png new file mode 100644 index 0000000..23ce0a5 Binary files /dev/null and b/snake-game/assets/head.png differ diff --git a/snake-game/assets/life.png b/snake-game/assets/life.png new file mode 100644 index 0000000..890f86d Binary files /dev/null and b/snake-game/assets/life.png differ diff --git a/snake-game/index.html b/snake-game/index.html index 293690c..13d2b96 100644 --- a/snake-game/index.html +++ b/snake-game/index.html @@ -1,13 +1,17 @@ - - - - - -

Snake

- - - - - - + + + + + + +

Snake

+ + + + +

+

+

+ + \ No newline at end of file diff --git a/snake-game/index.js b/snake-game/index.js index 4c9ef98..2c1886d 100644 --- a/snake-game/index.js +++ b/snake-game/index.js @@ -1,275 +1,409 @@ -const CELL_SIZE = 20; -const CANVAS_SIZE = 400; -const REDRAW_INTERVAL = 50; -const WIDTH = CANVAS_SIZE / CELL_SIZE; -const HEIGHT = CANVAS_SIZE / CELL_SIZE; -const DIRECTION = { - LEFT: 0, - RIGHT: 1, - UP: 2, - DOWN: 3, -} -let MOVE_INTERVAL = 150; - -function initPosition() { - return { - x: Math.floor(Math.random() * WIDTH), - y: Math.floor(Math.random() * HEIGHT), - } -} - -function initHeadAndBody() { - let head = initPosition(); - let body = [{x: head.x, y: head.y}]; - return { - head: head, - body: body, - } -} - -function initDirection() { - return Math.floor(Math.random() * 4); -} - -function initSnake(color){ - return { - color: color, - ...initHeadAndBody(), - direction: initDirection(), - score: 0, - } -} - -let snake = initSnake("green"); - -let apple1 = { - color: "yellow", - position: initPosition(), -} -let apple2 = { - color: "yellow", - position: initPosition(), -} - -let lifes = [ - { - color: "red", - position: initPosition(), - lifes: 3, - }, -]; - -function drawCell(ctx, x, y, color) { - ctx.fillStyle = color; - ctx.fillRect(x * CELL_SIZE, y * CELL_SIZE, CELL_SIZE, CELL_SIZE); -} - -function drawlifes(lifes){ - let lifesCanvas; - if (lifes.color == lifes.color) { - lifesCanvas = document.getElementById("score3Board"); - } - let lifesCtx = lifesCanvas.getContext("2d"); - - lifesCtx.clearRect(0, 0, CANVAS_SIZE, CANVAS_SIZE); - lifesCtx.font = "25px Arial"; - lifesCtx.fillStyle = lifes.color - lifesCtx.fillText("Life: \n" + lifes[0].lifes, 10, lifesCanvas.scrollHeight / 2); -} - -function drawScore(snake) { - let scoreCanvas; - if (snake.color == snake.color) { - scoreCanvas = document.getElementById("score1Board"); - } else { - scoreCanvas = document.getElementById("score2Board"); - } - let scoreCtx = scoreCanvas.getContext("2d"); - - scoreCtx.clearRect(0, 0, CANVAS_SIZE, CANVAS_SIZE); - scoreCtx.font = "30px Arial"; - scoreCtx.fillStyle = snake.color - scoreCtx.fillText(snake.score, 10, scoreCanvas.scrollHeight / 2); -} - -function draw() { - setInterval(function() { - let snakeCanvas = document.getElementById("snakeBoard"); - let ctx = snakeCanvas.getContext("2d"); - - ctx.clearRect(0, 0, CANVAS_SIZE, CANVAS_SIZE); - - drawCell(ctx, snake.head.x, snake.head.y, snake.color); - //loop - for (let i = 1; i < snake.body.length; i++) { - drawCell(ctx, snake.body[i].x, snake.body[i].y, snake.color); - } - - // loop untuk menampilkan life jika dibilangan prima - let pembagi = 0; - for(let i = 0; i <= snake.score; i++){ - if(snake.score % i == 0){ - pembagi++; - } - } - if (pembagi == 2){ - for (let i = 0; i < lifes.length; i++) { - let life = lifes[i]; - - var img = document.getElementById("lifes"); - ctx.drawImage(img, life.position.x * CELL_SIZE, life.position.y * CELL_SIZE, CELL_SIZE, CELL_SIZE); - } - } - - drawCell(ctx, apple1.position.x, apple1.position.y, apple1.color); - drawCell(ctx, apple2.position.x, apple2.position.y, apple2.color); - - drawScore(snake); - drawlifes(lifes); - }, REDRAW_INTERVAL); -} - -function teleport(snake) { - if (snake.head.x < 0) { - snake.head.x = CANVAS_SIZE / CELL_SIZE - 1; - } - if (snake.head.x >= WIDTH) { - snake.head.x = 0; - } - if (snake.head.y < 0) { - snake.head.y = CANVAS_SIZE / CELL_SIZE - 1; - } - if (snake.head.y >= HEIGHT) { - snake.head.y = 0; - } -} - -function eat(snake, apple1, apple2, lifes) { - if (snake.head.x == apple1.position.x && snake.head.y == apple1.position.y) { - apple1.position = initPosition(); - snake.score++; - //this - snake.body.push({x: snake.head.x, y: snake.head.y}); - } - if (snake.head.x == apple2.position.x && snake.head.y == apple2.position.y) { - apple2.position = initPosition(); - snake.score++; - //this - snake.body.push({x: snake.head.x, y: snake.head.y}); - } - for (let i = 0; i < lifes.length; i++) { - let life = lifes[i]; - if (snake.head.x == life.position.x && snake.head.y == life.position.y) { - life.position = initPosition(); - life.lifes++; - snake.score++; - } - } -} - -function moveLeft(snake) { - snake.head.x--; - teleport(snake); - eat(snake, apple1, apple2, lifes); -} - -function moveRight(snake) { - snake.head.x++; - teleport(snake); - eat(snake, apple1, apple2, lifes); -} - -function moveDown(snake) { - snake.head.y++; - teleport(snake); - eat(snake, apple1, apple2, lifes); -} - -function moveUp(snake) { - snake.head.y--; - teleport(snake); - eat(snake, apple1, apple2, lifes); -} - -function EatSelf(snake){ - let isEatSelf = false; - - for(var i = 0; i < snake.length; i++){ - for(var o = 0; o < snake.length; o++){ - for(var p = 1; p < snake[o].body.length; p++){ - if (snake[i].head.x == snake[o].body[p].x && snake[i].head.y == snake[o].body[p].y) { - isEatSelf = true; - } - } - } - } - if(isEatSelf == true){ - lifes[0].lifes -= 1; - return isEatSelf = false; - } else if(lifes[0].lifes <= 0){ - alert("Game over"); - window.location.reload(); - } - return isEatSelf; -} - -function move(snake) { - switch (snake.direction) { - case DIRECTION.LEFT: - moveLeft(snake); - break; - case DIRECTION.RIGHT: - moveRight(snake); - break; - case DIRECTION.DOWN: - moveDown(snake); - break; - case DIRECTION.UP: - moveUp(snake); - break; - } - moveBody(snake); - if(!EatSelf([snake])){ - setTimeout(function() { - move(snake); - }, MOVE_INTERVAL); - }else{ - initGame(); - } -} - -function moveBody(snake) { - snake.body.unshift({ x: snake.head.x, y: snake.head.y }); - snake.body.pop(); -} - -function turn(snake, direction) { - const oppositeDirections = { - [DIRECTION.LEFT]: DIRECTION.RIGHT, - [DIRECTION.RIGHT]: DIRECTION.LEFT, - [DIRECTION.DOWN]: DIRECTION.UP, - [DIRECTION.UP]: DIRECTION.DOWN, - } - - if (direction !== oppositeDirections[snake.direction]) { - snake.direction = direction; - } -} - -document.addEventListener("keydown", function (event) { - if (event.key === "ArrowLeft") { - turn(snake, DIRECTION.LEFT) - } else if (event.key === "ArrowRight") { - turn(snake, DIRECTION.RIGHT) - } else if (event.key === "ArrowUp") { - turn(snake, DIRECTION.UP) - } else if (event.key === "ArrowDown") { - turn(snake, DIRECTION.DOWN) - } -}) - -function initGame() { - move(snake); -} - -move(snake); \ No newline at end of file +const CELL_SIZE = 20; +const CANVAS_SIZE = 600; +const REDRAW_INTERVAL = 50; +const WIDTH = CANVAS_SIZE / CELL_SIZE; +const HEIGHT = CANVAS_SIZE / CELL_SIZE; +const DIRECTION = { + LEFT: 0, + RIGHT: 1, + UP: 2, + DOWN: 3, +} +let MOVE_INTERVAL = 150; + +function initPosition() { + return { + x: Math.floor(Math.random() * WIDTH), + y: Math.floor(Math.random() * HEIGHT), + } +} + +function initHeadAndBody() { + let head = initPosition(); + let body = [{x: head.x, y: head.y}]; + return { + head: head, + body: body, + } +} + +function initDirection() { + return Math.floor(Math.random() * 4); +} + +function makeSnake(color){ + return { + ...initHeadAndBody(), + direction: initDirection() + } +} + +function initProperty() { + return { + life: 3, + level: 1, + score: 0, + counter: 0, + } +} + +let snakeObj = makeSnake("green"); +let prop = initProperty(); + +let apples = [{ + position: initPosition(), +}, +{ + position: initPosition(), +}] + +let lifes = { + position: initPosition(), + visible: true, + visibleCount: 0, +} + +function drawCell(ctx, x, y, color) { + ctx.fillStyle = color; + ctx.fillRect(x * CELL_SIZE, y * CELL_SIZE, CELL_SIZE, CELL_SIZE); +} + +function drawHead(ctx, x, y) { + let snakeHead = document.getElementById('snakeHead'); + ctx.drawImage(snakeHead, x * CELL_SIZE, y * CELL_SIZE, CELL_SIZE, CELL_SIZE) +} + +function drawBody(ctx, x, y) { + let snakeBody = document.getElementById('snakeBody'); + ctx.drawImage(snakeBody, x * CELL_SIZE, y * CELL_SIZE, CELL_SIZE, CELL_SIZE) +} + +function drawlevel() { + let scoreCanvas; + scoreCanvas = document.getElementById("levelberapa"); + + let scoreCtx = scoreCanvas.getContext("2d"); + + scoreCtx.clearRect(0, 0, CANVAS_SIZE, CANVAS_SIZE); + scoreCtx.font = "20px Arial"; + scoreCtx.fillStyle = "black" + scoreCtx.fillText("Snake Game - Level: "+prop.level, 10, scoreCanvas.scrollHeight / 2); +} + +function drawScore(snake) { + let scoreCanvas; + if (snakeObj.color == snake.color) { + scoreCanvas = document.getElementById("score1Board"); + } + let scoreCtx = scoreCanvas.getContext("2d"); + + scoreCtx.clearRect(0, 0, CANVAS_SIZE, CANVAS_SIZE); + scoreCtx.font = "20px Arial"; + scoreCtx.fillStyle = "black" + scoreCtx.fillText("Score: \n" +prop.score, 10, scoreCanvas.scrollHeight / 2); +} + +function drawkeceptan() { + let kecepetanCanvas; + kecepetanCanvas = document.getElementById("score2Board"); + let keceptanCtx = kecepetanCanvas.getContext("2d"); + + keceptanCtx.clearRect(0, 0, CANVAS_SIZE, CANVAS_SIZE); + keceptanCtx.font = "20px Arial"; + keceptanCtx.fillStyle = "black" + keceptanCtx.fillText("Speed: "+MOVE_INTERVAL + " .ms", 10, kecepetanCanvas.scrollHeight / 2); +} + +function drawNyawa(ctx) { + while (lifes.position.y == 0 || wallCollision(lifes.position.x, lifes.position.y)) { + lifes.position = initPosition(); + } + if (lifes.visible) { + var img = document.getElementById("life"); + ctx.drawImage(img, lifes.position.x * CELL_SIZE, lifes.position.y * CELL_SIZE, CELL_SIZE, CELL_SIZE); + lifes.visibleCount++; + if (lifes.visibleCount == 10) { + lifes.visible = false; + } + } else { + drawCell(ctx, lifes.position.x, lifes.position.y, "rgb(255,255,255,0)") + lifes.visibleCount--; + if (lifes.visibleCount == 0) { + lifes.visible = true; + } + } +} + +function isPrima() { + let isPrime = true; + if (prop.score > 1) { + for (let i = 2; i < prop.score; i++) { + if (prop.score % i == 0) { + isPrime = false; + break; + } + } + return isPrime; + } +} + +function drawWall(ctx, x1, y1, x2, y2) { + ctx.strokeStyle = "brown"; + ctx.lineWidth = 10; + ctx.beginPath(); + ctx.moveTo(x1 * CELL_SIZE, y1 * CELL_SIZE); + ctx.lineTo(x2 * CELL_SIZE, y2 * CELL_SIZE); + ctx.stroke(); +} + +let walls = [] + +function isNaikLevel() { + if (prop.score == 5 && prop.counter == 0) { + var audio = new Audio('assets/NaikLevel.mp3'); + alert("Level 1 Complete"); + audio.play(); + prop.level = 2; + MOVE_INTERVAL = 120; + walls[0] = {x1: 15,y1: 5,x2: 15,y2: 25}; + prop.counter++; + } else if (prop.score == 10 && prop.counter == 1) { + var audio = new Audio('assets/NaikLevel.mp3'); + alert("Level 2 Complete"); + audio.play(); + prop.level = 3; + MOVE_INTERVAL = 100; + walls[0] = {x1: 5,y1: 10,x2: 25,y2: 10}; + walls[1] = {x1: 5,y1: 20,x2: 25,y2: 20}; + prop.counter++; + } else if (prop.score == 15 && prop.counter == 2) { + var audio = new Audio('assets/NaikLevel.mp3'); + alert("Level 3 Complete"); + audio.play(); + prop.level = 4; + MOVE_INTERVAL = 85; + walls[0] = {x1: 5,y1: 5,x2: 25,y2: 5}; + walls[1] = {x1: 5,y1: 15,x2: 25,y2: 15}; + walls[2] = {x1: 5,y1: 25,x2: 25,y2: 25}; + prop.counter++; + } else if (prop.score == 20 && prop.counter == 3) { + var audio = new Audio('assets/NaikLevel.mp3'); + alert("Level 4 Complete"); + audio.play(); + prop.level = 5; + MOVE_INTERVAL = 75; + walls[0] = {x1: 10,y1: 5,x2: 20,y2: 5}; + walls[1] = {x1: 5,y1: 10,x2: 5,y2: 20}; + walls[2] = {x1: 10,y1: 25,x2: 20,y2: 25}; + walls[3] = {x1: 25,y1: 10,x2: 25,y2: 20}; + prop.counter++; + } +} + +function draw() { + setInterval(function() { + let snakeCanvas = document.getElementById("snakeBoard"); + let ctx = snakeCanvas.getContext("2d"); + + ctx.clearRect(0, 0, CANVAS_SIZE, CANVAS_SIZE); + drawHead(ctx, snakeObj.head.x, snakeObj.head.y); + for (let i = 1; i < snakeObj.body.length; i++) { + drawBody(ctx, snakeObj.body[i].x, snakeObj.body[i].y); + } + + for (let i = 0; i < apples.length; i++) { + let apple = apples[i]; + while (apple.position.y == 0 || wallCollision(apple.position.x, apple.position.y)) { + apple.position = initPosition(); + } + var img = document.getElementById("apple"); + ctx.drawImage(img, apple.position.x * CELL_SIZE, apple.position.y * CELL_SIZE, CELL_SIZE, CELL_SIZE); + } + + for (let i = 0; i < prop.life; i++) { + var img = document.getElementById("life"); + ctx.drawImage(img, i * CELL_SIZE, 0, CELL_SIZE, CELL_SIZE); + } + + if (isPrima()){ + drawNyawa(ctx); + } + + if (prop.level > 1) { + for (i = 0; i < prop.level - 1; i++) { + drawWall(ctx, walls[i].x1, walls[i].y1, walls[i].x2, walls[i].y2); + } + } + drawlevel(snakeObj); + drawkeceptan(snakeObj); + drawScore(snakeObj); + }, REDRAW_INTERVAL); +} + +function teleport(snake) { + if (snake.head.x < 0) { + snake.head.x = CANVAS_SIZE / CELL_SIZE - 1; + } + if (snake.head.x >= WIDTH) { + snake.head.x = 0; + } + if (snake.head.y < 0) { + snake.head.y = CANVAS_SIZE / CELL_SIZE - 1; + } + if (snake.head.y >= HEIGHT) { + snake.head.y = 0; + } +} + +function eat(snake, apples) { + for (let i = 0; i < apples.length; i++) { + let apple = apples[i]; + if (snake.head.x == apple.position.x && snake.head.y == apple.position.y) { + apple.position = initPosition(); + prop.score++; + snake.body.push({x: snake.head.x, y: snake.head.y}); + } + } + isNaikLevel(); + eatNyawa(); +} + +function eatNyawa() { + if (snakeObj.head.x == lifes.position.x && snakeObj.head.y == lifes.position.y) { + lifes.position = initPosition(); + prop.life++; + prop.score++; + snakeObj.body.push({x: snakeObj.head.x, y: snakeObj.head.y}); + isNaikLevel(); + } +} + +function wallCollision(x, y) { + let isCollide = false; + + if (prop.level > 1) { + for (let i = 0; i < prop.level - 1; i++) { + if (x == walls[i].x1 && y >= walls[i].y1 && y < walls[i].y2 || y == walls[i].y1 && x >= walls[i].x1 && x < walls[i].x2 ) { + isCollide = true; + } + } + } + return isCollide; +} + +function selfCollision(snake){ + let isCollide = false; + + for (let i = 0; i < snake.length; i++) { + for (let j = 0; j < snake.length; j++) { + for (let k = 1; k < snake[j].body.length; k++) { + if (snake[i].head.x == snake[j].body[k].x && snake[i].head.y == snake[j].body[k].y) { + isCollide = true; + } + } + } + } + if (wallCollision(snakeObj.head.x, snakeObj.head.y)) { + isCollide = true; + } + if (isCollide) { + snakeObj = makeSnake("purple"); + prop.life--; + if (prop.life == 0) { + var audio = new Audio('assets/game-over.wav'); + audio.play(); + alert("Game Over"); + + snakeObj = makeSnake(); + prop = initProperty(); + MOVE_INTERVAL = 120; + } + } + return isCollide; +} + + +function moveLeft(snake) { + snake.head.x--; + teleport(snake); + eat(snake, apples); +} + +function moveRight(snake) { + snake.head.x++; + teleport(snake); + eat(snake, apples); +} + +function moveDown(snake) { + snake.head.y++; + teleport(snake); + eat(snake, apples); +} + +function moveUp(snake) { + snake.head.y--; + teleport(snake); + eat(snake, apples); +} + +function move(snake) { + switch (snake.direction) { + case DIRECTION.LEFT: + moveLeft(snake); + break; + case DIRECTION.RIGHT: + moveRight(snake); + break; + case DIRECTION.DOWN: + moveDown(snake); + break; + case DIRECTION.UP: + moveUp(snake); + break; + } + moveBody(snake); + if(!selfCollision([snake])){ + setTimeout(function() { + move(snakeObj); + }, MOVE_INTERVAL); + }else{ + startGame(); + } +} + +function moveBody(snake) { + snake.body.unshift({ x: snake.head.x, y: snake.head.y }); + snake.body.pop(); +} + +function turn(snake, direction) { + const oppositeDirections = { + [DIRECTION.LEFT]: DIRECTION.RIGHT, + [DIRECTION.RIGHT]: DIRECTION.LEFT, + [DIRECTION.DOWN]: DIRECTION.UP, + [DIRECTION.UP]: DIRECTION.DOWN, + } + + if (direction !== oppositeDirections[snake.direction]) { + snake.direction = direction; + } +} + +document.addEventListener("keydown", function (event) { + if (event.key === "ArrowLeft") { + turn(snakeObj, DIRECTION.LEFT) + } else if (event.key === "ArrowRight") { + turn(snakeObj, DIRECTION.RIGHT) + } else if (event.key === "ArrowUp") { + turn(snakeObj, DIRECTION.UP) + } else if (event.key === "ArrowDown") { + turn(snakeObj, DIRECTION.DOWN) + } +}) + +function startGame() { + move(snakeObj); +} + +move(snakeObj); \ No newline at end of file diff --git a/snake-game/style.css b/snake-game/style.css new file mode 100644 index 0000000..5983793 --- /dev/null +++ b/snake-game/style.css @@ -0,0 +1,10 @@ +body { + margin-top: 40px; + text-align: center; + background: rgb(61, 255, 0); + background: linear-gradient(0deg, rgba(110, 177, 223, 0.614) 0%, rgba(24, 84, 141, 0.261) 38%, rgba(35, 136, 194, 0.056) 91%); +} + +* { + font-family:'Courier New', Courier, monospace; +} \ No newline at end of file