首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >HTML5游戏-本地缓存整个游戏

HTML5游戏-本地缓存整个游戏
EN

Stack Overflow用户
提问于 2014-07-06 01:19:16
回答 2查看 553关注 0票数 0

我正在创建一个HTML5 2D游戏,我只想请求每个资产一次,然后将它们存储在用户的文件系统中,我将使用localStorage来完成这项任务,但是AFAIK的每个来源限制为5mb (我的整个游戏将有更多),我想知道如何在用户的机器中存储我的游戏资产,而不是这个限制,这是我到现在为止所做的:

items.js:

代码语言:javascript
复制
/**
 * Copyright 2014 - Edgar Alexander Franco.
 *
 * @author Edgar Alexander Franco
 * @version 1.0.0
 */

var items = [
  {
    name : 'characters_scott', 
    url : './img/game/characters/scott', 
    type : 'png'
  }, 
  {
    name : 'map_1', 
    url : './img/game/map/1', 
    type : 'jpg'
  }, 
  {
    name : 'map_2', 
    url : './img/game/map/2', 
    type : 'jpg'
  }
];

Resource.js

代码语言:javascript
复制
/**
 * Copyright 2014 - Edgar Alexander Franco.
 *
 * @author Edgar Alexander Franco
 * @version 1.0.0
 */

var Resource = (function () {
  var self = {};

  self.get = {};

  self.load = function (items) {
    var xhr = (typeof XMLHttpRequest != 'undefined') ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP') ;
    var item, content, mime;

    for (var i in items) {
      item = items[ i ];
      content = localStorage.getItem(item.url);

      if (content == null) {
        xhr.open('GET', item.url, false);
        xhr.send();
        content = xhr.responseText;
        localStorage.setItem(item.url, content);
      }

      if (item.type != 'audio') {
        mime = (item.type == 'jpg') ? 'image/jpeg' : 'image/png' ;
        self.get[ item.name ] = new Image();
        self.get[ item.name ].src = 'data:' + mime + ';base64,' + content;
      } else {
        // Not yet...
      }
    }
  }

  return self;
})();

上面的代码很好用,但并不能满足我的需求,正如您所看到的,我正在使用localStore,而且它有其局限性,我想要修改相同的代码,但是对于一个无限的存储,有什么想法吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-07-08 22:29:24

经过长时间的研究,我得出结论: IndexedDB可能是我们能够找到的最适合这个任务的本地存储设备,因此,我重新设计了我的代码,现在是完整的类:

代码语言:javascript
复制
/**
 * Copyright 2014 - Edgar Alexander Franco.
 *
 * @author Edgar Alexander Franco
 * @version 1.0.0
 */

var Resources = (function () {
  var self = {};

  self.get = {};

  self.DOWNLOADED = 1;
  self.LOADED = 2;

  var DB_NAME = 'evilition';
  var TABLE_NAME = 'resources';

  self.audioType = (document.createElement('audio').canPlayType('audio/mp3') == '') ? '.ogg' : '.mp3' ;

  /**
   * Load the assets from the server / filesystem depending if each is cached or not.
   *
   * @param {object} resources Resources of the game.
   * @param {function} callback1 Function to be called on progress.
   * @param {function} callback2 Function to be called on error.
   * @param {function} callback3 Function to be called once the resources are loaded.
   */
  self.load = function (resources, callback1, callback2, callback3) {
    var request = indexedDB.open(DB_NAME, 3);

    request.onerror = function (evt) {
      callback2({});
    }

    request.onupgradeneeded = function (evt) {
      var db = evt.target.result;
      var table = db.createObjectStore(TABLE_NAME, {
        keyPath : 'name'
      });
      table.createIndex('name', 'name', {
        unique : true
      });
    }

    request.onsuccess = function (evt) {
      function loadResource () {
        var resource = resources[ i ];
        var request = objectStore.get(resource.name);

        request.onerror = function (evt) {
          callback2(resource);
        }

        request.onsuccess = function (evt) {
          var progress = Math.round(((i + 1) * 100) / total);
          var content;

          if (typeof request.result == 'undefined') {
            if (resource.type == 'audio') {
              resource.path += self.audioType;
            }

            xhr.open('GET', resource.path + '.b64', false);
            xhr.send();

            if (xhr.readyState == 4 && xhr.status == 200) {
              content = xhr.responseText;
              objectStore.add({
                name : resource.name, 
                content : content
              });
              callback1(resource, progress, self.DOWNLOADED);
            } else {
              callback2(resource);

              return;
            }
          } else {
            content = request.result.content;
            callback1(resource, progress, self.LOADED);
          }

          var mime;

          if (resource.type != 'audio') {
            mime = (resource.type == 'jpg') ? 'image/jpeg' : 'image/png' ;
            self.get[ resource.name ] = new Image;
          } else {
            mime = (self.audioType == '.mp3') ? 'audio/mp3' : 'audio/ogg' ;
            self.get[ resource.name ] = new Audio;
          }

          self.get[ resource.name ].src = 'data:' + mime + ';base64,' + content;
          i++;

          if (i == total) {
            db.close();
            callback3();
          } else {
            loadResource();
          }
        }
      }

      var db = evt.target.result;
      var objectStore = db.transaction(TABLE_NAME, 'readwrite').objectStore(TABLE_NAME);
      var xhr = (typeof XMLHttpRequest != 'undefined') ? new XMLHttpRequest : new ActiveXObject('Microsoft.XMLHTTP') ;
      var total = resources.length;
      var i = 0;

      loadResource();
    }
  }

  /**
   * Delete the resources database requiring the creation of a new one in the next load.
   */
  self.clearLocalCache = function () {
    indexedDB.deleteDatabase(DB_NAME);
  }

  return self;
})();

谢谢Gregor的推荐:)

票数 0
EN

Stack Overflow用户

发布于 2014-07-06 12:27:59

我建议你用localForage,Mozilla1。它提供了与localStorage相同的简单API,但得到了IndexedDB的支持(我认为有一个WebSQL / localStorage回退)。

另一种选择是,如果所有玩家的资产URL是相同的,则可以使用applicationCache。我建议您使用appCache包装库,如appCacheNanny2

1

2

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24591887

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档