Hoppy Beaver

edited April 2016 in Share Your Work

Hi folks! Just converted & refined "Hoppy Beaver" sketch from KhanAcademy.org's Processing.JS version, which uses JS syntax, to both Processing's Java/JS Modes! :bz

You can check that out online in its original form @ https://www.KhanAcademy.org/computing/computer-programming/programming-games-visualizations/side-scroller/a/scoring-and-winning

And also in JS Mode @ http://Studio.ProcessingTogether.com/sp/pad/export/ro.9bTfM49wCIJza

Hope y'all like it too: :-bd

/**
 * Hoppy Beaver (v1.0)
 * Author: Pamela (2014/Feb)
 * Processing: GoToLoop (2015/Jan)
 *
 * Forum.Processing.org/two/discussion/8997/hoppy-beaver
 *
 * www.KhanAcademy.org/computing/computer-programming/
 * programming-games-visualizations/side-scroller/a/scoring-and-winning
 *
 * Studio.ProcessingTogether.com/sp/pad/export/ro.9bTfM49wCIJza
 */

/* @pjs pauseOnBlur = true;
 preload = "creatures/Hopper-Happy.png,
 creatures/Hopper-Jumping.png,
 cute/GrassBlock.png";
 */

/* @pjs pauseOnBlur = true;
 preload = "/static/uploaded_resources/p.6273/Hopper-Happy.png,
 /static/uploaded_resources/p.6273/Hopper-Jumping.png,
 /static/uploaded_resources/p.6273/GrassBlock.png";
 */

static final String KHAN = "https://" + "www.KaSandbox.org/third_party/"
+ "javascript-khansrc/live-editor/build/images/";

static final String SKETCHPAD = "/static/uploaded_resources/p.6273/";

static final boolean REMOTE = true;
//static final boolean REMOTE = false;

static final color BG = #E0FFFF, SOIL = #80502A;
static final short SMOOTH = 4, FPS = 60, SCROLL = 2;
static final short STICKS = 200, TURFS = 30;

Stick[] sticks = new Stick[STICKS];
Grass[] turfs  = new Grass[TURFS];

Beaver beaver;
Score score;

void setup() {
  size(500, 400, JAVA2D);
  smooth(SMOOTH);
  frameRate(FPS);
  noStroke();

  textSize(Score.SIZE);
  textAlign(CENTER, CENTER);

  rectMode(CORNER);
  imageMode(CORNER);

  //String path = REMOTE? SKETCHPAD : "";
  String path = REMOTE? KHAN : "";

  //(Beaver.falling = loadImage(path + "Hopper-Happy.png"))
  (Beaver.falling = loadImage(path + "creatures/Hopper-Happy.png"))
    .resize(Beaver.SIZE, Beaver.SIZE);
  //(Beaver.jumping = loadImage(path + "Hopper-Jumping.png"))
  (Beaver.jumping = loadImage(path + "creatures/Hopper-Jumping.png"))
    .resize(Beaver.SIZE, Beaver.SIZE);
  //(Grass.lawn = loadImage(path + "GrassBlock.png"))
  (Grass.lawn = loadImage(path + "cute/GrassBlock.png"))
    .resize(Grass.SIZE, Grass.SIZE);

  beaver = new Beaver(width>>1, height - Beaver.GROUND);
  Stick.counter = score = new Score(80, 20);

  for (int y = round (height*.85), i = 0; i != TURFS; ++i)
    turfs[i] = new Grass(i*Grass.GAP, y);

  for (int y = round (height*.65), i = 0; i != STICKS; ++i)
    sticks[i] = new Stick(i*Stick.GAP + width, (int) random(20, y));
}

