This commit is contained in:
Ali Shakiba 2014-01-29 06:17:49 +03:30
Родитель 9e3f6cc3b2
Коммит 8b546433ca
7 изменённых файлов: 2665 добавлений и 11 удалений

Просмотреть файл

@ -8,13 +8,8 @@ O! is a JavaScript game so familiarity with JavaScript is required. It is also r
### Getting started
##### Download
Use git or the download button (on the right) to download the game source code.
Use git or the download button (on the right) to download the game source code. Dependencies are only [Cut.js](https://github.com/piqnt/cut.js) and [Extra.js](https://github.com/piqnt/extra.js) which are included.
##### Dependencies
Dependencies are only [Cut.js](https://github.com/piqnt/cut.js) and [Extra.js](https://github.com/piqnt/extra.js), you can download them using bower (`cd src` then `bower install`) or manually download them and update `src/index.html` to point to them.
##### Run
Open `src/index.html` with your browser, the game should start, if not check errors with your browser debugging utility.
### Graphics/Textures

Просмотреть файл

@ -11,12 +11,12 @@
</style>
</head><body>
<script src="bower_components/cutjs/cut-core.js"></script>
<script src="bower_components/cutjs/cut-mouse.js"></script>
<script src="bower_components/cutjs/cut-loader.js"></script>
<script src="js/cut-core.js"></script>
<script src="js/cut-mouse.js"></script>
<script src="js/cut-loader.js"></script>
<script src="bower_components/extrajs/pool.js"></script>
<script src="bower_components/extrajs/randomize.js"></script>
<script src="js/pool.js"></script>
<script src="js/randomize.js"></script>
<script src="polyfills.js"></script>
<script src="app.js"></script>

2074
src/js/cut-core.js Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

179
src/js/cut-loader.js Normal file
Просмотреть файл

@ -0,0 +1,179 @@
/*
* Cut.js
* Copyright (c) 2013-2014 Ali Shakiba, Piqnt LLC and other contributors
* Available under the MIT license
* @license
*/
DEBUG = (typeof DEBUG === 'undefined' || DEBUG) && console;
/**
* Default loader for web.
*/
window.addEventListener("load", function() {
DEBUG && console.log("On load.");
Cut.Loader.start();
}, false);
Cut.Loader = {
start : function() {
if (this.started) {
return;
}
this.started = true;
Cut.Loader.play();
},
play : function() {
this.played = true;
for (var i = this.loaders.length - 1; i >= 0; i--) {
this.roots.push(this.loaders[i]());
this.loaders.splice(i, 1);
}
},
pause : function() {
for (var i = this.loaders.length - 1; i >= 0; i--) {
this.roots[i].pause();
}
},
resume : function() {
for (var i = this.loaders.length - 1; i >= 0; i--) {
this.roots[i].resume();
}
},
loaders : [],
roots : [],
load : function(app, canvas) {
function loader() {
var context = null, full = false;
var width = 0, height = 0, ratio = 1;
DEBUG && console.log("Creating root...");
var root = Cut.root(function(root) {
context.setTransform(1, 0, 0, 1, 0, 0);
context.clearRect(0, 0, width, height);
root.render(context);
}, requestAnimationFrame);
if (!canvas) {
canvas = document.getElementById("cutjs");
}
if (!canvas) {
full = true;
DEBUG && console.log("Creating element...");
canvas = document.createElement("canvas");
canvas.style.position = "absolute";
var body = document.body;
body.insertBefore(canvas, body.firstChild);
}
DEBUG && console.log("Loading images...");
Cut.loadImages(function(src, handleComplete, handleError) {
var image = new Image();
DEBUG && console.log("Loading image: " + src);
image.onload = handleComplete;
image.onerror = handleError;
image.src = src;
return image;
}, init);
function init() {
DEBUG && console.log("Images loaded.");
context = canvas.getContext("2d");
var devicePixelRatio = window.devicePixelRatio || 1;
var backingStoreRatio = context.webkitBackingStorePixelRatio
|| context.mozBackingStorePixelRatio
|| context.msBackingStorePixelRatio
|| context.oBackingStorePixelRatio
|| context.backingStorePixelRatio || 1;
ratio = devicePixelRatio / backingStoreRatio;
canvas.resize = resize;
DEBUG && console.log("Loading...");
app(root, canvas);
resize();
window.addEventListener("resize", resize, false);
DEBUG && console.log("Start playing...");
root.start();
}
function resize() {
if (full) {
width = (window.innerWidth > 0 ? window.innerWidth : screen.width);
height = (window.innerHeight > 0 ? window.innerHeight : screen.height);
canvas.style.width = width + "px";
canvas.style.height = height + "px";
} else {
width = canvas.clientWidth;
height = canvas.clientHeight;
}
width *= ratio;
height *= ratio;
canvas.width = width;
canvas.height = height;
root.ratio = ratio;
DEBUG
&& console.log("Resize: " + width + " x " + height + " / " + ratio);
root.visit({
start : function(cut) {
var stop = true;
var listeners = cut.listeners("resize");
if (listeners) {
for (var l = 0; l < listeners.length; l++)
stop &= !listeners[l].call(cut, width, height);
}
return stop;
}
});
}
return root;
}
if (this.played) {
this.roots.push(loader());
} else {
this.loaders.push(loader);
}
}
};
!function() {
var vendors = [ 'ms', 'moz', 'webkit', 'o' ];
for (var v = 0; v < vendors.length && !window.requestAnimationFrame; v++) {
var vendor = vendors[v];
window.requestAnimationFrame = window[vendor + 'RequestAnimationFrame'];
window.cancelAnimationFrame = window[vendor + 'CancelAnimationFrame']
|| window[vendor + 'CancelRequestAnimationFrame'];
}
if (!window.requestAnimationFrame) {
var next = 0;
window.requestAnimationFrame = function(callback) {
var now = new Date().getTime();
next = Math.max(next + 16, now);
return window.setTimeout(function() {
callback(next);
}, next - now);
};
}
if (!window.cancelAnimationFrame) {
window.cancelAnimationFrame = function(id) {
clearTimeout(id);
};
}
}();

195
src/js/cut-mouse.js Normal file
Просмотреть файл

@ -0,0 +1,195 @@
/*
* Cut.js
* Copyright (c) 2013-2014 Ali Shakiba, Piqnt LLC and other contributors
* Available under the MIT license
* @license
*/
DEBUG = true || (typeof DEBUG === 'undefined' || DEBUG) && console;
Cut.Mouse = {
CLICK : "click",
START : "touchstart mousedown",
MOVE : "touchmove mousemove",
END : "touchend mouseup",
};
Cut.Mouse.subscribe = function(listener, elem, move) {
elem = elem || document;
var isTouchSupported = "ontouchstart" in window;
var CLICK = "click";
var START = isTouchSupported ? "touchstart" : "mousedown";
var MOVE = isTouchSupported ? "touchmove" : "mousemove";
var END = isTouchSupported ? "touchend" : "mouseup";
elem.addEventListener(CLICK, mouseClick);
elem.addEventListener(START, mouseStart);
elem.addEventListener(END, mouseEnd);
move && elem.addEventListener(MOVE, mouseMove);
var visitor = null;
var abs = {
x : 0,
y : 0,
toString : function() {
return (this.x | 0) + "x" + (this.y | 0);
}
};
var rel = {
x : 0,
y : 0,
toString : function() {
return abs + " / " + (this.x | 0) + "x" + (this.y | 0);
}
};
var clicked = {
x : 0,
y : 0,
state : 0
};
function mouseStart(event) {
update(event, elem);
DEBUG && console.log("Mouse Start: " + event.type + " " + abs);
!move && elem.addEventListener(MOVE, mouseMove);
event.preventDefault();
publish(event.type, event);
clicked.x = abs.x;
clicked.y = abs.y;
clicked.state = 1;
}
function mouseEnd(event) {
try {
// New xy is not valid/available, last xy is used instead.
DEBUG && console.log("Mouse End: " + event.type + " " + abs);
!move && elem.removeEventListener(MOVE, mouseMove);
event.preventDefault();
publish(event.type, event);
if (clicked.state == 1 && clicked.x == abs.x && clicked.y == abs.y) {
DEBUG && console.log("Mouse Click [+]");
publish("click", event);
clicked.state = 2;
} else {
clicked.state = 0;
}
} catch (e) {
console && console.log(e);
}
}
function mouseMove(event) {
try {
update(event, elem);
// DEBUG && console.log("Mouse Move: " + event.type + " " +
// abs);
event.preventDefault();
publish(event.type, event);
} catch (e) {
console && console.log(e);
}
}
function mouseClick(event) {
try {
update(event, elem);
DEBUG && console.log("Mouse Click: " + event.type + " " + abs);
event.preventDefault();
if (clicked.state != 2) {
publish(event.type, event);
} else {
DEBUG && console.log("Mouse Click [-]");
}
} catch (e) {
console && console.log(e);
}
}
function publish(type, event) {
abs.type = type;
abs.event = event;
rel.x = abs.x;
rel.y = abs.y;
listener.visit(visitor);
}
visitor = {
reverse : true,
visible : true,
start : function(cut) {
if (!cut.spy()) {
cut.matrix().reverse().map(abs, rel);
if (rel.x < 0 || rel.x > cut._pin._width || rel.y < 0
|| rel.y > cut._pin._height) {
return true;
}
}
},
end : function(cut) {
var listeners = cut.listeners(abs.type);
if (listeners) {
cut.matrix().reverse().map(abs, rel);
for (var l = 0; l < listeners.length; l++)
if (listeners[l].call(cut, abs.event, rel)) {
return true;
}
}
}
};
function update(event, elem) {
var isTouch = false;
// touch screen events
if (event.touches) {
if (event.touches.length) {
isTouch = true;
abs.x = event.touches[0].pageX;
abs.y = event.touches[0].pageY;
} else {
return;
}
} else {
// mouse events
abs.x = event.clientX;
abs.y = event.clientY;
// http://www.softcomplex.com/docs/get_window_size_and_scrollbar_position.html
if (document.body.scrollLeft || document.body.scrollTop) {
// body is added as offsetParent
} else if (document.documentElement) {
abs.x += document.documentElement.scrollLeft;
abs.y += document.documentElement.scrollTop;
}
}
// accounts for border
abs.x -= elem.clientLeft || 0;
abs.y -= elem.clientTop || 0;
var par = elem;
while (par) {
abs.x -= par.offsetLeft || 0;
abs.y -= par.offsetTop || 0;
if (!isTouch) {
// touch events offset scrolling with pageX/Y
// so scroll offset not needed for them
abs.x += par.scrollLeft || 0;
abs.y += par.scrollTop || 0;
}
par = par.offsetParent;
}
// see loader
abs.x *= listener.ratio || 1;
abs.y *= listener.ratio || 1;
}
};

79
src/js/pool.js Normal file
Просмотреть файл

@ -0,0 +1,79 @@
/*
* Extra.js
* Copyright (c) 2013-2014 Ali Shakiba, Piqnt LLC and other contributors
* Available under the MIT license
* @license
*/
function Pool(_create, _exit, _enter, _discard) {
var _list = [], _max = 4, _name = "";
var _created = 0, _checkedout = 0, _checkedin = 0, _discarded = 0;
this.create = function(create) {
_create = create;
return this;
};
this.exit = function(exit) {
_exit = func;
return this;
};
this.enter = function(enter) {
_enter = func;
return this;
};
this.discard = function(discard) {
_discard = discard;
return this;
};
this.max = function(max) {
if (!arguments.length) {
return _max;
}
_max = max;
return this;
};
this.name = function(name) {
if (!arguments.length) {
return _name;
}
_name = name;
return this;
};
this.checkOut = function(create) {
var item;
if (_list.length) {
item = _list.shift();
} else {
_created++;
item = (create || _create).apply(this);
}
_checkedout++;
_exit && _exit.call(this, item);
return item;
};
this.checkIn = function(item, discard) {
if (_list.length < _max) {
_checkedin++;
_enter && _enter.call(this, item);
_list.push(item);
} else {
_discarded++;
(discard = discard || _discard) && discard.call(this, item);
}
};
this.toString = function() {
return "Pool (" + _name + "):" + " +" + _created + " >" + _checkedout
+ " <" + _checkedin + " -" + _discarded + " =" + _list.length + "/"
+ _max;
};
}

132
src/js/randomize.js Normal file
Просмотреть файл

@ -0,0 +1,132 @@
/*
* Extra.js
* Copyright (c) 2013-2014 Ali Shakiba, Piqnt LLC and other contributors
* Available under the MIT license
* @license
*/
function Randomize() {
this._options = [];
this._nope = null;
this._filter = function(option) {
return option;
};
};
Randomize.prototype.reset = function() {
this._reset && this._reset();
return this;
};
Randomize.prototype.clone = function() {
var clone = new Randomize();
Array.push.apply(clone._options, this._options);
clone._nope = this._nope;
clone._filter = this._filter;
clone._lock = this._lock;
clone._condition = this._condition;
return clone;
};
Randomize.prototype.filter = function(func) {
this._filter = func || function(option) {
return option;
};
return this;
};
Randomize.prototype.nope = function(nope) {
if (!arguments.length) {
return this._nope;
}
this._nope = nope;
return this;
};
Randomize.prototype.add = function(option, weight, lock) {
this._options.push([ option, Randomize._numbor(weight, 1) ]);
if (lock) {
this._lock = this._options.length - 1;
}
return this;
};
Randomize.prototype.condition = function(condition, reset) {
this._condition = condition;
this._reset = reset;
return this;
};
Randomize.prototype.select = function(select) {
return this._filter(this._options[select][0]);
};
Randomize.prototype.random = function() {
if (this._condition && !this._condition.apply(null, arguments)) {
return this._filter(this._nope);
}
if (typeof this._lock === "number") {
return this.select(this._lock);
}
var sum = 0;
for ( var i = 0; i < this._options.length; i++) {
var option = this._options[i];
option[2] = option[1].apply(null, arguments);
sum += (option[2]);
}
var rand = Math.random() * sum;
var selected = this._nope;
for ( var i = 0; i < this._options.length; i++) {
var option = this._options[i];
if ((rand -= option[2]) < 0) {
selected = option[0];
break;
}
}
return this._filter(selected);
};
Randomize.prototype.spacing = function(spacing) {
spacing = Randomize._numbor(spacing, 1);
var space = null;
this.condition(function() {
if (space === null) {
space = spacing.apply(null, arguments);
return false;
}
if (--space < 0) {
space = spacing.apply(null, arguments);
return true;
}
return false;
}, function() {
space = null;
});
return this;
};
Randomize.prototype.prob = function(prob) {
prob = Randomize._numbor(prob, 1);
this.condition(function() {
var p = prob();
console.log(p);
return p > Math.random();
});
return this;
};
Randomize._numbor = function(value, fallback) {
if (typeof value == "function") {
return value;
}
if (typeof value !== "number") {
value = fallback;
}
return function() {
return value;
};
};