/** * Copyright 2008 - 2011 * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. * * @project loon * @author cping * @email:javachenpeng@yahoo.com * @version 0.1 */ package loon.opengl.light; import loon.LSystem; import loon.canvas.LColor; import loon.utils.TArray; public abstract class LLight { protected LColor[] colors; // 图层光源是否被开启 protected boolean lightingOn; protected boolean colouredLights; protected boolean isLightDirty; // 图层光源 protected float[][][] lightValue; // 光源集合 protected TArray<Light> lights = new TArray<Light>(); // 默认的主控光源 protected Light mainLight; private int width; private int height; public static Light create(float x, float y, float str) { return new Light(x, y, str); } protected void maxLightSize(int width, int height) { this.width = width; this.height = height; } public void setColor(int corner, float r, float g, float b, float a) { if (colors == null) { colors = new LColor[] { new LColor(1, 1, 1, 1f), new LColor(1, 1, 1, 1f), new LColor(1, 1, 1, 1f), new LColor(1, 1, 1, 1f) }; } colors[corner].r = r; colors[corner].g = g; colors[corner].b = b; colors[corner].a = a; } /** * 设定地图光影颜色 * * @param image * @param x * @param y */ public void setLightColor(int x, int y) { if (x < width && y < height) { setColor(0, lightValue[x][y][0], lightValue[x][y][1], lightValue[x][y][2], 1); setColor(1, lightValue[x + 1][y][0], lightValue[x + 1][y][1], lightValue[x + 1][y][2], 1); setColor(2, lightValue[x + 1][y + 1][0], lightValue[x + 1][y + 1][1], lightValue[x + 1][y + 1][2], 1); setColor(3, lightValue[x][y + 1][0], lightValue[x][y + 1][1], lightValue[x][y + 1][2], 1); isLightDirty = true; } } private void createLight() { if (lightValue == null) { lightValue = new float[width + 1][height + 1][3]; } lights.clear(); if (mainLight != null) { lights.add(mainLight); } updateLight(); } public void setMainLight(Light l) { this.mainLight = l; this.isLightDirty = true; } public Light getMainLight() { return mainLight; } public void addLight(Light l) { if (l != null) { this.lights.add(l); this.isLightDirty = true; } } public void removeLight(Light l) { if (l != null) { this.lights.remove(l); this.isLightDirty = true; } } public void setLight(boolean l) { if (lightValue == null && l) { createLight(); } this.lightingOn = l; if (!l) { colors = null; } } public boolean isLight() { return lightingOn; } public void clearLight() { if (lights != null) { this.lights.clear(); this.isLightDirty = true; } } public void updateLight() { if (mainLight == null) { throw LSystem.runThrow("the main light is null !"); } for (int y = 0; y < height + 1; y++) { for (int x = 0; x < width + 1; x++) { for (int component = 0; component < 3; component++) { lightValue[x][y][component] = 0; } for (int i = 0; i < lights.size; i++) { float[] effect = (lights.get(i)).getEffectAt(x, y, colouredLights); for (int component = 0; component < 3; component++) { lightValue[x][y][component] += effect[component]; } } for (int component = 0; component < 3; component++) { if (lightValue[x][y][component] > 1) { lightValue[x][y][component] = 1; } } } } this.isLightDirty = true; } // 地图光源用类 public static class Light { private float xpos; private float ypos; private float strength; private LColor color; public Light(float x, float y, float str, LColor col) { this.xpos = x; this.ypos = y; this.strength = str; this.color = col; } public Light(float x, float y, float str) { this(x, y, str, null); } public void setLocation(float x, float y) { xpos = x; ypos = y; } public float[] getEffectAt(float x, float y, boolean colouredLights) { float dx = (x - xpos); float dy = (y - ypos); float distance2 = (dx * dx) + (dy * dy); float effect = 1 - (distance2 / (strength * strength)); if (effect < 0) { effect = 0; } if (colouredLights) { return new float[] { color.r * effect, color.g * effect, color.b * effect }; } else { return new float[] { effect, effect, effect }; } } } }