Pandaban – Build HTML5 Sokoban game with Panda2 and play it with keyboard or by swiping
Talking about Sokoban game, Game development, HTML5 and Javascript.
Do you like my tutorials?
Then consider supporting me on Ko-fi.

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.