Package it.marteEngine.game.starcleaner

Source Code of it.marteEngine.game.starcleaner.LightMap

package it.marteEngine.game.starcleaner;

import it.marteEngine.ME;
import it.marteEngine.entity.Entity;

import java.util.ArrayList;

import org.newdawn.slick.Color;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Image;
import org.newdawn.slick.ImageBuffer;
import org.newdawn.slick.SlickException;

public class LightMap extends Entity {

  public static final int DAWN = 0;
  public static final int DAY = 4;
  public static final int EVENING = 16;
  public static final int NIGHT = 20;
  public static final int ENDOFDAY = 29;

  // dawn is between 0 and 4 (5 seconds), day is between 5 and 14, evening
  // between 15 and 19 and night between 20 and 29
  private int dayTime = 12; // we'll start with late morning
  private int incrDayTime = 1000; // increment daytime every second
  private int counterDayTime = 0;

  private int dawnCounter = 0;
  private int dawnSpan = 0;

  private boolean colouredLights = true;

  private Image whiteSquare;

  private ArrayList<Light> lights = new ArrayList<Light>();
  /**
   * The values calculated for each vertex of the tile map, note how it's one
   * more to account for the bottom corner of the map. The 3 dimension is for
   * colour components (red, green, blue) used for coloured lighting
   */
  private float[][][] roughLightValues;
  private float[][][] smoothLightValues;

  private int mapWidth, mapHeight, mapTileSize;

  public LightMap(float x, float y, int tilesize) {
    super(x, y);
    mapTileSize = tilesize;
    mapWidth = StarCleaner.WIDTH / tilesize;
    mapHeight = StarCleaner.HEIGHT / tilesize;
    roughLightValues = new float[mapWidth + 1][mapHeight + 1][4];
    smoothLightValues = new float[mapWidth + 1][mapHeight + 1][4];
    depth = 250; // lightmap is on top of all of them, but below the blender
    whiteSquare = createImage(tilesize);
  }

  private Image createImage(int tilesize) {
    ImageBuffer buf = new ImageBuffer(tilesize, tilesize);
    for (int x = 0; x < tilesize; x++)
      for (int y = 0; y < tilesize; y++)
        buf.setRGBA(x, y, 255, 255, 255, 255);
    return buf.getImage();
  }

  public void update(GameContainer container, int delta)
      throws SlickException {
    counterDayTime += delta;
    if (counterDayTime >= incrDayTime) {
      counterDayTime -= incrDayTime;
      dayTime++;
      if (dayTime > ENDOFDAY)
        dayTime = 0;
    }
    updateLightMap(delta);
  }

  // do nothing during day time
  public void updateLightMap(int delta) {
    boolean dawn = false;
    // Log.debug("updateLightMap() is called, dayTime is " + dayTime);
    if (dayTime >= DAWN && dayTime < DAY) {
      dawn = fillLightMap(delta, -1, DAY - DAWN);
      if (!dawn)
        return;
    } else if (dayTime >= EVENING && dayTime < NIGHT) {
      dawn = fillLightMap(delta, 1, NIGHT - EVENING);
    }
    // for every vertex on the map (notice the +1 again accounting for the
    // trailing vertex)
    for (int y = 0; y < mapHeight + 1; y++) {
      for (int x = 0; x < mapWidth + 1; x++) {
        // first reset the lighting value for each component (red,
        // green, blue, alpha)
        if (!dawn) {
          for (int component = 0; component < 4; component++) {
            roughLightValues[x][y][component] = 0;
          }
        }

        // next cycle through all the lights. Ask each light how much
        // effect
        // it'll have on the current vertex. Combine this value with the
        // currently
        // existing value for the vertex. This lets us blend coloured
        // lighting and
        // brightness
        for (int i = 0; i < lights.size(); i++) {
          float[] effect = ((Light) lights.get(i)).getEffectAt(x
              * mapTileSize, y * mapTileSize, colouredLights);
          // if (effect[0] != 0 || effect[1] != 0 || effect[2] != 0)
          // Log.debug("Light " + i + ": x = " + x + ", y = " + y +
          // ", effect[0]-[3]=" + effect[0] + ", " + effect[1] + ", "
          // + effect[2] + ", " + effect[3]);
          for (int component = 0; component < 3; component++) {
            roughLightValues[x][y][component] += effect[component];
          }
          // alpha value is treated different, not added but the min
          // value wins
          if (effect[3] > 0)
            if (roughLightValues[x][y][3] > 0)
              roughLightValues[x][y][3] = Math.min(effect[3],
                  roughLightValues[x][y][3]);
            else
              roughLightValues[x][y][3] = effect[3];
        }

        // finally clamp the components to 1, since we don't want to
        // blow up over the colour values
        for (int component = 0; component < 4; component++) {
          if (roughLightValues[x][y][component] > 1) {
            roughLightValues[x][y][component] = 1;
          }
        }
      }
    }

    // smooth the light map
    float smooth = 1 / 9f;
    for (int x = 0; x < mapWidth + 1; x++) {
      for (int y = 0; y < mapHeight + 1; y++) {
        for (int i = 0; i < 3; i++) {
          smoothLightValues[x][y][i] = 0;
          for (int a = -1; a < 2; a++) {
            for (int b = -1; b < 2; b++) {
              if ((x + a) >= 0 && (y + b) >= 0
                  && (x + a) < mapWidth + 1
                  && (y + b) < mapHeight + 1)
                smoothLightValues[x][y][i] += (roughLightValues[x
                    + a][y + b][i] * smooth);
            }
          }
        }
        smoothLightValues[x][y][3] = roughLightValues[x][y][3];
      }
    }
  }

