Home > other >  Drawing image from external class in Processing
Drawing image from external class in Processing

Time:01-21

I'm trying to create an external Archer class for a tower defense game with its own draw function, but I'm having trouble accessing the image function from within the Archer class. I've got a workaround working as shown below but I feel like there must be a better way to do it.

public class Sketch extends PApplet {
  static PImage archerImg;
  static Sketch s;

  public void setup() {
    s = this;
    archerImg = loadImage("img/Archerv2.png");
  }
}

class Archer {
  public Archer(int x, int y) {
    this.x = x;
    this.y = y;
    image = Sketch.archerImg;
  }

  public void draw() {
    Sketch.s.image(image, x, y);
  }
}

Can anyone recommend a more elegant way to do this?

CodePudding user response:

One option would be to use preload() to load the image; it is run once before the rest of your code. The following will run in p5.js web editor using Processing IDE. The img folder with the archer image inside needs to be in your sketch folder.

let archerImg;

function preload(){
  archerImg = loadImage('img/Archerv2.png');
}

function setup() {
 createCanvas(500,500);
 background(209);
 archer = new Archer(50,60);
}

function draw() {
 archer.display();
}

class Archer {
  constructor(x, y) {
    this.x = x;
    this.y = y;    
  }

  display() {    
    image(archerImg, this.x, this.y );
  }
}

CodePudding user response:

As far as I understand you're trying to get a reference to the sketch so you can simply use image() when rendering an instance of Archer from the scope of the class itself.

One option could to take advantage of the fact that g is PApplet's global PGraphics buffer which provides the rendering functions (such image()):

public class Sketch extends PApplet {
  
  PImage archerImg;
  
  Archer archer;

  public void setup() {
    size(300, 300);
    archerImg = loadImage("img/Archerv2.png");
    archer = new Archer(150, 150, archerImg);
  }

  public void draw(){
    background(0);
    archer.draw(g);
  }

  public void mouseDragged(){
    archer.x = mouseX;
    archer.y = mouseY;
  }

}

class Archer {

  int x, y;
  PImage image;

  public Archer(int x, int y, PImage image) {
    this.x = x;
    this.y = y;
    this.image = image;
  }

  public void draw(PGraphics g) {
    g.image(image, x, y);
  }
}

The advantage is that if you chose to have multiple buffers(e.g. a background layer, sprites layer, a HUD layer, etc.) you can explicitly tell the Archer instance into which layer it should render to.

Alternatively you can pass the sketch directly in the constructor which you can reuse later to call image:

public class Sketch extends PApplet {
  
  PImage archerImg;
  
  Archer archer;

  public void setup() {
    size(300, 300);
    archerImg = loadImage("img/Archerv2.png");
    archer = new Archer(this, 150, 150, archerImg);
  }

  public void draw(){
    background(0);
    archer.draw();
  }

  public void mouseDragged(){
    archer.x = mouseX;
    archer.y = mouseY;
  }

}

class Archer {

  int x, y;
  PImage image;
  PApplet parent;

  public Archer(PApplet parent, int x, int y, PImage image) {
    this.x = x;
    this.y = y;
    this.image = image;
    this.parent = parent;
  }

  public void draw() {
    parent.image(image, x, y);
  }
}

If you can to pass the Sketch directly you can as well, though this would mean even tighter coupling:

public class Sketch extends PApplet {
  
  public PImage archerImg;
  
  Archer archer;

  public void setup() {
    size(300, 300);
    archerImg = loadImage("img/Archerv2.png");
    archer = new Archer(this, 150, 150);
  }

  public void draw(){
    background(0);
    archer.draw();
  }

  public void mouseDragged(){
    archer.x = mouseX;
    archer.y = mouseY;
  }

}

class Archer {

  int x, y;
  Sketch parent;

  public Archer(Sketch parent, int x, int y) {
    this.x = x;
    this.y = y;
    this.parent = parent;
  }

  public void draw() {
    parent.image(parent.archerImg, x, y);
  }
}

Without more context on the design of your game it's tricky to get an exact answer, however you have multiple options above. Personally, even though it's slightly more verbose I'd go with the PGraphics option since less coupled than the other options.

  •  Tags:  
  • Related