Picture moving in canvas with imperfections

  • (2 Pages)
  • +
  • 1
  • 2

20 Replies - 372 Views - Last Post: 07 December 2017 - 11:39 AM

#16 DK3250  Icon User is offline

  • Pythonian
  • member icon

Reputation: 396
  • View blog
  • Posts: 1,269
  • Joined: 27-December 13

Re: Picture moving in canvas with imperfections

Posted 06 December 2017 - 02:16 PM

@baavgai: Yes, I realized the part about fillRect parameters.
When you helped me 3-4 years ago learning Python, I often had to spend much time really understanding your answers and get it under my skin. Often as much time as I had used already making the code.
I see now, that you have not changed your style.... - good!
Was This Post Helpful? 0
  • +
  • -

#17 DK3250  Icon User is offline

  • Pythonian
  • member icon

Reputation: 396
  • View blog
  • Posts: 1,269
  • Joined: 27-December 13

Re: Picture moving in canvas with imperfections

Posted 06 December 2017 - 02:38 PM

@baavgai: Your line 76-68:
clear();
allSnow();
mover();


The two first are easy, return functions from the call to createClear() and createAllSnow().
But where the h... did mover() come from?

And you program structure: Enlightening! Javascript is more different from Python than I thought.
Was This Post Helpful? 0
  • +
  • -

#18 baavgai  Icon User is offline

  • Dreaming Coder
  • member icon


Reputation: 7153
  • View blog
  • Posts: 14,896
  • Joined: 16-October 07

Re: Picture moving in canvas with imperfections

Posted 06 December 2017 - 04:53 PM

View PostDK3250, on 06 December 2017 - 04:38 PM, said:

But where the h... did mover() come from?


We created it:
// these are mostly your values
// pass ctx and callback function
function createMovingThingy(ctx, cb) {
  const initX = -20;
  const resetX = 1000;
  const velocity = 2;
  const y = 10;
  // set starting value for x
  var x = initX;
  // init that image
  var img = new Image();
  img.src = 'julebryg.png';
  // when that image is loading
  // we call the callback and 
  // give it a function that will move the image
  img.onload = function () { cb(doit);  }
  // here's that function that will do the moving
  function doit() {
    ctx.drawImage(img, x, y);
    x += velocity;
    if (x > resetX) {
      x = initX;
    }
  }
}



Javascript loves closures and high order functions. If you stare at that doit() for a while, you'll see it's doing the movement you want. It has that image instance, so you only load it once.

Think of clever little functions with captured values as objects with only one public method; the call. Because, actually, that's what they are. Indeed, you can take a function reference and use a number of esoteric methods beyond that call...

I considered making Snow a function, but didn't want to mess with you. Conversely, you could make the above an object:
class Sprite {
  constructor(ctx, img) {
    this.ctx = ctx;
    this.initX = -20;
    this.x = initX;
    this.img = img;
  }
  move() {
    const resetX = 1000;
    const velocity = 2;
    const y = 10;
    this.ctx.drawImage(this.img, this.x, y);
    this.x += velocity;
    if (this.x > resetX) {
      this.x = initX;
    }
  }
}


Was This Post Helpful? 1
  • +
  • -

#19 baavgai  Icon User is offline

  • Dreaming Coder
  • member icon


Reputation: 7153
  • View blog
  • Posts: 14,896
  • Joined: 16-October 07

Re: Picture moving in canvas with imperfections

Posted 06 December 2017 - 05:52 PM

Another spin, before I turn in:
const SnowField = {
  canvasId: "myCanvas",
  speed: 20,
  width: 1200,
  height: 120
};

function createSnowFlake(ctx) {
  const radius = Math.floor(Math.random() * 3) + 2;
  const xPos = Math.floor(Math.random() * (SnowField.width - radius)) + radius;
  const P2 = 2 * Math.PI;
  let yPos = 15;
  return flake;
  function flake(){
    yPos += radius - 1;
    draw();
    return (yPos > SnowField.height) ? undefined : flake;
  }
  function draw(){
    ctx.beginPath();
    ctx.arc(xPos, yPos, radius, 0, P2);
    ctx.fillStyle = "white";
    ctx.fill();
  }
}

