Code Smaple
Check a SceneBox prototype to control CSS sprite.
SceneBox.prototype = {
initSprite: function (_spriteClassName, _width, _height, _scale) {
this.spriteClassName = _spriteClassName;
this.sceneDiv.css({
overflow: "hidden",
width: _width,
height: _height,
transformOrigin: "top left",
transform: "scale("+_scale+", "+_scale+")"
});
},
addSprite: function (_name, _imgSelector) {
var spriteDiv = $("<div></div>").addClass("sprite_"+_name);
spriteDiv.css({
position: "absolute",
top: "0",
left: "0",
maxWidth: "100%",
backgroundSize: "100%",
backgroundImage: "url("+$(_imgSelector).attr("src")+")",
backgroundColor: "black",
width: "100%",
height: "100%",
zIndex: 0
});
this.sceneDiv.append(spriteDiv);
},
addMovieClip: function (_startFrame, _endFrame, _spriteName) {
this.movieClip[name] = new MovieClip(_startFrame, _endFrame, _spriteName);
},
playMoiveClip: function (_name, _loop) {
this.animationQueue.push({"name": _name, "loop": _loop});
if(this.debug){
console.log("playMoiveClip: ");
console.log(this.animationQueue);
}
},
nextMovieClip: function(){
if(this.animationQueue.length > 0){
this.animationQueue[0].loop = false;
}
},
setFrameCover: function(_num, _spriteName){
if($("#cssSpritePool > ."+this.spriteClassName+_num).length <= 0){
var _div = $("<div></div>").addClass(this.spriteClassName+_num);
$("#cssSpritePool").append(_div);
}
var _bgPosX = $("."+this.spriteClassName+_num).css('background-position-x');
var _bgPosY = $("."+this.spriteClassName+_num).css('background-position-y');
this.sceneDiv.find("div[class*=sprite_]").css({
zIndex:1
});
this.sceneDiv.find("div.sprite_"+_spriteName).css({
backgroundPositionX: _bgPosX,
backgroundPositionY: _bgPosY,
zIndex:2
});
},
setFrameNum: function(_num, _movieClip){
this.setFrameCover(_num, _movieClip.spriteName);
},
updateMoiveClip: function (){
if(this.animationQueue.length > 0){
var _movieClip = this.movieClip[this.animationQueue[0].name];
if(this.sceneCurrentFrame == 0){
this.sceneCurrentFrame = _movieClip.startFrame;
}
this.setFrameNum(this.sceneCurrentFrame, _movieClip);
if(++this.sceneCurrentFrame > _movieClip.endFrame){
if(this.animationQueue[0].loop){
this.sceneCurrentFrame = _movieClip.startFrame;
}else{
if(this.animationQueue.length > 1){
var _movieClipNext = this.movieClip[this.animationQueue[1].name];
this.sceneCurrentFrame = _movieClipNext.startFrame;
this.animationQueue.shift();
}else{
this.sceneCurrentFrame = _movieClip.endFrame;
}
}
}
}
}
};
A multi-player WebSocket project - Sever Side
var cluster = require('cluster');
var numCPUs = require('os').cpus().length;
if (cluster.isMaster) {
console.log("master start...");
// Fork workers.
for (var i = 0; i < numCPUs; i++) {
cluster.fork();
}
cluster.on('listening',function(worker,address){
console.log('listening: worker ' + worker.process.pid +', Address: '+address.address+":"+address.port);
});
cluster.on('exit', function(worker, code, signal) {
console.log('worker ' + worker.process.pid + ' died');
});
return;
}
var sockjs = require('sockjs');
var redis = require('redis');
var http = require('http');
var uuid = require('node-uuid');
var app = require('./app');
// Redis publisher
var publisher = redis.createClient();
// Sockjs server
var sockjs_opts = {sockjs_url: "javascripts/sockjs.min.js"};
var sockjs_chat = sockjs.createServer(sockjs_opts);
sockjs_chat.on('connection', function(conn) {
console.log("======== New Player!!! ========");
// Init Redis DB
var browser = redis.createClient();
var channel_id = "";
browser.subscribe('public_channel');
browser.on("message", function(channel, message){
conn.write(message);
});
// Call when data received
conn.on('data', function(message) {
var msgJSON = JSON.parse(message);
console.log("Method: "+msgJSON.method);
switch(msgJSON.method){
// Open new channel
case "new-channel":
channel_id = uuid.v1();
console.log("channel_id: "+channel_id);
browser.subscribe(channel_id);
publisher.publish(channel_id, JSON.stringify({
'channel': channel_id,
'action': "qrcode",
'player': "1"}));
break;
// Player two join
case "join-channel":
channel_id = msgJSON.channel;
browser.subscribe(channel_id);
publisher.publish(channel_id, JSON.stringify({
'channel': channel_id,
'action': "start",
'player': "0"}));
break;
// Call when loading finish
case "loading-unlock":
console.log("Method: "+msgJSON.method+" "+msgJSON.player+" "+msgJSON.perload_count);
publisher.publish(channel_id, JSON.stringify({
'channel': channel_id,
'action': "loading-unlock",
'perload_count': msgJSON.perload_count,
'player': msgJSON.player}));
break;
// Next Status
case "next-action":
publisher.publish(channel_id, JSON.stringify({
'channel': channel_id,
'action': "next-action",
'player': "0"}));
break;
}
});
// Clearup and unsubscribe when connection close
conn.on('close', function() {
publisher.publish(channel_id, JSON.stringify({'method': "close"}));
console.log('Close: '+channel_id);
browser.unsubscribe(channel_id);
browser.end();
});
});
// Creat http server
var server = http.createServer(app);
sockjs_chat.installHandlers(server, {prefix:'/lobby'});
console.log(' [*] Listening on 0.0.0.0:9001' );
server.listen(9001, '0.0.0.0');
A multi-player WebSocket project - Client Side
document.ontouchmove = function(event){
event.preventDefault();
}
// ScokJS
var sockjs_url = '/lobby';
var sockjs = new SockJS(sockjs_url);
sockjs.onopen = function() {
// perloading image and audio when sock open
perLoading0();
}
sockjs.onclose = function() {print('Closing Connection.');};
sockjs.onerror = function(e) {print(e.data);};
// When sock msg received
sockjs.onmessage = function(e) {
var json = jQuery.parseJSON(e.data);
switch(json.action){
// Show qrcoe
case "qrcode":
if(parseInt(json.player) == player){
channelID = json.channel;
showQRCode(channelID);
}
break;
// All player ready - Start game
case "start":
gameStatus = 1;
gameStatusChange(gameStatus);
sendLoadingLock(perloadCountSync[player]);
break;
// Loading finished
case "loading-unlock":
perloadCountSync[json.player] = json.perload_count;
loadingUnLock();
break;
// Next Status
case "next-action":
gameStatus++;
gameStatusChange(gameStatus);
break;
}
}
var channelID = "";
var gameStatus = 0;
var player = 1;
var current_url = $.url();
// Check Player
if(current_url.fparam('join_game') == 1){
player = 2;
if(current_url.fparam('channel')){
channelID = current_url.fparam('channel');
}
}
window.location.hash = '#';
// Resize canvas for different screen
var screenRate = 640 / 1029;
var canvasWidth;
var canvasHeight;
var spriteScale, bgScale;
$(window).resize(resize);
resize();
function resize() {
var _width = $("#mainCanvas").height() * screenRate;
$("#mainCanvas, #loadingCanvas").css({
width: _width,
marginLeft: -_width/2
});
$("#sceneHome > .qrcode > img").css({
position: "absolute",
top: 0.145*$("#sceneHome").height(),
left: ($("#sceneHome").width()-0.25*$("#sceneHome").height())/2,
height: 0.25*$("#sceneHome").height()
})
}
// Device orientation
function checkOrientation(){
setTimeout(function(){
$("#popupTip").fadeIn(300);
orientationLock = false;
}, 1000);
}
window.addEventListener('deviceorientation', orientationCallback, false);
function orientationCallback(eventData){
if(!orientationLock && eventData.gamma > orientationGammaMin && eventData.gamma < orientationGammaMax){
orientationLock = true;
nextAnimation();
}
}
// Init Div
$("#popupTip, #sharePage, #sceneHome").fadeOut(0);
// Init Player
var orientationGammaMin = 0;
var orientationGammaMax = 0;
if(player == 2){
orientationGammaMin = -80;
orientationGammaMax = -60;
$("#popupTip").css({
backgroundImage : "url(./images/p2_tips.png)"
});
$("body").css({
backgroundColor: "#000000"
});
$("#loadingCanvas").css({
backgroundColor: "rgba(0, 0, 0, 0.5)"
});
}else if(player == 1){
orientationGammaMin = 60;
orientationGammaMax = 80;
$("#popupTip").css({
backgroundImage : "url(./images/p1_tips.png)"
});
$("#sceneHome").css({
backgroundImage: "url(./images/bg_qrcode.jpg)"
});
$("body").css({
backgroundColor: "#FFFFF"
});
$("#loadingCanvas").css({
backgroundColor: "rgba(255, 255, 255, 0.5)"
});
}
var stage,loader, manifest;
var spriteAnimation = [], spriteJson, loadingAnimation;
var backgroundMusic;
var perloadCount = 0;
var perloadCountSync = [];
perloadCountSync[1] = 0;
perloadCountSync[2] = 0;
function perLoading0() {
stage = new createjs.Stage("mainCanvas");
stageLoading = new createjs.Stage("loadingCanvas");
manifest = [
{src: "images/sprite/loading.png", id: "sprtie_loading"}
];
spriteJson = loadingSpriteJson;
loader = new createjs.LoadQueue(false);
loader.installPlugin(createjs.Sound);
loader.setMaxConnections(5);
loader.addEventListener("complete", handleComplete);
loader.addEventListener('progress', function(e){
if(perloadCount > 0){
var progress = Math.round(145*e.loaded);
var rect = new createjs.Shape();
if(player == 1){
rect.graphics.beginFill("#000").drawRect(95, 300, Math.round(145*e.loaded), 1);
}else if(player == 2){
rect.graphics.beginFill("#FFF").drawRect(95, 300, Math.round(145*e.loaded), 1);
}
stageLoading.addChild(rect);
}
});
loader.loadManifest(manifest, true, "./");
}
function perLoading1() {
if(player == 1){
manifest = [
{src: "audios/white-背景音乐一直loop.mp3", id: "audio_bg"},
{src: "audios/white-蛇变龙.mp3", id: "audio_p1_dragon"},
{src: "audios/蛇.mp3", id: "audio_p1_snake"},
{src: "audios/white-蜜蜂.mp3", id: "audio_p1_bee"},
{src: "images/sprite/p1-a-0.jpg", id: "sprtie_p1_a_0"},
{src: "images/sprite/p1-a-1.jpg", id: "sprtie_p1_a_1"},
{src: "images/sprite/p1-a-2.jpg", id: "sprtie_p1_a_2"},
{src: "images/sprite/p1-a-3.jpg", id: "sprtie_p1_a_3"},
{src: "images/sprite/p1-b-0.jpg", id: "sprtie_p1_b_0"},
{src: "images/sprite/p1-b-1.jpg", id: "sprtie_p1_b_1"},
{src: "images/sprite/p1-b-2.jpg", id: "sprtie_p1_b_2"},
{src: "images/sprite/p1-b-3.jpg", id: "sprtie_p1_b_3"},
{src: "images/sprite/p1-c-0.jpg", id: "sprtie_p1_c_0"},
{src: "images/sprite/p1-c-1.jpg", id: "sprtie_p1_c_1"},
{src: "images/sprite/p1-c-2.jpg", id: "sprtie_p1_c_2"},
{src: "images/sprite/p1-c-3.jpg", id: "sprtie_p1_c_3"},
];
}else if(player == 2){
manifest = [
{src: "audios/black-剑.mp3", id: "audio_p2_knife"},
{src: "audios/black-剑变忍者.mp3", id: "audio_p2_ninja"},
{src: "audios/black-背景音乐一直loop.mp3", id: "audio_bg"},
{src: "audios/black-蜂变鸟.mp3", id: "audio_p2_bee"},
{src: "images/sprite/p2-a-0.jpg", id: "sprtie_p2_a_0"},
{src: "images/sprite/p2-a-1.jpg", id: "sprtie_p2_a_1"},
{src: "images/sprite/p2-a-2.jpg", id: "sprtie_p2_a_2"},
{src: "images/sprite/p2-a-3.jpg", id: "sprtie_p2_a_3"},
{src: "images/sprite/p2-b-0.jpg", id: "sprtie_p2_b_0"},
{src: "images/sprite/p2-b-1.jpg", id: "sprtie_p2_b_1"},
{src: "images/sprite/p2-b-2.jpg", id: "sprtie_p2_b_2"},
{src: "images/sprite/p2-b-3.jpg", id: "sprtie_p2_b_3"},
{src: "images/sprite/p2-c-0.jpg", id: "sprtie_p2_c_0"},
{src: "images/sprite/p2-c-1.jpg", id: "sprtie_p2_c_1"},
{src: "images/sprite/p2-c-2.jpg", id: "sprtie_p2_c_2"},
{src: "images/sprite/p2-c-3.jpg", id: "sprtie_p2_c_3"},
];
}
loader.loadManifest(manifest, true, "./");
}
function perLoading2(){
if(player == 1){
manifest = [
{src: "audios/white-ending页面.mp3", id: "audio_p1_end"},
{src: "audios/white-忍者出现.mp3", id: "audio_p1_ninja"},
{src: "images/sprite/p1-d-0.jpg", id: "sprtie_p1_d_0"},
{src: "images/sprite/p1-d-1.jpg", id: "sprtie_p1_d_1"},
{src: "images/sprite/p1-e-0.jpg", id: "sprtie_p1_e_0"},
{src: "images/sprite/p1-e-1.jpg", id: "sprtie_p1_e_1"},
{src: "images/sprite/p1-e-2.jpg", id: "sprtie_p1_e_2"},
{src: "images/sprite/p1-e-3.jpg", id: "sprtie_p1_e_3"},
{src: "images/sprite/p1-e-4.jpg", id: "sprtie_p1_e_4"},
{src: "images/sprite/p1-e-5.jpg", id: "sprtie_p1_e_5"},
{src: "images/sprite/p1-e-6.jpg", id: "sprtie_p1_e_6"},
{src: "images/sprite/p1-e-7.jpg", id: "sprtie_p1_e_7"},
{src: "images/sprite/p1-e-8.jpg", id: "sprtie_p1_e_8"}
];
}else if(player == 2){
manifest = [
{src: "images/sprite/p2-d-0.jpg", id: "sprtie_p2_d_0"},
{src: "images/sprite/p2-d-1.jpg", id: "sprtie_p2_d_1"},
{src: "images/sprite/p2-d-2.jpg", id: "sprtie_p2_d_2"},
{src: "images/sprite/p2-e-0.jpg", id: "sprtie_p2_e_0"},
{src: "images/sprite/p2-e-1.jpg", id: "sprtie_p2_e_1"},
{src: "images/sprite/p2-e-2.jpg", id: "sprtie_p2_e_2"},
{src: "images/sprite/p2-e-3.jpg", id: "sprtie_p2_e_3"},
{src: "images/sprite/p2-e-4.jpg", id: "sprtie_p2_e_4"},
{src: "images/sprite/p2-e-5.jpg", id: "sprtie_p2_e_5"},
{src: "images/sprite/p2-e-6.jpg", id: "sprtie_p2_e_6"},
{src: "images/sprite/p2-e-7.jpg", id: "sprtie_p2_e_7"},
{src: "images/sprite/p2-e-8.jpg", id: "sprtie_p2_e_8"}
];
}
loader.loadManifest(manifest, true, "./");
}
function loadingComplete0(){
spriteJson.images = [
loader.getResult("sprtie_loading")
];
var spriteSheet = new createjs.SpriteSheet(spriteJson);
loadingAnimation = new createjs.Sprite(spriteSheet);
loadingAnimation.x = 95;
loadingAnimation.y = 186;
if(player == 1){
loadingAnimation.gotoAndPlay("p1_loading");
}else if(player == 2){
loadingAnimation.gotoAndPlay("p2_loading");
}
stage.snapToPixelEnabled = true;
stage.autoClear = true;
stageLoading.snapToPixelEnabled = true;
stageLoading.autoClear = true;
stageLoading.addChild(loadingAnimation);
createjs.Ticker.addEventListener("tick", tick);
createjs.Ticker.setFPS(12);
}
function loadingComplete1(){
if(player == 1){
p1SpriteJsonS1.images = [
loader.getResult("sprtie_p1_a_0"),
loader.getResult("sprtie_p1_a_1"),
loader.getResult("sprtie_p1_a_2"),
loader.getResult("sprtie_p1_a_3")
];
p1SpriteJsonS2.images = [
loader.getResult("sprtie_p1_b_0"),
loader.getResult("sprtie_p1_b_1"),
loader.getResult("sprtie_p1_b_2"),
loader.getResult("sprtie_p1_b_3")
];
p1SpriteJsonS3.images = [
loader.getResult("sprtie_p1_c_0"),
loader.getResult("sprtie_p1_c_1"),
loader.getResult("sprtie_p1_c_2"),
loader.getResult("sprtie_p1_c_3")
];
var spriteSheet = new createjs.SpriteSheet(p1SpriteJsonS1);
spriteAnimation[0] = new createjs.Sprite(spriteSheet);
var spriteSheet = new createjs.SpriteSheet(p1SpriteJsonS2);
spriteAnimation[1] = new createjs.Sprite(spriteSheet);
var spriteSheet = new createjs.SpriteSheet(p1SpriteJsonS3);
spriteAnimation[2] = new createjs.Sprite(spriteSheet);
}else if(player == 2){
p2SpriteJsonS1.images = [
loader.getResult("sprtie_p2_a_0"),
loader.getResult("sprtie_p2_a_1"),
loader.getResult("sprtie_p2_a_2"),
loader.getResult("sprtie_p2_a_3")
];
p2SpriteJsonS2.images = [
loader.getResult("sprtie_p2_b_0"),
loader.getResult("sprtie_p2_b_1"),
loader.getResult("sprtie_p2_b_2"),
loader.getResult("sprtie_p2_b_3")
];
p2SpriteJsonS3.images = [
loader.getResult("sprtie_p2_c_0"),
loader.getResult("sprtie_p2_c_1"),
loader.getResult("sprtie_p2_c_2"),
loader.getResult("sprtie_p2_c_3")
];
var spriteSheet = new createjs.SpriteSheet(p2SpriteJsonS1);
spriteAnimation[0] = new createjs.Sprite(spriteSheet);
var spriteSheet = new createjs.SpriteSheet(p2SpriteJsonS2);
spriteAnimation[1] = new createjs.Sprite(spriteSheet);
var spriteSheet = new createjs.SpriteSheet(p2SpriteJsonS3);
spriteAnimation[2] = new createjs.Sprite(spriteSheet);
}
if(player == 1){
createGameRoom();
}else if(player == 2){
if(channelID){
joinGameRoom(channelID);
}
}
$("#loadingCanvas").fadeOut(300);
}
function loadingComplete2(){
if(player == 1){
p1SpriteJsonS4.images = [
loader.getResult("sprtie_p1_d_0"),
loader.getResult("sprtie_p1_d_1")
];
p1SpriteJsonS5.images = [
loader.getResult("sprtie_p1_e_0"),
loader.getResult("sprtie_p1_e_1"),
loader.getResult("sprtie_p1_e_2"),
loader.getResult("sprtie_p1_e_3"),
loader.getResult("sprtie_p1_e_4"),
loader.getResult("sprtie_p1_e_5"),
loader.getResult("sprtie_p1_e_6"),
loader.getResult("sprtie_p1_e_7"),
loader.getResult("sprtie_p1_e_8")
];
var spriteSheet = new createjs.SpriteSheet(p1SpriteJsonS4);
spriteAnimation[3] = new createjs.Sprite(spriteSheet);
var spriteSheet = new createjs.SpriteSheet(p1SpriteJsonS5);
spriteAnimation[4] = new createjs.Sprite(spriteSheet);
}else if(player == 2){
p2SpriteJsonS4.images = [
loader.getResult("sprtie_p2_d_0"),
loader.getResult("sprtie_p2_d_1"),
loader.getResult("sprtie_p2_d_2")
];
p2SpriteJsonS5.images = [
loader.getResult("sprtie_p2_e_0"),
loader.getResult("sprtie_p2_e_1"),
loader.getResult("sprtie_p2_e_2"),
loader.getResult("sprtie_p2_e_3"),
loader.getResult("sprtie_p2_e_4"),
loader.getResult("sprtie_p2_e_5"),
loader.getResult("sprtie_p2_e_6"),
loader.getResult("sprtie_p2_e_7"),
loader.getResult("sprtie_p2_e_8")
];
var spriteSheet = new createjs.SpriteSheet(p2SpriteJsonS4);
spriteAnimation[3] = new createjs.Sprite(spriteSheet);
var spriteSheet = new createjs.SpriteSheet(p2SpriteJsonS5);
spriteAnimation[4] = new createjs.Sprite(spriteSheet);
}
}
// Loading Complete Handler
function handleComplete() {
if(perloadCount > 1){
sendLoadingLock(perloadCount);
}
perloadCountSync[player] = perloadCount;
switch(perloadCount){
case 0:
loadingComplete0();
perLoading1();
break;
case 1:
loadingComplete1();
perLoading2();
break;
case 2:
loadingComplete2();
break;
}
perloadCount++;
}
var loadingCanvas = $("#loadingCanvas");
// Canvas Update
function tick(event) {
stage.update(event);
if (loadingCanvas.is(":visible")) {
stageLoading.update(event);
}
}
function createGameRoom(cid){
sockjs.send(JSON.stringify({'method': 'new-channel'}));
}
var soundLoop;
var orientationLoadingLockCount = 0;
var orientationLoadingLockPlayer = 0;
var orientationLock = true;
function gameStatusChange(game_status){
switch(game_status){
case 1:
$("#sceneHome").fadeOut(300, function(){
if(backgroundMusic){
backgroundMusic.stop();
}
backgroundMusic = createjs.Sound.play("audio_bg");
backgroundMusic.setLoop(99999);
if(player == 2){
backgroundMusic.volume = 0.1;
}
});
stage.addChild(spriteAnimation[0]);
spriteAnimation[0].gotoAndPlay("animation");
spriteAnimation[0].on("animationend", function(evt){
if(evt.name == "animation"){
if(player == 1){
checkOrientation();
}
}
});
if(player == 1){
setTimeout(function(){
soundLoop = createjs.Sound.play("audio_p1_bee");
soundLoop.setLoop(99999);
}, 4000);
}
break;
case 2:
$("#popupTip").fadeOut(100);
stage.removeChild(spriteAnimation[0]);
stage.addChild(spriteAnimation[1]);
spriteAnimation[1].gotoAndPlay("animation");
spriteAnimation[1].on("animationend", function(evt){
if(evt.name == "animation"){
if(player == 2){
checkOrientation();
}
}
});
if(player == 1){
if(soundLoop){
setTimeout(function(){
soundLoop.stop();
}, 1500);
}
setTimeout(function(){
soundLoop = createjs.Sound.play("audio_p1_snake");
soundLoop.setLoop(99999);
}, 2200);
}else{
soundLoop = createjs.Sound.play("audio_p2_bee");
}
break;
case 3:
$("#popupTip").fadeOut(100);
stage.removeChild(spriteAnimation[1]);
stage.addChild(spriteAnimation[2]);
spriteAnimation[2].gotoAndPlay("animation");
spriteAnimation[2].on("animationend", function(evt){
if(evt.name == "animation"){
if(player == 1){
checkOrientation();
}
}
});
if(player == 1){
if(soundLoop){
setTimeout(function(){
soundLoop.stop();
}, 1800);
}
setTimeout(function(){
soundLoop = createjs.Sound.play("audio_p1_dragon");
soundLoop.setLoop(99999);
}, 2000);
}else{
setTimeout(function(){
soundLoop = createjs.Sound.play("audio_p2_knife");
}, 2500);
}
break;
case 4:
$("#popupTip").fadeOut(100);
stage.removeChild(spriteAnimation[2]);
stage.addChild(spriteAnimation[3]);
spriteAnimation[3].gotoAndPlay("animation");
spriteAnimation[3].on("animationend", function(evt){
if(evt.name == "animation"){
checkLoadingSync(2, 2);
}
});
if(player == 1){
if(soundLoop){
setTimeout(function(){
soundLoop.stop();
}, 1000);
}
}else{
setTimeout(function(){
createjs.Sound.play("audio_p2_ninja");
}, 300);
}
break;
case 5:
$("#popupTip").fadeOut(100);
if(soundLoop){
soundLoop.stop();
}
stage.removeChild(spriteAnimation[3]);
stage.addChild(spriteAnimation[4]);
if(player == 1){
createjs.Sound.play("audio_p1_ninja");
}
spriteAnimation[4].gotoAndPlay("animation");
spriteAnimation[4].on("animationend", function(evt){
if(evt.name == "animation"){
sharePage();
}
});
setTimeout(function(){
if(backgroundMusic){
backgroundMusic.stop();
}
if(player == 1){
backgroundMusic = createjs.Sound.play("audio_p1_end");
backgroundMusic.setLoop(99999);
}
}, 8000);
break;
}
}
function checkLoadingSync(_count, _player){
if(perloadCountSync[1] < _count || perloadCountSync[2] < _count){
$("#loadingCanvas").fadeIn(300);
orientationLoadingLockCount = _count;
orientationLoadingLockPlayer = _player;
}else{
if(player == _player){
checkOrientation();
}
orientationLoadingLockCount = 0;
orientationLoadingLockPlayer = 0;
}
}
function loadingUnLock(){
$("#loadingCanvas").fadeOut(100);
if(orientationLoadingLockCount != 0 || orientationLoadingLockPlayer != 0){
checkLoadingSync(orientationLoadingLockCount, orientationLoadingLockPlayer);
}
}
function sendLoadingLock(_count){
sockjs.send(JSON.stringify({'method': 'loading-unlock', "player" : player, "perload_count" : _count}));
}
function nextAnimation(){
sockjs.send(JSON.stringify({'method': 'next-action', "player" : player}));
}
function joinGameRoom(cid){
sockjs.send(JSON.stringify({'method': 'join-channel', 'channel': channelID}));
}
function showQRCode(cid){
$("#sceneHome > .qrcode").qrcode({
"render": "image",
"size": 250,
"color": "#3a3",
"text": current_url.attr('protocol')+"://"+
current_url.attr('host')+":"+
current_url.attr('port')+
current_url.attr('path')+"#join_game=1&channel="+cid
});
setTimeout(function(){
$("#sceneHome > .qrcode > img").css({
position: "absolute",
top: 0.145*$("#sceneHome").height(),
left: ($("#sceneHome").width()-0.25*$("#sceneHome").height())/2,
height: 0.25*$("#sceneHome").height()
})
$("#sceneHome").fadeIn(300);
}, 500);
}
function sharePage(){
$("#sharePage").fadeIn(0);
}
// Share Screen
$("#sharePage > .btnPlayAgain").click(function(){
window.location.href = "/";
});
$("#sharePage > .btnSharePopup").click(function(){
$("#sharePage > .btnBack").fadeIn(0);
spriteAnimation[4].gotoAndPlay("share");
});
$("#sharePage > .btnBack").click(function(){
$(this).fadeOut(300);
spriteAnimation[4].gotoAndPlay("share_reverse");
});
A Codeigniter controllers sample
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
include __DIR__."/../assets/lib/wechat.class.php";
date_default_timezone_set('Asia/Shanghai');
define('PATH_UPLOAD_ORIGINAL', "uploads/original/");
define('APPID', '');
define('SECRET', '');
define('LOG_HISTORY', __DIR__."/../assets/log/history.txt");
function logdebug($text){
file_put_contents('log.txt',$text."\n",FILE_APPEND);
}
function shortenSinaUrl($long_url){
$apiKey='2499377203';
$apiUrl='http://api.t.sina.com.cn/short_url/shorten.json?source='.$apiKey.'&url_long='.$long_url;
$curlObj = curl_init();
curl_setopt($curlObj, CURLOPT_URL, $apiUrl);
curl_setopt($curlObj, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curlObj, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($curlObj, CURLOPT_HEADER, 0);
curl_setopt($curlObj, CURLOPT_HTTPHEADER, array('Content-type:application/json'));
$response = curl_exec($curlObj);
curl_close($curlObj);
$json = json_decode($response);
return $json[0]->url_short;
}
class Admin extends CI_Controller {
public $data;
public function __construct()
{
parent::__construct();
$this->load->helper(array('form', 'url'));
$this->load->model('portraits_model');
$this->data=array(
"assets_path"=>base_url("/application/assets/")
);
}
function logout()
{
$this->session->unset_userdata('logged_in');
session_destroy();
redirect('login', 'refresh');
}
public function index()
{
if($this->session->userdata('logged_in')){
if(isset($_REQUEST["mode"])){
$this->data['mode'] = $_REQUEST["mode"];
}else{
$this->data['mode'] = 0;
}
$this->data['stats'] = $this->portraits_model->get_all();
switch($this->data['mode']){
case 0:
case 1:
case 2:
$this->data['portraits'] = $this->portraits_model->get_all_by_approval_status_limit($this->data['mode']);
$this->load->view('admin/header.php', $this->data);
$this->load->view('admin/index.php', $this->data);
$this->load->view('admin/footer.php', $this->data);
break;
case 3:
$this->data['log_history'] = read_file(LOG_HISTORY);
$this->load->view('admin/header.php', $this->data);
$this->load->view('admin/log.php', $this->data);
$this->load->view('admin/footer.php', $this->data);
break;
case 4:
$this->data['portraits'] = $this->portraits_model->get_processing_status();
$this->load->view('admin/header.php', $this->data);
$this->load->view('admin/index.php', $this->data);
$this->load->view('admin/footer.php', $this->data);
break;
}
}else{
redirect('login', 'refresh');
}
}
public function api()
{
header("Access-Control-Allow-Origin: *");
$action = $_REQUEST["action"];
if(!isset($action)){
die(json_encode(array("error_code"=>"100", "message"=>"Parameter[action] missing.")));
}
switch($action){
case "upload":
$this->upload_resize();
break;
case "gallery":
$pager = 0;
$number = 20;
if(isset($_REQUEST['pager'])) $pager = $_REQUEST['pager'];
if(isset($_REQUEST['number'])) $number = $_REQUEST['number'];
echo json_encode($this->portraits_model->get_gallery($pager, $number));
break;
case "gallery_debug":
echo json_encode($this->portraits_model->get_gallery_all());
break;
case "regenerate":
if(!isset($_REQUEST["pid"])){
die(json_encode(array("error_code"=>"301", "message"=>"Parameter[pid] missing.")));
}
$pArr = $this->portraits_model->get_portrait($_REQUEST["pid"]);
if(count($pArr)>0){
$this->send_photoshop_server($pArr["id"], "/".PATH_UPLOAD_ORIGINAL.$pArr["photo_name"], $pArr["photo_quote"], $pArr["photo_key"]);
}
break;
}
}
public function upload()
{
$this->load->view('normal_upload1.php', $this->data);
}
public function upload_resize()
{
$minWidth = "640";
$minHeight = "853";
if(!isset($_REQUEST['uid']) ||
!isset($_REQUEST['sns']) ||
!isset($_REQUEST['key']) ||
!isset($_REQUEST['quote']) ||
empty($_FILES["file"]["name"])){
die(json_encode(array("error_code"=>"101", "message"=>"Parameter missing.")));
}
$username="";
if(isset($_REQUEST['username'])){
$username=$_REQUEST['username'];
}
$pid = $this->portraits_model->add($_REQUEST['sns'], $_REQUEST['uid'], $username, $_REQUEST['key'], $_REQUEST['quote']);
$photo_name = $pid.".".pathinfo($_FILES["file"]["name"], PATHINFO_EXTENSION);
$photo_name_new = $pid.".jpg";
$config['upload_path'] = "./".PATH_UPLOAD_ORIGINAL;
$config['allowed_types'] = 'jpg|png';
$config['max_size'] = '5000';
$config['max_width'] = '4096';
$config['max_height'] = '4096';
$config['overwrite'] = true;
$this->load->library('upload', $config);
$_FILES['file']['name'] = $photo_name;
if(!$this->upload->do_upload('file')){
die(json_encode(array("error_code"=>"102", "message"=>$this->upload->display_errors())));
}else{
$config['image_library'] = 'ImageMagick';
$config['source_image'] = $this->upload->upload_path.$this->upload->file_name;
$config['new_image'] = $this->upload->upload_path.$photo_name_new;
$config['maintain_ratio'] = FALSE;
$config['quality'] = '95%';
$config['library_path'] = '/usr/bin/convert';
list($imagewidth, $imageheight, $imageType) = getimagesize($this->upload->upload_path.$this->upload->file_name);
$rWidth = $minWidth/$imagewidth;
$rHeight = $minHeight/$imageheight;
if($rWidth > $rHeight){
$config['width'] = $rWidth*$imagewidth;
$config['height'] = $rWidth*$imageheight;
}else{
$config['width'] = $rHeight*$imagewidth;
$config['height'] = $rHeight*$imageheight;
}
$this->load->library('image_lib', $config);
if (!$this->image_lib->resize()){
die(json_encode(array("error_code"=>"103", "message"=>$this->image_lib->display_errors())));
}
$this->portraits_model->update_photo($pid, $photo_name_new);
$this->send_photoshop_server($pid, "/".PATH_UPLOAD_ORIGINAL.$photo_name_new, $_REQUEST['quote'], $_REQUEST['key']);
die(json_encode(array("error_code"=>"0", "message"=>"File upload success.")));
}
}
public function send_photoshop_server($pid, $photo_path, $quote, $key)
{
$target_url = 'server/index.php';
$img_path = "@".realpath('./').$photo_path;
$data = array("pid" => $pid,
"action" => "sendPhoto",
"quote" => $quote,
"selectedKey" => $key,
"picture" => $img_path);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$target_url);
curl_setopt($ch, CURLOPT_POST,1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
$result=curl_exec ($ch);
$this->portraits_model->update_curl_log($pid, $result);
$this->portraits_model->update_photo_status($pid, "processing");
$this->log_history("SUCCESS: Image sent to photoshop server: ".$pid." $result");
}
public function approve_portrait()
{
$pid = $_REQUEST["pid"];
$sns_id = $_REQUEST["sns_id"];
if(isset($pid)){
if($this->portraits_model->update_approve_status($pid, 1)){
if($sns_id == 1){
$this->send_wechat_message($pid, 1);
} else if($sns_id == 3) {
$this->send_douban_message($pid, 1);
}
echo json_encode(array("error"=>0));
$this->log_history("SUCCESS: Portrait approved: ".$pid);
}else{
echo json_encode(array("error"=>1));
$this->log_history("ERROR: Portrait approve: ".$pid);
}
}
}
public function reject_portrait()
{
$pid = $_REQUEST["pid"];
$sns_id = $_REQUEST["sns_id"];
if(isset($pid)){
if($this->portraits_model->update_approve_status($pid, 2)){
if($sns_id == 1){
$this->send_wechat_message($pid, 0);
} else if($sns_id == 3) {
$this->send_douban_message($pid, 0);
}
echo json_encode(array("error"=>0));
$this->log_history("SUCCESS: Portrait rejected: ".$pid);
}else{
echo json_encode(array("error"=>1));
$this->log_history("ERROR: Portrait reject: ".$pid);
}
}
}
public function resize_photo()
{
$pid = $_REQUEST["pid"];
$scale = $_REQUEST["scale"];
$imgX = $_REQUEST["x"]*$scale;
$imgY = $_REQUEST["y"]*$scale;
$width = $_REQUEST["width"];
$height = $_REQUEST["height"];
$imageName = $_REQUEST["name"];
if(!isset($pid) ||
!isset($imgX) ||
!isset($imgY) ||
!isset($width) ||
!isset($height) ||
!isset($imageName)){
die(json_encode(array("error" => 1)));
}
$image = "./uploads/original/".$imageName;
$imageCrop = "./uploads/crop/".$imageName;
list($imagewidth, $imageheight, $imageType) = getimagesize($image);
$imageType = image_type_to_mime_type($imageType);
$newImageWidth = ceil($width * $scale);
$newImageHeight = ceil($height * $scale);
$newImage = imagecreatetruecolor($newImageWidth,$newImageHeight);
switch($imageType) {
case "image/gif":
$source=imagecreatefromgif($image);
break;
case "image/pjpeg":
case "image/jpeg":
case "image/jpg":
$source=imagecreatefromjpeg($image);
break;
case "image/png":
case "image/x-png":
$source=imagecreatefrompng($image);
break;
}
imagecopyresampled($newImage,$source,0,0,$imgX,$imgY,$newImageWidth,$newImageHeight,$newImageWidth,$newImageHeight);
switch($imageType) {
case "image/gif":
imagegif($newImage,$imageCrop);
break;
case "image/pjpeg":
case "image/jpeg":
case "image/jpg":
imagejpeg($newImage,$imageCrop,90);
break;
case "image/png":
case "image/x-png":
imagepng($newImage,$imageCrop);
break;
}
$this->portraits_model->update_photo_cropped($pid);
$arr = $this->portraits_model->get_portrait($pid);
$this->send_photoshop_server($pid, "/uploads/crop/".$imageName, $arr["photo_quote"], $arr["photo_key"]);
die(json_encode(array("error" => 0)));
}
public function callback()
{
// log_message('error', 'PS Callback');
$config['upload_path'] = './uploads/processed/';
$config['allowed_types'] = 'gif|jpg|png';
$config['max_size'] = '10000';
$config['max_width'] = '2048';
$config['max_height'] = '2048';
$config['overwrite'] = true;
$pid = $_REQUEST["pid"];
$_FILES['picture']['name'] = $_REQUEST["pid"].'.jpg';
$this->load->library('upload', $config);
if (!$this->upload->do_upload('picture'))
{
echo '{"response":"ERROR"}';
$this->portraits_model->update_photo_status($pid, "process error");
$this->log_history("ERROR: Image processing: ".$pid);
}else{
echo '{"response":"OK"}';
$this->portraits_model->update_photo_status($pid, "processed");
$this->log_history("SUCCESS: Image processed: ".$pid);
}
}
public function send_wechat_message($pid, $status)
{
if(!isset($pid)) return false;
$wechat_sdk_options = array(
'token'=>'weixin_key',
'appid'=>APPID,
'appsecret'=>SECRET,
'debug'=>true,
'logcallback'=>'logdebug'
);
$weChatObj = new WechatSDK($wechat_sdk_options);
$portraitArr = $this->portraits_model->get_portrait($pid);
if(count($portraitArr)>0 ){
if($status == 1){
$newmedia = $weChatObj->uploadMedia('image', "/uploads/processed/".$portraitArr["photo_name"]);
$weChatObj->sendCustomImage($newmedia['media_id'], $portraitArr['user_id']);
sleep(3);
$weChatObj->sendCustomText("诚邀您分享至微博。".shortenSinaUrl("portrait.php?pic=".$portraitArr['photo_name']), $portraitArr['user_id']);
}else{
$newmedia = $weChatObj->uploadMedia('image', "/application/assets/images/wechat_rejected_message.jpg");
$weChatObj->sendCustomImage($newmedia['media_id'], $portraitArr['user_id']);
}
$this->log_history("SUCCESS: Send wechat message to ".$pid."(".$portraitArr['user_id'].")");
}else{
$this->log_history("ERROR: Send wechat message, no ".$pid);
}
}
public function send_douban_message($pid, $status)
{
$portraitArr = $this->portraits_model->get_portrait($pid);
if(count($portraitArr)>0 ){
if($status == 1){
$ch = curl_init();
$data = array('user_id' => $portraitArr['user_id'], 'image' => '@' . "/data/webroot/www/backend/uploads/processed/".$portraitArr["photo_name"]);
curl_setopt($ch, CURLOPT_URL, "/upload");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
$doubanResult = curl_exec($ch);
//$this->log_history("DOUBAN DEBUG: " . json_encode($data));
if ($doubanResult === FALSE) {
$this->log_history("ERROR (1): Send douban message, no ".$pid . " error: " . curl_error($ch));
} else {
$dataDouban = json_decode($doubanResult);
if(isset($dataDouban->url)) {
$this->log_history("SUCCESS: Send douban message to ".$pid."(".$dataDouban->url.")");
} else {
$this->log_history("ERROR (2): Send douban message, no ".$pid . " error: " . $dataDouban);
}
}
}else{
$ch = curl_init();
$data = array('user_id' => $portraitArr['user_id']);
curl_setopt($ch, CURLOPT_URL, "/reject");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
$doubanResult = curl_exec($ch);
if ($doubanResult === FALSE) {
$this->log_history("ERROR (1): Reject douban photo, no ".$pid . " error: " . curl_error($ch));
} else {
$dataDouban = json_decode($doubanResult);
if(isset($dataDouban->r) && $dataDouban->r == 0) {
$this->log_history("SUCCESS: Reject douban photo");
} else {
$this->log_history("ERROR (2): Reject douban photo, error: " . $dataDouban);
}
}
}
}else{
$this->log_history("ERROR (4): Send douban message, no ".$pid);
}
}
public function wechat_portal()
{
$options = array(
'token'=>'weixin_key',
'appid'=>APPID,
'appsecret'=>SECRET,
'debug'=>false,
'logcallback'=>'logdebug'
);
$weObj = new WechatSDK($options);
$weObj->valid();
$type = $weObj->getRev()->getRevType();
$sleep_time = 1.5;
switch($type) {
case WechatSDK::MSGTYPE_TEXT:
break;
case WechatSDK::MSGTYPE_EVENT:
$event_array = $weObj->getRevEvent();
$event_type = $event_array["event"];
// subscribe
if(strcasecmp($event_type, "subscribe") == 0){
$weObj->sendCustomText("感谢关注。", $weObj->getRevFrom());
}
break;
}
}
Private function log_history($text)
{
$file = read_file(LOG_HISTORY);
$text = date('Y/m/d/ h:i:s a', time())." ".$text."<br />\n".$file;
write_file(LOG_HISTORY, $text, "w+");
}
}