forked from cory/tildefriends
All of the changes that have been sitting on tildepi for ages. For posterity.
git-svn-id: https://www.unprompted.com/svn/projects/tildefriends/trunk@3530 ed5197a5-7fde-0310-b194-c3ffbd925b24
This commit is contained in:
208
packages/cory/tanks/tanks.js
Normal file
208
packages/cory/tanks/tanks.js
Normal file
@ -0,0 +1,208 @@
|
||||
"use strict";
|
||||
|
||||
//! {"require": ["libiframe"]}
|
||||
|
||||
let isClient = imports.terminal != null;
|
||||
if (isClient) {
|
||||
require("libiframe").iframe({
|
||||
source: `
|
||||
document.documentElement.setAttribute("style", "width: 100%; height: 100%; margin: 0; padding: 0");
|
||||
document.body.setAttribute("style", "display: flex; flex-direction: column; height: 100%; width: 100%; margin: 0; padding: 0");
|
||||
document.body.style.color = '#fff';
|
||||
document.body.style.backgroundColor = '#000';
|
||||
|
||||
var canvas = document.createElement("canvas");
|
||||
canvas.setAttribute("style", "flex: 1 1; image-rendering: pixelated");
|
||||
canvas.width = 128;
|
||||
canvas.height = 128;
|
||||
document.body.append(canvas);
|
||||
|
||||
var buttonBar = document.createElement("div");
|
||||
buttonBar.setAttribute("style", "flex: 0 1 1in; display: flex; flex-direction: row");
|
||||
var buttons = ["<", "^", "v", ">", "Fire!"];
|
||||
for (var i = 0; i < buttons.length; i++) {
|
||||
var button = document.createElement("input");
|
||||
button.setAttribute("type", "button");
|
||||
button.setAttribute("style", "flex: 1 1");
|
||||
button.value = buttons[i];
|
||||
button.onclick = buttonClicked.bind(null, buttons[i]);
|
||||
buttonBar.append(button);
|
||||
}
|
||||
document.body.append(buttonBar);
|
||||
|
||||
var buttonCallback;
|
||||
function buttonClicked(button) {
|
||||
if (buttonCallback) {
|
||||
buttonCallback(button);
|
||||
}
|
||||
}
|
||||
|
||||
var kExportNames = [
|
||||
"beginPath",
|
||||
"fill",
|
||||
"save",
|
||||
"restore",
|
||||
"scale",
|
||||
"rotate",
|
||||
"translate",
|
||||
"transform",
|
||||
"arc",
|
||||
"moveTo",
|
||||
"lineTo",
|
||||
"fillRect",
|
||||
"fillText",
|
||||
"stroke",
|
||||
];
|
||||
var context = canvas.getContext("2d");
|
||||
var exports = {};
|
||||
for (var i = 0; i < kExportNames.length; i++) {
|
||||
exports[kExportNames[i]] = context[kExportNames[i]].bind(context);
|
||||
}
|
||||
exports.setButtonCallback = function(callback) { buttonCallback = callback; };
|
||||
exports.setFillStyle = function(style) { context.fillStyle = style; };
|
||||
exports.setStrokeStyle = function(style) { context.strokeStyle = style; };
|
||||
exports.setLineWidth = function(width) { context.lineWidth = width; };
|
||||
rpc.export(exports);
|
||||
`,
|
||||
style: `
|
||||
border: 0;
|
||||
`}).then(initialize).catch(terminal.print);
|
||||
|
||||
function initialize(iframe) {
|
||||
iframe.setButtonCallback(click);
|
||||
draw(iframe);
|
||||
core.register("onMessage", onMessage.bind(null, iframe));
|
||||
core.getService("server").then(function(server) {
|
||||
server.postMessage({ready: true});
|
||||
});
|
||||
}
|
||||
|
||||
async function click(button) {
|
||||
(await core.getService("server")).postMessage({button: button});
|
||||
}
|
||||
|
||||
function draw(iframe) {
|
||||
iframe.setFillStyle('#222');
|
||||
iframe.fillRect(0, 0, 640, 480);
|
||||
}
|
||||
|
||||
function drawTank(iframe, x, y, color, angle) {
|
||||
iframe.save();
|
||||
iframe.setLineWidth(1);
|
||||
iframe.setFillStyle(color);
|
||||
iframe.setStrokeStyle(color);
|
||||
iframe.translate(x, y);
|
||||
iframe.beginPath();
|
||||
iframe.arc(0, 0, 4, Math.PI, 2 * Math.PI);
|
||||
iframe.fill();
|
||||
iframe.beginPath();
|
||||
var radians = Math.PI + angle * Math.PI / 180.0;
|
||||
iframe.moveTo(Math.cos(radians) * 2, Math.sin(radians) * 2 - 0.5);
|
||||
iframe.lineTo(Math.cos(radians) * 10, Math.sin(radians) * 10 - 0.5);
|
||||
iframe.stroke();
|
||||
iframe.restore();
|
||||
}
|
||||
|
||||
function onMessage(iframe, sender, message) {
|
||||
iframe.setFillStyle('#222');
|
||||
iframe.fillRect(0, 0, 640, 480);
|
||||
|
||||
for (let i = 0; i < message.users.length; i++) {
|
||||
var tank = message.users[i];
|
||||
drawTank(iframe, tank.position.x, tank.position.y, tank.user == core.user.index ? '#f00' : '#0f0', tank.angle);
|
||||
}
|
||||
iframe.setFillStyle('#0f0');
|
||||
for (let i = 0; i < message.terrain.length; i++) {
|
||||
let h = message.terrain[i];
|
||||
iframe.fillRect(i, 128 - h, i + 1, h);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let users = {};
|
||||
let terrain = new Array(128);
|
||||
let updating = false;
|
||||
|
||||
function startUpdating() {
|
||||
if (!updating) {
|
||||
setTimeout(100, update);
|
||||
updating = true;
|
||||
}
|
||||
}
|
||||
|
||||
function update() {
|
||||
updating = false;
|
||||
for (let u of Object.values(users)) {
|
||||
user.position.y++;
|
||||
updating = true;
|
||||
}
|
||||
broadcastUsers();
|
||||
if (updating) {
|
||||
setTimeout(100, update);
|
||||
}
|
||||
}
|
||||
|
||||
function initializeTerrain() {
|
||||
for (let i = 0; i < terrain.length; i++) {
|
||||
terrain[i] = 32;
|
||||
}
|
||||
}
|
||||
|
||||
function broadcastUsers() {
|
||||
core.broadcast({
|
||||
users: Object.keys(users).map(x => ({user: x, position: users[x].position, angle: users[x].angle})),
|
||||
terrain: terrain,
|
||||
});
|
||||
}
|
||||
|
||||
function placeNewUser() {
|
||||
let positions = Object.keys(users).map(x => users[x].position.x);
|
||||
var best = 128 / 2;
|
||||
var bestDistance = -1;
|
||||
if (positions.length) {
|
||||
for (var i = 10; i < 118; i++) {
|
||||
var thisDistance = Math.min.apply(null, positions.map(x => Math.abs(i - x)));
|
||||
if (thisDistance > bestDistance) {
|
||||
bestDistance = thisDistance;
|
||||
best = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
return {x: best, y: 10, d: bestDistance};
|
||||
}
|
||||
|
||||
initializeTerrain();
|
||||
|
||||
core.register("onMessage", function(sender, message) {
|
||||
if (message.ready) {
|
||||
users[sender.index] = {
|
||||
user: sender,
|
||||
angle: 0,
|
||||
velocity: 100,
|
||||
position: placeNewUser(),
|
||||
};
|
||||
broadcastUsers();
|
||||
startUpdating();
|
||||
} else if (message.button) {
|
||||
switch (message.button) {
|
||||
case "<":
|
||||
users[sender.index].angle = Math.round(Math.max(users[sender.index].angle - 5.0, 0.0));
|
||||
break;
|
||||
case ">":
|
||||
users[sender.index].angle = Math.round(Math.min(users[sender.index].angle + 5.0, 180.0));
|
||||
break;
|
||||
case "^":
|
||||
users[sender.index].velocity++;
|
||||
break;
|
||||
case "v":
|
||||
users[sender.index].velocity--;
|
||||
break;
|
||||
}
|
||||
broadcastUsers();
|
||||
}
|
||||
});
|
||||
|
||||
core.register("onSessionEnd", function(user) {
|
||||
delete users[user.index];
|
||||
broadcastUsers();
|
||||
});
|
||||
}
|
Reference in New Issue
Block a user