  private boolean fillLightMap(int delta, int multiplier, int rangeInSeconds) {
    // Log.debug("fillLightMap() is called, dayTime is " + dayTime +
    // ", value is " + value + ", range is " + range);

    if (this.dawnSpan == 0) {
      this.dawnSpan = rangeInSeconds * 1000;
      if (multiplier == 1)
        this.dawnCounter = 0;
      else
        this.dawnCounter = this.dawnSpan;
    }
    this.dawnCounter += (delta * multiplier);
    float greyVal = 0.0f;
    if (this.dawnCounter <= 0) {
      this.dawnSpan = 0;
      this.dawnCounter = 0;
      return false;
      // greyVal = 1.0f;
    } else if (this.dawnCounter >= this.dawnSpan) {
      this.dawnSpan = 0;
      this.dawnCounter = 0;
      return false;
      // greyVal = 0.0f;
    } else
      greyVal = ((float) this.dawnCounter) / ((float) this.dawnSpan);

    for (int y = 0; y < mapHeight + 1; y++) {
      for (int x = 0; x < mapWidth + 1; x++) {
        // first reset the lighting value for each component (red,
        // green, blue, alpha)
        for (int component = 0; component < 3; component++) {
          // lightValues[x][y][component] = 0;
          roughLightValues[x][y][component] = 0;
        }
        // lightValues[x][y][3] = greyVal;
        roughLightValues[x][y][3] = greyVal;
      }
    }
    return true;
  }

  public void render(GameContainer container, Graphics g)
      throws SlickException {
    super.render(container, g);
    if (dayTime >= EVENING || dayTime < DAY) {
      // only during dawn, evening and night do we have some work to do.
      for (int y = 0; y < mapHeight; y++) {
        for (int x = 0; x < mapWidth; x++) {
          g.setColor(Color.white);
          // if lighting is on apply the lighting values we've
          // calculated for each vertex to the image. We can apply
          // colour components here as well as just a single value.
          whiteSquare.setColor(Image.TOP_LEFT,
              smoothLightValues[x][y][0],
              smoothLightValues[x][y][1],
              smoothLightValues[x][y][2],
              smoothLightValues[x][y][3]);
          whiteSquare.setColor(Image.TOP_RIGHT,
              smoothLightValues[x + 1][y][0],
              smoothLightValues[x + 1][y][1],
              smoothLightValues[x + 1][y][2],
              smoothLightValues[x + 1][y][3]);
          whiteSquare.setColor(Image.BOTTOM_RIGHT,
              smoothLightValues[x + 1][y + 1][0],
              smoothLightValues[x + 1][y + 1][1],
              smoothLightValues[x + 1][y + 1][2],
              smoothLightValues[x + 1][y + 1][3]);
          whiteSquare.setColor(Image.BOTTOM_LEFT,
              smoothLightValues[x][y + 1][0],
              smoothLightValues[x][y + 1][1],
              smoothLightValues[x][y + 1][2],
              smoothLightValues[x][y + 1][3]);
          // draw the image with it's newly declared vertex colours
          // to the display
          whiteSquare.draw(x * mapTileSize, y * mapTileSize,
              mapTileSize, mapTileSize);
        }
      }
    }
    if (ME.debugEnabled) {
      g.setColor(Color.white);
      g.drawString("Lights: " + lights.size(),
          container.getWidth() - 110, 100);
      g.drawString("dayTime: " + dayTime, container.getWidth() - 110, 120);
    }
  }

  public int getDayTime() {
    return dayTime;
  }

  public void setDayTime(int newDayTime) {
    dayTime = newDayTime;
  }

  public boolean isDay() {
    if (dayTime >= DAWN && dayTime < NIGHT)
      return true;
    return false;
  }

  public boolean isNight() {
    if (dayTime >= NIGHT || dayTime < DAWN)
      return true;
    return false;
  }

  public void addLight(Light light) {
    light.setLightMap(this);
    lights.add(light);

  }

  public void removeLight(Light light) {
    lights.remove(light);
  }

}
TOP

Related Classes of it.marteEngine.game.starcleaner.LightMap

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.