/* @pjs crisp=true;
preload="bar_bg.png, bar_fg.png, circle.png, coltan_goal_black.png, finger.png, intro_bg.png, mine_bg.png, mine_fg.png, mineral.png, slave_fearing.png, slave_idling.png, slave_working.png, slave_working0.png, slave_working1.png, slave_working2.png, slave_working3.png, slave_working4.png, slave_working5.png, slave_working6.png, slave_working7.png, slave_working_flipped.png, soldier_intimidate.png, soldier_stand.png, soldier_walk_down.png, soldier_walk_down0.png, soldier_walk_down1.png, soldier_walk_down2.png, soldier_walk_down3.png, soldier_walk_down4.png, soldier_walk_down5.png, soldier_walk_up.png, soldier_walk_up0.png, soldier_walk_up1.png, soldier_walk_up2.png, soldier_walk_up3.png, soldier_walk_up4.png, soldier_walk_up5.png, title.png";
*/
/**
This is a Web Standard version of PhoneStory
Processing code by DW dw@mondonerd.com
This software is licensed under GPL v.3
Graphical resources under Creative Commons BY-NC-SA 2011
**/
PImage introBg, title, bg, fg, barBg, barFg, barGoal;
Animation[] animations = new Animation[9];
Soldier[] soldiers = new Soldier[2];
Slave[] slaves = new Slave[10];
Sprite[] minerals = new Sprite[3];
Sprite[] fingers = new Sprite[2];
Sprite circle;
int[][] leftRow = new int[4][2];
int SOLDIER_STANDING = 0;
int SOLDIER_WALK_UP = 1;
int SOLDIER_WALK_DOWN = 2;
int SOLDIER_INTIMIDATING = 3;
int SLAVE_WORKING = 0;
int SLAVE_IDLING = 1;
int SLAVE_FEARING = 2;
boolean intro = true;
boolean showingScore = false;
float lastIdle;
float nextIdle = 3000;
float counterGoalProduction = 0;
float counterCurrentProduction = 0;
float goalProductionStep = 0.02;
int lastScore, highScore;
boolean tutorialEnded = false;
boolean tutorialExit = false;
float circleFrameTimer;
float scoreTimer;
boolean circleShowing = false;
PFont font;
void setup() {
size(160, 240);
frameRate(20);
font = loadFont("phonestoryfont.vlw");
textFont(font, 10);
textMode(CENTER);
bg = loadImage("mine_bg.png");
fg = loadImage("mine_fg.png");
barBg = loadImage("bar_bg.png");
barFg = loadImage("bar_fg.png");
barGoal = loadImage("coltan_goal_black.png");
introBg = loadImage("intro_bg.png");
title = loadImage("title.png");
animations[0] = new Animation("soldier_walk_down", 6);
animations[1] = new Animation("soldier_walk_up", 6);
animations[2] = new Animation("soldier_walk_down", 1);
animations[3] = new Animation("slave_working", 8);
animations[4] = new Animation("slave_idling.png", 30, 25);
animations[5] = new Animation("soldier_intimidate.png", 34, 52);
animations[6] = new Animation("mineral.png", 13, 8);
animations[7] = new Animation("circle.png", 44, 44);
animations[8] = new Animation("finger.png", 105, 107);
soldiers[0] = new Soldier();
soldiers[0].setPosition(25, 70);
soldiers[1] = new Soldier();
soldiers[1].setPosition(140, 100);
soldiers[1].flipped = true;
for (int i = 0; i < minerals.length; i++) {
minerals[i] = new Sprite();
minerals[i].sprites = animations[6];
}
minerals[0].setPosition(65, 76);
minerals[1].setPosition(95, 136);
minerals[2].setPosition(92, 215);
setupSlaves();
setupTutorial();
initLevel();
}
void setupTutorial() {
fingers[0] = new Sprite();
fingers[1] = new Sprite();
fingers[0].setPosition(-40, 170);
fingers[0].flipped = true;
fingers[1].setPosition(200, 270);
fingers[0].sprites = animations[8];
fingers[1].sprites = animations[8];
circle = new Sprite();
circle.setPosition(93, 92);
circle.sprites = animations[7];
}
void renderTutorial() {
if (tutorialEnded)
return;
if (!tutorialExit) {
if (fingers[0].position.x < -20) {
fingers[0].position.x += 2;
fingers[1].position.x -= 2;
} else if (fingers[0].position.y < 270) {
fingers[0].position.y += 2;
fingers[1].position.y -= 2;
} else {
tutorialExit = true;
}
} else {
if (fingers[0].position.x > -60) {
fingers[0].position.x -= 4;
fingers[1].position.x += 4;
}
else {
tutorialEnded = true;
}
}
fingers[0].render();
fingers[1].render();
if (millis() - circleFrameTimer > 500) {
circleShowing = !circleShowing;
circleFrameTimer = millis();
}
if (circleShowing)
circle.render();
}
void setupSlaves() {
for (int i = 0; i < slaves.length; i++) {
slaves[i] = new Slave();
if (i > 4) {
slaves[i].flipped = true;
}
else {
slaves[i].flipped = false;
}
}
slaves[0].setPosition(122 / 2 -15, 122 / 2 -25);
slaves[1].setPosition(130 / 2 -15, 208 / 2 -25);
slaves[2].setPosition(118 / 2 -15, 286 / 2 -25);
slaves[3].setPosition(120 / 2 -15, 362 / 2 -25);
slaves[4].setPosition(118 / 2 -15, 432 / 2 -25);
slaves[5].setPosition(210 / 2 -15, 96 / 2 -25);
slaves[6].setPosition(190 / 2 -15, 162 / 2 -25);
slaves[7].setPosition(198 / 2 -15, 240 / 2 -25);
slaves[8].setPosition(192 / 2 -15, 330 / 2 -25);
slaves[9].setPosition(202 / 2 -15, 400 / 2 -25);
slaves[6].setState(SLAVE_IDLING);
}
void initLevel() {
counterGoalProduction = 0;
counterCurrentProduction = 0;
}
void winLevel() {
showingScore = true;
lastScore = int(counterCurrentProduction - counterGoalProduction);
if (highScore < lastScore)
highScore = lastScore;
setupSlaves();
scoreTimer = millis();
initLevel();
}
void gameOver() {
intro = true;
setupSlaves();
initLevel();
}
void updateScore() {
if (counterCurrentProduction < 0)
counterCurrentProduction = 0;
counterGoalProduction += goalProductionStep * slaves.length;
if (counterGoalProduction >= 100)
if (counterCurrentProduction < 100)
gameOver();
else
winLevel();
}
void draw() {
if (intro) {
background(introBg);
image(title, width * .5 - title.width * .5, height * .5 - title.height * .5);
return;
} else if (showingScore) {
background(introBg);
text("YOUR SCORE", 30, height * .3);
text(lastScore, 30, height * .4);
text("YOUR HIGHSCORE", 30, height * .6);
text(highScore, 30, height * .7);
return;
}
updateScore();
background(bg);
soldiers[0].update();
soldiers[1].update();
boolean soldierRightAggressive = (soldiers[1].state == SOLDIER_INTIMIDATING);
boolean soldierLeftAggressive = (soldiers[0].state == SOLDIER_INTIMIDATING);
int offSet = int(random(0, slaves.length - 1));
for (int i = offSet; i < slaves.length; i++) {
if (slaves[i].state != SLAVE_IDLING && millis() - lastIdle > nextIdle) {
slaves[i].state = SLAVE_IDLING;
nextIdle = random(1000, 5000);
lastIdle = millis();
}
}
for (int i = 0; i < minerals.length; i++) {
minerals[i].render();
}
for (int i = 0; i < slaves.length; i++) {
slaves[i].update();
if (slaves[i].state == SLAVE_IDLING) {
if (i > 4) {
if (soldierRightAggressive && abs(soldiers[1].position.y -25 - slaves[i].position.y) < 20) {
slaves[i].state = SLAVE_WORKING;
}
}
else {
if (soldierLeftAggressive && abs(soldiers[0].position.y -25 - slaves[i].position.y) < 20) {
slaves[i].state = SLAVE_WORKING;
}
}
}
slaves[i].update();
slaves[i].render();
}
soldiers[0].render();
soldiers[1].render();
image(fg, 0, 0);
renderScore();
renderTutorial();
}
void renderScore() {
image(barBg, 29, 230);
if (counterCurrentProduction < 100 && counterCurrentProduction > 0)
image(barFg, 30, 231, counterCurrentProduction, 2);
else if (counterCurrentProduction >= 100)
image(barFg, 30, 231, 100, 2);
image(barGoal, 30 + counterGoalProduction - barGoal.width / 2, 231);
}
void mousePressed() {
if (intro) {
intro = false;
return;
} else if (showingScore && millis() - scoreTimer > 2000) {
showingScore = false;
}
int selectedSlave = -1;
float minimumDistance = 30;
for (int i = 0; i < slaves.length; i++) {
float currentDistanceFromMouse = dist(slaves[i].position.x + 12, slaves[i].position.y + 25, mouseX, mouseY);
if (currentDistanceFromMouse < minimumDistance) {
minimumDistance = currentDistanceFromMouse;
selectedSlave = i;
}
}
if (selectedSlave < 0)
return;
if (mouseX < width * .5)
soldiers[0].setTargetPosition(slaves[selectedSlave].position.x + 12, slaves[selectedSlave].position.y + 25);
else
soldiers[1].setTargetPosition(slaves[selectedSlave].position.x + 12, slaves[selectedSlave].position.y + 25);
}
class Animation {
PImage[] images;
int imageCount;
String imagePrefix;
Animation(String _imagePrefix, int count) {
imagePrefix = _imagePrefix;
imageCount = count;
images = new PImage[imageCount];
for (int i = 0; i < imageCount; i++) {
// Use nf() to number format 'i' into four digits
String filename = imagePrefix + i + ".png";
images[i] = loadImage(filename);
}
}
Animation(String imageURI, int frameWidth, int frameHeight) {
PImage tempImage = loadImage(imageURI);
imageCount = tempImage.width / frameWidth;
images = new PImage[imageCount];
for (int i = 0; i < imageCount; i++) {
images[i] = createImage(frameWidth, frameHeight, ARGB);
images[i].copy(tempImage, frameWidth * i, 0, frameWidth, frameHeight, 0, 0, frameWidth, frameHeight);
}
}
void display(float xpos, float ypos, int currentFrame) {
currentFrame %= imageCount;
image(images[currentFrame], xpos, ypos);
}
void display(float xpos, float ypos, boolean flipped, int currentFrame) {
currentFrame %= imageCount;
if (!flipped) {
image(images[currentFrame], xpos, ypos);
} else {
pushMatrix();
translate(xpos, ypos);
scale(-1, 1);
image(images[currentFrame], -images[currentFrame].width, 0);
popMatrix();
}
}
int getWidth() {
return images[0].width;
}
int getHeight() {
return images[0].height;
}
}
class Slave extends Sprite {
void update() {
if (state == SLAVE_WORKING) {
counterCurrentProduction += .02;
}
if (state == SLAVE_IDLING) {
counterCurrentProduction -= .03;
}
}
void setState(int newState) {
state = newState;
}
void render() {
currentFrame++;
int currentX = int(position.x);
int currentY = int(position.y);
if (state == SLAVE_WORKING) {
animations[3].display(currentX, currentY, flipped, currentFrame);
}
if (state == SLAVE_IDLING) {
animations[4].display(currentX, currentY, flipped, currentFrame);
}
}
}
class Soldier extends Sprite {
float intimidatingTimer;
void render() {
currentFrame++;
int currentX = int(position.x) - (animations[0].getWidth() / 2);
int currentY = int(position.y) - animations[0].getHeight();
if (state == SOLDIER_WALK_UP)
animations[0].display(currentX, currentY, flipped, currentFrame);
else if (state == SOLDIER_WALK_DOWN)
animations[1].display(currentX, currentY, flipped, currentFrame);
else if (state == SOLDIER_STANDING)
animations[2].display(currentX, currentY, flipped, currentFrame);
else if (state == SOLDIER_INTIMIDATING)
animations[5].display(currentX, currentY, flipped, currentFrame);
}
void update() {
if (state == SOLDIER_INTIMIDATING && millis() - intimidatingTimer > 2000) {
state = SOLDIER_STANDING;
}
float distanceFromTarget = abs(position.y - positionTarget.y);
if (distanceFromTarget > 5) {
position.y += (positionTarget.y - position.y) * easying;
if (position.y < positionTarget.y) {
state = SOLDIER_WALK_UP;
}
else {
state = SOLDIER_WALK_DOWN;
}
}
else if (state == SOLDIER_WALK_DOWN || state == SOLDIER_WALK_UP) {
state = SOLDIER_INTIMIDATING;
intimidatingTimer = millis();
}
}
}
class Sprite {
int state = 0;
boolean flipped = false;
PVector position = new PVector();
PVector positionTarget = new PVector();
float easying = .1;
int currentFrame;
Animation sprites;
Sprite() {
}
void render() {
if (sprites == null)
return;
int currentX = int(position.x) - (sprites.getWidth() / 2);
int currentY = int(position.y) - sprites.getHeight();
sprites.display(currentX, currentY, flipped, currentFrame);
}
void setPosition(float x, float y) {
position.x = x;
position.y = y;
positionTarget.x = x;
positionTarget.y = y;
}
void setTargetPosition(float x, float y) {
positionTarget.x = x;
positionTarget.y = y;
}
}