package sg.atom2d.tools.map;
import java.awt.*;
import java.util.*;
import java.net.*;
import java.io.*;
/**
* this class was originally meant to simply hold a reference to a map and a
* collection of sprites, which it delegated all the work to in the logic and
* render methods of these objects...<p>
*
* so it is reasonably fitting that this class also manage the loading of the
* maps and sprites it uses from files or URLs.<p>
*
* Each scene consists of a Map, and a collection of sprites, as intended, but
* may also be loaded or saved.
*/
public class Scene {
int offsetX = 0;
int offsetY = 0;
float effect_rScale = 1;
float effect_gScale = 1;
float effect_bScale = 1;
float effect_hue = 0;
float effect_sat = 1;
Map map;
ArrayList sprites;
GraphicsBank tileset;
/**
* creates a scene using the given map and sprites.
*/
public Scene(Map m, ArrayList s, GraphicsBank gfx) {
this.map = m;
sprites = s;
this.tileset = gfx;
}
/* Create a new empty scene */
public Scene() {
map = new Map(10, 10, 32, 32);
tileset = new GraphicsBank();
}
public GraphicsBank getTileset() {
return tileset;
}
public void setTileset(GraphicsBank gfx) {
tileset = gfx;
map.setTileset(gfx);
}
/**
* loads a scene from the given URL. takes tiles from the given
* GraphicsBank.
*/
static Scene loadScene(File f) throws IOException {
boolean hasColourEffect = false;
float r = 1;
float g = 1;
float b = 1;
float h = 0;
float s = 1;
BufferedReader reader = new BufferedReader(new FileReader(f));
String line = reader.readLine();
StringTokenizer tokens = new StringTokenizer(line);
int width = Integer.parseInt(tokens.nextToken());
int height = Integer.parseInt(tokens.nextToken());
String tileset = tokens.nextToken();
GraphicsBank gfx = new GraphicsBank();
System.out.println("Attempt to load tileset " + tileset);
System.out.println("Working path is " + f.getParentFile());
File ts = new File(f.getParentFile(), tileset);
System.out.println("Attempt to load tileset " + ts.getAbsoluteFile());
gfx.loadTileset(ts);
Map map = new Map(width, height);
line = reader.readLine();
tokens = new StringTokenizer(line);
if (tokens.nextToken().equalsIgnoreCase("colorization")) {
hasColourEffect = true;
r = Float.parseFloat(tokens.nextToken());
g = Float.parseFloat(tokens.nextToken());
b = Float.parseFloat(tokens.nextToken());
h = Float.parseFloat(tokens.nextToken());
s = Float.parseFloat(tokens.nextToken());
}
while (!line.equals(".")) {
line = reader.readLine();
}
for (int z = 0; z < 3; z++) {
line = reader.readLine();
tokens = new StringTokenizer(line);
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
String code = tokens.nextToken();
map.setTile(x, y, z, gfx.getTile(Integer.parseInt(code)));
}
}
}
reader.close();
Scene scene = new Scene(map, new ArrayList(), gfx);
scene.tileset = gfx;
if (hasColourEffect) {
System.out.println("Calling setEffect on scene recently loaded.");
scene.setEffect(r, g, b, h, s, 1f);
}
return scene;
}
static Scene loadScene(String filename) throws IOException {
Scene scene = loadScene(new File(filename));
return scene;
}
/**
* writes the map only (at the moment) to a file.
*/
public void saveScene(File file) {
if (tileset.isUnsaved()) {
throw new RuntimeException("Tileset is unsaved. Cannot save the scene");
}
try {
PrintWriter writer = new PrintWriter(new BufferedWriter(new FileWriter(file)));
String line = "";
int width = map.getWidth();
int height = map.getHeight();
File wd = new File(file.getParentFile().getCanonicalFile().toString());
File ts = new File(tileset.getFile().getCanonicalFile().toString());
String relativePath = RelativePath.getRelativePath(wd, ts);
line = width + " " + height + " " + relativePath;
writer.println(line);
line = "colorization " + effect_rScale
+ " " + effect_gScale
+ " " + effect_bScale
+ " " + effect_hue
+ " " + effect_sat;
writer.println(line);
System.out.println("Colorization red in save is " + effect_rScale);
writer.println(".");
for (int z = 0; z < 3; z++) {
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
Tile t = map.getTile(j, i, z);
if (t != null) {
writer.print(t.getNumber() + " ");
} else {
writer.print("0 ");
}
}
}
writer.println();
}
writer.flush();
writer.close();
} catch (IOException e) {
throw new RuntimeException("Could not save the level");
}
System.err.println("Saved");
}
/**
* calls each sprites logic method.
*/
void logic() {
for (int i = 0; i < sprites.size(); i++) {
Sprite s = (Sprite) sprites.get(i);
s.logic();
}
}
/**
* renders the scene to the graphics context. at the moment, sprites appear
* above everything else.
*
* TODO: Fix this up.
*/
void render(Graphics g) {
//System.out.println("Render Scene");
map.render(g, offsetX, offsetY);
for (int i = 0; i < sprites.size(); i++) {
Sprite s = (Sprite) sprites.get(i);
//s.render(g, offsetX, offsetY);
}
}
public void render(Graphics g, int offX, int offY) {
map.render(g, offX, offY);
}
public void render(Graphics g, Camera c) {
map.render(g, c);
}
public void render(Graphics g, Point origin, Dimension size) {
map.render(g, origin, size);
}
public void render(Graphics g, Point origin, Dimension size, int layer) {
map.render(g, origin, size, layer);
}
/**
* sets the visible area of the scene. This will probably not be used once
* the game is finished.
*/
void setViewSize(int width, int height) {
map.setViewSize(width, height);
}
/**
* sets the screen offset. Screen offset can be anywhere, not just following
* a character around. This is good for cut scenes.
*/
void setOffset(int x, int y) {
offsetX = x;
offsetY = y;
}
/**
* Apply RGB scalars and hue/sat adjustments to the tiles and characters in
* the scene. The hue and sat are always applied first
*
*/
public void setEffect(float r, float g, float b, float h, float s, float z) {
System.out.println("Scene setEffect called. will call for the gfx bank...r" + r + " g" + g + " b" + b + " z" + z);
effect_rScale = r;
effect_gScale = g;
effect_bScale = b;
effect_hue = h;
effect_sat = s;
tileset.setEffect(r, g, b, h, s, z);
map.setZoom(z);
}
/**
* returns the map. not really any reason to want to do this except for the
* level editor.
*/
public Map getMap() {
return map;
}
}