summaryrefslogtreecommitdiffhomepage
path: root/deploy_template
diff options
context:
space:
mode:
Diffstat (limited to 'deploy_template')
-rw-r--r--deploy_template/.dragonruby/stubs/html5/dragonruby-html5-loader.js688
-rw-r--r--deploy_template/.dragonruby/stubs/html5/stub/game.css8
-rw-r--r--deploy_template/.dragonruby/stubs/html5/stub/index.html93
-rw-r--r--deploy_template/CHANGELOG.txt291
-rw-r--r--deploy_template/mygame/app/main.rb3
-rw-r--r--deploy_template/mygame/app/tests.rb2
-rw-r--r--deploy_template/mygame/sprites/border-black.pngbin0 -> 908 bytes
-rw-r--r--deploy_template/mygame/sprites/dragon-0.pngbin0 -> 12896 bytes
-rw-r--r--deploy_template/mygame/sprites/dragon-1.pngbin0 -> 2964 bytes
-rw-r--r--deploy_template/mygame/sprites/dragon-2.pngbin0 -> 3047 bytes
-rw-r--r--deploy_template/mygame/sprites/dragon-3.pngbin0 -> 2655 bytes
-rw-r--r--deploy_template/mygame/sprites/dragon-4.pngbin0 -> 2725 bytes
-rw-r--r--deploy_template/mygame/sprites/dragon-5.pngbin0 -> 2655 bytes
-rw-r--r--deploy_template/mygame/sprites/explosion-0.pngbin0 -> 267 bytes
-rw-r--r--deploy_template/mygame/sprites/explosion-1.pngbin0 -> 4585 bytes
-rw-r--r--deploy_template/mygame/sprites/explosion-2.pngbin0 -> 4675 bytes
-rw-r--r--deploy_template/mygame/sprites/explosion-3.pngbin0 -> 4724 bytes
-rw-r--r--deploy_template/mygame/sprites/explosion-4.pngbin0 -> 4773 bytes
-rw-r--r--deploy_template/mygame/sprites/explosion-5.pngbin0 -> 4742 bytes
-rw-r--r--deploy_template/mygame/sprites/explosion-6.pngbin0 -> 4665 bytes
-rw-r--r--deploy_template/mygame/sprites/explosion-sheet.pngbin0 -> 2584 bytes
-rw-r--r--deploy_template/mygame/sprites/star.pngbin0 -> 711 bytes
22 files changed, 1065 insertions, 20 deletions
diff --git a/deploy_template/.dragonruby/stubs/html5/dragonruby-html5-loader.js b/deploy_template/.dragonruby/stubs/html5/dragonruby-html5-loader.js
new file mode 100644
index 0000000..c321422
--- /dev/null
+++ b/deploy_template/.dragonruby/stubs/html5/dragonruby-html5-loader.js
@@ -0,0 +1,688 @@
+function syncDataFiles(dbname, baseurl)
+{
+ var retval = {};
+ if (typeof (dbname) === "undefined") { dbname = "files"; }
+ if (typeof (baseurl) === "undefined") { baseurl = ""; }
+
+ // this is appended to files as an arg to defeat XMLHttpRequest cacheing.
+ // (Don't do this on most hosting services, from itch.io to
+ // playonjump.com, since we generally don't update the datafiles anyhow
+ // once we're shipping, and it defeats Cloudflare cacheing, causing it
+ // to abuse Amazon S3, etc.)
+ var urlrandomizerarg = '';
+ if (false) {
+ urlrandomizerarg = "?nocache=" + (Date.now() / 1000 | 0);
+ }
+
+ var state = {
+ db: null,
+ reported_result: false,
+ xhrs: {},
+ remote_manifest: {},
+ remote_manifest_loaded: false,
+ local_manifest: {},
+ local_manifest_loaded: false,
+ total_to_download: 0,
+ total_downloaded: 0,
+ total_files: 0,
+ pending_files: 0
+ };
+
+ var log = function(str) { console.log("CACHEAPPDATA: " + str); }
+ var debug = function(str) {}
+ //debug = function(str) { log(str); }
+
+ var clear_state = function() {
+ for (var i in state.xhrs) {
+ state.xhrs[i].abort();
+ }
+ delete state.db;
+ delete state.xhrs;
+ delete state.remote_manifest;
+ delete state.local_manifest;
+ };
+
+ var failed = function(why) {
+ if (state.reported_result) { return; }
+ state.reported_result = true;
+ log("[FAILURE] " + why);
+ clear_state();
+ if (retval.onerror) {
+ retval.onerror(why);
+ }
+ };
+
+ retval.abort = function() {
+ failed("Aborted.");
+ }
+
+ var succeeded = function() {
+ if (state.reported_result) { return; }
+ state.reported_result = true;
+ var why = "File data synchronized (downloaded " + Math.ceil(state.total_downloaded / 1048576) + " megabytes in " + state.total_files + " files)";
+ log("[SUCCESS] " + why);
+ retval.db = state.db;
+ retval.manifest = state.remote_manifest;
+ clear_state();
+ if (retval.onsuccess) {
+ retval.onsuccess(why);
+ }
+ };
+
+ var prevprogress = "";
+ var progress = function(str) {
+ if (state.reported_result) { return; }
+ if (str == prevprogress) { return; }
+ prevprogress = str;
+ log("[PROGRESS] " + str);
+ if (retval.onprogress) {
+ retval.onprogress(str, state.total_downloaded, state.total_to_download);
+ }
+ }
+
+ debug("Database name is '" + dbname + "'.");
+ progress("Opening database...");
+ var dbopen = window.indexedDB.open(dbname, 1);
+
+ // this is called if we change the version or the database doesn't exist.
+ // Use it to create the schema.
+ dbopen.onupgradeneeded = function(event) {
+ progress("Upgrading/creating local database...");
+ var db = event.target.result;
+ var metadataStore = db.createObjectStore("metadata", { keyPath: 'filename' });
+ var dataStore = db.createObjectStore("data", { keyPath: 'chunkid', autoIncrement: true });
+ dataStore.createIndex("data", "filename", { unique: false });
+ };
+
+ dbopen.onerror = function(event) {
+ failed("Couldn't open local database: " + event.target.error.message);
+ };
+
+ var finished_file = function(fname) {
+ debug("Finished writing '" + fname + "' to the database!");
+ state.pending_files--;
+ if (state.pending_files < 0) {
+ state.pending_files = 0;
+ debug("Uhoh, pending_files went negative?!");
+ }
+ if (state.pending_files == 0) {
+ succeeded();
+ }
+ };
+
+ var store_file = function(xhr) {
+ // write to the database...
+ var databuf = xhr.response;
+ var transaction = state.db.transaction(["metadata", "data"], "readwrite");
+ var objstoremetadata = transaction.objectStore("metadata");
+ var objstoredata = transaction.objectStore("data");
+
+ objstoremetadata.add({ filename: xhr.filename, filesize: xhr.filesize, filetime: xhr.filetime });
+ // !!! FIXME: _of course_ this crashes Safari on large files
+ /*
+ var chunksize = 1048576; // 1 megabyte each.
+ var chunks = Math.ceil(xhr.response.byteLength / chunksize);
+ for (var i = 0; i < chunks; i++) {
+ var bufoffset = i * chunksize;
+ objstoredata.add({
+ filename: xhr.filename,
+ offset: bufoffset,
+ chunk: new Uint8Array(databuf, bufoffset, chunksize);
+ });
+ }
+ */
+ objstoredata.add({ filename: xhr.filename, offset: 0, chunk: databuf });
+
+ transaction.oncomplete = function(event) {
+ finished_file(xhr.filename); // all done here!
+ };
+ };
+
+ var download_new_files = function() {
+ if (state.reported_result) { return; }
+ progress("Downloading new files...");
+ var downloadme = [];
+ for (var i in state.remote_manifest) {
+ var remoteitem = state.remote_manifest[i];
+ var remotefname = i;
+ if (typeof state.local_manifest[remotefname] !== "undefined") {
+ debug("remote filename '" + remotefname + "' already downloaded.");
+ } else {
+ debug("remote filename '" + remotefname + "' needs downloading.");
+ // the browser will let a handful of these go in parallel, and
+ // then will queue the rest, firing events as appropriate
+ // when it gets around to them, so just fire them all off
+ // here.
+
+ // !!! FIXME: use the Fetch API, plus streaming, as an option.
+ // !!! FIXME: It can use less memory, since it doesn't need
+ // !!! FIXME: to keep the whole file in memory.
+ state.total_to_download += remoteitem.filesize;
+ state.total_files++;
+ state.pending_files++;
+
+ var xhr = new XMLHttpRequest();
+ state.xhrs[remotefname] = xhr;
+ xhr.previously_loaded = 0;
+ xhr.filename = remotefname;
+ xhr.filesize = state.remote_manifest[i].filesize;
+ xhr.filetime = state.remote_manifest[i].filetime;
+ xhr.expected_filesize = remoteitem.filesize;
+ xhr.responseType = "arraybuffer";
+ xhr.addEventListener("error", function(e) { failed("Download error on '" + e.target.filename + "'!"); });
+ xhr.addEventListener("timeout", function(e) { failed("Download timeout on '" + e.target.filename + "'!"); });
+ xhr.addEventListener("abort", function(e) { failed("Download abort on '" + e.target.filename + "'!"); });
+
+ xhr.addEventListener('progress', function(e) {
+ if (state.reported_result) { return; }
+ var xhr = e.target;
+ var additional = e.loaded - xhr.previously_loaded;
+ state.total_downloaded += additional;
+ xhr.previously_loaded = e.loaded;
+ debug("Downloaded " + additional + " more bytes for file '" + xhr.filename + "'");
+ var percent = state.total_to_download ? Math.floor((state.total_downloaded / state.total_to_download) * 100.0) : 0;
+ progress("Downloaded " + percent + "% (" + Math.ceil(state.total_downloaded / 1048576) + "/" + Math.ceil(state.total_to_download / 1048576) + " megabytes)");
+ });
+
+ xhr.addEventListener("load", function(e) {
+ if (state.reported_result) { return; }
+ var xhr = e.target;
+ if (xhr.status != 200) {
+ failed("Server reported failure downloading '" + xhr.filename + "'!");
+ } else {
+ debug("Finished download of '" + xhr.filename + "'!");
+ state.total_downloaded -= xhr.previously_loaded;
+ state.total_downloaded += xhr.expected_filesize;
+ xhr.previously_loaded = xhr.expected_filesize;
+ delete state.xhrs[xhr.filename];
+ var percent = state.total_to_download ? Math.floor((state.total_downloaded / state.total_to_download) * 100.0) : 0;
+ progress("Downloaded " + percent + "% (" + Math.ceil(state.total_downloaded / 1048576) + "/" + Math.ceil(state.total_to_download / 1048576) + " megabytes)");
+ store_file(xhr);
+ }
+ });
+
+ xhr.open("get", baseurl + remotefname + urlrandomizerarg, true);
+ xhr.send();
+ }
+ }
+
+ if (state.pending_files == 0) {
+ succeeded(); // we're already done. :)
+ }
+ };
+
+ var delete_old_files = function() {
+ if (state.reported_result) { return; }
+ var deleteme = []
+ for (var i in state.local_manifest) {
+ var localitem = state.local_manifest[i];
+ var localfname = localitem.filename;
+ var removeme = false;
+ if (typeof state.remote_manifest[localfname] === "undefined") {
+ removeme = true;
+ } else {
+ var remoteitem = state.remote_manifest[localfname];
+ if ( (localitem.filesize != remoteitem.filesize) ||
+ (localitem.filetime != remoteitem.filetime) ) {
+ removeme = true;
+ }
+ }
+
+ if (removeme) {
+ debug("Marking old file '" + localfname + "' for removal.");
+ deleteme.push(localfname);
+ delete state.local_manifest[i];
+ }
+ }
+
+ if (deleteme.length == 0) {
+ debug("No old files to delete.");
+ download_new_files(); // just move on to the next stage.
+ } else {
+ progress("Cleaning up old files...");
+ var transaction = state.db.transaction(["data", "metadata"], "readwrite");
+ transaction.oncomplete = function(event) {
+ debug("All old files are deleted.");
+ download_new_files();
+ };
+
+ var objstoremetadata = transaction.objectStore("metadata");
+ var objstoredata = transaction.objectStore("data");
+ var dataindex = objstoredata.index("data");
+ for (var i of deleteme) {
+ debug("Deleting metadata for '" + i + "'.");
+ objstoremetadata.delete(i);
+ dataindex.openCursor(IDBKeyRange.only(i)).onsuccess = function(event) {
+ var cursor = event.target.result;
+ if (cursor) {
+ debug("Deleting file chunk " + cursor.value.chunkid + " for '" + cursor.value.filename + "' (offset=" + cursor.value.offset + ", size=" + cursor.value.size + ").");
+ objstoredata.delete(cursor.value.chunkid);
+ cursor.continue();
+ }
+ }
+ }
+ }
+ };
+
+ var manifest_loaded = function() {
+ if (state.reported_result) { return; }
+ if (state.local_manifest_loaded && state.remote_manifest_loaded) {
+ debug("both manifests loaded, moving on to next step.");
+ delete_old_files(); // on success, will start downloads.
+ }
+ };
+
+ var load_local_manifest = function(db) {
+ if (state.reported_result) { return; }
+ debug("Loading local manifest...");
+ var transaction = db.transaction("metadata", "readonly");
+ var objstore = transaction.objectStore("metadata");
+ var cursor = objstore.openCursor();
+
+ // this gets called once for each item in the object store.
+ cursor.onsuccess = function(event) {
+ if (state.reported_result) { return; }
+ var cursor = event.target.result;
+ if (cursor) {
+ debug("Another local manifest item: '" + cursor.value.filename + "'");
+ state.local_manifest[cursor.value.filename] = cursor.value;
+ cursor.continue();
+ } else {
+ debug("All local manifest items iterated.");
+ state.local_manifest_loaded = true;
+ manifest_loaded(); // maybe move on to next step.
+ }
+ };
+ };
+
+ dbopen.onsuccess = function(event) {
+ debug("Database is open!");
+ var db = event.target.result;
+ state.db = db;
+
+ // just catch all database errors here, where they will bubble up
+ // from objectstores and transactions.
+ db.onerror = function(event) {
+ failed("Database error: " + event.target.error.message);
+ };
+
+ progress("Loading file manifests...");
+
+ // this is async, so it happens while remote manifest downloads.
+ load_local_manifest(db);
+
+ debug("Loading remote manifest...");
+ var xhr = new XMLHttpRequest();
+ xhr.responseType = "text";
+ xhr.addEventListener("error", function(e) { failed("Manifest download error!"); });
+ xhr.addEventListener("timeout", function(e) { failed("Manifest download timeout!"); });
+ xhr.addEventListener("abort", function(e) { failed("Manifest download abort!"); });
+ xhr.addEventListener("load", function(e) {
+ if (e.target.status != 200) {
+ failed("Server reported failure downloading manifest!");
+ } else {
+ debug("Remote manifest loaded!");
+ debug("json: " + e.target.responseText);
+ state.remote_manifest_loaded = true;
+ try {
+ state.remote_manifest = JSON.parse(e.target.responseText);
+ } catch (e) {
+ failed("Remote manifest is corrupted.");
+ }
+ delete state.remote_manifest[""]
+ manifest_loaded(); // maybe move on to next step.
+ }
+ });
+ xhr.open("get", "manifest.json" + urlrandomizerarg, true);
+ xhr.send();
+ };
+
+ return retval;
+}
+
+var statusElement = document.getElementById('status');
+var progressElement = document.getElementById('progress');
+var canvasElement = document.getElementById('canvas');
+
+canvasElement.style.width = '1280px';
+canvasElement.style.height = '720px';
+canvasElement.style.display = 'block';
+canvasElement.style['margin-left'] = 'auto';
+canvasElement.style['margin-right'] = 'auto';
+
+statusElement.style.display = 'none';
+progressElement.style.display = 'none';
+document.getElementById('progressdiv').style.display = 'none';
+document.getElementById('output').style.display = 'none';
+document.getElementById('game-input').style.display = "none"
+
+if (!window.parent.window.gtk) {
+ window.parent.window.gtk = {};
+}
+
+window.parent.window.gtk.saveMain = function(text) {
+ FS.writeFile('app/main.rb', text);
+ window.gtk.play();
+}
+
+
+var loadDataFiles = function(dbname, baseurl, onsuccess) {
+ var syncdata = syncDataFiles(dbname, baseurl);
+ window.gtk.syncdata = syncdata;
+
+ syncdata.onerror = function(why) {
+ Module.setStatus(why);
+ }
+
+ syncdata.onprogress = function(why, total_downloaded, total_to_download) {
+ Module.setStatus(why);
+ }
+
+ syncdata.onsuccess = function(why) {
+ //Module.setStatus(why);
+ console.log(why);
+
+ GGameFilesDatabase = syncdata.db;
+ window.gtk.filedb = syncdata.db;
+
+ var db = syncdata.db;
+ var manifest = syncdata.manifest;
+ syncdata.failed = false;
+ syncdata.num_requests = 0;
+ syncdata.total_requests = 0;
+
+ db.onerror = function(event) {
+ Module.setStatus("Database error: " + event.target.error.message);
+ syncdata.failed = true;
+ };
+
+ var transaction = db.transaction("data", "readonly");
+ var objstore = transaction.objectStore("data");
+ var dataindex = objstore.index("data");
+
+ for (var i in manifest) {
+ // !!! FIXME: this assumes the whole file is in one chunk, but
+ // !!! FIXME: that was not my original plan.
+ syncdata.total_requests++;
+ syncdata.num_requests++;
+ //console.log("'" + i + "' is headed for MEMFS...");
+ var req = dataindex.get(i);
+ req.filesize = manifest[i].filesize;
+ req.onsuccess = function(event) {
+ var path = "/" + event.target.result.filename;
+ //console.log("'" + path + "' is loaded in from IndexedDB...");
+ var ui8arr = new Uint8Array(event.target.result.chunk);
+ var len = event.target.filesize;
+ var arr = new Array(len);
+ for (var i = 0; i < len; ++i) {
+ arr[i] = ui8arr[i];
+ }
+
+ var basedir = PATH.dirname(path);
+ FS.mkdirTree(basedir);
+
+ var okay = false;
+ try {
+ okay = FS.createDataFile(basedir, PATH.basename(path), arr, true, true, true);
+ } catch (err) { // throws if file exists, etc. Nuke and try one more time.
+ FS.unlink(path);
+ try {
+ okay = FS.createDataFile(basedir, PATH.basename(path), arr, true, true, true);
+ } catch (err) {
+ okay = false; // oh well.
+ }
+ }
+
+ if (!okay) {
+ Module.setStatus("ERROR: Failed to put '" + path + "' in MEMFS.");
+ } else {
+ var completed = syncdata.total_requests - syncdata.num_requests;
+ var percent = Math.floor((completed / syncdata.total_requests) * 100.0);
+ Module.setStatus("Preparing game data: " + percent + "%");
+ //console.log("'" + path + "' has made it to MEMFS! (" + syncdata.num_requests + " to go)");
+ syncdata.num_requests--;
+ if (syncdata.num_requests <= 0) {
+ if (!syncdata.failed) {
+ onsuccess();
+ }
+ }
+ }
+ };
+ }
+ }
+}
+
+// https://stackoverflow.com/a/7372816
+var base64Encode = function(ui8array) {
+ var CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+ var out = "", i = 0, len = ui8array.length, c1, c2, c3;
+ while (i < len) {
+ c1 = ui8array[i++] & 0xff;
+ if (i == len) {
+ out += CHARS.charAt(c1 >> 2);
+ out += CHARS.charAt((c1 & 0x3) << 4);
+ out += "==";
+ break;
+ }
+ c2 = ui8array[i++];
+ if (i == len) {
+ out += CHARS.charAt(c1 >> 2);
+ out += CHARS.charAt(((c1 & 0x3)<< 4) | ((c2 & 0xF0) >> 4));
+ out += CHARS.charAt((c2 & 0xF) << 2);
+ out += "=";
+ break;
+ }
+ c3 = ui8array[i++];
+ out += CHARS.charAt(c1 >> 2);
+ out += CHARS.charAt(((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4));
+ out += CHARS.charAt(((c2 & 0xF) << 2) | ((c3 & 0xC0) >> 6));
+ out += CHARS.charAt(c3 & 0x3F);
+ }
+ return out;
+}
+
+var Module = {
+ noInitialRun: true,
+ preInit: [],
+ clickedToPlay: false,
+ clickToPlayListener: function() {
+ if (Module.clickedToPlay) return;
+ Module.clickedToPlay = true;
+ var div = document.getElementById('clicktoplaydiv');
+ if (div) {
+ div.removeEventListener('click', Module.clickToPlayListener);
+ document.body.removeChild(div);
+ }
+ if (window.parent.window.gtk.starting) {
+ window.parent.window.gtk.starting();
+ }
+ Module["callMain"](); // go go go!
+ },
+ startClickToPlay: function() {
+ var base64 = base64Encode(FS.readFile(GDragonRubyIcon, {}));
+ var div = document.createElement('div');
+ var leftPx = ((window.innerWidth - 640) / 2);
+ var leftPerc = Math.floor((leftPx / window.innerWidth) * 100);
+ div.id = 'clicktoplaydiv';
+ div.style.backgroundColor = 'rgb(40, 44, 52)';
+ div.style.left = leftPerc.toString() + "%";
+ div.style.top = '10%';
+ div.style.display = 'block';
+ div.style.position = 'absolute';
+ div.style.width = "640px"
+ div.style.height = "360px"
+
+
+
+ var img = new Image();
+ img.onload = function() { // once we know its size, scale it, keeping aspect ratio.
+ var zoomRatio = 100.0 / this.width;
+ img.style.width = (zoomRatio * this.width.toString()) + "px";
+ img.style.height = (zoomRatio * this.height.toString()) + "px";
+ img.style.display = "block";
+ img.style['margin-left'] = 'auto';
+ img.style['margin-right'] = 'auto';
+ }
+
+ img.style.display = 'none';
+ img.src = 'data:image/png;base64,' + base64;
+ div.appendChild(img);
+
+
+ var p;
+
+ p = document.createElement('h1');
+ p.textContent = GDragonRubyGameTitle + " " + GDragonRubyGameVersion + " by " + GDragonRubyDevTitle;
+ p.style.textAlign = 'center';
+ p.style.color = '#FFFFFF';
+ p.style.width = '100%';
+ p.style['font-family'] = "monospace";
+ div.appendChild(p);
+
+ p = document.createElement('p');
+ p.innerHTML = 'Click here to begin.';
+ p.style['font-family'] = "monospace";
+ p.style['font-size'] = "20px";
+ p.style.textAlign = 'center';
+ p.style.backgroundColor = 'rgb(40, 44, 52)';
+ p.style.color = '#FFFFFF';
+ p.style.width = '100%';
+ div.appendChild(p);
+
+ document.body.appendChild(div);
+ div.addEventListener('click', Module.clickToPlayListener);
+ window.gtk.play = Module.clickToPlayListener;
+ },
+ preRun: function() {
+ // set up a persistent store for save games, etc.
+ FS.mkdir('/persistent');
+ FS.mount(IDBFS, {}, '/persistent');
+ FS.syncfs(true, function(err) {
+ if (err) {
+ console.log("WARNING: Failed to populate persistent store. Save games likely lost?");
+ } else {
+ console.log("Read in from persistent store.");
+ }
+
+ loadDataFiles(GDragonRubyGameId, 'gamedata/', function() {
+ console.log("Game data is sync'd to MEMFS. Starting click-to-play()...");
+ //Module.setStatus("Ready!");
+ //setTimeout(function() { Module.setStatus(""); statusElement.style.display='none'; }, 1000);
+ Module.setStatus("");
+ statusElement.style.display='none';
+ Module.startClickToPlay();
+ });
+ });
+ },
+ postRun: [],
+ print: (function() {
+ var element = document.getElementById('output');
+ if (element) element.value = ''; // clear browser cache
+ return function(text) {
+ if (arguments.length > 1) 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) {
+ if (arguments.length > 1) 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: (function() {
+ var canvas = document.getElementById('canvas');
+
+ // As a default initial behavior, pop up an alert when webgl context is lost. To make your
+ // application robust, you may want to override this behavior before shipping!
+ // See http://www.khronos.org/registry/webgl/specs/latest/1.0/#5.15.2
+ canvas.addEventListener("webglcontextlost", function(e) { alert('WebGL context lost. You will need to reload the page.'); e.preventDefault(); }, false);
+ canvas.addEventListener("click", function() {
+ document.getElementById('toplevel').click();
+ document.getElementById('toplevel').focus();
+ document.getElementById('game-input').style.display = "inline"
+ document.getElementById('game-input').focus();
+ document.getElementById('game-input').blur();
+ document.getElementById('game-input').style.display = "none"
+ canvas.focus();
+ });
+
+
+ return 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;
+ } else {
+ progressElement.value = null;
+ progressElement.max = null;
+ progressElement.hidden = true;
+ }
+ 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.');
+ }
+};
+Module.setStatus('Downloading...');
+window.onerror = function(event) {
+ // TODO: do not warn on ok events like simulating an infinite loop or exitStatus
+ Module.setStatus('Exception thrown, see JavaScript console');
+ Module.setStatus = function(text) {
+ if (text) Module.printErr('[post-exception status] ' + text);
+ };
+};
+
+var hasWebAssembly = false;
+if (typeof WebAssembly==="object" && typeof WebAssembly.Memory==="function") {
+ hasWebAssembly = true;
+}
+//console.log("Do we have WebAssembly? " + ((hasWebAssembly) ? "YES" : "NO"));
+
+var buildtype = hasWebAssembly ? "wasm" : "asmjs";
+var module = "dragonruby-" + buildtype + ".js";
+window.gtk = {};
+window.gtk.module = Module;
+
+//console.log("Our main module is: " + module);
+
+var script = document.createElement('script');
+script.src = module;
+if (hasWebAssembly) {
+ script.async = true;
+} else {
+ script.async = false; // !!! FIXME: can this be async?
+ (function() {
+ var memoryInitializer = module + '.mem';
+ if (typeof Module['locateFile'] === 'function') {
+ memoryInitializer = Module['locateFile'](memoryInitializer);
+ } else if (Module['memoryInitializerPrefixURL']) {
+ memoryInitializer = Module['memoryInitializerPrefixURL'] + memoryInitializer;
+ }
+ var meminitXHR = Module['memoryInitializerRequest'] = new XMLHttpRequest();
+ meminitXHR.open('GET', memoryInitializer, true);
+ meminitXHR.responseType = 'arraybuffer';
+ meminitXHR.send(null);
+ })();
+}
+document.body.appendChild(script);
diff --git a/deploy_template/.dragonruby/stubs/html5/stub/game.css b/deploy_template/.dragonruby/stubs/html5/stub/game.css
new file mode 100644
index 0000000..3fb16d4
--- /dev/null
+++ b/deploy_template/.dragonruby/stubs/html5/stub/game.css
@@ -0,0 +1,8 @@
+body {
+ margin: 0;
+ padding: 0;
+ border: 0;
+}
+canvas {
+ background-color: rgb(40, 44, 52);
+}
diff --git a/deploy_template/.dragonruby/stubs/html5/stub/index.html b/deploy_template/.dragonruby/stubs/html5/stub/index.html
new file mode 100644
index 0000000..b2bcf9f
--- /dev/null
+++ b/deploy_template/.dragonruby/stubs/html5/stub/index.html
@@ -0,0 +1,93 @@
+<!doctype html>
+<html lang="en-us">
+ <head>
+ <meta charset="utf-8">
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <link rel="icon" href="favicon.png" type="image/png" />
+ <title>DragonRuby</title>
+ <style>
+ body {
+ font-family: arial;
+ margin: 0;
+ padding: none;
+ background: #000000;
+ }
+
+ .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; background-color: black; }
+
+ #emscripten_logo {
+ display: inline-block;
+ margin: 0;
+ }
+
+ @-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;
+ font-weight: bold;
+ color: rgb(120, 120, 120);
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ }
+
+ #progress {
+ height: 20px;
+ width: 30px;
+ }
+
+ #output {
+ width: 100%;
+ height: 200px;
+ margin: 0 auto;
+ margin-top: 10px;
+ border-left: 0px;
+ border-right: 0px;
+ padding-left: 0px;
+ padding-right: 0px;
+ display: none;
+ background-color: black;
+ color: white;
+ font-family: 'Lucida Console', Monaco, monospace;
+ outline: none;
+ }
+ </style>
+ <link rel="stylesheet" href="game.css" />
+ <title>DragonRuby Game Toolkit Tutorial</title>
+ </head>
+ <body id='toplevel'>
+ <div class="emscripten_border" id='borderdiv'>
+ <input id="game-input" autocomplete="off" />
+ <canvas class="game emscripten" id="canvas" oncontextmenu="event.preventDefault()"></canvas>
+ </div>
+ <br/>
+ <textarea style="display: none;" id="output" rows="8"></textarea>
+
+ <div class="emscripten" id="status"></div>
+ <div class="emscripten" id='progressdiv'>
+ <progress value="0" max="100" id="progress"></progress>
+ </div>
+
+ <script type='text/javascript' src='dragonruby-html5-loader.js'></script>
+ </body>
+</html>
diff --git a/deploy_template/CHANGELOG.txt b/deploy_template/CHANGELOG.txt
index 9bde121..cf22fc9 100644
--- a/deploy_template/CHANGELOG.txt
+++ b/deploy_template/CHANGELOG.txt
@@ -1,3 +1,261 @@
+= 1.14 =
+
+ * [Support] Better HTML5 template. Additional JS events added to
+ handle loss of keyboard input within an iframe.
+ * [Bugfix] `args.outputs.screenshots` regression fixed.
+ * [Docs] Added documentation for a few more Numeric methods.
+ * [Samples] Brand new advanced sample app: 99_sample_sprite_animation_creator.
+ The sample app uses `args.outputs.screenshots` and `render_targets` heavily along with
+ in memory queues as a means to consolidate events coming from
+ different parts of the app.
+
+
+= 1.13 =
+
+ * [API] Sprite angle now accepts fractional degrees.
+ * [Samples] Better font added to LOWREZJAM 2020 template.
+ * [API] Added `args.outputs[RENDER_TARGET_NAME]` as an alias to
+ `args.render_target(RENDER_TARGET_NAME)`. Either of the following will work:
+
+ ```ruby
+ def tick args
+ if args.state.tick_count == 1
+ args.render_target(:camera).width = 100
+ args.render_target(:camera).height = 100
+ args.render_target(:camera).solids << [0, 0, 50, 50, 255, 0, 0]
+ end
+
+ if args.state.tick_count > 0
+ args.outputs.sprites << { x: 0,
+ y: 0,
+ w: 500,
+ h: 500,
+ source_x: 0,
+ source_y: 0,
+ source_w: 50,
+ source_h: 50,
+ path: :camera }
+ end
+ end
+
+ $gtk.reset
+ ```
+
+ Is the same as:
+
+ ```ruby
+ def tick args
+ if args.state.tick_count == 1
+ args.outputs[:camera].width = 100
+ args.outputs[:camera].height = 100
+ args.outputs[:camera].solids << [0, 0, 50, 50, 255, 0, 0]
+ end
+
+ if args.state.tick_count > 0
+ args.outputs.sprites << { x: 0,
+ y: 0,
+ w: 500,
+ h: 500,
+ source_x: 0,
+ source_y: 0,
+ source_w: 50,
+ source_h: 50,
+ path: :camera }
+ end
+ end
+
+ $gtk.reset
+ ```
+
+= 1.12 =
+
+ * [Samples] LOWREZ Jam sample app reworked in preparation for LOWREZ
+ Jam 2020 (starts on August 1st so hurry and join).
+ * [Docs] Docs added for GTK::Mouse, you can access them via the
+ Console by typing `GTK::Mouse.docs` or `$gtk.args.inputs.mouse.docs`.
+ * [MacOS] Updated minimum OS support to include MacOS 10.9+.
+
+= 1.11 =
+
+ * [Bugfix] Fixed error in docs_search "TERM".
+
+= 1.10 =
+
+ * [Support] Documentation infrastructure added (take a look at docs/docs.html). Bring up the DragonRuby Console and:
+
+ To search docs you can type `docs_search "SEARCH TERM"`
+
+ If you want to get fancy you can provide a `lambda` to filter documentation:
+
+ docs_search { |entry| (entry.include? "Array") && (!entry.include? "Enumerable") }
+
+ * [Bugfix] Fixed sprite rendering issues with source_(x|y|w|h) properties on sprites.
+ * [Support] Removed double buffering of game if framerate drops below 60 fps.
+ * [Support] Console now supports mouse wheel scrolling.
+ * [Support] One time notifications have less noise/easier to read.
+ * [Bugfix] Rogue ~app/main.rb~ directory will no longer be created if you run a sample app.
+
+= 1.9 =
+
+ * [Bugfix] HTTP on windows should now work, for real this time.
+ * [Bugfix] Non-720p render targets now use correct coordinate system.
+
+= 1.8 =
+
+ * [Experimental] Added the ability to control the logical game size. You can use cli
+ arguments to set it. Example ultra-wide support would be:
+ `./dragonruby --window_width 3840 --window_height 1080`
+ * [Bugfix] HTTP on windows should now work.
+ * [Bugfix] `even?` and `odd?` return the correct result for Fixnum.
+ * [Bugfix] args.intputs.mouse_wheel now reports the delta change in x and y correctly.
+ * [Bugfix] Improved analog joystick accuracy when converting to percentages.
+ * [Support] Incorporated pull request from https://github.com/kfischer-okarin that adds
+ autocompletion to the Console. This is the PR:
+ - https://github.com/DragonRuby/dragonruby-game-toolkit-contrib/commit/da0fdcfbd2bd9739fe056eb646920df79a32954c
+ - https://github.com/DragonRuby/dragonruby-game-toolkit-contrib/commit/99305ca79118fa0704c8681f4019738b8c7a500d
+
+= 1.7 =
+
+ * [BREAKING] args.inputs.mouse.wheel.point is gone. Use args.inputs.mouse.x
+ and .y if you need cursor position.
+ * [BREAKING] args.inputs.mouse.wheel.x and .y now represent the amount the
+ mousewheel/trackpad has moved since the last tick and not the mouse cursor
+ position. Use args.inputs.mouse.x and .y if you need cursor position.
+
+= 1.6 =
+
+ * [API] Sprite now supports source_(x|y|w|h). These properties are consistent with the origin
+ being in the bottom left. The existing properties tile_(x|y|w|h) assumes that origin 0, 0 is in the top left.
+ The code below will render the same sprite (in their respective coordinate systems):
+
+ # using tile_(x|y|w|h) properties
+ args.outputs.sprites << { x: 0,
+ y: 0,
+ w: 1280,
+ h: 100,
+ path: :block,
+ tile_x: 0,
+ tile_y: 720 - 100,
+ tile_w: 1280,
+ tile_h: 100 }
+
+ is equivalent to:
+
+ # using source_(x|y|w|h) properties
+ args.outputs.sprites << { x: 0,
+ y: 0,
+ w: 1280,
+ h: 100,
+ path: :block,
+ source_x: 0,
+ source_y: 0,
+ source_w: 1280,
+ source_h: 100 }
+
+ Note: if you provide both tile_(x|y|w|h) and source_(x|y|w|h). The values of tile_ will "win" so as not to
+ break existing code out there.
+ * [Bugfix] Updated require to remove duplicate requires of the same file (or files that have recently been required).
+ * [Bugfix] Strict entities of different types/names serialize and deserialize correctly.
+ * [Samples] Updated render targets sample app to show two render targets with transparencies.
+ * [API] No really, render targets now have a transparent background and respect opacity.
+
+= 1.5 =
+
+ * [API] Added $gtk.show_cursor and $gtk.hide_cursor to show and hide the mouse cursor. The
+ function only needs to be called once. EG: args.gtk.hide_cursor if args.state.tick_count == 0.
+ * [Samples] Jam Craft 2020 sample app updated to have more comments and demonstrate a custom
+ mouse cursor.
+
+= 1.4 =
+
+ * [Bugfix] Adding $gtk.reset at the bottom of main.rb will no longer cause an infinite loop.
+ * [Samples] Sample app added for Jam Craft 2020.
+
+= 1.3 =
+
+ * [Bugfix] Adding $gtk.reset at the bottom of main.rb will no longer cause an infinite loop.
+ * [Samples] Better instructions added to various sample apps.
+
+= 1.2 =
+
+ * [Bugfix] Top-level require statements within main.rb will load before
+ invoking the rest of the code in main.rb.
+ * [Samples] Better keyboard input sample app.
+ * [Samples] New sample app that shows how to use Numeric#ease_spline.
+ * [Bugfix] Fixed "FFI::Draw cannot be serialized" error message.
+
+= 1.1 =
+
+ * [Bugfix] Fixed exception associated with providing serialization related help.
+ * [Bugfix] Fixed comments on how to run tests from CLI.
+ * [Support] More helpful global variables added. Here's a list:
+ - $gtk
+ - $console
+ - $args
+ - $state
+ - $tests
+ - $record
+ - $replay
+ * [API] inputs.keyboard.key_(down|held|up).any? and inputs.keyboard.key_(down|held|up).all?
+ added.
+ * [Support] Recording gameplay and replaying streamlined a bit more. GIVE THE
+ REPLAY FEATURE A SHOT! IT'S AWESOME!! Bring up the console and run: $record.start SEED_NUMBER.
+ * [Support] Bringing up the console will stop a replay if one is running.
+
+= 1.0 =
+
+ * [News] DragonRuby Game Toolkit turns 1.0. Happy birthday!
+ * [Bugfix] args.state.new_entity_strict serializes and deserializes correctly now.
+ * [BREAKING] Entity#hash has been renamed to Entity#as_hash so as not to redefine
+ Object#hash. This is a "private" method so you probably don't have to worry about
+ anything breaking on your end.
+ * [BREAKING] gtk.save_state and gtk.load_state have been replaced with gtk.serialize_state
+ and gtk.deserialize_state (helpful error messages have been added).
+ * [Support] Console can now render sprites (this is still in its early stages). Try
+ $gtk.console.addsprite(w: 50, h: 50, path: "some_path.png").
+ * [API] Render targets now have a transparent background and respect opacity.
+ * [API] Render targets can be cached/programatically created once and reused.
+ * [Samples] A new render target sample app has been created to show how to cache them.
+ * [Samples] Easing sample app reworked/simplified.
+ * [Support] GTK will keep a backup of your source file changes under the tmp directory.
+ One day this feature will save your ass.
+
+= 20200301 =
+
+ * [Samples] Added sample app that shows how you can draw a cubic bezier curves.
+ * [Support] Keyup event prints key and raw_key to the console.
+ * [Support] Circumflex now opens the console.
+
+= 20200227 =
+
+ * [Bugfix] Game will now auto restart in the event of a syntax error.
+ * [Samples] Sample app added to show how to use a sprite sheet for sprite animations:
+ 09_sprite_animation_using_tile_sheet.
+ * [Samples] Sample app added to show how to use a tile sheet for a roguelike:
+ 20_roguelike_starting_point_two.
+ * [Samples] Example code added to show how sort an array with a custom sort block:
+ 00_intermediate_ruby_primer/07_powerful_arrays.txt
+ * [OSS] The following files have been open sourced at https://github.com/DragonRuby/dragonruby-game-toolkit-contrib:
+ - modified: dragon/args.rb
+ - new file: dragon/assert.rb
+ - new file: dragon/attr_gtk.rb
+ - modified: dragon/console.rb
+ - new file: dragon/docs.rb
+ - new file: dragon/geometry.rb
+ - new file: dragon/help.rb
+ - modified: dragon/index.rb
+ - modified: dragon/inputs.rb
+ - new file: dragon/log.rb
+ - new file: dragon/numeric.rb
+ - new file: dragon/string.rb
+ - new file: dragon/tests.rb
+ - new file: dragon/trace.rb
+ * [Support] Added isometric placeholder sprites.
+ * [Support] Added $gtk.reset_sprite 'path' to refresh a sprite from
+ the file system (while the game is running). Future releases will
+ automatically auto load sprites but you can use this to reload them
+ on demand.
+
= 20200225 =
* [Bugfix] Fixed macOS compatibility back to Mac OS X 10.9 or so.
@@ -22,9 +280,8 @@
= 20200217 =
* [Bugfix] `dragonruby-publish` would only build html5. It now builds
- all of the platforms again. Ryan "The Juggernaut" Gordon has given Amir
- a warning and has told him to be more careful releasing. Amir cackled
- in defiance.
+ all of the platforms again. Ryan has given Amir a warning and has told him
+ to be more careful releasing. Amir cackled in defiance.
= 20200213 =
@@ -87,7 +344,7 @@
http.
* [Support] [Samples] Added a sample app that shows how create
collision detection associated with constraint points against
- a ramp. This sample app also demostrates the use of `gtk.slowmo!`
+ a ramp. This sample app also demonstrates the use of `gtk.slowmo!`
which you can use the slow down the tick execution of your game
to see things frame by frame (still experimental).
* [Support] Added sprites to default template folder. The sprites
@@ -165,7 +422,7 @@
* [Samples] Added sample app that shows how trace can be used within a class.
* [Support] Added $gtk.log_level. Valid values are :on,
- :off. When the value is set to :on, GTK log mesages will show up
+ :off. When the value is set to :on, GTK log messages will show up
in the DragonRuby Console *AND* be written to logs/log.txt. When the
value is set to :off, GTK log messages will *NOT* show up in the
console, but will *STILL* be written to logs/log.txt
@@ -306,7 +563,7 @@
* [Samples] New sample app called 02_collisions_02_moving_objects has been added.
* [Support] Previous console messages are subdued if unhandled exception is resolved.
This removes visual confusion if another exception is thrown (easier to determine what the current exception is).
- * [Support] Added api documentation about thruthy_keys for keyboards and controllers.
+ * [Support] Added api documentation about truthy_keys for keyboards and controllers.
* [API] [Experimental] Hashes now quack like render primitives. For example some_hash[:x] is the same as
some_hash.x and can be interchangeable with some_array.x (this is a work in progress
so there may be some geometric/collision apis that aren't covered).
@@ -316,7 +573,7 @@
loops, and arrays. Special thanks to @raulrita (https://www.twitch.tv/raulrita)
for live streaming and bringing light to these enhancements.
* [Support] `puts` statements that begin with "====" are rendered as teal in the Console. This
- provides a visual seperation that will help with print line debugging.
+ provides a visual separation that will help with print line debugging.
* [OSS] The DragonRuby Game Toolkit Console has been open sourced under an MIT license. You can find it
here: https://github.com/DragonRuby/dragonruby-game-toolkit-contrib
@@ -325,9 +582,9 @@
* [Support] The mygame directory now contains a documentation folder that provides high level
APIs for the engine (it's a work in progress, but a good starting point).
* [Samples] A sample app called "hash primitives" has been added that shows how you can use a Hash
- to render a primitive. This will make specifying sprite's advanced properites much easier.
+ to render a primitive. This will make specifying sprite's advanced properties much easier.
* [Samples] The sprite limits sample app shows how you can ducktype a class and render it as a sprite.
- Doing this is a tiny bit more work, but there is a huge perfomance benefit.
+ Doing this is a tiny bit more work, but there is a huge performance benefit.
* [Bugfix] Internal limits total textures/render targets/fonts is removed.
* [BREAKING] args.dragon has been deprecated, you must now use the new property args.gtk.
* [BREAKING] args.game has been deprecated, you must now use the new property args.state.
@@ -390,7 +647,7 @@
= release-20190731 =
- * [Bugfix] Fixed bug in dragon ruby console returning evalued value.
+ * [Bugfix] Fixed bug in DragonRuby console returning evaled value.
* [Support] Updated collisions sample app with comments.
* [Support] Added comments for sprite animation sample app.
* [Support] dragonruby-publish will look for your game in the
@@ -472,9 +729,9 @@
* [API] A new entity type has been introduced and is accessible via `args.state.new_entity_strict`
the usage of StrictEntity over OpenEntity (`args.state.new_entity`) yield significantly faster
property access. The downside is that `args.state.new_entity_strict` requires
- you to define all properties upfront within the implicit block. You will recieve
+ you to define all properties upfront within the implicit block. You will receive
an exception if you attempt to access a property that hasn't be
- pre-defined. For usage info and preformance differences, take a look at the Sprite Limit
+ pre-defined. For usage info and performance differences, take a look at the Sprite Limit
sample app.
* [Support] Exception messages have been significantly improved. Hashes and Type .to_s
information is well formatted. "stack too deep" exceptions resolved.
@@ -484,7 +741,7 @@
* [Support] Framerate warnings wait 10 seconds before calculating the moving average. If your
framerates begin to drop, consider using `args.state.new_entity_static` for game structures that have been
fleshed out.
- * [Performance] Rendering of primitives is can support over twice as many sprites at 60 fps (see Sprit Limits
+ * [Performance] Rendering of primitives is can support over twice as many sprites at 60 fps (see Sprite Limits
sample app for demonstration).
* [Support] Headless testing has been added. Take a look at the Basic Gorillas sample app to see
how headless testing can help you dial into frame-by-frame problems within your game.
@@ -507,7 +764,7 @@
args.outputs.sprites << create_sprite(x: 0, y: 0, w: 100, h: 100, vflip: true)
```
- We're still chewing on the API above before it get's integrated
+ We're still chewing on the API above before it gets integrated
into GTK proper.
* [API] "Superscript Two" can be used to bring up the DragonRuby
Console. People with international keyboards (which don't have a ~
@@ -597,11 +854,11 @@
course of Ruby the programming language.
* [Sample] The composition of primitives in DragonRuby GTK are
incredibly flexible. A sample app called "Fluid Primitives" has
- been beed added to show this flexibility.
+ been added to show this flexibility.
* [MacOS] [Linux] [Windows] If your screen resolution is below 720p,
the game will start at a smaller (but still aspect-correct) resolution.
* [Sample] Sample added showing `intersects_rect?` collision
- tollerances as a topdown level (similar to what's
+ tolerances as a topdown level (similar to what's
in Zelda for the NES).
= release-20190516 =
@@ -675,7 +932,7 @@
`notepad.exe`.
* [Packaging] Default icon added to `mygame`.
* [Samples] Reworked `doomwipe` (render targets tech demo) sample app so that
- it's less eratic before the effect is revealed.
+ it's less erratic before the effect is revealed.
* [Windows] Fixed bug where rendering would stop on Windows if the screen was
resized.
* [Size] Deleted files that don't need to be packaged with DragonRuby GTK.
diff --git a/deploy_template/mygame/app/main.rb b/deploy_template/mygame/app/main.rb
index a7d9ad6..5683cc2 100644
--- a/deploy_template/mygame/app/main.rb
+++ b/deploy_template/mygame/app/main.rb
@@ -1,6 +1,5 @@
def tick args
args.outputs.labels << [ 580, 500, 'Hello World!' ]
- args.outputs.labels << [ 475, 150, '(Consider reading README.txt now.)' ]
+ args.outputs.labels << [ 640, 460, 'Go to docs/docs.html and read it!', 5, 1 ]
args.outputs.sprites << [ 576, 310, 128, 101, 'dragonruby.png' ]
end
-
diff --git a/deploy_template/mygame/app/tests.rb b/deploy_template/mygame/app/tests.rb
index a60c8be..db71ff6 100644
--- a/deploy_template/mygame/app/tests.rb
+++ b/deploy_template/mygame/app/tests.rb
@@ -4,7 +4,7 @@
# Here is an example test and game
-# To run the test: ./dragonruby mygame --eval tests.rb --no-tick
+# To run the test: ./dragonruby mygame --eval app/tests.rb --no-tick
class MySuperHappyFunGame
attr_gtk
diff --git a/deploy_template/mygame/sprites/border-black.png b/deploy_template/mygame/sprites/border-black.png
new file mode 100644
index 0000000..c9d0bad
--- /dev/null
+++ b/deploy_template/mygame/sprites/border-black.png
Binary files differ
diff --git a/deploy_template/mygame/sprites/dragon-0.png b/deploy_template/mygame/sprites/dragon-0.png
new file mode 100644
index 0000000..fb179af
--- /dev/null
+++ b/deploy_template/mygame/sprites/dragon-0.png
Binary files differ
diff --git a/deploy_template/mygame/sprites/dragon-1.png b/deploy_template/mygame/sprites/dragon-1.png
new file mode 100644
index 0000000..8cfe531
--- /dev/null
+++ b/deploy_template/mygame/sprites/dragon-1.png
Binary files differ
diff --git a/deploy_template/mygame/sprites/dragon-2.png b/deploy_template/mygame/sprites/dragon-2.png
new file mode 100644
index 0000000..cb462e1
--- /dev/null
+++ b/deploy_template/mygame/sprites/dragon-2.png
Binary files differ
diff --git a/deploy_template/mygame/sprites/dragon-3.png b/deploy_template/mygame/sprites/dragon-3.png
new file mode 100644
index 0000000..04c4977
--- /dev/null
+++ b/deploy_template/mygame/sprites/dragon-3.png
Binary files differ
diff --git a/deploy_template/mygame/sprites/dragon-4.png b/deploy_template/mygame/sprites/dragon-4.png
new file mode 100644
index 0000000..b29fa3d
--- /dev/null
+++ b/deploy_template/mygame/sprites/dragon-4.png
Binary files differ
diff --git a/deploy_template/mygame/sprites/dragon-5.png b/deploy_template/mygame/sprites/dragon-5.png
new file mode 100644
index 0000000..99f4e74
--- /dev/null
+++ b/deploy_template/mygame/sprites/dragon-5.png
Binary files differ
diff --git a/deploy_template/mygame/sprites/explosion-0.png b/deploy_template/mygame/sprites/explosion-0.png
new file mode 100644
index 0000000..f48636f
--- /dev/null
+++ b/deploy_template/mygame/sprites/explosion-0.png
Binary files differ
diff --git a/deploy_template/mygame/sprites/explosion-1.png b/deploy_template/mygame/sprites/explosion-1.png
new file mode 100644
index 0000000..b4018d9
--- /dev/null
+++ b/deploy_template/mygame/sprites/explosion-1.png
Binary files differ
diff --git a/deploy_template/mygame/sprites/explosion-2.png b/deploy_template/mygame/sprites/explosion-2.png
new file mode 100644
index 0000000..3abaedd
--- /dev/null
+++ b/deploy_template/mygame/sprites/explosion-2.png
Binary files differ
diff --git a/deploy_template/mygame/sprites/explosion-3.png b/deploy_template/mygame/sprites/explosion-3.png
new file mode 100644
index 0000000..fe94a5a
--- /dev/null
+++ b/deploy_template/mygame/sprites/explosion-3.png
Binary files differ
diff --git a/deploy_template/mygame/sprites/explosion-4.png b/deploy_template/mygame/sprites/explosion-4.png
new file mode 100644
index 0000000..ed04237
--- /dev/null
+++ b/deploy_template/mygame/sprites/explosion-4.png
Binary files differ
diff --git a/deploy_template/mygame/sprites/explosion-5.png b/deploy_template/mygame/sprites/explosion-5.png
new file mode 100644
index 0000000..2cd8f06
--- /dev/null
+++ b/deploy_template/mygame/sprites/explosion-5.png
Binary files differ
diff --git a/deploy_template/mygame/sprites/explosion-6.png b/deploy_template/mygame/sprites/explosion-6.png
new file mode 100644
index 0000000..e55909c
--- /dev/null
+++ b/deploy_template/mygame/sprites/explosion-6.png
Binary files differ
diff --git a/deploy_template/mygame/sprites/explosion-sheet.png b/deploy_template/mygame/sprites/explosion-sheet.png
new file mode 100644
index 0000000..8559a5c
--- /dev/null
+++ b/deploy_template/mygame/sprites/explosion-sheet.png
Binary files differ
diff --git a/deploy_template/mygame/sprites/star.png b/deploy_template/mygame/sprites/star.png
new file mode 100644
index 0000000..e0ee0f9
--- /dev/null
+++ b/deploy_template/mygame/sprites/star.png
Binary files differ