Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@alexhornbake
Last active September 24, 2017 18:58
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 alexhornbake/ca4f2b2a338629b55a91bd527b9546a7 to your computer and use it in GitHub Desktop.
Save alexhornbake/ca4f2b2a338629b55a91bd527b9546a7 to your computer and use it in GitHub Desktop.
push pop mechanic
<!DOCTYPE html>
<html>
<head>
<title>pusher</title>
<style>
.tile {
width: 4%;
padding-bottom: 4%;
display: inline-block;
margin: 5px;
}
.box {
background-color: blue;
}
.empty {
background-color: grey;
}
.obstacle {
background-color: green;
}
.player {
background-color: red;
}
</style>
</head>
<body>
<div id="app">
<div id="board"></div>
</div>
<script type="text/javascript">
(function () {
var EMPTY = 0;
var PLAYER = 1;
var BOX = 2;
var OBSTACLE = 3;
function getRandomInt(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min)) + min; //The maximum is exclusive and the minimum is inclusive
}
var Board = {
board : [
[2,2,0,0,0],
[0,2,2,0,0],
[0,0,1,0,0],
[0,3,0,0,0],
[0,0,2,0,0],
],
playerPos: { x: 2, y: 2 },
shouldAddBox: false,
getWidth() {
return this.board[0].length
},
getHeight() {
return this.board.length
},
getAllEmptyCoordinates() {
var empties = [];
for (var i = 0; i < this.getHeight(); i++) {
for (var j = 0; j < this.getWidth(); j++) {
if (this.board[i][j] == EMPTY) {
empties.push({x: j, y: i});
}
}
}
return empties
},
addRandomBox() {
var empties = this.getAllEmptyCoordinates();
if (empties.length == 0) {
return
}
var newBox=empties[getRandomInt(0, empties.length)];
this.board[newBox.y][newBox.x] = BOX;
},
clearFullRowsAndCols() {
var rowCounts = [];
var colCounts = [];
// count how many dots are in each row and col
for (var i = 0; i < this.getHeight(); i++) {
rowCounts.push(0);
for (var j = 0; j < this.getWidth(); j++) {
if (i === 0) {
colCounts.push(0);
}
if (this.board[i][j] === BOX) {
rowCounts[i]++;
colCounts[j]++;
}
}
}
// if curr position is in a full row or col, clear it.
var didClear = false;
for (var i = 0; i < this.getHeight(); i++) {
for (var j = 0; j < this.getWidth(); j++) {
if (rowCounts[i] === this.getWidth() || colCounts[j] === this.getHeight() ){
didClear = true;
this.board[i][j] = EMPTY;
}
}
}
return didClear
},
setPlayerPos(x, y) {
if (x === this.playerPos.x && y === this.playerPos.y) {
return false
}
this.board[this.playerPos.y][this.playerPos.x] = EMPTY;
this.playerPos = {x : x, y : y};
this.board[y][x] = PLAYER;
return true
},
isPositionOnBoard(x, y) {
return (
x < this.getWidth() &&
x >= 0 &&
y < this.getHeight() &&
y >= 0
)
},
handlePlayerMove(deltaX, deltaY, results) {
if (!results) {
results = { didPlayerMove : false, didBoxMove : false}
}
var newPos = {
x : this.playerPos.x + deltaX,
y : this.playerPos.y + deltaY,
}
// check that you are not moving off the board
if ( !this.isPositionOnBoard(newPos.x, newPos.y) ){
return results
}
//Check collisions
var dest = this.board[newPos.y][newPos.x]
switch (dest) {
case BOX:
var didBoxMove = this.playerCollidesWithBox(newPos, deltaX, deltaY);
return {
didBoxMove : didBoxMove,
didPlayerMove: true,
}
break
case OBSTACLE:
return { didPlayerMove : results.didPlayerMove || false, didBoxMove : results.didBoxMove || false}
default:
this.setPlayerPos(newPos.x, newPos.y);
return this.handlePlayerMove(deltaX, deltaY, { didPlayerMove : true, didBoxMove : results.didBoxMove || false});
break
}
},
playerCollidesWithBox(newPos, deltaX, deltaY) {
// We have to simply compress the array between the player and the boarder.
// For instance [player, 2, 2, 2, 0 ] becomes [ 0, player, 2, 2 , 2 ]
// This logic could maybe be simplified to 1 case instead of 4 by transposing the game board
// such that there is only one case, however, that would also require the overhead
// of rotating the matrix...
if (deltaX === -1 || deltaX === 1) {
var emptyCount = 0
// count the empty positions between the player and the boundary
// fill those spaces with dots
for (var i = newPos.x+deltaX ; (i > -1 && i < this.getWidth()); i+=deltaX) {
if (this.board[newPos.y][i] === EMPTY ) {
this.board[newPos.y][i] = BOX
emptyCount ++
}
if (this.board[newPos.y][i] === OBSTACLE) {
break
}
}
// if there are no empty spaces, do nothing
if (emptyCount === 0) {
return false
}
// move the now filled empty spaces to the "front" of the line.
for (var i = newPos.x; (i < newPos.x+emptyCount) && (i > newPos.x-emptyCount); i+=deltaX) {
this.board[newPos.y][i] = EMPTY
}
this.setPlayerPos(newPos.x + deltaX*(emptyCount-1), newPos.y)
return true
} else {
var emptyCount = 0
// count the empty positions between the player and the boundary
// fill those spaces with dots
for (var i = newPos.y+deltaY ; (i > -1 && i < this.getHeight()); i+=deltaY) {
if (this.board[i][newPos.x] === EMPTY ) {
this.board[i][newPos.x] = BOX
emptyCount ++
}
if (this.board[i][newPos.x] === OBSTACLE) {
break
}
}
// if there are no empty spaces, do nothing
if (emptyCount === 0) {
return false
}
// move the now filled empty spaces to the "front" of the line.
for (var i = newPos.y; (i < newPos.y+emptyCount) && (i > newPos.y-emptyCount); i+=deltaY) {
this.board[i][newPos.x] = EMPTY
}
this.setPlayerPos(newPos.x, newPos.y + deltaY*(emptyCount-1))
return true
}
}
}
var Key = {
_pressed: {},
LEFT: 37,
UP: 38,
RIGHT: 39,
DOWN: 40,
isDown: function(keyCode) {
if (this._pressed[keyCode]) {
delete this._pressed[keyCode];
return true
}
return false
},
onKeydown: function(event) {
this._pressed[event.keyCode] = Date.now();
},
onKeyup: function(event) {
delete this._pressed[event.keyCode];
}
};
function updateDOM(board) {
var appEl = document.getElementById("app");
var oldBoardEl = document.getElementById("board");
var newBoardEl = document.createElement("div");
newBoardEl.id="board";
for (var i=0;i<board.length;i++) {
var row = document.createElement("div");
var text = "";
for (var j = 0; j < board[i].length; j++) {
var cell = document.createElement("div")
switch (board[i][j]) {
case EMPTY:
cell.className = "tile empty";
break
case BOX:
cell.className = "tile box";
break
case PLAYER:
cell.className = "tile player";
break
case OBSTACLE:
cell.className = "tile obstacle";
break
default:
cell.className = "tile";
}
row.appendChild(cell);
}
newBoardEl.appendChild(row);
}
appEl.replaceChild(newBoardEl, oldBoardEl);
}
window.addEventListener('keyup', function(event) { Key.onKeyup(event); }, false);
window.addEventListener('keydown', function(event) { Key.onKeydown(event); }, false);
updateDOM(Board.board);
var everyOtherTurn = false;
// recursive main loop.
function main() {
window.requestAnimationFrame( main );
var delta = undefined;
if (Key.isDown(Key.UP)) delta = {x:0,y:-1};
if (Key.isDown(Key.LEFT)) delta = {x:-1,y:0};
if (Key.isDown(Key.DOWN)) delta = {x:0,y:1};
if (Key.isDown(Key.RIGHT)) delta = {x:1,y:0};
if (delta) {
var results = Board.handlePlayerMove(delta.x, delta.y)
if (results.didPlayerMove) {
if (everyOtherTurn) {
Board.addRandomBox();
}
everyOtherTurn = !everyOtherTurn
var didClearBoxs = Board.clearFullRowsAndCols();
updateDOM(Board.board);
}
}
}
// start main loop
main();
})()
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment