something undefined here: const canvas=document.getElementById("game-canvas");const context=canvas.getContext("2d");canvas.width=800;canvas.height=600;const GRAVITY=80;const ENEMY_RADIUS=10;const PLAYER_RADIUS=10;const TRACTION=1;const OBSTACLE_COUNT=10;const OBSTACLE_GAP=0;let playerX=1e3;let playerY=100;let isPlayerAlive=true;let enemyX=1e3;let enemyY=100;let enemySpeedX=0;let enemySpeedY=0;let enemyMultiplier=0;let playerSpeedX=0;let playerSpeedY=0;let playerIsOnGround=false;let lasers=[];let shootingTimer=0;let obstacles=[];const obstacleWidth=10;const obstacleHeight=10;let offsetX=0;let offsetY=0;let scrollSpeed=1;function applyGravity(){if(!playerIsOnGround){playerSpeedY+=GRAVITY/60}}function applyTraction(){playerSpeedX*=TRACTION}function movePlayer(){if(!isPlayerAlive)return;playerX+=playerSpeedX;playerY+=playerSpeedY;if(playerX<0){playerX=0}if(playerX+PLAYER_RADIUS*2>canvas.width){playerX=canvas.width-PLAYER_RADIUS*2}context.fillStyle="pink";context.fillRect(playerX-offsetX,playerY-offsetY,PLAYER_RADIUS*2,PLAYER_RADIUS*2)}if(playerX<-PLAYER_RADIUS){playerX=canvas.width-PLAYER_RADIUS;generateNewObstacle()}if(playerX>canvas.width-PLAYER_RADIUS){playerX=-PLAYER_RADIUS;generateNewObstacle()}function moveEnemy(){if(!isPlayerAlive)return;const targetIndex=findNearestObstacle(playerX,playerY);const targetX=obstacles[targetIndex].x+obstacleWidth/2;const targetY=obstacles[targetIndex].y+obstacleHeight/2;const epsilon=.2;if(Math.abs(enemyX-targetX)>epsilon||Math.abs(enemyY-targetY)>epsilon){const angle=Math.atan2(targetY-enemyY,targetX-enemyX);enemySpeedX=Math.cos(angle)*2;enemySpeedY=Math.sin(angle)*2}else{enemySpeedX=0;enemySpeedY=0}enemyX+=enemySpeedX;enemyY+=enemySpeedY;context.fillStyle="cyan";context.fillRect(enemyX-ENEMY_RADIUS-offsetX,enemyY-ENEMY_RADIUS,ENEMY_RADIUS*2,ENEMY_RADIUS*2)}function findNearestObstacle(x,y){let minIndex=0;let minDistance=Number.MAX_VALUE;for(let i=0;i<obstacles.length;i++){const dx=x-(obstacles[i].x+obstacleWidth/2);const dy=y-(obstacles[i].y+obstacleHeight/2);const distance=Math.sqrt(dx*dx+dy*dy);if(distance<minDistance){minDistance=distance;minIndex=i}}return minIndex}function isColliding(x,y,width,height){for(const obstacle of obstacles){if(x<obstacle.x+obstacle.width&&x+width>obstacle.x&&y<obstacle.y+obstacle.height&&y+height>obstacle.y){const dx=Math.max(0,Math.min(x+width,obstacle.x+obstacle.width)-Math.max(x,obstacle.x));const dy=Math.max(0,Math.min(y+height,obstacle.y+obstacle.height)-Math.max(y,obstacle.y));const distance=Math.sqrt(dxdx+dydy);if(distance<PLAYER_RADIUS){if(dy>dx&&x+width/2>obstacle.x&&x+width/2<obstacle.x+obstacle.width){playerY=obstacle.y-PLAYER_RADIUS*2;playerSpeedY=0;playerIsOnGround=true}else if(dx>dy&&y+height/2>obstacle.y&&y+height/2<obstacle.y+obstacle.height){if(playerX<obstacle.x+obstacle.width/2){playerX=obstacle.x-PLAYER_RADIUS*2}else{playerX=obstacle.x+obstacle.width}playerSpeedX=0}}return true}}return false}function checkCollision(){if(isColliding(playerX,playerY,PLAYER_RADIUS*2,PLAYER_RADIUS*2)){playerY-=playerSpeedY;offsetY-=playerSpeedY;playerSpeedY=0;playerIsOnGround=true}else{playerIsOnGround=false}}function detectObstacleCollision(){for(const obstacle of obstacles){if(playerX+PLAYER_RADIUS*2>obstacle.x&&playerX<obstacle.x+obstacle.width&&playerY+PLAYER_RADIUS*2>obstacle.y&&playerY<obstacle.y+obstacle.height){if(playerX+PLAYER_RADIUS*2<obstacle.x+5){playerX=obstacle.x-PLAYER_RADIUS*2}else if(playerX>obstacle.x+obstacle.width-5){playerX=obstacle.x+obstacle.width}else{if(playerY+PLAYER_RADIUS*2<obstacle.y+5){playerY=obstacle.y-PLAYER_RADIUS*2;playerIsOnGround=true}if(playerY>obstacle.y+obstacle.height-5){playerY=obstacle.y+obstacle.height;playerSpeedY=0}}}if(enemyX+ENEMY_RADIUS*2>obstacle.x&&enemyX<obstacle.x+obstacle.width&&enemyY+ENEMY_RADIUS*2>obstacle.y&&enemyY<obstacle.y+obstacle.height){if(enemyX+ENEMY_RADIUS*2<obstacle.x+5){enemyX=obstacle.x-ENEMY_RADIUS*2}else if(enemyX>obstacle.x+obstacle.width-5){enemyX=obstacle.x+obstacle.width}else{if(enemyY+ENEMY_RADIUS*2<obstacle.y+5){enemyY=obstacle.y-ENEMY_RADIUS*2}else if(enemyY>obstacle.y+obstacle.height-5){enemyY=obstacle.y+obstacle.height;enemySpeedY=0}}}}}function shootLaser(){const laserSpeed=2;const angle=Math.atan2(playerX-enemyX);const laserSpeedX=Math.cos(angle)*laserSpeed;const laserSpeedY=Math.sin(angle)*laserSpeed;lasers.push({x:enemyX+ENEMY_RADIUS,y:enemyY+ENEMY_RADIUS,speedX:laserSpeedX,speedY:laserSpeedY})}function moveLasers(){let playerHit=false;for(let i=0;i<lasers.length;i++){const laser=lasers[i];laser.x+=laser.speedX;laser.y+=laser.speedY;if(!playerHit&&laser.x>=playerX&&laser.x<=playerX+PLAYER_RADIUS*2&&laser.y>=playerY&&laser.y<=playerY+PLAYER_RADIUS*2){const randomColor="rgb("+Math.floor(Math.random()*256)+","+Math.floor(Math.random()*256)+","+Math.floor(Math.random()*256)+")";context.strokeStyle=randomColor;context.beginPath();context.moveTo(laser.x,laser.y);context.lineTo(laser.x+laser.speedX,laser.y+laser.speedY);context.lineWidth=3;context.stroke();playerHit=true;isPlayerAlive=false}if(laser.x<0||laser.x>canvas.width||laser.y<0||laser.y>canvas.height){lasers.splice(i,1);i}}if(playerHit){playerX=-100;playerY=-100}}function drawLasers(){context.fillStyle="red";for(const laser of lasers){context.beginPath();context.arc(laser.x,laser.y,5,0,Math.PI*2);context.fill()}}function drawObstacles(){context.fillStyle="yellow";for(const obstacle of obstacles){context.fillRect(obstacle.x,obstacle.y,obstacle.width,obstacle.height)}if(obstacles.length&&obstacles[0].y>canvas.height){obstacles.shift();const obstacleX=Math.random()*(canvas.width-obstacleWidth);const obstacleY=obstacles[obstacles.length-1].y-canvas.height/OBSTACLE_COUNT-OBSTACLE_GAP;obstacles.push({x:obstacleX,y:obstacleY,width:obstacleWidth,height:obstacleHeight})}}function createObstacles(){for(let i=0;i<OBSTACLE_COUNT;i++){const obstacleX=Math.random()*(canvas.width-obstacleWidth);const obstacleY=i*(canvas.height/OBSTACLE_COUNT)+OBSTACLE_GAP;obstacles.push({x:obstacleX,y:obstacleY,width:obstacleWidth,height:obstacleHeight})}}function setPlayerStartPosition(){const startingObstacle=obstacles[0];playerX=startingObstacle.x+obstacleWidth/2-PLAYER_RADIUS;playerY=startingObstacle.y-PLAYER_RADIUS*2}function drawObstacles(){context.fillStyle="yellow";for(const obstacle of obstacles){context.fillRect(obstacle.x,obstacle.y,obstacle.width,obstacle.height)}}function generateNewObstacle(){obstacles.shift();const obstacleX=Math.random()*(canvas.width-obstacleWidth);const obstacleY=obstacles[obstacles.length-1].y-canvas.height/OBSTACLE_COUNT-OBSTACLE_GAP;obstacles.push({x:obstacleX,y:obstacleY,width:obstacleWidth,height:obstacleHeight})}function checkEnemyDeath(){if(isPlayerAlive&&playerSpeedX>=0&&playerY+PLAYER_RADIUS*2>enemyY-ENEMY_RADIUS&&playerX+PLAYER_RADIUS*2>enemyX-ENEMY_RADIUS&&playerX<enemyX+ENEMY_RADIUS){playerIsOnGround=false;playerSpeedY=-20;setTimeout(()=>{playerSpeedY=0},100);enemyX=-100;setTimeout(spawnNewEnemy,1e3);enemyMultiplier++}}function spawnNewEnemy(){enemyX=Math.random()*(canvas.width-ENEMY_RADIUS*2);enemyY=Math.random()*(canvas.height-ENEMY_RADIUS*2);for(let i=0;i<enemyMultiplier-10;i++){shootLaser()}}function draw(timestamp){context.fillStyle="black";context.fillRect(0,0,canvas.width,canvas.height);const elapsedSeconds=(timestamp-lastFrameTime)/1e3;lastFrameTime=timestamp;applyGravity(elapsedSeconds);applyTraction();movePlayer();moveEnemy();moveLasers();detectObstacleCollision();drawLasers();drawObstacles();checkEnemyDeath();if(playerY<offsetY+PLAYER_RADIUS*2&&playerX>offsetX-PLAYER_RADIUS*2&&playerX<offsetX+obstacleWidth+PLAYER_RADIUS*2){offsetY-=canvas.height/OBSTACLE_COUNT;playerY+=canvas.height/OBSTACLE_COUNT;enemyY+=canvas.height/OBSTACLE_COUNT;generateNewObstacle()}requestAnimationFrame(draw)}let lastFrameTime=0;createObstacles();setPlayerStartPosition();draw();document.addEventListener("keydown",event=>{if(event.code==="KeyA"){playerSpeedX=-5}if(event.code==="KeyD"){playerSpeedX=5}if(event.code==="KeyW"&&playerIsOnGround){playerSpeedY=-20;playerIsOnGround=false}});document.addEventListener("keyup",event=>{if(event.code==="KeyA"||event.code==="KeyD"){playerSpeedX=0}});