.html のなかみ

更新:2022年8月16日   HSPトップへもどる


HSP製 Webアプリの実体は JavaScript を含んだ htmlファイルです。
自分の作ったオリジナルのスクリプトがこの部分に変換されます。
それに加えて
プログラムエンジンとなる hsp3dish.js
まとめた素材データ test.data
の3つのファイルでWebアプリがブラウザから実行されます。

・HSPスクリプトエディタで .hsp スクリプトを作成
 ↓
・HSP3Dish helper で 変換
 ↓
・ .html ができる。 

#include "hsp3dish.as"

title "いちばん簡単なスクリプト"

*main
	redraw 0
	pos 10,100 : mes "みなさん こんにちは"
	redraw 1
	await 100
	goto *main

↓ これを HSP3Dish helper で .html に変換すると

<!doctype html>
<html lang="en-us">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>minimum - HSP3Dish</title>
    <style>
      body {
        font-family: arial;
        margin: 0;
        padding: none;
      }

      .emscripten { padding-right: 0; margin-left: auto; margin-right: auto; display: block; }
      div.emscripten { text-align: center; }      
      div.emscripten_border { border: 1px solid black; }
      /* the canvas *must not* have any border or padding, or mouse coords will be wrong */
      canvas.emscripten { border: 0px none; }

      #emscripten_logo {
        display: inline-block;
        margin: 0;
      }

      .spinner {
        height: 30px;
        width: 30px;
        margin: 0;
        margin-top: 20px;
        margin-left: 20px;
        display: inline-block;
        vertical-align: top;

        -webkit-animation: rotation .8s linear infinite;
        -moz-animation: rotation .8s linear infinite;
        -o-animation: rotation .8s linear infinite;
        animation: rotation 0.8s linear infinite;

        border-left: 5px solid rgb(235, 235, 235);
        border-right: 5px solid rgb(235, 235, 235);
        border-bottom: 5px solid rgb(235, 235, 235);
        border-top: 5px solid rgb(120, 120, 120);
        
        border-radius: 100%;
        background-color: rgb(189, 215, 46);
      }

      @-webkit-keyframes rotation {
        from {-webkit-transform: rotate(0deg);}
        to {-webkit-transform: rotate(360deg);}
      }
      @-moz-keyframes rotation {
        from {-moz-transform: rotate(0deg);}
        to {-moz-transform: rotate(360deg);}
      }
      @-o-keyframes rotation {
        from {-o-transform: rotate(0deg);}
        to {-o-transform: rotate(360deg);}
      }
      @keyframes rotation {
        from {transform: rotate(0deg);}
        to {transform: rotate(360deg);}
      }

      #status {
        display: inline-block;
        vertical-align: top;
        margin-top: 30px;
        margin-left: 20px;
        font-weight: bold;
        color: rgb(120, 120, 120);
      }

      #progress {
        height: 20px;
        width: 30px;
      }

      #controls {
        display: inline-block;
        float: right;
        vertical-align: top;
        margin-top: 30px;
        margin-right: 20px;
      }

      #output {
        width: 100%;
        height: 200px;
        margin: 0 auto;
        margin-top: 10px;
        display: block;
        background-color: black;
        color: white;
        font-family: 'Lucida Console', Monaco, monospace;
        outline: none;
      }
    </style>
  </head>
  <body>
    <div class="spinner" id='spinner'></div>
    <div class="emscripten" id="status">Downloading...</div>

<span id='controls'>
  <span><input type="hidden" id="resize"></span>
  <span><input type="hidden" id="pointerLock"></span>
  <span><input type="hidden" value="Fullscreen" onclick="Module.requestFullScreen(document.getElementById('pointerLock').checked, 
                                                                            document.getElementById('resize').checked)">
  </span>
