packageslicktests;
importjava.util.ArrayList;
importjava.util.List;
importjava.util.Random;
importorg.newdawn.slick.AppGameContainer;
importorg.newdawn.slick.BasicGame;
importorg.newdawn.slick.Color;
importorg.newdawn.slick.GameContainer;
importorg.newdawn.slick.Graphics;
importorg.newdawn.slick.Image;
importorg.newdawn.slick.Input;
importorg.newdawn.slick.SlickException;
publicclassLightingTestAlphaextendsBasicGame {
//number of tiles in our simple horizontal sprite sheet
publicstaticfinalintTILE_COUNT = 5;
//width/height of tile in pixels
publicstaticfinalintTILE_SIZE = 40;
//size of alpha map (for use with sprite sheet)
publicstaticfinalintALPHA_MAP_SIZE = 256;
//space after tile, before next tile
publicstaticfinalintTILE_SPACING = 2;
//the "sprite sheet" or texture atlas image
privateImagespriteSheet;
//the sub-images of our sprite sheet
privateImage[] tileSprites;
//our 2D map array
privateImage[][] tileMap;
//map size in tiles
privateintmapWidth, mapHeight;
//our alpha map image; just a feathered black circle on a transparent background
privateImagealphaMap;
privateRandomrandom = newRandom();
//our lights
privateList<Light> lights = newArrayList<Light>();
//a timer used for simple light scaling effect
privatelongelapsed;
//a shared instance of Color so we don't need to create a new one each frame
privateColorsharedColor = newColor(1f, 1f, 1f, 1f);
/** Describes a single point light. */publicstaticclassLight {
/** The position of the light */floatx, y;
/** The RGB tint of the light, alpha is ignored */Colortint;
/** The alpha value of the light, default 1.0 (100%) */floatalpha;
/** The amount to scale the light (use 1.0 for default size). */privatefloatscale;
//original scale
privatefloatscaleOrig;
publicLight(floatx, floaty, floatscale, Colortint) {
this.x = x;
this.y = y;
this.scale = scaleOrig = scale;
this.alpha = 1f;
this.tint = tint;
}
publicLight(floatx, floaty, floatscale) {
this(x, y, scale, Color.white);
}
publicvoidupdate(floattime) {
//effect: scale the light slowly using a sin func
scale = scaleOrig + 1f + .5f*(float)Math.sin(time);
}
}
publicLightingTestAlpha() {
super("Alpha Map Lighting");
}
publicvoidinit(GameContainercontainer) throwsSlickException {
// container.setVSync(true);
container.setTargetFrameRate(60);
//To reduce texture binds, our alpha map and tilesheet will be in the same texture
//Most games will implement their own SpriteSheet class, but for simplicity's sake:
//map tiles are in a horizontal row starting at (0, 0)
//alpha map is located below the tiles, at (0, TILE_SIZE+TILE_SPACING)
spriteSheet = newImage("res/lighting/lighting_sprites.png", false, Image.FILTER_NEAREST);
//grab the tiles
tileSprites = newImage[TILE_COUNT];
for (inti = 0; i < tileSprites.length; i++) {
tileSprites[i] = spriteSheet.getSubImage(i * (TILE_SIZE + TILE_SPACING), 0, TILE_SIZE, TILE_SIZE);
}
//grab the alpha map
alphaMap = spriteSheet.getSubImage(0, TILE_SIZE + TILE_SPACING, ALPHA_MAP_SIZE, ALPHA_MAP_SIZE);
//randomize our map
randomize(container);
//reset the lighting
resetLights(container);
}
ImagerandomTile() {
intr = random.nextInt(100);
if (r < 5)
returntileSprites[1 + random.nextInt(4) ];
elsereturntileSprites[0];
}
voidrandomize(GameContainercontainer) {
// create the map
mapWidth = container.getWidth() / TILE_SIZE + 1;
mapHeight = container.getHeight() / TILE_SIZE + 1;
tileMap = newImage[mapWidth][mapHeight];
for (intx = 0; x < mapWidth; x++) {
for (inty = 0; y < mapHeight; y++) {
tileMap[x][y] = randomTile();
}
}
}
publicvoidresetLights(GameContainercontainer) {
//clear the lights and add a new one with default scale
lights.clear();
lights.add(newLight(container.getInput().getMouseX(), container.getInput().getMouseY(), 1f));
}
publicvoidrender(GameContainercontainer, Graphicsg)
throwsSlickException {
//each light requires a new pass to blend with the previous lights
//FPS will be affected with too many lights at once
for (inti=0; i<lights.size(); i++) {
Lightlight = lights.get(i);
//set up our alpha map for the light
g.setDrawMode(Graphics.MODE_ALPHA_MAP);
//clear the alpha map before we draw to it...
g.clearAlphaMap();
intalphaW = (int)(alphaMap.getWidth() * light.scale);
intalphaH = (int)(alphaMap.getHeight() * light.scale);
intalphaX = (int)(light.x - alphaW/2f);
intalphaY = (int)(light.y - alphaH/2f);
//we apply the light alpha here; RGB will be ignored
sharedColor.a = light.alpha;
//draw the alpha map
alphaMap.draw(alphaX, alphaY, alphaW, alphaH);
//start blending in our tiles
g.setDrawMode(Graphics.MODE_ALPHA_BLEND);
//we'll clip to the alpha rectangle, since anything outside of it will be transparent
g.setClip(alphaX, alphaY, alphaW, alphaH);
//we'll use startUse/drawEmbedded/endUse for efficiency
spriteSheet.startUse();
//after startUse, we can apply a new tint like so..
//since we're in MODE_ALPHA_BLEND, the alpha value will be ignored (hence applying it above)
light.tint.bind();
for (intx = 0; x < mapWidth; x++) {
for (inty = 0; y < mapHeight; y++) {
tileMap[x][y].drawEmbedded(x * TILE_SIZE, y * TILE_SIZE, TILE_SIZE, TILE_SIZE);
}
}
spriteSheet.endUse();
g.clearClip();
}
//reset the mode to normal before continuing..
g.setDrawMode(Graphics.MODE_NORMAL);
g.setColor(Color.white);
g.drawString("Mouse click to add a light (total count: "+lights.size()+")", 10, 25);
g.drawString("Press R to randomize the map tiles", 10, 40);
g.drawString("Press SPACE to reset the lights", 10, 55);
}
publicvoidupdate(GameContainercontainer, intdelta)
throwsSlickException {
if (container.getInput().isKeyPressed(Input.KEY_R))
randomize(container);
if (container.getInput().isKeyPressed(Input.KEY_SPACE)) {
resetLights(container);
}
elapsed += delta;
//update all lights to have them smoothly scale
for (inti=0; i<lights.size(); i++) {
lights.get(i).update(elapsed / 1000f);
}
//the last-added light will be the one under the mouse
if (lights.size()>0) {
Lightl = lights.get(lights.size()-1);
l.x = container.getInput().getMouseX();
l.y = container.getInput().getMouseY();
}
}
//adds a new light
publicvoidmousePressed(intbutton, intx, inty) {
floatrandSize = random.nextInt(15)*.1f+.5f;
ColorrandColor = newColor(random.nextFloat(), random.nextFloat(), random.nextFloat());
lights.add(newLight(x, y, randSize, randColor));
}
publicstaticvoidmain(String[] args) {
try {
newAppGameContainer(newLightingTestAlpha(), 800, 600, false).start();
} catch (SlickExceptione) {
e.printStackTrace();
}
}
}
Special syntax:
To highlight a line (yellow background), prefix it with '@@'
To indicate that a line should be removed (red background), prefix it with '-'
To indicate that a line should be added (green background), prefix it with '+'
To post multiple snippets, seperate them by '~~~~'