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+"); } }