void update_roper(Lixxie& l, const UpdateArgs& ua) { // Normales Update, einmal pro Tick if (!ua.aim_c) { if (l.get_frame() < frame_aiming_first) { l.next_frame(); } // Nagel fertig in der Erde, aber vor Haken abschiessen else if (l.get_special_x() == 0) { set_frame_after_aiming(l, ua); // Wenn man zu lange wartet, weiterlaufen, einfach l.set_special_y(l.get_special_y() + 1); if (l.get_special_y() > Lixxie::updates_roper_before) l.become(LixEn::WALKER); } // Haken wurde schon abgeschossen, warten, ehe man weiterlaeuft else { l.set_special_y(l.get_special_y() + 1); if (l.get_special_y() > Lixxie::updates_roper_after) l.become(LixEn::WALKER); } } // Zusaetzliches Update pro Tick, wenn zum Zielen per Klick aufgefordert // wurde: Dies wird vor dem normalen Update ausgefuehrt. else { // Nagel in den Boden hauen: Zwar Maus in Beschlag nehmen durch // special_x == 0, aber nix machen. Weiter die Klicks aufsaugen. if (l.get_frame() < frame_aiming_first); // Zielen, aber noch nicht abgeschossen: Nun abschiessen else if (l.get_special_x() == 0) { l.set_special_x(1); l.set_special_y(0); set_frame_after_aiming(l, ua); } } }
void update_builder(Lixxie& l, const UpdateArgs& ua) { switch (l.get_frame()) { // Bau-Frame case 7: // don't glitch up through steel, but still get killed by top of // screen: first see whether trapped, then make brick. For the magic // number 13, see walker.cpp, it's because they can ascend 12 pixels. l.set_special_y(l.solid_wall_height(2) >= 13); l.set_special_x(l.get_special_x() - 1); l.draw_brick (-2, 0, 9, 1); if (l.get_special_x() < 3 && l.get_queue() <= 0) l.play_sound_if_trlo(ua, Sound::BRICK); l.move_up(); break; // Zwei Fortbewegungs-Frames case 11: // Kollision mit Landschaft? Dann umdrehen! // Kopf und Fuß werden geprüft hierfür. // +6|-18 statt +2|-16: Die Lix soll wissen, wo's hin geht. // +6|-1 ist die Koordinate über dem Stein, nicht -2, da sonst // in seltenen Fällen (Lix in dünner Horizontalen) nicht // bis zu dieser Ebene hochgebaut wird. // Die zweite Abfrage in der Und-Klammer dient dazu, Treppen // auch auf anderen Treppen bauen zu können. // Last line is Horus bug prevention. // Note that the lix has already moved up and the image has its // feet below the regular position, inside the newly placed brick. // // XX - the effective coordinate of the checking Lixxie. She has // already moved up from inside the brick, but not yet walked // forward. // 11 - numbers denote the checks in the corresp. code line below // // // // 33 22 11 // // XX // 44 44 34 24 11 // ()()()()()()()()()()()() // ()()()()()()()()()()()() // [][][][][][][][][][][][] // [][][][][][][][][][][][] // // lines 1, 2, 3, don't build through walls if ((l.is_solid(6, 1) && l.is_solid(6, -2)) || (l.is_solid(4, 1) && l.is_solid(4, -2)) || (l.is_solid(2, 1) && l.is_solid(2, -2)) // line 4, don't allow building through long, 2px-thin horiz. beams || (l.is_solid(4, 1) && l.is_solid(2, 1) && l.is_solid(0, 1) && l.is_solid(-2, 1)) // hit head || l.is_solid(6, -16) || l.is_solid(4, -16) ) { // Ueberfluessige Faehigkeitsbenutzngen an den Spieler // zurueckgeben, passiert nur bei Option "multiple Builders". // Wird von l.assign() erledigt. // See top comment for the check of special_y. l.turn(); if (l.get_special_y() == 1) l.move_down(); l.become(LixEn::WALKER); } break; case 12: case 13: l.move_ahead(); break; // Klötze zählen und ggf. zum Shrugger werden. case 15: if (l.get_special_x() <= 0) { if (l.get_queue() <= 0) l.become(LixEn::SHRUGGER); else { l.set_queue (l.get_queue() - 1); l.set_special_x(l.get_special_x() + 12); } } break; } if (l.get_ac() == LixEn::BUILDER) l.next_frame(); }
void update_faller(Lixxie& l, const UpdateArgs& ua) { for (int i = 0; i <= l.get_special_y() && l.get_ac() == LixEn::FALLER;++i){ // a bit kludgy, we can't do such a thing for flingers etc, since // they might be nonconstant. if (l.get_foot_encounters() & Lookup::bit_trampoline) { // stop falling, so the trampoline can be used break; } else if (l.is_solid(0, i+2)) { l.move_down(i); l.set_special_x(l.get_special_x() + i); // Schirm in letzter Sekunde? if (l.get_special_x() > Lixxie::distance_safe_fall && !l.get_floater()) { l.become(LixEn::SPLATTER); l.play_sound(ua, Sound::SPLAT); // Nicht explodieren lassen, das täte er bei 76 :-) if (l.get_updates_since_bomb() == 75) l.set_updates_since_bomb(0); } else if ((l.get_special_x() <= 9 && l.get_frame() < 1) || l.get_special_x() == 0) { l.become(LixEn::WALKER); if (l.get_runner()) l.set_frame(6); else l.set_frame(8); } else if (l.get_frame() < 2) { l.become(LixEn::WALKER); l.set_frame(0); } else if (l.get_frame() < 3) { l.become(LixEn::LANDER); l.set_frame(1); } else { l.become(LixEn::LANDER); // use the regular frame 0 } } } if (l.get_ac() == LixEn::FALLER) { l.set_special_x(l.get_special_x() + l.get_special_y()); l.move_down(l.get_special_y()); if (l.get_special_y() < 8) l.set_special_y(l.get_special_y() + 1); // The last two frames alternate, the first frames are just the // initial frames of falling. if (l.is_last_frame()) l.set_frame(l.get_frame() - 1); else l.next_frame(); if (l.get_floater() && l.get_special_x() >= Lixxie::distance_float) { const int sy = l.get_special_y(); l.become(LixEn::FLOATER); l.set_special_y(sy); } } }
void update_jumper(Lixxie& l, const UpdateArgs& ua) { if (l.get_special_x() % 2 == 1) { if (l.get_special_x() > 0) l.set_special_x(l.get_special_x() + 1); else l.set_special_x(l.get_special_x() - 1); } const int sgn = l.get_special_y() >= 0 ? 1 : -1; // sgn(Y-Spd.) const unsigned abs = l.get_special_y() / sgn; // |Y-Spd.| const unsigned& spe = l.get_special_x(); // X-Spd. // Das Signum ist auch fuer 0 gleich +1, das macht im Code allerdings // nix, weil in dem Fall null Schleifendurchlaeufe passieren oder // mit null multipliziert wird. // Schrittweise schraeg vorruecken und jedes Mal auf // Kollision mit der Landschaft testen. // Die groessere Laenge wird pixelweise abgearbeitet. for (unsigned i = 0; i < (abs >= spe ? abs : spe); ++i) { // 2 * (... / 2) sorgt fuer das Einhalten der geraden X-Zahlen. // Es wird jeweils geguckt, ob der Zaehler i weit genug vor- // geschritten ist, damit in die kurze Richtung ein // Schritt stattfinden kann - wenn nicht, ist das Argument // von move_ahead stets 0. In die lange Richtung geht's immer. const int old_ex = l.get_ex(); const int old_ey = l.get_ey(); const Lookup::LoNr old_enc_foot = l.get_foot_encounters(); const Lookup::LoNr old_enc_body = l.get_body_encounters(); if (abs >= spe) { l.move_ahead(2 * ((i+1)*spe/2 / abs - i*spe/2 / abs)); l.move_down(sgn); } else { l.move_down(sgn * ((i+1)*abs/spe - i*abs/spe)); l.move_ahead(i%2 * 2); } int coll = jumper_and_tumbler_collision(l); if (coll == 0) { // nothing hit, proceed with next step for this frame } else if (coll == 1) { // we hit something, but don't have to reset anything. Stop motion. break; } else if (coll == 2) { // We hit something, reset encounters and check again at position. l.set_foot_encounters(old_enc_foot); l.set_body_encounters(old_enc_body); l.set_ey(l.get_ey()); // re-check encounters at current position break; } else if (coll == 3) { // Like coll == 2, but also reset position. l.set_foot_encounters(old_enc_foot); l.set_body_encounters(old_enc_body); l.set_ex(old_ex); l.set_ey(old_ey); // Do this for completely immobilizied tumblers if (l.is_solid(0, 0)) l.become(LixEn::STUNNER); break; } // end checking return val of collision } // end of motion // Wenn nicht beim Bewegen irgendwo angestossen... if (l.get_ac() == LixEn::JUMPER || l.get_ac() == LixEn::TUMBLER) { const int sp_y = l.get_special_y(); if (sp_y <= 12) l.set_special_y(sp_y + 2); else if (sp_y < 64) l.set_special_y(sp_y + 1); if (l.get_ac() == LixEn::TUMBLER && (l.get_foot_encounters() & Lookup::bit_trampoline) && l.get_special_y() > 0) { // don't use the tumbler frame selection that is used onwards here, // but take a nicer frame l.set_frame(std::max(0, l.get_frame() - 4)); } else if (l.get_special_y() > 14) { if (l.get_floater()) { const int sx = l.get_special_x(); const int sy = l.get_special_y(); l.become(LixEn::FLOATER); l.set_special_x(sx); l.set_special_y(sy); } else if (l.get_ac() == LixEn::JUMPER) { l.set_ac(LixEn::TUMBLER); l.set_frame(3); // override autoframechoice for 1 frame now } else { // we're already a tumbler tumbler_frame_selection(l); } } else if (l.get_ac() == LixEn::TUMBLER) { tumbler_frame_selection(l); } else { // we are a jumper if (l.is_last_frame()) { if (l.get_runner()) l.set_frame(12); else l.set_frame(l.get_frame() - 1); } else l.next_frame(); } } switch (l.get_ac()) { case LixEn::STUNNER: l.play_sound(ua, Sound::OUCH); break; case LixEn::SPLATTER: l.play_sound(ua, Sound::SPLAT); break; case LixEn::CLIMBER: l.play_sound(ua, Sound::CLIMBER); break; default: break; } }