1
1
Fork 0
mirror of https://github.com/boxgaming/qbjs.git synced 2024-09-28 06:27:47 +00:00

v0.3.0-beta updates

This commit is contained in:
boxgaming 2022-03-30 17:37:36 -05:00
parent 03466d5c32
commit 137145cc85
11 changed files with 1402 additions and 1548 deletions

View file

@ -35,13 +35,18 @@ CodeMirror.defineMode("qbjs", function(conf, parserConf) {
// TODO: adjust for QB
var atomWords = ['true', 'false', 'nothing', 'empty', 'null'];
var builtinFuncsWords = ['_alpha', '_alpha32', '_atan2', '_autodisplay', '_blue', '_blue32', '_copyimage', '_delay', '_dest', '_dest', '_display', '_fontwidth',
'_freeimage', '_green', '_green32', '_height', '_instrrev', '_limit', '_keyclear', '_keydown', '_keyhit', '_loadimage',
'_mousebutton', '_mouseinput', '_mousex', '_mousey', '_newimage', '_pi', '_printstring', '_printwidth', '_putimage',
'_red', '_red32', '_rgb', '_rgba', '_rgb32', '_rgba32', '_round', '_screenexists', '_title', '_trim', '_width', 'abs',
'asc', 'atn', 'chr', 'circle', 'cls', 'color', 'command', 'cos', 'exp', 'fix', 'input', 'inkey', 'instr', 'int',
'lbound', 'left', 'lcase', 'len', 'line', 'locate', 'log', 'ltrim', 'mid', 'print', 'pset', 'right', 'rtrim', 'rnd',
'screen', 'sgn', 'sin', 'sleep', 'sqr', 'str', 'swap', 'tan', 'timer', 'ubound', 'ucase', 'val'];
var builtinFuncsWords = ['_alpha', '_alpha32', '_atan2', '_autodisplay', '_blue', '_blue32', '_continue', '_copyimage', '_delay', '_dest', '_dest',
'_display', '_fontwidth', '_freeimage', '_green', '_green32', '_height', '_instrrev', '_limit', '_keyclear', '_keydown',
'_keyhit', '_loadimage', '_mousebutton', '_mouseinput', '_mousex', '_mousey', '_newimage', '_pi', '_printstring', '_printwidth',
'_putimage', '_red', '_red32', '_resize', '_resizewidth', '_resizeheight', '_rgb', '_rgba', '_rgb32', '_rgba32', '_round',
'_screenexists', '_sndclose', '_sndopen', '_sndplay', '_sndloop', '_sndpause', '_sndstop', '_sndvol',
'_title', '_trim', '_width', 'abs', 'asc', 'atn', 'chr', 'circle', 'cls', 'color', 'command', 'cos', 'cvi', 'cvl', 'exp',
'fix', 'input', 'inkey', 'instr', 'int', 'lbound', 'left', 'lcase', 'len', 'line', 'locate', 'log', 'ltrim', 'mid', 'mki', 'mkl',
'print', 'pset', 'right', 'rtrim', 'rnd', 'screen', 'shared', 'sgn', 'sin', 'sleep', 'space', 'sqr', 'str', 'swap', 'tan',
'timer', 'ubound', 'ucase', 'val',
// QBJS-specific
'alert', 'confirm', 'domadd', 'domcontainer', 'domcreate', 'domevent','domget', 'domgetimage', 'domremove', 'prompt',
'storageclear', 'storageget', 'storagekey', 'storagelength', 'storageset', 'storageremove'];
var builtinConsts = ['gx_true', 'gx_false', 'gxevent_init', 'gxevent_update', 'gxevent_drawbg', 'gxevent_drawmap', 'gxevent_drawscreen',
'gxevent_mouseinput', 'gxevent_paintbefore', 'gxevent_paintafter', 'gxevent_collision_tile', 'gxevent_collision_entity',
@ -64,7 +69,8 @@ CodeMirror.defineMode("qbjs", function(conf, parserConf) {
'gxscene_follow_entity_center_x', 'gxscene_follow_entity_center_y', 'gxscene_follow_entity_center_x_pos',
'gxscene_follow_entity_center_x_neg', 'gxscene_constrain_none', 'gxscene_constrain_to_map', 'gxfont_default',
'gxfont_default_black', 'gxdevice_keyboard', 'gxdevice_mouse', 'gxdevice_controller', 'gxdevice_button',
'gxdevice_axis', 'gxdevice_wheel', 'gxtype_entity', 'gxtype_font', 'gx_cr', 'gx_lf', 'gx_crlf'];
'gxdevice_axis', 'gxdevice_wheel', 'gxtype_entity', 'gxtype_font', 'gx_cr', 'gx_lf', 'gx_crlf',
'local', 'session'];
var builtinObjsWords = ['\\$if', '\\$end if'];

View file

@ -1,105 +0,0 @@
'use strict';
/**
* Polyfill of dialog
* for Firefox
*
* author Nemo
*
* v1.1
* Supports:
* show
* hide
* showModal
* cancel(ESC)
*/
{
const UA = window.navigator.userAgent;
const browser = {
isFirefox: UA.includes('Firefox'),
};
const dlg = document.createElement('dialog');
let mask = undefined;
const initMask = () => {
if (mask != undefined)
return;
mask = document.createElement('div');
mask.style.display = 'none';
mask.style.position = 'absolute';
mask.style.zIndex = 999998;
mask.style.top = 0;
mask.style.left = 0;
mask.style.right = 0;
mask.style.bottom = 0;
mask.style.backgroundColor = 'rgba(0, 0, 0, 0.1)';
document.body.appendChild(mask);
};
// show support
if (!dlg.__proto__.show) {
dlg.__proto__.open = false;
dlg.__proto__.show = function() {
this.open = true;
this.style.backgroundColor = 'white';
this.style.position = 'absolute';
this.style.zIndex = 999999;
this.style.display = 'table';
this.style.top = '50%';
this.style.transform = 'translate(0, -50%)';
return this;
};
}
// showModal support
if (!dlg.__proto__.showModal) {
initMask();
dlg.__proto__.showModal = function() {
mask.style.display = 'block';
this.show();
return this;
};
}
// hide support
if (!dlg.__proto__.close) {
initMask();
dlg.__proto__.close = function() {
this.open = false;
mask.style.display = 'none';
this.style.display = 'none';
return this;
}
}
// cancel(ESC) support
if (dlg.oncancel === void 0) {
const dialogClass = 'dlg-dialog';
document.addEventListener('keypress', (e) => {
if (e.code !== 'Escape')
return;
let dlgs = document.querySelectorAll(`.${dialogClass}`);
for (let i = 0; i < dlgs.length; i++) {
let d = dlgs[i];
if (d.style.display === 'none')
continue;
if (d.wrapper.cancelable) {
d.close();
}
}
});
}
}

View file

@ -1,18 +0,0 @@
.dlg-dialog {
border: none;
box-shadow: 10px 10px 20px gray;
}
.dlg-header {
background-color: #555;
color: white;
}
.dlg-caption {
height: 1.17em;
text-shadow: 1px 1px 1px black;
}
.dlg-close-button::before,
.dlg-close-button::after {
background-color: white;
}

View file

@ -1,81 +0,0 @@
.dlg-dialog {
position: fixed;
top: 0;
bottom: 0;
box-sizing: border-box;
min-width: 300px;
max-width: 100%;
padding: 0;
overflow: hidden;
background-color: #ccc;
}
.dlg-dialog textarea {
background-color: #ccc;
font-family: dosvga;
font-size: 1em;
padding: .25em;
border: 2px solid #333;
}
.dlg-header {
padding: .5em;
background-color: #999;
border-bottom: 1px solid #333;
}
.dlg-caption {
font-size: 1em;
margin: 0;
padding-right: 2em;
font-weight: normal;
}
.dlg-close-button {
position: absolute;
right: .5em;
top: .5em;
width: 1.17em;
height: 1.17em;
cursor: pointer;
}
.dlg-close-button::before {
transform: rotate(45deg);
}
.dlg-close-button::after{
transform: rotate(-45deg);
}
.dlg-close-button::before,
.dlg-close-button::after {
content: '';
position: absolute;
height: 1px;
width: 100%;
top: 50%;
left:0;
background-color: black;
}
.dlg-body {
padding: .5em;
}
.dlg-content {
padding: .5em;
overflow: auto;
}
.dlg-button-area {
padding: 0 .5em;
text-align: right;
}
.dlg-button-area button {
padding: .3em .4em;
margin-left: 1em;
width: 5em;
text-align: center;
}

View file

@ -1,435 +0,0 @@
/**
* class Dialog {
*
* author: nemo
* date: 2017-06-20
* v: 1.1
* }
*/
{
'use strict';
class Dialog {
constructor(opt) {
Object.assign(this.option = {
caption: '',
message: '',
content: undefined,
buttons: Dialog.buttons.NONE,
resize: 'none',
cancelable: true,
showHeader: true,
showClose: true,
showFooter: false,
// handler
abortHandler: undefined,
cancelHandler: () => { this.close(); },
ignoreHandler: undefined,
noHandler: undefined,
okHandler: () => { this.close(); },
retryHandler: undefined,
yesHandler: undefined,
// events
beforeClosing: () => { return true; }, // set to false to prevent close
closed: undefined,
}, opt);
this.init();
}
/**
* START init
*/
init() {
return this
.initLayout()
.initAttributes()
.initContent()
.initEvents();
}
initLayout() {
this.dialog = create('dialog', 'dialog');
this.dialog.style.resize = this.option.resize,
appendTo(this.dialog, document.body);
this.show();
this.container = this.dialog;
this.header = create('header', 'header');
this.caption = create('h3', 'caption');
this.closeButton = create('em', 'close-button');
this.body = create('div', 'body');
this.content = create('section', 'content');
this.buttonArea = create('div', 'button-area');
this.footer = create('footer', 'footer');
// assembly dom
this.header.appendChild(this.caption);
if (this.option.showClose)
this.header.appendChild(this.closeButton);
if (this.option.showHeader)
this.dialog.appendChild(this.header);
this.body.appendChild(this.content);
this.body.appendChild(this.buttonArea);
this.assemblyButtons();
this.dialog.appendChild(this.body);
if (this.option.showFooter)
this.dialog.appendChild(this.footer);
return this;
}
initAttributes() {
this.dialog.wrapper = this;
this.cancelable = this.option.cancelable;
return this;
}
assemblyButtons() {
switch (this.option.buttons) {
case Dialog.buttons.ABORT_RETRY_IGNORE:
new DialogButton(this, Dialog.button.ABORT).assembly();
new DialogButton(this, Dialog.button.RETRY).assembly().focus();
new DialogButton(this, Dialog.button.IGNORE).assembly();
break;
case Dialog.buttons.OK:
new DialogButton(this, Dialog.button.OK).assembly().focus();
break;
case Dialog.buttons.OK_CANCEL:
new DialogButton(this, Dialog.button.OK).assembly();
new DialogButton(this, Dialog.button.CANCEL).assembly().focus();
break;
case Dialog.buttons.RETRY_CANCEL:
new DialogButton(this, Dialog.button.RETRY).assembly().focus();
new DialogButton(this, Dialog.button.CANCEL).assembly();
break;
case Dialog.buttons.YES_NO:
new DialogButton(this, Dialog.button.YES).assembly();
new DialogButton(this, Dialog.button.NO).assembly().focus();
break;
case Dialog.buttons.YES_NO_CANCEL:
new DialogButton(this, Dialog.button.YES).assembly();
new DialogButton(this, Dialog.button.NO).assembly();
new DialogButton(this, Dialog.button.CANCEL).assembly().focus();
break;
default:
// no button
break;
}
return this;
}
appendButton(btn) {
this.buttonArea.appendChild(btn.button);
return this;
}
removeButton(btn) {
this.buttonArea.removeChild(btn.button);
return this;
}
initContent() {
this.caption.innerText = this.option.caption;
if (this.option.content == undefined) {
this.content.innerText = this.option.message;
} else {
this.content.innerHTML = this.option.content;
}
return this;
}
initEvents() {
this.closeButton.addEventListener('click', () => {
this.close();
});
// prevent esc
this.dialog.addEventListener('cancel', (e) => {
!this.cancelable && e.preventDefault();
});
return this;
}
/**
* END init
*/
//:~
trigger(type) {
switch (type) {
case Dialog.button.ABORT:
callHandler(this.option.abortHandler, this);
break;
case Dialog.button.CANCEL:
callHandler(this.option.cancelHandler, this);
break;
case Dialog.button.IGNORE:
callHandler(this.option.ignoreHandler, this);
break;
case Dialog.button.NO:
callHandler(this.option.noHandler, this);
break;
case Dialog.button.OK:
callHandler(this.option.okHandler, this);
break;
case Dialog.button.RETRY:
callHandler(this.option.retryHandler, this);
break;
case Dialog.button.YES:
callHandler(this.option.yesHandler, this);
break;
default:
console.log(`Unknown type:${type}`);
break;
}
return this;
}
beforeClosing(func) {
this.option.beforeClosing = func;
return this;
}
closed(func) {
this.dialog.addEventListener('close', func);
return this;
}
get cancelable() {
return this.option.cancelable;
}
set cancelable(value) {
this.option.cancelable = !!value;
}
show() {
if (this.dialog.open)
return this;
try {
this.dialog.showModal();
} catch (e) {
appendTo(this.dialog, document.body);
this.dialog.showModal();
}
return this;
}
hide(dispose = true) {
if (!this.dialog.open)
return this;
if (typeof this.option.beforeClosing != 'function' ||
!!this.option.beforeClosing()) {
this.dialog.close();
try {
dispose && document.body.removeChild(this.dialog);
} finally { }
}
return this;
}
close(dispose = true) {
return this.hide(dispose);
}
addClass(className) {
addClass(this.dialog, className);
}
//:~
/**
* START static helper
*/
static alert(message, caption = '') {
return new Dialog({
caption: `${caption}`,
message: `${message}`,
buttons: Dialog.buttons.OK,
});
}
static confirm(message, caption = '', ok, cancel) {
return new Dialog({
caption: `${caption}`,
message: `${message}`,
buttons: Dialog.buttons.OK_CANCEL,
okHandler: ok,
cancelHandler: cancel,
});
}
static template(dom, caption = '') {
return new Dialog({
caption: `${caption}`,
content: dom.innerHTML,
});
}
static templet(dom, caption) {
return template(dom, caption);
}
static iframe(src, caption = '', width = 'auto', height = 'auto') {
let dlg = new Dialog({
caption: `${caption}`,
content: `<iframe style="border: none;" src="${src}"></iframe>`,
});
let iframe = dlg.content.childNodes[0];
iframe.style.width = width;
iframe.style.height = height;
}
/**
* END static helper
*/
}
class DialogButton {
constructor(dialog, type) {
this.dialog = dialog;
this.type = type;
this.button = create('button', `btn-${type}`);
this.button.type = 'button';
this.button.innerText = Dialog.buttonText[type];
this.click(() => {
this.dialog.trigger(this.type);
});
}
assembly() {
this.dialog.appendButton(this);
return this;
}
click(func) {
this.button.addEventListener('click', func);
return this;
}
focus() {
window.setTimeout(() => {
this.button.focus();
}, 1);
return this;
}
}
Object.assign(Dialog, {
buttons: {
ABORT_RETRY_IGNORE: 1,
OK: 2,
OK_CANCEL: 3,
RETRY_CANCEL: 4,
YES_NO: 5,
YES_NO_CANCEL: 6,
},
button: {
NONE: 0,
ABORT: 1,
CANCEL: 2,
IGNORE: 3,
NO: 4,
OK: 5,
RETRY: 6,
YES: 7,
},
buttonText: [
undefined,
'Abort',
'Cancel',
'Ignore',
'NO',
'OK',
'Retry',
'Yes',
],
});
let callHandler = (func, dlg) => {
return typeof func == 'function' ?
func(dlg) : undefined;
}
let cls = (cls) => {
return `dlg-${cls}`;
}
let addClass = (dom, className) => {
let c = dom.className;
let add = cls(className);
if (c == '') {
return add;
} else {
return c + ' ' + add;
}
}
let prependTo = (sub, base) => {
if (base.hasChildNodes()) {
base.insertBefore(sub, base.firstChild);
} else {
base.appendChild(sub);
}
}
let appendTo = (sub, base) => {
base.appendChild(sub);
}
let show = (dom, display = 'block') => {
visible(dom, true, display);
}
let hide = (dom) => {
visible(dom, true);
}
let visible = (dom, v, display) => {
if (dom == undefined || dom.style == undefined)
return;
else
dom.style.display = v ? display : 'none';
}
let create = (name, className) => {
let e = document.createElement(name);
if (typeof className == 'string')
e.className = cls(className);
return e;
}
// export { Dialog } // ES6
window['Dialog'] = Dialog;
}

View file

@ -572,6 +572,11 @@ var GX = new function() {
// Sound Methods
// ----------------------------------------------------------------------------
function _soundClose (sid) {
_sounds[sid-1].pause();
_sounds[sid-1] = undefined;
}
function _soundLoad (filename) {
var a = new Audio(filename);
_sounds.push(a);
@ -613,7 +618,6 @@ var GX = new function() {
return _sound_muted;
}
// Entity Functions
// -----------------------------------------------------------------------------
function _entityCreate (imageFilename, ewidth, height, seqFrames, uid) {
@ -2299,6 +2303,7 @@ var GX = new function() {
this.backgroundHeight = _backgroundHeight;
this.backgroundClear = _backgroundClear;
this.soundClose = _soundClose;
this.soundLoad = _soundLoad;
this.soundPlay = _soundPlay;
this.soundRepeat = _soundRepeat;

View file

@ -116,16 +116,60 @@
background-color: transparent;
color: #ccc;
}
#gx-load-screen {
display: none;
text-align: center;
margin: auto;
width: 600px;
height: 360px;
font-size: 24px;
color: #ccc;
border: 1px solid #000;
text-decoration: none;
background-position: center center;
background-image: url('play.png');
background-repeat: no-repeat;
background-color: #444;
}
#gx-load-screen:hover {
background-color: #555;
}
#gx-load-screen:before { content: ""; }
#gx-load-screen:after { content: ""; }
#gx-container a, #gx-container a:link, #gx-container a:visited {
color: rgb(69, 118, 147);
}
#gx-container a:hover {
color: rgb(69, 118, 147);
text-decoration: underline;
}
#gx-container a:before { content: ""; }
#gx-container a:after { content: ""; }
#gx-container, #gx-container table {
font-family: arial, helvetica, sans-serif;
font-size: 14px;
}
#share-dialog {
background-color:#ddd;
}
#share-dialog textarea {
font-family: dosvga;
font-size: 1em;
background-color: #efefef;
}
#share-dialog a { color: #333; }
#share-dialog a:hover { color: #000; }
</style>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.52.2/codemirror.min.css"></link>
<link rel="stylesheet" href="codemirror/qb-ide.css"></link>
<link rel="stylesheet" href="dialog/dialog.css"></link>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.52.2/codemirror.min.js"></script>
<script type="text/javascript" src="codemirror/qb-lang.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.52.2/addon/selection/active-line.js"></script>
<script type="text/javascript" src="util/shorty.min.js"></script>
<script type="text/javascript" src="dialog/dialog.js"></script>
<script type="text/javascript" src="dialog/dialog-polyfill.js"></script>
</head>
<body>
<div id="code-container">
@ -139,7 +183,9 @@
<div id="slider-right" class="slider-button" onclick="slideRight()">&gt;</div>
</div>
<div id="game-container">
<div id="gx-container"></div>
<div id="gx-container">
<a href="javascript:runProgram()" id="gx-load-screen">&nbsp;</a>
</div>
<div id="output-container">
<div id="tabs">
<div id="tab-console" class="tab active" onclick="changeTab('console')">Console</div><div id="tab-js" class="tab" onclick="changeTab('js')">Javascript</div>
@ -153,9 +199,19 @@
</div>
<div id="gx-footer"></div>
<div style="display:none" id="share-dialog">
<textarea id="share-code" rows="15" cols="80" readonly></textarea>
</div>
<dialog id="share-dialog">
<div style="margin-bottom:5px">Copy the link below to share your code:</div>
<div><textarea id="share-code" rows="15" cols="80" readonly></textarea></div>
<div style="margin-top: 5px; float:left">Launch Mode:
<select id="share-mode" onchange="shareProgram()">
<option value="">IDE (Default)</option>
<option value="play">Play</option>
<option value="auto">Auto</option>
</select>
</div>
<a href="javascript:closeDialog()" style="display:block; float:right; margin-top: 5px">Close</a>
<a href="javascript:testShare()" style="display: block; float:right; margin-top: 5px; margin-right: 10px">Test</a>
</dialog>
</body>
<script language="javascript" src="gx/gx.js"></script>
<script language="javascript" src="qb.js"></script>
@ -166,6 +222,7 @@
var qbcode = "";
var url = location.href;
var sizeMode = "normal";
var appMode = "ide";
var consoleVisible = false;
var currTab = "console";
@ -179,8 +236,14 @@
qbcode = zin.inflate(atob(nv[1]));
break;
}
else if (nv[0] == "mode") {
appMode = nv[1];
}
}
}
if (appMode == "play") {
document.getElementById("gx-load-screen").style.display = "block";
}
// initialize the code editor
var editor = CodeMirror(document.querySelector("#code"), {
@ -209,6 +272,8 @@
var warnCount = 0;
async function runProgram() {
document.getElementById("gx-load-screen").style.display = "none";
if (sizeMode == "max") {
slideLeft();
}
@ -219,7 +284,6 @@
var jsCode = await QBCompiler.compile(qbCode);
await displayWarnings();
//displayTypes();
var jsDiv = document.getElementById("js-code");
jsDiv.innerHTML = jsCode;
@ -244,6 +308,8 @@
GX.sceneStop();
}
document.getElementById("gx-container").focus();
return false;
}
function stopProgram() {
@ -256,9 +322,26 @@
var b64 = btoa(zout.deflate(editor.getValue()));
var baseUrl = location.href.split('?')[0];
var mode = document.getElementById("share-mode").value;
var codeShare = document.getElementById("share-code");
codeShare.innerHTML = baseUrl + "?qbcode=" + b64;
Dialog.template(document.getElementById("share-dialog"), "Copy the link below to share your code!");
var url = baseUrl + "?";
if (mode) {
url += "mode=" + mode + "&";
}
url += "qbcode=" + b64;
codeShare.value = url;
document.getElementById("share-dialog").showModal();
codeShare.focus();
codeShare.select();
}
function testShare() {
var url = document.getElementById("share-code").value;
open(url, "_blank");
}
function closeDialog() {
document.getElementById("share-dialog").close();
}
async function displayWarnings() {
@ -277,7 +360,8 @@
function showConsole() {
consoleVisible = !consoleVisible;
window.onresize();
window.dispatchEvent(new Event('resize'));
//window.onresize();
}
function changeTab(tabName) {
@ -315,7 +399,8 @@
sizeMode = "min"
document.getElementById("slider-left").style.display = "none";
}
window.onresize();
//window.onresize();
window.dispatchEvent(new Event('resize'));
}
function slideRight() {
@ -327,65 +412,81 @@
sizeMode = "max"
document.getElementById("slider-right").style.display = "none";
}
window.onresize();
//window.onresize();
window.dispatchEvent(new Event('resize'));
}
window.onresize = function() {
var f = document.getElementById("gx-container");
var jsDiv = document.getElementById("output-container");
var cmwidth = 600;
if (sizeMode == "min") {
cmwidth = 0;
editor.getWrapperElement().style.display = "none";
document.getElementById("code").style.borderRight = "0";
}
else if (sizeMode == "max") {
cmwidth = window.innerWidth - 25;
document.getElementById("game-container").style.display = "none";
document.getElementById("slider").style.border = "1px solid #666";
document.getElementById("slider").style.borderLeft = "0";
if (appMode == "play" || appMode == "auto") {
f.style.left = "0px";
f.style.top = "0px";
f.style.width = window.innerWidth;
f.style.height = window.innerHeight;
f.style.border = "0px";
document.getElementById("code-container").style.display = "none";
document.getElementById("slider").style.display = "none";
document.getElementById("show-js-container").style.display = "none";
document.getElementById("game-container").style.left = "0px";
document.getElementById("game-container").style.top = "0px";
jsDiv.style.display = "none";
}
else {
editor.getWrapperElement().style.display = "block";
document.getElementById("game-container").style.display = "block";
document.getElementById("code").style.borderRight = "1px solid #666";
document.getElementById("slider").style.border = "0";
}
document.getElementById("game-container").style.left = (cmwidth + 20) + "px";
f.style.width = (window.innerWidth - (cmwidth + 35)) + "px";
jsDiv.style.width = f.style.width;
document.getElementById("slider").style.left = (cmwidth + 12) + "px";
if (consoleVisible) { // /*document.getElementById("show-js").checked ||*/ warnCount > 0) {
f.style.height = (window.innerHeight - 237) + "px";
jsDiv.style.display = "block";
jsDiv.style.top = (window.innerHeight - 227) + "px";
document.getElementById("toggle-console").innerHTML = "Hide Console";
if (currTab == "console") {
document.getElementById("warning-container").style.display = "block";
document.getElementById("js-code").style.display = "none";
var cmwidth = 600;
if (sizeMode == "min") {
cmwidth = 0;
editor.getWrapperElement().style.display = "none";
document.getElementById("code").style.borderRight = "0";
}
else if (sizeMode == "max") {
cmwidth = window.innerWidth - 25;
document.getElementById("game-container").style.display = "none";
document.getElementById("slider").style.border = "1px solid #666";
document.getElementById("slider").style.borderLeft = "0";
}
else {
document.getElementById("warning-container").style.display = "none";
document.getElementById("js-code").style.display = "block";
editor.getWrapperElement().style.display = "block";
document.getElementById("game-container").style.display = "block";
document.getElementById("code").style.borderRight = "1px solid #666";
document.getElementById("slider").style.border = "0";
}
}
else {
f.style.height = (window.innerHeight - 50) + "px";
jsDiv.style.display = "none";
document.getElementById("toggle-console").innerHTML = "Show Console";
}
document.getElementById("show-js-container").style.top = (window.innerHeight - 45) + "px";
document.getElementById("show-js-container").style.right = "5px";
//document.getElementById("js-code").style.display = document.getElementById("show-js").checked ? "block" : "none";
editor.setSize(cmwidth, window.innerHeight - 50);
document.getElementById("code").style.height = (window.innerHeight - 50) + "px";
document.getElementById("slider").style.height = (window.innerHeight - 50) + "px";
document.getElementById("game-container").style.left = (cmwidth + 20) + "px";
f.style.width = (window.innerWidth - (cmwidth + 35)) + "px";
jsDiv.style.width = f.style.width;
document.getElementById("slider").style.left = (cmwidth + 12) + "px";
if (consoleVisible) {
f.style.height = (window.innerHeight - 237) + "px";
jsDiv.style.display = "block";
jsDiv.style.top = (window.innerHeight - 227) + "px";
document.getElementById("toggle-console").innerHTML = "Hide Console";
if (currTab == "console") {
document.getElementById("warning-container").style.display = "block";
document.getElementById("js-code").style.display = "none";
}
else {
document.getElementById("warning-container").style.display = "none";
document.getElementById("js-code").style.display = "block";
}
}
else {
f.style.height = (window.innerHeight - 50) + "px";
jsDiv.style.display = "none";
document.getElementById("toggle-console").innerHTML = "Show Console";
}
document.getElementById("show-js-container").style.top = (window.innerHeight - 45) + "px";
document.getElementById("show-js-container").style.right = "5px";
editor.setSize(cmwidth, window.innerHeight - 50);
document.getElementById("code").style.height = (window.innerHeight - 50) + "px";
document.getElementById("slider").style.height = (window.innerHeight - 50) + "px";
}
//QB.resize(f.style.width.replace("px", ""), f.style.height.replace("px", ""));
QB.resize(f.clientWidth, f.clientHeight);
}
window.onresize();
@ -401,6 +502,10 @@
setTimeout(checkButtonState, 100);
}
checkButtonState();
if (appMode == "auto") {
runProgram();
}
</script>
</html>

