#import "MBtypes.h" #import "MBBill.h" #import "MButil.h" #import "MBComputer.h" #import "MBGame.h" #import "MBHorde.h" #import "MBNetwork.h" #import "MBOS.h" #import "MBUI.h" /* speed at which OS drops */ #define GRAVITY 3 /* speed of moving Bill */ #define SLOW 0 #define FAST 1 #define WCELS 4 /* # of bill walking animation frames */ #define DCELS 5 /* # of bill dying animation frames */ #define ACELS 13 /* # of bill switching OS frames */ static MBPicture *lcels[WCELS], *rcels[WCELS], *acels[ACELS], *dcels[DCELS]; static int width, height; static MBGame *game; static MBHorde *horde; static MBNetwork *network; static MBOS *os; static MBUI *ui; static void get_border(int *x, int *y) { int i = RAND(0, 3); int screensize = [game Game_screensize]; if (i % 2 == 0) *x = RAND(0, screensize - width); else *y = RAND(0, screensize - height); switch (i) { case 0: *y = -height - 16; break; case 1: *x = screensize + 1; break; case 2: *y = screensize + 1; break; case 3: *x = -width - 2; break; } } static int step_size(unsigned int level) { return MIN(11 + level, 15); } /* Moves bill toward his target - returns whether or not he moved */ static int move(MBBill *bill, int mode) { int xdist = bill->target_x - bill->x; int ydist = bill->target_y - bill->y; int step = step_size([game Game_level]); int dx, dy; int signx = xdist >= 0 ? 1 : -1; int signy = ydist >= 0 ? 1 : -1; xdist = abs(xdist); ydist = abs(ydist); if (!xdist && !ydist) return 0; else if (xdist < step && ydist < step) { bill->x = bill->target_x; bill->y = bill->target_y; } else { dx = (xdist*step*signx)/(xdist+ydist); dy = (ydist*step*signy)/(xdist+ydist); if (mode == FAST) { dx *= 1.25; dy *= 1.25; } bill->x += dx; bill->y += dy; if (dx < 0) bill->cels = lcels; else if (dx > 0) bill->cels = rcels; } return 1; } static void draw_std(MBBill *bill) { if (bill->cargo >= 0) [os OS_draw:bill->cargo :bill->x + bill->x_offset :bill->y + bill->y_offset + 35]; [ui UI_draw:bill->cels[bill->index] :bill->x :bill->y]; } static void draw_at(MBBill *bill) { MBComputer *computer = [network Network_get_computer:bill->target_c]; if (bill->index > 6 && bill->index < 12) [os OS_draw:0 :bill->x + bill->sx :bill->y + bill->sy]; if (bill->cargo >= 0) [os OS_draw:bill->cargo :bill->x + bill->x_offset :bill->y + bill->y_offset]; [ui UI_draw:bill->cels[bill->index] :computer->x :computer->y]; } static void draw_stray(MBBill *bill) { [os OS_draw:bill->cargo :bill->x :bill->y]; } /* Update Bill's position */ static void update_in(MBBill *bill) { int moved = move(bill, SLOW); MBComputer *computer = [network Network_get_computer:bill->target_c]; if (!moved && computer->os != OS_WINGDOWS && !computer->busy) { computer->busy = 1; bill->cels = acels; bill->index = 0; bill->state = BILL_STATE_AT; return; } else if (!moved) { int i; do { i = RAND(0, [network Network_num_computers] - 1); } while (i == bill->target_c); computer = [network Network_get_computer:i]; bill->target_c = i; bill->target_x = computer->x + [computer Computer_width] - BILL_OFFSET_X; bill->target_y = computer->y + BILL_OFFSET_Y; } bill->index++; bill->index %= WCELS; bill->y_offset += (8 * (bill->index % 2) - 4); } /* Update Bill standing at a computer */ static void update_at(MBBill *bill) { MBComputer *computer = [network Network_get_computer:bill->target_c]; if (bill->index == 0 && computer->os == OS_OFF) { bill->index = 6; if (computer->stray == NULL) bill->cargo = -1; else { bill->cargo = computer->stray->cargo; [horde Horde_remove_bill:computer->stray]; computer->stray = NULL; } } else bill->index++; if (bill->index == 13) { bill->y_offset = -15; bill->x_offset = -2; get_border(&bill->target_x, &bill->target_y); bill->index = 0; bill->cels = lcels; bill->state = BILL_STATE_OUT; computer->busy = 0; return; } bill->y_offset = height - [os OS_height]; switch (bill->index) { case 1: case 2: bill->x -= 8; bill->x_offset +=8; break; case 3: bill->x -= 10; bill->x_offset +=10; break; case 4: bill->x += 3; bill->x_offset -=3; break; case 5: bill->x += 2; bill->x_offset -=2; break; case 6: if (computer->os != OS_OFF) { [network Network_inc_counter:NETWORK_COUNTER_BASE: -1]; [network Network_inc_counter:NETWORK_COUNTER_OFF: 1]; bill->cargo = computer->os; } else { bill->x -= 21; bill->x_offset += 21; } computer->os = OS_OFF; bill->y_offset = -15; bill->x += 20; bill->x_offset -=20; break; case 7: bill->sy = bill->y_offset; bill->sx = -2; break; case 8: bill->sy = -15; bill->sx = -2; break; case 9: bill->sy = -7; bill->sx = -7; bill->x -= 8; bill->x_offset +=8; break; case 10: bill->sy = 0; bill->sx = -7; bill->x -= 15; bill->x_offset +=15; break; case 11: bill->sy = 0; bill->sx = -7; computer->os = OS_WINGDOWS; [network Network_inc_counter:NETWORK_COUNTER_OFF: -1]; [network Network_inc_counter:NETWORK_COUNTER_WIN: 1]; break; case 12: bill->x += 11; bill->x_offset -=11; } } /* Updates Bill fleeing with his ill gotten gain */ static void update_out(MBBill *bill) { int screensize = [game Game_screensize]; if ([ui UI_intersect:bill->x :bill->y :width :height :0 :0 :screensize :screensize]) { move(bill, FAST); bill->index++; bill->index %= WCELS; bill->y_offset += (8*(bill->index%2)-4); } else { [horde Horde_remove_bill:bill]; [horde Horde_inc_counter:HORDE_COUNTER_ON :-1]; [horde Horde_inc_counter:HORDE_COUNTER_OFF :1]; } } /* Updates a Bill who is dying */ static void update_dying(MBBill *bill) { if (bill->index < DCELS - 1){ bill->y_offset += (bill->index * GRAVITY); bill->index++; } else { bill->y += bill->y_offset; if (bill->cargo < 0 || bill->cargo == OS_WINGDOWS) [horde Horde_remove_bill:bill]; else { [horde Horde_move_bill:bill]; bill->state = BILL_STATE_STRAY; } [horde Horde_inc_counter:HORDE_COUNTER_ON :-1]; } } @implementation MBBill + (void)Bill_class_init:g :h :n :o :u { game = g; horde = h; network = n; os = o; ui = u; } /* Adds a bill to the in state */ + Bill_enter { MBBill *bill; MBComputer *computer; bill = [[self alloc] init]; bill->state = BILL_STATE_IN; get_border(&bill->x, &bill->y); bill->index = 0; bill->cels = lcels; bill->cargo = OS_WINGDOWS; bill->x_offset = -2; bill->y_offset = -15; bill->target_c = RAND(0, [network Network_num_computers] - 1); computer = [network Network_get_computer:bill->target_c]; bill->target_x = computer->x + [computer Computer_width] - BILL_OFFSET_X; bill->target_y = computer->y + BILL_OFFSET_Y; [horde Horde_inc_counter:HORDE_COUNTER_ON: 1]; [horde Horde_inc_counter:HORDE_COUNTER_OFF: -1]; bill->prev = NULL; bill->next = NULL; return bill; } - (void)Bill_draw { switch (state) { case BILL_STATE_IN: case BILL_STATE_OUT: case BILL_STATE_DYING: draw_std(self); break; case BILL_STATE_AT: draw_at(self); break; case BILL_STATE_STRAY: draw_stray(self); break; default: break; } } - (void)Bill_update { switch (state) { case BILL_STATE_IN: update_in(self); break; case BILL_STATE_AT: update_at(self); break; case BILL_STATE_OUT: update_out(self); break; case BILL_STATE_DYING: update_dying(self); break; default: break; } } - (void)Bill_set_dying { index = -1; cels = dcels; x_offset = -2; y_offset = -15; state = BILL_STATE_DYING; } - (int)Bill_clicked:(int)locx :(int)locy { return (locx > x && locx < x + width && locy > y && locy < y + height); } - (int)Bill_clickedstray:(int)locx :(int)locy { return (locx > x && locx < x + [os OS_width] && locy > y && locy < y + [os OS_height]); } + (void)Bill_load_pix { int i; for (i = 0; i < WCELS - 1; i++) { [ui UI_load_picture_indexed:"billL" :i :1 :&lcels[i]]; [ui UI_load_picture_indexed:"billR" :i :1 :&rcels[i]]; } lcels[WCELS - 1] = lcels[1]; rcels[WCELS - 1] = rcels[1]; for (i = 0; i < DCELS; i++) [ui UI_load_picture_indexed:"billD" :i :1 :&dcels[i]]; width = [ui UI_picture_width:dcels[0]]; height = [ui UI_picture_height:dcels[0]]; for (i = 0; i < ACELS; i++) [ui UI_load_picture_indexed:"billA" :i :1 :&acels[i]]; } + (int)Bill_width { return width; } - (int)Bill_height { return height; } - (int)Bill_get_state { return state; } @end