package snakemeleon;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.PointerInfo;
import java.awt.RenderingHints;
import java.awt.Toolkit;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Scanner;
import javax.swing.JOptionPane;
import maryb.player.Player;
import org.jbox2d.callbacks.ContactImpulse;
import org.jbox2d.callbacks.ContactListener;
import org.jbox2d.collision.Manifold;
import org.jbox2d.dynamics.Body;
import org.jbox2d.dynamics.BodyType;
import org.jbox2d.dynamics.contacts.Contact;
import snakemeleon.types.ChameleonScript;
import snakemeleon.types.ChameleonStickyScript;
import snakemeleon.types.Collectable;
import snakemeleon.types.KeyTriggerEntityAction;
import toritools.debug.Debug;
import toritools.entity.Entity;
import toritools.entity.Level;
import toritools.entity.ReservedTypes;
import toritools.entity.sprite.AbstractSprite.AbstractSpriteAdapter;
import toritools.entity.sprite.ImageSprite;
import toritools.entrypoint.Binary;
import toritools.io.FontLoader;
import toritools.io.Importer;
import toritools.math.MidpointChain;
import toritools.math.Vector2;
import toritools.physics.Universe;
import toritools.scripting.EntityScript;
import toritools.scripting.EntityScript.EntityScriptAdapter;
import toritools.scripting.ScriptUtils;
public class Snakemeleon extends Binary {
/*
* CONSTANTS!
*/
/**
* The core universe. Reference this to apply forces, etc.
*/
public static Universe uni;
/*
* The midpoint chain with the a tracking the player, and being the camera
* offset.
*/
private static MidpointChain camera;
private static Vector2 offset = Vector2.ZERO;
public static boolean isMouseDragging = false, rightSticking = false;
public static Vector2 mousePos = Vector2.ZERO;
private static int currentLevel = 0;
private static String[] levels = {};
private static Font uiFont;
private static SnakemeleonHUD hud = new SnakemeleonHUD();
private static File bgFile;
Player player;
public static void main(String[] args) {
new Snakemeleon();
}
public Snakemeleon() {
super(new Vector2(800, 600), 60, "Snakemeleon");
super.getApplicationFrame().setIconImage(ScriptUtils.fetchImage(new File("snakemeleon/chameleon_head.png")));
super.getApplicationFrame().setResizable(true);
}
@Override
protected void initialize() {
// Load the campaign
try {
ArrayList<String> levels = new ArrayList<String>();
Scanner fileScanner = new Scanner(new File("snakemeleon/campaign.conf"));
while(fileScanner.hasNextLine()) {
String levelFile = fileScanner.nextLine();
if(levelFile.startsWith("snakemeleon")) {
levels.add(levelFile.trim());
}
}
Snakemeleon.levels = levels.toArray(new String[0]);
} catch (FileNotFoundException e) {
JOptionPane.showMessageDialog(null, "Can't find campaign.conf in the snakemeleon directory!");
System.exit(1);
}
try {
FontLoader.loadFont(new File("snakemeleon/eartm.ttf"));
} catch (Exception e1) {
e1.printStackTrace();
}
uiFont = new Font("Earth's Mightiest", Font.TRUETYPE_FONT, 40);
bgFile = new File("snakemeleon/forest1.png");
player = new Player();
player.setSourceLocation("snakemeleon/sounds/BGM/Wallpaper.mp3");
player.play();
// Create a new blank cursor.
Cursor blankCursor = Toolkit.getDefaultToolkit().createCustomCursor(
new BufferedImage(10, 10, BufferedImage.TYPE_INT_ARGB), new Point(), "Red Circle Cursor");
// Set the blank cursor to the JFrame.
super.getApplicationFrame().getContentPane().setCursor(blankCursor);
super.getApplicationFrame().addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent arg0) {
if (arg0.getButton() == MouseEvent.BUTTON1)
Snakemeleon.isMouseDragging = true;
else
Snakemeleon.rightSticking = true;
}
@Override
public void mouseReleased(MouseEvent arg0) {
if (arg0.getButton() == MouseEvent.BUTTON1)
Snakemeleon.isMouseDragging = false;
else
Snakemeleon.rightSticking = false;
}
});
}
@Override
protected void globalLogic(Level level) {
if (ScriptUtils.getKeyHolder().isPressed(KeyEvent.VK_ESCAPE)) {
System.exit(0);
}
if (ScriptUtils.getKeyHolder().isPressedThenRelease(KeyEvent.VK_F12)) {
nextLevel();
}
if (ScriptUtils.getKeyHolder().isPressedThenRelease(KeyEvent.VK_P)) {
Debug.showDebugPrintouts = !Debug.showDebugPrintouts;
}
uni.step(60 / 1000f, 1);
camera.setA(level.getEntityWithId(SnakemeleonConstants.playerTypeId).getPos());
camera.smoothTowardA();
Vector2 halfPort = VIEWPORT.scale(.5f);
float x = Math.min(Math.max(camera.getB().x, halfPort.x), level.getDim().x - halfPort.x);
float y = Math.min(Math.max(camera.getB().y, halfPort.y), level.getDim().y - halfPort.y);
offset = halfPort.sub(new Vector2(x, y));
PointerInfo e = MouseInfo.getPointerInfo();
Point frameLoc = super.getApplicationFrame().getLocationOnScreen();
mousePos = new Vector2(-offset.getWidth() + e.getLocation().x - frameLoc.x, -offset.getHeight()
+ e.getLocation().y - frameLoc.y);
hud.update(1, level);
if(player.isEndOfMediaReached()) {
player.play();
}
}
@Override
protected void setupCurrentLevel(Level levelBeingLoaded) {
uni = new Universe(SnakemeleonConstants.gravity);
final Entity cham = levelBeingLoaded.getEntityWithId(SnakemeleonConstants.playerTypeId);
cham.addScript(new ChameleonScript());
// A script to enable the chameleon to stick to things. Should be the
// last script you add to cham.
cham.addScript(new ChameleonStickyScript());
for (Entity e : levelBeingLoaded.getEntitiesWithType(ReservedTypes.WALL)) {
uni.addEntity(e, BodyType.STATIC, false, false, 1f, .3f);
}
for (Entity e : levelBeingLoaded.getEntitiesWithType("RIGHT_DIAG_WALL")) {
uni.addEntity(e, BodyType.STATIC, false, false, 1f, .3f,
new Vector2[] { (e.getDim().scale(.5f, -.5f)), (e.getDim().scale(-.5f, .5f)) }, false);
}
for (Entity e : levelBeingLoaded.getEntitiesWithType("LEFT_DIAG_WALL")) {
uni.addEntity(e, BodyType.STATIC, false, false, 1f, .3f,
new Vector2[] { (e.getDim().scale(-.5f, -.5f)), (e.getDim().scale(.5f, .5f)) }, false);
}
final EntityScript breakScript = new EntityScriptAdapter() {
@Override
public void onDeath(Entity self, Level level, boolean isRoomExit) {
boolean childrenAreProps = self.getDim().x > 32 && self.getDim().y > 32;
for (int i = 0; i < 2; i++) {
for (int i2 = 0; i2 < 2; i2++) {
try {
Entity e = new Entity();
e.setPos(self.getPos().add(self.getDim().scale(i * .5f)));
e.setDim(self.getDim().scale(.5f));
e.setSprite(new ImageSprite(self.getSprite().getImageIndex(), 2, 2));
e.getSprite().set(i, i2);
level.spawnEntity(e);
if (childrenAreProps) {
e.addScript(this);
e.setType(SnakemeleonConstants.dynamicPropType);
}
Body body = Snakemeleon.uni.addEntity(e, BodyType.DYNAMIC, true, false, .2f, .03f);
Snakemeleon.uni.applyLinearImpulse(e, new Vector2((float) (-.5 + Math.random()) * .01f,
(float) (-.5 + Math.random()) * .01f));
if (!childrenAreProps) {
body.getFixtureList().m_filter.categoryBits = 3;
}
} catch (final Exception e) {
e.printStackTrace();
}
}
}
}
};
for (Entity e : levelBeingLoaded.getEntitiesWithType(SnakemeleonConstants.dynamicPropType)) {
String isRound = e.getVariableCase().getVar("round");
boolean round = false;
if (isRound != null && isRound.equalsIgnoreCase("true")) {
round = true;
}
uni.addEntity(e, BodyType.DYNAMIC, true, round, 1f, .3f);
if (e.getVariableCase().getVar("key") != null) {
e.addScript(new KeyTriggerEntityAction());
}
if (e.getVariableCase().getVar("id") != null && e.getVariableCase().getVar("id").equals("collectable")) {
e.addScript(new Collectable());
} else {
e.addScript(breakScript);
}
}
for (Entity e : levelBeingLoaded.getEntitiesWithType(SnakemeleonConstants.hingeType)) {
levelBeingLoaded.despawnEntity(e);
Entity a = null, b = null;
Vector2 pos = e.getPos().add(e.getDim().scale(.5f));
for (Entity object : levelBeingLoaded.getNewEntities()) {
if (!object.getType().equals(ReservedTypes.BACKGROUND) && ScriptUtils.isPointWithin(object, pos)
&& object != e) {
if (a == null)
a = object;
else if (a != null)
b = object;
}
}
if (a != null && b != null)
uni.addHinge(a, b, pos);
}
EntityScript spikeScript = new EntityScript() {
Entity player;
@Override
public void onSpawn(Entity self, Level level) {
player = level.getEntityWithId("player");
}
@Override
public void onUpdate(Entity self, float time, Level level) {
if (!Debug.showDebugPrintouts && player.isActive() && ScriptUtils.isColliding(self, player)) {
player.setActive(false);
}
}
@Override
public void onDeath(Entity self, Level level, boolean isRoomExit) {
}
};
for (Entity e : levelBeingLoaded.getEntitiesWithType("spike")) {
e.addScript(spikeScript);
}
for (Entity e : levelBeingLoaded.getEntitiesWithType("message")) {
final String message = e.getVariableCase().getVar("message");
e.setSprite(new AbstractSpriteAdapter() {
@Override
public void draw(Graphics2D g, Entity self) {
g.setColor(Color.CYAN);
g.drawString(message, self.getPos().getWidth(), self.getPos().getHeight());
}
});
}
/*
* if a dynamic prop is dangerous, hurt cham
*/
uni.addContactListener(new ContactListener() {
@Override
public void beginContact(Contact arg0) {
Entity a = (Entity) arg0.m_fixtureA.getUserData();
Entity b = (Entity) arg0.m_fixtureB.getUserData();
if ((a == cham && b.getVariableCase().getVar("hurt") != null)
|| (b == cham && a.getVariableCase().getVar("hurt") != null)) {
if (!Debug.showDebugPrintouts && cham.isActive())
cham.setActive(false);
} else if (a.getType().equals(SnakemeleonConstants.dynamicPropType)
&& a.getVariableCase().getVar("hurt") == null && b.getVariableCase().getVar("hurt") != null
&& !"collectable".equals(a.getVariableCase().getVar("id")))
ScriptUtils.getCurrentLevel().despawnEntity(a);
else if (a.getType().equals(SnakemeleonConstants.dynamicPropType)
&& b.getVariableCase().getVar("hurt") == null && a.getVariableCase().getVar("hurt") != null
&& !"collectable".equals(b.getVariableCase().getVar("id")))
ScriptUtils.getCurrentLevel().despawnEntity(b);
}
@Override
public void endContact(Contact arg0) {
}
@Override
public void postSolve(Contact arg0, ContactImpulse arg1) {
}
@Override
public void preSolve(Contact arg0, Manifold arg1) {
}
});
levelBeingLoaded.bakeBackground();
camera = new MidpointChain(levelBeingLoaded.getEntityWithId(SnakemeleonConstants.playerTypeId).getPos(),
SnakemeleonConstants.cameraLag);
bgFile = new File(levelBeingLoaded.getVariableCase().getString("background"));
}
@Override
protected Level getStartingLevel() {
try {
return Importer.importLevel(new File(levels[0]));
} catch (FileNotFoundException e) {
e.printStackTrace();
System.exit(1);
}
return null;
}
private final BasicStroke dottedStroke = new BasicStroke(2, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 10,
new float[] { 5, 5, 5, 5 }, 0);
@Override
protected boolean render(Graphics2D rootCanvas, Level level) {
try {
rootCanvas.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
rootCanvas.setFont(uiFont);
Entity player = level.getEntityWithId(SnakemeleonConstants.playerTypeId);
if (player == null) {
System.out.println("You need to make an entity with id set to player!");
System.exit(1);
}
rootCanvas.drawImage(ScriptUtils.fetchImage(bgFile), (int) 0, (int) 0, VIEWPORT.getWidth(),
VIEWPORT.getHeight(), null);
rootCanvas.translate(offset.getWidth(), offset.getHeight());
rootCanvas.drawImage(level.getBakedBackground(), (int) 0, (int) 0, (int) level.getDim().x,
(int) level.getDim().y, null);
if (ChameleonStickyScript.isGrabbing && player.isActive()) {
rootCanvas.setColor(Color.GREEN);
rootCanvas.setStroke(dottedStroke);
rootCanvas.drawOval(player.getPos().getWidth(), player.getPos().getHeight(),
player.getDim().getWidth(), player.getDim().getHeight());
}
for (int i = level.getLayers().size() - 1; i >= 0; i--) {
for (Entity e : level.getLayers().get(i)) {
if (e.isVisible() && e.isInView())
e.draw(rootCanvas);
}
}
if (Debug.showDebugPrintouts)
for (Entity wall : level.getEntitiesWithType("WALL"))
wall.draw(rootCanvas);
rootCanvas.translate(-offset.getWidth(), -offset.getHeight());
hud.draw(rootCanvas, VIEWPORT);
} catch (final Exception e) {
return false;
}
return true;
}
public static void restartLevel() {
try {
ScriptUtils.queueLevelSwitch(Importer.importLevel(new File(levels[currentLevel])));
} catch (FileNotFoundException e) {
e.printStackTrace();
System.exit(1);
}
}
public static void nextLevel() {
try {
ScriptUtils.queueLevelSwitch(Importer.importLevel(new File(levels[++currentLevel])));
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IndexOutOfBoundsException winner) {
System.out.println("You won!");
System.exit(1);
}
}
}