import ddf.minim.*;
/**
* Game 18: "Dragondot's Sky"
* (lots to load, be patient!)
* Tips:
* *Charge your attack to spit a fireball.
* *The longer you take to beat enemies, the more they'll move on the map.
* *Different bosses are vulnerable at different moments.
*
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.
*/
float THREAT_SCALING = 0.7;
float MOVEMENT_SCALING = 0.5;
int KOBOLDS_NEEDED = 15;
float RECRUIT_DELAY = 4;
float GAME_START_ADVANCE = 8;
int game_over_timer;
boolean cheats = false;
boolean[] keys = new boolean[256];
boolean title;
boolean paused;
boolean muted;
boolean dash_charged;
int drawing_ms_last;
int draw_frame;
int physics_frame;
int physics_ms_last;
int CORE_FPS = 540;
int DRAWING_FPS = 60;
int PHYSICS_FPS = 180;
int DRAW_MS = 1000 / DRAWING_FPS;
int PHYS_MS = 1000 / PHYSICS_FPS;
int WIDTH = 720;
int HEIGHT = 480;
Minim minim;
AudioPlayer music;
AudioSample fightWhoosh;
AudioSample dashCharge;
AudioSample dashReady;
AudioSample dashGo;
AudioSample clawSound;
AudioSample biteSound;
AudioSample hintSound;
AudioSample timeSound;
AudioSample mapBlonk;
AudioSample fireCharge;
AudioSample fireSpit1;
AudioSample fireSpit2;
AudioSample fireReady;
AudioSample hitSound;
AudioSample poofSound;
AudioSample ddBip;
AudioSample foeBip;
AudioSample marchSound;
AudioSample routRiff;
AudioSample peckSound;
AudioSample reflectSound;
void audioSetup()
{
fightWhoosh = minim.loadSample("battle_transition_3.wav", 1024);
dashCharge = minim.loadSample("dash_charge_start.wav", 1024);
dashReady = minim.loadSample("dash_charged.wav", 1024);
dashGo = minim.loadSample("dash.wav", 1024);
clawSound = minim.loadSample("claw.wav", 1024);
biteSound = minim.loadSample("bite.wav", 1024);
hintSound = minim.loadSample("hint.wav", 1024);
timeSound = minim.loadSample("timetick.wav", 1024);
mapBlonk = minim.loadSample("mapblonk.wav", 1024);
fireCharge = minim.loadSample("fireball_charge.wav", 1024);
fireSpit1= minim.loadSample("fireball2.wav", 1024);
fireSpit2= minim.loadSample("fireball3.wav", 1024);
fireReady =minim.loadSample("fire_ready.wav", 1024);
hitSound = minim.loadSample("hit.wav", 1024);
poofSound = minim.loadSample("poof.wav", 1024);
poofSound.setGain(-5);
ddBip = minim.loadSample("ddtalk.wav", 1024);
foeBip = minim.loadSample("foetalk.wav", 1024);
marchSound = minim.loadSample("march.wav", 1024);
marchSound.setGain(-15);
routRiff = minim.loadSample("rout.wav", 1024);
peckSound = minim.loadSample("peck.wav", 1024);
reflectSound = minim.loadSample("nodamage.wav", 1024);
}
void stop()
{
if(music != null) music.close();
fightWhoosh.close();
dashCharge.close();
dashReady.close();
dashGo.close();
clawSound.close();
biteSound.close();
hintSound.close();
timeSound.close();
mapBlonk.close();
fireCharge.close();
fireSpit1.close();
fireSpit2.close();
fireReady.close();
hitSound.close();
poofSound.close();
ddBip.close();
foeBip.close();
marchSound.close();
routRiff.close();
peckSound.close();
reflectSound.close();
minim.stop();
super.stop();
}
void bgm(String file)
{
if(music != null) music.close();
music = minim.loadFile(file, 2048);
if(muted) music.mute();
music.loop();
}
void bgmOnce(String file)
{
if(music != null) music.close();
music = minim.loadFile(file, 2048);
if(muted) music.mute();
music.play();
}
int[][] map_threat;
int[][] kobolds;
float[][] kobold_peril;
int kobolds_remaining;
int player_map_x;
int player_map_y;
ArrayList all_enemies;
ArrayList battle_enemies;
ArrayList clouds;
ArrayList dialog_queue;
ParticleList particles;
ParticleList screen_particles;
boolean boss_fight;
Enemy killed_boss;
Enemy last_hit_enemy;
Boss bossNW;
Boss bossNE;
Boss bossSW;
Boss bossSE;
int battle_clock;
float battle_finish_time;
int game_clock;
int FRAMES_PER_TICK = PHYSICS_FPS * 3;
int WORLD_W = 5;
int WORLD_H = 5;
int TILE_W = 130;
int TILE_H = 80;
int BANNER_H = 16;
float SKY_LENGTH = WIDTH * 10;
color NORMAL_SKY = color(32, 192, 255);
color DARK_SKY = color(16, 64, 128);//color(64, 32, 128);
color NORMAL_CLOUDS = color(255, 255, 255);
color DARK_CLOUDS = color(128, 148, 168);//color(255, 192, 128);
color GROUND_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);
float DRAGONDOT_RADIUS = 16;
color DRAGONDOT_FILL = color(192, 16, 64);
color DRAGONDOT_STROKE = color(148, 0, 32);
color ATTACK_TEXT = color(220);
int NUM_CLOUDS = 80;
int transition_timer;
int TRANSITION_TIME = 250;
int battle_wrap_timer;
int BATTLE_WRAP_TIME = 700;
int BOSS_WRAP_TIME = 1200;
int hint_timer;
int HINT_TIME = 180;
String hint_message = "";
boolean map_management_to_do;
boolean map_ready;
float diamonds_timer;
float DIAMONDS_MAX = 100;
float DIAMONDS_RATE = 1;
PVector player_pos;
PVector player_recoil;
float PLAYER_RECOIL_RECOVER = 0.05;
PVector camera_pos;
float player_heading;
float player_target_heading;
float PLAYER_BASE_SPEED = 1.0;
float PLAYER_GRAVITY_BONUS = 5.5;
float PLAYER_BASE_TURN = 0.015;
float player_speed;
int player_life;
int PLAYER_MAX_LIFE = 20;
int player_hitstun;
float brake_meter;
float BRAKE_CHARGE_RATE = 0.01;
float BRAKE_MIN_SPEED = 0.75;
float BRAKE_TURN_BONUS = PLAYER_BASE_TURN * 1;
float boost_meter;
float BOOST_DEPLETE_RATE = 0.007;
float BOOST_MAX_SPEED = 6.0;
int attack_timer;
int combo_count;
int fireball_charge;
int fireball_life;
int FIREBALL_MAX_LIFE = 200;
PVector fireball_pos;
PVector fireball_vel;
int fireball_power;
float FIREBALL_RADIUS = DRAGONDOT_RADIUS * 1.7;
int attack_key_frames;
boolean attack_buffered;
int CLAW_ACTIVE = 18;
int CLAW_COOL = 24;
int CLAW_DIST = 12;
int CLAW_RAD = 25;
int CLAW_DAM = 1;
int BITE_ACTIVE = 18;
int BITE_COOL = 24;
int BITE_DIST = 24;
int BITE_RAD = 20;
int BITE_DAM = 2;
int BUFFER_TIME = 80;
int FIREBALL_MIN_CHARGE = 200;
int FIREBALL_CHARGE_WINDOW = 30;
int STUN_DURATION = 42;
int THROES_DURATION = 120;
void processAttack()
{
attack_timer++;
if(attack_timer > BUFFER_TIME) combo_count = -1;
if(keys[ATTACK_KEY] && battle_wrap_timer == 0) attack_key_frames++;
else attack_key_frames = 0;
if(attack_key_frames == 1)
{
if(combo_count == -1)
{
combo_count = 0;
attack_timer = 0;
if(!muted) clawSound.trigger();
callAttack(player_pos, "claw!");
}
else if((combo_count == 0 || combo_count == 1))
{
attack_buffered = true;
}
}
if(attack_buffered && attack_timer > CLAW_ACTIVE + CLAW_COOL)
{
if(combo_count < 2)
{
combo_count++;
attack_buffered = false;
attack_timer = 0;
if(combo_count < 2)
{
if(!muted) clawSound.trigger();
callAttack(player_pos, "claw!");
}
else
{
if(!muted) biteSound.trigger();
callAttack(player_pos, "bite!");
}
}
}
if(attack_key_frames > 0 && !attack_buffered && attack_timer > CLAW_ACTIVE + CLAW_COOL)
{
if(fireball_charge == 0) if(!muted) fireCharge.trigger();
fireball_charge++;
if(fireball_charge == FIREBALL_MIN_CHARGE)
{
fireCharge.stop();
if(!muted) fireReady.trigger();
}
}
if(attack_key_frames == 0)
{
if(fireball_charge > FIREBALL_MIN_CHARGE)
{
if(fireball_charge <= FIREBALL_MIN_CHARGE + FIREBALL_CHARGE_WINDOW) doFireball(2);
else doFireball(1);
}
if(fireball_charge > 0) fireCharge.stop();
fireball_charge = 0;
}
/// hit enemies
Iterator ie = battle_enemies.iterator();
PVector attack_center = new PVector(0, 0);
float attack_radius = 0;
boolean attack_active = false;
int attack_damage = 0;
if((combo_count == 0 || combo_count == 1) && attack_timer <= CLAW_ACTIVE)
{
attack_active = true;
attack_center = PVector.add(player_pos, new PVector(cos(player_heading)*CLAW_DIST, sin(player_heading)*CLAW_DIST));
attack_damage = 1;
attack_radius = CLAW_RAD;
}
if((combo_count == 2) && attack_timer <= BITE_ACTIVE)
{
attack_active = true;
attack_center = PVector.add(player_pos, new PVector(cos(player_heading)*BITE_DIST, sin(player_heading)*BITE_DIST));
attack_damage = 2;
attack_radius = BITE_RAD;
}
if(attack_active) while(ie.hasNext())
{
Enemy e = (Enemy) ie.next();
if(inRadius(e.pos, attack_center, attack_radius + e.radius))
{
PVector away = PVector.sub(e.pos, player_pos);
away.normalize();
away.mult(2);
if(combo_count == 2) away.mult(0);
int success = e.smack(attack_damage, away);
//if(success != -1)
// player_recoil.add(PVector.mult(away, -1));
}
}
}
void drawAttack()
{
PVector attack_center = new PVector(0, 0);
float attack_radius = 0;
int attack_damage = 0;
if((combo_count == 0 || combo_count == 1) && attack_timer <= CLAW_ACTIVE)
{
attack_center = PVector.add(player_pos, new PVector(cos(player_heading)*CLAW_DIST, sin(player_heading)*CLAW_DIST));
attack_radius = CLAW_RAD;
//fill(255, map(attack_timer, 0, CLAW_ACTIVE, 255, 0));
//noStroke();
//ellipse(attack_center.x, attack_center.y, attack_radius, attack_radius);
drawSlash(attack_center, attack_radius, attack_timer / (float) CLAW_ACTIVE);
}
if((combo_count == 2) && attack_timer <= BITE_ACTIVE)
{
attack_center = PVector.add(player_pos, new PVector(cos(player_heading)*BITE_DIST, sin(player_heading)*BITE_DIST));
attack_radius = BITE_RAD;
//fill(255, map(attack_timer, 0, CLAW_ACTIVE, 255, 0));
//noStroke();
//ellipse(attack_center.x, attack_center.y, attack_radius, attack_radius);
drawBite(attack_center, attack_radius, attack_timer / (float) BITE_ACTIVE);
}
}
boolean fireball_hostile;
void doFireball(int strength)
{
fireball_hostile = false;
if(strength == 2)
{
if(!muted) fireSpit1.trigger();
if(!muted) fireSpit2.trigger();
callAttack(player_pos, "fireball!!");
}
else
{
if(!muted) fireSpit2.trigger();
callAttack(player_pos, "fireball!");
}
fireball_pos = new PVector(player_pos.x + cos(player_heading)*FIREBALL_RADIUS, player_pos.y + sin(player_heading)*FIREBALL_RADIUS);
fireball_vel = new PVector(cos(player_heading)*(3+player_speed), sin(player_heading)*(3+player_speed));
fireball_life = FIREBALL_MAX_LIFE;
fireball_power = strength;
}
void processFireball()
{
if(fireball_life > 0)
{
fireball_life --;
fireball_pos.add(fireball_vel);
Iterator ie = battle_enemies.iterator();
while(ie.hasNext())
{
Enemy e = (Enemy) ie.next();
if(inRadius(e.pos, fireball_pos, e.radius + FIREBALL_RADIUS))
{
PVector away = PVector.sub(e.pos, fireball_pos);
away.normalize();
away.mult(2);
e.smack(fireball_power*2, away);
}
}
if(fireball_hostile && inRadius(player_pos, fireball_pos, DRAGONDOT_RADIUS + FIREBALL_RADIUS))
{
PVector away = PVector.sub(player_pos, fireball_pos);
away.normalize();
away.mult(5);
smackPlayer(fireball_power*2, away);
fireball_hostile = false;
}
if(physics_frame % 3 == 0)
{
if(fireball_power == 2)
{
PVector fireball_heading = new PVector(fireball_vel.x, fireball_vel.y);
fireball_heading.normalize();
float wave = sin(physics_frame / 12.0);
PVector displace = new PVector(-fireball_heading.y * wave * FIREBALL_RADIUS, fireball_heading.x * wave * FIREBALL_RADIUS);
particles.add(new Ember(PVector.add(fireball_pos, displace)));
displace.mult(-1);
particles.add(new Ember(PVector.add(fireball_pos, displace)));
}
else particles.add(new Ember(PVector.add(fireball_pos, randomVector(random(FIREBALL_RADIUS/2)))));
}
}
}
void drawFireball()
{
if(fireball_life > 0)
{
fill(255, 127+64*((draw_frame / 2)%3), 0);
noStroke();
ellipse(fireball_pos.x, fireball_pos.y, FIREBALL_RADIUS, FIREBALL_RADIUS);
}
}
int last_dir = 1;
int LOW_PERCENT = 20;
int MED_PERCENT = 50;
color percentColor(int percent)
{
if(percent == 0) return color(0, 255, 255);
if(percent < LOW_PERCENT) return color(0, 255, 0);
if(percent < MED_PERCENT) return color(255, 255, 0);
if(percent < 100) return color(255, 64, 0);
return color(255, 96*((draw_frame/3)%2),96*((draw_frame/3)%2));
}
int game_state;
int TITLE = 0;
int MAP_SCREEN = 1;
int BATTLE_TRANSITION = 2;
int IN_LEVEL = 3;
char ATTACK_KEY = 'X';
char DASH_KEY = 'Z';
PFont font;
void engage()
{
if(game_state == MAP_SCREEN && transition_timer == 0)
{
transition_timer = 1;
music.mute();
music.pause();
if(!muted) fightWhoosh.trigger();
}
}
void calculateThreat()
{
kobolds_remaining = 0;
for(int x = 0; x < WORLD_W; x++)for(int y = 0; y < WORLD_H; y++)
{
map_threat[x][y] = 0;
kobolds_remaining += kobolds[x][y];
}
for(int i = 0; i < all_enemies.size(); i++)
{
Enemy e = (Enemy) all_enemies.get(i);
map_threat[e.map_x][e.map_y] += e.threat_level;
if(map_threat[e.map_x][e.map_y] > 100) map_threat[e.map_x][e.map_y] = 100;
}
for(int x = 0; x < WORLD_W; x++)for(int y = 0; y < WORLD_H; y++)
{
if(map_threat[x][y] == 0) kobold_peril[x][y] = 0;
if(kobolds[x][y] == 0) kobold_peril[x][y] = 0;
}
}
Boss theTestBoss;
void newGame()
{
map_threat = new int[WORLD_W][WORLD_H];
kobolds = new int[WORLD_W][WORLD_H];
kobold_peril = new float[WORLD_W][WORLD_H];
kobolds[2][2] = 9;
kobolds[1][2] = kobolds[3][2] = kobolds[2][1] = kobolds[2][3] = 3;
kobolds[1][1] = kobolds[1][3] = kobolds[3][1] = kobolds[3][3] = 1;
all_enemies = new ArrayList();
dialog_queue = new ArrayList();
game_clock = 0;
battle_clock = 0;
battle_finish_time = 0;
player_map_x = player_map_y = 2;
//bgm("select_music.mp3");
//game_state = MAP_SCREEN;
bossNW = new Turtle(0, 0);
bossNE = new Pterodactyl(4, 0);
bossSW = new Wyvern(0, 4);
bossSE = new BigBuzzard(4, 4);
all_enemies.add(bossNW);
all_enemies.add(bossNE);
all_enemies.add(bossSW);
all_enemies.add(bossSE);
while(bossNW.recruit() || bossNE.recruit() || bossSW.recruit() || bossSE.recruit()); //one-liner
Iterator ie = all_enemies.iterator();
while(ie.hasNext())
{
Enemy e = (Enemy) ie.next();
e.tickTime(GAME_START_ADVANCE);
}
game_over_timer = 0;
setUpMap();
clouds = new ArrayList();
for(int i = 0; i < NUM_CLOUDS; i++)
clouds.add(new PVector(random(width * 2 - width/2), random(height), (i/(float)NUM_CLOUDS)));
game_state = TITLE;
}
boolean been_sad;
void setUpMap()
{
particles = new ParticleList();
map_management_to_do = false;
map_ready = false;
been_sad = false;
game_state = MAP_SCREEN;
transition_timer = -TRANSITION_TIME;
Iterator ie = all_enemies.iterator();
while(ie.hasNext())
{
Enemy e = (Enemy) ie.next();
if(e.is_dead)
{
ie.remove();
if(e.is_boss)
{
killed_boss = e;
map_management_to_do = true;
}
}
else
{
e.tickTime(battle_finish_time/10.0);
if(e.wander_timer >= 1)
map_management_to_do = true;
}
}
calculateThreat();
}
void setUpBattle(int mapx, int mapy)
{
battle_enemies = new ArrayList();
boss_fight = false;
killed_boss = null;
for(int i = 0; i < all_enemies.size(); i++)
{
Enemy e = (Enemy) all_enemies.get(i);
if(e.map_x == mapx && e.map_y == mapy)
{
if(e.is_boss)
{
boss_fight = true;
e.pos = new PVector(SKY_LENGTH - WIDTH/2, HEIGHT/2);
}
else e.pos = new PVector(WIDTH + random(SKY_LENGTH-WIDTH), random(HEIGHT));
e.skyEntry();
battle_enemies.add(e);
}
}
clouds = new ArrayList();
for(int i = 0; i < NUM_CLOUDS; i++)
clouds.add(new PVector(random(width * 2 - width/2), random(height), (i/(float)NUM_CLOUDS)));
//boss_fight = true;
if(all_enemies.isEmpty()) bgm("credits_music.mp3");
else if(boss_fight) bgm("boss_music.mp3");
else bgm("sky_music.mp3");
game_state = IN_LEVEL;
diamonds_timer = 0;
player_pos = new PVector(width/2 - WIDTH, height/2);
camera_pos = new PVector(0 - WIDTH, 0);
player_heading = 0;
player_target_heading = 0;
last_dir = 1;
battle_clock = 0;
battle_finish_time = 0;
brake_meter = 0;
boost_meter = 0;
dash_charged = false;
particles = new ParticleList();
screen_particles = new ParticleList();
dialog_queue = new ArrayList();
battle_wrap_timer = 0;
hint_timer = 0;
fireball_charge = 0;
fireball_life = 0;
attack_timer = 0;
combo_count = -1;
player_recoil = new PVector(0, 0);
player_life = PLAYER_MAX_LIFE;
player_hitstun = 0;
last_hit_enemy = null;
}
void setup()
{
size(720, 480);
frameRate(600);
minim = new Minim(this);
audioSetup();
font = loadFont("PressStartK-32.vlw");
newGame();
}
int letters_showing;
int letter_timer;
int LETTER_TIME = 15;
int mapstuff_timer = 0;
int MAPSTUFF_TIME = 15;
String topic_text = "";
void physicsStep()
{
if(dialog_queue.isEmpty()) physics_frame++;
if(game_state == MAP_SCREEN)
{
particles.tick();
if(transition_timer != 0) {
transition_timer ++;
topic_text = "";
}
if(!map_ready)
{
if(transition_timer == 0)
{
//behold a nightmare of flow control!
if(mapstuff_timer == 0) //dead enemies go poof
{
Iterator ie = all_enemies.iterator();
while(ie.hasNext())
{
Enemy e = (Enemy) ie.next();
if(e.is_dead)
{
float orbitphase = 100 + draw_frame * 0.05;
poof(e.radius/4, new PVector(xcen(e.map_x) + 0.9 *TILE_W / 2 * sin(e.lissa_x * orbitphase), ycen(e.map_y) + 0.9* TILE_H / 3 * sin(e.lissa_y * orbitphase) - 32 + 16*sin(e.lissa_z * orbitphase)));
mapstuff_timer = MAPSTUFF_TIME;
ie.remove();
calculateThreat();
break;
}
}
}
if(mapstuff_timer == 0) //handle rout
{
if(bossNW.is_dead && bossNE.is_dead && bossSW.is_dead && bossSE.is_dead && !all_enemies.isEmpty())
{
topic_text = "Enemy forces routed!";
if(!muted) routRiff.trigger();
mapstuff_timer = 270;
Iterator ie = all_enemies.iterator();
while(ie.hasNext())
{
Enemy e = (Enemy) ie.next();
//if(e.allegiance == killed_boss)
//{
e.is_dead = true;
//}
}
killed_boss = null;
}
}
if(mapstuff_timer == 0) //oh noes, killing kobolds!
{
boolean broke = false;
topic_text = "Oh no! Kobolds slain!";
for(int x = 0; x < WORLD_W; x++)
{
for(int y = 0; y < WORLD_H; y++)
{
if(kobold_peril[x][y] >= 100)
{
if(!been_sad)
{
bgmOnce("defeated.wav");
been_sad = true;
mapstuff_timer = 270;
}
else
{
kobolds[x][y] --;
calculateThreat();
poof(3, new PVector(xcen(x)+random(TILE_W)-TILE_W/2, ycen(y)+random(TILE_H)-TILE_H/2));
mapstuff_timer = MAPSTUFF_TIME * 3;
}
broke = true;
break;
}
if(broke) break;
}
}
}
if(mapstuff_timer == 0) //handle wandering
{
Iterator ie = all_enemies.iterator();
Enemy w = null;
int count = 0;
while(ie.hasNext())
{
Enemy e = (Enemy) ie.next();
if(e.wander_timer >= 1)
{
count++;
if(random(count) <= 1) w = e;
}
}
if(w != null)
{
topic_text = "Enemies advancing...";
if(w.mapWander()) mapstuff_timer = MAPSTUFF_TIME;
else mapstuff_timer = 1;
}
}
if(mapstuff_timer == 0) //reinforcements
{
if(bossNW != null && bossNW.recruit()) mapstuff_timer = MAPSTUFF_TIME;
if(bossNE != null && bossNE.recruit()) mapstuff_timer = MAPSTUFF_TIME;
if(bossSW != null && bossSW.recruit()) mapstuff_timer = MAPSTUFF_TIME;
if(bossSE != null && bossSE.recruit()) mapstuff_timer = MAPSTUFF_TIME;
topic_text = "Enemies reinforcing...";
}
if(mapstuff_timer == 0)
{
if(!all_enemies.isEmpty())
{
bgm("select_music.mp3");
map_ready = true;
topic_text = "Select an area:";
}
else
{
bgmOnce("game_clear_music.mp3");
map_ready = true;
topic_text = "Victory!";
}
}
mapstuff_timer --;
if(mapstuff_timer < 0) mapstuff_timer = 0;
}
}
if(music != null && !music.isPlaying() && all_enemies.isEmpty() && map_ready)
{
engage();
}
if(kobolds_remaining < KOBOLDS_NEEDED && map_ready)
{
game_over_timer++;
music.pause();
}
if(transition_timer == TRANSITION_TIME)
{
setUpBattle(player_map_x, player_map_y);
}
}
if(!dialog_queue.isEmpty())
{
DialogItem di = (DialogItem) dialog_queue.get(0);
letter_timer ++;
if(keys[ATTACK_KEY]) letter_timer += 3;
if(letter_timer >= LETTER_TIME && letters_showing < di.message.length())
{
letter_timer = 0;
letters_showing ++;
if(Character.isLetter(di.message.charAt(letters_showing - 1)))
{
if(di.speaker == null)
{
if(!muted) ddBip.trigger();
}
else if(!muted) foeBip.trigger();
}
}
}
if(game_state == IN_LEVEL && dialog_queue.isEmpty())
{
letters_showing = 0;
letter_timer = 0;
particles.tick();
screen_particles.tick();
if(battle_wrap_timer == 0) battle_clock++;
int steer_x = 0;
int steer_y = 0;
if(battle_wrap_timer == 0)
{
if(keys[LEFT]) {
steer_x -= 1;
}
if(keys[RIGHT]) {
steer_x += 1;
}
if(keys[UP]) steer_y -= 1;
if(keys[DOWN]) steer_y += 1;
}
if(cos(player_heading) > 0.1) last_dir = 1;
if(cos(player_heading) < -0.1) last_dir = -1;
if(steer_x == 0 && steer_y == 0)
{
steer_x = last_dir;
}
if(player_pos.y < 0) steer_y = 1;
if(player_pos.y > HEIGHT) steer_y = -1;
player_target_heading = atan2(steer_y, steer_x);
if(player_life == 0) player_target_heading = HALF_PI; //crash when dead
player_heading = angleTowards(player_heading, player_target_heading, PLAYER_BASE_TURN + brake_meter * BRAKE_TURN_BONUS);
float gravy = sqrt(max(PLAYER_GRAVITY_BONUS * player_pos.y / HEIGHT, 0.05));
player_speed = (PLAYER_BASE_SPEED + gravy);
if(keys['Z'] && battle_wrap_timer == 0)
{
if(boost_meter <= 0)
{
if(brake_meter == 0) if(!muted) dashCharge.trigger();
brake_meter+= BRAKE_CHARGE_RATE;
}
if(brake_meter >= 1)
{
brake_meter = 1;
if(!dash_charged) if(!muted) dashReady.trigger();
dash_charged = true;
}
}
else
{
dash_charged = false;
if(brake_meter >= 1)
{
boost_meter = 1;
brake_meter = 0;
player_heading = player_target_heading;
if(!muted) dashGo.trigger();
particles.add(new BoostWave(player_pos));
}
else
{
brake_meter -= BRAKE_CHARGE_RATE;
if(brake_meter < 0) brake_meter = 0;
}
}
if(brake_meter > 0) player_speed = map(brake_meter, 0, 1, player_speed, BRAKE_MIN_SPEED);
else if(boost_meter > 0)
{
player_speed = map(boost_meter, 0, 1, player_speed, BOOST_MAX_SPEED);
boost_meter -= BOOST_DEPLETE_RATE;
if(boost_meter > 0.5 && physics_frame % 15 == 0) particles.add(new DashEcho(player_pos));
}
player_pos.x += cos(player_heading) * player_speed;
player_pos.y += sin(player_heading) * player_speed;
//Do player recoil
player_pos.add(player_recoil);
if(player_recoil.mag() < PLAYER_RECOIL_RECOVER) player_recoil.x = player_recoil.y = 0;
else
{
PVector recoil_cancel = new PVector(player_recoil.x, player_recoil.y);
recoil_cancel.normalize();
recoil_cancel.mult(-PLAYER_RECOIL_RECOVER);
player_recoil.add(recoil_cancel);
}
if(player_hitstun > 0) player_hitstun--;
float cam_delta = (player_pos.x +(cos(player_heading)) * 200 - WIDTH/2 - camera_pos.x)/30;
if(battle_wrap_timer % 30 == 1 && kobolds[player_map_x][player_map_y] > 0 && player_life > 0)
{
particles.add(new TextBlip(new PVector(camera_pos.x + random(WIDTH), HEIGHT), 270, "<3", color(255, 80, 255)));
}
if(battle_wrap_timer > 0 && battle_wrap_timer < BATTLE_WRAP_TIME / 2) cam_delta = 0;
moveClouds(-cam_delta);
camera_pos.x += cam_delta;
float enemy_left_extent = 100000;
float enemy_right_extent = -100000;
Iterator ie = battle_enemies.iterator();
while(ie.hasNext())
{
Enemy e = (Enemy) ie.next();
enemy_left_extent = min(enemy_left_extent, e.pos.x);
enemy_right_extent = max(enemy_right_extent, e.pos.x);
}
if(battle_enemies.size() > 0)
{
if(player_pos.x < enemy_left_extent - WIDTH*2)
{
float difference = (enemy_left_extent - WIDTH*2) - player_pos.x;
player_pos.x += difference;
camera_pos.x += difference;
if(fireball_life > 0) fireball_pos.x += difference;
Iterator pi = particles.iterator();
while(pi.hasNext())
{
Particle p = (Particle) pi.next();
p.pos.x += difference;
}
if(hint_timer == 0 && cos(player_heading) < 0)
{
hint_timer = HINT_TIME;
hint_message = "ENEMY -->";
if(!muted) hintSound.trigger();
}
}
if(player_pos.x > enemy_right_extent + WIDTH*2)
{
float difference = (enemy_right_extent + WIDTH*2) - player_pos.x;
player_pos.x += difference;
camera_pos.x += difference;
if(fireball_life > 0) fireball_pos.x += difference;
Iterator pi = particles.iterator();
while(pi.hasNext())
{
Particle p = (Particle) pi.next();
p.pos.x += difference;
}
if(hint_timer == 0 && cos(player_heading) > 0)
{
hint_timer = HINT_TIME;
hint_message = "<-- ENEMY";
if(!muted) hintSound.trigger();
}
}
}
processAttack();
processFireball();
ie = battle_enemies.iterator();
//DO ENEMY AI///////////////////////////////////////////////////////////////////////////////////////////////
while(ie.hasNext())
{
Enemy e = (Enemy) ie.next();
e.skyTick();
//slam attack
if(inRadius(e.pos, player_pos, DRAGONDOT_RADIUS + e.radius) && boost_meter > 0.5)
{
PVector away = PVector.sub(e.pos, player_pos);
away.normalize();
away.mult(3);
e.smack(1, away);
}
//collision ejection
if(inRadius(e.pos, player_pos, DRAGONDOT_RADIUS + e.radius))
{
PVector from_player = PVector.sub(e.pos, player_pos);
float overlap = DRAGONDOT_RADIUS + e.radius - from_player.mag();
float player_relative_mass = DRAGONDOT_RADIUS / (DRAGONDOT_RADIUS + e.radius);
from_player.normalize();
e.pos.add(PVector.mult(from_player, player_relative_mass * overlap));
player_pos.add(PVector.mult(from_player, -(1 - player_relative_mass) * overlap));
}
if(e.pos.x > camera_pos.x -WIDTH*0.5 && e.pos.x < camera_pos.x +WIDTH*1.5)
{
Iterator ij = battle_enemies.iterator();
while(ij.hasNext())
{
Enemy j = (Enemy) ij.next();
if(inRadius(e.pos, j.pos, j.radius + e.radius))
{
PVector from_j = PVector.sub(e.pos, j.pos);
float overlap = j.radius + e.radius - from_j.mag();
float j_relative_mass = j.radius / (j.radius + e.radius);
from_j.normalize();
e.pos.add(PVector.mult(from_j, j_relative_mass * overlap));
j.pos.add(PVector.mult(from_j, -(1 - j_relative_mass) * overlap));
}
}
}
//enemy death handling
if(e.is_dead)
{
poof(e.radius, e.pos);
if(e.is_boss)
{
//kill minions on boss defeat
for(int i = 0; i < battle_enemies.size(); i++)
{
Enemy f = (Enemy) battle_enemies.get(i);
f.life = 0;
f.stun_time = THROES_DURATION + i*(THROES_DURATION/5);
}
}
ie.remove();
if(last_hit_enemy == e) last_hit_enemy = null;
}
}
if((battle_enemies.isEmpty() || player_life == 0) && !all_enemies.isEmpty())
{
if(battle_wrap_timer == 0)
{
if(player_life > 0)
{
if(boss_fight)
bgmOnce("boss_victory_music.mp3");
else bgmOnce("area_clear.mp3");
}
else
{
bgmOnce("defeated.wav");
boost_meter = 0;
brake_meter = 0;
fireball_charge = 0;
combo_count = -1;
player_hitstun = 1000;
battle_clock += 10*FRAMES_PER_TICK;
}
if(boss_fight) battle_wrap_timer = BOSS_WRAP_TIME;
else battle_wrap_timer = BATTLE_WRAP_TIME;
battle_finish_time = battle_clock / FRAMES_PER_TICK;
}
battle_wrap_timer--;
if(battle_wrap_timer < BATTLE_WRAP_TIME / 2)
{
if(battle_clock >= FRAMES_PER_TICK && physics_frame % 6 == 0)
{
battle_clock -= FRAMES_PER_TICK;
game_clock += FRAMES_PER_TICK;
if(!muted) timeSound.trigger();
}
}
if(battle_wrap_timer == 1)
{
while(battle_clock >= FRAMES_PER_TICK)
{
battle_clock -= FRAMES_PER_TICK;
game_clock += FRAMES_PER_TICK;
}
setUpMap();
}
}
diamonds_timer += DIAMONDS_RATE;
if(hint_timer > 0) hint_timer --;
}
}
void smackPlayer(int damage, PVector knockback)
{
if(player_hitstun == 0)
{
player_life -= damage;
if(player_life < 0) player_life = 0;
player_hitstun = STUN_DURATION;
player_recoil.add(knockback);
showDamage(player_pos, damage);
if(!muted) hitSound.trigger();
}
}
void drawingStep()
{
if(game_state == TITLE)
{
background(NORMAL_SKY);
color cloud_color = NORMAL_CLOUDS;
color sky_color = NORMAL_SKY;
moveClouds(-1);
noStroke();
ellipseMode(RADIUS);
for(int i = 0; i < clouds.size(); i++)
{
PVector cloud = (PVector) clouds.get(i);
fill(blendColors(sky_color, cloud_color, cloud.z * 0.8));
ellipse(cloud.x, cloud.y, 50*cloud.z, 50*cloud.z);
}
fill(255);
textAlign(CENTER, BOTTOM);
textFont(font, 32);
fill(0);
text("Dragondot's Sky", WIDTH/2+2, HEIGHT/2+2);
fill(255);
text("Dragondot's Sky", WIDTH/2, HEIGHT/2);
textAlign(CENTER, TOP);
textFont(font, 8);
fill(0);
text("\nDragondot must defend her home (and her kobolds) once again!\n\narrow keys to move\nx = attack / select area\nz = brake / dash\n\np = pause m = mute\n\n[press SPACE]", WIDTH/2+1, HEIGHT/2+1);
fill(255);
text("\nDragondot must defend her home (and her kobolds) once again!\n\narrow keys to move\nx = attack / select area\nz = brake / dash\n\np = pause m = mute\n\n[press SPACE]", WIDTH/2, HEIGHT/2);
}
if(game_state == MAP_SCREEN)
{
draw_frame++;
drawMap();
if(transition_timer != 0)
{
mosaic((int)(abs(transition_timer) / 5));
iris(xcen(player_map_x), ycen(player_map_y), int(WIDTH*1.5 * (TRANSITION_TIME-abs(transition_timer))/(float)TRANSITION_TIME));
}
}
if(game_state == IN_LEVEL)
{
if(!paused && dialog_queue.isEmpty()) draw_frame++;
drawSky();
if(diamonds_timer < DIAMONDS_MAX) diamonds(diamonds_timer);
if(battle_wrap_timer >0 && battle_wrap_timer < DIAMONDS_MAX) diamonds(battle_wrap_timer - 1);
}
}
void drawMap()
{
background(0);
ellipseMode(RADIUS);
float upcorner = (HEIGHT - (TILE_H * WORLD_H))/2;
float leftcorner = (WIDTH - (TILE_W * WORLD_W))/2;
fill(GROUND_COLOR);
noStroke();
rect(leftcorner, upcorner, TILE_W * WORLD_W, TILE_H * WORLD_H);
fill(BG_VARIATION_COLOR);
ellipse(330, 230, 90, 90);
fill(BG_VARIATION_COLOR_2);
ellipse(550, 300, 70, 70);
ellipse(120, 120, 40, 40);
for(int x = 0; x < WORLD_W; x++)for(int y = 0; y < WORLD_H; y++)
{
fill(128/2, 168/2, 64/2);
noStroke();
rect(leftcorner + x * TILE_W, upcorner + y * TILE_H + TILE_H - BANNER_H, TILE_W, BANNER_H);
noFill();
strokeWeight(3);
stroke(0);
rect(leftcorner + x * TILE_W, upcorner + y * TILE_H, TILE_W, TILE_H);
}
Iterator ie = all_enemies.iterator();
while(ie.hasNext())
{
Enemy e = (Enemy) ie.next();
e.mapDrawShadow();
}
fill(DRAGONDOT_FILL);
stroke(DRAGONDOT_STROKE);
strokeWeight(1);
ellipseMode(RADIUS);
ellipse(leftcorner + player_map_x*TILE_W + TILE_W/2, upcorner + player_map_y*TILE_H + TILE_H/2, DRAGONDOT_RADIUS/2, DRAGONDOT_RADIUS/2);
ie = all_enemies.iterator();
while(ie.hasNext())
{
Enemy e = (Enemy) ie.next();
e.mapDraw();
}
for(int x = 0; x < WORLD_W; x++)for(int y = 0; y < WORLD_H; y++)
{
textFont(font, 8);
textAlign(LEFT, BOTTOM);
fill(percentColor(map_threat[x][y]));
text(""+map_threat[x][y]+"%", leftcorner + x * TILE_W + 4, upcorner + y * TILE_H + TILE_H - 4);
fill(175, 215, 180);
textAlign(RIGHT, BOTTOM);
if(kobolds[x][y] > 0)
{
text("K:"+kobolds[x][y], leftcorner + x * TILE_W +TILE_W - 4, upcorner + y * TILE_H + TILE_H - 4);
textFont(font, 16);
textAlign(CENTER, CENTER);
if(kobold_peril[x][y] + map_threat[x][y] > 100)
{
float cycle = 1 - (physics_frame%45)/45.0;
fill(255, 255*cycle, 255*cycle);
text("!!!", xcen(x), ycen(y));
}
else if(kobold_peril[x][y] + map_threat[x][y] > 50)
{
float cycle = 1 - (physics_frame%60)/60.0;
fill(255, 160 + 95*cycle, 255*cycle);
text("!!", xcen(x), ycen(y));
}
else if(kobold_peril[x][y] + map_threat[x][y] > 25)
{
float cycle = 1 - (physics_frame%90)/90.0;
fill(255, 255, 255*cycle);
text("!", xcen(x), ycen(y));
}
}
}
particles.draw();
fill(255);
textFont(font, 16);
textAlign(LEFT, BOTTOM);
text("Total time: "+((game_clock/FRAMES_PER_TICK/10))+"."+((game_clock/FRAMES_PER_TICK)%10), leftcorner, HEIGHT - 8);
textAlign(RIGHT, BOTTOM);
text("Kobolds: "+kobolds_remaining+" (min "+KOBOLDS_NEEDED+")", WIDTH-leftcorner, HEIGHT - 8);
textAlign(CENTER, TOP);
text(topic_text, WIDTH/2, 8);
if(game_over_timer > 0)
{
mosaic(game_over_timer / 20);
fill(0, game_over_timer/2);
rect(0, 0, WIDTH, HEIGHT);
fill(255);
textFont(font, 16);
textAlign(CENTER, CENTER);
text("GAME OVER\nToo many of your kobolds perished...\n\n[press p to try again]", WIDTH/2, HEIGHT/2);
}
}
void drawSky()
{
drawClouds();
pushMatrix();
translate(-camera_pos.x, -camera_pos.y);
float bob = 2*sin(physics_frame / 15.0);
if(brake_meter > 0 && brake_meter < 1)
{
noFill();
strokeWeight(2);
stroke(255, 255, 255);
drawCharge(player_pos.x, player_pos.y + bob, brake_meter, DRAGONDOT_RADIUS * 3, DRAGONDOT_RADIUS, 3);
}
if(fireball_charge > 0 && fireball_charge < FIREBALL_MIN_CHARGE)
{
noStroke();
strokeWeight(2);
fill(255, 127+64*((draw_frame / 2)%3), 0);
drawCharge(player_pos.x, player_pos.y + bob, fireball_charge / (float)FIREBALL_MIN_CHARGE, DRAGONDOT_RADIUS * 5, DRAGONDOT_RADIUS, 5);
}
if(fireball_charge >= FIREBALL_MIN_CHARGE && fireball_charge <= FIREBALL_MIN_CHARGE + FIREBALL_CHARGE_WINDOW)
{
noStroke();
strokeWeight(2);
fill(255, 127+64*((draw_frame / 2)%3), 0);
ellipse(player_pos.x, player_pos.y + bob, DRAGONDOT_RADIUS + 8, DRAGONDOT_RADIUS + 8);
}
if(fireball_charge > FIREBALL_MIN_CHARGE + FIREBALL_CHARGE_WINDOW)
{
noStroke();
strokeWeight(2);
fill(255, 127+64*((draw_frame / 2)%3), 0);
ellipse(player_pos.x, player_pos.y + bob, DRAGONDOT_RADIUS + 3, DRAGONDOT_RADIUS + 3);
}
float speed = player_speed;
strokeWeight(2);
noFill();
stroke(128);
ellipse(player_pos.x + cos(player_heading)*(40 * speed), player_pos.y + sin(player_heading)*(40 * speed), DRAGONDOT_RADIUS/2, DRAGONDOT_RADIUS/2);
if(player_hitstun == 0 || draw_frame%2 == 0)
{
drawAttack();
fill(DRAGONDOT_FILL);
stroke(DRAGONDOT_STROKE);
if(dash_charged && draw_frame/2%2 == 0)
{
fill(blendColors(DRAGONDOT_FILL, color(255), 0.2));
stroke(blendColors(DRAGONDOT_STROKE, color(255), 0.2));
}
strokeWeight(2);
ellipse(player_pos.x, player_pos.y + bob, DRAGONDOT_RADIUS, DRAGONDOT_RADIUS);
noFill();
}
Iterator ie = battle_enemies.iterator();
while(ie.hasNext())
{
Enemy e = (Enemy) ie.next();
e.skyDraw();
}
particles.draw();
drawFireball();
popMatrix();
if(!all_enemies.isEmpty())
{
screen_particles.draw();
fill(0);
textFont(font, 16);
textAlign(CENTER, TOP);
text("TIME", WIDTH/2+2 ,10);
textFont(font, 32);
text(""+((battle_clock/FRAMES_PER_TICK/10))+"."+((battle_clock/FRAMES_PER_TICK)%10), WIDTH/2 + 2, 28);
fill(255);
textFont(font, 16);
textAlign(CENTER, TOP);
text("TIME", WIDTH/2, 8);
textFont(font, 32);
text(""+((battle_clock/FRAMES_PER_TICK/10))+"."+((battle_clock/FRAMES_PER_TICK)%10), WIDTH/2, 26);
textAlign(LEFT, TOP);
textFont(font, 8);
fill(0);
strokeWeight(1);
noStroke();
fill(0);
rect(8, 19, 300, 2);
fill(DRAGONDOT_FILL);
rect(8, 18, 300 * player_life / PLAYER_MAX_LIFE, 2);
fill(DRAGONDOT_STROKE);
rect(8, 20, 300 * player_life / PLAYER_MAX_LIFE, 2);
fill(0);
text("Dragondot", 9, 9);
fill(255);
text("Dragondot", 8, 8);
textAlign(RIGHT, TOP);
if(last_hit_enemy != null)
{
fill(0);
rect(WIDTH-8, 19, -300, 2);
fill(last_hit_enemy.fill_color);
rect(WIDTH-8, 18, -(300 * last_hit_enemy.life / last_hit_enemy.max_life), 2);
fill(last_hit_enemy.stroke_color);
rect(WIDTH-8, 20, -(300 * last_hit_enemy.life / last_hit_enemy.max_life), 2);
fill(0);
text(last_hit_enemy.name, WIDTH-7, 9);
fill(255);
text(last_hit_enemy.name, WIDTH-8, 8);
}
}
if(!dialog_queue.isEmpty())
{
DialogItem di = (DialogItem) dialog_queue.get(0);
di.draw();
}
if(battle_wrap_timer != 0)
{
textFont(font, 32);
textAlign(CENTER, BOTTOM);
fill(0);
if(player_life > 0) text("Area Clear!", WIDTH/2 + 2, HEIGHT/2 + 2);
else text("Defeated...", WIDTH/2 + 2, HEIGHT/2 + 2);
fill(255);
if(player_life > 0) text("Area Clear!", WIDTH/2, HEIGHT/2);
else text("Defeated...", WIDTH/2, HEIGHT/2);
textAlign(CENTER, TOP);
fill(0);
text("Total time: "+((game_clock/FRAMES_PER_TICK/10))+"."+((game_clock/FRAMES_PER_TICK)%10), WIDTH/2+2, HEIGHT/2+2);
fill(255);
text("Total time: "+((game_clock/FRAMES_PER_TICK/10))+"."+((game_clock/FRAMES_PER_TICK)%10), WIDTH/2, HEIGHT/2);
if(player_life == 0)
{
fill(255, 0, 0, 255 *battle_wrap_timer / (float)BATTLE_WRAP_TIME);
text("+1.0", WIDTH/2, 32 +(BATTLE_WRAP_TIME - battle_wrap_timer) / 10);
}
}
if(hint_timer > 0)
{
textFont(font, 16);
textAlign(CENTER, BOTTOM);
fill(255, 192, 0, 255*hint_timer/HINT_TIME);
text(hint_message, WIDTH/2, HEIGHT/3);
}
if(all_enemies.isEmpty())
{///draw credits
fill(255);
textFont(font, 16);
textAlign(LEFT, TOP);
text("DRAGONDOT'S SKY", 16, 16);
fill(255);
textFont(font, 8);
textAlign(RIGHT, BOTTOM);
text("v1.2", WIDTH-4, HEIGHT-4);
textAlign(CENTER, TOP);
fill(255, battle_clock - 400);
textFont(font, 16);
text("Completion Time:", WIDTH/2, 200);
fill(255, battle_clock - 700);
textFont(font, 32);
text(""+((game_clock/FRAMES_PER_TICK/10))+"."+((game_clock/FRAMES_PER_TICK)%10), WIDTH/2, 220);
fill(255, battle_clock - 1000);
textFont(font, 16);
text("Your rate for rescuing kobolds is:", WIDTH/2, 260);
fill(255, battle_clock - 1300);
textFont(font, 32);
text(""+(100*kobolds_remaining/25)+"%", WIDTH/2, 280);
fill(255, battle_clock - 2300);
textFont(font, 15);
text("SEE YOU NEXT DRAGON", WIDTH/2, 360);
}
if(paused)
{
fill(0, 128);
noStroke();
rect(0, 0, WIDTH, HEIGHT);
textFont(font, 16);
textAlign(CENTER, CENTER);
fill(255);
text("PAUSED", WIDTH/2, HEIGHT/2);
}
}
void drawClouds()
{
color cloud_color;
color sky_color;
if(boss_fight)
{
cloud_color = DARK_CLOUDS;
sky_color = DARK_SKY;
if(battle_wrap_timer != 0 && player_life > 0)
{
cloud_color = blendColors(DARK_CLOUDS, NORMAL_CLOUDS,min( 2 - 2 * battle_wrap_timer / (float)BOSS_WRAP_TIME, 1));
sky_color = blendColors(DARK_SKY, NORMAL_SKY, min(2 - 2* battle_wrap_timer / (float)BOSS_WRAP_TIME, 1));
}
}
else
{
cloud_color = NORMAL_CLOUDS;
sky_color = NORMAL_SKY;
}
if(all_enemies.isEmpty())
{
cloud_color = color(192, 255, 255);
sky_color = color(16, 0, 64);
}
background(sky_color);
noStroke();
if(all_enemies.isEmpty())
{
fill(0, 64, 16);
rect(0, HEIGHT/2, WIDTH, HEIGHT/2);
fill(192, 220, 255);
ellipse(WIDTH*3/4, HEIGHT*1/4, 50, 50);
for(int i = 0; i < clouds.size(); i++)
{
PVector cloud = (PVector) clouds.get(i);
fill(blendColors(sky_color, cloud_color, cloud.z * 0.8));
ellipse(cloud.x, HEIGHT/2 - (HEIGHT/2)*cloud.z, 50*cloud.z, 50*cloud.z);
fill(0, 60, 14);
ellipse(cloud.x, HEIGHT/2 + (HEIGHT/2)*cloud.z, 50*cloud.z, 12*cloud.z);
}
}
else
{
for(int i = 0; i < clouds.size(); i++)
{
PVector cloud = (PVector) clouds.get(i);
fill(blendColors(sky_color, cloud_color, cloud.z * 0.8));
ellipse(cloud.x, cloud.y, 50*cloud.z, 50*cloud.z);
}
}
}
void moveClouds(float movement)
{
for(int i = 0; i < clouds.size(); i++)
{
PVector cloud = (PVector) clouds.get(i);
cloud.x += movement * cloud.z;
if(cloud.x < -width*0.5)
{
cloud.x = width*1.25;
if(random(2) < 1)
cloud.y = random(height);
}
if(cloud.x > width*1.5)
{
cloud.x = -width*0.25;
cloud.y = random(height);
}
}
}
void draw()
{
while(physics_ms_last + PHYS_MS < millis())
{
if(!paused)
{
physicsStep();
}
physics_ms_last += PHYS_MS;
}
if(drawing_ms_last + DRAW_MS < millis())
{
drawingStep();
drawing_ms_last = millis();
}
}
void keyPressed()
{
if(!keys[keyCode])
{
keys[keyCode] = true;
down(keyCode);
}
}
void keyReleased()
{
if(keys[keyCode])
{
keys[keyCode] = false;
up(keyCode);
}
}
void down(int theKey)
{
println(theKey + " down");
if(theKey == 'M')
{
muted = !muted;
if(muted) music.mute();
else music.unmute();
}
if(game_over_timer != 0 && theKey =='P') newGame();
else if(game_state == TITLE && theKey == ' ') game_state = MAP_SCREEN;
if(game_state == IN_LEVEL && dialog_queue.isEmpty() && theKey == 'P')
{
paused = !paused;
if(paused) music.setGain(-10); else music.setGain(0);
}
if(game_state == MAP_SCREEN && transition_timer == 0 && map_ready && game_over_timer == 0)
{
boolean moved = false;
if(theKey == LEFT && player_map_x > 0) {
player_map_x --;
moved = true;
}
if(theKey == RIGHT && player_map_x < WORLD_W-1) {
player_map_x ++;
moved = true;
}
if(theKey == UP && player_map_y > 0) {
player_map_y --;
moved = true;
}
if(theKey == DOWN && player_map_y < WORLD_H - 1) {
player_map_y ++;
moved = true;
}
if(moved)
{
if(!muted) mapBlonk.trigger();
if(map_threat[player_map_x][player_map_y] >=LOW_PERCENT) engage();
}
if(theKey == ATTACK_KEY && map_threat[player_map_x][player_map_y] > 0) engage();
if(theKey == 'T' && cheats)
{
music.pause();
Iterator ie = all_enemies.iterator();
while(ie.hasNext())
{
Enemy e = (Enemy) ie.next();
e.tickTime(1);
}
game_clock += FRAMES_PER_TICK * 10;
map_ready = false;
}
}
if(!dialog_queue.isEmpty() && theKey == ATTACK_KEY)
{
DialogItem di = (DialogItem) dialog_queue.get(0);
if(letters_showing == di.message.length())
{
dialog_queue.remove(0);
letters_showing = 0;
letter_timer = 0;
if(dialog_queue.isEmpty() && game_state == IN_LEVEL) bgm("duel_music.mp3");
}
}
if(cheats)
{
if(game_state == IN_LEVEL && theKey == 8)
{
Iterator ie = battle_enemies.iterator();
while(ie.hasNext())
{
Enemy e = (Enemy) ie.next();
e.life = 0;
}
}
if(game_state == MAP_SCREEN && theKey == 8)
{
all_enemies.clear();
map_ready = false;
}
if(game_state == IN_LEVEL && theKey == 'F')
{
player_life = 0;
}
}
}
void up(int theKey)
{
println(theKey + " up");
}
int xcen(int tile)
{
int leftcorner = (WIDTH - (TILE_W * WORLD_W))/2;
return leftcorner+TILE_W/2+TILE_W*tile;
}
int ycen(int tile)
{
int upcorner = (HEIGHT - (TILE_H * WORLD_H))/2;
return upcorner+TILE_H/2+TILE_H*tile;
}