Reactor
- Package
- purescript-grid-reactors
- Repository
- Eugleo/purescript-grid-reactors
As the Pyret documentation puts it, a reactor is a value enabling the creation of time-based animations, simulations, and interactive programs. During the creation of a reactor, the user supplies a function for handling clock ticks, and functions for handling mouse and keyboard input events. The reactor calls these event handlers whenever the respective event occurs. From within the event handlers, the reactor's state — or, the world, as we call it — can be updated. After each world update, the reactor renders the new world with the supplied drawing function.
You can read more in the documentation of the type Reactor
below, under the documentation for the module Reactor.Types
.
The base Reactor module re-exports some useful functions, apart
from the base color pallete which is best imported by import Reactor.Graphics.Colors as Color
.
In our implementation, the rendering is done using a hooks-based Halogen component.
Also, the world needs to have at least a boolean field named paused
, that signalizes
to the reactor whether the internal clock should be ticking or not.
#runReactor Source
runReactor :: forall world. Reactor world -> Configuration -> Effect Unit
Start a Reactor
and render it asynchronously as a Halogen component with the given Configuration
.
The reactor's world is required to have a field named paused
that is used to decide
whether the reactor's clock should be running (paused: false
) or not (paused: true
).
Re-exports from Reactor.Internal.Helpers
Re-exports from Reactor.Internal.Widget
#Widget Source
data Widget
Currently we support two types of widgets: sections and labels. Those two differ only in the way they are rendered. We recommend using labels for presenting important dynamic information to the user, and using sections to give short, descriptive labels to these pieces of information.
Constructors
Re-exports from Reactor.Reaction
#updateW_ Source
updateW_ :: forall changes t c world. Union changes t world => Nub changes c => Record changes -> Reaction (Record world)
Modify certain fields of the world by passing new values for them.
Behaves the same as the updateW
function, but returns unit
instead of the new value of the world.
type World = { player :: { x :: Int, y :: Int } }
handleEvent event = case event of
KeyPress { key : "ArrowUp" } -> do
oldWorld <- getW
updateW_
{ player: { x : oldWorld.player.x, y: oldWorld.player.y + 1 } }
newWorld <- getW
log $ "New world is: " <> show newWorld
#updateW Source
updateW :: forall changes t c world. Union changes t world => Nub changes c => Record changes -> ReactionM (Record world) (Record world)
Modify certain fields of the world by passing new values for them.
Returns the value of the new world.
type World = { player :: { x :: Int, y :: Int } }
handleEvent event = case event of
KeyPress { key : "ArrowUp" } ->
oldWorld <- getW
newWorld <-
updateW
{ player: { x : oldWorld.player.x, y: oldWorld.player.y + 1 } }
log $ "New world is: " <> show newWorld
#modifyW Source
modifyW :: forall world. (world -> world) -> ReactionM world world
Modify the current world by passing in a (world -> world)
updating function.
The function will receive the current value of the world, and should return the new updated value.
Returns the value of the new world.
type World = { player :: { x :: Int, y :: Int } }
handleEvent event = case event of
KeyPress { key : "ArrowUp" } ->
newWorld <- modifyW \oldWorld ->
{ player: { x : oldWorld.player.x, y: oldWorld.player.y + 1 } }
log $ "New world is: " <> show newWorld
#executeDefaultBehavior Source
executeDefaultBehavior :: forall world. Reaction world
After handling the event, execute the default behavior as well.
You can read more in the documentation of Reactor.Events
.
Usually you'll call this in the handleEvent
function, for events that you don't want to handle,
e.g. when pressing 'J' doesn't do anything in your game.
#dimensions Source
dimensions :: forall world. ReactionM world Dimensions
Get a record of the following:
height :: Int
, the height of the grid, in tileswidth :: Int
, the width of the grid, in tilestileSize :: Int
the size of one grid tile, in points. The size is set internally, and this is the only way to get its value.
Re-exports from Reactor.Types
#Reactor Source
type Reactor world = { draw :: world -> Drawing, handleEvent :: Event -> Reaction world, initial :: world, isPaused :: world -> Boolean }
The reactor is a simple record. Reactors are parametrized over the type of the world
which is saved in the reactor.
The fields in the record are the following:
initial
is the initial state of the reactor's worldisPaused
is a function used by the reactor to find out whether its internal clock should be paused or not. The clock is paused whenisPaused
returnstrue
.draw
is a function used to render the world anytime it is changedhandleEvent
is a function for handling the three types of events that can occur during your game or simulation: keypress events, mouse events, and tick events. The events are handled by running theReaction
returned byhandleEvent
.- Tick events are fired on every tick of the reactor's clock, around 60 times a second, provided the reactor is not paused.
- Keypress events are fired when a key on a keyboard is pressed.
- Mouse events are fired whenever a mouse is moved above the canvas (the drawing area of the reactor), when the canvas is clicked, or when the user drags something (i.e. clicks and then moves the mouse).
#Configuration Source
type Configuration = { height :: Int, title :: String, widgets :: Array (String /\ Widget), width :: Int }
Configuration for the Halogen component that renders the reactor. The component creates everything on the webpage you see when you run the reactor. Although a reactor is a general structure, this library focuses on reactors with grid-based rendering. The component thus needs a little more info than just what is in already the reactor, namely:
title
, the title of the webpage where the reactor is renderedwidth
, the width of the grid, in tilesheight
the height of the grid, in tileswidgets
is an array of widgets that are present in the Reactor from the start, ordered from top-most to bottom-most Notably, the size of the rendered tiles isn't customizable and is set to 30pts.
Button { importance :: Importance, label :: String, action :: world -> world }