canvas數字時鐘之Ball對象及如何模擬物理效果

前言

Canvas案例-炫酷的數字時鐘中,展現了案例的最終效果,並簡單介紹了案例用到的知識點和案例中的對象,如今先介紹Ball對象,代碼有什麼問題歡迎你們指出。javascript

效果以下 java


Ball的屬性

跟個前面的效果,下面是我列舉的關鍵屬性bash

  • posX, posY, vx, vy, gravity, bounce, canMove 對象位置、運動參數dom

  • alive, birth, life 對象生命參數ide

  • light, color, radius 對象狀態參數函數

// 給出代碼
function Ball(data) {
  this.posX = data.posX || 0;
  this.posY = data.posY || 0;
  this.radius = data.radius || 10;
  this.vx = data.vx || Math.random() - 0.5;
  this.vy = data.vy || Math.random() - 0.5;
  this.alive = true;
  this.canMove = false;
  this.birth = null;
  this.light = false;
  this.color = data.color || `#${Math.random().toString(16).substr(3, 6)}`;
}
Ball.prototype = {
  init(data) {
    this.initData(data);
    this.blender();
    return this;
  },
  initData(data) {
    this.WIDTH = data.WIDTH;
    this.HEIGHT = data.HEIGHT;
    this.ctx = data.ctx;
    this.life = 1000 * 15;
    this.gravity = 0.08;
    this.bounce = -0.7;
  },
}
複製代碼

先說說幾個簡單的

這裏說一下爲何把參數分兩部分,initData裏的屬性全部Ball實例都同樣,沒有必要單獨設置,放到原型上,算是優化吧,減小沒必要要的開銷。post

值得注意的是顏色的隨機使用了截取Math.random()的16進制串,想當年仍是傻傻的用學習

Math.ceil(Math.random() * 255)複製代碼

這裏的canMove用了控制Ball是否能夠移動,light控制是否啓用顏色,還記得數字時鐘的數字先後沒有改變的時候是固定不動的嗎,並且仍是沒有顏色優化

關於爲啥設置生命參數

固然是清除無用的對象,釋放內存了。好比那些小球出了畫布已經沒有做用了,就能夠清除了,這裏使用alive標記,這樣能夠很方便的清除這些無用對象。其實這裏面還有一些對象的vx可能特別小,若是等這些對象移出畫布等待的事件會很長,因此這裏設置了life來記錄小球的生命,生命到期就會被標記ui

具體實現以下:

// 標記生命到期的對象
if (new Date() - this.birth > this.life) {
	this.alive = false;
}
// 標記移出畫布的對象
if (this.posX - this.radius <= 0 || this.posX >= WIDTH) {
	this.alive = false;
}複製代碼

下面是模擬物理屬性

回想高中咱們學習的物理知識—拋物線運動

v = at v = v0 + at h = 1/2 * at^2

然而實際卻沒法用這些,由於這裏咱們拿不到時間t,那麼咱們就要換個思路了

勻速運動

好比x方向作勻速運動,那麼vx勢必是定值,而後每次跟新把當前的posX = posX + vx,這樣


就能夠實現勻速運動了

加速運動

同理,y方向作加速運動,那麼vy勢必是變值,不只每次跟新把當前的posY = posY + vy,還要把這個重力加速度vy = gravity + vy ,這樣就能夠實現加速運動了

阻力呢?

爲了達到每次彈跳有衰減,這裏引入bounce參數,經過把這個參數設置一個(-1~0)便可實現反彈和衰減,一箭雙鵰。

// collide函數中
if (this.posY - this.radius <= 0 || this.posY + this.radius >= HEIGHT) {
    // 這裏的min max是碰撞檢測一個經典的作法
    this.posY = Math.min(this.posY, HEIGHT - this.radius);
    this.posY = Math.max(this.posY, 0);
    this.vy *= this.bounce;
}
// update函數中
if (this.canMove) {
    this.posX += this.vx;
    this.posY += this.vy;
    this.collide();
    this.vy += this.gravity;
}複製代碼

小結

好了,至此咱們已經完成了Ball對象的構建,使用這個對象已經能夠完成一些基本效果,好比下圖這些。有什麼問題能夠留言交流,下期是Tile對象的構建。

相關文章
相關標籤/搜索