How to use sprites

edited November 2016 in Questions about Code

Hi, I'm trying to use some sprites in Processing, I already have class wich use only one image but I'd like to change that to multiple ones.

My classes look like that https://paste2.org/0Z7tgG1E with others classes that extend Vaisseau

«13

Answers

  • edited November 2016

    @poisson86 --

    I already have class which use only one image but I'd like to change that to multiple ones.

    I'm not sure I understand what your question is.

    Are you saying that you want to change your class from one image and one mask:

    Entity(int vie, float x, float y, PImage im, PImage masque, boolean ally)
    

    ...to multiple images and multiple masks?

    Entity(int vie, float x, float y, PImage[] imlist, PImage[] masquelist, boolean ally)
    

    Keep in mind that there are also sprite libraries for Processing if you want to pass around a sprite object rather than an image list -- check out the Libraries listed under Animation, like Sprites and Frames.

    Also, keep in mind that many sprites are not implemented as multiple images at all -- instead they implement pointers to different offset regions on a single image (a "sprite sheet").

  • edited November 2016

    @jeremydouglass

    Yes I know they're librairies but I don't how to use them quite well, and what I want to do is a bit blury too. Entity(int vie, float x, float y, PImage[] imlist, PImage[] masquelist, boolean ally) It could be something like that yes i think

  • Up ? :( I can't do proper animations in my program and it's kind of important :/

  • Yes I know they're librairies but I don't how to use them quite well,

    You have to decide which would be quicker, learn how to use an existing library like Sprites or learn how to do it from scratch.

    Looking at the Vaisseau class you have a lot to do to get sprite animations.

  • edited November 2016

    Yes that's why I'm a bit lost :/ i already download and check out the Sprite librairie but I'm not using my class as in it

  • @poisson86

    Check the following link: http://www.lagers.org.uk/s4p/ There is a reference an examples. If you are stuck, ask here in the forum. Notice the creator of this library is @quark... so you are a very lucky fellow!

    Kf

  • edited November 2016

    @kfrajer @quark

    Okay thanks :) So in the librairy I don't understand what Sprite (PApplet theApplet, String imageFname, int cols, int rows, int zOrder) the int zOrder means and how do we use the .setFrameSequence();

    Because I've done : explosion = new Sprite(this, "Explosion.png", 7, 1, 100); explosion.setFrameSequence(1,8); explosion.setXY(250,250);

    With this Sprite but it's not at the right size and it isn't "moving" image.noelshack.com/fichiers/2016/48/1480439880-explosion.png

  • First thing is that the image you are using is not suitable for sprites. It is common in games to use a sprites sheet, this is an image-file with multiple tiled images where ALL tiles are the same size. In your image the tiles are not the same size.

    Here is a sprite sheet I downloaded of the internet and I have used it in the sketch shown below. Notice it has 25 frames and they are numbered left-to-right top-to-bottom starting with 0 (zero). So the frame numbers are 0-24 inclusive.

    explosion

    The zOrder attribute determines the order that sprites are drawn. For instance if you have a spaceship and explosion sprite you would want the explosion to appear 'over' the spaceship. So the explosion sprite should have a higher number than the spaceship. The actual zOrder values are unimportant they simply decide on the order sprites are drawn on the screen.

    To animate the sprite we simply tell the sprite which frames to animate, the time interval between frames and how many times to repeat the animation.

    So in my sketch we have

    // Animate the sprite using frames 0 to 24 with a frame interval 
    // of 0.02 seconds and play the sequence just once 
    explosion.setFrameSequence(0, 24, 0.02, 1);
    

    In the sketch below we have created a StopWatch object (line 9) and this will be used to measure the elapsed time between frames. The real power of Sprites can be seen in the draw method.
    Line 18: we make a note of the elapsed time in seconds.
    Line 19: this single statement will update ALL sprites that have been created
    Line 20: this single statement will display ALL sprites that have been created

    Sprites is a powerful library which means that it takes a while getting used to but will do most of the hard work for you. You can use the sketch code below as a basis for trying out different parts of the library.

    import sprites.*;
    import sprites.maths.*;
    import sprites.utils.*;
    
    Sprite explosion;
    float px, py;
    
    // This will be used for timing
    StopWatch sw = new StopWatch();
    
    void setup() {
      size(400, 400);
      explosion = new Sprite(this, "explosion.png", 5, 5, 10);
    }
    
    void draw() {  
      // Get the elapsed time since the last frame
      float elapsedTime = (float) sw.getElapsedTime();
      S4P.updateSprites(elapsedTime);
      background(200, 200, 255);
      S4P.drawSprites();
    }
    
    void mouseClicked(){
      // Move the sprite so it in centerd over the mouse position
      explosion.setXY(mouseX, mouseY);
      // Animate the sprite using frames 0 to 24 with a frame interval 
      // of 0.02 seconds and play the sequence just once 
      explosion.setFrameSequence(0, 24, 0.02, 1);
    }
    
  • @quark

    Okay so I understood your example but now i'm trying to do this in a class but nothing appear :/

    https://paste2.org/xEAMhsVf

  • @poisson86

    We need to see all the code, or a short running version showing your problem. Your code in the link doesn't run as it is.

    Kf

  • So I think I removed things as much as I can : https://paste2.org/K0hEwUaM

  • Answer ✓

    I am not going to try and incorporate the library into your code instead I am going to give you an example of how to effectively use the Sprite library. Then you can adapt your code to suit.

    The first thing is that the base class should be the Sprite class. This gives your classes all the power of Sprite including easy updating and displaying. It also allows you to add extra functionality.

    I have made your Entity class non-abstract because it now inherits from Sprite.

    The update method in the child classes overrides the one in Sprite so we have to call the overridden method in Sprite first to make sure the sprite moves and is animated.

    Hopefully you will manage to work out what the code is doing but if not ask here. :)

    BTW the images used are below except explosion which is above. I leave you to open the Tardis doors ;)

    import sprites.*;
    import sprites.maths.*;
    import sprites.utils.*;
    
    StopWatch sw = new StopWatch();
    
    Entity dalek;
    Tardis tardis;
    Bullet bullet;
    VisualEffect explosion;
    MuzzleFlash flash;
    
    public void settings() {
      size(800, 600, P2D);
    }
    
    public void setup() {
      frameRate(120);
      tardis = new Tardis(this, "tardis.png", 5, 2, 10);
      tardis.setDomain(200, -150, width + 60, height + 150, Sprite.REBOUND);
      tardis.setXY(width/2, height/2);
      tardis.setVelXY(400*sin(radians(37)), 400*sin(radians(37)));
      explosion = new VisualEffect(this, "explosion.png", 5, 5, 20);
      dalek = new Entity(this, "dalek.png", 1, 1, 10);
      dalek.setDomain(0, 40, 60, height - 40, Sprite.HALT);
      dalek.setXY(30, height/2);
      dalek.setVelXY(0, 0);
      flash = new MuzzleFlash(this, "flash.png", 1, 4, 50);
      flash.setDead(true);
      bullet = new Bullet(this, "bullet.png", 2, 1, 10);
      bullet.setDead(true);
    }
    
    public void draw() {
      dalek.setVelY(1.5 * (mouseY - dalek.getY()));
      background(0);
      double et = sw.getElapsedTime();
      S4P.updateSprites(et);
      S4P.drawSprites();
    
      // Test for hit
      if (!bullet.isDead()) {
        if (tardis.pp_collision(bullet)) {
          tardis.hit(explosion);
          bullet.setDead(true);
        }
      }
    }
    
    public void mouseClicked() {
      flash.fire(dalek);
      bullet.fire(dalek);
    }
    
    // General purpose base class for your own game objects. 
    class Entity extends Sprite {
    
      public Entity(PApplet theApplet, String imageFname, int cols, int rows, int zOrder) {
        super(theApplet, imageFname, cols, rows, zOrder);
      }
    }
    
    class VisualEffect extends Entity {
    
      public VisualEffect(PApplet theApplet, String imageFname, int cols, int rows, int zOrder) {
        super(theApplet, imageFname, cols, rows, zOrder);
      }
    }
    
    class Tardis extends Entity {
    
      VisualEffect effect = null;
      double hx, hy;
      public Tardis(PApplet theApplet, String imageFname, int cols, int rows, int zOrder) {
        super(theApplet, imageFname, cols, rows, zOrder);
      }
    
      public void hit(VisualEffect effect) {
        this.effect = effect;
        effect.setFrameSequence(0, 24, 0.05, 1);
        effect.setDead(false);
        // Save pixel collosion position
        hx = getHitX();
        hy = getHitY();
      }
    
      public void update(double deltaTime) {
        // Make sure we do the library Sprite class update method
        super.update(deltaTime);
        // Now do any extra stuff
        // If the explosion is animating then keep it with the tardis otherwise
        // mark it as dead
        if (effect != null) {
          if (effect.isImageAnimating())
            effect.setXY(getX() - getWidth()/2 + hx, getY() - getHeight()/2 + hy);
          else 
          effect.setDead(true);
        }
      }
    }
    
    class Bullet extends Entity {
    
      public Bullet(PApplet theApplet, String imageFname, int cols, int rows, int zOrder) {
        super(theApplet, imageFname, cols, rows, zOrder);
      }
    
      public void fire(Entity dalek) {
        setFrameSequence(0, 1, 0.05);
        setXY(dalek.getX() + 88, dalek.getY());
        setVelXY(1000, 0);
        setDead(false);
      }
    
      public void update(double deltaTime) {
        // Make sure we do the library Sprite class update method
        super.update(deltaTime);
        // Now do any extra stuff
        // If the bullet has moved of screen ten it is dead
        if (!isOnScreem())
          setDead(true);
      }
    }
    
    class MuzzleFlash extends Entity {
    
      Entity dalek = null;
    
      public MuzzleFlash(PApplet theApplet, String imageFname, int cols, int rows, int zOrder) {
        super(theApplet, imageFname, cols, rows, zOrder);
      }
    
      public void update(double deltaTime) {
        // Make sure we do the library Sprite class update method
        super.update(deltaTime);
        // Now do any extra stuff
        // Track the dalek if we have one
        if (dalek != null && !dead)
          setXY(dalek.getX() + 78, dalek.getY());
        // If the animation is stopped then this is dead
        if (!isImageAnimating())
          setDead(true);
      }
    
      public void fire(Entity dalek) {
        this.dalek = dalek;
        setFrameSequence(0, 3, 0.02f, 10);
        setDead(false);
      }
    }
    

    bullet dalek flash tardis

  • @quark -- quick question. I see your sketch needs 5 pngs, but four are listed in this post. Is the fifth available somewhere? Or is the whole example sketch with resources somewhere?

  • Alright @quark

    Your exemple perfectly shows how Sprite works but you see in my program i have x, y and so on which permit me to move the image right after. So, should I redo everything to get something like you or it isn't necessary ?

  • @jeremydouglass the fifth image is the explosion which I posted in an earlier comment.

    Eventually I will include the code as an example sketch in the library download, but don't hold your breath as I am busy on a new project.

    So, should I redo everything to get something like you or it isn't necessary ?

    If you have your own variables like x and y for the sprite position then there will be confusion over which ones to use, the position stored in Sprite or the ones provided in your own class.

    I would recommend that you redo everything. Not so bad really because the example shows you how to do it and the Sprite class provides so much functionality that you would have to create. After all it took me several months to create the library first in C++ and later more months to translate it into Java to be used with Processing.

    Once you become familiar with the library you will be able to save so much time.

  • edited November 2016

    Alright thank you ;) i'll do that tomorrow, huge physics exam in the morning ^^

  • Good luck with the exam :)>-

  • edited December 2016

    Hi again :) so i'm going to try to redo everything but you saw that my class entity create objects in an arraylist. What should be the differences then ? Because you change x,y coordinate in your void setup() and i don't.

    Also I don't think i'm capable to rewrite everything with your method, this took me so much time and redo it would take almost as much time.

  • In your code the x/y sprite position is setup in the constructor. The sprite library uses the constructor to set up the sprite image frames and provides the setX, setY and setXY methods to do that.

    The library keeps track of all the sprites so that they can be updated and draw with 2 simple statements.

    S4P.updateSprites(et);
    S4P.drawSprites();
    

    which must be inside the main draw method. You can remove a sprite so they are not updated and drawn by deregistering it with

    S4P.deregisterSprite(sprite);

    and can be addded back later with

    S4P.registerSprite(sprite);

    So you don't need your own arraylist of sprites for updating and drawing the sprites but you might want your own to simplify collision detection etc.

    Notice that we don't update the sprites position manually rather we set the sprites velocity and let the library do the hard work.

  • edited December 2016

    No, i was talking about the rest, i already have my collision and everything but add Sprite would change too much things that I will be lost (like changing every Constructor)

  • If you think that using Sprite will cause too many problems then don't use it.

    Ultimately its your choice. :)

  • I'm not saying that, it's just I don't have enough experience to change everything without messing it ^^

  • Make a copy of the sketch as it is now and try modifying the copy. If it doesn't work you still have the original.

    The alternative is to start again from scratch using the Spite library, but I can understand your reluctance especially if you have already done a lot of code.

    I have been posting on this forum since December 2008 when Processing was version 1.2.1. My first library, G4P was released in March 2009 and since then PS has morphed through PS1 > PS2 > PS3 and there is hardly any of the original code left and that's thousands of lines of code. So I understand where you are coming from. There were times when I could have quite happily abandoned G4P because that the changes I needed to implement were so massive.

    I can't make the decision for you, you must do what you think best. :)

  • Alright :) I may at least try a bit :p Just a last question, do you have any clues change your entity as mine like using an arraylist for the objects ?

  • You appear to be using the arraylists to track all the entities that are alive and and dead so you can latter remove the dead ones without causing concurrent access violations. Which is a neat trick and one I use in Sprites, I have two lists of sprites to add and sprites to remove which are updated by the registerSprite and deregisterSprite, latter the updateSprites method will add the new sprites and remove the dead sprites from the main list.

    So put the two arraylists back in

    ArrayList<Entity> entities = new ArrayList<Entity>();
    ArrayList<Entity> toRemove = new ArrayList<Entity>();
    

    then when you create a sprite you can add it

    tardis = new Tardis(this, "tardis.png", 5, 2, 10);
    entities.add(tardis);
    

    when a sprite becomes dead remove it. This is the update method from the Bullet class

    public void update(double deltaTime) {
      // Make sure we do the library Sprite class update method
      super.update(deltaTime);
      // Now do any extra stuff
      // If the bullet has moved of screen ten it is dead
      if (!isOnScreem()){
        setDead(true);
        toRemove.add(this);
      }
    }
    

    Afraid I have to go now I am working on a new library and an application based on it, but I will look in and help when I can.

  • Finally I won't use it sorry :/ it demands me to redo everything and could be even unappropriate with other things I have :/ I'll try to look for something else maybe more simple to use x)

  • No need to apologise, it was an option, you tried it, and it wasn't for you. :)

  • Thank you anyway :) if you have an other idea just to do an explosion (not animate something moving) I won't be far away :)

  • There is a lib to animate gifs

    So if you have a gif with an explosion movie

  • @chrisir which one is it ? :) pls

  • @poisson86

    Install the imageLoader library using the library manager. Then check the example FileGifLoaderExample

    Other ideas... search in the forum:

    https://forum.processing.org/two/search?Search=gif
    https://forum.processing.org/two/search?Search=gifAnimation

    Kf

  • you also need a gif of an explosion!!!

  • ok, you can do a nice explosion without sprites, just like a particle system:

    // overall structure: The tab ShootTest1 is the main program.
    // A player (only a white rectangle) 
    // in tab player shoots bullets (in tab Bullet), when 
    // they hit the wall, they explode (tab Explosion).
    // Bullet and Explosion are really similar. 
    // The tabs Player, Bullet and Explosion each contain only 
    // the class.
    // The tower can only shoot upwards, follows mouse, click mouse. 
    //
    // idea from 
    // http://forum.processing.org/topic/need-help-adding-shooting
    // with help from 
    // http://forum.processing.org/topic/have-eyes-follow-mouse
    //
    // Player
    Player thePlayer = new Player();
    // for explosions (these are actually Shrapnels)
    ArrayList <Explosion> missiles; 
    //
    // bullets
    final float bulletFlySpeed = 4.2;  // how fast bullet flies
    final int fireSpeed=200; // how often you fire / distance between bullets
    int lastFired=millis();  // timer to determine when next bullet starts 
    
    
    // ------------------------------------------------------------------
    
    void setup() {
      size(600, 480);
      // explosions: Create an empty ArrayList
      missiles = new ArrayList<Explosion>();
      cursor(CROSS);
    }
    
    void draw() {
      background(111);
      thePlayer.draw();
      // blue rect
      noStroke();
      fill(0, 0, 255);
      rect (100, 100, 40, 40);
      ExplosionManager();
    }
    
    void mousePressed() {
      thePlayer.fire();
    }
    
    void keyPressed() {
      thePlayer.fire();
    }
    
    void ExplosionManager() {
      // this is a new for loop.
      // Actually for the Shrapnels.
      for (Explosion m : missiles) {
        m.decreaseLife(); // call the decrease life (for explosion)
        m.fly();          // call the "fly" method of the missile
        m.display();      // call the "display" method of the missile
      }
      //
      // remove dead ones (you need to have a conventional backward for-loop here)
      for (int i=missiles.size()-1; i>=0; i--) {
        Explosion m = (Explosion) missiles.get(i);
        if (m.dead) {
          missiles.remove(i);
        }
      }
    } // func
    //
    
    
    
    // ================================================================
    // Bullet - Simple class for bullets
    // http://www.processing.org/learning/topics/arraylistclass.html
    
    class Bullet {
    
      float x;
      float y;
      float speedX ;  
      float speedY;
      float w;
      float life = 255;
    
      Bullet(float tempX, float tempY, // new2
        float tempSpeedX, float tempSpeedY, 
        float tempW) {
        x = tempX;
        y = tempY;
        w = tempW;
        speedX = tempSpeedX; // 4.2; // new2 
        speedY = tempSpeedY; // 0;
      }
    
      void move() {
        // Add speed to location
        x = x + speedX; 
        y = y + speedY;
        //
        // kill bullet when outside screen
        if (x<4) 
          life=-1;
        if (y<4) 
          life=-1;
        if (x>width-4) 
          life=-1;
        if (y>width-4) 
          life=-1;
    
        // blue rect
        if (x>=100 && y>=100 && x<=140 && y<=140)   
          life=-1;
        //
        if (life==-1) 
          explode () ;
      } // method 
    
      void explode () {
        // explode!
        int maxMissiles= int(random(4, 222));
        for (int i=0; i<maxMissiles; i+=1) {   
          // this is where explode missile/shrapnel object is created
          // and added to the missiles arrayList.
          // It is small (4) and life decrease is .72 (how fast it dies),
          // no Line (false).
          missiles.add( new Explosion(
            random(x-3, x+3), random(y+9, y+12), 
            random(-1.3, 1.3), random(-2.7, .6), 
            4, .72, false)); //
        }
      } // method
    
      boolean finished() {
        // bullet dead?
        if (life < 0) {
          return true;
        } else {
          return false;
        }
      }
    
      void display() {
        // Display the circle
        fill(244, 2, 2);
        noStroke();
        //stroke(0,life);
        ellipse(x, y, w, w);
        // image( ammo_fired, x, y );
      }
    } // class 
    //
    
    
    
    // ===============================================================
    // the tab for Explosion class
    
    class Explosion {
      float startlocX, startlocY; // start pos
      float x, y;          // current pos
      float xvel, yvel;    // velocity
      float sizeMissile ;  // size for rect
      float life=20;       // how much lifes does it have
      float lifeDecrease;  // remove lifes
      boolean dead=false;  // is it alive?
      boolean withLine;    // draw line? Explosion has none.
      //
      // contructor
      Explosion(
        float _startlocX, float _startlocY, 
        float _xvel, float _yvel, 
        float _size, float _lifeDecrease, 
        boolean _withLine)
      {
        startlocX = _startlocX;
        startlocY = _startlocY;   
        x = startlocX;
        y = _startlocY;
        sizeMissile = _size;
        lifeDecrease=_lifeDecrease;
        xvel = _xvel;
        yvel = _yvel;
        withLine=_withLine;
      }  // contructor
      //
      void display() {
        //stroke(255, 2, 2);
        fill(255, 2, 2);
        noStroke();
        if (withLine) {
          line(startlocX, startlocY, x, y);
        }
        sizeMissile-=.07;
        rect(x, y, sizeMissile, sizeMissile);
      } // method
      //
      void fly() {
        x += xvel;
        y += yvel;
      } // method
      //
      void decreaseLife() {
        life-=lifeDecrease;
    
        // check wall collision
        if (x<0) 
          dead=true;
        if (y<0) 
          dead=true;
        if (x>width) 
          dead=true;
        if (y>width) 
          dead=true;
    
        if (life<=0 || sizeMissile<=0) {
          dead=true;
        }
      } // method
      //
    } // class
    //
    // ======================================================================
    
    
    
    // =====================================================================
    // the Player class
    
    class Player {
    
      ArrayList<Bullet> bullets;   
      PVector position, velocity; // contains x and y...
    
      // ammo not in use 
      int ammoCount = 70; 
    
      Player() {
        bullets  = new ArrayList();   
        position = new PVector(333, 333);
        velocity = new PVector();
        velocity.x = 0;
        velocity.y = 0;
      }
    
      void fire() {     // new2
        if (fireSpeed<=millis()-lastFired) {
          if (ammoCount>0) {
            // ammoCount--;
            lastFired=millis();
    
            float xSpeed ;
            float ySpeed ; 
            float angle = update(mouseX, mouseY);
            xSpeed = cos(angle);
            ySpeed = sin(angle);
            xSpeed*= bulletFlySpeed;
            ySpeed*= bulletFlySpeed;
            if (ySpeed>0)
              ySpeed=0;
            bullets.add ( new Bullet( 
              position.x+12, position.y-14, 
              xSpeed, ySpeed, 
              5 ));
          } // if
        } // if
      } // method 
    
      float update(int mx, int my) {
        //determines angle to mouse
        float angle = atan2(float(my)-(position.y-14), float(mx)-(position.x+12));
        return angle;
      }
    
      void draw() {
        // draw player & bullets
        //
        // draw player 
        pushMatrix();
        translate(position.x, position.y);
        noStroke();
        fill(255);
        rect (0, 0, 20, 40);
        popMatrix(); // undoes all
    
        // draw bullets
        for (Bullet currentBullet : bullets ) {     // new1 
          // println ("************************");
          currentBullet.move();
          currentBullet.display();
        }
    
        // With an array, we say length, with an ArrayList, we say size()
        // The length of an ArrayList is dynamic
        // Notice how we are looping through the ArrayList backwards
        // This is because we are deleting elements from the list  
        for (int i = bullets.size()-1; i >= 0; i--) { 
          // An ArrayList 
          Bullet currentBullet = bullets.get(i);
          if (currentBullet.finished()) {
            // Items can be deleted with remove()
            bullets.remove(i);
          }
        }
      }
    }
    
    // ==============================================================
    
  • edited December 2016

    you can also just use the sprite sheet with the explosion by quark (further up) to make your own animation of this sprite sheet.

    Click mouse to explode.

    Note that the sprite sheet by quark must be in the data folder with the name P6LFNRLPISUT.png (which occurs if you just save it from the forum).

    The data of the sprite sheet are very important: This is a 5x5 image sprite sheet with size of 64x64 per one image.

    Note: When you want to have multiple explosions, store them in an ArrayList and work with that. (Or PM me).

    Best, Chrisir ;-)

    // see https : // forum.processing.org/two/discussion/comment/80948#Comment_80948
    
    Explosion explosion1; 
    
    // ---------------------------------------------------------------
    
    void setup() {
      // runs only once - init
      size(800, 600);
      // init it
      explosion1 = new Explosion();
    }
    
    void draw() {
      background(0); 
      // show it 
      explosion1.display();
    }
    
    void mousePressed() {
      // start it
      explosion1.start(mouseX, mouseY);
    }
    
    // ===========================================
    
    class Explosion {
    
      // Starting position of Explosion 
      float xpos, ypos;   
    
      // a list of images with the frames of the explosion
      PImage frames[];
    
      // current frame is frameNumber
      int frameNumber = 0; 
      int frameNumberAdd=1; // add to go to next frame (mostly 1)
    
      // additional counter between two frames (to make it slower)
      int countBeforeNextFrame = 0;
      int speedOfAnimation = 1; // 1 is fast, 12 is slow e.g.
    
      // has the explosion started and 
      // does the explosion still exist? 
      boolean exist=false; // no
    
      // constructor 
      Explosion() {
    
        // run only once, not for every new explosion!!!!
    
        PImage spriteSheet;
    
        spriteSheet = loadImage("P6LFNRLPISUT.png");
    
        print ("spriteSheet is "
          +spriteSheet.width
          + " x "); 
        println (spriteSheet.height); 
    
        // We read the images from the sprite sheet to make things a little faster. 
        // All those numbers (5, 64...) used here 
        // depend from the sprite sheet you have.
        // This is a 5x5 image sprite sheet with size of 64x64 per one image. 
        frames = new PImage[5*5];
        for (int y = 0; y < 5; y++) {
          for (int x = 0; x < 5; x++) {
            frames[y*5+x] = spriteSheet.get(x*64, y*64, 64, 64);
          }
        } // for
      }//constr
    
      void start(float x_, float y_) {
        if (!exist) {
    
          // start it 
          exist=true;
    
          // reset 
          countBeforeNextFrame = 0;
          frameNumber=0; 
    
          // set position 
          xpos=x_;
          ypos=y_;
        }
      }
    
      void display() {
        // Display
    
        // if explosion (still) runs
        if (exist) {
    
          // println(frameNumber); 
    
          // display current frame
          image(frames[frameNumber], xpos-32, ypos-32);
    
          // to make movement slower: countBeforeNextFrame
          // by Chinchbug (http://www.openprocessing.org/sketch/26391)
          countBeforeNextFrame++; 
          if (countBeforeNextFrame > speedOfAnimation) {
            // reset countBeforeNextFrame
            countBeforeNextFrame = 0; 
            // go to next frame
            frameNumber+=frameNumberAdd;
            // if last frame, end explosion 
            if (frameNumber >= 25) {
              exist=false;
            }// if
          }// if
        }//if
      } // func
      //
    }// class 
    //
    
  • edited December 2016

    Hi @Chrisir :) thank you for your help but with your code combine with mine (and some modification) the explosion never stop and loop at the same place no matter what I do :(

  • Are you referring to my 1st or 2nd version?

    Post your code to get help

  • edited December 2016

    Your second version sorry ^^ this is the same code that I posted few days ago and I put the explosion1.start(x, y); in the destroy(){}function :)

    and by the way I would need multiple explosion (didn't see this part before ^^)

    https://paste2.org/nXw2Z2AF

  • edited December 2016

    that is not the entire code

    class Explosion is missing

    missing ; here

    void destroy()
      {
        explosion1.start(x, y) /// ;
      }
    

    how did you run the code in the first place?

  • woops forgot to past it ^^ but your Class is the same appart the name of the file ^^

  • edited December 2016

    next error :

    can't find anything named explosion1

      explosion1.display();
    

    dTime cannot be resolved....................

    cannot find S4P ..........................

    do you want me to do your work for you?

    Have you really ran the code?

  • edited December 2016

    https://paste2.org/ecX2F8f3 This one works :) I pasted a little bit too fast

    And I have to test on my main program but I cannot paste it, because it's way too big so sometimes I fail my pastes sorry :/

  • you need this at beginning of draw()

     toRemove.clear(); 
    
  • Wow that worked :o can you explain why ? :) I'm going to try to add multiple explosion.

    Thank you for help and your time :)

  • your way of removing stuff from ArrayList one by adding it to ArrayList toRemove is very clumsy

    Basically, the list toRemove wasn't empty, so the remaining thing got destroyed again and again

    Since toRemove is only a helplist, you need to reset it with clear as shown

    but there are better ways to do it without using toRemove at all

  • Alright :) I know I found out this way and I kinda like it so as long as it works properly, I don't mind ^^

  • this is without toRemove

    Explosion explosion;
    
    ArrayList<Entity> entities = new ArrayList<Entity>();
    
    float dTime=3.0;
    
    void setup() 
    {
      size(500, 500, P3D); 
      frameRate(120);
      background(0);
      explosion = new Explosion();
    
      entities.add(new Joueur(100, 300));
    }
    
    void draw() 
    {
      background(0); 
    
      // looping backward 
      for (int i = entities.size()-1; i >= 0; i--)
      {
        Entity entity = entities.get(i); 
        entity.display();
        entity.update();
    
        if (entity.x > 300 || entity.destroyed) { 
          entity.destroy(); 
          entities.remove(i);
        }
      }
    
      explosion.display();
    }
    // ====================================================
    abstract class Entity {
    
      float x, y, w, h;
      boolean ally, destroyed = false;
    
      Entity(float x, float y, boolean ally)
      {
        this.x = x;
        this.y = y;
        this.ally = ally;
      }
    
      void update()
      {
      }
    
      void display() 
      {
        rect(x, y, 20, 20);
      }
    
      void touched() 
      {
      }
    
      void destroy()
      {
      }
    }
    
    // ==========================================
    
    class Vaisseau extends Entity {
    
      int vie;
      double delay;
      double delayTir;
    
      Vaisseau(float x, float y, boolean player)
      {
        super(x, y, player);
        this.ally = player;
        delayTir = ally ? 10 : random(200, 250);
        delay = (ally ? delayTir : delayTir/2) * dTime ;
      }
    
      void update() 
      {
        //S4P.updateSprites(dTime);
        //S4P.drawSprites();
      }
    
      void tir() 
      {   
        //...
      }
    
      void touched()
      {
        vie -= 1;
        if (vie <= 0) destroyed = true;
      }
    
      void destroy()
      {
        explosion.start(x, y);
      }
    }
    
    // ==========================================
    
    class Joueur extends Vaisseau {
    
      int vitesse;
    
      Joueur(float x, float y)
      {
        super(x, y, true);
        vitesse = 5;
        vie = 1;
      }
    
      void update() 
      {        
        x ++;
      }
    }
    
    // ===========================================
    
    class Explosion {
    
      // Starting position of Explosion 
      float xpos, ypos;   
    
      // a list of images with the frames of the explosion
      PImage frames[];
    
      // current frame is frameNumber
      int frameNumber = 0; 
      int frameNumberAdd=1; // add to go to next frame (mostly 1)
    
      // additional counter between two frames (to make it slower)
      int countBeforeNextFrame = 0;
      int speedOfAnimation = 1; // 1 is fast, 12 is slow e.g.
    
      // has the explosion started and 
      // does the explosion still exist? 
      boolean exist=false; // no
    
      // constructor 
      Explosion() {
    
        // run only once, not for every new explosion!!!!
    
        PImage spriteSheet;
    
        spriteSheet = loadImage("P6LFNRLPISUT.png");
    
        print ("spriteSheet is "
          +spriteSheet.width
          + " x "); 
        println (spriteSheet.height); 
    
        // We read the images from the sprite sheet to make things a little faster. 
        // All those numbers (5, 64...) used here 
        // depend from the sprite sheet you have.
        // This is a 5x5 image sprite sheet with size of 64x64 per one image. 
        frames = new PImage[5*5];
        for (int y = 0; y < 5; y++) {
          for (int x = 0; x < 5; x++) {
            frames[y*5+x] = spriteSheet.get(x*64, y*64, 64, 64);
          }
        } // for
      }//constr
    
      void start(float x_, float y_) {
        if (!exist) {
    
          // start it 
          exist=true;
    
          // reset 
          countBeforeNextFrame = 0;
          frameNumber=0; 
    
          // set position 
          xpos=x_;
          ypos=y_;
        }
      }
    
      void display() {
        // Display
    
        // if explosion (still) runs
        if (exist) {
    
          // display current frame
          image(frames[frameNumber], xpos-32, ypos-32);
    
          // to make movement slower: countBeforeNextFrame
          // by Chinchbug. http : // www.openprocessing.org/sketch/26391
          countBeforeNextFrame++; 
          if (countBeforeNextFrame > speedOfAnimation) {
            // reset countBeforeNextFrame
            countBeforeNextFrame = 0; 
            // go to next frame
            frameNumber+=frameNumberAdd;
            // if last frame, end explosion 
            if (frameNumber >= 25) {
              exist=false;
            }// if
          }// if
        }//if
      } // func
      //
    }// class 
    //
    
  • Okay thank you :) i'll check than soon ;)

    Is there a way to speed up or slow down your animation without touching the framerate ? :)

  • Boy, have you even read my code???

    Look at line 141

  • How did I even skip the only one I wanted Oo I saw the bool and the frame count but I didn't see this one ^^ I'm use to see that much comments maybe :) Not more questions anyways, I'll change your class to get other things but I won't require any further help :) Thanks ;)

Sign In or Register to comment.