ClojureScript中的游戏架构

ClojureScript中的游戏架构,clojure,clojurescript,Clojure,Clojurescript,假设你正在做一个游戏。在游戏中,你有一些关于世界的状态:分数、玩家数量、敌人等等。让我们假设游戏足够简单,在文件中有全局更新世界不会那么糟糕。不是最优的,但这是一种方法。从OO的角度来看,您将拥有一个类似于World对象的单例对象,其中包含用于查询/更新的方法 检测按键并将按键状态传递到发动机的最佳实践是什么?会不会是这样的: (let [presses {}] (.addEventListener "keypress" #(!set presses (into presses

假设你正在做一个游戏。在游戏中,你有一些关于世界的状态:分数、玩家数量、敌人等等。让我们假设游戏足够简单,在文件中有全局更新世界不会那么糟糕。不是最优的,但这是一种方法。从OO的角度来看,您将拥有一个类似于World对象的单例对象,其中包含用于查询/更新的方法

检测按键并将按键状态传递到发动机的最佳实践是什么?会不会是这样的:

  (let [presses {}] 
     (.addEventListener "keypress" #(!set presses (into presses {%1 true})))
     (requestAnimationFrame js/window (fn [] (do-game presses))

是的,这很好,虽然全局状态不需要单例对象,但是一个简单的
atom
就可以了。像这样的交互式Clojurescript程序有太多的选项,在这种情况下无法推荐任何特定的选项

是的,这很好,尽管全局状态不需要单例对象,但简单的
atom
也可以。像这样的交互式Clojurescript程序有太多的选项,在这种情况下无法推荐任何特定的选项

使用core.async捕获和合并事件并将其转换为游戏命令是一种非常酷的方法

您可以在我的蛇游戏中看到一个示例:

一旦您捕获了您的输入并将其转换为游戏事件,您就可以将其传输到您拥有游戏逻辑的任何地方

在我的例子中,这是一个go循环,它处理命令并包含该fn的本地游戏状态,对其应用不同的函数并发出事件供UI作出反应:

更传统的方法是将这些命令传递给一个函数,该函数将选择如何更新包含游戏状态的atom

关于游戏中的core.async架构类型,有一篇很酷的帖子:

使用core.async捕获和合并事件并将其转换为游戏命令是一种非常酷的方法

您可以在我的蛇游戏中看到一个示例:

一旦您捕获了您的输入并将其转换为游戏事件,您就可以将其传输到您拥有游戏逻辑的任何地方

在我的例子中,这是一个go循环,它处理命令并包含该fn的本地游戏状态,对其应用不同的函数并发出事件供UI作出反应:

更传统的方法是将这些命令传递给一个函数,该函数将选择如何更新包含游戏状态的atom

关于游戏中的core.async架构类型,有一篇很酷的帖子:

您可以通过在RequestAnimationFrame中呈现的atom中创建应用程序状态来尝试Om,因为它可以通过在RequestAnimationFrame中呈现的atom中创建应用程序状态来尝试Om

有很多方法可以做到这一点,但我将展示我的方法。我使用用于clojurescript的baconjs和jquery包装器来实现这一点

(ns puzzle.input
  (:require [jayq.core :as j :refer [$]]
            [yolk.bacon :as b]))

(defn- read-key-input [e]
  (let [k (.-which e)]
    (condp = k
      38 :north
      40 :south
      37 :west
      39 :east
      :sit)))

(defn arrow-stream [$elem]
  (-> (.keydownE $elem)
      (b/filter (fn [e] (not= :sit (read-key-input e))))
      (b/do-action j/prevent)
      (b/map (fn [e] (read-key-input e)))))
我在身体上设置了一个键盘输入流。我用如下方式订阅该流:

(-> (puzzle.input/arrow-stream (jayq.core/$ "body"))
    (yolk.bacon/on-value (fn [direction] (change-world direction))))
现在,每当按键是箭头时,
change world
函数就会根据方向调用




有很多方法可以做到这一点,但我会展示我的方法。我使用用于clojurescript的baconjs和jquery包装器来实现这一点

(ns puzzle.input
  (:require [jayq.core :as j :refer [$]]
            [yolk.bacon :as b]))

(defn- read-key-input [e]
  (let [k (.-which e)]
    (condp = k
      38 :north
      40 :south
      37 :west
      39 :east
      :sit)))

(defn arrow-stream [$elem]
  (-> (.keydownE $elem)
      (b/filter (fn [e] (not= :sit (read-key-input e))))
      (b/do-action j/prevent)
      (b/map (fn [e] (read-key-input e)))))
我在身体上设置了一个键盘输入流。我用如下方式订阅该流:

(-> (puzzle.input/arrow-stream (jayq.core/$ "body"))
    (yolk.bacon/on-value (fn [direction] (change-world direction))))
现在,每当按键是箭头时,
change world
函数就会根据方向调用




您有什么好的资源来展示不同的选项吗?谢谢你的帮助!你有什么好的资源来展示不同的选择吗?谢谢你的帮助!你可能喜欢阅读。有很多东西值得思考。我得到了用户的输入,我只是在和自己讨论如何像他所说的那个样传递世界。谢谢你的链接!当然,在Clojure中没有义务纯粹起作用(正如他所讨论的),这就是为什么我们毕竟有原子。但至少值得深思一下。我认为关键点正好达到了正确的平衡:状态越少越好,但太少可能会很麻烦。我认为core.async提供了一些有趣的方法来处理输入,比如按键并将其输入游戏引擎。我发现,作者在其中使用core.async制作了一个Dots游戏,非常有趣。你可能会喜欢阅读。有很多值得思考的地方。我得到了用户的输入,我只是在和自己讨论如何像他所说的那个样传递世界。谢谢你的链接!当然,在Clojure中没有义务纯粹起作用(正如他所讨论的),这就是为什么我们毕竟有原子。但至少值得深思一下。我认为关键点正好达到了正确的平衡:状态越少越好,但太少可能会很麻烦。我认为core.async提供了一些有趣的方法来处理输入,比如按键并将其输入游戏引擎。我发现,作者使用core.async制作的Dots游戏非常有趣。