Search code examples
javaprocessing

Where should I insert the sprites of one single character in my sketch on Processing 3.5.4?


I need to build up a simple game for university purposes and I have downloaded some sprites in png of one single game character, however I'm not sufficiently familiarised with where I should combine all the sprites to make the character move. Below there is a screenshot of my basic code, which places a background on the screen. I just need a bit of guidance towards the structure of the code. Where the sprites should be placed?

screenshot


Solution

  • If your game character is already nicely cutout and with a transparent background you should be able to load it the same way you load the background. In terms of the file location it should be within the sketch folder or within a folder named data within your sketch folder:

    • PImage sprite = loadImage("yourSpriteHere.png"); would load the one character image
    • image(sprite, 0, 0); would render it at the top left corner.
    • you can define and use float x,y variables it's position which you can update if a key is pressed

    Let's assume you have a sketch that contains myAwesomeCharacter.png, a basic test sketch would look like this:

    // how many pixels per frame the character moves
    float charSpeed = 1.5;
    // current character position
    float charX, charY;
    // character image
    PImage charImage;
    
    void setup(){
      size(300, 300);
      // load image
      charImage = loadImage("myAwesomeCharacter.png");
    }
    
    void draw(){
      // update keys
      if(keyPressed){
        if(keyCode == UP && charY > 0){
          charY -= charSpeed;
        }
        if(keyCode == DOWN && charY < height){
          charY += charSpeed;
        }
        if(keyCode == LEFT && charX > 0){
          charX -= charSpeed;
        }
        if(keyCode == RIGHT && charX < width){
          charX += charSpeed;
        }
      }
      // render
      background(0);
      image(charImage, charX, charY);
    }
    

    It's unclear if you're going for a top down, side view or other view: this might change how you update the character movement a bit.

    Additionally it's unclear if you have a single static character image or a spritesheet image which in one image contains multiple poses such as a walk cycle animation. If this is the case you can find a detailed answer on spritesheets here: it is in p5.js, however it should be trivial to adapt the minor syntax changes from p5.js to Processing where needed:

    // full spritesheet
    PImage spriteSheet;
    // a sprite sampling from sprite sheet
    PImage mario;
    
    // 8 frames in the spritesheet
    int numSprites   = 8;
    // each sprite in the sheet has this bounding box
    int spriteWidth  = 18;
    int spriteHeight = 24; 
    // start frame
    int spriteIndex  = 1;
    
    void setup(){
      size(150,150);
      frameRate(24);
      noSmooth();
      noFill();
      spriteSheet = loadImage("mario.png");
      // create an image to draw a single sprite into
      mario = createImage(spriteWidth,spriteHeight, RGB);
    }
    // set all pixels (R,G,B,A) to the same value (e.g. clear image with a colour)
    void setAllPixels(PImage image,int brightness){
      // prep. pixels for manipulation
      image.loadPixels();
      int numPixels = image.pixels.length;
      // loop through all pixels (spriteWidth * spriteHeight * colourChannels(4))
      for(int i = 0 ; i < numPixels; i++){
        image.pixels[i] = brightness;
      }
      // commit value changes to image: updates it all in one go, more efficient than set()
      image.updatePixels();
    }
    
    void draw(){
      // clear frame
      background(255);
      // display the whole sprite sheet
      image(spriteSheet,0,0);
      // increment sprite index
      spriteIndex++;
      // reset sprite index if out of bounds
      if(spriteIndex >= numSprites){
        spriteIndex = 0;
      }
      // visualise sprite copy rect
      rect(spriteIndex * spriteWidth,0,spriteWidth,spriteHeight);
      
      // clear mario image
      setAllPixels(mario,color(255));
      // copy pixels from sprite sheet into sprite
      // copy (source image, source coordinates(x,y,w,h), destination coordiantes (x,y,w,h) )
      mario.copy(spriteSheet,
                 spriteIndex * spriteWidth,0,spriteWidth,spriteHeight,
                 0                        ,0,spriteWidth,spriteHeight);
                 
      // display mario sprite
      image(mario,mouseX,mouseY+spriteHeight);
    }
    

    mario.png data:

    data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJAAAAAYCAYAAAAVpXQNAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyhpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQwIDc5LjE2MDQ1MSwgMjAxNy8wNS8wNi0wMTowODoyMSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTggKE1hY2ludG9zaCkiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MzE1ODI1MkNDQ0MzMTFFOEJFNjA5ODI5Q0U0NzlGOEEiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MzE1ODI1MkRDQ0MzMTFFOEJFNjA5ODI5Q0U0NzlGOEEiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpFM0U1NkY3RkNDQTMxMUU4QkU2MDk4MjlDRTQ3OUY4QSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpFM0U1NkY4MENDQTMxMUU4QkU2MDk4MjlDRTQ3OUY4QSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PszND6MAAAXWSURBVHja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