0

I am having a problem with integrating a simple timer to a game I am trying to build for a practice exercise. I have attempted to search for this solution on the internet but my basic knowledge of .js leaves me stuck at this problem. Can anyone help me with a solution to this?

My codepen is located here: https://codepen.io/jankyvision/pen/PoqYEXV

var c = document.createElement("canvas");
var ctx = c.getContext("2d");
c.width = 720; 
c.height = 480;
document.body.appendChild(c);

var perm = [];
while (perm.length < 255){
    while(perm.includes(val = Math.floor(Math.random()*255)));
    perm.push(val);
}

var lerp = (a,b,t) => a + (b-a) * (1-Math.cos(t*Math.PI))/2;
var noise = x=>{
    x = x * 0.01 % 254;
    return lerp(perm[Math.floor(x)], perm[Math.ceil(x)], x - Math.floor(x));
}

var Player =  function(){
    this.x = c.width/2;
    this.y = 0;
    this.ySpeed = 0;
    this.rot = 0;
    this.rSpeed = 0;
    this.img = new Image();
    this.img.src = "./images/moto.png";
    this.draw = function(){
        var p1 =  c.height - noise(t + this.x) * 0.25;
        var p2 =  c.height - noise(t+5 + this.x) * 0.25;

        var grounded = 0;
        if(p1-12 > this.y){
            this.ySpeed += 0.1;
        }else{
            this.ySpeed -= this.y - (p1-12);
            this.y = p1 - 12;
            grounded = 1;
        }

        var angle = Math.atan2((p2-12) - this.y, (this.x+5) - this.x);
        this.y += this.ySpeed;

        if(!playing || grounded && Math.abs(this.rot) > Math.PI * 0.5){
            playing = false;
            this.rSpeed = 5;
            k.ArrowUp = 1;
            this.x -= speed * 5;
        }


        if(grounded && playing){
            this.rot -= (this.rot - angle) * 0.65;
            this.rSpeed = this.rSpeed - (angle - this.rot);
        }
        this.rSpeed += (k.ArrowLeft - k.ArrowRight) * 0.05;
        this.rot -= this.rSpeed * 0.1;
        if(this.rot > Math.PI) this.rot = -Math.PI;
        if(this.rot < -Math.PI) this.rot = Math.PI;
        ctx.save();
        ctx.translate(this.x, this.y - 3);
        ctx.rotate(this.rot);
        ctx.drawImage(this.img, -15, -15, 60, 30);
        ctx.restore();
    }
}

var player = new Player();
var t = 0;
var speed = 0;
var playing = true;
var k = {ArrowUp:0, ArrowDown:0, ArrowLeft:0, ArrowRight:0};
function loop(){
    speed -= (speed - (k.ArrowUp - k.ArrowDown)) * 0.01;
    t += 10 * speed;
    ctx.fillStyle = "#8D5BC2";
    ctx.fillRect(0,0,c.width, c.height);

    ctx.fillStyle = "rgba(0,0,0,0.1)";
    ctx.beginPath();
    ctx.moveTo(0, c.height);
    for (let i = 0; i < c.width; i++)
        ctx.lineTo(i, c.height*0.8 - noise(t + i*5) * 0.25);
    ctx.lineTo(c.width, c.height);
    ctx.fill();

    ctx.fillStyle = "#444";
    ctx.beginPath();
    ctx.moveTo(0, c.height);
    for (let i = 0; i < c.width; i++)
        ctx.lineTo(i, c.height - noise(t + i) * 0.25);
    ctx.lineTo(c.width, c.height);
    ctx.fill();

    player.draw();
    if(player.x < 0)
        restart();
    requestAnimationFrame(loop);
}

onkeydown = d=> k[d.key] = 1;
onkeyup = d=> k[d.key] = 0;

function restart(){

    player = new Player();
    t = 0;
    speed = 0;
    playing = true;
    k = {ArrowUp:0, ArrowDown:0, ArrowLeft:0, ArrowRight:0};

}
loop();

var instructions = document.createElement("div");
instructions.innerHTML += "[up] [down] = accelerate <br> [Left] [Rigth] = rotate";
document.body.appendChild(instructions);
2
  • What is the issue exactly, I didn't get your problem, do you mean just adding seconds timer to the game canvas/HTML? Commented Feb 4, 2020 at 20:08
  • @mamounothman, yes I would like to add a seconds timer for when the game starts and i want that timer to restart when the game restarts too. Commented Feb 4, 2020 at 20:17

2 Answers 2

1

With some help from https://stackoverflow.com/a/16255190/1309377 you are looking at a pretty simple function that uses ctx.fillText() to draw the amount of elapsed seconds onto the canvas.

You want to use the Date() object when doing a timer as it is more accurate than setTimeout or setInterval.

On restart you just set startTime to the current time again.

var c = document.createElement("canvas");
var ctx = c.getContext("2d");
var startTime = new Date();
c.width = 720;
c.height = 480;
document.body.appendChild(c);

var perm = [];
while (perm.length < 255) {
  while (perm.includes(val = Math.floor(Math.random() * 255)));
  perm.push(val);
}

