Commits

catseye  committed a2f2e81

Use yoob.PlayfieldCanvasView like we should be doing.

  • Participants
  • Parent commits ffaa905

Comments (0)

Files changed (3)

File impl/etcha.js/demo/etcha.html

 <script src="../src/yoob/controller.js"></script>
 <script src="../src/yoob/playfield.js"></script>
 <script src="../src/yoob/cursor.js"></script>
+<script src="../src/yoob/playfield-canvas-view.js"></script>
 <script src="../src/etcha.js"></script>
 <script>
   var c = new EtchaController();

File impl/etcha.js/src/etcha.js

  * requires yoob.Controller
  * requires yoob.Playfield
  * requires yoob.Cursor
+ * requires yoob.PlayfieldCanvasView
  */
 
 /*
-class EtchaPlayfield extends BasicPlayfield<BitElement> {
-    protected BasicCursor<BitElement> turtle;
-    public EtchaPlayfield() {
-        super(BitElement.ZERO);
-        this.turtle = new BasicCursor<BitElement>(this);
-        turtle.setDelta(0, -1);
-        clear();
-    }
-
-    public EtchaPlayfield clone() {
-        EtchaPlayfield c = new EtchaPlayfield();
-        c.copyBackingStoreFrom(this);
-        c.turtle = turtle.clone();
-        c.turtle.setPlayfield(c);
-        return c;
-    }
-
-    public int numCursors() {
-        return 1;
-    }
-
-    public BasicCursor<BitElement> getCursor(int index) {
-        if (index == 0)
-            return turtle;
-        return null;
-    }
-}
-
 class EtchaPlayfieldView extends BasicPlayfieldView {
     public void render(Graphics g, Element e, int x, int y, int w, int h) {
         BitElement be = (BitElement)e;
 
     var p;
     var ip;
+    var view;
     var program;
     var pc;
     var pendown;
     var pencounter;
 
     this.init = function(c) {
+        canvas = c;
         p = new EtchaPlayfield();
         ip = new EtchaTurtle(0, 0, 0, -1);
-        canvas = c;
+        view = new yoob.PlayfieldCanvasView().init(p, canvas)
+            .setCursors([ip])
+            .setCellDimensions(12, 12);
         ctx = canvas.getContext('2d');
         pendown = true;
         pencounter = 0;
     };
 
     this.draw = function() {
-        p.drawCanvas(canvas, undefined, 20, [ip]);
+        view.draw();
     };
 
     this.step = function() {
         }
 
         pc++;
-        if (pc >= program.length()) {
+        if (pc >= program.length) {
             halted = true;
         }
 
 
     this.load = function(text) {
         p.clear();
-        p.load(0, 0, text);
+        program = text;
         ip.x = 0;
         ip.y = 0;
         ip.dx = 0;

File impl/etcha.js/src/yoob/playfield-canvas-view.js

+/*
+ * 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 = {};
+
+/*
+ * 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?
+ */
+yoob.PlayfieldCanvasView = function() {
+    this.pf = undefined;
+    this.canvas = undefined;
+
+    this.init = function(pf, canvas) {
+        this.pf = pf;
+        this.canvas = canvas;
+        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 visible 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 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);
+    };
+
+    this.draw = function() {
+        this.drawCanvas(
+          this.canvas, this.cellWidth, this.cellHeight, this.cursors
+        );
+    };
+
+};