How can I put my JS script in a different file for the sake of neatness?

I have this html file with the html, css and js all in one place:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>Gamedev Canvas Workshop</title>
    <style>
    	* { padding: 0; margin: 0; }
    	canvas { background: #eee; display: block; margin: 0 auto; }
    </style>
</head>
<body>

<canvas id="myCanvas" width="480" height="320"></canvas>

<script>
// Variables
  var canvas = document.getElementById("myCanvas");
  var ctx = canvas.getContext("2d");

  var x = canvas.width/2;
  var y = canvas.height-30;
  var dx = -1;
  var dy = -1;
  var ballRadius = 10;

  var paddleHeight = 10;
  var paddleWidth = 75;
  var paddleX = (canvas.width-paddleWidth) / 2;
  var rightPressed = false;
  var leftPressed = false;

  var brickRowCount = 3;
  var brickColumnCount = 5;
  var brickWidth = 75;
  var brickHeight = 20;
  var brickPadding = 10;
  var brickOffsetTop = 30;
  var brickOffsetLeft = 30;
  var bricks = [];
  for(var c=0; c<brickColumnCount; c++) {
      bricks[c] = [];
      for(var r=0; r<brickRowCount; r++) {
          bricks[c][r] = { x: 0, y: 0, status: 1 };
      }
  }

  var score = 0;
  var lives = 2;

// Event listeners
  document.addEventListener("keydown", keyDownHandler, false);
  document.addEventListener("keyup", keyUpHandler, false);
  document.addEventListener("mousemove", mouseMoveHandler, false);

// Functions and event handlers

  function mouseMoveHandler(e) {
      var relativeX = e.clientX - canvas.offsetLeft;
      if(relativeX > 0 && relativeX < canvas.width) {
          paddleX = relativeX - paddleWidth/2;
      }
  }

  function drawBall() {
    ctx.beginPath();
    ctx.arc(x, y, ballRadius, 0, Math.PI*2);
    ctx.fillStyle = "#0095DD";
    ctx.fill();
    ctx.closePath();
  }

  function drawPaddle() {
      ctx.beginPath();
      ctx.rect(paddleX, canvas.height-paddleHeight, paddleWidth, paddleHeight);
      ctx.fillStyle = "#0095DD";
      ctx.fill();
      ctx.closePath();
  }

  function drawBricks() {
      for(var c=0; c<brickColumnCount; c++) {
          for(var r=0; r<brickRowCount; r++) {
              if(bricks[c][r].status == 1) {
                var brickX = (c*(brickWidth+brickPadding))+brickOffsetLeft;
                var brickY = (r*(brickHeight+brickPadding))+brickOffsetTop;
                bricks[c][r].x = brickX;
                bricks[c][r].y = brickY;
                ctx.beginPath();
                ctx.rect(brickX, brickY, brickWidth, brickHeight);
                ctx.fillStyle = "#0095DD";
                ctx.fill();
                ctx.closePath();
              }
          }
      }
  }

  function draw() {
      ctx.clearRect(0, 0, canvas.width, canvas.height);

      drawBall();
      drawPaddle();
      drawScore();
      drawLives();
      collisionDetection();
      drawBricks();

      x += dx;
      y += dy;

      if(x + dx > canvas.width-ballRadius || x + dx < ballRadius) {
          dx = -dx;
      }
      if(y + dy < ballRadius) {
        dy = -dy;
      } else if(y + dy > canvas.height-ballRadius) {
          if(x > paddleX && x < paddleX + paddleWidth) {
              dy = -(dy+0.5); 
              // for 30deg/60deg bouncing angle, keeping same speed magnitude use dy = -(dy*0.705);  and dx = dx*1.22; 
          }
          else {
            lives--;
            if(!lives) {
                alert("GAME OVER");
                document.location.reload();
            }
            else {
                x = canvas.width/2;
                y = canvas.height-30;
                dx = 2;
                dy = -2;
                paddleX = (canvas.width-paddleWidth)/2;
            }
          }
      }

      if(rightPressed) {
          paddleX += 7;
          if (paddleX + paddleWidth > canvas.width){
              paddleX = canvas.width - paddleWidth;
          }
      } else if (leftPressed) {
          paddleX -= 7;
          if (paddleX < 0){
              paddleX = 0;
          }
      }

      requestAnimationFrame(draw);
  }

  function keyDownHandler(e) {
    if(e.key == "Right" || e.key == "ArrowRight") {
        rightPressed = true;
    }
    else if(e.key == "Left" || e.key == "ArrowLeft") {
        leftPressed = true;
    }
  }
  function keyUpHandler(e) {
      if(e.key == "Right" || e.key == "ArrowRight") {
          rightPressed = false;
      }
      else if(e.key == "Left" || e.key == "ArrowLeft") {
          leftPressed = false;
      }
  }

  function collisionDetection() {
      for(var c=0; c<brickColumnCount; c++) {
          for(var r=0; r<brickRowCount; r++) {
              var b = bricks[c][r];
              if(b.status == 1) {
                  if(x > b.x && x < b.x+brickWidth && y > b.y && y < b.y+brickHeight) {
                      dy = -dy;
                      b.status = 0;
                      score++;
                      if(score == brickRowCount*brickColumnCount) {
                          alert("YOU WIN, CONGRATULATIONS!");
                          document.location.reload();
                      }
                  }
              }
          }
      }
  }

  function drawScore() {
      ctx.font = "16px Arial";
      ctx.fillStyle = "#0095DD";
      ctx.fillText("Score: "+score, 8, 20);
  }

  function drawLives() {
      ctx.font = "16px Arial";
      ctx.fillStyle = "#0095DD";
      ctx.fillText("Lives: "+lives, canvas.width-65, 20);
  }

// setInterval variable (must be at bottom)
  draw();
</script>

</body>
</html>

I want to put everything inside the <script> </script> tags in a different JS file and call it in the html file. I tried it once but it wouldn’t work (stuff would not render). Could someone please explain exactly how to do this properly?

I want to do this for the CSS code as well (code inside <style> </style>)

Thanks for your time

Jaime

For these and more questions, I recommend w3schools.
Stylesheets are implemented with HTML link tag
JS files by using the src-attribute of the script-tag.

1 Like

I have tried what you say once before but it did not work for me.

As an example, please take a look at this small project. My intention is to simply render a canvas and a ball at the moment, but because of this problem with seperating js script and html, I am unable to render anything. https://replit.com/@jaimeggb/2D-breakout-game-using-Phaser

Could you please pinpoint exactly what is wrong with my code? (Perhaps something is missing in the server.js file?)

I know the process is simple, but I must be doing something wrong or my code is missing something I’m not aware of.

Thanks for your time

Jaime

I, like i think a lot of other people, do this using the and tags. One for CSS (typically in the header) and one or more for javascript (i usually have at least 2 if i’m using a framework) located (usually) in the body near the bottom.

Something like this

<head>
 <link type='text/css' rel='stylesheet' hfref='style.css'>
</head>
<body>
 <!-- main content here -->
 <script type='text/javascript' src='script.js'></script>
</body>

you could then name your files style.css and script.js and locate them in the same directory as your html. It is more common to put them into folders and reference them there, but I’m trying K.I.S.S. for brevity here.

1 Like

Hi @d0c5i5

Thanks for your quick reply.

I have tried what you say but I think it is more complicated than that when using a server.js file (I don’t know why). Please check out my code to see what I mean:
https://replit.com/@jaimeggb/2D-breakout-game-using-pure-JavaScript

I am still unable to render the file when I seperate it

I have managed to make it work. The only thing that worked was putting files and folders in the following way:
image

I tried other ways without folders but no rendering occurred. I don’t know why but at least it renders now

2 Likes

Interesting, I think that must be something specific to repl. You could adjust the location in server and I suspect it would work, but i’m not 100% sure. I am not overly familiar with repl, sorry. Looks good thought and nice and clean now. :slight_smile: good job!

1 Like

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.