function createAllSnow(ctx) {
  let flakes = [];
  return function () {
    flakes.push(createSnowFlake(ctx));
    flakes = flakes.map(function(x) { return x(); }).filter(function(x) { return x; })
  }
}


function createClear(ctx) {
  const grd = ctx.createLinearGradient(0, 0, 0, 120);
  grd.addColorStop(0, "blue");
  grd.addColorStop(1, "white");
  return function () {
    ctx.fillStyle = grd;
    ctx.fillRect(0, 0, SnowField.width, SnowField.height);
  }
}



function createMovingThingy(ctx, cb) {
  const velocity = 2;
  const y = 10;
  let x = 0;
  const img = new Image();
  img.src = 'julebryg.png';
  img.onload = function () { cb(doit); }
  function doit() {
    ctx.drawImage(img, x, y);
    x += velocity;
    if (x > (SnowField.width - img.width)) {
      x = 0;
    }
  }
}

(function () {
  const ctx = document.getElementById(SnowField.canvasId).getContext("2d");
  const clear = createClear(ctx);
  const allSnow = createAllSnow(ctx);
  createMovingThingy(ctx, function (mover) {
    window.setInterval(function () {
      clear();
      allSnow();
      mover();
    }, SnowField.speed);
  })
})();


Was This Post Helpful? 0
  • +
  • -

#20 DK3250  Icon User is offline

  • Pythonian
  • member icon

Reputation: 396
  • View blog
  • Posts: 1,269
  • Joined: 27-December 13

Re: Picture moving in canvas with imperfections

Posted 07 December 2017 - 08:30 AM

@baavgai:
Your explanation in post #18 (first code block) was helpful. However, it took some time to understand the callback function and realize it constitute a closure. A function made callable despite the creating function 'createMovingThingy()' has been exhausted. Not easy stuff. Maybe with some similarities to decorators in Python..., but they are also not easy understood.

The second code block in post #18 is more straightforward - very similar to how I would make it in Python.
Phew, - something I understood directly!

The functions-only approach in post #19 is clear (now that I understand the callback/closure). It raises one question, however:
Is it better (or more Javascript'ish) to build the code around functions compared to class objects?
I have got used to class objects and find they are more OOP style...
Or maybe you just wanted to demonstrate the possibilities.

Thanks a lot for your effort, - it is certainly not wasted.

EDIT: Well lines 17 and 31 are maybe not so clear, but I think I've got the idea.

This post has been edited by DK3250: 07 December 2017 - 08:47 AM

Was This Post Helpful? 0
  • +
  • -

#21 baavgai  Icon User is offline

  • Dreaming Coder
  • member icon


Reputation: 7153
  • View blog
  • Posts: 14,896
  • Joined: 16-October 07

Re: Picture moving in canvas with imperfections

Posted 07 December 2017 - 11:39 AM

View PostDK3250, on 07 December 2017 - 10:30 AM, said:

Is it better (or more Javascript'ish) to build the code around functions compared to class objects?


Depends on who you ask, I guess. A curiosity of Javascript is that, while it's Object Oriented, it is no class based. It's prototype based. This has caused much confusion and there are probably more ways to create an "object" in JS than in any other language. Some have even suggested it's best to avoid the "new" instantiation all together.

When functional programming became popular, again, folks realized JS had all the attributes you'd want. Also, the callback pattern is baked into NodeJs and kind of became standard, though it was popular before then. However, the promise model is much easier. The jQuery library essentially invented a domain specific language in JS. Others have followed suit. Whether OOP is actually in play is often debatable. Ok, let's just say, like C++, modern Javascript is a glorious mess.

Like many OOP programmers, I find classes often get overused and messy and I'm joyously relieved when I can avoid them. Like functional programmers, I enjoy passing functions around when I can. It's done a lot now and I'm sure there are strong feelings for and against. I don't know what would be considered a best practice for this or even if it's possible.

As a programmer, you really just have to know such domains exist in a language. When you write your own code, you choose what works best for you.
Was This Post Helpful? 2
  • +
  • -

  • (2 Pages)
  • +
  • 1
  • 2