]> gitweb.factorcode.org Git - factor.git/commitdiff
Merge branch 'master' of git://factorcode.org/git/factor
authorJoe Groff <arcata@gmail.com>
Sun, 17 Jan 2010 07:15:02 +0000 (23:15 -0800)
committerJoe Groff <arcata@gmail.com>
Sun, 17 Jan 2010 07:15:02 +0000 (23:15 -0800)
13 files changed:
extra/game/loop/authors.txt [new file with mode: 0644]
extra/game/loop/loop-docs.factor [new file with mode: 0644]
extra/game/loop/loop.factor
extra/game/loop/summary.txt [new file with mode: 0644]
extra/game/worlds/authors.txt [new file with mode: 0644]
extra/game/worlds/summary.txt [new file with mode: 0644]
extra/game/worlds/worlds-docs.factor [new file with mode: 0644]
extra/game/worlds/worlds.factor
extra/gpu/demos/bunny/bunny.factor
extra/gpu/demos/raytrace/raytrace.factor
extra/method-chains/method-chains-docs.factor [new file with mode: 0644]
extra/method-chains/summary.txt [new file with mode: 0644]
extra/terrain/terrain.factor

diff --git a/extra/game/loop/authors.txt b/extra/game/loop/authors.txt
new file mode 100644 (file)
index 0000000..f13c9c1
--- /dev/null
@@ -0,0 +1 @@
+Joe Groff
diff --git a/extra/game/loop/loop-docs.factor b/extra/game/loop/loop-docs.factor
new file mode 100644 (file)
index 0000000..ea520af
--- /dev/null
@@ -0,0 +1,102 @@
+! (c)2009 Joe Groff bsd license
+USING: help.markup help.syntax kernel math ui.gadgets.worlds ;
+IN: game.loop
+
+HELP: <game-loop>
+{ $values
+    { "tick-interval-micros" integer } { "delegate" "a " { $link "game.loop-delegates" } }
+    { "loop" game-loop }
+}
+{ $description "Constructs a new stopped " { $link game-loop } " object. When started, the game loop will call the " { $link tick* } " method on the " { $snippet "delegate" } " every " { $snippet "tick-interval-micros" } " microseconds, and " { $link draw* } " on the delegate as frequently as possible. The " { $link start-loop } " and " { $link stop-loop } " words start and stop the game loop." } ;
+
+HELP: benchmark-frames-per-second
+{ $values
+    { "loop" game-loop }
+    { "n" float }
+}
+{ $description "Returns the average number of times per second the game loop has called " { $link draw* } " on its delegate since the game loop was started with " { $link start-loop } " or since the benchmark counters have been reset with " { $link reset-loop-benchmark } "." } ;
+
+HELP: benchmark-ticks-per-second
+{ $values
+    { "loop" game-loop }
+    { "n" float }
+}
+{ $description "Returns the average number of times per second the game loop has called " { $link tick* } " on its delegate since the game loop was started with " { $link start-loop } " or since the benchmark counters have been reset with " { $link reset-loop-benchmark } "." } ;
+
+{ reset-loop-benchmark benchmark-frames-per-second benchmark-ticks-per-second } related-words
+
+HELP: draw*
+{ $values
+    { "tick-slice" float } { "delegate" "a " { $link "game.loop-delegates" } }
+}
+{ $description "This generic word is called by a " { $link game-loop } " on its " { $snippet "delegate" } " object in a tight loop while the game loop is running. The " { $snippet "tick-slice" } " value represents what fraction of the game loop's " { $snippet "tick-interval-micros" } " time period has passed since " { $link tick* } " was most recently called on the delegate." } ;
+
+HELP: game-loop
+{ $class-description "Objects of the " { $snippet "game-loop" } " class manage game loops. See " { $link "game.loop" } " for an overview of the game loop library. To construct a game loop, use " { $link <game-loop> } ". To start and stop a game loop, use the " { $link start-loop } " and " { $link stop-loop } " words." } ;
+
+HELP: game-loop-error
+{ $values
+    { "game-loop" game-loop } { "error" "an error object" }
+}
+{ $description "If an uncaught error is thrown from inside a game loop delegate's " { $link tick* } " or " { $link draw* } ", the game loop will catch the error, stop the game loop, and rethrow an error of this class." } ;
+
+HELP: reset-loop-benchmark
+{ $values
+    { "loop" game-loop }
+}
+{ $description "Resets the benchmark counters on a " { $link game-loop } ". Subsequent calls to " { $link benchmark-frames-per-second } " and " { $link benchmark-ticks-per-second } " will measure their values from the point " { $snippet "reset-loop-benchmark" } " was called." } ;
+
+HELP: start-loop
+{ $values
+    { "loop" game-loop }
+}
+{ $description "Starts running a " { $link game-loop } "." } ;
+
+HELP: stop-loop
+{ $values
+    { "loop" game-loop }
+}
+{ $description "Stops running a " { $link game-loop } "." } ;
+
+{ start-loop stop-loop } related-words
+
+HELP: tick*
+{ $values
+    { "delegate" "a " { $link "game.loop-delegates" } }
+}
+{ $description "This generic word is called by a " { $link game-loop } " on its " { $snippet "delegate" } " object at regular intervals while the game loop is running. The game loop's " { $snippet "tick-interval-micros" } " attribute determines the number of microseconds between invocations of " { $snippet "tick*" } "." } ;
+
+{ draw* tick* } related-words
+
+ARTICLE: "game.loop-delegates" "Game loop delegate"
+"A " { $link game-loop } " object requires a " { $snippet "delegate" } " that implements the logic that controls the game. A game loop delegate can be any object that provides two methods for the following generic words:"
+{ $subsections
+    tick*
+    draw*
+}
+{ $snippet "tick*" } " will be called at a regular interval determined by the game loop's " { $snippet "tick-interval-micros" } " attribute. " { $snippet "draw*" } " will be invoked in a tight loop, updating as frequently as possible." ;
+
+ARTICLE: "game.loop" "Game loops"
+"The " { $vocab-link "game.loop" } " vocabulary contains the implementation of a game loop. The game loop supports decoupled rendering and game logic timers; given a delegate object with methods on the " { $link tick* } " and " { $link draw* } " methods, the game loop will invoke the " { $snippet "tick*" } " method at regular intervals while invoking the " { $snippet "draw*" } " method as frequently as possible. Game loop objects must first be constructed:"
+{ $subsections
+    "game.loop-delegates"
+    <game-loop>
+}
+"Once constructed, the game loop can be started and stopped:"
+{ $subsections
+    start-loop
+    stop-loop
+}
+"The game loop maintains performance counters for measuring drawing frames and ticks per second:"
+{ $subsections
+    reset-loop-benchmark
+    benchmark-frames-per-second
+    benchmark-ticks-per-second
+}
+"The game loop manages errors that occur in the delegate's methods during the course of the game loop:"
+{ $subsections
+    game-loop-error
+}
+"The " { $vocab-link "game.worlds" } " vocabulary provides a convenient " { $link world } " subclass that integrates the game loop implementation with UI applications, managing the starting and stopping of the loop for you." ;
+
+ABOUT: "game.loop"
index 0862a5e48c8ac6bc39c11865a11e335e757080a4..80753e4e409767f7f888ff4cfa27db6e92cae5a4 100644 (file)
@@ -1,3 +1,4 @@
+! (c)2009 Joe Groff bsd license
 USING: accessors calendar continuations destructors kernel math
 math.order namespaces system threads ui ui.gadgets.worlds
 sequences ;
diff --git a/extra/game/loop/summary.txt b/extra/game/loop/summary.txt
new file mode 100644 (file)
index 0000000..e75ed94
--- /dev/null
@@ -0,0 +1 @@
+Game loop
diff --git a/extra/game/worlds/authors.txt b/extra/game/worlds/authors.txt
new file mode 100644 (file)
index 0000000..f13c9c1
--- /dev/null
@@ -0,0 +1 @@
+Joe Groff
diff --git a/extra/game/worlds/summary.txt b/extra/game/worlds/summary.txt
new file mode 100644 (file)
index 0000000..6a65cd7
--- /dev/null
@@ -0,0 +1 @@
+World class that integrates game loop and game input
diff --git a/extra/game/worlds/worlds-docs.factor b/extra/game/worlds/worlds-docs.factor
new file mode 100644 (file)
index 0000000..faa21a1
--- /dev/null
@@ -0,0 +1,50 @@
+! (c)2009 Joe Groff bsd license
+USING: game.loop help.markup help.syntax kernel math method-chains
+ui ui.gadgets.worlds words ;
+IN: game.worlds
+
+HELP: GAME:
+{ $syntax """GAME: word { attributes }
+    attribute-code ;""" }
+{ $description "Similar to " { $link POSTPONE: MAIN-WINDOW: } ", defines a main entry point " { $snippet "word" } " for the current vocabulary that opens a UI window with the provided " { $snippet "attributes" } ". In addition to the standard " { $link world-attributes } ", additional " { $link game-attributes } " can be specified to specify game-specific attributes. Unlike " { $link POSTPONE: MAIN-WINDOW: } ", the " { $snippet "attributes" } " for " { $snippet "GAME:" } " must provide values for the " { $snippet "world-class" } " and " { $snippet "tick-interval-micros" } " slots." } ;
+
+HELP: game-attributes
+{ $class-description "Extends the " { $link world-attributes } " tuple class with extra attributes for " { $link game-world } "s:" }
+{ $list
+{ { $snippet "tick-interval-micros" } " specifies the number of microseconds between consecutive calls to the world's " { $link tick* } " method by the game loop." }
+} ;
+
+HELP: game-world
+{ $class-description "A subclass of " { $link world } " that automatically sets up and manages connections to the " { $vocab-link "game.loop" } " and " { $vocab-link "game.input" } " libraries. It does this by providing methods on " { $link begin-world } ", " { $link end-world } ", and " { $link draw* } ". Subclasses can provide their own world setup and teardown code by adding methods to the " { $link begin-game-world } " and " { $link end-game-world } " generic words." } ;
+
+HELP: begin-game-world
+{ $values { "world" game-world } }
+{ $description "This generic word is called by the " { $link begin-world } " method for " { $link game-world } " subclasses immediately before the game world starts the game loop." } ;
+
+HELP: end-game-world
+{ $values { "world" game-world } }
+{ $description "This generic word is called by the " { $link end-world } " method for " { $link game-world } " subclasses immediately after the game world stops the game loop." } ;
+
+{ game-world begin-game-world end-game-world } related-words
+
+HELP: tick-interval-micros
+{ $values
+    { "world" game-world }
+    { "micros" integer }
+}
+{ $description "Subclasses of " { $link game-world } " can override this class to specify the number of microseconds between consecutive calls to the game world's " { $link tick* } " method by the game loop. Using the " { $link POSTPONE: GAME: } " syntax will define this method for you." } ;
+
+ARTICLE: "game.worlds" "Game worlds"
+"The " { $vocab-link "game.worlds" } " vocabulary provides a " { $link world } " subclass that integrates with " { $vocab-link "game.loop" } " and " { $vocab-link "game.input" } " to quickly provide game infrastructure." 
+{ $subsections
+    game-world
+    game-attributes
+    POSTPONE: GAME:
+}
+"Subclasses of " { $link game-world } " can provide their own setup and teardown code by providing methods for these generic words:"
+{ $subsections
+    begin-game-world
+    end-game-world
+} ;
+
+ABOUT: "game.worlds"
index f614943f0408d2b1f6e4c026656ce954c9af918e..d624a1b41e80f44837885ee0aae137507dbc1a75 100644 (file)
@@ -1,3 +1,4 @@
+! (c)2009 Joe Groff bsd license
 USING: accessors combinators fry game.input game.loop generic kernel math
 parser sequences ui ui.gadgets ui.gadgets.worlds ui.gestures threads
 words ;
@@ -9,25 +10,42 @@ TUPLE: game-world < world
 
 GENERIC: tick-interval-micros ( world -- micros )
 
+GENERIC: begin-game-world ( world -- )
+M: object begin-game-world drop ;
+
+GENERIC: end-game-world ( world -- )
+M: object end-game-world drop ;
+
 M: game-world draw*
     swap >>tick-slice relayout-1 yield ;
 
 M: game-world begin-world
     open-game-input 
+    dup begin-game-world
     dup [ tick-interval-micros ] [ ] bi <game-loop> [ >>game-loop ] keep start-loop
     drop ;
 
 M: game-world end-world
     [ [ stop-loop ] when* f ] change-game-loop
-    close-game-input
-    drop ;
+    end-game-world
+    close-game-input ;
 
 TUPLE: game-attributes < world-attributes
     { tick-interval-micros fixnum read-only } ;
 
+<PRIVATE
+
 : verify-game-attributes ( attributes -- )
-    world-class>> { f world } member?
-    [ "GAME: must be given a custom world-class" throw ] when ;
+    {
+        [
+            world-class>> { f world } member?
+            [ "GAME: must be given a custom world-class" throw ] when
+        ]
+        [
+            tick-interval-micros>> 0 <=
+            [ "GAME: must be given a nonzero tick-interval-micros" throw ] when
+        ]
+    } cleave ;
 
 : define-game-tick-interval-micros ( attributes -- )
     [ world-class>> \ tick-interval-micros create-method ]
@@ -40,11 +58,14 @@ TUPLE: game-attributes < world-attributes
         [ define-game-tick-interval-micros ]
     } cleave ;
 
-: define-game ( word attributes -- )
-    [ [ ] define-main-window ]
-    [ nip define-game-methods ] 2bi ;
+: define-game ( word attributes quot -- )
+    [ define-main-window ]
+    [ drop nip define-game-methods ] 3bi ;
+
+PRIVATE>
 
 SYNTAX: GAME:
     CREATE
     game-attributes parse-main-window-attributes
+    parse-definition
     define-game ;
index 067e9344531b5a6365fd1bb502da3903de65c808..3199cdcffd2a8b32e041c8633c792f5909cbf9a8 100644 (file)
@@ -214,7 +214,7 @@ CONSTANT: bunny-model-url "http://factorcode.org/bun_zipper.ply"
         dup 0 "vocab:gpu/demos/bunny/loading.tiff" load-image allocate-texture-image
         >>texture ;
 
-BEFORE: bunny-world begin-world
+M: bunny-world begin-game-world
     init-gpu
     
     { -0.2 0.13 0.1 } 1.1 0.2 set-wasd-view
@@ -308,4 +308,4 @@ GAME: bunny-game {
         { grab-input? t }
         { pref-dim { 1024 768 } }
         { tick-interval-micros $[ 1,000,000 60 /i ] }
-    }
+    } ;
index 8883609bce38faf5525bea2f470696a307b44e09..a58388fc00bb6b0d4337dd62ab945f3fc085b394 100644 (file)
@@ -69,7 +69,7 @@ CONSTANT: initial-spheres {
     T{ sphere f { 1.0 0.0  0.0 } {  0.0 5.0 0.0 } 0.025 1.0 { 1.0 1.0 0.0 1.0 } }
 }
 
-BEFORE: raytrace-world begin-world
+M: raytrace-world begin-game-world
     init-gpu
     { -2.0 6.25 10.0 } 0.19 0.55 set-wasd-view
     initial-spheres [ clone ] map >>spheres    
@@ -104,4 +104,4 @@ GAME: raytrace-game {
         { grab-input? t }
         { pref-dim { 1024 768 } }
         { tick-interval-micros $[ 1,000,000 60 /i ] }
-    }
+    } ;
diff --git a/extra/method-chains/method-chains-docs.factor b/extra/method-chains/method-chains-docs.factor
new file mode 100644 (file)
index 0000000..3e8e0e9
--- /dev/null
@@ -0,0 +1,22 @@
+! (c)2009 Joe Groff bsd license
+USING: help.markup help.syntax ;
+IN: method-chains
+
+HELP: AFTER:
+{ $syntax "AFTER: class generic
+    implementation ;" }
+{ $description "Defines a method on " { $snippet "generic" } " for " { $snippet "class" } " which executes the new " { $snippet "implementation" } " code after invoking the parent class method on " { $snippet "generic" } "." } ;
+
+HELP: BEFORE:
+{ $syntax "BEFORE: class generic
+    implementation ;" }
+{ $description "Defines a method on " { $snippet "generic" } " for " { $snippet "class" } " which executes the new " { $snippet "implementation" } " code, then invokes the parent class method on " { $snippet "generic" } "." } ;
+
+ARTICLE: "method-chains" "Method chaining syntax"
+"The " { $vocab-link "method-chains" } " vocabulary provides syntax for extending method implementations in class hierarchies." 
+{ $subsections
+    POSTPONE: AFTER:
+    POSTPONE: BEFORE:
+} ;
+
+ABOUT: "method-chains"
diff --git a/extra/method-chains/summary.txt b/extra/method-chains/summary.txt
new file mode 100644 (file)
index 0000000..dc80f82
--- /dev/null
@@ -0,0 +1 @@
+BEFORE: and AFTER: syntax for extending methods in class hierarchies
index adbeb9c441fa2fb7f062ea2d9f390a819fd7084b..370c7634a710d9c12c9e426879cfeecd38d71195 100644 (file)
@@ -6,7 +6,7 @@ math.vectors opengl opengl.capabilities opengl.gl
 opengl.shaders opengl.textures opengl.textures.private
 sequences sequences.product specialized-arrays
 terrain.generation terrain.shaders typed ui ui.gadgets
-ui.gadgets.worlds ui.pixel-formats game.worlds method-chains
+ui.gadgets.worlds ui.pixel-formats game.worlds
 math.matrices.simd noise ui.gestures combinators.short-circuit
 destructors grid-meshes math.vectors.simd ;
 QUALIFIED-WITH: alien.c-types c
@@ -233,7 +233,7 @@ M: terrain-world tick*
 : sky-theta ( world -- theta )
     game-loop>> tick-number>> SKY-SPEED * ;
 
-BEFORE: terrain-world begin-world
+M: terrain-world begin-game-world
     "2.0" { "GL_ARB_vertex_buffer_object" "GL_ARB_shader_objects" }
     require-gl-version-or-extensions
     GL_DEPTH_TEST glEnable
@@ -254,7 +254,7 @@ BEFORE: terrain-world begin-world
     terrain-vertex-size <grid-mesh> >>terrain-mesh
     drop ;
 
-AFTER: terrain-world end-world
+M: terrain-world end-game-world
     {
         [ terrain-mesh>> dispose ]
         [ terrain-program>> delete-gl-program ]
@@ -298,4 +298,4 @@ GAME: terrain-game {
         { grab-input? t }
         { pref-dim { 1024 768 } }
         { tick-interval-micros $[ 1,000,000 60 /i ] }
-    }
+    } ;