Ver código fonte

First implementation of movement

Includes a somewhat simplistic implementation of adding a new tile
for every move.
master
pai
commit
765604ffae
4 arquivos alterados com 181 adições e 5 exclusões
  1. +2
    -1
      index.html
  2. +144
    -0
      keyboard_input_manager.js
  3. +17
    -0
      src/ttfe/board.cljs
  4. +18
    -4
      src/ttfe/core.cljs

+ 2
- 1
index.html Ver arquivo

@@ -72,7 +72,8 @@
</p>
</div>

<script src="http://fb.me/react-0.9.0.js"></script>
<script src="react-0.9.0.js"></script>
<script src="keyboard_input_manager.js"></script>
<script src="out/goog/base.js" type="text/javascript"></script>
<script src="ttfe.js" type="text/javascript"></script>
<script type="text/javascript">goog.require("ttfe.core");</script>


+ 144
- 0
keyboard_input_manager.js Ver arquivo

@@ -0,0 +1,144 @@
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 up
76: 1, // Vim right
74: 2, // Vim down
72: 3, // Vim left
87: 0, // W
68: 1, // D
83: 2, // S
65: 3 // A
};

// Respond to direction keys
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);
}
}

// R key restarts the game
if (!modifiers && event.which === 82) {
self.restart.call(self, event);
}
});

// Respond to button presses
this.bindButtonPress(".retry-button", this.restart);
this.bindButtonPress(".restart-button", this.restart);
this.bindButtonPress(".keep-playing-button", this.keepPlaying);

// Respond 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; // Ignore if touching with more than 1 finger
}

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; // Ignore if still touching with one or more fingers
}

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");
};

KeyboardInputManager.prototype.bindButtonPress = function (selector, fn) {
var button = document.querySelector(selector);
button.addEventListener("click", fn.bind(this));
button.addEventListener(this.eventTouchend, fn.bind(this));
};

+ 17
- 0
src/ttfe/board.cljs Ver arquivo

@@ -47,3 +47,20 @@

(defn move-down [board]
(rotate-ccw (move-left (rotate-cw board))))

(defn find-empty-tiles [board]
(reduce (fn [acc row-n]
(let [row (nth board row-n)]
(concat acc (reduce (fn [col-acc col-n]
(let [tile (nth row col-n)]
(if (nil? tile)
(conj col-acc [row-n col-n])
col-acc)))
'()
(range (count row))))))
'()
(range (count board))))

(defn add-tile [board]
(let [[rand-row rand-col] (rand-nth (find-empty-tiles board))]
(update-in board [rand-row rand-col] (fn [_] 2))))

+ 18
- 4
src/ttfe/core.cljs Ver arquivo

@@ -1,6 +1,8 @@
(ns ttfe.core
(:require [om.core :as om :include-macros true]
[om.dom :as dom :include-macros true]))
[om.dom :as dom :include-macros true]
[ttfe.board :refer [move-left move-right move-up move-down
add-tile]]))

(enable-console-print!)

@@ -11,6 +13,8 @@
[nil 8 nil nil]
[nil nil nil nil]]}))

(def move-fns [move-up move-right move-down move-left])

(defn divs-for-board [board]
(reduce (fn [row-acc row-n]
(let [row (nth board row-n)]
@@ -37,6 +41,16 @@
cell-divs)))))

(defn init []
(om/root tiles-view
app-state
{:target (. js/document (getElementById "tiles"))}))
(let [input-manager (js/KeyboardInputManager.)]
(.on input-manager
"move"
(fn [direction]
(let [move-fn (nth move-fns direction)]
(swap! app-state
(fn [state]
(let [board (:board state)]
(update-in state [:board] (fn [b]
(add-tile (move-fn b))))))))))
(om/root tiles-view
app-state
{:target (. js/document (getElementById "tiles"))})))

Carregando…
Cancelar
Salvar