Skip to content

Instantly share code, notes, and snippets.

@macisi
Created April 3, 2014 07:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save macisi/9950181 to your computer and use it in GitHub Desktop.
Save macisi/9950181 to your computer and use it in GitHub Desktop.
<!DOCTYPE html>
<html>
<head>
<script src="http://cdnjs.cloudflare.com/ajax/libs/modernizr/2.6.2/modernizr.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<meta charset="utf-8">
<title>JS Bin</title>
</head>
<body>
<div class="grid-container position" id="J-grids">
<div class="grid"></div>
<div class="grid"></div>
<div class="grid"></div>
<div class="grid"></div>
<div class="grid"></div>
<div class="grid"></div>
<div class="grid"></div>
<div class="grid"></div>
<div class="grid"></div>
<div class="grid"></div>
<div class="grid"></div>
<div class="grid"></div>
<div class="grid"></div>
<div class="grid"></div>
<div class="grid"></div>
<div class="grid"></div>
</div>
<div class="tile-container position" id="J-tiles">
</div>
</body>
</html>
(function(d){
"use strict";
var GridSize = 100;
var GridGap = 10;
var UnitStep = GridSize + GridGap;
var Max = 3;
var Lock = false;
var _slice = [].slice;
var _sort = [].sort;
var _transform = Modernizr.prefixed("transform");
var Control = {
init: function(){
d.addEventListener("keyup", this.move, false);
},
move: function(e){
if (Lock) return;
switch(e.keyCode) {
case 39: //right
Tile.move(1, 0);
break;
case 38: //up
Tile.move(0, -1);
break;
case 40: //down
Tile.move(0, 1);
break;
case 37: //left
Tile.move(-1, 0);
break;
default:
break;
}
}
};
var Tile = {
el: d.getElementById("J-tiles"),
init: function(){
this.availables = [];
for (var i = 0; i <= Max; i += 1) {
for (var j = 0; j <= Max; j += 1) {
this.availables.push([i, j].join(","));
}
}
this.born(2);
},
collection: [],
//create a random tile
//born(4, [1, 2])
born: function(value){
var tilePos;
var availables = this.availables.slice(0);
value = value || 2;
this.collection.forEach(function(tile){
tilePos = [tile.dataset.x, tile.dataset.y].join(",");
if (availables.indexOf(tilePos) !== -1) {
availables.splice(availables.indexOf(tilePos), 1);
}
});
if (availables.length === 0) {
//game end
return;
}
tilePos = availables[Math.round(Math.random() * (availables.length - 1))];
tilePos = tilePos.split(",");
var tile = d.createElement("div");
tile.className = "tile";
tile.innerText = value;
tile.dataset.value = value;
tile.dataset.x = tilePos[0];
tile.dataset.y = tilePos[1];
tile.style[_transform] = "translate(" + tilePos[0] * UnitStep + "px, " + tilePos[1] * UnitStep + "px) scale(.4)";
this.collection.push(tile);
this.el.appendChild(tile);
Modernizr.prefixed('requestAnimationFrame', window)(function(){
tile.style[_transform] = "translate(" + tilePos[0] * UnitStep + "px, " + tilePos[1] * UnitStep + "px) scale(1)";
});
},
move: function(horizontal, vertical){
Lock = true;
var poses = [0, 1, 2, 3], groups = [], len, delt, updated = false;
if (horizontal !== 0) {
poses.forEach(function(pos){
groups.push(this.getTileGroup("y", pos));
}, this);
} else if(vertical !== 0) {
poses.forEach(function(pos){
groups.push(this.getTileGroup("x", pos));
}, this);
} else {
return;
}
groups.forEach(function(group, index){
if (horizontal + vertical > 0) {
//正向
len = group.length;
while(group[len - 1]) {
if (group[len - 2]) {
//if two tile has the same value, join them
if (group[len - 1].dataset.value === group[len - 2].dataset.value) {
this.join(group[len - 2], group[len - 1]);
group.splice(len - 2, 1);
updated = true;
len -= 2;
continue;
}
}
len -= 1;
}
} else {
//逆向
var i = 0;
len = group.length;
while(i < len) {
if (group[i + 1]) {
//if two tile has the same value, join them
if (group[i].dataset.value === group[i + 1].dataset.value) {
this.join(group[i + 1], group[i]);
group.splice(i + 1, 1);
updated = true;
i += 2;
continue;
}
}
i += 1;
}
}
delt = (horizontal + vertical) > 0 ? Max - (group.length - 1): 0;
group.forEach(function(tile, index){
if (horizontal && (+tile.dataset.x) !== (index + delt)) {
tile.dataset.x = index + delt;
updated = true;
} else if (vertical && (+tile.dataset.y) !== (index + delt)) {
tile.dataset.y = index + delt;
updated = true;
}
tile.style[_transform] = "translate(" + tile.dataset.x * UnitStep + "px, " + tile.dataset.y * UnitStep + "px)";
});
}, this);
updated && this.born(2);
Lock = false;
},
getTileGroup: function(prop, pos){
var tiles = this.el.querySelectorAll(".tile[data-" + prop + "='" + pos + "']");
var exchange = {x: "y", y: "x"};
tiles = _slice.call(tiles, 0);
if (tiles.length > 0) {
tiles.sort(function(t1, t2){
return t1.dataset[exchange[prop]] - t2.dataset[exchange[prop]];
});
}
return tiles;
},
// join two tiles to one tile with values doubled
// tileA + tileB == > tileB
join: function(tileA, tileB){
tileA.style[_transform] = tileB.style[_transform];
tileB.dataset.value *= 2;
tileB.innerText = tileB.dataset.value;
this.el.removeChild(tileA);
this.collection.splice(this.collection.indexOf(tileA), 1);
}
};
var Game = {
init: function(){
Control.init();
Tile.init();
console.clear();
//console.log(Modernizr.prefixed('requestAnimationFrame', window));
}
};
Game.init();
}(document));
@grid-width: 100px;
@grid-height: 100px;
@gap: 10px;
@background: #ccc;
@grid-color: #aaa;
@tile-color: #ffc7c7;
@font-color: #666;
.position {
position: absolute;
left: 0;
top: 0;
}
.grid-container {
z-index: 1;
display: flex;
padding: @gap;
/* flex-direction: row; */
/* flex-wrap: wrap; */
flex-flow: row wrap;
justify-content: space-between;
align-content: space-between;
width: @grid-width * 4 + @gap * 3;
height: @grid-height * 4 + @gap * 3;
background-color: @background;
.grid {
width: @grid-width;
height: @grid-height;
background-color: @grid-color;
}
}
.tile-container {
z-index: 2;
padding: @gap;
.tile {
position: absolute;
width: @grid-width;
height: @grid-height;
background-color: @tile-color;
text-align: center;
line-height: @grid-height;
font-size: 64px;
color: @font-color;
transition: transform ease .125s;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment