Commits

Cat's Eye Technologies committed cf0dc47

Update to latest yoob.js; in paritcular, use PlayfieldCanvasView.

Comments (0)

Files changed (6)

 </body>
 <script src="../src/yoob/controller.js"></script>
 <script src="../src/yoob/playfield.js"></script>
+<script src="../src/yoob/playfield-canvas-view.js"></script>
 <script src="../src/yoob/cursor.js"></script>
 <script src="../src/gemooy.js"></script>
 <script>
   var c = new GemooyController();
-  c.init(document.getElementById('canvas'));
+  var v = new yoob.PlayfieldCanvasView;
+  v.init(null, document.getElementById('canvas'));
+  v.setCellDimensions(undefined, 20);
+  c.init(v);
   c.connect({
     'start': 'start',
     'stop': 'stop',
 
 function GemooyController() {
     var intervalId;
-    var canvas;
-    var ctx;
 
     var p;
     var ip;
     var dp;
 
-    this.init = function(c) {
+    this.init = function(view) {
         p = new GemooyPlayfield();
 
         ip = new yoob.Cursor(0, 0, 1, 1);
             ctx.fillStyle = "#50ff80";
             ctx.fillRect(x, y, cellWidth, cellHeight);
         };
-        canvas = c;
-        ctx = canvas.getContext('2d');
-    };
-
-    this.draw = function() {
-        p.drawCanvas(canvas, undefined, 20, [ip, dp]);
+        view.pf = p;
+        this.view = view.setCursors([ip, dp]);
     };
 
     this.step = function() {
         }
 
         ip.advance();
-        this.draw();
+        this.view.draw();
     };
 
     this.load = function(text) {
         });
         ip.dx = 1;
         ip.dy = 1;
-        this.draw();
+        this.view.draw();
     };
 };
 GemooyController.prototype = new yoob.Controller();

src/yoob/controller.js

 /*
- * This file is part of yoob.js version 0.3-PRE
+ * This file is part of yoob.js version 0.3
+ * Available from https://github.com/catseye/yoob.js/
  * This file is in the public domain.  See http://unlicense.org/ for details.
  */
 if (window.yoob === undefined) yoob = {};

src/yoob/cursor.js

 /*
- * This file is part of yoob.js version 0.1
+ * This file is part of yoob.js version 0.3
+ * Available from https://github.com/catseye/yoob.js/
  * This file is in the public domain.  See http://unlicense.org/ for details.
  */
 if (window.yoob === undefined) yoob = {};

src/yoob/playfield-canvas-view.js

