Pandaban – Build HTML5 Sokoban game with Panda2 and play it with keyboard or by swiping
Talking about Sokoban game, Game development, HTML5 and Javascript.
Learn cross platform HTML5 game development
Check my Gumroad page for commented source code, games and books.

game.module(
"game.main"
)
.body(function() {
var gameOptions = {
tileSize: 40,
animationSpeed: 200
}
var level = [
[1,1,1,1,1,1,1,1],
[1,0,0,1,1,1,1,1],
[1,0,0,1,1,1,1,1],
[1,0,0,0,0,0,0,1],
[1,1,4,2,1,3,0,1],
[1,0,0,0,1,0,0,1],
[1,0,0,0,1,1,1,1],
[1,1,1,1,1,1,1,1]
]
var EMPTY = 0;
var WALL = 1;
var SPOT = 2;
var CRATE = 3;
var PLAYER = 4;
game.addAsset("tiles.png");
game.createScene("Main", {
init: function() {
this.canMove = true;
this.drawLevel();
},
drawLevel: function(){
this.sheet = new game.SpriteSheet("tiles.png", gameOptions.tileSize, gameOptions.tileSize);
this.crates = [];
this.crates.length = 0;
for (var i = 0; i < level.length; i++) {
this.crates[i] = [];
for (var j = 0; j < level[i].length; j++) {
this.crates[i][j] = null;
var item = level[i][j];
switch(item){
case PLAYER:
case PLAYER + SPOT:
this.player = this.sheet.frame(item);
this.player.position.set(j * gameOptions.tileSize, i * gameOptions.tileSize);
this.player.addTo(this.stage);
this.player.zIndex = 1;
this.player.posX = j;
this.player.posY = i;
var tile = this.sheet.frame(item - PLAYER);
tile.position.set(j * gameOptions.tileSize, i * gameOptions.tileSize);
tile.addTo(this.stage);
tile.zIndex = 0;
break;
case CRATE:
case CRATE + SPOT:
this.crates[i][j] = this.sheet.frame(item);
this.crates[i][j].position.set(j * gameOptions.tileSize, i * gameOptions.tileSize);
this.crates[i][j].addTo(this.stage);
this.crates[i][j].zIndex = 1;
var tile = this.sheet.frame(item - CRATE);
tile.position.set(j * gameOptions.tileSize, i * gameOptions.tileSize);
tile.addTo(this.stage);
tile.zIndex = 0;
break;
default:
var tile = this.sheet.frame(item);
tile.position.set(j * gameOptions.tileSize, i * gameOptions.tileSize);
tile.addTo(this.stage);
tile.zIndex = 0;
}
}
}
game.scene.stage.children.sort(this.depthCompare);
},
swipe: function(d){
switch(d){
case "RIGHT":
this.checkMove(1, 0);
break;
case "LEFT":
this.checkMove(-1, 0);
break;
case "UP":
this.checkMove(0, -1);
break;
case "DOWN":
this.checkMove(0, 1);
break;
}
},
checkMove: function(deltaX, deltaY){
if(this.canMove){
if(this.isWalkable(this.player.posX + deltaX, this.player.posY + deltaY)){
this.movePlayer(deltaX, deltaY, false);
return;
}
if(this.isCrate(this.player.posX + deltaX, this.player.posY + deltaY)){
if(this.isWalkable(this.player.posX + 2 * deltaX, this.player.posY + 2 * deltaY)){
this.movePlayer(deltaX, deltaY, true);
return;
}
}
}
},
isWalkable: function(posX, posY){
return level[posY][posX] == EMPTY || level[posY][posX] == SPOT;
},
isCrate: function(posX, posY){
return level[posY][posX] == CRATE || level[posY][posX] == CRATE + SPOT;
},
movePlayer: function(deltaX, deltaY, pushCrate){
this.canMove = false;
var playerTween = new game.Tween(this.player.position);
playerTween.to({
x: this.player.x + deltaX * gameOptions.tileSize,
y: this.player.y + deltaY * gameOptions.tileSize
}, gameOptions.animationSpeed);
playerTween.start();
playerTween.onComplete(function() {
level[this.player.posY][this.player.posX] -= PLAYER;
this.player.posX += deltaX;
this.player.posY += deltaY;
level[this.player.posY][this.player.posX] += PLAYER;
if(pushCrate){
this.crates[this.player.posY + deltaY][this.player.posX + deltaX] = this.crates[this.player.posY][this.player.posX];
this.crates[this.player.posY][this.player.posX] = null;
level[this.player.posY][this.player.posX] -= CRATE;
level[this.player.posY + deltaY][this.player.posX + deltaX] += CRATE;
this.crates[this.player.posY + deltaY][this.player.posX + deltaX].texture = this.sheet.textures[level[this.player.posY + deltaY][this.player.posX + deltaX]];
}
this.player.texture = this.sheet.textures[level[this.player.posY][this.player.posX]];
this.canMove = true;
}.bind(this));
if(pushCrate){
var crateTween = new game.Tween(this.crates[this.player.posY + deltaY][this.player.posX + deltaX].position);
crateTween.to({
x: this.crates[this.player.posY + deltaY][this.player.posX + deltaX].x + deltaX * gameOptions.tileSize,
y: this.crates[this.player.posY + deltaY][this.player.posX + deltaX].y + deltaY * gameOptions.tileSize
}, gameOptions.animationSpeed);
crateTween.start();
}
},
depthCompare: function (a, b){
if (a.zIndex < b.zIndex) return -1;
if (a.zIndex > b.zIndex) return 1;
return 0;
},
update: function() {
if (game.keyboard.down("LEFT")){
this.checkMove(-1, 0);
}
if (game.keyboard.down("RIGHT")){
this.checkMove(1, 0);
}
if (game.keyboard.down("UP")){
this.checkMove(0, -1);
}
if (game.keyboard.down("DOWN")){
this.checkMove(0, 1);
}
}
});
});
Never miss an update! Subscribe, and I will bother you by email only when a new game or full source code comes out.