mirror of
https://github.com/YunoHost-Apps/20euros_ynh.git
synced 2024-09-03 18:05:53 +02:00
sources
This commit is contained in:
parent
04f58749aa
commit
5c0a143863
24 changed files with 2792 additions and 3 deletions
|
@ -4,8 +4,6 @@ location __PATH__/ {
|
||||||
# Path to source
|
# Path to source
|
||||||
alias __FINALPATH__/ ;
|
alias __FINALPATH__/ ;
|
||||||
|
|
||||||
20 Euro.html;
|
|
||||||
|
|
||||||
# Force usage of https
|
# Force usage of https
|
||||||
if ($scheme = http) {
|
if ($scheme = http) {
|
||||||
rewrite ^ https://$server_name$request_uri? permanent;
|
rewrite ^ https://$server_name$request_uri? permanent;
|
||||||
|
|
|
@ -57,7 +57,10 @@ ynh_script_progression --message="Setting up source files..." --weight=1
|
||||||
ynh_app_setting_set --app=$app --key=final_path --value=$final_path
|
ynh_app_setting_set --app=$app --key=final_path --value=$final_path
|
||||||
|
|
||||||
# Download, check integrity, uncompress and patch the source from app.src
|
# Download, check integrity, uncompress and patch the source from app.src
|
||||||
ynh_setup_source --dest_dir="$final_path"
|
#ynh_setup_source --dest_dir="$final_path"
|
||||||
|
|
||||||
|
mkdir -p $final_path
|
||||||
|
cp -a ../sources/* $final_path
|
||||||
|
|
||||||
#=================================================
|
#=================================================
|
||||||
# NGINX CONFIGURATION
|
# NGINX CONFIGURATION
|
||||||
|
|
8
sources/README.md
Executable file
8
sources/README.md
Executable file
|
@ -0,0 +1,8 @@
|
||||||
|
20euros
|
||||||
|
=======
|
||||||
|
|
||||||
|
A 2048 variant with Euro coins and notes.
|
||||||
|
|
||||||
|
You'll find the game forum here: http://20euros.freeforums.net/
|
||||||
|
|
||||||
|
Feel free to fork my version and make pull requests!
|
32
sources/comment.html
Executable file
32
sources/comment.html
Executable file
|
@ -0,0 +1,32 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en" manifest="cache.appcache">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta http-equiv="refresh" content="0; url=http://20euros.freeforums.net/">
|
||||||
|
<title>20 Euros Forum</title>
|
||||||
|
|
||||||
|
<link href="style/main.css" rel="stylesheet" type="text/css">
|
||||||
|
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||||
|
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
var sc_project=9719822;
|
||||||
|
var sc_invisible=1;
|
||||||
|
var sc_security="bccc6417";
|
||||||
|
var scJsHost = (("https:" == document.location.protocol) ?
|
||||||
|
"https://secure." : "http://www.");
|
||||||
|
document.write("<sc"+"ript type='text/javascript' src='" +
|
||||||
|
scJsHost+
|
||||||
|
"statcounter.com/counter/counter.js'></"+"script>");
|
||||||
|
</script>
|
||||||
|
<noscript><div class="statcounter"><a title="ingyenes
|
||||||
|
webstatisztika" href="http://www.statcounter.hu/"
|
||||||
|
target="_blank"><img class="statcounter"
|
||||||
|
src="http://c.statcounter.com/9719822/0/bccc6417/1/"
|
||||||
|
alt="ingyenes webstatisztika"></a></div></noscript>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
79
sources/faq.html
Executable file
79
sources/faq.html
Executable file
|
@ -0,0 +1,79 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en" manifest="cache.appcache">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>20 Euros FAQ</title>
|
||||||
|
|
||||||
|
<link href="style/main.css" rel="stylesheet" type="text/css">
|
||||||
|
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||||
|
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
|
||||||
|
|
||||||
|
<meta property="og:title" content="20euro game"/>
|
||||||
|
<meta property="og:site_name" content="20euro game"/>
|
||||||
|
<meta property="og:description" content="Join the coins and get the 20 Euro tile!"/>
|
||||||
|
<meta property="og:image" content="http://gabrielecirulli.github.io/2048/meta/og_image.png"/>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
<div class="heading">
|
||||||
|
<h1 class="title">20 Euros FAQ</h1>
|
||||||
|
</div>
|
||||||
|
<p class="game-intro">Frequently asked questions about my game <a href="http://jatekos101.github.io/20euros">20 Euros</a>.</p>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<h2>Rules</h2>
|
||||||
|
<p><b>Q:</b> The game is buggy, sometimes it won't let me add two equal coins.<br>
|
||||||
|
<b>A:</b> Read the rules under the game first! For example, you can't add up two 2's to make 5, it wouldn't even make sense! To make a 5 cent coin, you have to combine two 2's and a 1.</p>
|
||||||
|
|
||||||
|
<p><b>Q:</b> Why doesn't 2+2+2+2+2 make 10?<br>
|
||||||
|
<b>A:</b> It's clearly written in the rules that at most 3 coins can merge at a time. Otherwise it would be too easy.</p>
|
||||||
|
|
||||||
|
<p><b>Q:</b> Can I continue after winning and make a 50 Euro note?<br>
|
||||||
|
<b>A:</b> Yes! You can even go all the way up to the 500 Euro note, if you can! <a href="http://20euros.freeforums.net/thread/8/500-achievement">That has actually been achieved (with an AI).</a></p>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<h2>Variants</h2>
|
||||||
|
<p><b>Q:</b> Does the game have any variants?<br>
|
||||||
|
<b>A:</b> The only official variant is the <a href="http://jatekos101.github.io/20euros-undo">undo version</a>.</p>
|
||||||
|
|
||||||
|
<p><b>Q:</b> Can I make my own variant/fork?<br>
|
||||||
|
<b>A:</b> Yes! You are free to make your own forks based on my variant, you can download it or <a href="http://github.com/jatekos101/20euros">fork it on GitHub.</a></p>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<h2>Others</h2>
|
||||||
|
<p>
|
||||||
|
<b>Q:</b> Is there a forum about the game?<br>
|
||||||
|
<b>A:</b> Yes, it's <a href="http://jatekos101.github.io/20euros/comment.html">here</a>. Feel free to add comments, suggestions or further questions!</p>
|
||||||
|
|
||||||
|
<p><b>Q:</b> Are the statistics of the game public?<br>
|
||||||
|
<b>A:</b> Yes, you can find them <a href="http://jatekos101.github.io/20euros/statistics.html">here</a>.</p>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
If you didn't find the answer to your question, you can ask it on the <a href="http://jatekos101.github.io/20euros/comment.html">forum</a>.
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
var sc_project=9719822;
|
||||||
|
var sc_invisible=1;
|
||||||
|
var sc_security="bccc6417";
|
||||||
|
var scJsHost = (("https:" == document.location.protocol) ?
|
||||||
|
"https://secure." : "http://www.");
|
||||||
|
document.write("<sc"+"ript type='text/javascript' src='" +
|
||||||
|
scJsHost+
|
||||||
|
"statcounter.com/counter/counter.js'></"+"script>");
|
||||||
|
</script>
|
||||||
|
<noscript><div class="statcounter"><a title="web analytics"
|
||||||
|
href="http://statcounter.com/" target="_blank"><img
|
||||||
|
class="statcounter"
|
||||||
|
src="http://c.statcounter.com/9719822/0/bccc6417/1/"
|
||||||
|
alt="web analytics"></a></div></noscript>
|
||||||
|
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
BIN
sources/images/bg_hr.png
Executable file
BIN
sources/images/bg_hr.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 943 B |
BIN
sources/images/blacktocat.png
Executable file
BIN
sources/images/blacktocat.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
BIN
sources/images/icon_download.png
Executable file
BIN
sources/images/icon_download.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
BIN
sources/images/sprite_download.png
Executable file
BIN
sources/images/sprite_download.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 16 KiB |
161
sources/index.html
Executable file
161
sources/index.html
Executable file
|
@ -0,0 +1,161 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en" manifest="cache.appcache">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>20 Euros</title>
|
||||||
|
|
||||||
|
<link href="style/main.css" rel="stylesheet" type="text/css">
|
||||||
|
<link href="style/example.css" rel="stylesheet" type="text/css">
|
||||||
|
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||||
|
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
|
||||||
|
|
||||||
|
<meta property="og:title" content="20euro game"/>
|
||||||
|
<meta property="og:site_name" content="20euro game"/>
|
||||||
|
<meta property="og:description" content="Join the coins and get the 20 Euro tile!"/>
|
||||||
|
<meta property="og:image" content="http://gabrielecirulli.github.io/2048/meta/og_image.png"/>
|
||||||
|
<script type="text/javascript" src="https://cdn.firebase.com/v0/firebase.js"></script>
|
||||||
|
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
|
||||||
|
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<div class="heading">
|
||||||
|
<h1 class="title">20 Euros</h1>
|
||||||
|
|
||||||
|
<div align="right"><a href="http://jatekos101.github.io/20euros/faq.html">FAQ</a> - <a href="http://jatekos101.github.io/20euros/comment.html">FORUM</a></div>
|
||||||
|
<p>
|
||||||
|
<div class="scores-container">
|
||||||
|
<div class="score-container">0</div>
|
||||||
|
<div class="best-container">0</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p class="game-intro">Join the coins until you reach <strong>20 Euro</strong>!
|
||||||
|
|
||||||
|
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="game-container">
|
||||||
|
<div class="game-message">
|
||||||
|
<p></p>
|
||||||
|
<div class="lower">
|
||||||
|
<a class="keep-playing-button">Continue (maybe 50 Euro?)</a>
|
||||||
|
<a class="retry-button">Retry</a>
|
||||||
|
<div class="score-sharing"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="grid-container">
|
||||||
|
<div class="grid-row">
|
||||||
|
<div class="grid-cell"></div>
|
||||||
|
<div class="grid-cell"></div>
|
||||||
|
<div class="grid-cell"></div>
|
||||||
|
<div class="grid-cell"></div>
|
||||||
|
<div class="grid-cell"></div>
|
||||||
|
</div>
|
||||||
|
<div class="grid-row">
|
||||||
|
<div class="grid-cell"></div>
|
||||||
|
<div class="grid-cell"></div>
|
||||||
|
<div class="grid-cell"></div>
|
||||||
|
<div class="grid-cell"></div>
|
||||||
|
<div class="grid-cell"></div>
|
||||||
|
</div>
|
||||||
|
<div class="grid-row">
|
||||||
|
<div class="grid-cell"></div>
|
||||||
|
<div class="grid-cell"></div>
|
||||||
|
<div class="grid-cell"></div>
|
||||||
|
<div class="grid-cell"></div>
|
||||||
|
<div class="grid-cell"></div>
|
||||||
|
</div>
|
||||||
|
<div class="grid-row">
|
||||||
|
<div class="grid-cell"></div>
|
||||||
|
<div class="grid-cell"></div>
|
||||||
|
<div class="grid-cell"></div>
|
||||||
|
<div class="grid-cell"></div>
|
||||||
|
<div class="grid-cell"></div>
|
||||||
|
</div>
|
||||||
|
<div class="grid-row">
|
||||||
|
<div class="grid-cell"></div>
|
||||||
|
<div class="grid-cell"></div>
|
||||||
|
<div class="grid-cell"></div>
|
||||||
|
<div class="grid-cell"></div>
|
||||||
|
<div class="grid-cell"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="tile-container">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<p class="game-explanation">
|
||||||
|
<strong class="important">HOW TO PLAY: </strong> Use your <strong>arrow keys</strong> to move the coins. If two or three mergeable coins touch, they <strong>merge into one!</strong> Your goal is to reach the <strong>20 Euro</strong> note! Restart with <strong>Space</strong>.
|
||||||
|
</p>
|
||||||
|
<hr>
|
||||||
|
<p class="game-explanation">
|
||||||
|
<strong class="important">Mergeable combinations: </strong> <br>
|
||||||
|
1+1=2<br>
|
||||||
|
2+2+1=5<br>
|
||||||
|
5+5=10<br>
|
||||||
|
10+10=20 or 5+10+5=20<br>
|
||||||
|
20+20+10=50<br>
|
||||||
|
and so on.
|
||||||
|
</p>
|
||||||
|
<hr>
|
||||||
|
<p>
|
||||||
|
<strong class="important">FAQ: </strong> <a href="http://jatekos101.github.io/20euros/faq.html">Click here for the frequently asked questions.</a><br>
|
||||||
|
<strong class="important">Forum: </strong> <a href="http://jatekos101.github.io/20euros/comment.html">Click here for the game's forum.</a><br>
|
||||||
|
<strong class="important">Statistics: </strong> <a href="http://jatekos101.github.io/20euros/statistics.html">Click here for the statistics.</a>
|
||||||
|
</p>
|
||||||
|
<hr>
|
||||||
|
<p>
|
||||||
|
<strong class="important">Undo version: </strong> <a href="http://jatekos101.github.io/20euros-undo">You can play the undo version of the game here.</a>
|
||||||
|
<br>
|
||||||
|
<strong class="important">GITHUB: </strong> <a href="https://github.com/jatekos101/20euros">You can see and fork my game on GitHub here.</a>
|
||||||
|
</p>
|
||||||
|
<hr>
|
||||||
|
<p>
|
||||||
|
This is not the original version of 2048.<br>
|
||||||
|
Original created by Gabriele Cirulli.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script src="js/animframe_polyfill.js"></script>
|
||||||
|
<script src="js/keyboard_input_manager.js"></script>
|
||||||
|
<script src="js/html_actuator.js"></script>
|
||||||
|
<script src="js/grid.js"></script>
|
||||||
|
<script src="js/tile.js"></script>
|
||||||
|
<script src="js/local_score_manager.js"></script>
|
||||||
|
<script src="js/game_manager.js"></script>
|
||||||
|
<script src="js/application.js"></script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
(function(i,s,o,g,r,a,m){i["GoogleAnalyticsObject"]=r;i[r]=i[r]||function(){
|
||||||
|
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
||||||
|
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
||||||
|
})(window,document,"script","//www.google-analytics.com/analytics.js","ga");
|
||||||
|
|
||||||
|
ga("create", "UA-42620757-2", "gabrielecirulli.github.io");
|
||||||
|
ga("send", "pageview");
|
||||||
|
</script>
|
||||||
|
<script type="text/javascript">
|
||||||
|
var sc_project=9719822;
|
||||||
|
var sc_invisible=1;
|
||||||
|
var sc_security="bccc6417";
|
||||||
|
var scJsHost = (("https:" == document.location.protocol) ?
|
||||||
|
"https://secure." : "http://www.");
|
||||||
|
document.write("<sc"+"ript type='text/javascript' src='" +
|
||||||
|
scJsHost+
|
||||||
|
"statcounter.com/counter/counter.js'></"+"script>");
|
||||||
|
</script>
|
||||||
|
<noscript><div class="statcounter"><a title="web analytics"
|
||||||
|
href="http://statcounter.com/" target="_blank"><img
|
||||||
|
class="statcounter"
|
||||||
|
src="http://c.statcounter.com/9719822/0/bccc6417/1/"
|
||||||
|
alt="web analytics"></a></div></noscript>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
1
sources/javascripts/main.js
Executable file
1
sources/javascripts/main.js
Executable file
|
@ -0,0 +1 @@
|
||||||
|
console.log('This would be the main JS file.');
|
26
sources/js/animframe_polyfill.js
Executable file
26
sources/js/animframe_polyfill.js
Executable file
|
@ -0,0 +1,26 @@
|
||||||
|
(function() {
|
||||||
|
var lastTime = 0;
|
||||||
|
var vendors = ['webkit', 'moz'];
|
||||||
|
for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
|
||||||
|
window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
|
||||||
|
window.cancelAnimationFrame =
|
||||||
|
window[vendors[x]+'CancelAnimationFrame'] || window[vendors[x]+'CancelRequestAnimationFrame'];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!window.requestAnimationFrame) {
|
||||||
|
window.requestAnimationFrame = function(callback, element) {
|
||||||
|
var currTime = new Date().getTime();
|
||||||
|
var timeToCall = Math.max(0, 16 - (currTime - lastTime));
|
||||||
|
var id = window.setTimeout(function() { callback(currTime + timeToCall); },
|
||||||
|
timeToCall);
|
||||||
|
lastTime = currTime + timeToCall;
|
||||||
|
return id;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!window.cancelAnimationFrame) {
|
||||||
|
window.cancelAnimationFrame = function(id) {
|
||||||
|
clearTimeout(id);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}());
|
3
sources/js/application.js
Executable file
3
sources/js/application.js
Executable file
|
@ -0,0 +1,3 @@
|
||||||
|
// Wait till the browser is ready to render the game (avoids glitches)
|
||||||
|
window.requestAnimationFrame(function () {
|
||||||
|
new GameManager(5, KeyboardInputManager, HTMLActuator, LocalScoreManager);});
|
328
sources/js/game_manager.js
Executable file
328
sources/js/game_manager.js
Executable file
|
@ -0,0 +1,328 @@
|
||||||
|
function GameManager(size, InputManager, Actuator, ScoreManager) {
|
||||||
|
this.size = size; // Size of the grid
|
||||||
|
this.inputManager = new InputManager;
|
||||||
|
this.scoreManager = new ScoreManager;
|
||||||
|
this.actuator = new Actuator;
|
||||||
|
|
||||||
|
this.startTiles = 2;
|
||||||
|
|
||||||
|
this.inputManager.on("move", this.move.bind(this));
|
||||||
|
this.inputManager.on("restart", this.restart.bind(this));
|
||||||
|
this.inputManager.on("keepPlaying", this.keepPlaying.bind(this));
|
||||||
|
|
||||||
|
this.setup();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Restart the game
|
||||||
|
GameManager.prototype.restart = function () {
|
||||||
|
this.actuator.
|
||||||
|
continue ();
|
||||||
|
this.setup();
|
||||||
|
};
|
||||||
|
|
||||||
|
// Keep playing after winning
|
||||||
|
GameManager.prototype.keepPlaying = function () {
|
||||||
|
this.keepPlaying = true;
|
||||||
|
this.actuator.
|
||||||
|
continue ();
|
||||||
|
};
|
||||||
|
|
||||||
|
GameManager.prototype.isGameTerminated = function () {
|
||||||
|
if (this.over || (this.won && !this.keepPlaying)) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Set up the game
|
||||||
|
GameManager.prototype.setup = function () {
|
||||||
|
this.grid = new Grid(this.size);
|
||||||
|
|
||||||
|
this.score = 0;
|
||||||
|
this.highestTile = 5;
|
||||||
|
this.over = false;
|
||||||
|
this.won = false;
|
||||||
|
this.keepPlaying = false;
|
||||||
|
|
||||||
|
// Add the initial tiles
|
||||||
|
this.addStartTiles();
|
||||||
|
|
||||||
|
// Update the actuator
|
||||||
|
this.actuate();
|
||||||
|
};
|
||||||
|
|
||||||
|
// Set up the initial tiles to start the game with
|
||||||
|
GameManager.prototype.addStartTiles = function () {
|
||||||
|
for (var i = 0; i < this.startTiles; i++) {
|
||||||
|
this.addRandomTile();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Adds a tile in a random position
|
||||||
|
GameManager.prototype.addRandomTile = function () {
|
||||||
|
if (this.grid.cellsAvailable()) {
|
||||||
|
var value = Math.random() < 0.9 ? 1 : 5;
|
||||||
|
var tile = new Tile(this.grid.randomAvailableCell(), value);
|
||||||
|
|
||||||
|
this.grid.insertTile(tile);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Sends the updated grid to the actuator
|
||||||
|
GameManager.prototype.actuate = function () {
|
||||||
|
if (this.scoreManager.get() < this.score) {
|
||||||
|
this.scoreManager.set(this.score);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.actuator.actuate(this.grid, {
|
||||||
|
score: this.score,
|
||||||
|
highest: this.highestTile,
|
||||||
|
over: this.over,
|
||||||
|
won: this.won,
|
||||||
|
bestScore: this.scoreManager.get(),
|
||||||
|
terminated: this.isGameTerminated()
|
||||||
|
});
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
// Save all tile positions and remove merger info
|
||||||
|
GameManager.prototype.prepareTiles = function () {
|
||||||
|
this.grid.eachCell(function (x, y, tile) {
|
||||||
|
if (tile) {
|
||||||
|
tile.mergedFrom = null;
|
||||||
|
tile.savePosition();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// Move a tile and its representation
|
||||||
|
GameManager.prototype.moveTile = function (tile, cell) {
|
||||||
|
this.grid.cells[tile.x][tile.y] = null;
|
||||||
|
this.grid.cells[cell.x][cell.y] = tile;
|
||||||
|
tile.updatePosition(cell);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Move tiles on the grid in the specified direction
|
||||||
|
GameManager.prototype.move = function (direction) {
|
||||||
|
// 0: up, 1: right, 2:down, 3: left
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
if (this.isGameTerminated()) return; // Don't do anything if the game's over
|
||||||
|
var cell, tile;
|
||||||
|
|
||||||
|
var vector = this.getVector(direction);
|
||||||
|
var traversals = this.buildTraversals(vector);
|
||||||
|
var moved = false;
|
||||||
|
|
||||||
|
// Save the current tile positions and remove merger information
|
||||||
|
this.prepareTiles();
|
||||||
|
|
||||||
|
// Traverse the grid in the right direction and move tiles
|
||||||
|
traversals.x.forEach(function (x) {
|
||||||
|
traversals.y.forEach(function (y) {
|
||||||
|
cell = {
|
||||||
|
x: x,
|
||||||
|
y: y
|
||||||
|
};
|
||||||
|
tile = self.grid.cellContent(cell);
|
||||||
|
|
||||||
|
if (tile && tile.merged) {
|
||||||
|
self.grid.removeTile(tile);
|
||||||
|
} else if (tile) {
|
||||||
|
var positions = self.findFarthestPosition(cell, vector);
|
||||||
|
var next = self.grid.cellContent(positions.next);
|
||||||
|
var pos2 = null;
|
||||||
|
var next2 = null;
|
||||||
|
if (next) {
|
||||||
|
pos2 = self.findFarthestPosition({
|
||||||
|
x: next.x,
|
||||||
|
y: next.y
|
||||||
|
}, vector);
|
||||||
|
next2 = self.grid.cellContent(pos2.next);
|
||||||
|
}
|
||||||
|
// Only one merger per row traversal?
|
||||||
|
if (next && next2 && !next.mergedFrom && next != next2 && (((tile.value == 1) && (next.value == 2) && (next2.value == 2)) || ((tile.value == 2) && (next.value == 1) && (next2.value == 2)) || ((tile.value == 2) && (next.value == 2) && (next2.value == 1)) || ((tile.value == 10) && (next.value == 20) && (next2.value == 20)) || ((tile.value == 20) && (next.value == 10) && (next2.value == 20)) || ((tile.value == 20) && (next.value == 20) && (next2.value == 10)) || ((tile.value == 100) && (next.value == 200) && (next2.value == 200)) || ((tile.value == 200) && (next.value == 100) && (next2.value == 200)) || ((tile.value == 200) && (next.value == 200) && (next2.value == 100)) || ((tile.value == 1000) && (next.value == 2000) && (next2.value == 2000)) || ((tile.value == 2000) && (next.value == 1000) && (next2.value == 2000)) || ((tile.value == 2000) && (next.value == 2000) && (next2.value == 1000)) || ((tile.value == 10000) && (next.value == 20000) && (next2.value == 20000)) || ((tile.value == 20000) && (next.value == 10000) && (next2.value == 20000)) || ((tile.value == 20000) && (next.value == 20000) && (next2.value == 10000)) || ((tile.value == 5) && (next.value == 10) && (next2.value == 5)) || ((tile.value == 50) && (next.value == 100) && (next2.value == 50)) || ((tile.value == 500) && (next.value == 1000) && (next2.value == 500)) || ((tile.value == 5000) && (next.value == 10000) && (next2.value == 5000)))) {
|
||||||
|
|
||||||
|
var merged = new Tile(pos2.next, tile.value + next.value + next2.value);
|
||||||
|
merged.mergedFrom = [next2, next, tile];
|
||||||
|
tile.merged = true;
|
||||||
|
next.merged = true;
|
||||||
|
next2.merged = true;
|
||||||
|
|
||||||
|
self.grid.removeTile(tile);
|
||||||
|
self.grid.removeTile(next);
|
||||||
|
self.grid.removeTile(next2);
|
||||||
|
|
||||||
|
self.grid.insertTile(merged);
|
||||||
|
// Converge the two tiles' positions
|
||||||
|
tile.updatePosition(pos2.next);
|
||||||
|
next.updatePosition(pos2.next);
|
||||||
|
// Update the score
|
||||||
|
self.score += merged.value;
|
||||||
|
|
||||||
|
if (merged.value > self.highestTile) self.highestTile = merged.value;
|
||||||
|
|
||||||
|
// The mighty 20 Euro tile
|
||||||
|
if (merged.value === 2000) self.won = true;
|
||||||
|
} else if (next && next.value === tile.value && !next.mergedFrom && next.value != 2 && next.value != 20 && next.value != 200 && next.value != 2000 && next.value != 20000 && next.value != 50000) {
|
||||||
|
|
||||||
|
var merged = new Tile(positions.next, tile.value * 2);
|
||||||
|
merged.mergedFrom = [tile, next];
|
||||||
|
tile.merged = true;
|
||||||
|
next.merged = true;
|
||||||
|
|
||||||
|
self.grid.insertTile(merged);
|
||||||
|
self.grid.removeTile(tile);
|
||||||
|
|
||||||
|
// Converge the two tiles' positions
|
||||||
|
tile.updatePosition(positions.next);
|
||||||
|
|
||||||
|
// Update the score
|
||||||
|
self.score += merged.value;
|
||||||
|
|
||||||
|
if (merged.value > self.highestTile) self.highestTile = merged.value;
|
||||||
|
|
||||||
|
// The mighty 20 Euro tile
|
||||||
|
if (merged.value === 2000) self.won = true;
|
||||||
|
} else if (!tile.merged) {
|
||||||
|
self.moveTile(tile, positions.farthest);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tile && !self.positionsEqual(cell, tile)) {
|
||||||
|
moved = true; // The tile moved from its original cell!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
if (moved) {
|
||||||
|
this.addRandomTile();
|
||||||
|
|
||||||
|
if (!this.movesAvailable()) {
|
||||||
|
this.over = true; // Game over!
|
||||||
|
}
|
||||||
|
|
||||||
|
this.actuate();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get the vector representing the chosen direction
|
||||||
|
GameManager.prototype.getVector = function (direction) {
|
||||||
|
// Vectors representing tile movement
|
||||||
|
var map = {
|
||||||
|
0: {
|
||||||
|
x: 0,
|
||||||
|
y: -1
|
||||||
|
},
|
||||||
|
// up
|
||||||
|
1: {
|
||||||
|
x: 1,
|
||||||
|
y: 0
|
||||||
|
},
|
||||||
|
// right
|
||||||
|
2: {
|
||||||
|
x: 0,
|
||||||
|
y: 1
|
||||||
|
},
|
||||||
|
// down
|
||||||
|
3: {
|
||||||
|
x: -1,
|
||||||
|
y: 0
|
||||||
|
} // left
|
||||||
|
};
|
||||||
|
|
||||||
|
return map[direction];
|
||||||
|
};
|
||||||
|
|
||||||
|
// Build a list of positions to traverse in the right order
|
||||||
|
GameManager.prototype.buildTraversals = function (vector) {
|
||||||
|
var traversals = {
|
||||||
|
x: [],
|
||||||
|
y: []
|
||||||
|
};
|
||||||
|
|
||||||
|
for (var pos = 0; pos < this.size; pos++) {
|
||||||
|
traversals.x.push(pos);
|
||||||
|
traversals.y.push(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Always traverse from the farthest cell in the chosen direction
|
||||||
|
if (vector.x === 1) traversals.x = traversals.x.reverse();
|
||||||
|
if (vector.y === 1) traversals.y = traversals.y.reverse();
|
||||||
|
|
||||||
|
return traversals;
|
||||||
|
};
|
||||||
|
|
||||||
|
GameManager.prototype.findFarthestPosition = function (cell, vector) {
|
||||||
|
var previous;
|
||||||
|
|
||||||
|
// Progress towards the vector direction until an obstacle is found
|
||||||
|
do {
|
||||||
|
previous = cell;
|
||||||
|
cell = {
|
||||||
|
x: previous.x + vector.x,
|
||||||
|
y: previous.y + vector.y
|
||||||
|
};
|
||||||
|
} while (this.grid.withinBounds(cell) && this.grid.cellAvailable(cell));
|
||||||
|
|
||||||
|
return {
|
||||||
|
farthest: previous,
|
||||||
|
next: cell // Used to check if a merge is required
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
GameManager.prototype.movesAvailable = function () {
|
||||||
|
return this.grid.cellsAvailable() || this.tileMatchesAvailable();
|
||||||
|
};
|
||||||
|
|
||||||
|
// Check for available matches between tiles(more expensive check)
|
||||||
|
GameManager.prototype.tileMatchesAvailable = function () {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
var tile;
|
||||||
|
var i = 0;
|
||||||
|
while (i < 4) {
|
||||||
|
for (var x = 0; x < this.size; x++) {
|
||||||
|
for (var y = 0; y < this.size; y++) {
|
||||||
|
var vector = this.getVector(i);
|
||||||
|
tile = this.grid.cellContent({
|
||||||
|
x: x,
|
||||||
|
y: y
|
||||||
|
});
|
||||||
|
|
||||||
|
cell = {
|
||||||
|
x: x,
|
||||||
|
y: y
|
||||||
|
};
|
||||||
|
tile = self.grid.cellContent(cell);
|
||||||
|
|
||||||
|
if (tile) {
|
||||||
|
var positions = self.findFarthestPosition(cell, vector);
|
||||||
|
var next = self.grid.cellContent(positions.next);
|
||||||
|
var pos2 = self.findFarthestPosition({
|
||||||
|
x: cell.x + vector.x,
|
||||||
|
y: cell.y + vector.y
|
||||||
|
}, vector);
|
||||||
|
var next2 = self.grid.cellContent(pos2.next);
|
||||||
|
// Only one merger per row traversal?
|
||||||
|
if (next && next2 && next != next2 && (((tile.value == 1) && (next.value == 2) && (next2.value == 2)) || ((tile.value == 2) && (next.value == 1) && (next2.value == 2)) || ((tile.value == 2) && (next.value == 2) && (next2.value == 1)) || ((tile.value == 10) && (next.value == 20) && (next2.value == 20)) || ((tile.value == 20) && (next.value == 10) && (next2.value == 20)) || ((tile.value == 20) && (next.value == 20) && (next2.value == 10)) || ((tile.value == 100) && (next.value == 200) && (next2.value == 200)) || ((tile.value == 200) && (next.value == 100) && (next2.value == 200)) || ((tile.value == 200) && (next.value == 200) && (next2.value == 100)) || ((tile.value == 1000) && (next.value == 2000) && (next2.value == 2000)) || ((tile.value == 2000) && (next.value == 1000) && (next2.value == 2000)) || ((tile.value == 2000) && (next.value == 2000) && (next2.value == 1000)) || ((tile.value == 10000) && (next.value == 20000) && (next2.value == 20000)) || ((tile.value == 20000) && (next.value == 10000) && (next2.value == 20000)) || ((tile.value == 20000) && (next.value == 20000) && (next2.value == 10000)) || ((tile.value == 5) && (next.value == 10) && (next2.value == 5)) || ((tile.value == 50) && (next.value == 100) && (next2.value == 50)) || ((tile.value == 500) && (next.value == 1000) && (next2.value == 500)) || ((tile.value == 5000) && (next.value == 10000) && (next2.value == 5000)))) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (next && next.value === tile.value && next.value != 2 && next.value != 20 && next.value != 200 && next.value != 2000 && next.value != 20000 && next.value != 50000) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
GameManager.prototype.positionsEqual = function (first, second) {
|
||||||
|
return first.x === second.x && first.y === second.y;
|
||||||
|
};
|
84
sources/js/grid.js
Executable file
84
sources/js/grid.js
Executable file
|
@ -0,0 +1,84 @@
|
||||||
|
function Grid(size) {
|
||||||
|
this.size = size;
|
||||||
|
|
||||||
|
this.cells = [];
|
||||||
|
|
||||||
|
this.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build a grid of the specified size
|
||||||
|
Grid.prototype.build = function () {
|
||||||
|
for (var x = 0; x < this.size; x++) {
|
||||||
|
var row = this.cells[x] = [];
|
||||||
|
|
||||||
|
for (var y = 0; y < this.size; y++) {
|
||||||
|
row.push(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Find the first available random position
|
||||||
|
Grid.prototype.randomAvailableCell = function () {
|
||||||
|
var cells = this.availableCells();
|
||||||
|
|
||||||
|
if (cells.length) {
|
||||||
|
return cells[Math.floor(Math.random() * cells.length)];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Grid.prototype.availableCells = function () {
|
||||||
|
var cells = [];
|
||||||
|
|
||||||
|
this.eachCell(function (x, y, tile) {
|
||||||
|
if (!tile) {
|
||||||
|
cells.push({ x: x, y: y });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return cells;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Call callback for every cell
|
||||||
|
Grid.prototype.eachCell = function (callback) {
|
||||||
|
for (var x = 0; x < this.size; x++) {
|
||||||
|
for (var y = 0; y < this.size; y++) {
|
||||||
|
callback(x, y, this.cells[x][y]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Check if there are any cells available
|
||||||
|
Grid.prototype.cellsAvailable = function () {
|
||||||
|
return !!this.availableCells().length;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Check if the specified cell is taken
|
||||||
|
Grid.prototype.cellAvailable = function (cell) {
|
||||||
|
return !this.cellOccupied(cell);
|
||||||
|
};
|
||||||
|
|
||||||
|
Grid.prototype.cellOccupied = function (cell) {
|
||||||
|
return !!this.cellContent(cell);
|
||||||
|
};
|
||||||
|
|
||||||
|
Grid.prototype.cellContent = function (cell) {
|
||||||
|
if (this.withinBounds(cell)) {
|
||||||
|
return this.cells[cell.x][cell.y];
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Inserts a tile at its position
|
||||||
|
Grid.prototype.insertTile = function (tile) {
|
||||||
|
this.cells[tile.x][tile.y] = tile;
|
||||||
|
};
|
||||||
|
|
||||||
|
Grid.prototype.removeTile = function (tile) {
|
||||||
|
this.cells[tile.x][tile.y] = null;
|
||||||
|
};
|
||||||
|
|
||||||
|
Grid.prototype.withinBounds = function (position) {
|
||||||
|
return position.x >= 0 && position.x < this.size &&
|
||||||
|
position.y >= 0 && position.y < this.size;
|
||||||
|
};
|
337
sources/js/html_actuator.js
Executable file
337
sources/js/html_actuator.js
Executable file
|
@ -0,0 +1,337 @@
|
||||||
|
function HTMLActuator() {
|
||||||
|
this.tileContainer = document.querySelector(".tile-container");
|
||||||
|
this.scoreContainer = document.querySelector(".score-container");
|
||||||
|
this.bestContainer = document.querySelector(".best-container");
|
||||||
|
this.messageContainer = document.querySelector(".game-message");
|
||||||
|
this.sharingContainer = document.querySelector(".score-sharing");
|
||||||
|
|
||||||
|
this.score = 0;
|
||||||
|
this.highestTile = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
HTMLActuator.prototype.actuate = function (grid, metadata) {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
window.requestAnimationFrame(function () {
|
||||||
|
self.clearContainer(self.tileContainer);
|
||||||
|
|
||||||
|
grid.cells.forEach(function (column) {
|
||||||
|
column.forEach(function (cell) {
|
||||||
|
if (cell) {
|
||||||
|
self.addTile(cell);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
self.updateScore(metadata.score);
|
||||||
|
self.updateBestScore(metadata.bestScore);
|
||||||
|
self.highestTile = metadata.highest;
|
||||||
|
|
||||||
|
if (metadata.terminated) {
|
||||||
|
if (metadata.over) {
|
||||||
|
self.message(false); // You lose
|
||||||
|
} else if (metadata.won) {
|
||||||
|
self.message(true); // You win!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// Continues the game (both restart and keep playing)
|
||||||
|
HTMLActuator.prototype.continue = function () {
|
||||||
|
if (typeof ga !== "undefined") {
|
||||||
|
ga("send", "event", "game", "restart");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.clearMessage();
|
||||||
|
};
|
||||||
|
|
||||||
|
HTMLActuator.prototype.clearContainer = function (container) {
|
||||||
|
while (container.firstChild) {
|
||||||
|
container.removeChild(container.firstChild);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
HTMLActuator.prototype.addTile = function (tile) {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
var wrapper = document.createElement("div");
|
||||||
|
var inner = document.createElement("div");
|
||||||
|
var position = tile.previousPosition || { x: tile.x, y: tile.y };
|
||||||
|
var positionClass = this.positionClass(position);
|
||||||
|
|
||||||
|
// We can't use classlist because it somehow glitches when replacing classes
|
||||||
|
var classes = ["tile", "tile-" + tile.value, positionClass];
|
||||||
|
|
||||||
|
if (tile.value > 50000) classes.push("tile-super");
|
||||||
|
|
||||||
|
this.applyClasses(wrapper, classes);
|
||||||
|
|
||||||
|
inner.classList.add("tile-inner");
|
||||||
|
inner.textContent = tile.value;
|
||||||
|
|
||||||
|
if (tile.previousPosition) {
|
||||||
|
// Make sure that the tile gets rendered in the previous position first
|
||||||
|
window.requestAnimationFrame(function () {
|
||||||
|
classes[2] = self.positionClass({ x: tile.x, y: tile.y });
|
||||||
|
self.applyClasses(wrapper, classes); // Update the position
|
||||||
|
});
|
||||||
|
} else if (tile.mergedFrom) {
|
||||||
|
classes.push("tile-merged");
|
||||||
|
this.applyClasses(wrapper, classes);
|
||||||
|
|
||||||
|
// Render the tiles that merged
|
||||||
|
tile.mergedFrom.forEach(function (merged) {
|
||||||
|
self.addTile(merged);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
classes.push("tile-new");
|
||||||
|
this.applyClasses(wrapper, classes);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the inner part of the tile to the wrapper
|
||||||
|
wrapper.appendChild(inner);
|
||||||
|
|
||||||
|
// Put the tile on the board
|
||||||
|
this.tileContainer.appendChild(wrapper);
|
||||||
|
};
|
||||||
|
|
||||||
|
HTMLActuator.prototype.applyClasses = function (element, classes) {
|
||||||
|
element.setAttribute("class", classes.join(" "));
|
||||||
|
};
|
||||||
|
|
||||||
|
HTMLActuator.prototype.normalizePosition = function (position) {
|
||||||
|
return { x: position.x + 1, y: position.y + 1 };
|
||||||
|
};
|
||||||
|
|
||||||
|
HTMLActuator.prototype.positionClass = function (position) {
|
||||||
|
position = this.normalizePosition(position);
|
||||||
|
return "tile-position-" + position.x + "-" + position.y;
|
||||||
|
};
|
||||||
|
|
||||||
|
HTMLActuator.prototype.updateScore = function (score) {
|
||||||
|
this.clearContainer(this.scoreContainer);
|
||||||
|
|
||||||
|
var difference = score - this.score;
|
||||||
|
this.score = score;
|
||||||
|
|
||||||
|
this.scoreContainer.textContent = this.score;
|
||||||
|
|
||||||
|
if (difference > 0) {
|
||||||
|
var addition = document.createElement("div");
|
||||||
|
addition.classList.add("score-addition");
|
||||||
|
addition.textContent = "+" + difference;
|
||||||
|
|
||||||
|
this.scoreContainer.appendChild(addition);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
HTMLActuator.prototype.updateBestScore = function (bestScore) {
|
||||||
|
this.bestContainer.textContent = bestScore;
|
||||||
|
};
|
||||||
|
|
||||||
|
HTMLActuator.prototype.message = function (won) {
|
||||||
|
var type = won ? "game-won" : "game-over";
|
||||||
|
var message = won ? "You won!" : "No more moves. Game over.";
|
||||||
|
|
||||||
|
// Build some firebase references.
|
||||||
|
var rootRef = new Firebase('https://20-euros.firebaseio.com');
|
||||||
|
var scoreListRef = rootRef.child("scoreList");
|
||||||
|
var highestScoreRef = rootRef.child("highestScore");
|
||||||
|
var RefPlays = rootRef.child("plays");
|
||||||
|
var Ref50 = rootRef.child("reached_50c");
|
||||||
|
var Ref100 = rootRef.child("reached_1e");
|
||||||
|
var Ref200 = rootRef.child("reached_2e");
|
||||||
|
var Ref500 = rootRef.child("reached_5e");
|
||||||
|
var Ref1000 = rootRef.child("reached_10e");
|
||||||
|
var Ref2000 = rootRef.child("reached_20e");
|
||||||
|
var Ref5000 = rootRef.child("reached_50e");
|
||||||
|
var Ref10000 = rootRef.child("reached_100e");
|
||||||
|
var Ref20000 = rootRef.child("reached_200e");
|
||||||
|
var Ref50000 = rootRef.child("reached_500e");
|
||||||
|
|
||||||
|
// Keep a mapping of firebase locations to HTML elements, so we can move / remove elements as necessary.
|
||||||
|
var htmlForPath = {};
|
||||||
|
|
||||||
|
// Helper function that takes a new score snapshot and adds an appropriate row to our leaderboard table.
|
||||||
|
function handleScoreAdded(scoreSnapshot, prevScoreName) {
|
||||||
|
var newScoreRow = $("<tr/>");
|
||||||
|
newScoreRow.append($("<td/>").append($("<em/>").text(scoreSnapshot.val().name)));
|
||||||
|
newScoreRow.append($("<td/>").text(scoreSnapshot.val().score));
|
||||||
|
|
||||||
|
// Store a reference to the table row so we can get it again later.
|
||||||
|
htmlForPath[scoreSnapshot.name()] = newScoreRow;
|
||||||
|
|
||||||
|
// Insert the new score in the appropriate place in the table.
|
||||||
|
if (prevScoreName === null) {
|
||||||
|
$("#leaderboardTable").append(newScoreRow);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var lowerScoreRow = htmlForPath[prevScoreName];
|
||||||
|
lowerScoreRow.before(newScoreRow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper function to handle a score object being removed; just removes the corresponding table row.
|
||||||
|
function handleScoreRemoved(scoreSnapshot) {
|
||||||
|
var removedScoreRow = htmlForPath[scoreSnapshot.name()];
|
||||||
|
removedScoreRow.remove();
|
||||||
|
delete htmlForPath[scoreSnapshot.name()];
|
||||||
|
}
|
||||||
|
|
||||||
|
function makeid()
|
||||||
|
{
|
||||||
|
var text = "";
|
||||||
|
var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||||
|
|
||||||
|
for( var i=0; i < 8; i++ )
|
||||||
|
text += possible.charAt(Math.floor(Math.random() * possible.length));
|
||||||
|
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a view to only receive callbacks for the last LEADERBOARD_SIZE scores
|
||||||
|
var scoreListView = scoreListRef.limit(10);
|
||||||
|
|
||||||
|
// Add a callback to handle when a new score is added.
|
||||||
|
scoreListView.on('child_added', function (newScoreSnapshot, prevScoreName) {
|
||||||
|
handleScoreAdded(newScoreSnapshot, prevScoreName);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add a callback to handle when a score is removed
|
||||||
|
scoreListView.on('child_removed', function (oldScoreSnapshot) {
|
||||||
|
handleScoreRemoved(oldScoreSnapshot);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add a callback to handle when a score changes or moves positions.
|
||||||
|
var changedCallback = function (scoreSnapshot, prevScoreName) {
|
||||||
|
handleScoreRemoved(scoreSnapshot);
|
||||||
|
handleScoreAdded(scoreSnapshot, prevScoreName);
|
||||||
|
};
|
||||||
|
scoreListView.on('child_moved', changedCallback);
|
||||||
|
scoreListView.on('child_changed', changedCallback);
|
||||||
|
|
||||||
|
var newScore = this.score;
|
||||||
|
var name = makeid();
|
||||||
|
$("#scoreInput").val("");
|
||||||
|
|
||||||
|
var userScoreRef = scoreListRef.child(name);
|
||||||
|
|
||||||
|
// Use setWithPriority to put the name / score in Firebase, and set the priority to be the score.
|
||||||
|
if ((newScore <= 500)||(this.highestTile <= 20)||(this.highestTile >= 2000)){
|
||||||
|
userScoreRef.setWithPriority({ name:name, score:newScore, highest:this.highestTile }, newScore);}
|
||||||
|
|
||||||
|
// Track the highest score using a transaction. A transaction guarantees that the code inside the block is
|
||||||
|
// executed on the latest data from the server, so transactions should be used if you have multiple
|
||||||
|
// clients writing to the same data and you want to avoid conflicting changes.
|
||||||
|
highestScoreRef.transaction(function (currentHighestScore) {
|
||||||
|
if (currentHighestScore === null || newScore > currentHighestScore) {
|
||||||
|
// The return value of this function gets saved to the server as the new highest score.
|
||||||
|
return newScore;
|
||||||
|
}
|
||||||
|
// if we return with no arguments, it cancels the transaction.
|
||||||
|
return;
|
||||||
|
});
|
||||||
|
|
||||||
|
RefPlays.transaction(function(current_value) {
|
||||||
|
return current_value + 1;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (this.highestTile >= 50){
|
||||||
|
Ref50.transaction(function(current_value) {
|
||||||
|
return current_value + 1;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.highestTile >= 100){
|
||||||
|
Ref100.transaction(function(current_value) {
|
||||||
|
return current_value + 1;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.highestTile >= 200){
|
||||||
|
Ref200.transaction(function(current_value) {
|
||||||
|
return current_value + 1;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.highestTile >= 500){
|
||||||
|
Ref500.transaction(function(current_value) {
|
||||||
|
return current_value + 1;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.highestTile >= 1000){
|
||||||
|
Ref1000.transaction(function(current_value) {
|
||||||
|
return current_value + 1;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.highestTile >= 2000){
|
||||||
|
Ref2000.transaction(function(current_value) {
|
||||||
|
return current_value + 1;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.highestTile >= 5000){
|
||||||
|
Ref5000.transaction(function(current_value) {
|
||||||
|
return current_value + 1;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.highestTile >= 10000){
|
||||||
|
Ref10000.transaction(function(current_value) {
|
||||||
|
return current_value + 1;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.highestTile >= 20000){
|
||||||
|
Ref20000.transaction(function(current_value) {
|
||||||
|
return current_value + 1;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.highestTile >= 50000){
|
||||||
|
Ref50000.transaction(function(current_value) {
|
||||||
|
return current_value + 1;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add a callback to the highest score in Firebase so we can update the GUI any time it changes.
|
||||||
|
highestScoreRef.on('value', function (newHighestScore) {
|
||||||
|
$("#highestScoreDiv").text(newHighestScore.val());
|
||||||
|
});
|
||||||
|
|
||||||
|
if (typeof ga !== "undefined") {
|
||||||
|
ga("send", "event", "game", "end", type, this.score);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.messageContainer.classList.add(type);
|
||||||
|
this.messageContainer.getElementsByTagName("p")[0].textContent = message;
|
||||||
|
|
||||||
|
this.clearContainer(this.sharingContainer);
|
||||||
|
this.sharingContainer.appendChild(this.scoreTweetButton());
|
||||||
|
twttr.widgets.load();
|
||||||
|
};
|
||||||
|
|
||||||
|
HTMLActuator.prototype.clearMessage = function () {
|
||||||
|
// IE only takes one value to remove at a time.
|
||||||
|
this.messageContainer.classList.remove("game-won");
|
||||||
|
this.messageContainer.classList.remove("game-over");
|
||||||
|
};
|
||||||
|
|
||||||
|
HTMLActuator.prototype.scoreTweetButton = function () {
|
||||||
|
var tweet = document.createElement("a");
|
||||||
|
tweet.classList.add("twitter-share-button");
|
||||||
|
tweet.setAttribute("href", "https://twitter.com/share");
|
||||||
|
tweet.setAttribute("data-via", "gabrielecirulli");
|
||||||
|
tweet.setAttribute("data-url", "http://git.io/2048");
|
||||||
|
tweet.setAttribute("data-counturl", "http://gabrielecirulli.github.io/2048/");
|
||||||
|
tweet.textContent = "Tweet";
|
||||||
|
var text = "I got " + this.score + " points in 20 Euro, a game where you " +
|
||||||
|
"join numbers to score high! #20eurogame";
|
||||||
|
tweet.setAttribute("data-text", text);
|
||||||
|
|
||||||
|
return tweet;
|
||||||
|
};
|
130
sources/js/keyboard_input_manager.js
Executable file
130
sources/js/keyboard_input_manager.js
Executable file
|
@ -0,0 +1,130 @@
|
||||||
|
function KeyboardInputManager() {
|
||||||
|
this.events = {};
|
||||||
|
|
||||||
|
if (window.navigator.msPointerEnabled) {
|
||||||
|
//Internet Explorer 10 style
|
||||||
|
this.eventTouchstart = "MSPointerDown";
|
||||||
|
this.eventTouchmove = "MSPointerMove";
|
||||||
|
this.eventTouchend = "MSPointerUp";
|
||||||
|
} else {
|
||||||
|
this.eventTouchstart = "touchstart";
|
||||||
|
this.eventTouchmove = "touchmove";
|
||||||
|
this.eventTouchend = "touchend";
|
||||||
|
}
|
||||||
|
|
||||||
|
this.listen();
|
||||||
|
}
|
||||||
|
|
||||||
|
KeyboardInputManager.prototype.on = function (event, callback) {
|
||||||
|
if (!this.events[event]) {
|
||||||
|
this.events[event] = [];
|
||||||
|
}
|
||||||
|
this.events[event].push(callback);
|
||||||
|
};
|
||||||
|
|
||||||
|
KeyboardInputManager.prototype.emit = function (event, data) {
|
||||||
|
var callbacks = this.events[event];
|
||||||
|
if (callbacks) {
|
||||||
|
callbacks.forEach(function (callback) {
|
||||||
|
callback(data);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
KeyboardInputManager.prototype.listen = function () {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
var map = {
|
||||||
|
38: 0, // Up
|
||||||
|
39: 1, // Right
|
||||||
|
40: 2, // Down
|
||||||
|
37: 3, // Left
|
||||||
|
75: 0, // vim keybindings
|
||||||
|
76: 1,
|
||||||
|
74: 2,
|
||||||
|
72: 3,
|
||||||
|
87: 0, // W
|
||||||
|
68: 1, // D
|
||||||
|
83: 2, // S
|
||||||
|
65: 3 // A
|
||||||
|
};
|
||||||
|
|
||||||
|
document.addEventListener("keydown", function (event) {
|
||||||
|
var modifiers = event.altKey || event.ctrlKey || event.metaKey ||
|
||||||
|
event.shiftKey;
|
||||||
|
var mapped = map[event.which];
|
||||||
|
|
||||||
|
if (!modifiers) {
|
||||||
|
if (mapped !== undefined) {
|
||||||
|
event.preventDefault();
|
||||||
|
self.emit("move", mapped);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.which === 32) self.restart.bind(self)(event);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var retry = document.querySelector(".retry-button");
|
||||||
|
retry.addEventListener("click", this.restart.bind(this));
|
||||||
|
retry.addEventListener(this.eventTouchend, this.restart.bind(this));
|
||||||
|
|
||||||
|
var keepPlaying = document.querySelector(".keep-playing-button");
|
||||||
|
keepPlaying.addEventListener("click", this.keepPlaying.bind(this));
|
||||||
|
keepPlaying.addEventListener("touchend", this.keepPlaying.bind(this));
|
||||||
|
|
||||||
|
// Listen to swipe events
|
||||||
|
var touchStartClientX, touchStartClientY;
|
||||||
|
var gameContainer = document.getElementsByClassName("game-container")[0];
|
||||||
|
|
||||||
|
gameContainer.addEventListener(this.eventTouchstart, function (event) {
|
||||||
|
if (( !window.navigator.msPointerEnabled && event.touches.length > 1) || event.targetTouches > 1) return;
|
||||||
|
|
||||||
|
if(window.navigator.msPointerEnabled){
|
||||||
|
touchStartClientX = event.pageX;
|
||||||
|
touchStartClientY = event.pageY;
|
||||||
|
} else {
|
||||||
|
touchStartClientX = event.touches[0].clientX;
|
||||||
|
touchStartClientY = event.touches[0].clientY;
|
||||||
|
}
|
||||||
|
|
||||||
|
event.preventDefault();
|
||||||
|
});
|
||||||
|
|
||||||
|
gameContainer.addEventListener(this.eventTouchmove, function (event) {
|
||||||
|
event.preventDefault();
|
||||||
|
});
|
||||||
|
|
||||||
|
gameContainer.addEventListener(this.eventTouchend, function (event) {
|
||||||
|
if (( !window.navigator.msPointerEnabled && event.touches.length > 0) || event.targetTouches > 0) return;
|
||||||
|
|
||||||
|
var touchEndClientX, touchEndClientY;
|
||||||
|
if(window.navigator.msPointerEnabled){
|
||||||
|
touchEndClientX = event.pageX;
|
||||||
|
touchEndClientY = event.pageY;
|
||||||
|
} else {
|
||||||
|
touchEndClientX = event.changedTouches[0].clientX;
|
||||||
|
touchEndClientY = event.changedTouches[0].clientY;
|
||||||
|
}
|
||||||
|
|
||||||
|
var dx = touchEndClientX - touchStartClientX;
|
||||||
|
var absDx = Math.abs(dx);
|
||||||
|
|
||||||
|
var dy = touchEndClientY - touchStartClientY;
|
||||||
|
var absDy = Math.abs(dy);
|
||||||
|
|
||||||
|
if (Math.max(absDx, absDy) > 10) {
|
||||||
|
// (right : left) : (down : up)
|
||||||
|
self.emit("move", absDx > absDy ? (dx > 0 ? 1 : 3) : (dy > 0 ? 2 : 0));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
KeyboardInputManager.prototype.restart = function (event) {
|
||||||
|
event.preventDefault();
|
||||||
|
this.emit("restart");
|
||||||
|
};
|
||||||
|
|
||||||
|
KeyboardInputManager.prototype.keepPlaying = function (event) {
|
||||||
|
event.preventDefault();
|
||||||
|
this.emit("keepPlaying");
|
||||||
|
};
|
48
sources/js/local_score_manager.js
Executable file
48
sources/js/local_score_manager.js
Executable file
|
@ -0,0 +1,48 @@
|
||||||
|
window.fakeStorage = {
|
||||||
|
_data: {},
|
||||||
|
|
||||||
|
setItem: function (id, val) {
|
||||||
|
return this._data[id] = String(val);
|
||||||
|
},
|
||||||
|
|
||||||
|
getItem: function (id) {
|
||||||
|
return this._data.hasOwnProperty(id) ? this._data[id] : undefined;
|
||||||
|
},
|
||||||
|
|
||||||
|
removeItem: function (id) {
|
||||||
|
return delete this._data[id];
|
||||||
|
},
|
||||||
|
|
||||||
|
clear: function () {
|
||||||
|
return this._data = {};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function LocalScoreManager() {
|
||||||
|
this.key = "bestScore";
|
||||||
|
|
||||||
|
var supported = this.localStorageSupported();
|
||||||
|
this.storage = supported ? window.localStorage : window.fakeStorage;
|
||||||
|
}
|
||||||
|
|
||||||
|
LocalScoreManager.prototype.localStorageSupported = function () {
|
||||||
|
var testKey = "test";
|
||||||
|
var storage = window.localStorage;
|
||||||
|
|
||||||
|
try {
|
||||||
|
storage.setItem(testKey, "1");
|
||||||
|
storage.removeItem(testKey);
|
||||||
|
return true;
|
||||||
|
} catch (error) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
LocalScoreManager.prototype.get = function () {
|
||||||
|
return this.storage.getItem(this.key) || 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
LocalScoreManager.prototype.set = function (score) {
|
||||||
|
this.storage.setItem(this.key, score);
|
||||||
|
};
|
||||||
|
|
17
sources/js/tile.js
Executable file
17
sources/js/tile.js
Executable file
|
@ -0,0 +1,17 @@
|
||||||
|
function Tile(position, value) {
|
||||||
|
this.x = position.x;
|
||||||
|
this.y = position.y;
|
||||||
|
this.value = value || 2;
|
||||||
|
|
||||||
|
this.previousPosition = null;
|
||||||
|
this.mergedFrom = null; // Tracks tiles that merged together
|
||||||
|
}
|
||||||
|
|
||||||
|
Tile.prototype.savePosition = function () {
|
||||||
|
this.previousPosition = { x: this.x, y: this.y };
|
||||||
|
};
|
||||||
|
|
||||||
|
Tile.prototype.updatePosition = function (position) {
|
||||||
|
this.x = position.x;
|
||||||
|
this.y = position.y;
|
||||||
|
};
|
122
sources/statistics.html
Executable file
122
sources/statistics.html
Executable file
|
@ -0,0 +1,122 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en" manifest="cache.appcache">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>20 Euros Statistics</title>
|
||||||
|
|
||||||
|
<link href="style/main.css" rel="stylesheet" type="text/css">
|
||||||
|
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||||
|
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
|
||||||
|
|
||||||
|
<meta property="og:title" content="20euro game"/>
|
||||||
|
<meta property="og:site_name" content="20euro game"/>
|
||||||
|
<meta property="og:description" content="Join the coins and get the 20 Euro tile!"/>
|
||||||
|
<meta property="og:image" content="http://gabrielecirulli.github.io/2048/meta/og_image.png"/>
|
||||||
|
<script src='https://cdn.firebase.com/js/client/1.0.11/firebase.js'></script>
|
||||||
|
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<script language="JavaScript">
|
||||||
|
var rootRef = new Firebase('https://20-euros.firebaseio.com/');
|
||||||
|
var highestScoreRef = rootRef.child("highestScore");
|
||||||
|
var RefPlays = rootRef.child("plays");
|
||||||
|
var Ref50 = rootRef.child("reached_50c");
|
||||||
|
var Ref100 = rootRef.child("reached_1e");
|
||||||
|
var Ref200 = rootRef.child("reached_2e");
|
||||||
|
var Ref500 = rootRef.child("reached_5e");
|
||||||
|
var Ref1000 = rootRef.child("reached_10e");
|
||||||
|
var Ref2000 = rootRef.child("reached_20e");
|
||||||
|
var Ref5000 = rootRef.child("reached_50e");
|
||||||
|
var Ref10000 = rootRef.child("reached_100e");
|
||||||
|
var Ref20000 = rootRef.child("reached_200e");
|
||||||
|
var Ref50000 = rootRef.child("reached_500e");
|
||||||
|
|
||||||
|
highestScoreRef.on('value', function(newHighestScore) {
|
||||||
|
document.getElementById("highestScoreDiv").innerHTML=newHighestScore.val();
|
||||||
|
});
|
||||||
|
RefPlays.on('value', function(newPlays) {
|
||||||
|
document.getElementById("DivPlays").innerHTML=newPlays.val();
|
||||||
|
});
|
||||||
|
|
||||||
|
Ref50.on('value', function(newPlays) {
|
||||||
|
document.getElementById("Div50").innerHTML=newPlays.val();
|
||||||
|
});
|
||||||
|
Ref100.on('value', function(newPlays) {
|
||||||
|
document.getElementById("Div100").innerHTML=newPlays.val();
|
||||||
|
});
|
||||||
|
Ref200.on('value', function(newPlays) {
|
||||||
|
document.getElementById("Div200").innerHTML=newPlays.val();
|
||||||
|
});
|
||||||
|
Ref500.on('value', function(newPlays) {
|
||||||
|
document.getElementById("Div500").innerHTML=newPlays.val();
|
||||||
|
});
|
||||||
|
Ref1000.on('value', function(newPlays) {
|
||||||
|
document.getElementById("Div1000").innerHTML=newPlays.val();
|
||||||
|
});
|
||||||
|
Ref2000.on('value', function(newPlays) {
|
||||||
|
document.getElementById("Div2000").innerHTML=newPlays.val();
|
||||||
|
});
|
||||||
|
Ref5000.on('value', function(newPlays) {
|
||||||
|
document.getElementById("Div5000").innerHTML=newPlays.val();
|
||||||
|
});
|
||||||
|
Ref10000.on('value', function(newPlays) {
|
||||||
|
document.getElementById("Div10000").innerHTML=newPlays.val();
|
||||||
|
});
|
||||||
|
Ref20000.on('value', function(newPlays) {
|
||||||
|
document.getElementById("Div20000").innerHTML=newPlays.val();
|
||||||
|
});
|
||||||
|
Ref50000.on('value', function(newPlays) {
|
||||||
|
document.getElementById("Div50000").innerHTML=newPlays.val();
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
<div class="heading">
|
||||||
|
<h1 class="title">Statistics</h1>
|
||||||
|
</div>
|
||||||
|
<p class="game-intro">Statistics of my game <a href="http://jatekos101.github.io/20euros">20 Euros</a>.</p>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<p>
|
||||||
|
Statistics since 2014-04-06.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
Out of the <b><span id="DivPlays"></span></b> plays, <br>
|
||||||
|
<b><span id="Div50"></span></b> reached the 50 cent coin, <br>
|
||||||
|
<b><span id="Div100"></span></b> reached the 1 euro coin, <br>
|
||||||
|
<b><span id="Div200"></span></b> reached the 2 euro coin, <br>
|
||||||
|
<b><span id="Div500"></span></b> reached the 5 euro note, <br>
|
||||||
|
<b><span id="Div1000"></span></b> reached the 10 euro note, <br>
|
||||||
|
and <b><span id="Div2000"></span></b> won the game! <br>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
The highest score achieved was <b><span id="highestScoreDiv"></span></b>.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
var sc_project=9719822;
|
||||||
|
var sc_invisible=1;
|
||||||
|
var sc_security="bccc6417";
|
||||||
|
var scJsHost = (("https:" == document.location.protocol) ?
|
||||||
|
"https://secure." : "http://www.");
|
||||||
|
document.write("<sc"+"ript type='text/javascript' src='" +
|
||||||
|
scJsHost+
|
||||||
|
"statcounter.com/counter/counter.js'></"+"script>");
|
||||||
|
</script>
|
||||||
|
<noscript><div class="statcounter"><a title="web analytics"
|
||||||
|
href="http://statcounter.com/" target="_blank"><img
|
||||||
|
class="statcounter"
|
||||||
|
src="http://c.statcounter.com/9719822/0/bccc6417/1/"
|
||||||
|
alt="web analytics"></a></div></noscript>
|
||||||
|
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
50
sources/style/example.css
Executable file
50
sources/style/example.css
Executable file
|
@ -0,0 +1,50 @@
|
||||||
|
/* Global */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#leaderboardTable {
|
||||||
|
background-color: white;
|
||||||
|
overflow: auto;
|
||||||
|
width: 100%;
|
||||||
|
padding: 10px;
|
||||||
|
border: 8px solid #424547;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#scoreInput {
|
||||||
|
width: 68%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#highestscore {
|
||||||
|
margin-top: 20px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Presence */
|
||||||
|
|
||||||
|
#presenceDiv {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tetris */
|
||||||
|
|
||||||
|
.tetris-body {
|
||||||
|
width: 600px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#canvas0, #canvas1 {
|
||||||
|
display: inline-block;
|
||||||
|
border: 4px solid #424547;
|
||||||
|
}
|
||||||
|
|
||||||
|
#restartButton {
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#gameInProgress {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hide {
|
||||||
|
display: none;
|
||||||
|
}
|
869
sources/style/main.css
Executable file
869
sources/style/main.css
Executable file
|
@ -0,0 +1,869 @@
|
||||||
|
@import url(fonts/clear-sans.css);
|
||||||
|
html, body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
background: #faf8ef;
|
||||||
|
color: #776e65;
|
||||||
|
font-family: "Clear Sans", "Helvetica Neue", Arial, sans-serif;
|
||||||
|
font-size: 18px; }
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin: 80px 0; }
|
||||||
|
|
||||||
|
.heading:after {
|
||||||
|
content: "";
|
||||||
|
display: block;
|
||||||
|
clear: both; }
|
||||||
|
|
||||||
|
h1.title {
|
||||||
|
font-size: 80px;
|
||||||
|
font-weight: bold;
|
||||||
|
margin: 0;
|
||||||
|
display: block;
|
||||||
|
float: left; }
|
||||||
|
|
||||||
|
@-webkit-keyframes move-up {
|
||||||
|
0% {
|
||||||
|
top: 25px;
|
||||||
|
opacity: 1; }
|
||||||
|
|
||||||
|
100% {
|
||||||
|
top: -50px;
|
||||||
|
opacity: 0; } }
|
||||||
|
|
||||||
|
@-moz-keyframes move-up {
|
||||||
|
0% {
|
||||||
|
top: 25px;
|
||||||
|
opacity: 1; }
|
||||||
|
|
||||||
|
100% {
|
||||||
|
top: -50px;
|
||||||
|
opacity: 0; } }
|
||||||
|
|
||||||
|
@keyframes move-up {
|
||||||
|
0% {
|
||||||
|
top: 25px;
|
||||||
|
opacity: 1; }
|
||||||
|
|
||||||
|
100% {
|
||||||
|
top: -50px;
|
||||||
|
opacity: 0; } }
|
||||||
|
|
||||||
|
.scores-container {
|
||||||
|
float: right;
|
||||||
|
text-align: right; }
|
||||||
|
|
||||||
|
.score-container, .best-container {
|
||||||
|
position: relative;
|
||||||
|
display: inline-block;
|
||||||
|
background: #bbada0;
|
||||||
|
padding: 15px 25px;
|
||||||
|
font-size: 25px;
|
||||||
|
height: 25px;
|
||||||
|
line-height: 47px;
|
||||||
|
font-weight: bold;
|
||||||
|
border-radius: 3px;
|
||||||
|
color: white;
|
||||||
|
margin-top: 8px;
|
||||||
|
text-align: center; }
|
||||||
|
.score-container:after, .best-container:after {
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
top: 10px;
|
||||||
|
left: 0;
|
||||||
|
text-transform: uppercase;
|
||||||
|
font-size: 13px;
|
||||||
|
line-height: 13px;
|
||||||
|
text-align: center;
|
||||||
|
color: #eee4da; }
|
||||||
|
.score-container .score-addition, .best-container .score-addition {
|
||||||
|
position: absolute;
|
||||||
|
right: 30px;
|
||||||
|
color: red;
|
||||||
|
font-size: 25px;
|
||||||
|
line-height: 25px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: rgba(119, 110, 101, 0.9);
|
||||||
|
z-index: 100;
|
||||||
|
-webkit-animation: move-up 600ms ease-in;
|
||||||
|
-moz-animation: move-up 600ms ease-in;
|
||||||
|
animation: move-up 600ms ease-in;
|
||||||
|
-webkit-animation-fill-mode: both;
|
||||||
|
-moz-animation-fill-mode: both;
|
||||||
|
animation-fill-mode: both; }
|
||||||
|
|
||||||
|
.score-container:after {
|
||||||
|
content: "Score"; }
|
||||||
|
|
||||||
|
.best-container:after {
|
||||||
|
content: "My best"; }
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin-top: 0;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
line-height: 1.65; }
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: #776e65;
|
||||||
|
font-weight: bold;
|
||||||
|
text-decoration: underline;
|
||||||
|
cursor: pointer; }
|
||||||
|
|
||||||
|
strong.important {
|
||||||
|
text-transform: uppercase; }
|
||||||
|
|
||||||
|
hr {
|
||||||
|
border: none;
|
||||||
|
border-bottom: 1px solid #d8d4d0;
|
||||||
|
margin-top: 20px;
|
||||||
|
margin-bottom: 30px; }
|
||||||
|
|
||||||
|
.container {
|
||||||
|
width: 640px;
|
||||||
|
margin: 0 auto; }
|
||||||
|
|
||||||
|
@-webkit-keyframes fade-in {
|
||||||
|
0% {
|
||||||
|
opacity: 0; }
|
||||||
|
|
||||||
|
100% {
|
||||||
|
opacity: 1; } }
|
||||||
|
|
||||||
|
@-moz-keyframes fade-in {
|
||||||
|
0% {
|
||||||
|
opacity: 0; }
|
||||||
|
|
||||||
|
100% {
|
||||||
|
opacity: 1; } }
|
||||||
|
|
||||||
|
@keyframes fade-in {
|
||||||
|
0% {
|
||||||
|
opacity: 0; }
|
||||||
|
|
||||||
|
100% {
|
||||||
|
opacity: 1; } }
|
||||||
|
|
||||||
|
.game-container {
|
||||||
|
margin-top: 40px;
|
||||||
|
position: relative;
|
||||||
|
padding: 15px;
|
||||||
|
cursor: default;
|
||||||
|
-webkit-touch-callout: none;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
background: #bbada0;
|
||||||
|
border-radius: 6px;
|
||||||
|
width: 640px;
|
||||||
|
height: 640px;
|
||||||
|
-webkit-box-sizing: border-box;
|
||||||
|
-moz-box-sizing: border-box;
|
||||||
|
box-sizing: border-box; }
|
||||||
|
|
||||||
|
.game-container .game-message {
|
||||||
|
display: none;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
background: rgba(238, 228, 218, 0.5);
|
||||||
|
z-index: 100;
|
||||||
|
text-align: center;
|
||||||
|
-webkit-animation: fade-in 800ms ease 1200ms;
|
||||||
|
-moz-animation: fade-in 800ms ease 1200ms;
|
||||||
|
animation: fade-in 800ms ease 1200ms;
|
||||||
|
-webkit-animation-fill-mode: both;
|
||||||
|
-moz-animation-fill-mode: both;
|
||||||
|
animation-fill-mode: both;
|
||||||
|
}
|
||||||
|
|
||||||
|
.game-container .game-message p {
|
||||||
|
font-size: 60px;
|
||||||
|
font-weight: bold;
|
||||||
|
height: 60px;
|
||||||
|
line-height: 60px;
|
||||||
|
margin-top: 222px; }
|
||||||
|
.game-container .game-message .lower {
|
||||||
|
display: block;
|
||||||
|
margin-top: 59px; }
|
||||||
|
.game-container .game-message a {
|
||||||
|
display: inline-block;
|
||||||
|
background: #8f7a66;
|
||||||
|
border-radius: 3px;
|
||||||
|
padding: 0 20px;
|
||||||
|
text-decoration: none;
|
||||||
|
color: #f9f6f2;
|
||||||
|
height: 40px;
|
||||||
|
line-height: 42px;
|
||||||
|
margin-left: 9px; }
|
||||||
|
.game-container .game-message a.keep-playing-button {
|
||||||
|
display: none; }
|
||||||
|
.game-container .game-message.game-won {
|
||||||
|
background: rgba(237, 194, 46, 0.5);
|
||||||
|
color: #f9f6f2; }
|
||||||
|
.game-container .game-message.game-won a.keep-playing-button {
|
||||||
|
display: inline-block; }
|
||||||
|
.game-container .game-message.game-won, .game-container .game-message.game-over {
|
||||||
|
display: block; }
|
||||||
|
|
||||||
|
.grid-container {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 1; }
|
||||||
|
|
||||||
|
.grid-row {
|
||||||
|
margin-bottom: 15px; }
|
||||||
|
.grid-row:last-child {
|
||||||
|
margin-bottom: 0; }
|
||||||
|
.grid-row:after {
|
||||||
|
content: "";
|
||||||
|
display: block;
|
||||||
|
clear: both; }
|
||||||
|
|
||||||
|
.grid-cell {
|
||||||
|
width: 110px;
|
||||||
|
height: 110px;
|
||||||
|
margin-right: 15px;
|
||||||
|
float: left;
|
||||||
|
border-radius: 3px;
|
||||||
|
background: rgba(238, 228, 218, 0.35); }
|
||||||
|
.grid-cell:last-child {
|
||||||
|
margin-right: 0; }
|
||||||
|
|
||||||
|
.tile-container {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 2; }
|
||||||
|
|
||||||
|
.tile, .tile .tile-inner {
|
||||||
|
width: 110px;
|
||||||
|
height: 110px;
|
||||||
|
line-height: 116.25px; }
|
||||||
|
|
||||||
|
.tile.tile-position-1-1 {
|
||||||
|
-webkit-transform: translate(0px, 0px);
|
||||||
|
-moz-transform: translate(0px, 0px);
|
||||||
|
transform: translate(0px, 0px); }
|
||||||
|
.tile.tile-position-1-2 {
|
||||||
|
-webkit-transform: translate(0px, 125px);
|
||||||
|
-moz-transform: translate(0px, 125px);
|
||||||
|
transform: translate(0px, 125px); }
|
||||||
|
.tile.tile-position-1-3 {
|
||||||
|
-webkit-transform: translate(0px, 250px);
|
||||||
|
-moz-transform: translate(0px, 250px);
|
||||||
|
transform: translate(0px, 250px); }
|
||||||
|
.tile.tile-position-1-4 {
|
||||||
|
-webkit-transform: translate(0px, 375px);
|
||||||
|
-moz-transform: translate(0px, 375px);
|
||||||
|
transform: translate(0px, 375px); }
|
||||||
|
.tile.tile-position-1-5 {
|
||||||
|
-webkit-transform: translate(0px, 500px);
|
||||||
|
-moz-transform: translate(0px, 500px);
|
||||||
|
transform: translate(0px, 500px); }
|
||||||
|
|
||||||
|
.tile.tile-position-2-1 {
|
||||||
|
-webkit-transform: translate(125px, 0px);
|
||||||
|
-moz-transform: translate(125px, 0px);
|
||||||
|
transform: translate(125px, 0px); }
|
||||||
|
.tile.tile-position-2-2 {
|
||||||
|
-webkit-transform: translate(125px, 125px);
|
||||||
|
-moz-transform: translate(125px, 125px);
|
||||||
|
transform: translate(125px, 125px); }
|
||||||
|
.tile.tile-position-2-3 {
|
||||||
|
-webkit-transform: translate(125px, 250px);
|
||||||
|
-moz-transform: translate(125px, 250px);
|
||||||
|
transform: translate(125px, 250px); }
|
||||||
|
.tile.tile-position-2-4 {
|
||||||
|
-webkit-transform: translate(125px, 375px);
|
||||||
|
-moz-transform: translate(125px, 375px);
|
||||||
|
transform: translate(125px, 375px); }
|
||||||
|
.tile.tile-position-2-5 {
|
||||||
|
-webkit-transform: translate(125px, 500px);
|
||||||
|
-moz-transform: translate(125px, 500px);
|
||||||
|
transform: translate(125px, 500px); }
|
||||||
|
|
||||||
|
.tile.tile-position-3-1 {
|
||||||
|
-webkit-transform: translate(250px, 0px);
|
||||||
|
-moz-transform: translate(250px, 0px);
|
||||||
|
transform: translate(250px, 0px); }
|
||||||
|
.tile.tile-position-3-2 {
|
||||||
|
-webkit-transform: translate(250px, 125px);
|
||||||
|
-moz-transform: translate(250px, 125px);
|
||||||
|
transform: translate(250px, 125px); }
|
||||||
|
.tile.tile-position-3-3 {
|
||||||
|
-webkit-transform: translate(250px, 250px);
|
||||||
|
-moz-transform: translate(250px, 250px);
|
||||||
|
transform: translate(250px, 250px); }
|
||||||
|
.tile.tile-position-3-4 {
|
||||||
|
-webkit-transform: translate(250px, 375px);
|
||||||
|
-moz-transform: translate(250px, 375px);
|
||||||
|
transform: translate(250px, 375px); }
|
||||||
|
.tile.tile-position-3-5 {
|
||||||
|
-webkit-transform: translate(250px, 500px);
|
||||||
|
-moz-transform: translate(250px, 500x);
|
||||||
|
transform: translate(250px, 500px); }
|
||||||
|
|
||||||
|
.tile.tile-position-4-1 {
|
||||||
|
-webkit-transform: translate(375px, 0px);
|
||||||
|
-moz-transform: translate(375px, 0px);
|
||||||
|
transform: translate(375px, 0px); }
|
||||||
|
.tile.tile-position-4-2 {
|
||||||
|
-webkit-transform: translate(375px, 125px);
|
||||||
|
-moz-transform: translate(375px, 125px);
|
||||||
|
transform: translate(375px, 125px); }
|
||||||
|
.tile.tile-position-4-3 {
|
||||||
|
-webkit-transform: translate(375px, 250px);
|
||||||
|
-moz-transform: translate(375px, 250px);
|
||||||
|
transform: translate(375px, 250px); }
|
||||||
|
.tile.tile-position-4-4 {
|
||||||
|
-webkit-transform: translate(375px, 375px);
|
||||||
|
-moz-transform: translate(375px, 375px);
|
||||||
|
transform: translate(375px, 375px); }
|
||||||
|
.tile.tile-position-4-5 {
|
||||||
|
-webkit-transform: translate(375px, 500px);
|
||||||
|
-moz-transform: translate(375px, 500px);
|
||||||
|
transform: translate(375px, 500px); }
|
||||||
|
|
||||||
|
.tile.tile-position-5-1 {
|
||||||
|
-webkit-transform: translate(500px, 0px);
|
||||||
|
-moz-transform: translate(500px, 0px);
|
||||||
|
transform: translate(500px, 0px); }
|
||||||
|
.tile.tile-position-5-2 {
|
||||||
|
-webkit-transform: translate(500px, 125px);
|
||||||
|
-moz-transform: translate(500px, 125px);
|
||||||
|
transform: translate(500px, 125px); }
|
||||||
|
.tile.tile-position-5-3 {
|
||||||
|
-webkit-transform: translate(500px, 250px);
|
||||||
|
-moz-transform: translate(500px, 250px);
|
||||||
|
transform: translate(500px, 250px); }
|
||||||
|
.tile.tile-position-5-4 {
|
||||||
|
-webkit-transform: translate(500px, 375px);
|
||||||
|
-moz-transform: translate(500px, 375px);
|
||||||
|
transform: translate(500px, 375px); }
|
||||||
|
.tile.tile-position-5-5 {
|
||||||
|
-webkit-transform: translate(500px, 500px);
|
||||||
|
-moz-transform: translate(500px, 500px);
|
||||||
|
transform: translate(500px, 500px); }
|
||||||
|
|
||||||
|
|
||||||
|
.tile {
|
||||||
|
position: absolute;
|
||||||
|
-webkit-transition: 100ms ease-in-out;
|
||||||
|
-moz-transition: 100ms ease-in-out;
|
||||||
|
transition: 100ms ease-in-out;
|
||||||
|
-webkit-transition-property: -webkit-transform;
|
||||||
|
-moz-transition-property: -moz-transform;
|
||||||
|
transition-property: transform; }
|
||||||
|
.tile .tile-inner {
|
||||||
|
border-radius: 3px;
|
||||||
|
background: #eee4da;
|
||||||
|
text-align: center;
|
||||||
|
font-weight: bold;
|
||||||
|
z-index: 10;
|
||||||
|
font-size: 0px; }
|
||||||
|
|
||||||
|
|
||||||
|
.tile.tile-1 .tile-inner {
|
||||||
|
background: #f0f url('https://www.ecb.europa.eu/euro/coins/common/shared/img/common_1cent.gif');
|
||||||
|
background-size: cover;
|
||||||
|
box-shadow: 0 0 30px 10px rgba(243, 215, 116, 0), inset 0 0 0 1px rgba(255, 255, 255, 0); }
|
||||||
|
|
||||||
|
|
||||||
|
.tile.tile-2 .tile-inner {
|
||||||
|
background: #f0f url('https://www.ecb.europa.eu/euro/coins/common/shared/img/common_2cent.gif');
|
||||||
|
background-size: cover;
|
||||||
|
box-shadow: 0 0 30px 10px rgba(243, 215, 116, 0), inset 0 0 0 1px rgba(255, 255, 255, 0); }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.tile.tile-5 .tile-inner {
|
||||||
|
background: #f0f url('https://www.ecb.europa.eu/euro/coins/common/shared/img/common_5cent.gif');
|
||||||
|
background-size: cover;
|
||||||
|
box-shadow: 0 0 30px 10px rgba(243, 215, 116, 0), inset 0 0 0 1px rgba(255, 255, 255, 0); }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.tile.tile-10 .tile-inner {
|
||||||
|
background: #f0f url('https://www.ecb.europa.eu/euro/coins/common/shared/img/common_10cent.gif');
|
||||||
|
background-size: cover;}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.tile.tile-20 .tile-inner {
|
||||||
|
background: #f0f url('https://www.ecb.europa.eu/euro/coins/common/shared/img/common_20cent.gif');
|
||||||
|
background-size: cover;}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.tile.tile-50 .tile-inner {
|
||||||
|
background: #f0f url('https://www.ecb.europa.eu/euro/coins/common/shared/img/common_50cent.gif');
|
||||||
|
background-size: cover;}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.tile.tile-100 .tile-inner {
|
||||||
|
background: #f0f url('https://www.ecb.europa.eu/euro/coins/common/shared/img/common_1euro.gif');
|
||||||
|
background-size: cover;}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.tile.tile-200 .tile-inner {
|
||||||
|
background: #f0f url('https://www.ecb.europa.eu/euro/coins/common/shared/img/common_2euro.gif');
|
||||||
|
background-size: cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.tile.tile-500 .tile-inner {
|
||||||
|
|
||||||
|
background: #ffffff url('http://www.126bay.com/images/banknote/europe/eURO/5%20Euro%202002%20-%20F.jpg');
|
||||||
|
background-size: contain; background-repeat: no-repeat;}
|
||||||
|
|
||||||
|
|
||||||
|
.tile.tile-1000 .tile-inner {
|
||||||
|
|
||||||
|
background: #ffffff url('http://www.126bay.com/images/banknote/europe/eURO/10%20Euro%202002%20-%20F.jpg');
|
||||||
|
background-size: contain; background-repeat: no-repeat;}
|
||||||
|
|
||||||
|
.tile.tile-2000 .tile-inner {
|
||||||
|
background: #ffffff url('http://www.126bay.com/images/banknote/europe/eURO/20%20Euro%202002%20-%20F.jpg');
|
||||||
|
background-size: contain; background-repeat: no-repeat;}
|
||||||
|
|
||||||
|
|
||||||
|
.tile.tile-5000 .tile-inner {
|
||||||
|
background: #ffffff url('http://www.126bay.com/images/banknote/europe/eURO/50%20Euro%202002%20-%20F.jpg');
|
||||||
|
background-size: contain; background-repeat: no-repeat;}
|
||||||
|
|
||||||
|
|
||||||
|
.tile.tile-10000 .tile-inner {
|
||||||
|
background: #ffffff url('http://www.blogger42.com/wp-content/uploads/100euro.jpg');
|
||||||
|
background-size: contain; background-repeat: no-repeat;}
|
||||||
|
|
||||||
|
|
||||||
|
.tile.tile-20000 .tile-inner {
|
||||||
|
background: #ffffff url('http://www.blogger42.com/wp-content/uploads/e.jpg');
|
||||||
|
background-size: contain; background-repeat: no-repeat;}
|
||||||
|
|
||||||
|
|
||||||
|
.tile.tile-50000 .tile-inner {
|
||||||
|
background: #ffffff url('http://www.rivistastudio.com/wp-content/uploads/2014/03/500euro.jpg');
|
||||||
|
background-size: contain; background-repeat: no-repeat;}
|
||||||
|
|
||||||
|
|
||||||
|
.tile.tile-super .tile-inner {
|
||||||
|
|
||||||
|
background: #ffffff url('http://upload.wikimedia.org/wikipedia/commons/c/c3/Euro_symbol_gold.svg');
|
||||||
|
background-size: cover;
|
||||||
|
font-size: 30px; }
|
||||||
|
|
||||||
|
|
||||||
|
@media screen and (max-width: 520px) {
|
||||||
|
.tile.tile-super .tile-inner {
|
||||||
|
font-size: 10px; } }
|
||||||
|
|
||||||
|
@-webkit-keyframes appear {
|
||||||
|
0% {
|
||||||
|
opacity: 0;
|
||||||
|
-webkit-transform: scale(0);
|
||||||
|
-moz-transform: scale(0);
|
||||||
|
transform: scale(0); }
|
||||||
|
|
||||||
|
100% {
|
||||||
|
opacity: 1;
|
||||||
|
-webkit-transform: scale(1);
|
||||||
|
-moz-transform: scale(1);
|
||||||
|
transform: scale(1); } }
|
||||||
|
|
||||||
|
@-moz-keyframes appear {
|
||||||
|
0% {
|
||||||
|
opacity: 0;
|
||||||
|
-webkit-transform: scale(0);
|
||||||
|
-moz-transform: scale(0);
|
||||||
|
transform: scale(0); }
|
||||||
|
|
||||||
|
100% {
|
||||||
|
opacity: 1;
|
||||||
|
-webkit-transform: scale(1);
|
||||||
|
-moz-transform: scale(1);
|
||||||
|
transform: scale(1); } }
|
||||||
|
|
||||||
|
@keyframes appear {
|
||||||
|
0% {
|
||||||
|
opacity: 0;
|
||||||
|
-webkit-transform: scale(0);
|
||||||
|
-moz-transform: scale(0);
|
||||||
|
transform: scale(0); }
|
||||||
|
|
||||||
|
100% {
|
||||||
|
opacity: 1;
|
||||||
|
-webkit-transform: scale(1);
|
||||||
|
-moz-transform: scale(1);
|
||||||
|
transform: scale(1); } }
|
||||||
|
|
||||||
|
.tile-new .tile-inner {
|
||||||
|
-webkit-animation: appear 200ms ease 100ms;
|
||||||
|
-moz-animation: appear 200ms ease 100ms;
|
||||||
|
animation: appear 200ms ease 100ms;
|
||||||
|
-webkit-animation-fill-mode: backwards;
|
||||||
|
-moz-animation-fill-mode: backwards;
|
||||||
|
animation-fill-mode: backwards; }
|
||||||
|
|
||||||
|
@-webkit-keyframes pop {
|
||||||
|
0% {
|
||||||
|
-webkit-transform: scale(0);
|
||||||
|
-moz-transform: scale(0);
|
||||||
|
transform: scale(0); }
|
||||||
|
|
||||||
|
50% {
|
||||||
|
-webkit-transform: scale(1.2);
|
||||||
|
-moz-transform: scale(1.2);
|
||||||
|
transform: scale(1.2); }
|
||||||
|
|
||||||
|
100% {
|
||||||
|
-webkit-transform: scale(1);
|
||||||
|
-moz-transform: scale(1);
|
||||||
|
transform: scale(1); } }
|
||||||
|
|
||||||
|
@-moz-keyframes pop {
|
||||||
|
0% {
|
||||||
|
-webkit-transform: scale(0);
|
||||||
|
-moz-transform: scale(0);
|
||||||
|
transform: scale(0); }
|
||||||
|
|
||||||
|
50% {
|
||||||
|
-webkit-transform: scale(1.2);
|
||||||
|
-moz-transform: scale(1.2);
|
||||||
|
transform: scale(1.2); }
|
||||||
|
|
||||||
|
100% {
|
||||||
|
-webkit-transform: scale(1);
|
||||||
|
-moz-transform: scale(1);
|
||||||
|
transform: scale(1); } }
|
||||||
|
|
||||||
|
@keyframes pop {
|
||||||
|
0% {
|
||||||
|
-webkit-transform: scale(0);
|
||||||
|
-moz-transform: scale(0);
|
||||||
|
transform: scale(0); }
|
||||||
|
|
||||||
|
50% {
|
||||||
|
-webkit-transform: scale(1.2);
|
||||||
|
-moz-transform: scale(1.2);
|
||||||
|
transform: scale(1.2); }
|
||||||
|
|
||||||
|
100% {
|
||||||
|
-webkit-transform: scale(1);
|
||||||
|
-moz-transform: scale(1);
|
||||||
|
transform: scale(1); } }
|
||||||
|
|
||||||
|
.tile-merged .tile-inner {
|
||||||
|
z-index: 20;
|
||||||
|
-webkit-animation: pop 200ms ease 100ms;
|
||||||
|
-moz-animation: pop 200ms ease 100ms;
|
||||||
|
animation: pop 200ms ease 100ms;
|
||||||
|
-webkit-animation-fill-mode: backwards;
|
||||||
|
-moz-animation-fill-mode: backwards;
|
||||||
|
animation-fill-mode: backwards; }
|
||||||
|
|
||||||
|
.game-intro {
|
||||||
|
margin-bottom: 0; }
|
||||||
|
|
||||||
|
.game-explanation {
|
||||||
|
margin-top: 50px; }
|
||||||
|
|
||||||
|
.sharing {
|
||||||
|
margin-top: 20px;
|
||||||
|
text-align: center; }
|
||||||
|
.sharing > iframe, .sharing > span, .sharing > form {
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: middle; }
|
||||||
|
|
||||||
|
@media screen and (max-width: 520px) {
|
||||||
|
html, body {
|
||||||
|
font-size: 15px; }
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin: 20px 0;
|
||||||
|
padding: 0 20px; }
|
||||||
|
|
||||||
|
h1.title {
|
||||||
|
font-size: 27px;
|
||||||
|
margin-top: 15px; }
|
||||||
|
|
||||||
|
.container {
|
||||||
|
width: 280px;
|
||||||
|
margin: 0 auto; }
|
||||||
|
|
||||||
|
.score-container, .best-container {
|
||||||
|
margin-top: 0;
|
||||||
|
padding: 15px 10px;
|
||||||
|
min-width: 40px; }
|
||||||
|
|
||||||
|
.heading {
|
||||||
|
margin-bottom: 10px; }
|
||||||
|
|
||||||
|
.game-container {
|
||||||
|
margin-top: 40px;
|
||||||
|
position: relative;
|
||||||
|
padding: 10px;
|
||||||
|
cursor: default;
|
||||||
|
-webkit-touch-callout: none;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
background: #bbada0;
|
||||||
|
border-radius: 6px;
|
||||||
|
width: 280px;
|
||||||
|
height: 280px;
|
||||||
|
-ms-touch-action: none;
|
||||||
|
-webkit-box-sizing: border-box;
|
||||||
|
-moz-box-sizing: border-box;
|
||||||
|
box-sizing: border-box; }
|
||||||
|
.game-container .game-message {
|
||||||
|
display: none;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
background: rgba(238, 228, 218, 0.5);
|
||||||
|
z-index: 100;
|
||||||
|
text-align: center;
|
||||||
|
-webkit-animation: fade-in 800ms ease 1200ms;
|
||||||
|
-moz-animation: fade-in 800ms ease 1200ms;
|
||||||
|
animation: fade-in 800ms ease 1200ms;
|
||||||
|
-webkit-animation-fill-mode: both;
|
||||||
|
-moz-animation-fill-mode: both;
|
||||||
|
animation-fill-mode: both; }
|
||||||
|
.game-container .game-message p {
|
||||||
|
font-size: 60px;
|
||||||
|
font-weight: bold;
|
||||||
|
height: 60px;
|
||||||
|
line-height: 60px;
|
||||||
|
margin-top: 222px; }
|
||||||
|
.game-container .game-message .lower {
|
||||||
|
display: block;
|
||||||
|
margin-top: 59px; }
|
||||||
|
.game-container .game-message a {
|
||||||
|
display: inline-block;
|
||||||
|
background: #8f7a66;
|
||||||
|
border-radius: 3px;
|
||||||
|
padding: 0 20px;
|
||||||
|
text-decoration: none;
|
||||||
|
color: #f9f6f2;
|
||||||
|
height: 40px;
|
||||||
|
line-height: 42px;
|
||||||
|
margin-left: 9px; }
|
||||||
|
.game-container .game-message a.keep-playing-button {
|
||||||
|
display: none; }
|
||||||
|
.game-container .game-message .score-sharing {
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: middle;
|
||||||
|
margin-left: 10px; }
|
||||||
|
.game-container .game-message.game-won {
|
||||||
|
background: rgba(237, 194, 46, 0.5);
|
||||||
|
color: #f9f6f2; }
|
||||||
|
.game-container .game-message.game-won a.keep-playing-button {
|
||||||
|
display: inline-block; }
|
||||||
|
.game-container .game-message.game-won, .game-container .game-message.game-over {
|
||||||
|
display: block; }
|
||||||
|
|
||||||
|
.grid-container {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 1; }
|
||||||
|
|
||||||
|
.grid-row {
|
||||||
|
margin-bottom: 10px; }
|
||||||
|
.grid-row:last-child {
|
||||||
|
margin-bottom: 0; }
|
||||||
|
.grid-row:after {
|
||||||
|
content: "";
|
||||||
|
display: block;
|
||||||
|
clear: both; }
|
||||||
|
|
||||||
|
.grid-cell {
|
||||||
|
width: 57.5px;
|
||||||
|
height: 57.5px;
|
||||||
|
margin-right: 10px;
|
||||||
|
float: left;
|
||||||
|
border-radius: 3px;
|
||||||
|
background: rgba(238, 228, 218, 0.35); }
|
||||||
|
.grid-cell:last-child {
|
||||||
|
margin-right: 0; }
|
||||||
|
|
||||||
|
.tile-container {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 2; }
|
||||||
|
|
||||||
|
.tile, .tile .tile-inner {
|
||||||
|
width: 58px;
|
||||||
|
height: 58px;
|
||||||
|
line-height: 67.5px; }
|
||||||
|
.tile.tile-position-1-1 {
|
||||||
|
-webkit-transform: translate(0px, 0px);
|
||||||
|
-moz-transform: translate(0px, 0px);
|
||||||
|
transform: translate(0px, 0px); }
|
||||||
|
.tile.tile-position-1-2 {
|
||||||
|
-webkit-transform: translate(0px, 67px);
|
||||||
|
-moz-transform: translate(0px, 67px);
|
||||||
|
transform: translate(0px, 67px); }
|
||||||
|
.tile.tile-position-1-3 {
|
||||||
|
-webkit-transform: translate(0px, 135px);
|
||||||
|
-moz-transform: translate(0px, 135px);
|
||||||
|
transform: translate(0px, 135px); }
|
||||||
|
.tile.tile-position-1-4 {
|
||||||
|
-webkit-transform: translate(0px, 202px);
|
||||||
|
-moz-transform: translate(0px, 202px);
|
||||||
|
transform: translate(0px, 202px); }
|
||||||
|
.tile.tile-position-2-1 {
|
||||||
|
-webkit-transform: translate(67px, 0px);
|
||||||
|
-moz-transform: translate(67px, 0px);
|
||||||
|
transform: translate(67px, 0px); }
|
||||||
|
.tile.tile-position-2-2 {
|
||||||
|
-webkit-transform: translate(67px, 67px);
|
||||||
|
-moz-transform: translate(67px, 67px);
|
||||||
|
transform: translate(67px, 67px); }
|
||||||
|
.tile.tile-position-2-3 {
|
||||||
|
-webkit-transform: translate(67px, 135px);
|
||||||
|
-moz-transform: translate(67px, 135px);
|
||||||
|
transform: translate(67px, 135px); }
|
||||||
|
.tile.tile-position-2-4 {
|
||||||
|
-webkit-transform: translate(67px, 202px);
|
||||||
|
-moz-transform: translate(67px, 202px);
|
||||||
|
transform: translate(67px, 202px); }
|
||||||
|
.tile.tile-position-3-1 {
|
||||||
|
-webkit-transform: translate(135px, 0px);
|
||||||
|
-moz-transform: translate(135px, 0px);
|
||||||
|
transform: translate(135px, 0px); }
|
||||||
|
.tile.tile-position-3-2 {
|
||||||
|
-webkit-transform: translate(135px, 67px);
|
||||||
|
-moz-transform: translate(135px, 67px);
|
||||||
|
transform: translate(135px, 67px); }
|
||||||
|
.tile.tile-position-3-3 {
|
||||||
|
-webkit-transform: translate(135px, 135px);
|
||||||
|
-moz-transform: translate(135px, 135px);
|
||||||
|
transform: translate(135px, 135px); }
|
||||||
|
.tile.tile-position-3-4 {
|
||||||
|
-webkit-transform: translate(135px, 202px);
|
||||||
|
-moz-transform: translate(135px, 202px);
|
||||||
|
transform: translate(135px, 202px); }
|
||||||
|
.tile.tile-position-4-1 {
|
||||||
|
-webkit-transform: translate(202px, 0px);
|
||||||
|
-moz-transform: translate(202px, 0px);
|
||||||
|
transform: translate(202px, 0px); }
|
||||||
|
.tile.tile-position-4-2 {
|
||||||
|
-webkit-transform: translate(202px, 67px);
|
||||||
|
-moz-transform: translate(202px, 67px);
|
||||||
|
transform: translate(202px, 67px); }
|
||||||
|
.tile.tile-position-4-3 {
|
||||||
|
-webkit-transform: translate(202px, 135px);
|
||||||
|
-moz-transform: translate(202px, 135px);
|
||||||
|
transform: translate(202px, 135px); }
|
||||||
|
.tile.tile-position-4-4 {
|
||||||
|
-webkit-transform: translate(202px, 202px);
|
||||||
|
-moz-transform: translate(202px, 202px);
|
||||||
|
transform: translate(202px, 202px); }
|
||||||
|
|
||||||
|
.game-container {
|
||||||
|
margin-top: 20px; }
|
||||||
|
|
||||||
|
.tile .tile-inner {
|
||||||
|
font-size: 35px; }
|
||||||
|
|
||||||
|
.game-message p {
|
||||||
|
font-size: 30px !important;
|
||||||
|
height: 30px !important;
|
||||||
|
line-height: 30px !important;
|
||||||
|
margin-top: 90px !important; }
|
||||||
|
.game-message .lower {
|
||||||
|
margin-top: 30px !important; }
|
||||||
|
|
||||||
|
.sharing > iframe, .sharing > span, .sharing > form {
|
||||||
|
display: block;
|
||||||
|
margin: 0 auto;
|
||||||
|
margin-bottom: 20px; } }
|
||||||
|
.pp-donate button {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
-moz-appearance: none;
|
||||||
|
appearance: none;
|
||||||
|
border: none;
|
||||||
|
font: inherit;
|
||||||
|
color: inherit;
|
||||||
|
cursor: pointer;
|
||||||
|
display: inline-block;
|
||||||
|
background: #8f7a66;
|
||||||
|
border-radius: 3px;
|
||||||
|
padding: 0 20px;
|
||||||
|
text-decoration: none;
|
||||||
|
color: #f9f6f2;
|
||||||
|
height: 40px;
|
||||||
|
line-height: 42px; }
|
||||||
|
.pp-donate button img {
|
||||||
|
vertical-align: -4px;
|
||||||
|
margin-right: 8px; }
|
||||||
|
|
||||||
|
.btc-donate {
|
||||||
|
position: relative;
|
||||||
|
margin-left: 10px;
|
||||||
|
display: inline-block;
|
||||||
|
background: #8f7a66;
|
||||||
|
border-radius: 3px;
|
||||||
|
padding: 0 20px;
|
||||||
|
text-decoration: none;
|
||||||
|
color: #f9f6f2;
|
||||||
|
height: 40px;
|
||||||
|
line-height: 42px;
|
||||||
|
cursor: pointer; }
|
||||||
|
.btc-donate img {
|
||||||
|
vertical-align: -4px;
|
||||||
|
margin-right: 8px; }
|
||||||
|
.btc-donate a {
|
||||||
|
color: #f9f6f2;
|
||||||
|
text-decoration: none;
|
||||||
|
font-weight: normal; }
|
||||||
|
.btc-donate .address {
|
||||||
|
cursor: auto;
|
||||||
|
position: absolute;
|
||||||
|
width: 340px;
|
||||||
|
right: 50%;
|
||||||
|
margin-right: -170px;
|
||||||
|
padding-bottom: 7px;
|
||||||
|
top: -30px;
|
||||||
|
opacity: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
-webkit-transition: 400ms ease;
|
||||||
|
-moz-transition: 400ms ease;
|
||||||
|
transition: 400ms ease;
|
||||||
|
-webkit-transition-property: top, opacity;
|
||||||
|
-moz-transition-property: top, opacity;
|
||||||
|
transition-property: top, opacity; }
|
||||||
|
.btc-donate .address:after {
|
||||||
|
position: absolute;
|
||||||
|
border-top: 10px solid #bbada0;
|
||||||
|
border-right: 7px solid transparent;
|
||||||
|
border-left: 7px solid transparent;
|
||||||
|
content: "";
|
||||||
|
bottom: 0px;
|
||||||
|
left: 50%;
|
||||||
|
margin-left: -7px; }
|
||||||
|
.btc-donate .address code {
|
||||||
|
background-color: #bbada0;
|
||||||
|
padding: 10px 15px;
|
||||||
|
width: 100%;
|
||||||
|
border-radius: 3px;
|
||||||
|
line-height: 1;
|
||||||
|
font-weight: normal;
|
||||||
|
font-size: 15px;
|
||||||
|
font-family: Consolas, "Liberation Mono", Courier, monospace;
|
||||||
|
text-align: center; }
|
||||||
|
.btc-donate:hover .address, .btc-donate .address:hover .address {
|
||||||
|
opacity: 1;
|
||||||
|
top: -45px;
|
||||||
|
pointer-events: auto; }
|
||||||
|
@media screen and (max-width: 480px) {
|
||||||
|
.btc-donate {
|
||||||
|
width: 120px; }
|
||||||
|
.btc-donate .address {
|
||||||
|
margin-right: -150px;
|
||||||
|
width: 300px; }
|
||||||
|
.btc-donate .address code {
|
||||||
|
font-size: 13px; }
|
||||||
|
.btc-donate .address:after {
|
||||||
|
left: 50%;
|
||||||
|
bottom: 2px; } }
|
70
sources/stylesheets/pygment_trac.css
Executable file
70
sources/stylesheets/pygment_trac.css
Executable file
|
@ -0,0 +1,70 @@
|
||||||
|
.highlight .hll { background-color: #ffffcc }
|
||||||
|
.highlight { background: #f0f3f3; }
|
||||||
|
.highlight .c { color: #0099FF; font-style: italic } /* Comment */
|
||||||
|
.highlight .err { color: #AA0000; background-color: #FFAAAA } /* Error */
|
||||||
|
.highlight .k { color: #006699; font-weight: bold } /* Keyword */
|
||||||
|
.highlight .o { color: #555555 } /* Operator */
|
||||||
|
.highlight .cm { color: #0099FF; font-style: italic } /* Comment.Multiline */
|
||||||
|
.highlight .cp { color: #009999 } /* Comment.Preproc */
|
||||||
|
.highlight .c1 { color: #0099FF; font-style: italic } /* Comment.Single */
|
||||||
|
.highlight .cs { color: #0099FF; font-weight: bold; font-style: italic } /* Comment.Special */
|
||||||
|
.highlight .gd { background-color: #FFCCCC; border: 1px solid #CC0000 } /* Generic.Deleted */
|
||||||
|
.highlight .ge { font-style: italic } /* Generic.Emph */
|
||||||
|
.highlight .gr { color: #FF0000 } /* Generic.Error */
|
||||||
|
.highlight .gh { color: #003300; font-weight: bold } /* Generic.Heading */
|
||||||
|
.highlight .gi { background-color: #CCFFCC; border: 1px solid #00CC00 } /* Generic.Inserted */
|
||||||
|
.highlight .go { color: #AAAAAA } /* Generic.Output */
|
||||||
|
.highlight .gp { color: #000099; font-weight: bold } /* Generic.Prompt */
|
||||||
|
.highlight .gs { font-weight: bold } /* Generic.Strong */
|
||||||
|
.highlight .gu { color: #003300; font-weight: bold } /* Generic.Subheading */
|
||||||
|
.highlight .gt { color: #99CC66 } /* Generic.Traceback */
|
||||||
|
.highlight .kc { color: #006699; font-weight: bold } /* Keyword.Constant */
|
||||||
|
.highlight .kd { color: #006699; font-weight: bold } /* Keyword.Declaration */
|
||||||
|
.highlight .kn { color: #006699; font-weight: bold } /* Keyword.Namespace */
|
||||||
|
.highlight .kp { color: #006699 } /* Keyword.Pseudo */
|
||||||
|
.highlight .kr { color: #006699; font-weight: bold } /* Keyword.Reserved */
|
||||||
|
.highlight .kt { color: #007788; font-weight: bold } /* Keyword.Type */
|
||||||
|
.highlight .m { color: #FF6600 } /* Literal.Number */
|
||||||
|
.highlight .s { color: #CC3300 } /* Literal.String */
|
||||||
|
.highlight .na { color: #330099 } /* Name.Attribute */
|
||||||
|
.highlight .nb { color: #336666 } /* Name.Builtin */
|
||||||
|
.highlight .nc { color: #00AA88; font-weight: bold } /* Name.Class */
|
||||||
|
.highlight .no { color: #336600 } /* Name.Constant */
|
||||||
|
.highlight .nd { color: #9999FF } /* Name.Decorator */
|
||||||
|
.highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */
|
||||||
|
.highlight .ne { color: #CC0000; font-weight: bold } /* Name.Exception */
|
||||||
|
.highlight .nf { color: #CC00FF } /* Name.Function */
|
||||||
|
.highlight .nl { color: #9999FF } /* Name.Label */
|
||||||
|
.highlight .nn { color: #00CCFF; font-weight: bold } /* Name.Namespace */
|
||||||
|
.highlight .nt { color: #330099; font-weight: bold } /* Name.Tag */
|
||||||
|
.highlight .nv { color: #003333 } /* Name.Variable */
|
||||||
|
.highlight .ow { color: #000000; font-weight: bold } /* Operator.Word */
|
||||||
|
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
|
||||||
|
.highlight .mf { color: #FF6600 } /* Literal.Number.Float */
|
||||||
|
.highlight .mh { color: #FF6600 } /* Literal.Number.Hex */
|
||||||
|
.highlight .mi { color: #FF6600 } /* Literal.Number.Integer */
|
||||||
|
.highlight .mo { color: #FF6600 } /* Literal.Number.Oct */
|
||||||
|
.highlight .sb { color: #CC3300 } /* Literal.String.Backtick */
|
||||||
|
.highlight .sc { color: #CC3300 } /* Literal.String.Char */
|
||||||
|
.highlight .sd { color: #CC3300; font-style: italic } /* Literal.String.Doc */
|
||||||
|
.highlight .s2 { color: #CC3300 } /* Literal.String.Double */
|
||||||
|
.highlight .se { color: #CC3300; font-weight: bold } /* Literal.String.Escape */
|
||||||
|
.highlight .sh { color: #CC3300 } /* Literal.String.Heredoc */
|
||||||
|
.highlight .si { color: #AA0000 } /* Literal.String.Interpol */
|
||||||
|
.highlight .sx { color: #CC3300 } /* Literal.String.Other */
|
||||||
|
.highlight .sr { color: #33AAAA } /* Literal.String.Regex */
|
||||||
|
.highlight .s1 { color: #CC3300 } /* Literal.String.Single */
|
||||||
|
.highlight .ss { color: #FFCC33 } /* Literal.String.Symbol */
|
||||||
|
.highlight .bp { color: #336666 } /* Name.Builtin.Pseudo */
|
||||||
|
.highlight .vc { color: #003333 } /* Name.Variable.Class */
|
||||||
|
.highlight .vg { color: #003333 } /* Name.Variable.Global */
|
||||||
|
.highlight .vi { color: #003333 } /* Name.Variable.Instance */
|
||||||
|
.highlight .il { color: #FF6600 } /* Literal.Number.Integer.Long */
|
||||||
|
|
||||||
|
.type-csharp .highlight .k { color: #0000FF }
|
||||||
|
.type-csharp .highlight .kt { color: #0000FF }
|
||||||
|
.type-csharp .highlight .nf { color: #000000; font-weight: normal }
|
||||||
|
.type-csharp .highlight .nc { color: #2B91AF }
|
||||||
|
.type-csharp .highlight .nn { color: #000000 }
|
||||||
|
.type-csharp .highlight .s { color: #A31515 }
|
||||||
|
.type-csharp .highlight .sc { color: #A31515 }
|
423
sources/stylesheets/stylesheet.css
Executable file
423
sources/stylesheets/stylesheet.css
Executable file
|
@ -0,0 +1,423 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
Slate Theme for GitHub Pages
|
||||||
|
by Jason Costello, @jsncostello
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
@import url(pygment_trac.css);
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
MeyerWeb Reset
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
html, body, div, span, applet, object, iframe,
|
||||||
|
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
|
||||||
|
a, abbr, acronym, address, big, cite, code,
|
||||||
|
del, dfn, em, img, ins, kbd, q, s, samp,
|
||||||
|
small, strike, strong, sub, sup, tt, var,
|
||||||
|
b, u, i, center,
|
||||||
|
dl, dt, dd, ol, ul, li,
|
||||||
|
fieldset, form, label, legend,
|
||||||
|
table, caption, tbody, tfoot, thead, tr, th, td,
|
||||||
|
article, aside, canvas, details, embed,
|
||||||
|
figure, figcaption, footer, header, hgroup,
|
||||||
|
menu, nav, output, ruby, section, summary,
|
||||||
|
time, mark, audio, video {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
border: 0;
|
||||||
|
font: inherit;
|
||||||
|
vertical-align: baseline;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* HTML5 display-role reset for older browsers */
|
||||||
|
article, aside, details, figcaption, figure,
|
||||||
|
footer, header, hgroup, menu, nav, section {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
ol, ul {
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
border-collapse: collapse;
|
||||||
|
border-spacing: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
Theme Styles
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
body {
|
||||||
|
box-sizing: border-box;
|
||||||
|
color:#373737;
|
||||||
|
background: #212121;
|
||||||
|
font-size: 16px;
|
||||||
|
font-family: 'Myriad Pro', Calibri, Helvetica, Arial, sans-serif;
|
||||||
|
line-height: 1.5;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1, h2, h3, h4, h5, h6 {
|
||||||
|
margin: 10px 0;
|
||||||
|
font-weight: 700;
|
||||||
|
color:#222222;
|
||||||
|
font-family: 'Lucida Grande', 'Calibri', Helvetica, Arial, sans-serif;
|
||||||
|
letter-spacing: -1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 36px;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
padding-bottom: 10px;
|
||||||
|
font-size: 32px;
|
||||||
|
background: url('../images/bg_hr.png') repeat-x bottom;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4 {
|
||||||
|
font-size: 21px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h5 {
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h6 {
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin: 10px 0 15px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer p {
|
||||||
|
color: #f2f2f2;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
text-decoration: none;
|
||||||
|
color: #007edf;
|
||||||
|
text-shadow: none;
|
||||||
|
|
||||||
|
transition: color 0.5s ease;
|
||||||
|
transition: text-shadow 0.5s ease;
|
||||||
|
-webkit-transition: color 0.5s ease;
|
||||||
|
-webkit-transition: text-shadow 0.5s ease;
|
||||||
|
-moz-transition: color 0.5s ease;
|
||||||
|
-moz-transition: text-shadow 0.5s ease;
|
||||||
|
-o-transition: color 0.5s ease;
|
||||||
|
-o-transition: text-shadow 0.5s ease;
|
||||||
|
-ms-transition: color 0.5s ease;
|
||||||
|
-ms-transition: text-shadow 0.5s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:hover, a:focus {text-decoration: underline;}
|
||||||
|
|
||||||
|
footer a {
|
||||||
|
color: #F2F2F2;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
em {
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
strong {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
position: relative;
|
||||||
|
margin: 0 auto;
|
||||||
|
max-width: 739px;
|
||||||
|
padding: 5px;
|
||||||
|
margin: 10px 0 10px 0;
|
||||||
|
border: 1px solid #ebebeb;
|
||||||
|
|
||||||
|
box-shadow: 0 0 5px #ebebeb;
|
||||||
|
-webkit-box-shadow: 0 0 5px #ebebeb;
|
||||||
|
-moz-box-shadow: 0 0 5px #ebebeb;
|
||||||
|
-o-box-shadow: 0 0 5px #ebebeb;
|
||||||
|
-ms-box-shadow: 0 0 5px #ebebeb;
|
||||||
|
}
|
||||||
|
|
||||||
|
p img {
|
||||||
|
display: inline;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
vertical-align: middle;
|
||||||
|
text-align: center;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre, code {
|
||||||
|
width: 100%;
|
||||||
|
color: #222;
|
||||||
|
background-color: #fff;
|
||||||
|
|
||||||
|
font-family: Monaco, "Bitstream Vera Sans Mono", "Lucida Console", Terminal, monospace;
|
||||||
|
font-size: 14px;
|
||||||
|
|
||||||
|
border-radius: 2px;
|
||||||
|
-moz-border-radius: 2px;
|
||||||
|
-webkit-border-radius: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
width: 100%;
|
||||||
|
padding: 10px;
|
||||||
|
box-shadow: 0 0 10px rgba(0,0,0,.1);
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
code {
|
||||||
|
padding: 3px;
|
||||||
|
margin: 0 3px;
|
||||||
|
box-shadow: 0 0 10px rgba(0,0,0,.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
pre code {
|
||||||
|
display: block;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote {
|
||||||
|
color: #666;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
padding: 0 0 0 20px;
|
||||||
|
border-left: 3px solid #bbb;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ul, ol, dl {
|
||||||
|
margin-bottom: 15px
|
||||||
|
}
|
||||||
|
|
||||||
|
ul {
|
||||||
|
list-style: inside;
|
||||||
|
padding-left: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
ol {
|
||||||
|
list-style: decimal inside;
|
||||||
|
padding-left: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
dl dt {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
dl dd {
|
||||||
|
padding-left: 20px;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
dl p {
|
||||||
|
padding-left: 20px;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr {
|
||||||
|
height: 1px;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
border: none;
|
||||||
|
background: url('../images/bg_hr.png') repeat-x center;
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
border: 1px solid #373737;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
th {
|
||||||
|
font-family: 'Lucida Grande', 'Helvetica Neue', Helvetica, Arial, sans-serif;
|
||||||
|
padding: 10px;
|
||||||
|
background: #373737;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
td {
|
||||||
|
padding: 10px;
|
||||||
|
border: 1px solid #373737;
|
||||||
|
}
|
||||||
|
|
||||||
|
form {
|
||||||
|
background: #f2f2f2;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
Full-Width Styles
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
.outer {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inner {
|
||||||
|
position: relative;
|
||||||
|
max-width: 640px;
|
||||||
|
padding: 20px 10px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
#forkme_banner {
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
top:0;
|
||||||
|
right: 10px;
|
||||||
|
z-index: 10;
|
||||||
|
padding: 10px 50px 10px 10px;
|
||||||
|
color: #fff;
|
||||||
|
background: url('../images/blacktocat.png') #0090ff no-repeat 95% 50%;
|
||||||
|
font-weight: 700;
|
||||||
|
box-shadow: 0 0 10px rgba(0,0,0,.5);
|
||||||
|
border-bottom-left-radius: 2px;
|
||||||
|
border-bottom-right-radius: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#header_wrap {
|
||||||
|
background: #212121;
|
||||||
|
background: -moz-linear-gradient(top, #373737, #212121);
|
||||||
|
background: -webkit-linear-gradient(top, #373737, #212121);
|
||||||
|
background: -ms-linear-gradient(top, #373737, #212121);
|
||||||
|
background: -o-linear-gradient(top, #373737, #212121);
|
||||||
|
background: linear-gradient(top, #373737, #212121);
|
||||||
|
}
|
||||||
|
|
||||||
|
#header_wrap .inner {
|
||||||
|
padding: 50px 10px 30px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#project_title {
|
||||||
|
margin: 0;
|
||||||
|
color: #fff;
|
||||||
|
font-size: 42px;
|
||||||
|
font-weight: 700;
|
||||||
|
text-shadow: #111 0px 0px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#project_tagline {
|
||||||
|
color: #fff;
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: 300;
|
||||||
|
background: none;
|
||||||
|
text-shadow: #111 0px 0px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#downloads {
|
||||||
|
position: absolute;
|
||||||
|
width: 210px;
|
||||||
|
z-index: 10;
|
||||||
|
bottom: -40px;
|
||||||
|
right: 0;
|
||||||
|
height: 70px;
|
||||||
|
background: url('../images/icon_download.png') no-repeat 0% 90%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.zip_download_link {
|
||||||
|
display: block;
|
||||||
|
float: right;
|
||||||
|
width: 90px;
|
||||||
|
height:70px;
|
||||||
|
text-indent: -5000px;
|
||||||
|
overflow: hidden;
|
||||||
|
background: url(../images/sprite_download.png) no-repeat bottom left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tar_download_link {
|
||||||
|
display: block;
|
||||||
|
float: right;
|
||||||
|
width: 90px;
|
||||||
|
height:70px;
|
||||||
|
text-indent: -5000px;
|
||||||
|
overflow: hidden;
|
||||||
|
background: url(../images/sprite_download.png) no-repeat bottom right;
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.zip_download_link:hover {
|
||||||
|
background: url(../images/sprite_download.png) no-repeat top left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tar_download_link:hover {
|
||||||
|
background: url(../images/sprite_download.png) no-repeat top right;
|
||||||
|
}
|
||||||
|
|
||||||
|
#main_content_wrap {
|
||||||
|
background: #f2f2f2;
|
||||||
|
border-top: 1px solid #111;
|
||||||
|
border-bottom: 1px solid #111;
|
||||||
|
}
|
||||||
|
|
||||||
|
#main_content {
|
||||||
|
padding-top: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#footer_wrap {
|
||||||
|
background: #212121;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
Small Device Styles
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
@media screen and (max-width: 480px) {
|
||||||
|
body {
|
||||||
|
font-size:14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#downloads {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inner {
|
||||||
|
min-width: 320px;
|
||||||
|
max-width: 480px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#project_title {
|
||||||
|
font-size: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 28px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 21px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4 {
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h5 {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h6 {
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
code, pre {
|
||||||
|
min-width: 320px;
|
||||||
|
max-width: 480px;
|
||||||
|
font-size: 11px;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in a new issue