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!
* Creative Commons License
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; }