{"id":274,"date":"2025-07-10T02:49:48","date_gmt":"2025-07-10T02:49:48","guid":{"rendered":"https:\/\/insaatsirketleri.com.tr\/en\/?p=274"},"modified":"2025-07-10T02:54:51","modified_gmt":"2025-07-10T02:54:51","slug":"pacman","status":"publish","type":"post","link":"https:\/\/insaatsirketleri.com.tr\/en\/pacman\/","title":{"rendered":"pacman"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<div id=\"game-container\">\n        <div id=\"info-panel\">\n            <span id=\"score\">SKOR: 0<\/span>\n            <span id=\"lives\">CAN: 3<\/span>\n        <\/div>\n        <canvas id=\"gameCanvas\"><\/canvas>\n        <div id=\"game-over-screen\">\n            <h2>Oyun Bitti<\/h2>\n            <button id=\"restart-button-over\">Tekrar Oyna<\/button>\n        <\/div>\n        <div id=\"win-screen\">\n            <h2>Kazand\u0131n!<\/h2>\n            <button id=\"restart-button-win\">Tekrar Oyna<\/button>\n        <\/div>\n    <\/div>\n\n    <div id=\"mobile-controls\">\n        <div class=\"control-row\"><button id=\"btn-up\">\u25b2<\/button><\/div>\n        <div class=\"control-row\"><button id=\"btn-left\">\u25c4<\/button><button style=\"visibility: hidden;\"><\/button><button id=\"btn-right\">\u25ba<\/button><\/div>\n        <div class=\"control-row\"><button id=\"btn-down\">\u25bc<\/button><\/div>\n    <\/div>\n\n    <script>\n    \/\/ Kodu WordPress \u00e7ak\u0131\u015fmalar\u0131ndan korumak i\u00e7in bir IIFE (Immediately Invoked Function Expression) i\u00e7ine al\u0131yoruz.\n    (function() {\n        const canvas = document.getElementById('gameCanvas');\n        const ctx = canvas.getContext('2d');\n        const scoreEl = document.getElementById('score');\n        const livesEl = document.getElementById('lives');\n        const gameOverScreen = document.getElementById('game-over-screen');\n        const winScreen = document.getElementById('win-screen');\n        const restartButtonOver = document.getElementById('restart-button-over');\n        const restartButtonWin = document.getElementById('restart-button-win');\n\n        const TILE_SIZE = 20;\n        const originalMap = [\n            [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],\n            [1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 3, 1],\n            [1, 2, 1, 1, 2, 1, 1, 1, 2, 1, 2, 1, 1, 1, 2, 1, 1, 2, 1],\n            [1, 2, 1, 1, 2, 1, 1, 1, 2, 1, 2, 1, 1, 1, 2, 1, 1, 2, 1],\n            [1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1],\n            [1, 2, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 2, 1],\n            [1, 2, 2, 2, 2, 1, 2, 2, 2, 1, 2, 2, 2, 1, 2, 2, 2, 2, 1],\n            [1, 1, 1, 1, 2, 1, 1, 1, 0, 1, 0, 1, 1, 1, 2, 1, 1, 1, 1],\n            [0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0],\n            [1, 1, 1, 1, 2, 1, 0, 1, 1, 5, 1, 1, 0, 1, 2, 1, 1, 1, 1],\n            [2, 2, 2, 2, 2, 2, 0, 1, 5, 5, 5, 1, 0, 2, 2, 2, 2, 2, 2],\n            [1, 1, 1, 1, 2, 1, 0, 1, 1, 1, 1, 1, 0, 1, 2, 1, 1, 1, 1],\n            [0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0],\n            [1, 1, 1, 1, 2, 1, 0, 1, 1, 1, 1, 1, 0, 1, 2, 1, 1, 1, 1],\n            [1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 3, 1],\n            [1, 2, 1, 1, 2, 1, 1, 1, 2, 1, 2, 1, 1, 1, 2, 1, 1, 2, 1],\n            [1, 3, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 3, 1],\n            [1, 1, 2, 1, 2, 1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, 2, 1, 1],\n            [1, 2, 2, 2, 2, 1, 2, 2, 2, 1, 2, 2, 2, 1, 2, 2, 2, 2, 1],\n            [1, 2, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 2, 1],\n            [1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1],\n            [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],\n        ];\n\n        let map;\n        let pacman, ghosts, score, lives, totalPellets, frightenedMode, frightenedTimer, ghostEatenPoints, gameLoopId, mouthOpen = true, mouthCounter = 0;\n\n        class Character {\n            constructor(x, y, speed, direction) {\n                this.x = x; this.y = y; this.speed = speed;\n                this.direction = direction; this.nextDirection = direction;\n            }\n\n            isWallCollision(dir) {\n                const checkTile = (x, y) => {\n                    const tileX = Math.floor(x \/ TILE_SIZE);\n                    const tileY = Math.floor(y \/ TILE_SIZE);\n                    const tile = map[tileY] && map[tileY][tileX];\n                    return tile === 1 || tile === 5;\n                };\n\n                let TILE_OFFSET = TILE_SIZE \/ 2;\n                let nextX = this.x + dir.x * this.speed;\n                let nextY = this.y + dir.y * this.speed;\n\n                if (dir.x === -1) {\n                    return checkTile(nextX - TILE_OFFSET, this.y - TILE_OFFSET) || checkTile(nextX - TILE_OFFSET, this.y + TILE_OFFSET - 1);\n                } else if (dir.x === 1) {\n                    return checkTile(nextX + TILE_OFFSET - 1, this.y - TILE_OFFSET) || checkTile(nextX + TILE_OFFSET - 1, this.y + TILE_OFFSET - 1);\n                } else if (dir.y === -1) {\n                    return checkTile(this.x - TILE_OFFSET, nextY - TILE_OFFSET) || checkTile(this.x + TILE_OFFSET - 1, nextY - TILE_OFFSET);\n                } else if (dir.y === 1) {\n                    return checkTile(this.x - TILE_OFFSET, nextY + TILE_OFFSET - 1) || checkTile(this.x + TILE_OFFSET - 1, nextY + TILE_OFFSET - 1);\n                }\n                return false;\n            }\n\n            canTurn(dir) {\n                return !this.isWallCollision(dir);\n            }\n\n            move() {\n                const isAxisChange = (this.direction.x !== this.nextDirection.x) || (this.direction.y !== this.nextDirection.y);\n                if (isAxisChange && this.canTurn(this.nextDirection)) {\n                    const currentTileX = Math.floor(this.x \/ TILE_SIZE);\n                    const currentTileY = Math.floor(this.y \/ TILE_SIZE);\n                    if(this.direction.x !== 0) {\n                         this.y = currentTileY * TILE_SIZE + TILE_SIZE \/ 2;\n                    } else if (this.direction.y !== 0) {\n                         this.x = currentTileX * TILE_SIZE + TILE_SIZE \/ 2;\n                    }\n                    this.direction = this.nextDirection;\n                }\n\n                if (!this.isWallCollision(this.direction)) {\n                    this.x += this.direction.x * this.speed;\n                    this.y += this.direction.y * this.speed;\n                }\n                \n                if (this.x < -TILE_SIZE \/ 2) this.x = canvas.width - TILE_SIZE \/ 2;\n                else if (this.x > canvas.width - TILE_SIZE \/ 2) this.x = -TILE_SIZE \/ 2;\n            }\n\n            getMapPos() { return { x: Math.floor(this.x \/ TILE_SIZE), y: Math.floor(this.y \/ TILE_SIZE) }; }\n        }\n\n        class Pacman extends Character {\n             draw() {\n                ctx.fillStyle = 'yellow';\n                ctx.beginPath();\n                mouthCounter = (mouthCounter + 1) % 20;\n                mouthOpen = mouthCounter < 10;\n\n                if (this.direction.x === 0 &#038;&#038; this.direction.y === 0 &#038;&#038; !mouthOpen) {\n                    ctx.arc(this.x, this.y, TILE_SIZE \/ 2, 0, Math.PI * 2);\n                } else {\n                    let angle = 0;\n                    if (this.direction.x === 1) angle = 0;\n                    else if (this.direction.x === -1) angle = Math.PI;\n                    else if (this.direction.y === 1) angle = 0.5 * Math.PI;\n                    else if (this.direction.y === -1) angle = 1.5 * Math.PI;\n                    const mouthAngle = mouthOpen ? 0.25 * Math.PI : 0;\n                    ctx.arc(this.x, this.y, TILE_SIZE \/ 2, angle + mouthAngle, angle - mouthAngle);\n                    ctx.lineTo(this.x, this.y);\n                }\n                ctx.fill();\n            }\n        }\n\n        class Ghost extends Character {\n            constructor(x, y, speed, direction, color) {\n                super(x, y, speed, direction);\n                this.color = color;\n                this.spawnPoint = {x, y};\n                this.isFrightened = false; this.isEaten = false;\n            }\n\n            draw() {\n                ctx.fillStyle = this.isEaten ? '#ccc' : (this.isFrightened ? '#0000FF' : this.color);\n                ctx.beginPath();\n                ctx.arc(this.x, this.y, TILE_SIZE \/ 2, Math.PI, 0);\n                ctx.lineTo(this.x + TILE_SIZE \/ 2, this.y + TILE_SIZE \/ 2);\n                ctx.lineTo(this.x - TILE_SIZE \/ 2, this.y + TILE_SIZE \/ 2);\n                ctx.closePath();\n                ctx.fill();\n                ctx.fillStyle = 'white';\n                ctx.beginPath();\n                ctx.arc(this.x - TILE_SIZE \/ 4, this.y - TILE_SIZE \/ 6, TILE_SIZE\/6, 0, Math.PI * 2);\n                ctx.arc(this.x + TILE_SIZE \/ 4, this.y - TILE_SIZE \/ 6, TILE_SIZE\/6, 0, Math.PI * 2);\n                ctx.fill();\n            }\n            \n            updateAI() {\n                if (this.isEaten) {\n                    if (Math.hypot(this.x - this.spawnPoint.x, this.y - this.spawnPoint.y) < this.speed) {\n                        this.isEaten = false; this.x = this.spawnPoint.x; this.y = this.spawnPoint.y;\n                    } else this.setDirectionTowards(this.spawnPoint);\n                } else if (this.isFrightened) this.setRandomDirection();\n                else this.setDirectionTowards(pacman);\n            }\n\n            setDirectionTowards(target) {\n                const possibleMoves = this.getPossibleMoves();\n                let bestMove = null, minDistance = Infinity;\n                for (const move of possibleMoves) {\n                    const distance = Math.hypot((this.x + move.x * TILE_SIZE) - target.x, (this.y + move.y * TILE_SIZE) - target.y);\n                    if (distance < minDistance) { minDistance = distance; bestMove = move; }\n                }\n                if (bestMove) this.nextDirection = bestMove;\n            }\n            \n            setRandomDirection() {\n                 if (Math.floor(this.x) % TILE_SIZE === 10 &#038;&#038; Math.floor(this.y) % TILE_SIZE === 10) {\n                     const possibleMoves = this.getPossibleMoves();\n                     if (possibleMoves.length > 0) this.nextDirection = possibleMoves[Math.floor(Math.random() * possibleMoves.length)];\n                 }\n            }\n\n            getPossibleMoves() {\n                const moves = [{x:0, y:-1}, {x:1, y:0}, {x:0, y:1}, {x:-1, y:0}];\n                const oppositeDir = {x: -this.direction.x, y: -this.direction.y};\n                const possible = moves.filter(m => (m.x !== oppositeDir.x || m.y !== oppositeDir.y) && !this.isWallCollision(m));\n                return possible.length > 0 ? possible : [oppositeDir];\n            }\n        }\n\n        function init() {\n            map = JSON.parse(JSON.stringify(originalMap));\n            canvas.width = map[0].length * TILE_SIZE; canvas.height = map.length * TILE_SIZE;\n            score = 0; lives = 3; totalPellets = map.flat().filter(t => t === 2 || t === 3).length;\n            frightenedMode = false; frightenedTimer = 0;\n            const startDir = {x: -1, y: 0};\n            pacman = new Pacman(9 * TILE_SIZE + TILE_SIZE\/2, 16 * TILE_SIZE + TILE_SIZE\/2, 2, startDir);\n            ghosts = [\n                new Ghost(9 * TILE_SIZE + TILE_SIZE\/2, 10 * TILE_SIZE + TILE_SIZE\/2, 1.8, {x: 1, y: 0}, 'red'),\n                new Ghost(8 * TILE_SIZE + TILE_SIZE\/2, 10 * TILE_SIZE + TILE_SIZE\/2, 1.8, {x: -1, y: 0}, 'pink'),\n                new Ghost(10 * TILE_SIZE + TILE_SIZE\/2, 10 * TILE_SIZE + TILE_SIZE\/2, 1.8, {x: 1, y: 0}, 'cyan'),\n                new Ghost(9 * TILE_SIZE + TILE_SIZE\/2, 9 * TILE_SIZE + TILE_SIZE\/2, 1.8, {x: -1, y: 0}, 'orange')\n            ];\n            updateUI();\n            gameOverScreen.style.display = 'none'; winScreen.style.display = 'none';\n            if(gameLoopId) cancelAnimationFrame(gameLoopId);\n            gameLoopId = requestAnimationFrame(gameLoop);\n        }\n\n        function resetAfterLifeLost() {\n             pacman.x = 9 * TILE_SIZE + TILE_SIZE\/2; pacman.y = 16 * TILE_SIZE + TILE_SIZE\/2;\n             pacman.direction = {x: -1, y: 0}; pacman.nextDirection = {x: -1, y: 0};\n             ghosts.forEach(g => { g.x = g.spawnPoint.x; g.y = g.spawnPoint.y; g.isFrightened = false; g.isEaten = false; });\n             frightenedMode = false;\n        }\n\n        function updateUI() { scoreEl.textContent = `SKOR: ${score}`; livesEl.textContent = `CAN: ${lives}`; }\n\n        function drawMap() {\n            for (let y = 0; y < map.length; y++) {\n                for (let x = 0; x < map[y].length; x++) {\n                    const tile = map[y][x];\n                    if (tile === 1) { ctx.fillStyle = '#0000FF'; ctx.fillRect(x * TILE_SIZE, y * TILE_SIZE, TILE_SIZE, TILE_SIZE); } \n                    else if (tile === 2) { ctx.fillStyle = 'white'; ctx.beginPath(); ctx.arc(x * TILE_SIZE + TILE_SIZE\/2, y * TILE_SIZE + TILE_SIZE\/2, TILE_SIZE\/6, 0, 2*Math.PI); ctx.fill(); } \n                    else if (tile === 3) { ctx.fillStyle = 'white'; ctx.beginPath(); ctx.arc(x * TILE_SIZE + TILE_SIZE\/2, y * TILE_SIZE + TILE_SIZE\/2, TILE_SIZE\/3, 0, 2*Math.PI); ctx.fill(); }\n                }\n            }\n        }\n        \n        function checkCollisions() {\n            const pos = pacman.getMapPos();\n            const tile = map[pos.y] &#038;&#038; map[pos.y][pos.x];\n            if (tile === 2 || tile === 3) {\n                map[pos.y][pos.x] = 0;\n                score += (tile === 2 ? 10 : 50);\n                totalPellets--;\n                updateUI();\n                if (tile === 3) {\n                    frightenedMode = true; frightenedTimer = 300; ghostEatenPoints = 200;\n                    ghosts.forEach(g => { if(!g.isEaten) g.isFrightened = true; });\n                }\n            }\n            for (const ghost of ghosts) {\n                if (Math.hypot(pacman.x - ghost.x, pacman.y - ghost.y) < TILE_SIZE * 0.8) {\n                    if (ghost.isFrightened &#038;&#038; !ghost.isEaten) {\n                        score += ghostEatenPoints; ghostEatenPoints *= 2; updateUI();\n                        ghost.isEaten = true; ghost.isFrightened = false;\n                    } else if (!ghost.isFrightened &#038;&#038; !ghost.isEaten) { loseLife(); break; }\n                }\n            }\n        }\n\n        function loseLife() {\n            lives--; updateUI();\n            if (lives <= 0) { cancelAnimationFrame(gameLoopId); gameOverScreen.style.display = 'block'; } \n            else resetAfterLifeLost();\n        }\n\n        function gameLoop() {\n            pacman.move();\n            ghosts.forEach(g => { g.updateAI(); g.move(); });\n            if (frightenedMode) { if (--frightenedTimer <= 0) { frightenedMode = false; ghosts.forEach(g => g.isFrightened = false); } }\n            checkCollisions();\n            if (totalPellets <= 0) { cancelAnimationFrame(gameLoopId); winScreen.style.display = 'block'; }\n            ctx.clearRect(0, 0, canvas.width, canvas.height);\n            drawMap();\n            pacman.draw();\n            ghosts.forEach(g => g.draw());\n            gameLoopId = requestAnimationFrame(gameLoop);\n        }\n\n        window.addEventListener('keydown', e => {\n            const keyMap = {'ArrowUp':'up', 'w':'up', 'ArrowDown':'down', 's':'down', 'ArrowLeft':'left', 'a':'left', 'ArrowRight':'right', 'd':'right'};\n            if(keyMap[e.key]) pacman.nextDirection = {up:{x:0,y:-1}, down:{x:0,y:1}, left:{x:-1,y:0}, right:{x:1,y:0}}[keyMap[e.key]];\n        });\n        \n        document.getElementById('btn-up').addEventListener('touchstart', e => { e.preventDefault(); pacman.nextDirection = {x:0, y:-1}; });\n        document.getElementById('btn-down').addEventListener('touchstart', e => { e.preventDefault(); pacman.nextDirection = {x:0, y:1}; });\n        document.getElementById('btn-left').addEventListener('touchstart', e => { e.preventDefault(); pacman.nextDirection = {x:-1, y:0}; });\n        document.getElementById('btn-right').addEventListener('touchstart', e => { e.preventDefault(); pacman.nextDirection = {x:1, y:0}; });\n\n        restartButtonOver.addEventListener('click', init);\n        restartButtonWin.addEventListener('click', init);\n\n        init();\n    })();\n    <\/script>\n","protected":false},"excerpt":{"rendered":"<p>SKOR: 0 CAN: 3 Oyun Bitti Tekrar Oyna Kazand\u0131n! Tekrar Oyna \u25b2 \u25c4\u25ba \u25bc<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-274","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/insaatsirketleri.com.tr\/en\/wp-json\/wp\/v2\/posts\/274","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/insaatsirketleri.com.tr\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/insaatsirketleri.com.tr\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/insaatsirketleri.com.tr\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/insaatsirketleri.com.tr\/en\/wp-json\/wp\/v2\/comments?post=274"}],"version-history":[{"count":2,"href":"https:\/\/insaatsirketleri.com.tr\/en\/wp-json\/wp\/v2\/posts\/274\/revisions"}],"predecessor-version":[{"id":276,"href":"https:\/\/insaatsirketleri.com.tr\/en\/wp-json\/wp\/v2\/posts\/274\/revisions\/276"}],"wp:attachment":[{"href":"https:\/\/insaatsirketleri.com.tr\/en\/wp-json\/wp\/v2\/media?parent=274"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/insaatsirketleri.com.tr\/en\/wp-json\/wp\/v2\/categories?post=274"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/insaatsirketleri.com.tr\/en\/wp-json\/wp\/v2\/tags?post=274"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}