HTML5 Client side Image puzzle

Posted: Wednesday, September 12, 2012 by Unknown in Labels:
0

As part of js13kGames competition i developed Client side Image puzzle game.

Game details:- 

User will upload an image of any pixel ratio. The uploaded image will be turned into puzzle. The puzzle will be a 4x4 matrix of jumbled tiles with one missed position. User will have to re-arrange the tiles into the image which was originally uploaded.

Would like to highlight some of the cool stuff that i used.

HTML5 File API
- Uploaded image is not sent to server rather HTML5 File API is used to set the users image to div background.

CSS3 background-size property
- User will upload image of any pixel ratio but the game needs only 500x500 image. CSS3 "background-size" is used to scale the image.

CSS3 scale property
- Legally movable tile is highlighted. Again thanks to CSS3, "scale" property is used  to highlight the legally movable tile on mouse hover.

Drag/Tap (Desktop/Mobile)
- To make sure drag works in both desktop and mobile browsers, I developed simple Drag library which makes use of mouse & touch events.

Code Modularity
- The code is very well distributed and spread across model,controller & view scopes under the main scope "slider". window.scope is the main variable which comprises the whole game.

And here is the entry link http://js13kgames.com/entries/image-puzzle/.

Future enhancements will be tracked here https://github.com/polavenki/HTML5-Client-side-Image-puzzle

Please stop there and play the game and don't forget to like the game too if you really like it :) :)

Welcome your feedback.

Last but not least great thanks to js13KGames for conducting it. Nice leanings !!!

Cheers!!!
Peda Venkateswarlu Pola

HTML5 Webworker best practices

Posted: Saturday, August 18, 2012 by Unknown in Labels:
0


Recently i explored HTML5 web workers and this caught my interest. Am very much excited to use it in performing heavy computation tasks in Javascript. Webworkers really smashes the single thread bottle neck problem in Javascript to some extent. Would like to share few thoughts on how i organized my code base with respect to my requirements.

Requirement 1:-

I had a hard requirement to have frequent communication between the page where the worker is spawned and the worker where all of my business logic resides. Due to which i had to call different functions multiple times to and fro.

So i don't want to bloat up the "worker.onmessage & self.onmessage" callbacks in both parent page and worker with lot of if..else with some conditions.

Here is what i come up with some smart approach where i defined the data structure something like below

{"cmd" : "func_call" , "scope" : ["add", "Controller","task1"],"params" : [1,2]}

If the command is func_call then i will fetch function object specified in the scope array right staring from the "self" as base scope object and is called with the respective params given in the array. In the below code you can find function "callFunction" which takes scope and params arrays and calls respective function with necessary params. Please refer to "worker.onmessage & self.onmessage" callbacks in the below sample code for the usage.

Requirement 2:-

I don't want to mess up my business logic JS files with the web worker specific code because these might be used by non worker application.

"importScirpts" is very helpful to accomplish it.

importScripts.apply(self,["task1.js","task2.js"]); // Assuming task1.js , task2.js are business logic files

Requirement 3:-

I too had to send too much JSON data with deep hierarchy in it between base page & worker. Even though "postMessage" inbuilt supports sending JSON objects in it. I found that sending big JSON's with too much hierarchy in it is causing some problems in webkit and in the receiver side it is coming as empty string.

I suggest to send the JSON data by manually stringifying it.
worker.postMessage(JSON.stringify({"a":{"b":"c"}}));

Requirement 4:-

If we try to load the worker js files using file:// protocol for testing purpose then it will end up with "Uncaught Error: SECURITY_ERR: DOM Exception". You can avoid it by opening chrome.exe with command line param --allow-file-access-from-files

"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --allow-file-access-from-files

Below is the sample example alternatively you can download the code from my github account here Worker-Best-Practices
 
index.html - Base page where the web-worker is spawned
myTaskWorker.js - Worker file
task1.js,task2.js - Contains business logic.


index.html

<html>
<head>
<script>

var loggerDiv;
var postToWorker = function(worker , data){
worker.postMessage(JSON.stringify(data));
};

var callFunction = function(funcScope , params){
for(var i =funcScope.length - 1  , funcObj = self; i>=0 ; i-- ){
if(funcObj) funcObj = funcObj[funcScope[i]];
}
if(typeof funcObj === "function") return funcObj.apply(this , params);
};

var logMessage = function(msg){
loggerDiv.innerHTML+=msg+" < br/>";
};

var worker = new Worker("./js/myTaskWorker.js"),
jsFiles = ["./task1.js","./task2.js"];

worker.onmessage = function(event) {
var instruction = event.data;
instruction = JSON.parse(instruction);

if(instruction["cmd"]==="func_call"){ // Worker trying to talk to function in base page
callFunction(instruction["scope"] , instruction["params"]);
}
 
};

worker.onerror = function(e){
console.log("Exception in Worker : "+e.message);
};


var onPageLoad = function(e){
loggerDiv = document.getElementById("log");
postToWorker(worker,{"cmd" : "start" , "data" : jsFiles}); // Start the worker.

postToWorker(worker,{"cmd" : "func_call" , "scope" : ["add", "Controller","task1"],"params" : [1,2]}); // Calls function directly in worker task1.Controller.getInfo()
postToWorker(worker,{"cmd" : "func_call" , "scope" : ["multiply", "Controller","task2"],"params" : [3,4]}); // Calls function directly in worker task1.Controller.getInfo()

}
</script>
</head>
<body onLoad="onPageLoad();">
<div id="log"> </div>
</body>
</html>

