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:
936
packages/cory/ldjam34/ldjam34.js
Normal file
936
packages/cory/ldjam34/ldjam34.js
Normal file
@ -0,0 +1,936 @@
|
||||
imports.terminal.print({iframe: `
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>become a game developer in 60 seconds</title>
|
||||
<script language="javascript">
|
||||
"use strict";
|
||||
|
||||
function ImageEditor() {
|
||||
this.kWidth = 256;
|
||||
this.kHeight = 256;
|
||||
this.kTop = 30;
|
||||
this.kLeft = 640 / 2 - this.kWidth / 2;
|
||||
this.kSpriteSize = 8;
|
||||
this.image = new Array(this.kSpriteSize * this.kSpriteSize);
|
||||
for (var i = 0; i < this.kSpriteSize * this.kSpriteSize; i++) {
|
||||
this.image[i] = 0;
|
||||
}
|
||||
this.pixelsFilled = 0;
|
||||
return this;
|
||||
}
|
||||
|
||||
ImageEditor.prototype.update = function() {
|
||||
if (this.title) {
|
||||
var fontSize = 16;
|
||||
gContext.font = 'bold ' + fontSize + 'px courier new';
|
||||
gContext.fillStyle = '#fff';
|
||||
gContext.fillText(this.title, 640 / 2 - gContext.measureText(this.title).width / 2, fontSize);
|
||||
}
|
||||
for (var i = 0; i < this.kSpriteSize; i++) {
|
||||
for (var j = 0; j < this.kSpriteSize; j++) {
|
||||
var p = j * this.kSpriteSize + i;
|
||||
if (this.pixelsFilled > p) {
|
||||
gContext.fillStyle = this.image[p] ? '#fff' : '#000';
|
||||
gContext.fillRect(
|
||||
this.kLeft + (i * this.kWidth / this.kSpriteSize),
|
||||
this.kTop + (j * this.kHeight / this.kSpriteSize),
|
||||
this.kWidth / this.kSpriteSize,
|
||||
this.kHeight / this.kSpriteSize);
|
||||
} else if (this.pixelsFilled == p) {
|
||||
gContext.fillStyle = pulseColor();
|
||||
gContext.fillRect(
|
||||
this.kLeft + (i * this.kWidth / this.kSpriteSize),
|
||||
this.kTop + (j * this.kHeight / this.kSpriteSize),
|
||||
this.kWidth / this.kSpriteSize,
|
||||
this.kHeight / this.kSpriteSize);
|
||||
} else {
|
||||
gContext.strokeStyle = '#fff';
|
||||
gContext.strokeRect(
|
||||
this.kLeft + (i * this.kWidth / this.kSpriteSize),
|
||||
this.kTop + (j * this.kHeight / this.kSpriteSize),
|
||||
this.kWidth / this.kSpriteSize,
|
||||
this.kHeight / this.kSpriteSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this.suggested) {
|
||||
var fontSize = 16;
|
||||
gContext.font = fontSize + 'px courier new';
|
||||
gContext.fillStyle = '#fff';
|
||||
gContext.fillText('suggested: ' + this.suggested.substring(this.pixelsFilled, this.pixelsFilled + 8), 10, this.kTop + this.kHeight + 2 * fontSize);
|
||||
}
|
||||
|
||||
if (gKeyPressed['0']) {
|
||||
this.image[this.pixelsFilled++] = 0;
|
||||
} else if (gKeyPressed['1']) {
|
||||
this.image[this.pixelsFilled++] = 1;
|
||||
}
|
||||
|
||||
if (this.pixelsFilled == this.kSpriteSize * this.kSpriteSize && this.completed) {
|
||||
var image = [];
|
||||
for (var i = 0; i < this.kSpriteSize; i++) {
|
||||
var line = '';
|
||||
for (var j = 0; j < this.kSpriteSize; j++) {
|
||||
line += this.image[i * this.kSpriteSize + j] ? '1' : '0';
|
||||
}
|
||||
image.push(line);
|
||||
}
|
||||
this.completed(makeImageData(image, 16));
|
||||
}
|
||||
}
|
||||
|
||||
"use strict";
|
||||
|
||||
function SoundEditor() {
|
||||
this.start = true;
|
||||
this.data = [null, null, null];
|
||||
this.downTime = null;
|
||||
this.part = 0;
|
||||
return this;
|
||||
};
|
||||
|
||||
SoundEditor.prototype.update = function() {
|
||||
if (this.start && (gKeyDown['0'] || gKeyDown['1'])) {
|
||||
return;
|
||||
}
|
||||
this.start = false;
|
||||
var min = [20, 20, 0.001];
|
||||
var max = [20000, 20000, 1.0];
|
||||
|
||||
var fontSize = 16;
|
||||
gContext.font = fontSize + 'px courier new';
|
||||
gContext.fillStyle = '#fff';
|
||||
gContext.fillText("start frequency", 1.5 * 640 / 7 - gContext.measureText('start frequency').width / 2, 2 * fontSize);
|
||||
gContext.fillText("end frequency", 3.5 * 640 / 7 - gContext.measureText('end frequency').width / 2, 2 * fontSize);
|
||||
gContext.fillText("duration", 5.5 * 640 / 7 - gContext.measureText('duration').width / 2, 2 * fontSize);
|
||||
|
||||
for (var i = 0; i < this.data.length; i++) {
|
||||
var kHeight = 240;
|
||||
gContext.strokeStyle = '#fff';
|
||||
gContext.strokeRect((2 * i + 1) * 640 / 7, 3 * fontSize, 640 / 7, kHeight);
|
||||
if (this.data[i] != null) {
|
||||
var v = (this.data[i] - min[i]) / (max[i] - min[i]);
|
||||
gContext.fillStyle = '#fff';
|
||||
gContext.fillRect((2 * i + 1) * 640 / 7, 3 * fontSize + kHeight * (1 - v), 640 / 7, kHeight * v);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.part < this.data.length) {
|
||||
if (gKeyPressed['0']) {
|
||||
this.data[this.part] = Math.random() * (max[this.part] - min[this.part]) + min[this.part];
|
||||
this.part++;
|
||||
} else {
|
||||
var now = Date.now();
|
||||
if (!this.downTime && gKeyDown['1']) {
|
||||
this.downTime = now;
|
||||
}
|
||||
if (this.downTime) {
|
||||
var v = Math.min((now - this.downTime) / 1000.0, 1.0);
|
||||
this.data[this.part] = v * (max[this.part] - min[this.part]) + min[this.part];
|
||||
if (!gKeyDown['1'] || (now - this.downTime) / 1000.0 > 1.0) {
|
||||
this.part++;
|
||||
this.downTime = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
var names = ['start frequency', 'end frequency', 'duration'];
|
||||
gContext.fillStyle = '#fff';
|
||||
gContext.font = 'bold ' + fontSize + 'px courier new';
|
||||
gContext.fillText("set " + names[this.part], 640 / 2 - gContext.measureText('set ' + names[this.part]).width / 2, 320);
|
||||
gContext.font = fontSize + 'px courier new';
|
||||
gContext.fillText("1 hold to set", 640 / 2 - gContext.measureText('1 hold to set').width / 2, 320 + fontSize);
|
||||
gContext.fillText("0 random", 640 / 2 - gContext.measureText('0 random').width / 2, 320 + fontSize * 2);
|
||||
} else {
|
||||
gContext.fillStyle = '#fff';
|
||||
gContext.fillText("1 hear it", 640 / 2 - gContext.measureText('1 hear it').width / 2, 320 + fontSize);
|
||||
gContext.fillText("0 done", 640 / 2 - gContext.measureText('0 done').width / 2, 320 + fontSize * 2);
|
||||
if (gKeyPressed['1']) {
|
||||
tone(this.data[0], this.data[1], this.data[2]);
|
||||
}
|
||||
if (gKeyPressed['0'] && this.completed) {
|
||||
this.completed(this.data);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
"use strict";
|
||||
|
||||
function Game(options) {
|
||||
this.options = {};
|
||||
for (var k in options) {
|
||||
this.options[k] = options[k];
|
||||
}
|
||||
this.velocity = [0, 0];
|
||||
this.position = [0, 0];
|
||||
this.gone = {};
|
||||
this.camera = 10;
|
||||
this.projectile = null;
|
||||
this.gameOver = false;
|
||||
this.start = true;
|
||||
this.countdown = 3;
|
||||
|
||||
this.points = 0;
|
||||
this.kills = 0;
|
||||
|
||||
document.location.hash = store(gGame);
|
||||
document.getElementById("share").href = document.location.href;
|
||||
|
||||
if (this.options.button0 == undefined) {
|
||||
this.options.button0 = 2;
|
||||
}
|
||||
|
||||
if (this.options.button1 == undefined) {
|
||||
this.options.button1 = 0;
|
||||
}
|
||||
|
||||
if (!this.options.score) {
|
||||
this.options.score = 1;
|
||||
}
|
||||
|
||||
if (!this.options.player) {
|
||||
this.options.player = makeImageData([
|
||||
'11111111',
|
||||
'10000001',
|
||||
'10100101',
|
||||
'10000001',
|
||||
'10100101',
|
||||
'10111101',
|
||||
'10000001',
|
||||
'11111111',
|
||||
], 16);
|
||||
}
|
||||
|
||||
if (!this.options.enemy) {
|
||||
this.options.enemy = makeImageData([
|
||||
'11111111',
|
||||
'10000001',
|
||||
'10100101',
|
||||
'10000001',
|
||||
'10111101',
|
||||
'10100101',
|
||||
'10000001',
|
||||
'11111111',
|
||||
], 16);
|
||||
}
|
||||
|
||||
if (!this.options.point) {
|
||||
this.options.point = makeImageData([
|
||||
'00000000',
|
||||
'00000000',
|
||||
'00011000',
|
||||
'00100100',
|
||||
'01011010',
|
||||
'01010010',
|
||||
'00100100',
|
||||
'00011000',
|
||||
], 16);
|
||||
}
|
||||
|
||||
this.background = makeImageData([
|
||||
'1110',
|
||||
'0101',
|
||||
'0011',
|
||||
'1001',
|
||||
], 16);
|
||||
|
||||
this.timer = [
|
||||
makeImageData([
|
||||
'110',
|
||||
'010',
|
||||
'010',
|
||||
'010',
|
||||
'111',
|
||||
], 16),
|
||||
makeImageData([
|
||||
'111',
|
||||
'001',
|
||||
'111',
|
||||
'100',
|
||||
'111',
|
||||
], 16),
|
||||
makeImageData([
|
||||
'111',
|
||||
'001',
|
||||
'011',
|
||||
'001',
|
||||
'111',
|
||||
], 16)
|
||||
];
|
||||
|
||||
if (!this.options.level) {
|
||||
this.options.level = '00102';
|
||||
} else {
|
||||
this.options.level = '0' + this.options.level;
|
||||
}
|
||||
|
||||
if (!this.options.jump) {
|
||||
this.options.jump = [1000, 3000, 0.25];
|
||||
}
|
||||
|
||||
if (!this.options.shoot) {
|
||||
this.options.shoot = [300, 300, 0.1];
|
||||
}
|
||||
|
||||
this.collect = [this.options.shoot[0], this.options.jump[1], (this.options.shoot[2] + this.options.jump[2]) / 2];
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
Game.prototype.update = function() {
|
||||
if (this.start && (gKeyDown['0'] || gKeyDown['1'])) {
|
||||
return;
|
||||
}
|
||||
this.start = false;
|
||||
|
||||
if (this.countdown > 0) {
|
||||
this.countdown -= gTimeDelta / 1000;
|
||||
if (this.countdown > 0) {
|
||||
var i = Math.min(Math.floor(this.countdown), 2);
|
||||
gContext.putImageData(this.timer[i], 640 / 2 - 16 * 3, 480 / 2 - 16 * 3);
|
||||
} else {
|
||||
this.countdown = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
for (var i = 0; i < this.options.level.length; i++) {
|
||||
if (!this.gone[i]) {
|
||||
var c = this.options.level.charAt(i);
|
||||
if (c == '1') {
|
||||
gContext.putImageData(this.options.enemy, i * 16 * 8 * 2 - this.position[0] + this.camera, 240);
|
||||
} else if (c == '2') {
|
||||
gContext.putImageData(this.options.point, i * 16 * 8 * 2 - this.position[0] + this.camera, 240);
|
||||
}
|
||||
}
|
||||
}
|
||||
var tile = Math.round(this.position[0] / (16 * 8 * 2));
|
||||
if (!this.gone[tile]) {
|
||||
var hit = this.options.level.charAt(tile);
|
||||
if (hit == '1' && this.position[1] <= 16 * 8) {
|
||||
if (this.velocity[1] < 0) {
|
||||
this.gone[tile] = true;
|
||||
this.velocity[1] = 1.5;
|
||||
this.kills++;
|
||||
tone(this.collect[1], this.collect[0], this.collect[2]);
|
||||
} else {
|
||||
this.gameOver = true;
|
||||
this.gone[tile] = true;
|
||||
}
|
||||
} else if (hit == '2' && this.position[1] <= 16 * 8) {
|
||||
tone(this.collect[0], this.collect[1], this.collect[2]);
|
||||
this.points += this.options.score;
|
||||
this.gone[tile] = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.projectile != null) {
|
||||
gContext.fillStyle = '#fff';
|
||||
var screenPosition = this.projectile - this.position[0] + this.camera;
|
||||
gContext.fillRect(screenPosition, 240 + 16 * 8 / 2, 16, 16);
|
||||
this.projectile += gTimeDelta;
|
||||
var p = Math.floor(this.projectile / (16 * 8 * 2));
|
||||
var hit = this.options.level.charAt(p);
|
||||
if (hit == '1' && !this.gone[p]) {
|
||||
this.gone[p] = true;
|
||||
this.projectile = null;
|
||||
}
|
||||
if (screenPosition > 640) {
|
||||
this.projectile = null;
|
||||
}
|
||||
}
|
||||
|
||||
gContext.putImageData(this.options.player, this.camera, 240 - this.position[1]);
|
||||
this.position[0] += this.velocity[0] * gTimeDelta;
|
||||
this.position[1] += this.velocity[1] * gTimeDelta;
|
||||
this.velocity[1] -= 0.005 * gTimeDelta;
|
||||
if (this.position[1] <= 0 && !this.gameOver) {
|
||||
this.position[1] = 0;
|
||||
this.velocity[1] = 0;
|
||||
}
|
||||
|
||||
if (this.gameOver) {
|
||||
this.position[0] -= 2 * gTimeDelta;
|
||||
if (this.position[1] > -480) {
|
||||
this.position[1] -= gTimeDelta * 0.1;
|
||||
} else {
|
||||
var fontSize = 16;
|
||||
gContext.fillStyle = '#fff';
|
||||
gContext.font = 'bold ' + fontSize + 'px courier new';
|
||||
gContext.fillText('game over', 640 / 2 - gContext.measureText('game over').width / 2, 240 - 2 * fontSize);
|
||||
gContext.font = fontSize + 'px courier new';
|
||||
gContext.fillText('1 retry', 640 / 2 - gContext.measureText('1 retry').width / 2, 240 + 16 * 8 + 2 * fontSize);
|
||||
gContext.fillText('0 back', 640 / 2 - gContext.measureText('1 retry').width / 2, 240 + 16 * 8 + 3 * fontSize);
|
||||
if (gKeyPressed['1'] && this.completed) {
|
||||
this.completed(1);
|
||||
}
|
||||
if (gKeyPressed['0'] && this.completed) {
|
||||
this.completed(0);
|
||||
}
|
||||
}
|
||||
} else if (tile > this.options.level.length) {
|
||||
var targetCamera = 640 / 2 - (16 * 8) / 2;
|
||||
if (this.camera < targetCamera) {
|
||||
this.camera += gTimeDelta / 5;
|
||||
} else {
|
||||
this.camera = targetCamera;
|
||||
if (this.velocity[1] == 0) {
|
||||
this.velocity[1] = 1.5;
|
||||
}
|
||||
var fontSize = 16;
|
||||
gContext.font = fontSize + 'px courier new';
|
||||
gContext.fillStyle = '#fff';
|
||||
gContext.fillText('1 again', 640 / 2 - gContext.measureText('1 again').width / 2, 240 + 16 * 8 + 2 * fontSize);
|
||||
gContext.fillText('0 back', 640 / 2 - gContext.measureText('1 again').width / 2, 240 + 16 * 8 + 3 * fontSize);
|
||||
|
||||
var results = '';
|
||||
if (this.points) {
|
||||
if (results.length) {
|
||||
results += ', ';
|
||||
}
|
||||
results += this.points + (this.points == 1 ? ' point' : ' points');
|
||||
}
|
||||
if (this.kills) {
|
||||
if (results.length) {
|
||||
results += ', ';
|
||||
}
|
||||
results += this.kills + (this.kills == 1 ? ' enemy vanquished' : ' enemies vanquished');
|
||||
}
|
||||
gContext.fillText(results, 640 / 2 - gContext.measureText(results).width / 2, 240 + 16 * 8 + 5 * fontSize);
|
||||
if (gKeyPressed['1'] && this.completed) {
|
||||
this.completed(1);
|
||||
}
|
||||
if (gKeyPressed['0'] && this.completed) {
|
||||
this.completed(0);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (var i = 0; i < 12; i++) {
|
||||
for (var j = 0; j < 2; j++) {
|
||||
gContext.putImageData(this.background, i * 16 * 4 - this.position[0] % (16 * 4), 240 + 16 * 8 + j * 16 * 4);
|
||||
}
|
||||
}
|
||||
var jump = this.velocity[1] == 0 &&
|
||||
(this.options.button0 == 0 && gKeyDown['0'] ||
|
||||
this.options.button1 == 0 && gKeyDown['1']);
|
||||
var shoot = this.projectile == null &&
|
||||
(this.options.button0 == 1 && gKeyDown['0'] ||
|
||||
this.options.button1 == 1 && gKeyDown['1']);
|
||||
var move = this.projectile == null &&
|
||||
(this.options.button0 == 2 && gKeyDown['0'] ||
|
||||
this.options.button1 == 2 && gKeyDown['1'] ||
|
||||
this.options.button0 != 2 && this.options.button1 != 2);
|
||||
if (jump) {
|
||||
this.velocity[1] = 1.5;
|
||||
tone(this.options.jump[0], this.options.jump[1], this.options.jump[2]);
|
||||
}
|
||||
if (shoot) {
|
||||
this.projectile = this.position[0];
|
||||
tone(this.options.shoot[0], this.options.shoot[1], this.options.shoot[2]);
|
||||
}
|
||||
if (move) {
|
||||
this.velocity[0] = 1;
|
||||
} else {
|
||||
this.velocity[0] = 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function packImage(imageData) {
|
||||
var result = '';
|
||||
for (var i = 0; i < imageData.width / 16; i++) {
|
||||
for (var j = 0; j < imageData.height / 16; j++) {
|
||||
result += (imageData.data[j * imageData.width * 4 * 16 + i * 4 * 16] ? '1' : '0');
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function unpackImageData(data) {
|
||||
var pixels = [];
|
||||
console.debug(data);
|
||||
for (var i = 0; i < 8; i++) {
|
||||
var line = '';
|
||||
for (var j = 0; j < 8; j++) {
|
||||
line += data.charAt(j * 8 + i);
|
||||
}
|
||||
pixels.push(line);
|
||||
}
|
||||
return makeImageData(pixels, 16);
|
||||
}
|
||||
|
||||
function store(game) {
|
||||
var simple = {};
|
||||
for (var k in game) {
|
||||
if (game[k] instanceof ImageData) {
|
||||
simple[k] = packImage(game[k]);
|
||||
} else {
|
||||
simple[k] = game[k];
|
||||
}
|
||||
}
|
||||
return JSON.stringify(simple);
|
||||
};
|
||||
|
||||
function load(game) {
|
||||
var simple = JSON.parse(game);
|
||||
for (var k in simple) {
|
||||
if (['player', 'enemy'].indexOf(k) != -1) {
|
||||
simple[k] = unpackImageData(simple[k]);
|
||||
}
|
||||
}
|
||||
return simple;
|
||||
};
|
||||
|
||||
"use strict";
|
||||
|
||||
var gAudio = null;
|
||||
var gGain = null;
|
||||
|
||||
function tone(frequency0, frequency1, duration) {
|
||||
var Context = window.AudioContext || window.webkitAudioContext || window.mozAudioContext || window.oAudioContext || window.msAudioContext;
|
||||
if (!gAudio && Context) {
|
||||
gAudio = new Context();
|
||||
}
|
||||
if (!gGain && gAudio) {
|
||||
gGain = gAudio.createGain();
|
||||
gGain.connect(gAudio.destination);
|
||||
gGain.gain.value = 0.15;
|
||||
}
|
||||
var now = gAudio.currentTime;
|
||||
var oscillator = gAudio.createOscillator();
|
||||
oscillator.frequency.setValueAtTime(frequency0, now);
|
||||
oscillator.frequency.linearRampToValueAtTime(frequency1, now + duration);
|
||||
oscillator.type = 'sine';
|
||||
oscillator.connect(gGain);
|
||||
oscillator.start(now);
|
||||
oscillator.stop(gAudio.currentTime + duration);
|
||||
}
|
||||
|
||||
"use strict";
|
||||
|
||||
function Menu(configuration) {
|
||||
this.title = configuration.title;
|
||||
this.options = configuration.options;
|
||||
this.footer = configuration.footer;
|
||||
this.image = configuration.image;
|
||||
this.bitsNeeded = 0;
|
||||
this.fontSize = 16;
|
||||
this.bits = '';
|
||||
var count = this.options.length;
|
||||
while (count > 1) {
|
||||
this.bitsNeeded += 1;
|
||||
count /= 2;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
Menu.prototype.update = function() {
|
||||
gContext.font = 'bold ' + this.fontSize + 'px courier new';
|
||||
gContext.fillStyle = '#fff';
|
||||
gContext.fillText(this.title, 640 / 2 - gContext.measureText(this.title).width / 2, this.fontSize);
|
||||
|
||||
var maxWidth = 0;
|
||||
for (var i = 0; i < this.options.length; i++) {
|
||||
maxWidth = Math.max(maxWidth, gContext.measureText(this.options[i]).width);
|
||||
}
|
||||
|
||||
for (var i = 0; i < this.options.length; i++) {
|
||||
gContext.font = this.fontSize + 'px courier new';
|
||||
gContext.fillStyle = '#fff';
|
||||
gContext.fillText(bits(i, this.bitsNeeded) + ' ' + this.options[i], 640 / 2 - maxWidth / 2, this.fontSize * (i + 3));
|
||||
}
|
||||
gContext.font = this.fontSize + 'px courier new';
|
||||
gContext.fillStyle = '#fff';
|
||||
var text = '';
|
||||
for (var i = 0; i < this.bitsNeeded; i++) {
|
||||
text += '0';
|
||||
}
|
||||
gContext.fillText(this.bits, 640 / 2 - maxWidth / 2, this.fontSize * (this.options.length + 4));
|
||||
gContext.fillStyle = blinkColor();
|
||||
gContext.fillRect(640 / 2 - maxWidth / 2 + gContext.measureText(this.bits).width, this.fontSize * (this.options.length + 3), 10, this.fontSize);
|
||||
|
||||
if (this.footer) {
|
||||
gContext.font = this.fontSize + 'px courier new';
|
||||
gContext.fillStyle = '#fff';
|
||||
gContext.fillText(this.footer, 640 / 2 - gContext.measureText(this.footer).width / 2, 480 - this.fontSize);
|
||||
}
|
||||
|
||||
if (this.image) {
|
||||
gContext.putImageData(this.image, 640 / 2 - this.image.width / 2, 480 / 2 - this.image.height / 2);
|
||||
}
|
||||
|
||||
if (gKeyPressed['0']) {
|
||||
this.bits += '0';
|
||||
} else if (gKeyPressed['1']) {
|
||||
this.bits += '1';
|
||||
}
|
||||
|
||||
if (this.bits.length >= this.bitsNeeded && this.completed) {
|
||||
var result = 0;
|
||||
for (var i = 0; i < this.bits.length; i++) {
|
||||
result *= 2;
|
||||
if (this.bits.charAt(i) == '1') {
|
||||
result |= 1;
|
||||
}
|
||||
}
|
||||
this.completed(result);
|
||||
}
|
||||
}
|
||||
|
||||
"use strict";
|
||||
var gContext;
|
||||
var gKeyDown = {}
|
||||
var gKeyPressed = {}
|
||||
var gMode;
|
||||
var gTimeDelta = 0;
|
||||
var gLastFrame = Date.now();
|
||||
var gTimer;
|
||||
|
||||
var gGame = {};
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
var canvas = document.getElementById("canvas");
|
||||
gContext = canvas.getContext("2d");
|
||||
|
||||
if (document.location.hash) {
|
||||
try {
|
||||
gGame = load(document.location.hash.substring(1));
|
||||
} catch (e) {
|
||||
console.debug(e);
|
||||
}
|
||||
}
|
||||
|
||||
document.body.onkeydown = function(event) {
|
||||
if (event.which == 48 || event.which == 96) {
|
||||
gKeyDown['0'] = true;
|
||||
}
|
||||
if (event.which == 49 || event.which == 97) {
|
||||
gKeyDown['1'] = true;
|
||||
}
|
||||
}
|
||||
|
||||
document.body.onkeyup = function(event) {
|
||||
if (event.which == 48 || event.which == 96) {
|
||||
gKeyDown['0'] = false;
|
||||
}
|
||||
if (event.which == 49 || event.which == 97) {
|
||||
gKeyDown['1'] = false;
|
||||
}
|
||||
}
|
||||
|
||||
document.body.onkeypress = function(event) {
|
||||
if (event.which == 48 || event.which == 96) {
|
||||
gKeyPressed['0'] = true;
|
||||
}
|
||||
if (event.which == 49 || event.which == 97) {
|
||||
gKeyPressed['1'] = true;
|
||||
}
|
||||
if ((event.which == 48 || event.which == 49 || event.which == 96 || event.which == 97) &&
|
||||
!(gMode instanceof Game) &&
|
||||
!(gMode instanceof SoundEditor)) {
|
||||
|
||||
var min = 40;
|
||||
var max = 2000;
|
||||
var f = Math.random() * (max - min) + min;
|
||||
tone(f, f, 0.1);
|
||||
}
|
||||
}
|
||||
|
||||
makeMainMenu();
|
||||
window.requestAnimationFrame(update);
|
||||
});
|
||||
|
||||
function makeMainMenu() {
|
||||
var menu = new Menu({
|
||||
title: 'become a game developer in 60 seconds',
|
||||
options: ['create', 'test'],
|
||||
footer: 'buttons: 0 and 1',
|
||||
image: makeImageData([
|
||||
'11001110110011101100111',
|
||||
'01001010010010100100101',
|
||||
'01001010010010100100101',
|
||||
'01001010010010100100101',
|
||||
'11101110111011101110111',
|
||||
'00000000000000000000000',
|
||||
'00111100100100010111000',
|
||||
'00100001010110110100000',
|
||||
'00101101110101010110000',
|
||||
'00100101010100010100000',
|
||||
'00111101010100010111000',
|
||||
], 16)}
|
||||
);
|
||||
menu.completed = function(result) {
|
||||
if (result == 0) {
|
||||
gTimer = 60;
|
||||
makeCreateMenu();
|
||||
} else {
|
||||
gTimer = undefined;
|
||||
makeGame();
|
||||
}
|
||||
};
|
||||
gMode = menu;
|
||||
}
|
||||
|
||||
function makeCreateMenu() {
|
||||
var menu = new Menu({title: 'make game', options: [
|
||||
'[' + (gGame.player ? 'x' : ' ') + '] player',
|
||||
'[' + (gGame.enemy ? 'x' : ' ') + '] enemy',
|
||||
'[' + (gGame.score ? 'x' : ' ') + '] score',
|
||||
'[' + (gGame.jump ? 'x' : ' ') + '] jump',
|
||||
'[' + (gGame.shoot ? 'x' : ' ') + '] shoot',
|
||||
'[' + (gGame.button0 != undefined ? 'x' : ' ') + '] buttons',
|
||||
'[' + (gGame.level ? 'x' : ' ') + '] level',
|
||||
' ship it',
|
||||
]});
|
||||
menu.completed = function(result) {
|
||||
if (result == 0) {
|
||||
makeImageEditor('player',
|
||||
'00111100'+
|
||||
'00111100'+
|
||||
'00111100'+
|
||||
'10011001'+
|
||||
'11111111'+
|
||||
'00011000'+
|
||||
'00100100'+
|
||||
'00100100');
|
||||
} else if (result == 1) {
|
||||
makeImageEditor('enemy',
|
||||
'00111100'+
|
||||
'01000010'+
|
||||
'10000001'+
|
||||
'10100101'+
|
||||
'10000001'+
|
||||
'11011011'+
|
||||
'01011010'+
|
||||
'01111110');
|
||||
} else if (result == 2) {
|
||||
gGame.score = 1;
|
||||
makeScoreEditor();
|
||||
} else if (result == 3) {
|
||||
makeSoundEditor('jump');
|
||||
} else if (result == 4) {
|
||||
makeSoundEditor('shoot');
|
||||
} else if (result == 5) {
|
||||
makeButtonsMenu();
|
||||
} else if (result == 6) {
|
||||
gGame.level = '';
|
||||
makeLevelEditor();
|
||||
} else if (result == 7) {
|
||||
gTimer = undefined;
|
||||
makeGame();
|
||||
}
|
||||
}
|
||||
gMode = menu;
|
||||
}
|
||||
|
||||
function makeImageEditor(what, suggested) {
|
||||
var editor = new ImageEditor();
|
||||
editor.suggested = suggested;
|
||||
editor.title = 'draw ' + what + ' by pressing 1 and 0';
|
||||
editor.completed = function(result) {
|
||||
gGame[what] = result;
|
||||
makeCreateMenu();
|
||||
};
|
||||
gMode = editor;
|
||||
}
|
||||
|
||||
function makeSoundEditor(what) {
|
||||
var editor = new SoundEditor();
|
||||
editor.completed = function(result) {
|
||||
gGame[what] = result;
|
||||
makeCreateMenu();
|
||||
};
|
||||
gMode = editor;
|
||||
}
|
||||
|
||||
function makeButtonMenu(button) {
|
||||
var menu = new Menu({title: 'what does ' + button + ' do?', options: [
|
||||
'jump',
|
||||
'shoot',
|
||||
'move',
|
||||
'nothing',
|
||||
]});
|
||||
return menu;
|
||||
}
|
||||
|
||||
function makeButtonsMenu(button) {
|
||||
var menu = makeButtonMenu('0');
|
||||
menu.completed = function(result) {
|
||||
gGame['button0'] = result;
|
||||
menu = makeButtonMenu('1');
|
||||
menu.completed = function(result) {
|
||||
gGame['button1'] = result;
|
||||
makeCreateMenu();
|
||||
}
|
||||
gMode = menu;
|
||||
};
|
||||
gMode = menu;
|
||||
}
|
||||
|
||||
function update() {
|
||||
gContext.fillStyle = '#000';
|
||||
gContext.fillRect(0, 0, 640, 480);
|
||||
|
||||
var now = Date.now();
|
||||
gTimeDelta = now - gLastFrame;
|
||||
gLastFrame = now;
|
||||
|
||||
if (gTimer != undefined) {
|
||||
if (gTimer > 0) {
|
||||
gTimer -= gTimeDelta / 1000;
|
||||
} else {
|
||||
gTimer = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (gMode) {
|
||||
gMode.update();
|
||||
} else {
|
||||
gContext.fillStyle = pulseColor();
|
||||
gContext.fillRect(0, 0, 640, 480);
|
||||
}
|
||||
|
||||
for (var i in gKeyPressed) {
|
||||
gKeyPressed[i] = false;
|
||||
}
|
||||
|
||||
if (!(gMode instanceof Game) && gTimer !== undefined) {
|
||||
var fontSize = 16;
|
||||
gContext.font = 'bold ' + fontSize + 'px courier new';
|
||||
gContext.fillStyle = '#fff';
|
||||
var remaining = Math.round(gTimer);
|
||||
if (gTimer <= 0) {
|
||||
remaining = 'OUT OF TIME! SHIP IT! OUT OF TIME! SHIP IT! OUT OF TIME! 111!';
|
||||
gContext.fillStyle = pulseColor();
|
||||
}
|
||||
gContext.fillText(remaining, 640 - gContext.measureText(remaining).width - 1, 480 - 1);
|
||||
}
|
||||
|
||||
window.requestAnimationFrame(update);
|
||||
}
|
||||
|
||||
function pulseColor() {
|
||||
var pulse = (Math.sin(15 * Date.now() / 1000) + 1) / 2;
|
||||
var value = Math.floor(255 * pulse).toString();
|
||||
return 'rgb(' + value + ',' + value + ',' + value + ')';
|
||||
}
|
||||
|
||||
function blinkColor() {
|
||||
var blink = (Math.floor(4 * Date.now() / 1000) & 1) == 0;
|
||||
var value = Math.floor(255 * blink).toString();
|
||||
return 'rgb(' + value + ',' + value + ',' + value + ')';
|
||||
}
|
||||
|
||||
function bits(value, count) {
|
||||
var result = '';
|
||||
for (var i = 0; i < count; i++) {
|
||||
if ((value & (1 << i)) != 0) {
|
||||
result = '1' + result;
|
||||
} else {
|
||||
result = '0' + result;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function makeImageData(pixels, scale) {
|
||||
var height = pixels.length;
|
||||
var width = pixels[0].length;
|
||||
|
||||
var data = gContext.createImageData(width * scale, height * scale);
|
||||
for (var i = 0; i < width * scale; i++) {
|
||||
for (var j = 0; j < height * scale; j++) {
|
||||
var v = pixels[Math.floor(j / scale)].charAt(Math.floor(i / scale)) == '1';
|
||||
data.data[4 * (j * width * scale + i) + 0] = v ? 255 : 0;
|
||||
data.data[4 * (j * width * scale + i) + 1] = v ? 255 : 0;
|
||||
data.data[4 * (j * width * scale + i) + 2] = v ? 255 : 0;
|
||||
data.data[4 * (j * width * scale + i) + 3] = 255;
|
||||
}
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
function makeGame() {
|
||||
var game = new Game(gGame);
|
||||
game.completed = function(result) {
|
||||
if (result == 1) {
|
||||
makeGame();
|
||||
} else {
|
||||
makeMainMenu();
|
||||
}
|
||||
};
|
||||
gMode = game;
|
||||
}
|
||||
|
||||
function makeLevelEditor() {
|
||||
var menu = new Menu({title: 'choose object for location ' + gGame.level.length, options: [
|
||||
'nothing',
|
||||
'enemy',
|
||||
'points',
|
||||
'finish',
|
||||
]});
|
||||
menu.completed = function(result) {
|
||||
if (result == 0) {
|
||||
gGame.level += '0';
|
||||
makeLevelEditor();
|
||||
} else if (result == 1) {
|
||||
gGame.level += '1';
|
||||
makeLevelEditor();
|
||||
} else if (result == 2) {
|
||||
gGame.level += '2';
|
||||
makeLevelEditor();
|
||||
} else if (result == 3) {
|
||||
makeCreateMenu();
|
||||
}
|
||||
};
|
||||
gMode = menu;
|
||||
}
|
||||
|
||||
function makeScoreEditor() {
|
||||
var menu = new Menu({title: 'how many points?: ' + gGame.score, options: [
|
||||
'more',
|
||||
'done',
|
||||
]});
|
||||
menu.completed = function(result) {
|
||||
if (result == 0) {
|
||||
gGame.score *= 10;
|
||||
if (gGame.score < 10000000000000000000) {
|
||||
makeScoreEditor();
|
||||
} else {
|
||||
makeCreateMenu();
|
||||
}
|
||||
} else if (result == 1) {
|
||||
makeCreateMenu();
|
||||
}
|
||||
};
|
||||
gMode = menu;
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
body {
|
||||
background-color: #444;
|
||||
color: #fff;
|
||||
}
|
||||
canvas {
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
display: block;
|
||||
width: 640px;
|
||||
}
|
||||
#share {
|
||||
color: #fff;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<canvas id="canvas" width="640" height="480"></canvas>
|
||||
<div><a id="share" href="http://www.unprompted.com/ldjam/compo34/">share link, updated on test</a></div>
|
||||
</body>
|
||||
</html>
|
||||
`,
|
||||
width: 720,
|
||||
height: 512,
|
||||
});
|
Reference in New Issue
Block a user