+/*
+ * This file is part of yoob.js version 0.5
+ * Available from https://github.com/catseye/yoob.js/
+ * This file is in the public domain.  See http://unlicense.org/ for details.
+ */
+if (window.yoob === undefined) yoob = {};
+
+/*
+ * A view (in the MVC sense) for depicting a yoob.Playfield (-compatible)
+ * object on an HTML5 <canvas> element (or compatible object).
+ *
+ * TODO: don't necesarily resize canvas each time?
+ * TODO: option to stretch content rendering to fill a fixed-size canvas
+ */
+yoob.PlayfieldCanvasView = function() {
+    this.pf = undefined;
+    this.canvas = undefined;
+
+    this.init = function(pf, canvas) {
+        this.pf = pf;
+        this.canvas = canvas;
+        this.cursors = [];
+        this.cellWidth = 8;
+        this.cellHeight = 8;
+        return this;
+    };
+    
+    /* Chain setters */
+    this.setCursors = function(cursors) {
+        this.cursors = cursors;
+        return this;
+    };
+    this.setCellDimensions = function(cellWidth, cellHeight) {
+        this.cellWidth = cellWidth;
+        this.cellHeight = cellHeight;
+        return this;
+    };
+
+    /*
+     * Override these if you want to draw some portion of the
+     * playfield which is not the whole playfield.
+     * (Not yet implemented)
+     */
+    this.getLowerX = function() {
+        return this.pf.getMinX();
+    };
+    this.getUpperX = function() {
+        return this.pf.getMaxX();
+    };
+    this.getLowerY = function() {
+        return this.pf.getMinY();
+    };
+    this.getUpperY = function() {
+        return this.pf.getMaxY();
+    };
+
+    /*
+     * Returns the number of occupied cells in the x direction.
+     */
+    this.getExtentX = function() {
+        if (this.getLowerX() === undefined || this.getUpperX() === undefined) {
+            return 0;
+        } else {
+            return this.getUpperX() - this.getLowerX() + 1;
+        }
+    };
+
+    /*
+     * Returns the number of occupied cells in the y direction.
+     */
+    this.getExtentY = function() {
+        if (this.getLowerY() === undefined || this.getUpperY() === undefined) {
+            return 0;
+        } else {
+            return this.getUpperY() - this.getLowerY() + 1;
+        }
+    };
+
+    /*
+     * Draws cells of the Playfield in a drawing context.
+     * cellWidth and cellHeight are canvas units of measure.
+     *
+     * The default implementation tries to call a .draw() method on the cell's
+     * value, if one exists, and just renders it as text, in black, if not.
+     *
+     * Override if you wish to draw elements in some other way.
+     */
+    this.drawCell = function(ctx, value, playfieldX, playfieldY,
+                             canvasX, canvasY, cellWidth, cellHeight) {
+        if (value.draw !== undefined) {
+            value.draw(ctx, playfieldX, playfieldY, canvasX, canvasY,
+                       cellWidth, cellHeight);
+        } else {
+            ctx.fillStyle = "black";
+            ctx.fillText(value.toString(), canvasX, canvasY);
+        }
+    };
+
+    /*
+     * Draws the Playfield in a drawing context.
+     * cellWidth and cellHeight are canvas units of measure for each cell.
+     * offsetX and offsetY are canvas units of measure for the top-left
+     *   of the entire playfield.
+     */
+    this.drawContext = function(ctx, offsetX, offsetY, cellWidth, cellHeight) {
+        var self = this;
+        this.pf.foreach(function (x, y, value) {
+            self.drawCell(ctx, value, x, y,
+                          offsetX + x * cellWidth, offsetY + y * cellHeight,
+                          cellWidth, cellHeight);
+        });
+    };
+
+    /*
+     * Draws the Playfield, and a set of Cursors, on a canvas element.
+     * Resizes the canvas to the needed dimensions.
+     * cellWidth and cellHeight are canvas units of measure for each cell.
+     * Note that this is a holdover from when this method was on Playfield
+     * itself; typically you'd just call draw() instead.
+     */
+    this.drawCanvas = function(canvas, cellWidth, cellHeight, cursors) {
+        var ctx = canvas.getContext('2d');
+      
+        var width = this.getExtentX();
+        var height = this.getExtentY();
+
+        if (cellWidth === undefined) {
+            ctx.textBaseline = "top";
+            ctx.font = cellHeight + "px monospace";
+            cellWidth = ctx.measureText("@").width;
+        }
+
+        canvas.width = width * cellWidth;
+        canvas.height = height * cellHeight;
+
+        ctx.clearRect(0, 0, canvas.width, canvas.height);
+
+        ctx.textBaseline = "top";
+        ctx.font = cellHeight + "px monospace";
+
+        var offsetX = this.pf.getMinX() * cellWidth * -1;
+        var offsetY = this.pf.getMinY() * cellHeight * -1;
+
+        if (this.fixedPosition) {
+            offsetX = 0;
+            offsetY = 0;
+        }
+
+        for (var i = 0; i < cursors.length; i++) {
+            cursors[i].drawContext(
+              ctx,
+              offsetX + cursors[i].x * cellWidth,
+              offsetY + cursors[i].y * cellHeight,
+              cellWidth, cellHeight
+            );
+        }
+
+        this.drawContext(ctx, offsetX, offsetY, cellWidth, cellHeight);
+    };
+
+    /*
+     * Render the playfield on the canvas.
+     */
+    this.draw = function() {
+        this.drawCanvas(
+          this.canvas, this.cellWidth, this.cellHeight, this.cursors
+        );
+    };
+
+};