BIN
play.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 533 B

251
qb.js
View file

@ -2,6 +2,9 @@ var QB = new function() {
// QB constants
this.COLUMN_ADVANCE = Symbol("COLUMN_ADVANCE");
this.PREVENT_NEWLINE = Symbol("PREVENT_NEWLINE");
this.LOCAL = Symbol("LOCAL");
this.SESSION = Symbol("SESSION");
var _fgColor = null;
var _bgColor = null;
@ -21,7 +24,12 @@ var QB = new function() {
var _images = {};
var _activeImage = 0;
var _nextImageId = 1000;
var _lastLimitTime = 0;
//var _lastLimitTime = 0;
var _resize = false;
var _resizeWidth = 0;
var _resizeHeight = 0;
var _domElements = [];
var _domEvents = [];
// Array handling methods
// ----------------------------------------------------
@ -75,12 +83,19 @@ var QB = new function() {
return value;
};
this.import = async function(url) {
this.resize = function(width, height) {
_resize = true;
_resizeWidth = width;
_resizeHeight = height;
}
/*this.import = async function(url) {
await fetch(url).then(response => response.text()).then((response) => {
var f = new Function(response);
f();
});
};
};*/
// Process control methods
// -------------------------------------------
@ -102,6 +117,7 @@ var QB = new function() {
_haltedFlag = false;
_nextImageId = 1000;
_activeImage = 0;
_domInit();
}
this.running = function() {
@ -177,7 +193,7 @@ var QB = new function() {
return 8;
};
this.func__FreeImage = function(imageId) {
this.sub__FreeImage = function(imageId) {
_images[imageId] = undefined;
}
@ -269,7 +285,7 @@ var QB = new function() {
this.func__NewImage = function(iwidth, iheight) {
var canvas = document.createElement("canvas");
canvas.id = "gx-canvas";
canvas.id = "qb-canvas-" + _nextImageId;
canvas.width = iwidth;
canvas.height = iheight;
ctx = canvas.getContext("2d");
@ -398,6 +414,20 @@ var QB = new function() {
return _color(rgb).r;
};
this.func__Resize = function() {
var tmp = _resize;
_resize = false;
return tmp ? -1 : 0;
}
this.func__ResizeHeight = function() {
return _resizeHeight;
};
this.func__ResizeWidth = function() {
return _resizeWidth;
};
this.func__RGB = function(r, g, b) {
return this.func__RGBA(r, g, b);
};
@ -441,7 +471,36 @@ var QB = new function() {
this.func__ScreenExists = function() {
return true;
}
};
this.sub__SndClose = function(sid) {
GX.soundClose(sid);
};
this.func__SndOpen = function(filename) {
return GX.soundLoad(filename);
};
this.sub__SndPlay = function(sid) {
GX.soundPlay(sid);
};
this.sub__SndLoop = function(sid) {
GX.soundRepeat(sid);
};
this.sub__SndPause = function(sid) {
GX.soundPause(sid);
};
this.sub__SndStop = function(sid) {
GX.soundStop(sid);
};
this.sub__SndVol = function(sid, v) {
GX.soundVolumne(sid, v);
};
this.sub__Title = function(title) {
document.title = title;
@ -487,11 +546,15 @@ var QB = new function() {
if (bgColor != undefined) {
color = _color(bgColor);
}
// TODO: parameter variants
ctx = _images[_activeImage].ctx;
ctx.beginPath();
ctx.fillStyle = color.rgba();
ctx.fillRect(0, 0, QB.func__Width() , QB.func__Height());
// reset the text position
_locX = 0;
_locY = 0;
};
function _color(c) {
@ -521,6 +584,24 @@ var QB = new function() {
return Math.cos(value);
};
this.func_Cvi = function(numString) {
var result = 0;
numString = numString.split("").reverse().join("");
for (let i=1;i>=0;i--) {
result+=numString.charCodeAt(1-i)<<(8*i);
}
return result;
}
this.func_Cvl = function(numString) {
var result = 0;
numString = numString.split("").reverse().join("");
for (let i=3;i>=0;i--) {
result+=numString.charCodeAt(3-i)<<(8*i);
}
return result;
}
this.func_Exp = function(value) {
return Math.exp(value);
};
@ -749,6 +830,22 @@ var QB = new function() {
}
};
this.func_Mki = function(num) {
var ascii = "";
for (var i=1; i >= 0; i--) {
ascii += String.fromCharCode((num>>(8*i))&255);
}
return ascii.split("").reverse().join("");
};
this.func_Mkl = function(num) {
var ascii = "";
for (var i=3; i >= 0; i--) {
ascii += String.fromCharCode((num>>(8*i))&255);
}
return ascii.split("").reverse().join("");
};
this.sub_Print = async function(args) {
// Print called with no arguments
if (args == undefined || args == null || args.length < 1) {
@ -892,6 +989,7 @@ var QB = new function() {
var img = _images[mode];
if (img && img.canvas) {
GX.sceneCreate(img.canvas.width, img.canvas.height);
this.sub__PutImage(undefined, undefined, undefined, undefined, undefined, undefined, mode);
}
}
_images[0] = { canvas: GX.canvas(), ctx: GX.ctx(), lastX: 0, lastY: 0 };
@ -915,6 +1013,14 @@ var QB = new function() {
else { return 0; }
};
this.func_Space = function(ccount) {
return QB.func_String(ccount, " ");
}
this.func_String = function(ccount, s) {
return "".padStart(ccount, s);
};
this.func_Sin = function(value) {
return Math.sin(value);
};
@ -1000,6 +1106,137 @@ var QB = new function() {
this.func_ToJSON = function(a) {
return JSON.stringify(a);
};
this.sub_Alert = function(text) {
alert(text);
}
this.func_Confirm = function(text) {
return confirm(text) ? -1 : 0;
}
this.sub_DomAdd = function(e, parent, beforeElement) {
if (typeof e == "string") {
e = document.getElementById(e);
}
if (parent == undefined || parent == "") {
parent = QB.func_DomContainer();
}
else if (typeof parent == "string") {
parent = document.getElementById(parent);
}
if (beforeElement == undefined || beforeElement == "") {
beforeElement = null;
}
else if (typeof beforeElement == "string") {
beforeElement = document.getElementById(beforeElement);
}
parent.insertBefore(e, beforeElement);
};
this.func_DomCreate = function(etype, parent, content, eid, beforeElement) {
var e = document.createElement(etype);
if (eid != undefined && eid != "") {
e.id = eid;
}
e.className = "qbjs";
if (content != undefined) {
if (e.value != undefined) {
e.value = content;
}
if (e.innerHTML != undefined) {
e.innerHTML = content;
}
}
_domElements.push(e);
QB.sub_DomAdd(e, parent, beforeElement);
return e;
};
this.sub_DomCreate = function(etype, parent, content, eid, beforeElement) {
this.func_DomCreate(etype, parent, content, eid, beforeElement);
};
this.sub_DomEvent = function(target, eventType, callbackFn) {
if (typeof target == "string") {
target = document.getElementById(target);
}
target.addEventListener(eventType, callbackFn);
_domEvents.push({ target: target, eventType: eventType, callbackFn: callbackFn});
};
this.func_DomContainer = function() {
return document.getElementById("gx-container");
}
this.func_DomGet = function(eid) {
return document.getElementById(eid);
};
this.func_DomGetImage = function(imageId) {
return _images[imageId].canvas;
};
this.sub_DomRemove = function(e) {
if (typeof e == "string") {
e = document.getElementById(e);
}
if (e != undefined && e != null) {
e.remove();
}
}
this.func_Prompt = function(text, defaultValue) {
return prompt(text, defaultValue);
}
function _storage(stype) {
return (stype == QB.SESSION) ? sessionStorage : localStorage;
}
this.sub_StorageClear = function(stype) {
_storage(stype).clear();
}
this.func_StorageGet = function(key, stype) {
return _storage(stype).getItem(key);
}
this.func_StorageKey = function(idx, stype) {
return _storage(stype).key(idx);
}
this.func_StorageLength = function(stype) {
return _storage(stype).length;
}
this.sub_StorageSet = function(key, value, stype) {
_storage(stype).setItem(key, value);
}
this.sub_StorageRemove = function(key, stype) {
_storage(stype).removeItem(key);
}
function _domInit() {
//var elements = document.getElementsByClassName("qbjs");
//for (var i=0; i < elements.length; i++) {
// elements[i].remove();
//}
var e = null;
while (e = _domElements.pop()) {
e.remove();
}
while (e = _domEvents.pop()) {
e.target.removeEventListener(e.eventType, e.callbackFn);
}
}
function _addInkeyPress(e) {

1727
qb2js.js

File diff suppressed because it is too large Load diff

View file

<
@ -399,7 +399,11 @@ Sub ConvertLines (firstLine As Integer, lastLine As Integer, functionName As Str
If FindMethod(subname, m, "SUB") Then
Dim subargs As String
subargs = Mid$(subline, Len(subname) + 2, Len(subline) - Len(subname) - 2)
If subname = subline Then
subargs = ""
Else
subargs = Mid$(subline, Len(subname) + 2, Len(subline) - Len(subname) - 2)
End If
js = ConvertSub(m, subargs)
Else
AddWarning i, "Missing Sub [" + subname + "], ignoring Call command"
@ -495,7 +499,8 @@ Function ConvertSub$ (m As Method, args As String)
js = CallMethod(m) + "(" + ConvertPutImage(args) + ");"
Else
js = CallMethod(m) + "(" + ConvertExpression(args) + ");"
'js = CallMethod(m) + "(" + ConvertExpression(args) + ");"
js = CallMethod(m) + "(" + ConvertMethodParams(args) + ");"
End If