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 ### Getting started
##### Download 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.
Use git or the download button (on the right) to download the game source code.
##### 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. Open `src/index.html` with your browser, the game should start, if not check errors with your browser debugging utility.
### Graphics/Textures ### Graphics/Textures

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

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