Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add mobile gestures and make demo more friendly #3

Merged
merged 2 commits into from Oct 14, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
25 changes: 19 additions & 6 deletions css/main.css
@@ -1,9 +1,22 @@
html, body {
background-color: black;
color: white;
font-family: sans-serif;
background-color: #eee;
color: #333;
}

#container {
max-width: 680px;
margin: 0 auto;
}

#container > * {
margin: 1rem;
}

width: 100%;
height: 100%;
margin: 0;
padding: 0;
#terminal {
height: 360px;
padding: 0.5rem;
background-color: #1f1f1f;
border-radius: 10px;
border: 3px solid black;
}
43 changes: 38 additions & 5 deletions index.html
Expand Up @@ -4,18 +4,51 @@
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>LC3 Virtual Machine</title>
<title>LC-3 Virtual Machine</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/8.0.1/normalize.min.css" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/xterm/3.10.1/xterm.min.css" />
<link rel="stylesheet" href="css/main.css" />
</head>
<body>
<div id="terminal"></div>
<div id="controls">
<button onclick="restartAndLoad(lc3_2048);">2048</button>
<button onclick="restartAndLoad(lc3_rogue);">Rogue</button>
<div id="container">
<div id="intro">
<h1>lc3sim-js</h1>
<p>lc3sim-js is a JavaScript implementation of the LC-3 virtual machine, an educational computer architecture.</p>
</div>

<div id="programs">
<h3>Programs</h3>
<p>Although lc3sim-js is capable of running any valid LC-3 program, this demo includes just two sample games:</p>
<p>
<button onclick="restartAndLoad(lc3_2048);">2048</button>
<button onclick="restartAndLoad(lc3_rogue);">Rogue</button>
</p>
</div>

<div id="terminal"></div>

<div id="controls">
<h3>Controls:</h3>
<p>Any keys that are pressed while the terminal is focused will be forwarded to the VM.</p>
<p>
On mobile (or devices with a touch screen), swiping on the terminal will simulate WASD key presses.
To send keys other than this, you can tap anywhere in the terminal to manually focus the terminal and open a keyboard.
</p>
</div>

<div id="more-information">
<h3>More Information</h3>
<p>Source code is available on GitHub at <a href="https://github.com/rpendleton/lc3sim-js">rpendleton/lc3sim-js</a>.</p>
<p>
This project is based on a tutorial written by my friend and me.
If you're interested in writing your own VM (or just want to learn more about the project), you can find the tutorial at
<a href="https://justinmeiners.github.io/lc3-vm">justinmeiners.github.io/lc3-vm</a>.
</p>
</div>
</div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/xterm/3.10.1/xterm.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/xterm/3.10.1/addons/fit/fit.min.js"></script>

<script src="obj/lc3os.js"></script>
<script src="obj/2048.js"></script>
Expand Down
71 changes: 68 additions & 3 deletions js/main.js
@@ -1,9 +1,18 @@
(function() {
var vm = new VirtualMachine();

var term = new Terminal();
term.open(document.getElementById('terminal'));
Terminal.applyAddon(fit);

var term = new Terminal({
theme: {
background: '#1f1f1f'
}
});

var termContainer = document.getElementById('terminal');
term.open(termContainer);
term.write('Choose a game to begin.\r\n');
term.fit();

// MARK: - display

Expand All @@ -25,6 +34,7 @@

// MARK: - input

var supportsTouch = 'ontouchstart' in document;
var availableKeys = [];

term.on('key', function(char, e) { // eslint-disable-line no-unused-vars
Expand All @@ -51,7 +61,10 @@

function restartAndLoad(program) {
term.clear();
term.focus();

if (!supportsTouch) {
term.focus();
}

vm.reset();
availableKeys = [];
Expand All @@ -62,4 +75,56 @@
}

window.restartAndLoad = restartAndLoad;

// MARK: - gestures

function recognizeGesture(touchStart, touchEnd) {
// If both deltas are >= this threshold, we'll consider the swipe to be
// diagonal and cancel it.
var swipeDiagonalThreshold = 50;

// If one of the detals is >= this threshold and the other is < the
// diagonal threshold, we'll consider the swipe to be valid.
var swipeMinimumThreshold = 75;
var swipeThreshold = 75;

var deltaX = touchEnd.x - touchStart.x;
var deltaY = touchEnd.y - touchStart.y;

if (Math.abs(deltaX) >= swipeMinimumThreshold && Math.abs(deltaY) < swipeDiagonalThreshold) {
return deltaX > 0 ? 'd' : 'a';
}
else if (Math.abs(deltaY) >= swipeMinimumThreshold && Math.abs(deltaX) < swipeDiagonalThreshold) {
return deltaY > 0 ? 's' : 'w';
}
else {
return null;
}
}

if (supportsTouch) {
var touchStart;

termContainer.addEventListener('touchstart', function(e) {
touchStart = {
x: e.changedTouches[0].screenX,
y: e.changedTouches[0].screenY
};
});

termContainer.addEventListener('touchend', function(e) {
var touchEnd = {
x: e.changedTouches[0].screenX,
y: e.changedTouches[0].screenY
};

var recognizedGestureKey = recognizeGesture(touchStart, touchEnd);
touchStart = null;

if (recognizedGestureKey !== null) {
availableKeys.push(recognizedGestureKey.charCodeAt(0));
vm.interrupt();
}
});
}
})();