myTaskWorker.js

var postToParent = function(data){
self.postMessage(JSON.stringify(data));
};


var callFunction = function(funcScope , params){
for(var i =funcScope.length - 1  , funcObj = self; i>=0 ; i-- ){
if(funcObj) funcObj = funcObj[funcScope[i]];  
}
if(typeof funcObj === "function") return funcObj.apply(this , params);
};
    
self.onmessage = function(event) {
var instruction = event.data;
instruction = JSON.parse(instruction);
if(instruction["cmd"]==="start"){
importScripts.apply(self,instruction["data"]);
postToParent({"cmd" : "func_call" , "scope" : ["logMessage"],"params" : ["Worker establishment done"]});
}else if(instruction["cmd"]==="func_call"){ // Parent page trying to call worker function
try{
var retValue = callFunction(instruction["scope"] , instruction["params"]),
scope = instruction["scope"].reverse(),
params = instruction["params"];
postToParent({"cmd" : "func_call" , "scope" : ["logMessage"],"params" : ["Value for "+scope.join(".")+" for params "+params.join(",")+" = "+retValue]});
}catch(err){
}
}
};

task1.js

(function(w){
var task1 = {};
task1.Controller = {};
task1.Controller.add = function(a,b){
return a+b;
};
w.task1 = task1;
})(self);

task2.js

(function(w){
var task2 = {};
task2.Controller = {};
task2.Controller.multiply = function(a,b){
return a*b;
};
w.task2 = task2;
})(self);

Cheers!!! Hope you find it useful. 

Google IO 2012 - The Web can do That?

Posted: Saturday, June 30, 2012 by Unknown in Labels:
0

A very wonderful session about future of the WEB. Rapid growth and very great to see WEB having most of the native capabilities. You can find the slides here. Can't wait to play with these things!!


Leave your legacy

Posted: Monday, June 18, 2012 by Unknown in Labels:
0

If you aren't pissed off for greatness, that means you are okay with being mediocre" - Ray Lewis to Stanford basketball men's team.

#leaveyourlegacy from Hooded Trees on Vimeo.

5 x 365 x 8 = Change

Posted: Saturday, June 16, 2012 by Unknown in Labels:
0

I had a perfect "EXECUTION" oriented movie plan. The plan, The commitment, The Sketch & The hard work exhibited in this movie is out standing and can be applied to any category of work.

But i love to apply this formula especially to POLITICS because this is the very worst place where change is required for sure in both politician and citizen as well.


HERO performs several roles through out the film as Mentor , Mentee, Student , Teacher , Slave , Leader based on situations with extreme emotions under self motivation at each moment who finally makes a Common Man to talk like "Come on man!!!"

Entire film has 4 rounds of elections.

1) Election 1 fails though HERO does 200% hard work.
2) Backed up from self motivation, Election 2 wins.
3) Election 3 wins with zero hard work in publicity as he believes what he has done as a Leader.
4) Election 4 - Hero quits politics and enjoys with family.

Climax :-
All media persons targets the hero and question like
-  You are the admirer to each citizen and you will be the next CM too. why did you quit politics?

HERO simply smiles and replies that
- I came here not to become a politician but came here to bring up the change.
- Now every citizen knows how to get the work done from politicians, so my work is done.
                                                             - A very humble response from a commitment oriented guy.

---
Its just outline, I haven't depicted the movie plan completely. I love to discuss if someone is really interested.

Thanks..

Peda Venkateswarlu Pola

Chrome document.title issue

Posted: Tuesday, June 12, 2012 by Unknown in Labels:
0

We generally rotate the page title for the sake of notifications and once the user gains focus of the concerned tab we reset the page title to old one.

This works out mostly in all browsers but in chrome there is a small problem.

Focus gain / lost of chrome browser works fine but there is a problem in focus gain / lost browser tab. In case of browser tab focus gain / lost, Chrome hides the whole browser tab DOM as the tab is not visible to the user and redraws whole DOM as soon as the tab gains focus. I would say this is really a great performance technique.

But the problem comes here only, as the document.title is part of DOM and it is redrawing what ever we set from Javascript in the onfocus listener gets overrides.

As a hack of this we could reset the title in asynch manner something like below,

window.onfocus = function(){

setTimeOut(function(){
document.title = your_title
},200) ;

}
Note : - If you still face the problem even with this approach also, then better increase the title rotation speed to 1-2 sec.
Enhanced by Zemanta

Responsive web design

Posted: Thursday, June 7, 2012 by Unknown in Labels:
0

Responsive web design allows users across a broad range of devices and browsers will have access to a single source of content, laid out so as to be easy to read and navigate with a minimum of resizing, panning, and scrolling.

We generally accomplish it using CSS3 media queries. Found below interesting article which makes use of Javascirpt API's to accomplish it.
https://hacks.mozilla.org/2012/06/using-window-matchmedia-to-do-media-queries-in-javascript/?utm_source=html5weekly&utm_medium=email

Enhanced by Zemanta