</span>

    <div class="emscripten">
      <progress value="0" max="100" id="progress" hidden=1></progress>
    </div>

    
    <div class="emscripten_border">
      <canvas class="emscripten" id="canvas" oncontextmenu="event.preventDefault()"></canvas>
    </div>
    <textarea id="output" rows="8"></textarea>

    <script type='text/javascript'>
      var statusElement = document.getElementById('status');
      var progressElement = document.getElementById('progress');
      var spinnerElement = document.getElementById('spinner');

      var Module = {
        INITIAL_MEMORY: 209715200,
        preRun: [],
        postRun: [],
        print: (function() {
          var element = document.getElementById('output');
          if (element) element.value = ''; // clear browser cache
          return function(text) {
            text = Array.prototype.slice.call(arguments).join(' ');
            // These replacements are necessary if you render to raw HTML
            //text = text.replace(/&/g, "&amp;");
            //text = text.replace(/</g, "&lt;");
            //text = text.replace(/>/g, "&gt;");
            //text = text.replace('\n', '<br>', 'g');
            console.log(text);
            if (element) {
              element.value += text + "\n";
              element.scrollTop = element.scrollHeight; // focus on bottom
            }
          };
        })(),
        printErr: function(text) {
          text = Array.prototype.slice.call(arguments).join(' ');
          if (0) { // XXX disabled for safety typeof dump == 'function') {
            dump(text + '\n'); // fast, straight to the real console
          } else {
            console.error(text);
          }
        },
        canvas: document.getElementById('canvas'),
        setStatus: function(text) {
          if (!Module.setStatus.last) Module.setStatus.last = { time: Date.now(), text: '' };
          if (text === Module.setStatus.text) return;
          var m = text.match(/([^(]+)\((\d+(\.\d+)?)\/(\d+)\)/);
          var now = Date.now();
          if (m && now - Date.now() < 30) return; // if this is a progress update, skip it if too soon
          if (m) {
            text = m[1];
            progressElement.value = parseInt(m[2])*100;
            progressElement.max = parseInt(m[4])*100;
            progressElement.hidden = false;
            spinnerElement.hidden = false;
          } else {
            progressElement.value = null;
            progressElement.max = null;
            progressElement.hidden = true;
            if (!text) spinnerElement.style.display = 'none';
          }
          statusElement.innerHTML = text;
        },
        totalDependencies: 0,
        monitorRunDependencies: function(left) {
          this.totalDependencies = Math.max(this.totalDependencies, left);
          Module.setStatus(left ? 'Preparing... (' + (this.totalDependencies-left) + '/' + this.totalDependencies + ')' : 'All downloads complete.');
        },
        arguments: ["minimum.ax"]
      };
      Module.setStatus('Downloading...');

/* block.js */

var Module;
if (typeof Module === 'undefined') Module = eval('(function() { try { return Module || {} } catch(e) { return {} } })()');
if (!Module.expectedDataFileDownloads) {
  Module.expectedDataFileDownloads = 0;
  Module.finishedDataFileDownloads = 0;
}
Module.expectedDataFileDownloads++;
(function() {

    var PACKAGE_PATH;
    if (typeof window === 'object') {
      PACKAGE_PATH = window['encodeURIComponent'](window.location.pathname.toString().substring(0, window.location.pathname.toString().lastIndexOf('/')) + '/');
    } else {
      // worker
      PACKAGE_PATH = encodeURIComponent(location.pathname.toString().substring(0, location.pathname.toString().lastIndexOf('/')) + '/');
    }
    var PACKAGE_NAME = 'minimum.data';
    var REMOTE_PACKAGE_NAME = (Module['filePackagePrefixURL'] || '') + 'minimum.data';
    var REMOTE_PACKAGE_SIZE = 312;
    var PACKAGE_UUID = '51f84d03-0c74-4552-ac13-924e79e76977';
  
    function fetchRemotePackage(packageName, packageSize, callback, errback) {
      var xhr = new XMLHttpRequest();
      xhr.open('GET', packageName, true);
      xhr.responseType = 'arraybuffer';
      xhr.onprogress = function(event) {
        var url = packageName;
        var size = packageSize;
        if (event.total) size = event.total;
        if (event.loaded) {
          if (!xhr.addedTotal) {
            xhr.addedTotal = true;
            if (!Module.dataFileDownloads) Module.dataFileDownloads = {};
            Module.dataFileDownloads[url] = {
              loaded: event.loaded,
              total: size
            };
          } else {
            Module.dataFileDownloads[url].loaded = event.loaded;
          }
          var total = 0;
          var loaded = 0;
          var num = 0;
          for (var download in Module.dataFileDownloads) {
          var data = Module.dataFileDownloads[download];
            total += data.total;
            loaded += data.loaded;
            num++;
          }
          total = Math.ceil(total * Module.expectedDataFileDownloads/num);
          if (Module['setStatus']) Module['setStatus']('Downloading data... (' + loaded + '/' + total + ')');
        } else if (!Module.dataFileDownloads) {
          if (Module['setStatus']) Module['setStatus']('Downloading data...');
        }
      };
      xhr.onload = function(event) {
        var packageData = xhr.response;
        callback(packageData);
      };
      xhr.send(null);
    };

    function handleError(error) {
      console.error('package error:', error);
    };
  
      var fetched = null, fetchedCallback = null;
      fetchRemotePackage(REMOTE_PACKAGE_NAME, REMOTE_PACKAGE_SIZE, function(data) {
        if (fetchedCallback) {
          fetchedCallback(data);
          fetchedCallback = null;
        } else {
          fetched = data;
        }
      }, handleError);
    
  function runWithFS() {

function assert(check, msg) {
  if (!check) throw msg + new Error().stack;
}



    function DataRequest(start, end, crunched, audio) {
      this.start = start;
      this.end = end;
      this.crunched = crunched;
      this.audio = audio;
    }
    DataRequest.prototype = {
      requests: {},
      open: function(mode, name) {
        this.name = name;
        this.requests[name] = this;
        Module['addRunDependency']('fp ' + this.name);
      },
      send: function() {},
      onload: function() {
        var byteArray = this.byteArray.subarray(this.start, this.end);

          this.finish(byteArray);

      },
      finish: function(byteArray) {
        var that = this;
        Module['FS_createPreloadedFile'](this.name, null, byteArray, true, true, function() {
          Module['removeRunDependency']('fp ' + that.name);
        }, function() {
          if (that.audio) {
            Module['removeRunDependency']('fp ' + that.name); // workaround for chromium bug 124926 (still no audio with this, but at least we don't hang)
          } else {
            Module.printErr('Preloading file ' + that.name + ' failed');
          }
        }, false, true); // canOwn this data in the filesystem, it is a slide into the heap that will never change
        this.requests[this.name] = null;
      },
    };

      new DataRequest(0, 312, 0, 0).open('GET', 'minimum.ax');


    function processPackageData(arrayBuffer) {
      Module.finishedDataFileDownloads++;
      assert(arrayBuffer, 'Loading data file failed.');
      var byteArray = new Uint8Array(arrayBuffer);
      var curr;
      
      // copy the entire loaded file into a spot in the heap. Files will refer to slices in that. They cannot be freed though.
      var ptr = Module['_malloc'](byteArray.length);
      Module['HEAPU8'].set(byteArray, ptr);
      DataRequest.prototype.byteArray = Module['HEAPU8'].subarray(ptr, ptr+byteArray.length);

          DataRequest.prototype.requests["minimum.ax"].onload();

          Module['removeRunDependency']('datafile_minimum.data');

    };
    Module['addRunDependency']('datafile_minimum.data');
  
    if (!Module.preloadResults) Module.preloadResults = {};
  
      Module.preloadResults[PACKAGE_NAME] = {fromCache: false};
      if (fetched) {
        processPackageData(fetched);
        fetched = null;
      } else {
        fetchedCallback = processPackageData;
      }
    
        ENV.HSP_WX = "320";//スクリプトの動作解像度
        ENV.HSP_WY = "480";
        ENV.HSP_SX = "320";//表示解像度
        ENV.HSP_SY = "480";
        ENV.HSP_AUTOSCALE = "0";//スケーリングモード
        ENV.HSP_FPS = "0";//フレームレート
        ENV.HSP_LIMIT_STEP = "15000";//ブラウザに処理を返すまでの実行ステップ数

  }
  if (Module['calledRun']) {
    runWithFS();
  } else {
    if (!Module['preRun']) Module['preRun'] = [];
    Module["preRun"].push(runWithFS); // FS is not initialized yet, wait for it
  }

})();


				var fixAudioContext = function (e) {
				        SDL.openAudioContext();
					var context = SDL.audioContext;
					if (context) {
						// Create empty buffer
						var buffer = context.createBuffer(1, 1, 22050);
						var source = context.createBufferSource();
						source.buffer = buffer;
						// Connect to output (speakers)
						source.connect(context.destination);
						// Play sound
						if (source.start) {
							source.start(0);
						} else if (source.play) {
							source.play(0);
						} else if (source.noteOn) {
							source.noteOn(0);
						}
						//const soundEffect = new Audio();
						//soundEffect.play();
					      console.log('audio unlock:');
					}

					var target = document;
					//var target = document.getElementById('canvas');

					// Remove events
					target.removeEventListener('touchstart', fixAudioContext);
					target.removeEventListener('touchend', fixAudioContext);
					target.removeEventListener('mousedown', fixAudioContext);
				};
				//var target = document.getElementById('canvas');
				var target = document;
				// iOS 6-8
				target.addEventListener('touchstart', fixAudioContext);
				// iOS 9
				target.addEventListener('touchend', fixAudioContext);
				target.addEventListener('mousedown', fixAudioContext);


    </script>
    <script async type="text/javascript" src="hsp3dish.js"></script>
  <p><font size="2" color="#404040">powered by <a href="https://hsp.tv/make/hsp3dish.html" target="_blank">hsp3dish.js</a> / OpenHSP</font></p>
  </body>
</html>

※ HSP3Dish helper は HSP3.7ベータ2付属の ver.1.94 を使用。
↑このページでは見づらいので、自分のテキストエディタにコピー貼り付けして横幅の広い画面でみると見やすいです。

この .htmlファイルは開発者が自由に編集してかまいません

 これまでに ホームページを作ったことがなかったり、HTML タグを見たことがなかったり、JavaScript を勉強した経験がないと、どこを修正してよいのか、わけがわからなくて心配になるかもしれません。
「なかみを書き換えて変更したら、動かなくなっちゃうんじゃないかな…?」
という不安があるかもしれませんが、一つづつゆっくり見ていけば、それほどむずかしくはありません。
よくみると HSPでいうところの「命令」と似ている htmlの「タグ」は、

・ここからタグの命令がはじまりますよ
・ここまででタグの命令はおわりですよ

<title> かんたんサンプル </title>
<script> </script>

のように、それぞれの命令が「開始のしるし」「終了のしるし」一組づつになって、それがたくさんあつまっているだけです。

おおまかに言うと、HSPスクリプトエディタで作ったプログラムの部分は、変換されて、まんなかの
<script> </script> のあいだに含まれています。
さいしょは、それ以外の部分を編集、追記、修正していくとよいかもしれません。

たとえば、アプリ画面の下部に、ゲームの説明文章を表示するだけでも親切で役に立つかもしれません。

.html を編集するときは、テキストエディタ(アプリ)を使用するのが良いです。
「テキストエディタ」はネットで検索するといろいろ無料のものが出てきます。
自分の好きなモノ、安全なモノを使用しましょう。

Webサイト用 htmlファイルを編集するのに特化したアプリもあります。

ざんねんながら付属の「HSPスクリプトエディタ」では日本語文字が化けてコメントなど読みにくくなるので「htmlファイルを編集する」という目的では使いづらいです。

◆画面サイズの実験」のページに、タグのコメント化(無効化)や修正の具体例が書いてあります


もっと詳しい情報を知りたい方、
または、この分野が得意で知識と開発技術があって協力したい方は、
OpenHSP( .js 作者 zakki )  OpenHSP(公式 onitama )
こちらをご覧ください


   HSPトップへもどる