Skip to content

Commit

Permalink
Beta update 9
Browse files Browse the repository at this point in the history
  • Loading branch information
morgan3d committed Aug 18, 2019
1 parent 5e5ee90 commit 9f7f672
Show file tree
Hide file tree
Showing 12 changed files with 103 additions and 64 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
The **quadplay✜** fantasy console by [CasualEffects](https://casual-effects.com)
is now in public beta.

- [Play online](https://morgan3d.github.io/quadplay/console/index.html)
- [See the IDE](https://morgan3d.github.io/quadplay/console/index.html?IDE=1&game=quad://games/quadpaddle) (editing disabled)
- [Play online](https://morgan3d.github.io/quadplay/console/quadplay.html)
- [See the IDE](https://morgan3d.github.io/quadplay/console/quadplay.html?IDE=1&game=quad://games/quadpaddle) (editing disabled)
- [Read the manual](https://morgan3d.github.io/quadplay/doc/manual.md.html)
- [Download the console](https://github.com/morgan3d/quadplay/archive/master.zip)

Expand Down
30 changes: 19 additions & 11 deletions console/quadplay-host.js
Original file line number Diff line number Diff line change
Expand Up @@ -248,15 +248,16 @@ function getIdealGamepads() {
let pad = gamepads[i];
if (pad && pad.connected) {
// Construct a simplified web gamepad API
let mypad = {axes:[0, 0, 0, 0], buttons:[]};
const axisRemap = gamepadAxisRemap[pad.id] || gamepadAxisRemap.identity;
let mypad = {axes:[0, 0, 0, 0], buttons:[], analogAxes:[0,0,0,0]};
const axisRemap = gamepadAxisRemap[pad.id] || gamepadAxisRemap.identity;
for (let a = 0; a < Math.min(4, pad.axes.length); ++a) {
const axis = pad.axes[axisRemap[a]];
mypad.axes[a] = (Math.abs(axis) > deadZone) ? Math.sign(axis) : 0;
mypad.analogAxes[a] = axis;
}

// Process all 17 buttons/axes as digital buttons first
const buttonRemap = gamepadButtonRemap[pad.id] || gamepadButtonRemap.identity;
const buttonRemap = gamepadButtonRemap[pad.id] || gamepadButtonRemap.identity;
for (let b = 0; b < 17; ++b) {
const button = pad.buttons[buttonRemap[b]];
// Different browsers follow different APIs for the value of buttons
Expand Down Expand Up @@ -612,7 +613,7 @@ function submitFrame() {


function updateInput() {
const axes = 'xy', buttons = 'abcdpq', BUTTONS = 'ABCDPQ';
const axes = 'xy', AXES = 'XY', buttons = 'abcdpq', BUTTONS = 'ABCDPQ';

// HTML gamepad indices of corresponding elements of the buttons array
// A, B, C, D, P, Q
Expand All @@ -639,15 +640,16 @@ function updateInput() {
altPrevRealGamepad = (player === 2) ? prevRealGamepadState[0] : (player === 3) ? prevRealGamepadState[0] : undefined; */

// Have player 0 physical alt controls set player 1 virtual buttons
const altRealGamepad = (player === 1) ? gamepadArray[0] : undefined,
const altRealGamepad = (player === 1) ? gamepadArray[0] : undefined,
altPrevRealGamepad = (player === 1) ? prevRealGamepadState[0] : undefined;

// Axes
for (let a = 0; a < axes.length; ++a) {
const axis = axes[a];
const AXIS = '_analog' + AXES[a];
const pos = '+' + axis, neg = '-' + axis;
const old = pad[axis];
const scale = (axis == 'x') ? Runtime._scaleX : Runtime._scaleY;
const scale = (axis === 'x') ? Runtime._scaleX : Runtime._scaleY;

if (map) {
// Keyboard controls
Expand All @@ -664,7 +666,13 @@ function updateInput() {
pad[axis] = pad[axis + axis] = 0;
}

if (realGamepad && (realGamepad.axes[a] !== 0)) { pad[axis] = realGamepad.axes[a] * scale; }
pad[AXIS] = pad[axis];

if (realGamepad && (realGamepad.axes[a] !== 0)) {
pad[axis] = realGamepad.axes[a] * scale;
pad[AXIS] = realGamepad.analogAxes[a] * scale;
}

if (realGamepad && (prevRealGamepad.axes[a] !== realGamepad.axes[a])) {
pad[axis + axis] = realGamepad.axes[a] * scale;
}
Expand All @@ -675,13 +683,13 @@ function updateInput() {
// to controller[1] d-pad (axes 0 + 1) for "dual stick" controls
if (otherPad.axes[a + 2] !== 0) {
pad[axis] = otherPad.axes[a + 2] * scale;
pad[AXIS] = otherPad.analogAxes[a + 2] * scale;
}
if (otherPad.axes[a + 2] !== otherPad.axes[a + 2]) {
pad[axis + axis] = otherPad.axes[a + 2] * scale;
}
} // dual-stick


pad['d' + axis] = pad[axis] - old;
}

Expand All @@ -701,7 +709,7 @@ function updateInput() {
const i = buttonIndex[b], j = altButtonIndex[b];
const isPressed = (realGamepad && realGamepad.buttons[i]) || (altRealGamepad && altRealGamepad.buttons[j]);

const wasPressed = (prevRealGamepad && prevRealGamepad.buttons[i]) ||
const wasPressed = (prevRealGamepad && prevRealGamepad.buttons[i]) ||
(altPrevRealGamepad && altPrevRealGamepad.buttons[j]);

if (isPressed) { pad[button] = 1; }
Expand Down Expand Up @@ -733,9 +741,9 @@ function updateInput() {
// loop so that the alternative buttons for player 2 are not
// immediately overrident during player 1's processing.
for (let player = 0; player < 4; ++player) {
if (gamepadArray[player]) {
if (gamepadArray[player]) {
prevRealGamepadState[player] = gamepadArray[player];
}
}
}

// Reset the just-pressed state
Expand Down
103 changes: 57 additions & 46 deletions console/quadplay-ide.js
Original file line number Diff line number Diff line change
Expand Up @@ -610,8 +610,16 @@ function deviceControl(cmd) {
case "stopGIFRecording": stopGIFRecording(); break;
case "takeScreenshot": downloadScreenshot(); break;
case "startPreviewRecording": startPreviewRecording(); break;
case "getAnalogAxes":
{
const i = clamp(parseInt(arguments[1]), 0, 3);
const pad = Runtime.pad[i];
return {x: pad._analogX, y: pad._analogY};
break;
}

case "setPadType":

{
const i = arguments[1];
const type = arguments[2];
const prompt = controlSchemeTable[type];
Expand All @@ -620,6 +628,7 @@ function deviceControl(cmd) {
Runtime.pad[i].type = type;
Runtime.pad[i].prompt = prompt;
break;
}
}
}

Expand Down Expand Up @@ -1538,6 +1547,8 @@ function setFramebufferSize(w, h) {

// The layout may need updating as well
setTimeout(onResize, 0);
setTimeout(onResize, 250);
setTimeout(onResize, 1250);
}


Expand Down Expand Up @@ -2149,33 +2160,33 @@ function loadGameIntoIDE(url, callback) {
// Let the boot screen show before we add to it
setTimeout(function() {
{
let serverURL = location.origin + location.pathname;
// Remove common subexpression for shorter URLs
if (url.substring(0, serverURL.length) === serverURL) {
url = url.substring(serverURL.length);
let serverURL = location.origin + location.pathname;
// Remove common subexpression for shorter URLs
if (url.substring(0, serverURL.length) === serverURL) {
url = url.substring(serverURL.length);
}

// Remove redundant filename for shorterURLs
url = url.replace(/([^\/:=&]+)\/([^\/:=&]+?)\.game\.json$/, function (match, path, filename) {
return (path === filename) ? path + '/' : match;
});

serverURL += '?game=' + url;
qrcode.makeCode(serverURL);
document.getElementById('serverURL').innerHTML =
`<a href="${serverURL}" target="_blank">${serverURL}</a>`;
}

// Remove redundant filename for shorterURLs
url = url.replace(/([^\/:=&]+)\/([^\/:=&]+?)\.game\.json$/, function (match, path, filename) {
return (path === filename) ? path + '/' : match;
});

serverURL += '?game=' + url;
qrcode.makeCode(serverURL);
document.getElementById('serverURL').innerHTML =
`<a href="${serverURL}" target="_blank">${serverURL}</a>`;
}

document.getElementById('playButton').enabled = false;
onLoadFileStart(url);
afterLoadGame(url, function () {
onLoadFileComplete(url);
hideBootScreen();
console.log('Loading complete.');
setFramebufferSize(gameSource.json.screenSize.x, gameSource.json.screenSize.y);
createProjectWindow(gameSource);
let resourcePane = document.getElementById('resourcePane');
resourcePane.innerHTML = `
document.getElementById('playButton').enabled = false;
onLoadFileStart(url);
afterLoadGame(url, function () {
onLoadFileComplete(url);
hideBootScreen();
console.log('Loading complete.');
setFramebufferSize(gameSource.json.screenSize.x, gameSource.json.screenSize.y);
createProjectWindow(gameSource);
let resourcePane = document.getElementById('resourcePane');
resourcePane.innerHTML = `
<br/><center><b style="color:#888">Resource Limits</b></center>
<hr>
<br/>
Expand All @@ -2187,19 +2198,19 @@ function loadGameIntoIDE(url, callback) {
<tr><td>Source Statements</td><td class="right">${resourceStats.sourceStatements}</td><td>/</td><td class="right">8192</td><td class="right">(${Math.round(resourceStats.sourceStatements*100/8192)}%)</td></tr>
<tr><td>Sounds</td><td class="right">${resourceStats.sounds}</td><td>/</td><td class="right">128</td><td class="right">(${Math.round(resourceStats.sounds*100/128)}%)</td></tr>
</table>`;
document.getElementById('playButton').enabled = true;

const modeEditor = document.getElementById('modeEditor');
if (modeEditor.style.visibility === 'visible') {
// Update the editor
visualizeModes(modeEditor);
}

aceEditor.gotoLine(0, 0, false);
aceEditor.scrollToLine(0, false, false, undefined);
hideWaitDialog();

appendToBootScreen(`
document.getElementById('playButton').enabled = true;
const modeEditor = document.getElementById('modeEditor');
if (modeEditor.style.visibility === 'visible') {
// Update the editor
visualizeModes(modeEditor);
}
aceEditor.gotoLine(0, 0, false);
aceEditor.scrollToLine(0, false, false, undefined);
hideWaitDialog();
appendToBootScreen(`
QuadOS ROM: 256269 bytes
Runtime ROM: 159754 bytes
Expand All @@ -2216,13 +2227,13 @@ Checking game pad input…OK
Starting…
`);
if (callback) { callback(); }
}, function (e) {
hideBootScreen();
setErrorStatus('Loading ' + url + ' failed: ' + e);
onStopButton();
hideWaitDialog();
});
if (callback) { callback(); }
}, function (e) {
hideBootScreen();
setErrorStatus('Loading ' + url + ' failed: ' + e);
onStopButton();
hideWaitDialog();
});
}, 15);
}

Expand Down
4 changes: 3 additions & 1 deletion console/quadplay-runtime.js
Original file line number Diff line number Diff line change
Expand Up @@ -1038,7 +1038,9 @@ function _makePad(index) {
lt: '⍇',
dn: '⍗',
rt: '⍈'
})
}),
_analogX: 0,
_analogY: 0
});
}

Expand Down
File renamed without changes.
15 changes: 13 additions & 2 deletions doc/manual.md.html
Original file line number Diff line number Diff line change
Expand Up @@ -2682,7 +2682,7 @@
: Reserved function for executing device-specific features such as the
game launcher, GPIO, and alternative input devices. `command` is a
string telling the host which control feature to execute, and the
remaining arguments are passed to it. All `deviceControl` commands
remaining arguments are passed to it. All `deviceControl()` commands
may change in future releases and may not work on any given platform.

- `"startGIFRecording"` Begin GIF recording.
Expand All @@ -2692,7 +2692,8 @@
terminates automatically after a set time.
- `"takeScreenshot"` Take a screenshot and download it to the local disk.
- `"setPadType", index, "type"` Set `pad[index].type` and the corresponding prompts.

- `"getAnalogAxes", index` Return an `xy()` of the analog axis values for `pad[index]`, without D-pad snapping.
Needed for accessing Atari paddles, car pedals, steering wheels, and flight stick throttles in a meaningful way.

`drawBounds(e, color (= gray(60%)), recurse (= true))`
: Render a debugging view of the bounds of an entity or other object
Expand Down Expand Up @@ -2987,6 +2988,8 @@

![`quad://fonts/nano-3.font.json`](../fonts/nano-3.png)

![`quad://fonts/nanob-3.font.json`](../fonts/nanob-3.png)


Sounds
------------------------------------------------------------------------------------
Expand Down Expand Up @@ -4793,6 +4796,14 @@

Changes for both the specification and implementation in each release.

2019 August 17: Beta update 9

- Added `nanob-3.font.json` (like nano-3, but with thinner L and I characters)
- Patch for emulator view resizing for new dimensions on slower browsers
- Added `deviceControl()` `"getAnalogAxes" command
- Renamed `index.html` to `quadplay.html` for improved itch.io compatibility


2019 August 16: Beta update 8

- Allowed `for` and `with` variable lists to be split across multiple lines
Expand Down
2 changes: 1 addition & 1 deletion fonts/nano-3.font.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"url": "nano-3.png",
"license": "© 2019 Morgan McGuire. Licensed as CC BY 4.0",
"charSize": {"x": 4, "y": 4},
"charSize": {"x": 4, "y": 5},
"letterSpacing": {"x": 1, "y": 0},
"baseline": 2
}
Binary file modified fonts/nano-3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified fonts/nano-4.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 7 additions & 0 deletions fonts/nanob-3.font.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"url": "nanob-3.png",
"license": "© 2019 Morgan McGuire. Licensed as CC BY 4.0",
"charSize": {"x": 4, "y": 5},
"letterSpacing": {"x": 1, "y": 0},
"baseline": 2
}
Binary file added fonts/nanob-3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion tools/pyxlscript-mode.el
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
"makeEntity" "drawEntity" "overlaps" "updateEntityChildren" "physicsStepEntity"
"now" "gameFrames" "modeFrames" "findMapPath" "findPath"
"gray" "rgb" "rgba" "hsv" "hsva"
"call"
"call" "setPostEffects" "resetPostEffects"
"abs" "acos" "atan" "asin" "sign" "signNonZero" "cos" "clamp" "hash" "lerp" "log" "log2" "log10" "loop" "min" "max" "mid" "noise" "oscillate" "overlap" "pow" "rndInt" "rndDisk" "rndSquare" "rndValue" "rnd" "ξ" "sgn" "sqrt" "sin" "srand" "tan"
"clone" "copy" "drawPreviousMode" "cross" "direction" "dot" "equivalent" "magnitude" "maxComponent" "minComponent" "xy" "xyz"
"fastRemoveKey" "find" "keys" "removeKey" "size" "substring" "sort" "resize" "push" "pop" "removeValues" "pad" "joy" "round" "floor" "ceil"
Expand Down

0 comments on commit 9f7f672

Please sign in to comment.