src/yoob/playfield.js

 /*
- * This file is part of yoob.js version 0.2
+ * This file is part of yoob.js version 0.4
+ * Available from https://github.com/catseye/yoob.js/
  * This file is in the public domain.  See http://unlicense.org/ for details.
  */
 if (window.yoob === undefined) yoob = {};
      */
     this.setDefault = function(v) {
         this._default = v;
+        return this;
     };
 
     /*
     };
 
     /*
+     * Scroll a rectangular subrectangle of this Playfield, up.
+     * TODO: support other directions.
+     */
+    this.scrollRectangleY = function(dy, minX, minY, maxX, maxY) {
+        if (dy < 1) {
+            for (var y = minY; y <= (maxY + dy); y++) {
+                for (var x = minX; x <= maxX; x++) {
+                    this.put(x, y, this.get(x, y - dy));
+                }
+            }
+        } else { alert("scrollRectangleY(" + dy + ") notImplemented"); }
+    };
+
+    this.clearRectangle = function(minX, minY, maxX, maxY) {
+        // Could also do this with a foreach that checks
+        // each position.  Would be faster on sparser playfields.
+        for (var y = minY; y <= maxY; y++) {
+            for (var x = minX; x <= maxX; x++) {
+                this.put(x, y, undefined);
+            }
+        }
+    };
+
+    /*
      * Load a string into this Playfield.
      * The string may be multiline, with newline (ASCII 10)
      * characters delimiting lines.  ASCII 13 is ignored.
     };
 
     /*
-     * Draws elements of the Playfield in a drawing context.
-     * x and y are canvas coordinates, and width and height
-     * are canvas units of measure.
-     * The default implementation just renders them as text,
-     * in black.
-     * Override if you wish to draw them differently.
+     * Accessors for the minimum (resp. maximum) x (resp. y) values of
+     * occupied (non-default-valued) cells in this Playfield.  If there are
+     * no cells in this Playfield, these will refturn undefined.  Note that
+     * these are not guaranteed to be tight bounds; if values in cells
+     * are deleted, these bounds may still be considered to be outside them.
      */
-    this.drawElement = function(ctx, x, y, cellWidth, cellHeight, elem) {
-        ctx.fillStyle = "black";
-        ctx.fillText(elem.toString(), x, y);
+    this.getMinX = function() {
+        return this.minX;
+    };
+    this.getMaxX = function() {
+        return this.maxX;
+    };
+    this.getMinY = function() {
+        return this.minY;
+    };
+    this.getMaxY = function() {
+        return this.maxY;
     };
 
     /*
-     * Draws the Playfield in a drawing context.
-     * cellWidth and cellHeight are canvas units of measure for each cell.
-     * offsetX and offsetY are canvas units of measure for the playfield.
+     * Returns the number of occupied cells in the x direction.
      */
-    this.drawContext = function(ctx, offsetX, offsetY, cellWidth, cellHeight) {
-        var me = this;
-        this.foreach(function (x, y, elem) {
-            me.drawElement(ctx, offsetX + x * cellWidth, offsetY + y * cellHeight,
-                           cellWidth, cellHeight, elem);
-        });
-    };
-
-    this.getMinX = function() { return this.minX; }
-    this.getMaxX = function() { return this.maxX; }
-    this.getMinY = function() { return this.minY; }
-    this.getMaxY = function() { return this.maxY; }
-
     this.getExtentX = function() {
         if (this.maxX === undefined || this.minX === undefined) {
             return 0;
         }
     };
 
+    /*
+     * Returns the number of occupied cells in the y direction.
+     */
     this.getExtentY = function() {
         if (this.maxY === undefined || this.minY === undefined) {
             return 0;
             return this.maxY - this.minY + 1;
         }
     };
-
-    /*
-     * Draws the Playfield, and a set of Cursors, on a canvas element.
-     * Resizes the canvas to the needed dimensions.
-     * cellWidth and cellHeight are canvas units of measure for each cell.
-     */
-    this.drawCanvas = function(canvas, cellWidth, cellHeight, cursors) {
-        var ctx = canvas.getContext('2d');
-      
-        var width = this.getExtentX();
-        var height = this.getExtentY();
-
-        if (cellWidth === undefined) {
-            ctx.textBaseline = "top";
-            ctx.font = cellHeight + "px monospace";
-            cellWidth = ctx.measureText("@").width;
-        }
-
-        canvas.width = width * cellWidth;
-        canvas.height = height * cellHeight;
-
-        ctx.clearRect(0, 0, canvas.width, canvas.height);
-
-        ctx.textBaseline = "top";
-        ctx.font = cellHeight + "px monospace";
-
-        var offsetX = this.minX * cellWidth * -1;
-        var offsetY = this.minY * cellHeight * -1;
-
-        for (var i = 0; i < cursors.length; i++) {
-            cursors[i].drawContext(
-              ctx,
-              offsetX + cursors[i].x * cellWidth,
-              offsetY + cursors[i].y * cellHeight,
-              cellWidth, cellHeight
-            );
-        }
-
-        this.drawContext(ctx, offsetX, offsetY, cellWidth, cellHeight);
-    };
-
 };