var lerp = (a, b, t) => a + (b - a) * (1 - Math.cos(t * Math.PI)) / 2;
var noise = x => {
  x = x * 0.01 % 254;
  return lerp(perm[Math.floor(x)], perm[Math.ceil(x)], x - Math.floor(x));
}

function drawElapsedTime() {
  var elapsed = parseInt((new Date() - startTime) / 1000);
  ctx.save();
  ctx.beginPath();
  ctx.fillStyle = "black";
  ctx.font = "14px Verdana"
  // draw the running time at half opacity
  ctx.globalAlpha = 0.50;
  ctx.fillText(elapsed + " seconds", 30,30);
  ctx.restore();
}

var Player = function() {
  this.x = c.width / 2;
  this.y = 0;
  this.ySpeed = 0;
  this.rot = 0;
  this.rSpeed = 0;
  this.img = new Image();
  this.img.src = "https://upload.wikimedia.org/wikipedia/en/3/3b/SpongeBob_SquarePants_character.svg";
  this.draw = function() {
    var p1 = c.height - noise(t + this.x) * 0.25;
    var p2 = c.height - noise(t + 5 + this.x) * 0.25;

    var grounded = 0;
    if (p1 - 12 > this.y) {
      this.ySpeed += 0.1;
    } else {
      this.ySpeed -= this.y - (p1 - 12);
      this.y = p1 - 12;
      grounded = 1;
    }

    var angle = Math.atan2((p2 - 12) - this.y, (this.x + 5) - this.x);
    this.y += this.ySpeed;

    if (!playing || grounded && Math.abs(this.rot) > Math.PI * 0.5) {
      playing = false;
      this.rSpeed = 5;
      k.ArrowUp = 1;
      this.x -= speed * 5;
    }


    if (grounded && playing) {
      this.rot -= (this.rot - angle) * 0.65;
      this.rSpeed = this.rSpeed - (angle - this.rot);
    }
    this.rSpeed += (k.ArrowLeft - k.ArrowRight) * 0.05;
    this.rot -= this.rSpeed * 0.1;
    if (this.rot > Math.PI) this.rot = -Math.PI;
    if (this.rot < -Math.PI) this.rot = Math.PI;
    ctx.save();
    ctx.translate(this.x, this.y - 3);
    ctx.rotate(this.rot);
    ctx.drawImage(this.img, -15, -15, 60, 30);
    ctx.restore();
  }
}

var player = new Player();
var t = 0;
var speed = 0;
var playing = true;
var k = {
  ArrowUp: 0,
  ArrowDown: 0,
  ArrowLeft: 0,
  ArrowRight: 0
};

function loop() {
  speed -= (speed - (k.ArrowUp - k.ArrowDown)) * 0.01;
  t += 10 * speed;
  ctx.fillStyle = "#8D5BC2";
  ctx.fillRect(0, 0, c.width, c.height);

  ctx.fillStyle = "rgba(0,0,0,0.1)";
  ctx.beginPath();
  ctx.moveTo(0, c.height);
  for (let i = 0; i < c.width; i++)
    ctx.lineTo(i, c.height * 0.8 - noise(t + i * 5) * 0.25);
  ctx.lineTo(c.width, c.height);
  ctx.fill();

  ctx.fillStyle = "#444";
  ctx.beginPath();
  ctx.moveTo(0, c.height);
  for (let i = 0; i < c.width; i++)
    ctx.lineTo(i, c.height - noise(t + i) * 0.25);
  ctx.lineTo(c.width, c.height);
  ctx.fill();

  player.draw();
  drawElapsedTime();
  if (player.x < 0)
    restart();
  requestAnimationFrame(loop);
}

onkeydown = d => k[d.key] = 1;
onkeyup = d => k[d.key] = 0;

function restart() {
  
  player = new Player();
  startTime = new Date();
  t = 0;
  speed = 0;
  playing = true;
  k = {
    ArrowUp: 0,
    ArrowDown: 0,
    ArrowLeft: 0,
    ArrowRight: 0
  };

}
loop();

var instructions = document.createElement("div");
instructions.innerHTML += "[up] [down] = accelerate <br> [Left] [Rigth] = rotate";
document.body.appendChild(instructions);

Sign up to request clarification or add additional context in comments.

Comments

0
var secs = 0;
setInterval(function(){secs++},1000);

this.draw = function(){

  // Fill in a rectangle to put the time inside of
  ctx.fillStyle="#000000";
  ctx.fillRect(10,10,55,25);

  ctx.fillStyle="#8D5BC2";
  ctx.font = "12px";

  // Format the number of seconds - 0:00
  timestr = Math.floor(secs/60) + ":";
  timestr += ((secs%60<10)&&"0") + secs%60;

  // Write the time string over the rectangle
  ctx.fillText(timestr,25,25);





2 Comments

Hi Kevin Morey, can you please clarify how I would implement your code above?
I edited my reply to show you the fillRect and fillText parts should go at the beginning of your this.draw function

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.