void draw() {
  background(BG);

  fill(SOIL);
  rect(0, height*.9, width, height*.1);

  for (Grass t : turfs)  t.script();

  fill(Stick.INK);
  for (Stick s : sticks)
    if (beaver.gotStick(s))  s.x ^= ~++score.collected | ++score.dead;
    else s.script();

  keyCode = keyPressed | mousePressed? beaver.jump() : beaver.fall();
  beaver.display();

  fill(Score.INK);
  score.display();

  if (score.dead == STICKS) {
    boolean win = score.collected/(float)STICKS >= Score.PERCENT;
    fill(win? #008000 : #FF0000);
    text(win? "YOU WIN!!!" : "Collect More Next Time..."
      , width>>1, height>>1);
  }
}

static abstract class BeaverStatic {
  static final int SIZE = 40, GROUND = SIZE+10, SPD = 5;
  static PImage falling, jumping;
}

final class Beaver extends BeaverStatic {
  boolean isJumping;
  int x, y;

  Beaver(int xx, int yy) {
    x = xx;
    y = yy;
  }

  void display() {
    image(isJumping? jumping : falling, x, y);
  }

  int fall() {
    isJumping = false;
    return y = min(y + SPD, height - GROUND);
  }

  int jump() {
    isJumping = true;
    return y = max(y - SPD, 0);
  }

  boolean gotStick(Stick s) {
    return x+SIZE > s.x & x < s.x+Stick.W & y+SIZE > s.y & y < s.y+Stick.H;
  }
}

static abstract class GrassStatic {
  static final int SIZE = 20, GAP = 20;
  static PImage lawn;
}

final class Grass extends GrassStatic {
  short x, y;

  Grass(int xx, int yy) {
    x = (short) xx;
    y = (short) yy;
  }

  void script() {
    update();
    display();
  }

  void update() {
    if ((x -= SCROLL) < -SIZE)  x = (short) width;
  }

  void display() {
    image(lawn, x, y);
  }
}

static abstract class StickStatic {
  static final color INK = #5A4A00;
  static final short W = 10, H = 50, GAP = 40;
  static Score counter;
}

final class Stick extends StickStatic {
  short x, y;

  Stick(int xx, int yy) {
    x = (short) xx;
    y = (short) yy;
  }

  void script() {
    if (x < -W)  return;
    update();
    if (x < -W)  ++counter.dead;
    else if (x < width)  display();
  }

  void update() {
    x -= SCROLL;
  }

  void display() {
    rect(x, y, W, H);
  }
}

final class Score {
  static final color INK  = #0000FF;
  static final short SIZE = 18;
  static final float PERCENT = .9;

  short x, y;
  short collected = 0, dead = 0;

  Score(int xx, int yy) {
    x = (short) xx;
    y = (short) yy;
  }

  void display() {
    text("Score: " + nf(collected, 3) + "/" + STICKS, x, y);
  }
}

Comments

  • edited August 2016

    This time, Java Mode converted to P5*JS framework, which relies on JS syntax just like Khan's PJS version:

    /**
     * Hoppy Beaver (v1.04)
     * Author: Pamela (2014/Feb)
     * Processing: GoToLoop (2015/Jan)
     *
     * forum.Processing.org/two/discussion/8997/hoppy-beaver#Item_1
     *
     * www.KhanAcademy.org/computing/computer-programming/
     * programming-games-visualizations/side-scroller/p/project-hoppy-beaver-extreme
     *
     * p5js.ProcessingTogether.com/sp/pad/export/ro.Cp2G$x5ApiPI5r
     * studio.ProcessingTogether.com/sp/pad/export/ro.9bTfM49wCIJza
     */
    
    const KHAN = 'https:/' + '/www.KaSandbox.org/third_party/'
      + 'javascript-khansrc/live-editor/build/images/';
    
    const REMOTE = true;
    //const REMOTE = false;
    
    const PATH = REMOTE && KHAN || '';
    
    const BG   = Object.freeze([0xE0, 0xFF, 0xFF]);
    const SOIL = Object.freeze([0x80, 0x50, 0x2A]);
    
    const WIN  = Object.freeze([0, 0x80, 0]);
    const LOSE = Object.freeze([0xFF, 0, 0]);
    
    const STICKS = 200, TURFS = 30, FPS = 60, SCROLL = 2;
    const sticks = Array(STICKS), turfs = Array(TURFS);
    
    var beaver, score;
    
    function preload() {
      Beaver.falling = loadImage(PATH + 'creatures/Hopper-Happy.png');
      Beaver.jumping = loadImage(PATH + 'creatures/Hopper-Jumping.png');
      Grass.lawn = loadImage(PATH + 'cute/GrassBlock.png');
    }
    
    function setup() {
      createCanvas(500, 400);
      frameRate(FPS).smooth().rectMode(CORNER).imageMode(CORNER);
      textSize(Score.SIZE).textAlign(CENTER, CENTER);
    
      Beaver.falling.resize(Beaver.SIZE, Beaver.SIZE);
      Beaver.jumping.resize(Beaver.SIZE, Beaver.SIZE);
      Grass.lawn.resize(Grass.SIZE, Grass.SIZE);
    
      beaver = new Beaver(width>>1, height - Beaver.GROUND);
      Stick.counter = score = new Score(80, 20);
    
      for (var y = round(height*.85), i = 0; i != TURFS; ++i)
        turfs[i] = new Grass(i*Grass.GAP, y);
      Object.freeze(turfs);
    
      for (var y = round(height*.65), i = 0; i != STICKS; ++i)
        sticks[i] = new Stick(i*Stick.GAP + width, round(random(20, y)));
      Object.freeze(sticks);
    }
    
    function draw() {
      background(BG).fill(SOIL).rect(0, height*.9, width, height*.1);
      for (var i = 0; i != TURFS; turfs[i++].script());
    
      fill(Stick.INK);
      for (var s, i = 0; i != STICKS; beaver.gotStick(s = sticks[i++])
        ? (s.x = -Stick.W, ++score.collected, ++score.dead) : s.script());
    
      keyIsPressed|mouseIsPressed && beaver.jump() || beaver.fall();
      beaver.display();
    
      fill(Score.INK), score.display();
      if (score.dead == STICKS) {
        const win = score.collected/STICKS >= Score.PERCENT;
        fill(win? WIN : LOSE);
        text(win? 'YOU WIN!!!' : 'Collect More Next Time...', width>>1, height>>1);
      }
    }
    
    /** Beaver Class **/
    
    Beaver.SIZE = 40, Beaver.GROUND = Beaver.SIZE+10, Beaver.SPD = 5;
    Beaver.falling = Beaver.jumping = null;
    
    function Beaver(x, y) {
      this.x = x, this.y = y, this.isJumping = false;
    }
    
    Beaver.prototype.display = function() {
      image(this.isJumping && Beaver.jumping || Beaver.falling, this.x, this.y);
    };
    
    Beaver.prototype.fall = function() {
      this.y = min(this.y + Beaver.SPD, height - Beaver.GROUND);
      return this.isJumping = false;
    };
    
    Beaver.prototype.jump = function() {
      this.y = max(this.y - Beaver.SPD, 0);
      return this.isJumping = true;
    };
    
    Beaver.prototype.gotStick = function(s) {
      return this.x+Beaver.SIZE > s.x & this.x < s.x+Stick.W &
             this.y+Beaver.SIZE > s.y & this.y < s.y+Stick.H;
    };
    
    /** Grass Class **/
    
    Grass.SIZE = 20, Grass.GAP = 20;
    Grass.lawn = null;
    
    function Grass(x, y) {
      this.x = x, this.y = y;
    }
    
    Grass.prototype.script = function() {
      this.update(), this.display();
    };
    
    Grass.prototype.update = function() {
      (this.x -= SCROLL) < -Grass.SIZE && (this.x = width);
    };
    
    Grass.prototype.display = function() {
      image(Grass.lawn, this.x, this.y);
    };
    
    /** Stick Class **/
    
    Stick.INK = Object.freeze([0x5A, 0x4A, 0]);
    Stick.W = 10, Stick.H = 50, Stick.GAP = 40;
    Stick.counter = null;
    
    function Stick(x, y) {
      this.x = x, this.y = y;
    }
    
    Stick.prototype.script = function() {
      if (this.x <= -Stick.W)  return;
      this.update() <= -Stick.W?
        ++Stick.counter.dead : this.x < width && this.display();
    };
    
    Stick.prototype.update = function() {
      return this.x -= SCROLL;
    };
    
    Stick.prototype.display = function() {
      rect(this.x, this.y, Stick.W, Stick.H);
    };
    
    /** Score Class **/
    
    Score.INK  = Object.freeze([0, 0, 0xFF]);
    Score.SIZE = 18, Score.PERCENT = .9;
    
    function Score(x, y) {
      this.x = x, this.y = y, this.collected = this.dead = 0;
    }
    
    Score.prototype.display = function() {
      text('Score: ' + nf(this.collected, 3) + '/' + STICKS, this.x, this.y);
    };
    
  • edited August 2016

    Now a modern version using newest ES6 JS's keyword class: :bz
    https://developer.Mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes

    It's now also hosted to be played online just like the previous Pjs version: \m/
    http://p5js.SketchPad.cc/sp/pad/view/ro.GrwKUsycNrY/latest
    http://p5js.ProcessingTogether.com/sp/pad/export/ro.Cp2G$x5ApiPI5r

    /**
     * Hoppy Beaver (v2.04)
     * Author: Pamela (2014/Feb)
     * Processing: GoToLoop (2016/Apr/08)
     *
     * forum.Processing.org/two/discussion/8997/hoppy-beaver#Item_2
     *
     * www.KhanAcademy.org/computing/computer-programming/
     * programming-games-visualizations/side-scroller/p/project-hoppy-beaver-extreme
     *
     * p5js.ProcessingTogether.com/sp/pad/export/ro.Cp2G$x5ApiPI5r
     * studio.ProcessingTogether.com/sp/pad/export/ro.9bTfM49wCIJza
     */
    
    "use strict"
    
    const KHAN = 'http:/' + '/www.KaSandbox.org/third_party/'
      + 'javascript-khansrc/live-editor/build/images/'
    
    const REMOTE = true
    //const REMOTE = false
    
    const PATH = REMOTE && KHAN || ''
    
    const STICKS = 200, TURFS = 30, FPS = 60, WEIGHT = 2.5
    const sticks = Array(STICKS), turfs = Array(TURFS)
    
    let beaver, score, bg, soil, win, lose
    
    function preload() {
      Beaver.falling = loadImage(PATH + 'creatures/Hopper-Happy.png')
      Beaver.jumping = loadImage(PATH + 'creatures/Hopper-Jumping.png')
      Grass.lawn = loadImage(PATH + 'cute/GrassBlock.png')
    }
    
    function setup() {
      createCanvas(500, 400)
      frameRate(FPS).strokeWeight(WEIGHT).rectMode(CORNER).imageMode(CORNER)
      textSize(Score.SIZE).textAlign(CENTER, CENTER)
    
      Beaver.falling.resize(Beaver.SIZE, Beaver.SIZE)
      Beaver.jumping.resize(Beaver.SIZE, Beaver.SIZE)
      Grass.lawn.resize(Grass.SIZE, Grass.SIZE)
    
      beaver = new Beaver(width>>1, height - Beaver.GROUND)
      Stick.counter = score = new Score(80, 20)
    
      for (let y = round(height*.85), i = 0; i !== TURFS; ++i)
        turfs[i] = new Grass(i*Grass.GAP, y)
      Object.freeze(turfs)
    
      for (let y = round(height*.65), i = 0; i !== STICKS; ++i)
        sticks[i] = new Stick(i*Stick.GAP + width, round(random(20, y)))
      Object.freeze(sticks)
    
      bg = Object.freeze(color(0xE0, 0xFF, 0xFF))
      soil = Object.freeze(color(0x80, 0x50, 0x2A))
    
      win = Object.freeze(color('green'))
      lose = Object.freeze(color('red'))
    
      Stick.ink = Object.freeze(color(0x5A, 0x4A, 0))
      Score.ink = Object.freeze(color('blue'))
    
      Object.freeze(Object.freeze(Beaver).prototype)
      Object.freeze(Object.freeze(Grass).prototype)
      Object.freeze(Object.freeze(Stick).prototype)
      Object.freeze(Object.freeze(Score).prototype)
    }
    
    function draw() {
      background(bg).stroke(0).fill(soil).rect(0, height*.9, width, height*.1)
      for (let i = 0; i !== TURFS; turfs[i++].script());
    
      fill(Stick.ink)
      for (let s, i = 0; i !== STICKS; beaver.gotStick(s = sticks[i++])
        ? (s.x = -Stick.W, ++score.collected, ++score.dead) : s.script());
    
      keyIsPressed|mouseIsPressed && beaver.jump() || beaver.fall()
      beaver.display()
    
      noStroke().fill(Score.ink), score.display(STICKS)
      if (score.dead === STICKS) {
        const won = score.collected/STICKS >= Score.PERCENT
        fill(won && win || lose)
        text(won && 'YOU WIN!!!' || 'Collect More Next Time...', width>>1, height>>1)
      }
    }
    
    class Beaver {
      constructor(x, y) { this.x = x, this.y = y, this.isJumping = false }
    
      static get SIZE() { return 40 }
      static get GROUND() { return 50 } // Beaver.SIZE + 10
      static get SPD() { return 5 }
    
      display() {
        image(this.isJumping && Beaver.jumping || Beaver.falling, this.x, this.y)
      }
    
      fall() {
        this.y = min(this.y + Beaver.SPD, height - Beaver.GROUND)
        return this.isJumping = false
      }
    
      jump() {
        this.y = max(this.y - Beaver.SPD, 0)
        return this.isJumping = true
      }
    
      gotStick(s) {
        return this.x+Beaver.SIZE > s.x & this.x < s.x+Stick.W &
               this.y+Beaver.SIZE > s.y & this.y < s.y+Stick.H
      }
    }
    
    class Grass {
      constructor(x, y) { this.x = x, this.y = y }
    
      static get SIZE() { return 20 }
      static get GAP() { return 20 }
      static get SCROLL() { return 2 }
    
      script() { this.update(), this.display() }
      update() { (this.x -= Grass.SCROLL) < -Grass.SIZE && (this.x = width) }
      display() { image(Grass.lawn, this.x, this.y) }
    }
    
    class Stick {
      constructor(x, y) { this.x = x, this.y = y }
    
      static get W() { return 10 }
      static get H() { return 50 }
      static get GAP() { return 40 }
      static get SCROLL() { return 2 }
    
      script() {
        if (this.x > -Stick.W)  this.update() <= -Stick.W?
          ++Stick.counter.dead : this.x < width && this.display()
      }
    
      update() { return this.x -= Stick.SCROLL }
      display() { rect(this.x, this.y, Stick.W, Stick.H) }
    }
    
    class Score {
      constructor(x, y) { this.x = x, this.y = y, this.collected = this.dead = 0 }
    
      static get SIZE() { return 18 }
      static get PERCENT() { return .9 }
    
      display(total) {
        text('Score: ' + nf(this.collected, 3) + '/' + total, this.x, this.y)
      }
    }
    
  • Wow !!! =D>

Sign In or Register to comment.