/**
* Game 28: "Giant Vex"
* Taunt the giant for fun and profit.
*
Go play more games at NMcCoy.net!
* 
This work by Nathan McCoy is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License.
*/
import ddf.minim.*;
color BG_COLOR = color(128, 168, 64);// color(96, 168, 32);
color BG_VARIATION_COLOR = color(133, 173, 64);// color(96, 168, 32);
color BG_VARIATION_COLOR_2 = color(123, 163, 64);// color(96, 168, 32);
color SHADOW_COLOR = color(96, 128, 32);//color(0, 32, 64, 64);//
float DRAGONDOT_RADIUS = 16;
color DRAGONDOT_FILL = color(192, 16, 64);
color DRAGONDOT_STROKE = color(148, 0, 32);
float KOBOLD_RADIUS = 10;
color KOBOLD_FILL = color(175, 215, 180);
color KOBOLD_STROKE = color(196, 176, 97);
float PLAYER_WALK_SPEED = 3;
float PLAYER_MASS = 10;
float Z_SCALE = 0.5;
float GRAVITY = 0.3;
float JUMP_STRENGTH = 5;
float FLAP_STRENGTH = 5;
float FLAP_CEILING = 400;
float FLAP_DRAG = 0.9;
float FLAP_SPEED = 3;
int COMBO_TIME = 8;
int NAME_TIME = 120;
int PLAYER_START_HP = 10;
int WORLD_WIDTH = 1;
int WORLD_HEIGHT = 1;
int WORLD_START_X = 0;
int WORLD_START_Y = 0;
int LIFEBAR_W = 50;
int LIFEBAR_H = 4;
PFont font;
ZSorter zSort = new ZSorter();
Screen testScreen;
Screen[][] world;
int world_x;
int world_y;
ParticleList smokeParticles;
ParticleList textParticles;
ArrayList loot_drop;
boolean muted;
boolean paused;
int score;
int level;
int topscore;
int toplevel = 1;
boolean can_fly;
boolean cheated;
boolean won;
boolean at_title;
String overlay_text;
boolean[] keys = new boolean[255];
int KEY_LEFT = 37;
int KEY_RIGHT = 39;
int KEY_UP = 38;
int KEY_DOWN = 40;
int KEY_JUMP = 90; //Z
int KEY_ATTACK = 88; //X
int KEY_SPECIAL = 67; //C
int KEY_KILLALL = 8; //backspace
int KEY_PHATLOOT = 61;
Critter player;
Giant theGiant;
Minim minim;
AudioSample clawSound;
AudioSample biteSound;
AudioSample sweepSound;
AudioSample poofSound;
AudioSample knifeSound;
AudioSample hitSound;
AudioSample lootSound;
AudioSample lootBounceSound;
AudioSample heartSound;
AudioSample clearSound;
AudioSample clubSound;
AudioSample levelUpSound;
AudioSample ghostSound;
AudioSample thunderSound;
AudioSample tauntSound;
AudioPlayer bgm;
/// UTILITY //////////////////////////////////////////////////////////////////////////////
void openSound()
{
minim = new Minim(this);
clawSound = minim.loadSample("claw.wav", 1024);
biteSound = minim.loadSample("bite.wav", 1024);
sweepSound = minim.loadSample("sweep.wav", 1024);
poofSound = minim.loadSample("poof.wav", 1024);
knifeSound = minim.loadSample("knife.wav", 1024);
hitSound = minim.loadSample("hit.wav", 1024);
lootSound = minim.loadSample("loot.wav", 1024);
lootBounceSound = minim.loadSample("lootbounce.wav", 1024);
heartSound = minim.loadSample("heart.wav", 1024);
clearSound = minim.loadSample("areaclear.wav", 1024);
clubSound = minim.loadSample("club.wav", 1024);
levelUpSound = minim.loadSample("levelup.wav", 2048);
ghostSound = minim.loadSample("ghost.wav", 1024);
thunderSound = minim.loadSample("thunder.wav", 1024);
tauntSound = minim.loadSample("taunt.wav", 1024);
bgm = minim.loadFile("koboldot.mp3", 4096);
}
void closeSound()
{
clawSound.close();
biteSound.close();
sweepSound.close();
poofSound.close();
knifeSound.close();
hitSound.close();
lootSound.close();
lootBounceSound.close();
heartSound.close();
clearSound.close();
clubSound.close();
levelUpSound.close();
ghostSound.close();
thunderSound.close();
tauntSound.close();
bgm.close();
minim.stop();
}
boolean inRadius(PVector a, PVector b, float rad)
{
return rad*rad > (a.x - b.x)*(a.x - b.x) + (a.y - b.y) * (a.y - b.y) + (a.z - b.z) * (a.z - b.z);
}
PVector randomVector(float magn)
{
float angle = random(TWO_PI);
return new PVector(cos(angle)*magn, sin(angle)*magn);
}
class ParticleList extends ArrayList
{
void tick()
{
Iterator i = iterator();
while(i.hasNext())
{
Particle p = (Particle) i.next();
p.tick();
if(p.life <= 0) i.remove();
}
}
void draw()
{
Iterator i = iterator();
while(i.hasNext())
{
Particle p = (Particle) i.next();
p.draw();
}
}
}
void spawnEnemies()
{
int i = (int) (level * 1.5)+1;
//i = 20;
while(i > 0)
{
Critter c;
if(i >= 15 && random(3)< 1)
{
c = new Drakeling(random(width), random(height));
i -= 10;
}else
if(i >= 10 && random(5)< 1)
{
c = new Ghost(random(width), random(height));
i -= 5;
}else if(i >= 6 && random(4)< 1)
{
c = new Rogue(random(width), random(height));
i -= 4;
}else if(i >= 4 && random(2)< 1)
{
c = new Worg(random(width), random(height));
i -= 3;
}else if(i >= 3 && random(2)< 1)
{
c = new Hobgoblin(random(width), random(height));
i -= 2;
}
else
{
c = new Goblin(random(width), random(height));
i--;
}
c.pos.z = random(600)+600;
world[0][0].critters.add(c);
}
}
abstract class Particle
{
PVector pos;
PVector vel;
PVector accel;
int life;
int maxlife;
Particle(PVector p, PVector v, int lifetime)
{
this(p, v, new PVector(0, 0), lifetime);
}
Particle(PVector p, PVector v, PVector a, int lifetime)
{
accel = new PVector(a.x, a.y);
pos = new PVector(p.x, p.y);
vel = new PVector(v.x, v.y);
life = maxlife = lifetime;
}
void tick()
{
vel.add(accel);
pos.add(vel);
life--;
}
abstract void draw();
}
class SmokePoof extends Particle
{
SmokePoof(PVector p, int bigness)
{
super(p, randomVector(random(1)), new PVector(0, -0.05), bigness*2);
}
void draw()
{
fill(230, 230, 220);
noStroke();
ellipse(pos.x, pos.y, life/2, life/2);
}
}
class TextBlip extends Particle
{
String myText;
color myColor;
TextBlip(PVector p, int life, String label)
{
super(p, PVector.add(randomVector(0.5), new PVector(0, -2)), new PVector(0, 4.0/life), life);
myText = label;
myColor = color(255);
}
TextBlip(PVector p, int life, String label, color c)
{
super(p, PVector.add(randomVector(0.5), new PVector(0, -2)), new PVector(0, 4.0/life), life);
myText = label;
myColor = c;
}
void draw()
{
textAlign(CENTER, BOTTOM);
textFont(font, 8);
fill(myColor);
text(myText, pos.x, pos.y);
}
}
// CLASSES ////////////////////////////////////////////////////////////////////////////////
class ZSorter implements Comparator
{
int compare(Object o1, Object o2)
{
Critter c1 = (Critter) o1;
Critter c2 = (Critter) o2;
if(c1.pos.z < c2.pos.z) return -1;
if(c1.pos.z > c2.pos.z) return 1;
return 0;
}
}
/////// ATTACKS
class Attack
{
String name;
float radius;
float distance;
float knock_away;
float knock_upward;
int damage;
int warm_frames;
int active_frames;
int cool_frames;
int animation;
int stun_time;
static final int SLASH = 0;
static final int SWEEP = 1;
static final int BITE = 2;
static final int FIREBALL = 3;
color anim_color = color(255);
AudioSample sound;
void draw(int frame)
{
if(frame >= warm_frames && frame < warm_frames + active_frames)
{
if(animation == SLASH)
{
noFill();
stroke(anim_color, map(frame, warm_frames, warm_frames+active_frames, 255, 0));
strokeWeight(2);
ellipse(0, 0, radius, radius);
ellipse(0, 0, radius * 0.8, radius * 0.8);
ellipse(0, 0, radius * 0.6, radius * 0.6);
}
else if(animation == BITE)
{
noFill();
float ratio = map(frame, warm_frames, warm_frames+active_frames, 0, 1);
stroke(anim_color);
strokeWeight(2);
line(0, -radius, 0, -radius + 2 * ratio * radius);
line(-radius * 0.8, -radius * 0.5, -radius * 0.8, (-radius + 2 * ratio * radius) * 0.5);
line(radius * 0.8, -radius * 0.5, radius * 0.8, (-radius + 2 * ratio * radius) * 0.5);
line(-radius * 0.4, radius * 0.75, -radius * 0.4, (radius - 2 * ratio * radius) * 0.75);
line(radius * 0.4, radius * 0.75, radius * 0.4, (radius - 2 * ratio * radius) * 0.75);
}
else if(animation == SWEEP)
{
fill(anim_color,
min(map(frame, warm_frames, warm_frames+active_frames, 510, 0), map(frame, warm_frames, warm_frames+active_frames, 0, 510)));
noStroke();
ellipse(0, 0, radius, radius);
}
else
{
fill(anim_color);
noStroke();
ellipse(0, 0, radius, radius);
}
}
}
}
class DrakeClaw extends Attack
{
DrakeClaw()
{
name = "claw!";
radius = 22;
distance = 9;
warm_frames = 8;
active_frames = 6;
cool_frames = 8;
animation = SLASH;
damage = 1;
knock_away = 3;
knock_upward = 2;
stun_time = 6;
sound = clawSound;
}
}
class Claw extends Attack
{
Claw()
{
name = "claw!";
radius = 22;
distance = 9;
warm_frames = 0;
active_frames = 6;
cool_frames = 8;
animation = SLASH;
damage = 1;
knock_away = 3;
knock_upward = 2;
stun_time = 6;
sound = clawSound;
}
}
class Bite extends Attack
{
Bite()
{
name = "bite!";
radius = 20;
distance = 30;
warm_frames = 0;
active_frames = 6;
cool_frames = 10;
animation = BITE;
damage = 2;
knock_away = 0;
knock_upward = 0;
stun_time = 12;
sound = biteSound;
}
}
class TailSweep extends Attack
{
TailSweep()
{
name = "tail sweep!";
radius = 43;
distance = 9;
warm_frames = 3;
active_frames = 12;
cool_frames = 20;
anim_color = DRAGONDOT_FILL;
animation = SWEEP;
damage = 1;
knock_away = 4;
knock_upward = 8;
stun_time = 30;
sound = sweepSound;
}
}
class Knife extends Attack
{
Knife()
{
name = "knife!";
radius = 10;
distance = 8;
warm_frames = 20;
active_frames = 6;
cool_frames = 8;
animation = SLASH;
damage = 1;
knock_away = 4;
knock_upward = 2;
stun_time = 30;
sound = knifeSound;
}
}
class Club extends Attack
{
Club()
{
name = "club!";
radius = 16;
distance = 10;
warm_frames = 15;
active_frames = 8;
cool_frames = 10;
animation = SWEEP;
damage = 2;
knock_away = 8;
knock_upward = 5;
stun_time = 30;
anim_color = color(128, 64, 0);
sound = clubSound;
}
}
class WorgBite extends Attack
{
WorgBite()
{
name = "bite!";
radius = 14;
distance = 15;
warm_frames = 15;
active_frames = 8;
cool_frames = 60;
animation = BITE;
damage = 2;
knock_away = 0;
knock_upward = 0;
stun_time = 20;
sound = biteSound;
}
}
class DireWorgBite extends Attack
{
DireWorgBite()
{
name = "bite!!";
radius = 32;
distance = 35;
warm_frames = 15;
active_frames = 8;
cool_frames = 80;
animation = BITE;
damage = 5;
knock_away = 0;
knock_upward = 0;
stun_time = 30;
sound = biteSound;
}
}
class GhostAura extends Attack
{
GhostAura()
{
name = "BOO!";
radius = 17;
distance = 0;
warm_frames = 0;
active_frames = 20;
cool_frames = 20;
animation = SWEEP;
damage = 2;
knock_away = 10;
knock_upward = 10;
stun_time = 30;
sound = ghostSound;
}
}
class ScorchingBurst extends Attack
{
ScorchingBurst()
{
name = "Fireball!";
radius = 35;
distance = 150;
warm_frames = 20;
active_frames = 10;
cool_frames = 120;
animation = SWEEP;
damage = 3;
knock_away = 0;
knock_upward = 20;
stun_time = 30;
anim_color = color(255, 192, 0);
sound = sweepSound;
}
}
class ThunderWave extends Attack
{
ThunderWave()
{
name = "Thunder Pulse!";
radius = 50;
distance = 0;
warm_frames = 0;
active_frames = 10;
cool_frames = 100;
animation = SLASH;
damage = 1;
knock_away = 10;
knock_upward = 10;
stun_time = 30;
anim_color = color(192, 192, 192);
sound = thunderSound;
}
}
class NinjaKnife extends Knife
{
NinjaKnife()
{
super();
warm_frames = 8;
cool_frames = 15;
}
}
class GiantClub extends Attack
{
GiantClub()
{
name = "club!!";
radius = 60;
distance = 40;
warm_frames = 20;
active_frames = 12;
cool_frames = 0;//100;
anim_color = color(128, 64, 0);
animation = SWEEP;
damage = 4;
knock_away = 20;
knock_upward = 20;
stun_time = 50;
sound = clubSound;
}
}
class BGFeature
{
float radius;
color col;
PVector pos;
BGFeature(PVector p, float r, color c)
{
pos = p;
radius = r;
col = c;
}
void draw()
{
noStroke();
fill(col);
ellipse(pos.x, pos.y, radius, radius);
}
}
class Screen
{
int rescue_award = 5;
ArrayList critters;
ArrayList features;
boolean cleared;
boolean killedFriendly;
Screen()
{
cleared = false;
killedFriendly = false;
critters = new ArrayList();
features = new ArrayList();
for(int i = 0; i < 5; i++)
{
features.add(new BGFeature(new PVector(random(width), random(height)), random(40)+40, BG_VARIATION_COLOR_2));
}
for(int i = 0; i < 5; i++)
{
features.add(new BGFeature(new PVector(random(width), random(height)), random(20)+20, BG_VARIATION_COLOR));
}
}
void draw()
{
for(int i = 0; i < features.size(); i++)
{
BGFeature b = (BGFeature) features.get(i);
b.draw();
}
for(int i = 0; i < critters.size(); i++)
{
Critter c = (Critter) critters.get(i);
c.drawShadow();
}
for(int i = 0; i < critters.size(); i++)
{
Critter c = (Critter) critters.get(i);
c.drawAttack();
c.draw();
}
for(int i = 0; i < critters.size(); i++)
{
Critter c = (Critter) critters.get(i);
if(c.name_timer > 0) c.drawName();
}
}
void stepPhysics()
{
if(cleared) spawnEnemies();
for(int i = 0; i < critters.size(); i++)
{
Critter c = (Critter) critters.get(i);
c.step();
}
for(int i = 0; i < critters.size(); i++)
{
Critter c = (Critter) critters.get(i);
for(int j = i+1; j< critters.size(); j++)
{
Critter d = (Critter) critters.get(j);
c.resolveCollision(d);
}
}
for(int i = 0; i < critters.size(); i++)
{
Critter c = (Critter) critters.get(i);
for(int j = 0; j< critters.size(); j++)
{
if(i != j)
{
Critter d = (Critter) critters.get(j);
c.resolveAttack(d);
}
}
}
Iterator it = critters.iterator();
{
boolean hadHostiles = false;
boolean hadFriendly = false;
boolean hasHostiles = false;
while(it.hasNext())
{
Critter c = (Critter) it.next();
if(c.hostile) hadHostiles = true;
else if(!c.inanimate && c!=player) hadFriendly = true;
if(c.hp <= 0 && c.stun_timer == 0 && c.max_hp > 0 && !c.airborne)
{
c.poof(); // may create loot
it.remove();
if(!c.hostile && !c.inanimate)
{
killedFriendly = true;
println("Killed friendly "+c.name);
}
}
else if(c.hostile) hasHostiles = true;
}
if(hadHostiles && !hasHostiles && player.hp > 0)
{
if(!muted) clearSound.trigger();
textParticles.add(new TextBlip(new PVector(width/2, height/2), 120, "Wave "+level+" Cleared!", color(128, 255, 255)));
level++;
toplevel = max(level, toplevel);
/*
if(!killedFriendly && hadFriendly)
{
textParticles.add(new TextBlip(new PVector(width/2, height/2), 180, "Rescue Bonus!", color(128, 255, 255)));
loot_drop.add(new Loot(width/2, height/2, rescue_award));
}*/
}
if(!hasHostiles) cleared = true;
else cleared = false;
}
critters.addAll(loot_drop);
loot_drop.clear();
//sort by Z-value for drawing
Collections.sort(critters, zSort);
}
}
abstract class Critter
{
PVector pos;
PVector vel;
PVector desired_vel;
PVector fidget;
PVector heading;
PVector facing;
float radius;
color fill_color;
color stroke_color;
int hp;
int max_hp;
String name;
float walk_speed;
float traction;
float air_traction;
boolean airborne;
int walk_timer;
int stun_timer;
float mass;
int loot_value;
int combo = -1;
ArrayList attacks;
int attack_timer;
boolean attack_cue;
boolean hostile;
boolean inanimate;
int name_timer;
void touched(Critter c)
{
if(max_hp > 0)
{
if(c.mass > mass && c.pos.z > pos.z && c.vel.z < -12 && stun_timer == 0)
injure(1, 20);
}
}
Critter(float x, float y, float z)
{
pos = new PVector(x, y, z);
radius = z;
vel = new PVector(0, 0);
desired_vel = new PVector(0, 0);
fidget = new PVector(0, 0);
heading = new PVector(0, 0);
facing = new PVector(0, -1);
walk_speed = 1;
traction = 1;
name = "Something";
airborne = false;
mass = 1;
attacks = new ArrayList();
name_timer = NAME_TIME;
loot_value = 2;
}
void resolveCollision(Critter c)
{
if(inRadius(pos, c.pos, radius+c.radius))
{
touched(c);
c.touched(this);
float overlap = (radius+c.radius) - PVector.dist(pos, c.pos);
float myEject;
if(mass == 0) myEject = 0; //zero-mass objects have infinite mass
else if(c.mass == 0) myEject = 1;
else myEject = 1-mass/(mass + c.mass);
PVector toThem = PVector.sub(c.pos, pos);
toThem.normalize();
pos.add(PVector.mult(toThem, -overlap*myEject));
c.pos.add(PVector.mult(toThem, overlap*(1-myEject)));
vel.add(PVector.mult(toThem, -myEject * overlap));
c.vel.add(PVector.mult(toThem, (1-myEject) * overlap));
}
}
void resolveAttack(Critter c)
{
if(combo > -1)
{
Attack a = (Attack) attacks.get(combo);
if(attack_timer >= a.warm_frames && attack_timer < a.warm_frames + a.active_frames)
{
PVector attackPos = new PVector(pos.x, pos.y, pos.z);
attackPos.add(PVector.mult(facing, a.distance));
if(inRadius(attackPos, c.pos, a.radius + c.radius) && c.stun_timer == 0)
{
c.injure(a.damage, a.stun_time);
if(c == theGiant)
{
theGiant.vexed = true;
theGiant.target = this;
textParticles.add(new TextBlip(theGiant.pos, 60, ">:O", color(255, 64, 0)));
}
if(c.mass != 0)
{
PVector away = PVector.sub(c.pos, pos);
away.z = 0;
away.normalize();
away.mult(a.knock_away);
away.z = a.knock_upward;
away.mult(11/(10+c.mass));
c.vel = away;
}
}
}
}
}
void injure(int amount, int stun)
{
hp -= amount;
stun_timer = stun;
if(max_hp != 0)textParticles.add(new TextBlip(pos, 60, ""+amount));
if(!muted) hitSound.trigger();
name_timer = NAME_TIME;
}
void poof()
{
for(int i = 0; i < 5; i++)
{
smokeParticles.add(new SmokePoof(pos, (int)radius + 5));
}
if(!muted) poofSound.trigger();
int lootValue = loot_value;
//if(!hostile) lootValue /= 2;
while(lootValue > 0)
{
int value = lootValue/4 + 1;
int drop_type = (int)random(3);
PVector location = randomVector(random(radius));
location.add(pos);
if(drop_type == 0 || drop_type == 1 || player.hp == player.max_hp || value > player.max_hp) loot_drop.add(new Loot(location.x, location.y, value));
else if(drop_type == 2) loot_drop.add(new Heart(location.x, location.y, value));
lootValue -= value;
}
}
void drawShadow()
{
pushMatrix();
translate(pos.x, pos.y);
translate(fidget.x, fidget.y);
noStroke();
fill(SHADOW_COLOR);
ellipse(0, 0, radius, radius);
popMatrix();
}
void draw()
{
pushMatrix();
translate(pos.x, pos.y);
translate(fidget.x, fidget.y);
translate(0, -Z_SCALE * pos.z);
strokeWeight(2);
fill(fill_color);
stroke(stroke_color);
if(stun_timer/2 % 2 == 0) ellipse(0, 0, radius, radius);
popMatrix();
}
void drawName()
{
textFont(font, 8);
textAlign(CENTER, BOTTOM);
fill(0);
text(name, (int)pos.x+1, (int)(pos.y - Z_SCALE * pos.z - radius - 8 + 1));
fill(255);
text(name, (int)pos.x, (int)(pos.y - Z_SCALE * pos.z - radius - 8));
if(max_hp > 0)
{
fill(0);
noStroke();
strokeWeight(1);
rect(pos.x - LIFEBAR_W/2, pos.y - Z_SCALE * pos.z - radius - LIFEBAR_H, LIFEBAR_W, LIFEBAR_H);
noStroke();
fill(255, 0, 0);
rect(pos.x - LIFEBAR_W/2, pos.y - Z_SCALE * pos.z - radius - LIFEBAR_H, map(max(hp, 0), 0, max_hp, 0, LIFEBAR_W), LIFEBAR_H);
}
}
void drawAttack()
{
if(combo > -1)
{
Attack a = (Attack) attacks.get(combo);
pushMatrix();
translate(pos.x, pos.y - Z_SCALE * pos.z);
translate(facing.x * a.distance, facing.y * a.distance);
a.draw(attack_timer);
popMatrix();
}
}
void step()
{
name_timer --;
/// PHYSICS
heading.normalize();
//hack to make monsters stop attacking a dead player
if(player.hp <= 0)
{
heading.x = 0;
heading.y = 0;
}
if(combo > -1 || stun_timer > 0) heading.mult(0);
stun_timer--;
if(stun_timer < 0) stun_timer = 0;
//else attack_cue = false;
if(pos.z <= radius)
{
pos.z = radius;
airborne = false;
if(vel.z<0) vel.z= 0;
}
else airborne = true;
if(hp <= 0) air_traction = 0;
float using_traction;
if(airborne) using_traction = air_traction;
else using_traction = traction;
PVector flatvel = new PVector(vel.x, vel.y);
//if(!airborne)
//{
desired_vel.x = heading.x * walk_speed;
desired_vel.y = heading.y * walk_speed;
if(PVector.dist(desired_vel, flatvel) < using_traction)
{
flatvel.x = desired_vel.x;
flatvel.y = desired_vel.y;
}
else
{
PVector steer = PVector.sub(desired_vel, flatvel);
steer.normalize();
steer.mult(using_traction);
flatvel.add(steer);
}
if((heading.x != 0 || heading.y != 0) && !airborne) //if heading's not zero and we're on the ground, update walk anim
{
walk_timer++;
int walk_frame = (int)(walk_timer / (radius / walk_speed))%4;
if(walk_frame %2 == 0) {
fidget.x = heading.x;
fidget.y = heading.y;
}
if(walk_frame == 1) {
fidget.x = -heading.y;
fidget.y = heading.x;
}
if(walk_frame == 3) {
fidget.x = heading.y;
fidget.y = -heading.x;
}
}
else
{
walk_timer = 0;
fidget.x = 0;
fidget.y = 0;
}
//}
vel.x = flatvel.x;
vel.y = flatvel.y;
if(airborne) vel.z -= GRAVITY;
pos.add(vel);
// if(this != player) /// bad practice!
{
if(pos.x < 0) {
pos.x = 0;
vel.x *= -1;
}
if(pos.x > width) {
pos.x = width;
vel.x *= -1;
}
if(pos.y < 0) {
pos.y = 0;
vel.y *= -1;
}
if(pos.y > height) {
pos.y = height;
vel.y *= -1;
}
}
if(heading.x != 0 || heading.y != 0)
{
facing.x = heading.x;
facing.y = heading.y;
facing.normalize();
}
////// ATTACKS
if(combo == -1 && attack_cue && !attacks.isEmpty() && player.hp > 0 && hp > 0)
{
combo = 0;
attack_cue = false;
attack_timer = 0;
}
if(combo > -1)
{
Attack a = (Attack) attacks.get(combo);
if(attack_timer == a.warm_frames)
{
if(!muted) a.sound.trigger();
textParticles.add(new TextBlip(new PVector(pos.x, pos.y - radius), 30, a.name, color(192)));
}
attack_timer++;
if(attack_timer >= a.warm_frames + a.active_frames + a.cool_frames)
{
if(attack_cue && attacks.size() > combo+1)
{
attack_cue = false;
combo++;
attack_timer = 0;
}
else if(attack_timer >= a.warm_frames + a.active_frames + a.cool_frames + COMBO_TIME)
{
combo = -1;
attack_cue = false;
}
}
}
}
}
class Dragon extends Critter
{
Dragon(float x, float y)
{
super(x, y, DRAGONDOT_RADIUS);
fill_color = DRAGONDOT_FILL;
stroke_color = DRAGONDOT_STROKE;
walk_speed = PLAYER_WALK_SPEED;
traction = 1;//PLAYER_WALK_SPEED*4;
air_traction = 0.05;
hp = max_hp = PLAYER_START_HP;
name = "Dragondot";
mass = PLAYER_MASS;
}
}
class Kobold extends Critter
{
Kobold(float x, float y)
{
super(x, y, KOBOLD_RADIUS);
fill_color = KOBOLD_FILL;
stroke_color = KOBOLD_STROKE;
walk_speed = 3;
traction = 1.0;//PLAYER_WALK_SPEED*4;
air_traction = 0.1;
hp = max_hp = 5;
name = "Kobold";
mass = 1;
}
void step()
{
/*if(!inRadius(pos, player.pos, 70))
heading = PVector.sub(player.pos, pos);
else{
heading.x = 0;
heading.y=0;
}
*/
heading.z = 0;
super.step();
//if(walk_timer == 1 && hp == max_hp) textParticles.add(new TextBlip(pos, 60, "<3", color(255, 128, 255)));
}
void poof()
{
super.poof();
textParticles.add(new TextBlip(pos, 60, ":(", color(128, 0, 128)));
}
}
class Goblin extends Critter
{
Goblin(float x, float y)
{
super(x, y, KOBOLD_RADIUS);
hostile = true;
fill_color = color(64, 192, 96);
stroke_color = color(128, 96, 64);
walk_speed = 1.5;
traction = 0.5;//PLAYER_WALK_SPEED*4;
hp = max_hp = 4;
name = "Goblin";
mass = 1;
attacks.add(new Knife());
loot_value = 2;
}
void step()
{
heading = PVector.sub(player.pos, pos);
heading.z = 0;
if(inRadius(player.pos, pos, player.radius + 20)) attack_cue = true;
super.step();
}
}
class Hobgoblin extends Critter
{
Hobgoblin(float x, float y)
{
super(x, y, 12);
hostile = true;
fill_color = color(255, 160, 96);
stroke_color = color(128, 96, 64);
walk_speed = 1;
traction = 0.5;//PLAYER_WALK_SPEED*4;
hp = max_hp = 8;
name = "Hobgoblin";
mass = 5;
attacks.add(new Club());
loot_value = 4;
}
void step()
{
heading = PVector.sub(player.pos, pos);
heading.z = 0;
if(inRadius(player.pos, pos, player.radius + 25)) attack_cue = true;
super.step();
}
}
class Worg extends Critter
{
Worg(float x, float y)
{
super(x, y, 12);
hostile = true;
fill_color = color(172, 160, 145);
stroke_color = color(162, 130, 96);
walk_speed = 2;
traction = 0.1;//PLAYER_WALK_SPEED*4;
hp = max_hp = 8;
name = "Worg";
mass = 3;
attacks.add(new WorgBite());
loot_value = 6;
}
void step()
{
heading = PVector.sub(player.pos, pos);
heading.z = 0;
if(inRadius(player.pos, pos, player.radius + 26)) attack_cue = true;
super.step();
}
}
class Drakeling extends Critter
{
Drakeling(float x, float y)
{
super(x, y, 13);
hostile = true;
fill_color = color(230, 50, 20);
stroke_color = color(100, 30, 0);
walk_speed = 2.5;
traction = 0.3;//PLAYER_WALK_SPEED*4;
air_traction = 0.3;
hp = max_hp = 9;
name = "Drakeling";
mass = 3;
attacks.add(new DrakeClaw());
attacks.add(new Claw());
attacks.add(new Bite());
loot_value = 20;
}
void step()
{
heading = PVector.sub(player.pos, pos);
heading.z = 0;
if(inRadius(player.pos, pos, player.radius + 30)) attack_cue = true;
super.step();
}
}
class DireWorg extends Critter
{
DireWorg(float x, float y)
{
super(x, y, 24);
hostile = true;
fill_color = color(172, 160, 145);
stroke_color = color(162, 130, 96);
walk_speed = 3;
traction = 0.1;//PLAYER_WALK_SPEED*4;
hp = max_hp = 20;
name = "Dire Worg";
mass = 20;
attacks.add(new DireWorgBite());
}
void step()
{
heading = PVector.sub(player.pos, pos);
heading.z = 0;
//facing = heading;
if(inRadius(player.pos, pos, player.radius + 54) && stun_timer == 0) attack_cue = true;
super.step();
}
}
class Ghost extends Critter
{
Ghost(float x, float y)
{
super(x, y, 12);
hostile = true;
fill_color = color(200, 200, 230);
stroke_color = color(0, 180, 230);
walk_speed = 3;
traction = 0.03;//PLAYER_WALK_SPEED*4;
hp = max_hp = 8;
name = "Ghost";
mass = 1;
attacks.add(new GhostAura());
loot_value = 10;
}
void step()
{
heading = PVector.sub(player.pos, pos);
heading.z = 0;
if(inRadius(player.pos, pos, player.radius + radius + 5)) attack_cue = true;
super.step();
}
}
class Peasant extends Critter
{
Peasant(float x, float y)
{
super(x, y, KOBOLD_RADIUS);
fill_color = color(255, 222, 208);
stroke_color = color(166, 79, 21);
walk_speed = 1;
traction = 0.5;//PLAYER_WALK_SPEED*4;
hp = max_hp = 1;
name = "Peasant";
mass = 1;
}
void step()
{
if(inRadius(pos, player.pos, 100))
heading = PVector.sub(pos, player.pos);
else{
heading.x = 0;
heading.y=0;
}
heading.z = 0;
super.step();
if(walk_timer == 1) textParticles.add(new TextBlip(pos, 60, ":O", color(0, 0, 128)));
}
}
class Wizard extends Critter
{
ArrayList closeAttacks;
ArrayList farAttacks;
Wizard(float x, float y)
{
super(x, y, KOBOLD_RADIUS);
closeAttacks = new ArrayList();
farAttacks = new ArrayList();
hostile = true;
fill_color = color(64, 96, 255);
stroke_color = color(0, 32, 128);
walk_speed = 2;
traction = 0.5;//PLAYER_WALK_SPEED*4;
hp = max_hp = 16;
name = "Wizard";
mass = 1;
closeAttacks.add(new ThunderWave());
farAttacks.add(new ScorchingBurst());
}
void step()
{
PVector flatmypos = new PVector(pos.x, pos.y);
PVector flatppos = new PVector(player.pos.x, player.pos.y);
if(inRadius(flatppos, flatmypos, 125))
{
heading = PVector.sub(flatmypos, flatppos);
heading.z = 0;
if(inRadius(player.pos, pos, player.radius + 50) && combo == -1)
{
attacks = closeAttacks;
attack_cue = true;
}
}
else if(!inRadius(flatmypos, flatppos, 175))
{
heading = PVector.sub(flatppos, flatmypos);
heading.z = 0;
}
else
{
if(combo == -1)
{
heading = PVector.sub(flatppos, flatmypos);
attacks = farAttacks;
attack_cue = true;
}
}
super.step();
}
}
class Rogue extends Critter
{
Rogue(float x, float y)
{
super(x, y, KOBOLD_RADIUS);
hostile = true;
fill_color = color(96, 96, 96);
stroke_color = color(16, 16, 16);
walk_speed = 4;
traction = 0.5;//PLAYER_WALK_SPEED*4;
hp = max_hp = 8;
name = "Ninja";
mass = 1;
attacks.add(new NinjaKnife());
loot_value = 8;
}
void step()
{
if(inRadius(player.pos, pos, player.radius + 20))
{
heading = PVector.sub(player.pos, pos);
attack_cue = true;
}
else
{
PVector dest = PVector.sub(player.pos, PVector.mult(player.facing, player.radius));
heading = PVector.sub(dest, pos);
}
super.step();
}
}
class Giant extends Critter
{
boolean vexed;
Critter target;
Giant(float x, float y)
{
super(x, y, 20);
hostile = false;
fill_color = color(230, 200, 170);
stroke_color = color(128, 96, 64);
walk_speed = 1;
traction = 0.5;//PLAYER_WALK_SPEED*4;
hp = max_hp = 20;
name = "Giant";
mass = 20;
attacks.add(new GiantClub());
vexed = false;
target = player;
loot_value = 60;
}
void step()
{
if(vexed)
heading = PVector.sub(target.pos, pos);
else {heading.x = 0; heading.y = 0;}
heading.z = 0;
if(inRadius(target.pos, pos, target.radius + 100) && stun_timer == 0 && vexed)
{
attack_cue = true;
vexed = false;
}
super.step();
}
void draw()
{
super.draw();
if(vexed)
{
fill(255, 0, 0, 64);
noStroke();
ellipse(pos.x, pos.y - pos.z*Z_SCALE, radius, radius);
}
}
}
class Loot extends Critter
{
int shiny_timer;
color base_color;
Loot(float x, float y, int value)
{
super(x, y, 3 + value);
vel = randomVector(0.5);
vel.z = 5+random(8);
stroke_color = color(192, 172, 60);
fill_color = base_color = color(255, 245, 64);
shiny_timer = 0;
walk_speed = 3;
traction = 0.05;//PLAYER_WALK_SPEED*4;
air_traction = 0.02;
hp = max_hp = value;
name = "Loot";
mass = 0.2;
inanimate = true;
}
void injure(int amount, int stun)
{
}
void touched(Critter c)
{
if(c == player) hp = 0;
}
void poof()
{
if(!muted) lootSound.trigger();
textParticles.add(new TextBlip(pos, 60, "+"+max_hp, base_color));
addScore(max_hp);
}
void drawName()
{
}
void step()
{
//if(world[world_x][world_y].cleared) vel.add(PVector.mult(PVector.sub(player.pos, pos), 0.0012));
super.step();
shiny_timer += (int)random(3);
if(shiny_timer > 60) shiny_timer = 0;
if(shiny_timer < 6) fill_color = color(255);
else fill_color = base_color;
}
}
class Heart extends Loot
{
Heart(float x, float y, int value)
{
super(x, y, value);
fill_color = base_color = color(255, 160, 192);
stroke_color = color(255, 32, 32);
}
void poof()
{
if(!muted) heartSound.trigger();
if(player.hp < player.max_hp) textParticles.add(new TextBlip(player.pos, 120, "<3", color(255, 128, 255)));
player.hp = min(player.hp + max_hp, player.max_hp);
player.name_timer = NAME_TIME;
textParticles.add(new TextBlip(pos, 60, "+"+max_hp, base_color));
}
}
void doControls()
{
player.heading.x = 0;
player.heading.y = 0;
if(keys[KEY_UP]) player.heading.y += -1;
if(keys[KEY_DOWN]) player.heading.y += 1;
if(keys[KEY_LEFT]) player.heading.x += -1;
if(keys[KEY_RIGHT]) player.heading.x += 1;
player.heading.normalize();
}
void levelUpTune()
{
if(!muted) levelUpSound.trigger();
bgm.setGain(-50);
bgm.shiftGain(-50.0, 0.0, 4000);
}
void addScore(int amt)
{
score+= amt;
topscore = max(score, topscore);
/*
if(score >= 25 && level <= 1)
{
levelUpTune();
level++;
textParticles.add(new TextBlip(player.pos, 180, "LEVEL UP!\n+5 HP!", color(128, 255, 255)));
player.hp = player.max_hp = player.max_hp + 5;
}
if(score >= 50 && level <= 2)
{
levelUpTune();
level++;
textParticles.add(new TextBlip(player.pos, 180, "LEVEL UP!\nGained Tail Sweep!", color(128, 255, 255)));
player.attacks.add(new TailSweep());
player.hp = player.max_hp;
//player.hp = player.max_hp = player.max_hp + 5;
}
if(score >= 75 && level <= 3)
{
levelUpTune();
level++;
textParticles.add(new TextBlip(player.pos, 180, "LEVEL UP!\n+5 HP!", color(128, 255, 255)));
player.hp = player.max_hp = player.max_hp + 5;
}
if(score >= 100 && level <= 4)
{
levelUpTune();
level++;
textParticles.add(new TextBlip(player.pos, 180, "LEVEL UP!\nGained Flight!", color(128, 255, 255)));
can_fly = true;
player.hp = player.max_hp;
}
if(score >= 125 && level <= 5)
{
levelUpTune();
level++;
textParticles.add(new TextBlip(player.pos, 180, "LEVEL UP!\n+5 HP!", color(128, 255, 255)));
player.hp = player.max_hp = player.max_hp + 5;
}
if(score >= 150 && level <= 6)
{
levelUpTune();
level++;
textParticles.add(new TextBlip(player.pos, 180, "LEVEL UP!\nClaw Power Up!", color(128, 255, 255)));
((Attack)player.attacks.get(0)).damage = 2;
((Attack)player.attacks.get(1)).damage = 2;
player.hp = player.max_hp;
}
if(score >= 175 && level <= 7)
{
levelUpTune();
level++;
textParticles.add(new TextBlip(player.pos, 180, "LEVEL UP!\n+5 HP!", color(128, 255, 255)));
player.hp = player.max_hp = player.max_hp + 5;
}
if(score >= 200 && level <= 8)
{
levelUpTune();
level++;
textParticles.add(new TextBlip(player.pos, 180, "LEVEL UP!\nBite and Tail Power Up!", color(128, 255, 255)));
((Attack)player.attacks.get(2)).damage = 4;
((Attack)player.attacks.get(3)).damage = 2;
player.hp = player.max_hp;
}
if(score >= 225 && level <= 9)
{
levelUpTune();
level++;
textParticles.add(new TextBlip(player.pos, 180, "LEVEL UP!\n+5 HP!", color(128, 255, 255)));
player.hp = player.max_hp = player.max_hp + 5;
}
*/
}
void zonePlayer()
{
boolean zoned = false;
if(player.pos.x < 0)
{
if(world_x > 0)
{
world_x --;
player.pos.x += width;
zoned = true;
}
else player.pos.x = 0;
}
if(player.pos.y < 0)
{
if(world_y > 0)
{
world_y --;
player.pos.y += height;
zoned = true;
}
else player.pos.y = 0;
}
if(player.pos.x > width)
{
if(world_x < WORLD_WIDTH - 1)
{
world_x ++;
player.pos.x -= width;
zoned = true;
}
else player.pos.x = width;
}
if(player.pos.y > height)
{
if(world_y < WORLD_HEIGHT - 1)
{
world_y ++;
player.pos.y -= height;
zoned = true;
}
else player.pos.y = height;
}
if(zoned)
{
for(int i = 0; i < world[world_x][world_y].critters.size(); i++)
{
Critter c = (Critter) world[world_x][world_y].critters.get(i);
if(c != player)
{
c.hp = c.max_hp;
c.name_timer = NAME_TIME;
}
}
textParticles.clear();
smokeParticles.clear();
}
}
void drawMap(float x, float y, float w, float h)
{
float cellw = w / WORLD_WIDTH;
float cellh = h / WORLD_HEIGHT;
for(int mapx = 0; mapx < WORLD_WIDTH; mapx++) for(int mapy = 0; mapy < WORLD_HEIGHT; mapy++)
{
float offx = x + cellw * mapx;
float offy = y + cellh * mapy;
if(world[mapx][mapy].cleared)
fill(0, 32, 64, 48);
else fill(64, 0, 0, 48);
noStroke();//stroke(192);
strokeWeight(1);
rect(offx, offy, cellw-1, cellh-1);
for(int i = 0; i < world[mapx][mapy].critters.size(); i++)
{
Critter c = (Critter) world[mapx][mapy].critters.get(i);
if(c != player && !c.inanimate)
{
noStroke();
if(c.hostile) fill(255, 0, 0);
else fill(0, 255, 255);
smooth();
ellipse(offx + map(c.pos.x, 0, width, 0, cellw), offy + map(c.pos.y, 0, height, 0, cellh), 2, 2);
noSmooth();
}
}
}
fill(255, 0, 255);
noStroke();
ellipse(x + cellw*world_x + map(player.pos.x, 0, width, 0, cellw), y + cellh*world_y + map(player.pos.y, 0, height, 0, cellh), 2, 2);
}
/////////////////////////////////////////////////////////////////////////////////////////////
void initializeWorld()
{
bgm.close();
bgm = minim.loadFile("koboldot.mp3", 4096);
if(muted) bgm.mute();
bgm.loop();
player = new Kobold(width/4, height*3/4);
theGiant = new Giant(width*3/4, height/4);
smokeParticles = new ParticleList();
textParticles = new ParticleList();
loot_drop = new ArrayList();
score = 0;
level = 1;
can_fly = false;
cheated = false;
won = false;
overlay_text = "";
world = new Screen[WORLD_WIDTH][WORLD_HEIGHT];
for(int wx = 0; wx < WORLD_WIDTH; wx++) for(int wy = 0; wy < WORLD_HEIGHT; wy++)
{
world[wx][wy] = new Screen();
world[wx][wy].critters.add(player);
}
world_x = WORLD_START_X;
world_y = WORLD_START_Y;
testScreen = world[world_x][world_y];
world[0][0].critters.add(theGiant);
//world[0][0].critters.add(new Goblin(width/2, height/2));
spawnEnemies();
//player.attacks.add(new Claw());
//player.attacks.add(new Claw());
//player.attacks.add(new Bite());
///player.attacks.add(new TailSweep());
/*
for(int i = 0; i < 5; i++)
world[2][2].critters.add(new Kobold(random(width), random(height)));
for(int i = 0; i < 4; i++)
world[1][2].critters.add(new Goblin(random(width), random(height)));
for(int i = 0; i < 3; i++)
world[2][1].critters.add(new Goblin(random(width), random(height)));
for(int i = 0; i < 3; i++)
world[2][1].critters.add(new Kobold(random(width), random(height)));
for(int i = 0; i < 3; i++)
world[1][1].critters.add(new Goblin(random(width), random(height)));
for(int i = 0; i < 2; i++)
world[1][1].critters.add(new Hobgoblin(random(width), random(height)));
world[1][1].critters.add(new Kobold(random(width), random(height)));
world[1][1].rescue_award = 7;
for(int i = 0; i < 3; i++)
world[1][3].critters.add(new Goblin(random(width), random(height)));
world[1][3].critters.add(new Hobgoblin(random(width), random(height)));
for(int i = 0; i < 2; i++)
world[2][3].critters.add(new Hobgoblin(random(width), random(height)));
for(int i = 0; i < 2; i++)
world[3][3].critters.add(new Worg(random(width), random(height)));
for(int i = 0; i < 2; i++)
world[3][2].critters.add(new Goblin(random(width), random(height)));
world[3][2].critters.add(new Worg(random(width), random(height)));
for(int i = 0; i < 2; i++)
world[3][1].critters.add(new Hobgoblin(random(width), random(height)));
world[3][1].critters.add(new Worg(random(width), random(height)));
world[0][1].critters.add(new Ghost(random(width), random(height)));
world[0][1].critters.add(new Kobold(random(width), random(height)));
world[0][1].rescue_award = 5;
world[1][0].critters.add(new Ghost(random(width), random(height)));
world[1][0].critters.add(new Worg(random(width), random(height)));
world[0][0].critters.add(new Ghost(random(width), random(height)));
world[0][0].critters.add(new Ghost(random(width), random(height)));
world[0][0].critters.add(new Ghost(random(width), random(height)));
for(int i = 0; i < 4; i++)
world[3][4].critters.add(new Worg(random(width), random(height)));
for(int i = 0; i < 3; i++)
world[4][3].critters.add(new Worg(random(width), random(height)));
world[4][3].critters.add(new Kobold(random(width), random(height)));
world[4][3].rescue_award = 10;
//testScreen.critters.add(new Boulder(random(width), random(height)));
world[4][4].critters.add(new DireWorg(width/2, height/2));
world[4][0].critters.add(new Wizard(width/2, height/2));
for(int i = 0; i < 5; i++)
{
world[3][0].critters.add(new Rogue(random(width), random(height)));
}
for(int i = 0; i < 4; i++)
{
world[2][0].critters.add(new Goblin(random(width), random(height)));
}
world[2][0].critters.add(new Rogue(random(width), random(height)));
world[2][0].critters.add(new Kobold(random(width), random(height)));
world[2][0].critters.add(new Kobold(random(width), random(height)));
world[2][0].rescue_award = 10;
world[4][2].critters.add(new Rogue(random(width), random(height)));
world[4][2].critters.add(new Worg(random(width), random(height)));
world[4][2].critters.add(new Worg(random(width), random(height)));
for(int i = 0; i < 4; i++)
{
world[4][1].critters.add(new Rogue(random(width), random(height)));
}
for(int i = 0; i < 3; i++)
{
world[4][1].critters.add(new Kobold(random(width), random(height)));
}
world[4][1].rescue_award = 10;
world[0][4].critters.add(new Giant(width/2, height/2));
world[0][4].critters.add(new Goblin(random(width), random(height)));
world[0][4].critters.add(new Goblin(random(width), random(height)));
for(int i = 0; i < 3; i++)
{
world[0][2].critters.add(new Kobold(random(width), random(height)));
world[0][2].critters.add(new Goblin(random(width), random(height)));
world[0][2].critters.add(new Hobgoblin(random(width), random(height)));
}
world[0][2].rescue_award = 7;
for(int i = 0; i < 5; i++)
{
world[0][3].critters.add(new Goblin(random(width), random(height)));
world[0][3].critters.add(new Hobgoblin(random(width), random(height)));
}
for(int i = 0; i < 9; i++)
{
world[1][4].critters.add(new Hobgoblin(random(width), random(height)));
}
world[2][4].critters.add(new Hobgoblin(random(width), random(height)));
world[2][4].critters.add(new Hobgoblin(random(width), random(height)));
world[2][4].critters.add(new Hobgoblin(random(width), random(height)));
world[2][4].critters.add(new Worg(random(width), random(height)));
world[2][4].critters.add(new Worg(random(width), random(height)));
*/
}
void setup()
{
at_title = true;
size(720, 480,P2D);
frameRate(60);
font = loadFont("PressStartK-32.vlw");
openSound();
//initializeWorld();
}
void draw()
{
if(!at_title)
{
if(player.hp <=0)
{
overlay_text = "GAME OVER\npress SPACE to try again\n\n\nTop score: "+ topscore+" Highest wave: "+toplevel;
bgm.pause();
}
else doControls();
background(BG_COLOR);
ellipseMode(RADIUS);
if(!paused) world[world_x][world_y].stepPhysics();
zonePlayer();
world[world_x][world_y].draw();
smokeParticles.draw();
if(!paused) smokeParticles.tick();
textParticles.draw();
if(!paused) textParticles.tick();
//drawMap(width-158, 8, 150, 100);
fill(255);
textAlign(LEFT, TOP);
text("Score: "+score+"\nWave: "+level+"\nHP: "+player.hp+"/"+player.max_hp, 8, 8);
//won = true;
boolean kobolds = true;
boolean massacre = true;
for(int x = 0; x < WORLD_WIDTH; x++) for(int y = 0; y < WORLD_HEIGHT; y++)
{
if(world[x][y].cleared == false) won = false;
if(world[x][y].killedFriendly == true) kobolds = false;
if(world[x][y].critters.isEmpty() == false) massacre = false;
}
/*
if(won)
{
overlay_text = "VICTORY!";
if(kobolds) overlay_text += "\nAnd all the kobolds survived! w00t!";
if(massacre) overlay_text += "\n...There's nothing left. o_O";
if(cheated) overlay_text += "\nNow try to do it without cheating!";
overlay_text += "\n\nPress SPACE to play again.";
}*/
textAlign(CENTER, TOP);
text(overlay_text, width/2, height/3);
}
else
{
background(BG_COLOR);
textFont(font, 8);
textAlign(CENTER, TOP);
text("GIANT VEX\n\nMonsters are back.\nDragon is not back.\nGiant is big stupid.\nTime is for kobold fun?\n\npress SPACE to play\n\nx = vex giant z = jump SPACE = pause", width/2, (int)(height/3));
}
}
void stop()
{
closeSound();
super.stop();
}
void togglePause()
{
paused = !paused;
if(paused) bgm.mute();
else if(!muted) bgm.unmute();
}
/////////////// INPUT HANDLING CODE
//input processing goes here:
void keyPressed()
{
if(!keys[keyCode])
{
keys[keyCode] = true;
down(keyCode);
}
}
void keyReleased()
{
if(keys[keyCode])
{
keys[keyCode] = false;
up(keyCode);
}
}
void down(int theKey)
{
if(!at_title)
{
if(theKey == 32 && (player.hp <= 0 || won))
{
initializeWorld(); // temporary game over
}
else if(theKey == 32) togglePause();
if(theKey == 'M')
{
muted = !muted;
if(bgm != null)
{
if(muted) bgm.mute();
else bgm.unmute();
}
}
if(!paused)
{
println(theKey + " down");
if(theKey == KEY_JUMP && player.combo == -1 && player.stun_timer == 0)
{
if(!player.airborne) player.vel.z = JUMP_STRENGTH;
else if(can_fly)
{
player.vel.mult(FLAP_DRAG);
player.vel.add(PVector.mult(player.heading, FLAP_SPEED));
if(player.pos.z < FLAP_CEILING) player.vel.z += (FLAP_STRENGTH * 1-(player.pos.z / FLAP_CEILING));
}
}
if(theKey == KEY_ATTACK && player.hp > 0) //player.attack_cue = true;
{
if(!muted) tauntSound.trigger();
textParticles.add(new TextBlip(player.pos, 60, ":P", color(255, 192, 128)));
if(!theGiant.vexed) textParticles.add(new TextBlip(theGiant.pos, 60, ">:O", color(255, 64, 0)));
theGiant.vexed = true;
theGiant.target = player;
}
/*
if(theKey == KEY_PHATLOOT) {
cheated = true;
addScore(25);
}
if(theKey == KEY_KILLALL)
{
cheated = true;
int sz = world[world_x][world_y].critters.size();
for(int i = 0; i < sz; i++)
{
Critter c = (Critter) world[world_x][world_y].critters.get(i);
if(c.hostile) c.hp = 0;
}
}
*/
}
}
else
{
if(theKey == 32)
{
at_title = false;
initializeWorld();
}
}
}
void up(int theKey)
{
println(theKey + " up");
}