How to create 2D lights for game ?

I want to have day and night there and when it's night, I want some lights there

Tagged:

Answers

  • Here is a simple 24-hour clock, driven by the millis() command.

    Every 500 milliseconds (every half second) it counts up a game-hour towards 24. It loops back around from 23 (11pm) to 0 (12a). You can slow down the clock by making "500" larger -- a game-hour per second (1000) or a game-hour per minute (60000).

    int hour;
    void setup() {
      frameRate(10);
    }
    void draw() {
       hour = (millis()/500)%24;
       println(hour);
    }
    

    Now the game knows what game-hour of the game-day it is.

  • Let's use the hour (0-23) to set how light or dark the sky is.

    /**
     * TimeDependentSky
     * Rendering a scene using a simple day-night clock.
     * 2017-10-16 Jeremy Douglass - Processing 3.3.6
     * forum.processing.org/two/discussion/24534/how-to-create-2d-lights-for-game
     */
    float hour;
    float light;
    void setup() {
      frameRate(10);
      noStroke();
    }
    
    void draw() {
      hour = (millis()/500.0)%24;
      light = sin(TWO_PI * hour/24 - 8);
      println(hour, light);
    
      background(0);
    
      // draw the sky
      fill(0, 0, light*255 );
      rect(0,0,width,height/2);
      fill(255);
      ellipse(width/2, height/2 - height/2*light, 10, 10);
    
      // draw a house
      fill(64);
      rect(6, height/2 - 14, 30, 18);
      // turn on the lights
      if( hour > 14 ) {
        fill(255);
        rect(10, height/2 - 10, 10, 10);
        rect(22, height/2 - 10, 10, 10);
      }
    }
    

    The sun is drawn in front of the scene and moves only to the edges of the screen to make it very easy to see what the hour (noon is up, midnight is down) and how the blueness of the sky and the lights in the windows react to the hour.

    TimeDependentSky--screenshot

    There is one tricky line here:

    light = sin(TWO_PI * hour/24 - 8);
    

    This takes the hour of day and feeds it into a sine wave such that:

    hour =  0, light = -1
    hour =  6, light =  0
    hour = 12, light =  1
    hour = 18, light =  0
    hour =  0, light = -1
    
  • But i want to create shadow mask for player :/ and on this mask i want create light mask...

  • i want to this.... Test it:

    size(500,500);
    background(255,0,0);
    noStroke();
    fill(0,125);
    rect(50,50,400,400);
    fill(255,125);
    rect(100,100,300,300);
    fill(255);
    text("Why this color is not same\n as default background ?",150,150);
    
  • Can you explain a little more about this please

    What do you want to achieve?

  • I want to make light when is night :D

  • I don't understand what you are saying.

    Use. More. Words.

  • I want to do the night in the game. And when the player is there, I want him to have a flashlight so light is around him

  • Ah. See the tint() and mask() examples.

    One approach to having a pool of light that shows the background is to tint a version of the background image on a PGraphics, mask it with a circle (or a partially transparent set of nested circles) and then draw it under the Player.

  • Answer ✓

    George, do you realize how much work jeremy put into this? And now you say you want to have something totally different. Please describe longer what you mean in future.

    You haven’t even said Thanks....

  • Can you create exemple ?

  • @GeorgeJava -- glad you got your tint/mask working.

    Would you please share your solution here?

    That could help future learners on the forum.

  • Here is a demo of the compositing order to create a simple player flashlight / fog-of-war effect. Parts of the background are hidden (e.g. in shadow) and the player presence reveals them (using a mask).

    /**
     * PlayerLight
     * Demonstration of a simple flashlight / fog-of-war type effect,
     * in shadowed parts of the background are only visible near the player.
     * 2017-10-18 Jeremy Douglass - Processing 3.3.6
     * forum.processing.org/two/discussion/24534/how-to-create-2d-lights-for-game
     */
    PImage bg;
    PImage light;
    PGraphics lightMask;
    
    void setup() {
      bg = loadImage("https://processing.org/reference/images/PImage.png");
      bg.resize(width, height);
      light = bg.copy();
      lightMask = createGraphics(width, height);
    }
    
    void draw() {
      background(0);
      image(bg, 0, 0);
      shadow();
      drawLight(mouseX, mouseY, 30, lightMask);
      light.mask(lightMask);
      image(light, 0, 0);
      drawPlayer();
    }
    
    void shadow() {
      pushStyle();
      noStroke();
      int step=16;
      for (int i=4; i<=step; i++) {
        fill(0, 64);
        rect(i*width/step, 0, width, height);
      }
      popStyle();
    }
    
    void drawLight(float x, float y, float radius, PGraphics pg) {
      pg.beginDraw();
      pg.noStroke();
      pg.fill(255);
      pg.background(0, 0);
      pg.ellipse(x, y, radius, radius);
      pg.endDraw();
    }
    
    void drawPlayer() {
      pushStyle();
      fill(0, 255, 0);
      ellipse(mouseX, mouseY, 10, 10);
      popStyle();
    }
    

    PlayerLight--screenshot

    These effects can also be used to create a looking-glass effect, e.g. for hidden object games.

    MaskToRevealHiddenImage

  • WOOOW :O THX VEEEERYYY MUCH :) :O

  • And how create more lights ? :/

  • drawLight(mouseX, mouseY, 30, lightMask);
    drawLight(mouseX, mouseY - 40, 30, lightMask);
    drawLight(80,80, 20, lightMask);
    
  • edited October 2017

    Not worked but background was restarting light... new code:

  • edited October 2017

    But how to make collision with other circle of lights ?

    PImage light;
    PGraphics lightMask;
    PGraphics pg;
    void setup() {
      size(500, 500);
      bg = loadImage("https://forum.processing.org/two/uploads/imageupload/549/SQQXW3DIWRN5.jpg");
      bg.resize(width, height);
      light = bg.copy();
      lightMask = createGraphics(width, height);
    }
    
    void draw() {
      background(0);
      image(bg, 0, 0);
      shadow();
      pg = lightMask;
      pg.beginDraw();
      pg.background(0, 0);
      drawLight(mouseX, mouseY, 158);
      drawLight(mouseX, mouseY - 40, 98);
      drawLight(400, 400, 100);
      pg.endDraw();
      light.mask(lightMask);
      image(light, 0, 0);
      drawPlayer();
    }
    
    void shadow() {
      pushStyle();
      noStroke();
      int step=16;
      for (int i=4; i<=step; i++) {
        fill(0, 64);
        rect(i*width/step, 0, width, height);
      }
      popStyle();
    }
    
    void drawLight(int x, int y, float radius) {
      pg.noStroke();
      pg.fill(255);
      int size = int(radius);
      for (int i=0; i<=size/2; i++) {
        pg.fill(0+i*255/size*2);
        pg.ellipse(x, y, size-i*2, size-i*2);
      }
    }
    
    void drawPlayer() {
      pushStyle();
      fill(0, 255, 0);
      ellipse(mouseX, mouseY, 10, 10);
      popStyle();
    }
    
  • What do you mean? Use more words.

    By collision, do you mean:

    http://www.jeffreythompson.org/collision-detection/circle-circle.php

  • when two lights collide it looks strange ... Try it :D

  • edited October 2017

    I don't know what you mean by "when two lights collide." It looks fine to me.

    Also, the code you posted is broken. Try it.

    Use more words! By more words, I mean that you should write more than ten words. Try twenty words, or thirty words.

    1. Define what you mean by "collide".
    2. Give examples -- what should it look like? What are you trying to accomplish?
    3. How does it look "strange"?
    4. What code did you use that makes it look "strange"?

    Explain.

  • PImage bg;
    PImage light, screen;
    PGraphics lightMask;
    PGraphics pg;
    void setup() {
      size(500, 500);
      bullets = new ArrayList<Bullet>();
      bg = loadImage("https://forum.processing.org/two/uploads/imageupload/549/SQQXW3DIWRN5.jpg");
      bg.resize(width, height);
      light = bg.copy();
      lightMask = createGraphics(width, height);
      bullets.add( new Bullet(400, 400, 58));
      bullets.add( new Bullet(300, 400, 199));
    }
    void draw() {
      println(frameRate);
      background(199);
      image(bg, 0, 0, width/2, height/2);
    
      screen = get(0, 0, width, height);
      shadow();
      pg = lightMask;
      pg.beginDraw();
      pg.background(0, 0);
      drawLight(mouseX, mouseY, 158);
      //drawLight(mouseX, mouseY - 40, 98);
      //drawLight(400, 400, 100);
      pg.endDraw();
      screen.mask(lightMask);
      image(screen, 0, 0);
      drawPlayer();
    }
    
    void shadow() {
      pushStyle();
      noStroke();
      int step=16;
      for (int i=4; i<=step; i++) {
        fill(0, 64);
        rect(i*width/step, 0, width, height);
      }
      popStyle();
    }
    
    void drawLight(int x, int y, float radius) {
      pg.noStroke();
      pg.fill(255);
      int size  = bullets.get(0).size;
      for (int i=0; i<=size/2; i++) {
        pg.fill(0+i*255/size*2);
        for (int c = bullets.size()-1; c >= 0; c--) {
          Bullet bullet = bullets.get(c);
          pg.ellipse(bullet.x, bullet.y, bullet.size-i*2, bullet.size-i*2);
        }
      }
    }
    
    void drawPlayer() {
      pushStyle();
      fill(0, 255, 0);
      ellipse(mouseX, mouseY, 10, 10);
      popStyle();
    }
    ArrayList<Bullet> bullets;
    class Bullet {
      int x, y, size;
      public Bullet(int x_, int y_, int size_) {
        x = x_;
        y = y_;
        size = size_;
      }
    }
    
  • Hah.

    If you want additive light (I guess), at the top of drawLight() add pg.blendMode(ADD);

    To understand why, read:

  • edited October 2017

    tests Good, but :D i take this code for create darkening circle of light and now not working :/

    CODE FOR CIRCLE:

    for (int i=0; i<=radius/2; i++) {
        pg.fill(0+i*255/radius*2);
        pg.ellipse(x, y, radius-i*2, radius-i*2);
      }
    
  • PImage bg;
    PImage light, screen;
    PGraphics lightMask;
    PGraphics pg;
    void setup() {
      size(500, 500);
      bullets = new ArrayList<Bullet>();
      bg = loadImage("https://forum.processing.org/two/uploads/imageupload/549/SQQXW3DIWRN5.jpg");
      bg.resize(width, height);
      light = bg.copy();
      lightMask = createGraphics(width, height);
      bullets.add( new Bullet(400, 400, 58));
      bullets.add( new Bullet(300, 400, 199));
    }
    void draw() {
      println(frameRate);
      background(199);
      image(bg, 0, 0, width/2, height/2);
    
      screen = get(0, 0, width, height);
      shadow();
      pg = lightMask;
      pg.beginDraw();
      pg.background(0, 0);
      pg.blendMode(ADD);
      drawLight(mouseX, mouseY, 158);
      drawLight(mouseX, mouseY - 40, 98);
      drawLight(400, 400, 100);
      pg.endDraw();
      //lightMask.tint(0,255,0);
      screen.mask(lightMask);
      image(screen, 0, 0);
      drawPlayer();
    }
    
    void shadow() {
      pushStyle();
      noStroke();
      int step=16;
      for (int i=4; i<=step; i++) {
        fill(0, 64);
        rect(i*width/step, 0, width, height);
      }
      popStyle();
    }
    
    void drawLight(int x, int y, int radius) {
      pg.noStroke();
      //pg.fill(255);
      for (int i=0; i<=radius/2; i++) {
        //pg.fill(0+i*255/radius*2);
        pg.fill(1);
        pg.ellipse(x, y, radius-i*2, radius-i*2);
      }
    }
    
    void drawPlayer() {
      pushStyle();
      fill(0, 255, 0);
      ellipse(mouseX, mouseY, 10, 10);
      popStyle();
    }
    ArrayList<Bullet> bullets;
    class Bullet {
      int x, y, size;
      public Bullet(int x_, int y_, int size_) {
        x = x_;
        y = y_;
        size = size_;
      }
    }
    

    NICE !!! I HAVE IT :D can i make color of light ? plsss :) :D

  • PImage bg;
    PImage light, screen;
    PGraphics lightMask;
    PGraphics pg;
    void setup() {
      size(500, 500);
      bullets = new ArrayList<Bullet>();
      bg = loadImage("https://" + "forum.processing.org/two/uploads/imageupload/549/SQQXW3DIWRN5.jpg");
      bg.resize(width/2, height/2);
      light = bg.copy();
      lightMask = createGraphics(width, height);
      bullets.add( new Bullet(400, 400, 58));
      bullets.add( new Bullet(300, 400, 199));
    }
    void draw() {
      println(frameRate);
      background(199);
      image(bg, 0, 0);
    
      screen = get(0, 0, width, height);
      shadow();
      pg = lightMask;
      pg.beginDraw();
      pg.background(0, 0);
      pg.blendMode(ADD);
      drawLight(mouseX, mouseY-300, 200, LIGHTEST, 96, 10);
      drawLight(mouseX, mouseY-200, 200, LIGHTEST, 128, 10);
      drawLight(mouseX, mouseY-100, 200, LIGHTEST, 255, 10);
      drawLight(mouseX, mouseY, 158, LIGHTEST, 255, 6);
      drawLight(400, 200, 100, LIGHTEST, 96, 6);
      pg.endDraw();
      screen.mask(lightMask);
      image(screen, 0, 0);
      drawPlayer();
    }
    
    void shadow() {
      pushStyle();
      noStroke();
      int step=16;
      for (int i=4; i<=step; i++) {
        fill(0, 64);
        rect(i*width/step, 0, width, height);
      }
      popStyle();
    }
    
    
    void drawLight(int x, int y, int radius, int mode, int brightness, int resolution) {
      pg.noStroke();
      pg.blendMode(mode);
      for (int i=radius; i>0; i=i-resolution) {
        pg.fill(255, brightness*(radius-i+1)/radius);
        pg.ellipse(x, y, i, i);
      }
    }
    
    void drawPlayer() {
      pushStyle();
      fill(0, 255, 0);
      ellipse(mouseX, mouseY, 10, 10);
      popStyle();
    }
    ArrayList<Bullet> bullets;
    class Bullet {
      int x, y, size;
      public Bullet(int x_, int y_, int size_) {
        x = x_;
        y = y_;
        size = size_;
      }
    }
    

    To color tint the masked image before drawing it:

    pushStyle();
      tint(255,0,0);
      image(screen, 0, 0);
    popStyle();
    
  • edited October 2017

    testImage

    VERY NICE :O THX A LOT !

  • edited October 2017
    PImage light, screen, bg;
    PGraphics pg, lightMask;
    boolean lights;
    int x;
    color randomColor;
    void setup() {
      size(480, 270);
      frameRate(60);
      bg = loadImage( "https://ichef.bbci.co.uk/images/ic/480xn/p01lckx1.jpg" );
      bg.resize(width, height);
      light = bg.copy();
      lightMask = createGraphics(width, height);
      randomColor = color(random(256), random(256), random(256));
    }
    void draw() {
      background(199);
      image(bg, 0, 0);
      screen = get(0, 0, width, height);
    
      fill(0, 250);
      noStroke();
      rect(0, 0, width, height);
      pg = lightMask;
      pg.beginDraw();
      pg.background(0, 0);
      pg.blendMode(ADD);
      pg.noStroke();
      drawLight(x, height/2, x/2);
      x+=3;
      if (x>=width) {
        x=0;
        randomColor = color(random(256), random(256), random(256));
      }
      pg.endDraw();
      screen.mask(lightMask);
      pushStyle();
      tint(randomColor);
      image(screen, 0, 0);
      popStyle();
      fill(255, 255, 0);
      textAlign(LEFT, TOP);
      textSize(39);
      text(int(frameRate) + " FPS", 5, 5);
      textAlign(LEFT, BOTTOM);
      textSize(10);
      fill(255);
      text("Press key \"L\" to lights rendering smooth or fast.", 5, height-5);
      fill(randomColor);
      noStroke();
      rect(width-35, height-35, 30, 30);
    }
    void drawLight(int x, int y, float radius) {
      for (int i=0; i<=radius/2; i++) {
        pg.fill(2);
        if (!lights) {
          pg.fill(50);
          radius = radius/1.2;
        }
        pg.ellipse(x, y, radius-i*2, radius-i*2);
        if (!lights) {
          i=int(radius/2);
        }
      }
    }
    void keyPressed() {
      if (key == 'l' || key == 'L') {
        if (lights) {
          lights = false;
        } else {
          lights = true;
        }
      }
    }
    
  • edited October 2017 Answer ✓

    Looks good. Good luck!

    Also, I see you corrected it from earlier, but remember:

    If you care about FPS, DON'T do this:

    image(bg, 0, 0, width/2, height/2);
    

    The five-argument form of image() is extremely slow. Instead use .resize() once in setup, then use it with:

    image(bg, 0, 0);
    
  • And how to create more fps ? :D but i have only 20... or more down.. :/

  • I dont no where is problem...

  • Why dont working image ?

    PImage light, screen, bg, lightImage;
    PGraphics pg, lightMask;
    boolean lights;
    int x;
    color randomColor;
    void setup() {
      size(480, 270);
      frameRate(60);
      background(0);
      bg = loadImage("https://ichef.bbci.co.uk/images/ic/480xn/p01lckx1.jpg");
      lightImage = loadImage("https://i.stack.imgur.com/NaD6F.png");
      bg.resize(width, height);
      light = bg.copy();
      lightMask = createGraphics(width, height);
      randomColor = color(random(256), random(256), random(256));
    }
    void draw() {
      background(199);
      image(bg, 0, 0);
      screen = get(0, 0, width, height);
      fill(0, 250);
      noStroke();
      rect(0, 0, width, height);
      pg = lightMask;
      pg.beginDraw();
      pg.background(0, 0);
      //pg.blendMode(ADD);
      //pg.noStroke();
      drawLight(x, height/2, x/2);
      x+=3;
      if (x>=width) {
        x=0;
        randomColor = color(random(256), random(256), random(256));
      }
      pg.endDraw();
      screen.mask(lightMask);
      pushStyle();
      tint(randomColor);
      image(screen, 0, 0);
      popStyle();
      fill(255, 255, 0);
      textAlign(LEFT, TOP);
      textSize(39);
      text(int(frameRate) + " FPS", 5, 5);
      textAlign(LEFT, BOTTOM);
      textSize(10);
      fill(255);
      text("Press key \"L\" to lights rendering smooth or fast.", 5, height-5);
      fill(randomColor);
      noStroke();
      rect(width-35, height-35, 30, 30);
    }
    void drawLight(int x, int y, int radius) {
      /*for (int i=0; i<=radius/2; i++) {
       pg.fill(2);
       if (!lights) {
       pg.fill(50);
       radius = radius/1.2;
       }
       pg.ellipse(x, y, radius-i*2, radius-i*2);
       if (!lights) {
       i=int(radius/2);
       }
       }*/
      //pg.ellipse(x, y, radius, radius);
      if (radius>0) {
        println(x/2);
        lightImage.resize(radius, radius);
        pg.imageMode(CENTER);
        pg.image(lightImage, x, y);
      }
    }
    void keyPressed() {
      if (key == 'l' || key == 'L') {
        if (lights) {
          lights = false;
        } else {
          lights = true;
        }
      }
    }
    
  • edited October 2017 Answer ✓
    1. For more speed, don't call resize every frame. Very slow.

      lightImage.resize(radius, radius); // don't do this every frame!
      
    2. For pasting code into and out of the forum, break urls into 2 strings:

      bg = loadImage("https:" + "//ichef.bbci.co.uk/images/ic/480xn/p01lckx1.jpg");
      lightImage = loadImage("https:" + "//i.stack.imgur.com/NaD6F.png");
      
  • How to make colored lights ? Every light have own colors... Can it works?

  • How create more colors of lights ?

  • WHERE IS THE PROBLEM ?

    PImage light, screen, bg, lightImage, mask;
    PGraphics pg, lightMask;
    int up, down, right, left;
    float x, y, speed = 1;
    color randomColor;
    float camX=0, camY=0;
    float  Ox1, Ox2, Oy1, Oy2;
    int globalMX, globalMY;
    void setup() {
      size(480, 270, P3D);
      frameRate(60);
      background(0);
      bg = loadImage("https://ichef.bbci.co.uk/images/ic/480xn/p01lckx1.jpg");
      lightImage = loadImage("https://i.stack.imgur.com/NaD6F.png");
      bg.resize(width, height);
      light = bg.copy();
      lightMask = createGraphics(width, height);
      randomColor = color(random(256), random(256), random(256));
      bullets = new ArrayList<Bullet>();
      reloadLights();
      x = width/2;
      y = height/2;
    }
    void draw() {  
      background(0);
      x += (right - left) * speed;
      y += (down - up) * speed;
      Ox1=camX-width+x;
      Ox2=camX+x;
      Oy1=camY-y;
      Oy2=camY+height-y;
      ortho(Ox1, Ox2, Oy1, Oy2);
      println(x + "  " + y);
      imageMode(CORNER);
      image(bg, 0, 0);
      pushMatrix();
      translate(x,y);
      screen = get(0, 0, width, height);
      popMatrix(); 
      fill(0, 125);
      noStroke();
      rectMode(CENTER);
      rect(x, y, width, height);
      screen.mask(lightMask);
      image(screen, 0,0);
      fill(255, 255, 0);
      textAlign(LEFT, TOP);
      textSize(39);
      text(int(frameRate) + " FPS", 5, 5);
      ellipse(globalMX,globalMY,20,20);
      //popMatrix();
    }
    void reloadLights() {
      pg = lightMask;
      pg.beginDraw();
      pg.background(0);
      pg.blendMode(ADD);
      for (int i = bullets.size()-1; i >= 0; i--) {
        Bullet bullet = bullets.get(i);
        drawLight(bullet.x, bullet.y, bullet.r);
      }
      //mask = pg;
      pg.endDraw();
    }
    void drawLight(int xL, int yL, int rL) {
     // pushMatrix();
     // translate(x,y);
      pg.imageMode(CENTER);
      pg.image(lightImage, xL,yL, rL, rL);
      //popMatrix();
    }
    
    void mousePressed() {
      bullets.add( new Bullet(globalMX, globalMY, 50));
      reloadLights();
    }
    ArrayList<Bullet> bullets;
    class Bullet {
      int x, y, r;
      public Bullet(int x_, int y_, int r_) {
        x = x_;
        y = y_;
        r = r_;
      }
    }
    void keyPressed() {
      if (key == 'a' || key == 'A') {
        left = 1;
      }
      if (key == 'd' || key == 'D') {
        right = 1;
      }
      if (key == 'w' || key == 'W') {
        up = 1;
      }
      if (key == 's' || key == 'S') {
        down = 1;
      }
    }
    void keyReleased() {
      if (key == 'a' || key == 'A') {
        left = 0;
      }
      if (key == 'd' || key == 'D') {
        right = 0;
      }
      if (key == 'w' || key=='W') {
        up = 0;
      }
      if (key == 's' || key == 'S') {
        down = 0;
      }
    }
    void mouseMoved() {
      globalMX=mouseX;
      globalMY=mouseY;
    }
    

    wtf

Sign In or Register to comment.