// 该类作为基类使用,用于刷新绘制 // 定义绘制对象数组,存放每一帧绘制的对象 const AC_GAME_OBJECTS = []; // 导出类 export class AcGameObject { // 构造函数 constructor(){ // push(this) 是将当前对象存下来的意思 // 每创建一个,就 push 一个,先创建先 push,后创建后 push // 先创建的先执行 update ,后创建的会把先创建的给覆盖掉 AC_GAME_OBJECTS.push(this); // 帧与帧执行的时间间隔 this.timedelta=0; // 是否执行过 start 函数 this.has_called_start = false; } // start 函数只执行一次 start(){ } // 除第一帧之外,每一帧执行一遍 update(){ } // 删除之前执行 on_destroy(){ } // 删除 destroy(){ // 删除之前调用 on_destroy 函数 this.on_destroy(); // 在 js 里,使用 of 遍历的是数组里的值;使用 in 遍历的是数组的下标。 for(let i in AC_GAME_OBJECTS){ const obj = AC_GAME_OBJECTS[i]; // 如果 obj 等于当前对象,则删除该对象 if(obj === this){ // 使用 splice 删除数组里的对象 AC_GAME_OBJECTS.splice(i); break; } } } } // 上一帧执行的时刻 let last_timestamp; // step 函数需要传入当前帧执行的时刻 timestamp const step = (timestamp) => { // 遍历所有的物品 // 在 js 里,使用 of 遍历的是数组里的值;使用 in 遍历的是数组的下标。 for(let obj of AC_GAME_OBJECTS){ // 如果当前物品没有执行 start 函数,则该物品执行一次 start 函数 if(!obj.has_called_start){ // 将该物品的 has_called_start 赋值为 true,表示其已经执行过了 obj.has_called_start = true; obj.start(); } // 如果执行过 start ,则接下来应该执行 update 函数 else{ // 当前帧与上一帧的时间间隔:当前帧执行时刻减去上一帧执行时刻 obj.timedelta = timestamp - last_timestamp; obj.update(); } } // 更新 last_timestamp ,作为下一次更新的“上一帧执行的时刻” last_timestamp = timestamp; // 递归调用 requestAnimationFrame(step) } // 定义需要的刷新次数,传入的函数step会在下一帧浏览器渲染之前执行一遍。 requestAnimationFrame(step)