// 'TheChef.java', 4/01 Joe Rosen // 4/17/01, "The Chef" (java port), 'packaged food series' import java.applet.Applet; import java.awt.*; // classes // food object (e.g. pasta pocket, wheat kernal, etc.) class FoodObject { // constants public static final int TOTAL_FOODOBJ_IMGS = 12; // total # of food object images // food object images // base index public static final int BASE_IDX_FOODOBJECT = 0; // width and height public static final int FOODOBJ_W = 59; public static final int FOODOBJ_H = 59; // direction public static final int DIRECTION_LEFT = 0; public static final int DIRECTION_UP = 1; public static final int DIRECTION_RIGHT = 2; public static final int DIRECTION_DOWN = 3; // origin position x,y public static final int ORIGIN_X = 185; public static final int ORIGIN_Y = 302; // grow food object from center/from bottom public static final int GROW_FROM_CENTER = 0; public static final int GROW_FROM_BOTTOM = 1; // vars // flag, active while enlarging or floating public boolean active_flg; // active= true/inactive= false // enlarge public boolean enlarge_flg; // flag enlarge public int enlarge_w, enlarge_h; // float public boolean float_flg; // after enlarging begin floating public int pos_x, pos_y; // position x,y public float offset_x, offset_y; // offset x,y // direction of float public int direction_flg; // randomly selected int, 0 to 3 // orientation (randomly chosen image set) public int orientation_flg; // squiggle anim timer public long squiggle_delay; // squiggle flag public int squiggle_flg; // 0-2, 3 frame squiggle anim // static vars // drawing environment info (passed in from main class) public static Applet the_applet; public static int canvas_w; public static int canvas_h; public static Component main_component; public static Graphics composite_graphics; // images and media tracker public static Image[] foodobj_imgs = new Image[TOTAL_FOODOBJ_IMGS]; public static MediaTracker foodobj_img_tracker; // drawing canvas public static Rectangle canvas_rect; // methods: // constructor // public static: // init_foodobj_environvars // load_foodobj_imgs // public: // activate_foodobj // draw_foodobject // private: // target_foodobj_direction // constructor void FoodObject() { // init state enlarge_flg = false; active_flg = false; } // end 'constructor' // init static food obj applet environment vars public static void init_foodobj_environvars( Applet the_aplt, int can_width, int can_height, Graphics comp_graphics ) { // applet environment info the_applet = the_aplt; canvas_w = can_width; canvas_h = can_height; composite_graphics = comp_graphics; // drawing canvas canvas_rect = new Rectangle(0, 0, canvas_w, canvas_h); } // end method 'init_foodobj_environvars' // load food object images public static void load_foodobj_imgs() { // load food object images and media tracker // frames 1-3 X orientation 1-4 int idx, fr_lp, or_lp; idx = 0; foodobj_img_tracker = new MediaTracker(the_applet); for (or_lp = 1; or_lp <= 4; or_lp++) { for (fr_lp = 1; fr_lp <= 3; fr_lp++) { foodobj_imgs[idx] = the_applet.getImage( the_applet.getCodeBase(), ("images/pasta_" + fr_lp + "_" + or_lp + ".gif") ); foodobj_img_tracker.addImage(foodobj_imgs[idx], idx + 1); idx++; } } } // end 'load_foodobj_imgs' // re-init food object public void activate_foodobj() { // flag enlarge enlarge_w = 4; enlarge_h = 4; enlarge_flg = true; // flag float float_flg = false; // position x,y pos_x = ORIGIN_X; pos_y = ORIGIN_Y; // choose food object direction and float offset target_foodobj_direction(); // orientation (randomly chosen image set) orientation_flg = (int) (Math.random() * 4); // 4 image sets // squiggle anim timer squiggle_delay = System.currentTimeMillis() + 100; // squiggle anim, 10 fps; // squiggle flag squiggle_flg = 0; // 0-2, 3 frame squiggle anim // activate active_flg = true; } // end method 'activate_foodobj' // draw food object public void draw_foodobject(int grow_flg) { int img_base_offset = 0; // calculated coords int calc_coord_x, calc_coord_y; // build left/top food object coords // squiggle anim timer if ( System.currentTimeMillis() >= squiggle_delay ) { if (squiggle_flg < 2) squiggle_flg = squiggle_flg + 1; else squiggle_flg = 0; // reset squiggle timer squiggle_delay = System.currentTimeMillis() + 100; // squiggle anim, 10 fps; } // base idx switch (orientation_flg) { case 0: img_base_offset = 0; break; case 1: img_base_offset = 3; break; case 2: img_base_offset = 6; break; case 3: img_base_offset = 9; break; } int img_idx = BASE_IDX_FOODOBJECT + squiggle_flg + img_base_offset; // calculated coords if (grow_flg == GROW_FROM_CENTER) { // grow food object from center coord calc_coord_x = pos_x - (enlarge_w / 2); calc_coord_y = pos_y - (enlarge_h / 2); } else { // GROW_FROM_BOTTOM // grow food object up from bottom/center coord calc_coord_x = pos_x - (enlarge_w / 2); calc_coord_y = pos_y - enlarge_h; } // food object rect Rectangle foodobj_rect = new Rectangle(pos_x, pos_y, FOODOBJ_W, FOODOBJ_H); // enlarge if (enlarge_w < FOODOBJ_W) { enlarge_w = enlarge_w + 2; enlarge_h = enlarge_h + 2; // shut down enlargment if ( (enlarge_w >= FOODOBJ_W) || (enlarge_h >= FOODOBJ_H) ) { enlarge_flg = false; // make sure we haven't grown too large enlarge_w = FOODOBJ_W; enlarge_h = FOODOBJ_H; } // draw food object into buffer composite_graphics.drawImage( foodobj_imgs[img_idx], calc_coord_x, calc_coord_y, enlarge_w, enlarge_h, null ); } // float else if ( canvas_rect.intersects(foodobj_rect) ) { // float pos_x = (int) Math.round(((float) pos_x) + offset_x); pos_y = (int) Math.round(((float) pos_y) + offset_y); // draw food object into buffer composite_graphics.drawImage( foodobj_imgs[img_idx], calc_coord_x, calc_coord_y, FOODOBJ_W, FOODOBJ_H, null ); } // deactivate else { active_flg = false; } } // end method 'draw_foodobject()' // choose food object direction and float offset private void target_foodobj_direction() { float direction_target; float number_of_moves; // direction direction_flg = (int) (Math.random() * 4); // randomly selected int, 0 to 3 // target, calculated offset switch (direction_flg) { case DIRECTION_UP: offset_y = (float) -1.0; number_of_moves = ORIGIN_Y; direction_target = (float) ((Math.random() * canvas_w) + 1); offset_x = (direction_target - ORIGIN_X) / number_of_moves; break; case DIRECTION_DOWN: offset_y = (float) 1.0; number_of_moves = canvas_h - ORIGIN_Y; direction_target = (float) ((Math.random() * canvas_w) + 1); offset_x = (direction_target - ORIGIN_X) / number_of_moves; break; case DIRECTION_LEFT: offset_x = (float) -1.0; number_of_moves = ORIGIN_X; direction_target = (float) ((Math.random() * canvas_h) + 1); offset_y = (direction_target - ORIGIN_Y) / number_of_moves; break; default: case DIRECTION_RIGHT: offset_x = (float) 1.0; number_of_moves = canvas_w - ORIGIN_X; direction_target = (float) ((Math.random() * canvas_h) + 1); offset_y = (direction_target - ORIGIN_Y) / number_of_moves; break; } // begin: report if (false) { String tmp_str = ""; // build report string switch (direction_flg) { case DIRECTION_UP: tmp_str = "UP: "; break; case DIRECTION_LEFT: tmp_str = "LEFT: "; break; case DIRECTION_DOWN: tmp_str = "DOWN: "; break; case DIRECTION_RIGHT: tmp_str = "RIGHT: "; break; } tmp_str = tmp_str + "offset_x= " + offset_x + ", " + "offset_y= " + offset_y + " direction_target= " + direction_target; // print data to console System.out.println(tmp_str); } // end: report } // end 'target_foodobj_direction' } // end class 'FoodObject' // main program class public class TheChef extends Applet implements Runnable { // constants // x/y, drawings canvas public static final int CANVAS_W = 375; public static final int CANVAS_H = 450; public static final int TOTAL_IMGS = 12; // total # of images // base buff idx references for image parts // head public static final int BASE_IDX_HEAD_CLOSED = 0; public static final int BASE_IDX_HEAD_OPEN = 2; // eyes public static final int BASE_IDX_EYES_LEFT = 4; public static final int BASE_IDX_EYES_CENTER = 6; public static final int BASE_IDX_EYES_RIGHT = 8; public static final int BASE_IDX_EYES_CLOSED = 10; // image dimensions // head public static final int HEAD_W = 212; public static final int HEAD_H = 344; // eyes public static final int EYES_W = 91; public static final int EYES_H = 23; // eyes open/close flag public final int EYES_CLD = 0; public final int EYES_OPN = 1; // total number of food objects public static final int TOTAL_FOODOBJS = 50; // vars // composite buffer, images and media tracker static Image composite_image; static Graphics composite_graphics; static Image[] imgs = new Image[TOTAL_IMGS]; static MediaTracker img_tracker; // animation thread static Thread anim_thread; // anim timers static long squiggle_delay; // squiggle anim // anim flags // squiggle flag static int squiggle_flg; // 0/1, 2 frame squiggle anim // head action (e.g. mouth open, hat off, etc.) flag static int head_action_flg; // 1= on; 0= off // eyes status flg (0= closed/1= open) static int eyesstatus_flg; // eyes blink delay static long eyesblink_delay; // eyes gaze left or right static int gaze_flg; // gaze: 0= center; 1= left; 2= right static long gaze_time; // eyes gaze left or right every 4000 - 10000 miliseconds static long gaze_delay; // hold eyes gazing left or right (before returning center) 1000 - 3000 miliseconds // food object static FoodObject[] food_obj; // init flag static boolean init_flg = false; // false until initialization in 'main()' is complete // methods: // init // start // stop // destroy // update // run // mouseDown // paint // private methods: // my_paint // draw_head // 'init()' public void init() { int idx; // array index // composite buffer composite_image = createImage(CANVAS_W, CANVAS_H); composite_graphics = composite_image.getGraphics(); // init static food obj environment vars FoodObject.init_foodobj_environvars(this, CANVAS_W, CANVAS_H, composite_graphics); // instantiate food objects food_obj = new FoodObject[TOTAL_FOODOBJS]; for (idx = 0; idx < TOTAL_FOODOBJS; idx++) food_obj[idx] = new FoodObject(); // load images and media tracker img_tracker = new MediaTracker(this); // head closed imgs[0] = getImage(getCodeBase(), "images/head_1_closed.gif"); img_tracker.addImage(imgs[0], 1); imgs[1] = getImage(getCodeBase(), "images/head_2_closed.gif"); img_tracker.addImage(imgs[1], 2); // head open imgs[2] = getImage(getCodeBase(), "images/head_1_open.gif"); img_tracker.addImage(imgs[2], 3); imgs[3] = getImage(getCodeBase(), "images/head_2_open.gif"); img_tracker.addImage(imgs[3], 4); // eyes left imgs[4] = getImage(getCodeBase(), "images/eyes_1_left.gif"); img_tracker.addImage(imgs[4], 5); imgs[5] = getImage(getCodeBase(), "images/eyes_2_left.gif"); img_tracker.addImage(imgs[5], 6); // eyes center imgs[6] = getImage(getCodeBase(), "images/eyes_1_center.gif"); img_tracker.addImage(imgs[6], 7); imgs[7] = getImage(getCodeBase(), "images/eyes_2_center.gif"); img_tracker.addImage(imgs[7], 8); // eyes right imgs[8] = getImage(getCodeBase(), "images/eyes_1_right.gif"); img_tracker.addImage(imgs[8], 9); imgs[9] = getImage(getCodeBase(), "images/eyes_2_right.gif"); img_tracker.addImage(imgs[9], 10); // eyes closed imgs[10] = getImage(getCodeBase(), "images/eyes_1_closed.gif"); img_tracker.addImage(imgs[10], 11); imgs[11] = getImage(getCodeBase(), "images/eyes_2_closed.gif"); img_tracker.addImage(imgs[11], 12); // load food object images FoodObject.load_foodobj_imgs(); // misc init // anim flags // squiggle flag squiggle_flg = 0; // 0/1, 2 frame squiggle anim // head action flag head_action_flg = 0; // 1= on; 0= off // anim timers squiggle_delay = System.currentTimeMillis() + 100; // squiggle anim, 10 fps // init eyes status flg (0= closed/1= open) eyesstatus_flg = 1; // initially open // init eyes blink delay (blink every .50 to 1.5 seconds) eyesblink_delay = System.currentTimeMillis() + ((long) ((Math.random() * 1001) + 500)); // eyes gaze left or right gaze_flg = 2; // gaze: 0= left; 1= right; 2= center gaze_time = System.currentTimeMillis() + ((long) ((Math.random() * 6001) + 4000)); // eyes gaze left or right every 4000 - 10000 miliseconds // init flag init_flg = true; // false until initialization is complete } // end method 'init()' // 'start()' // called when the applet becomes visible on screen public void start() { // create animation thread anim_thread = new Thread(this); // start animation thread anim_thread.start(); } // end method 'start()' // 'stop()' // called when the applet is no longer visible on screen public void stop() { // stop and destroy animation thread if (anim_thread != null) anim_thread = null; } // end method 'stop()' // 'destroy()' // called just before the browser exits public void destroy() { // stop and destroy animation thread if (anim_thread != null) anim_thread = null; // dispose offscreen graphics context, TheChef composite buffer composite_graphics.dispose(); composite_graphics = null; } // end method 'destroy()' // 'update()' // update the screen public void update(Graphics g) { // intercepting 'update()' avoids background erase if (composite_graphics != null) paint(g); // call 'paint()' } // end method 'update()' // thread runner public void run() { int idx; int paint_flg = 0; while ( anim_thread == Thread.currentThread() ) { // anim timers if (System.currentTimeMillis() >= squiggle_delay) { // squiggle flag if (squiggle_flg == 1) squiggle_flg = 0; // 0/1, 2 frame squiggle anim else squiggle_flg = 1; squiggle_delay = System.currentTimeMillis() + 100; // squiggle anim, 10 fps // flag paint paint_flg = 1; } // eyes blink update // blink if ( (eyesstatus_flg == 1) && (System.currentTimeMillis() >= eyesblink_delay) ) { // mark eyes status flag eyesstatus_flg = 0; // flag eyes closed // keep blinking eyes closed 125 milisecs eyesblink_delay = System.currentTimeMillis() + 125; // flag paint paint_flg = 1; } // open else if ( (eyesstatus_flg == 0) && (System.currentTimeMillis() >= eyesblink_delay) ) { // mark eyes status flag eyesstatus_flg = 1; // flag eyes open // re-init eyes blink delay (blink every .50 to 1.5 seconds) eyesblink_delay = System.currentTimeMillis() + ((long) (((Math.random() * 1001) + 500))); // flag paint paint_flg = 1; } // gaze-- eyes open, left, center or right // note: adjust gaze regardless of whether eyes are open or closed // left or right ? if ( (gaze_flg == 2) && (System.currentTimeMillis() >= gaze_time) ) { // random gaze_flg = (int) (Math.random() * 2); // hold eyes gazing left or right (before returning center) 1000 - 3000 miliseconds gaze_delay = System.currentTimeMillis() + ((long) ((Math.random() * 3001) + 1000)); } // return eyes center ? else if ( (gaze_flg < 2) && (System.currentTimeMillis() >= gaze_delay) ) { gaze_flg = 2; gaze_time = System.currentTimeMillis() + ((long) ((Math.random() * 6001) + 4000)); // eyes gaze left or right every 4000 - 10000 miliseconds } // paint (??) if (paint_flg == 1) repaint(); // force repaint // sleep try { Thread.sleep(25); } catch (InterruptedException e) {} } // end "while (Thread.currentThread() == anim_thread)" } // end method 'run()' // 'mouseDown()' // called when the mouse button is pressed down public boolean mouseDown(Event evt, int x, int y) { int idx; // activate the first free (inactive) food object for (idx = 0; idx < TOTAL_FOODOBJS; idx++) { if (food_obj[idx].active_flg == false) { food_obj[idx].activate_foodobj(); // activate head action (?) if (head_action_flg == 0) head_action_flg = 1; // head action flag, 1= on; 0= off break; // we've found an available food object, we're done here } } // force repaint repaint(); return true; } // end method 'mouseClicked()' public void paint(Graphics g) { // if init's complete, draw images in composite buffer and blast to screen if (init_flg) my_paint(g); } // end method 'paint()' // private methods // draw images in composite buffer and blast to screen void my_paint(Graphics g) { int idx; // if composite buffer's non-existent, return immediately if (composite_graphics == null) return; // fill composite buffer with white paint composite_graphics.setColor(Color.white); composite_graphics.fillRect(0, 0, CANVAS_W, CANVAS_H); // have images loaded? if ( (! img_tracker.checkAll(true)) || (! FoodObject.foodobj_img_tracker.checkAll(true)) ) { // text font Font txt_Font = new Font("Helvetica", Font.PLAIN, 9); // set text string font composite_graphics.setFont(txt_Font); // set text string color composite_graphics.setColor(Color.black); // write to screen composite_graphics.drawString("Loading Images...", 25, 25); } else { // is head event still active? // cycle through all food objects, if one food object is still expanding then head event is still active boolean head_action_complete_flg = true; for (idx = 0; idx < TOTAL_FOODOBJS; idx++) { if ( (food_obj[idx].active_flg) && (food_obj[idx].enlarge_flg) ) { head_action_complete_flg = false; break; // we've found an active enlarging food object, we're done here } } // shut down head action? if (head_action_complete_flg == true) head_action_flg = 0; // 1= on; 0= off // draw head draw_head(); // draw food object, cycle through all available food objects for (idx = 0; idx < TOTAL_FOODOBJS; idx++) { if (food_obj[idx].active_flg == true) food_obj[idx].draw_foodobject(FoodObject.GROW_FROM_CENTER); } } // black border composite_graphics.setColor(Color.black); composite_graphics.drawRect(0, 0, (CANVAS_W - 1), (CANVAS_H - 1)); // blast composite buffer to screen g.drawImage(composite_image, 0, 0, null); } // end method 'my_paint()' // draw head void draw_head() { int tmp_left, tmp_top, img_idx; // calc top/left tmp_left = ((CANVAS_W - HEAD_W) / 2) + 18; tmp_top = ((CANVAS_H - HEAD_H) / 2) - 4; // base idx, head if ( head_action_flg == 0 ) img_idx = BASE_IDX_HEAD_CLOSED; else img_idx = BASE_IDX_HEAD_OPEN; // squiggle anim base if (squiggle_flg == 1) img_idx = img_idx + 1; // draw head into buffer composite_graphics.drawImage(imgs[img_idx], tmp_left, tmp_top, null); // eyes // calc x,y loc tmp_left = tmp_left + 43; tmp_top = tmp_top + 171; // base idx, eyes // eyes closed? if (eyesstatus_flg == 0) img_idx = BASE_IDX_EYES_CLOSED; // gaze-- left, center, or right else { switch (gaze_flg) { // left case 0: img_idx = BASE_IDX_EYES_LEFT; break; // right case 1: img_idx = BASE_IDX_EYES_RIGHT; break; // center case 2: img_idx = BASE_IDX_EYES_CENTER; break; } } // squiggle anim if (squiggle_flg == 1) img_idx = img_idx + 1; // draw eyes into buffer composite_graphics.drawImage(imgs[img_idx], tmp_left, tmp_top, null); } // end method 'draw_head()' } // end class "TheChef"