|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T j
Length: 16953 (0x4239) Types: TextFile Names: »joystick.c.orig«
└─⟦b20c6495f⟧ Bits:30007238 EUUGD18: Wien-båndet, efterår 1987 └─⟦this⟧ »EUUGD18/Sun/Qix/joystick.c.orig«
#include "qix.h" #include "math.h" /* the pen marker */ short marker_curs_dat[] = { #include "marker.cursor" }; mpr_static(pen_image, 16, 16, 1, marker_curs_dat); short fast_draw_off_dat[] = { #include <images/mouse_left_hand.pr> }; mpr_static(ms_fast_off, 16, 23, 1, fast_draw_off_dat); short fast_draw_on_dat[] = { #include <images/mouse_left_hand_grey.pr> }; mpr_static(ms_fast_on, 16, 23, 1, fast_draw_on_dat); short slow_draw_off_dat[] = { #include <images/mouse_mid_hand.pr> }; mpr_static(ms_slow_off, 16, 23, 1, slow_draw_off_dat); short slow_draw_on_dat[] = { #include <images/mouse_mid_hand_grey.pr> }; mpr_static(ms_slow_on, 16, 23, 1, slow_draw_on_dat); /* joystick (really, arrow) symbols */ short left_arrow_dat[] = { #include "joystick.lf" }; mpr_static(joystick_left, 64, 64, 1, left_arrow_dat); short right_arrow_dat[] = { #include "joystick.rt" }; mpr_static(joystick_right, 64, 64, 1, right_arrow_dat); short up_arrow_dat[] = { #include "joystick.up" }; mpr_static(joystick_up, 64, 64, 1, up_arrow_dat); short dn_arrow_dat[] = { #include "joystick.dn" }; mpr_static(joystick_down, 64, 64, 1, dn_arrow_dat); /* a circle with line thru it */ short stop_dat[] = { #include "joystick.stop" }; mpr_static(joystick_stop, 64, 64, 1, stop_dat); /* a big right mouse button */ short ready_icon_dat[] = { #include "mouse.rt.icon" }; mpr_static(ready_icon, 64, 64, 1, ready_icon_dat); /* * the main window selection catches input interrupts and calls this * routine to process what just happened. Nothing is actually done * besides that -- that is, the pen is not moved, the qix isn't moved, * and sparks don't move. however, we will reset the "moving" variable, * start the or finish the "drawing" state, and reset the icon that displays * the joystick icon that indicates which way the user is moving. */ move_joystick(canvas, event, data) register Canvas canvas; register Event *event; { register int ID = event->ie_code; static start_fast; if (play_mode != REAL_PLAY && ID != ' ' && ID != MS_RIGHT) return; if ((ID == LOC_MOVE) && moving != NO_MOVE) { register int delta_x, delta_y; if (event_x(event) <= 0) event_set_x(event, 1); if (event_y(event) <= 0) event_set_y(event, 1); delta_x = event_x(event) - MID_X; delta_y = event_y(event) - MID_Y; /* didn't move enough */ if (abs(delta_x) <= SENS_FACTOR && abs(delta_y) <= SENS_FACTOR) return; if (abs(delta_x) > abs(delta_y)) if (delta_x > 0) moving = RIGHT; else moving = LEFT; else if (delta_y > 0) moving = DOWN; else moving = UP; } if (isascii(ID) && ID != ' ') { #ifdef DEBUG if (isdigit(ID)) { debug = ID - '0'; msg("Debugging level set to %d", debug); sleep(2); remove_msgs(); return; } else #endif DEBUG if (event_is_up(event)) { /* up events -- user released a key, so stop moving */ /* unimplemented -- holding key down results in fast up/down's */ moving = STOP; drawing = 0; return; } else if (event_shift_is_down(event)) fast = drawing = 1; else if (event_meta_is_down(event)) fast = !(drawing = 1); else drawing = 0; } switch(ID) { when MS_LEFT : fast = (drawing = (!event_is_up(event))); start_fast = TRUE; return; when MS_MIDDLE : fast = 0; if (start_fast == TRUE && region) drawing = 0; else drawing = !event_is_up(event); return; when MS_RIGHT : case ' ' : if (event_is_up(event)) break; /* if moving == NO_MOVE, RIGHT, LEFT, UP or DOWN */ if (!is_alive || play_mode != REAL_PLAY) { lives = 0; play_mode = REAL_PLAY; /* set Nowhere else but here! */ change_life(LIVE); /* "next" life in current game */ } else if (moving != STOP) { /* NO_MOVE state goes right to STOP state */ if (moving == NO_MOVE) reset_joystick_win(FALSE); /* all other directions go right to STOP state */ moving = STOP; } else /* STOP state goes right to NO_MOVE state */ moving = NO_MOVE, reset_joystick_win(TRUE); when 'h' : case 'H' : case KEY_RIGHT(10) : moving = LEFT; when 'l' : case 'L' : case KEY_RIGHT(12) : moving = RIGHT; when 'j' : case 'J' : case KEY_RIGHT(14) : moving = DOWN; when 'k' : case 'K' : case KEY_RIGHT(8) : moving = UP; when LOC_MOVE : break; /* let those thru! */ #ifdef DEBUG case '@' : no_qix_kill = !no_qix_kill; drawing = 0; when '#' : clear_sparks(); when '+' : lives = min(lives+1, MAX_LIVES); update_score(); drawing = 0; when '-' : lives = max(lives-1, 1); update_score(); drawing = 0; when '!' : drawing = 0; if (play_mode == REAL_PLAY) { lives = 0; change_life(LIVE); } /* fall thru */ #endif DEBUG default : return; /* do nothing */ } if (moving != NO_MOVE && (event_x(event) != MID_X || event_y(event) != MID_Y)) window_set(canvas, WIN_MOUSE_XY, MID_X, MID_Y, 0); } /* * The main routine waits for input from the user until an alarm goes off * which says, "ok, go to the next state of the machine" which may very * well be "do nothing". The timer is restarted when we're done processing * whatever we have to process. This is where the pen actually moves to the * next position, drawing lines, or running scared from a vicious spark. */ move_pen() { register int x = pen_x, y = pen_y, new_value, old_value; static slow_draw; if (!is_alive && lives > 0) { /* user has died and is waiting to start again */ sleep(2); change_life(LIVE); stop_timer(); /* change_life restarts it */ msg("Ready?"); sleep(2); remove_msgs(0); start_timer(); return; } /* don't play if the joystick isn't active */ if (moving == NO_MOVE || play_mode != REAL_PLAY) { if (play_mode != REAL_PLAY) { time_left--; if (play_mode == DEMO && lives > 0) { if (time_left == 0) { int lastmove = moving; register int left, right, up, down; drawing = 1; if (!(board[x][y] & NEW_LINE)) fast = (rrand() & 3); left = (!check_painted(x, y, CL_PNT_LEFT) && !(board[x-1][y] & NEW_LINE)); right = (!check_painted(x, y, CL_PNT_RIGHT) && !(board[x+1][y] & NEW_LINE)); up = (!check_painted(x, y, CL_PNT_TOP) && !(board[x][y-1] & NEW_LINE)); down = (!check_painted(x, y, CL_PNT_BOT) && !(board[x][y+1] & NEW_LINE)); if (!left && !right && !up && !down) moving = STOP, time_left = -1; /* let fuse catch up */ else { int dx = region ? region->x - x : 0; int dy = region ? region->y - y : 0; time_left = 15 + (rrand() & 31); /* first attempt to limit box to less than 25 X 25 */ if (region && (_ABS(dx) > 25 || _ABS(dy) > 25)) { if (_ABS(dx) > 25 || _ABS(dy) > 25 && (moving == LEFT || moving == RIGHT)) if (moving != LEFT && moving != RIGHT) moving = (dx > 25) ? RIGHT : LEFT; else moving = (dy > 0) ? DOWN : UP; else if (_ABS(dy) > 25) if (moving != UP && moving != DOWN) moving = (dy > 25) ? DOWN : UP; else moving = (dx > 0) ? RIGHT : LEFT; } /* Make sure we can move in that direction */ while (moving == lastmove || !left && moving == LEFT || !up && moving == UP || !down && moving == DOWN || !right && moving== RIGHT) moving = LEFT + (rrand() & 3); } } } else if (time_left <= 0) { drawing = 0; level = -2; moving = NO_MOVE; init_qix(); switch (play_mode = (play_mode + 1) % (DEMO+1)) { when SHOW_SCORES : clear_board(); score_board(TRUE, FALSE); time_left = 50; when SHOW_POINTS : score = 0; update_score(); move_fuse(fuse = NULL); /* just in case */ rm_cur_line(PIX_CLR); clear_board(); place_pen(); msg("Direct the mouse to control joystick."); time_left = 315; moving = LEFT; when SHOW_QIX : remove_msgs(0); msg("Your Enemies:"); sleep(2); time_left = 40; when SHOW_SPARKS : time_left = 90; when SHOW_FUSE : drawing = fast = 1; moving = UP; time_left = 280; when SHOW_SPIRAL : moving = STOP; drawing = 0; time_left = 100; when DEMO : time_left = 1; change_life(LIVE); stop_timer(); msg("Enclose more than\n75%%\nof the play area for extra bonus."); sleep(2); remove_msgs(0); level = -2; drawing = fast = 1; goto done; } } else switch (play_mode) { when SHOW_QIX : move_qix(); if (time_left == 1) { pw_text(draw_win, 200,200,PIX_SRC,big_font, "The qix."); sleep(2); } when SHOW_SPARKS : move_sparks(); if (time_left == 1) { pw_text(draw_win, 15, 110, PIX_SRC, big_font, "Sparx."); pw_text(draw_win,625, 110, PIX_SRC, big_font, "Sparx."); sleep(2); } when SHOW_FUSE : /* after the pw_text, this moves into spiral death trap */ switch (time_left) { when 230 : drawing = 0; pw_text(draw_win, convert_x(pen_x - 7), convert_y(pen_y + 7), PIX_SRC, big_font, "The fuse."); when 80 : pw_text(draw_win, 265, 445, PIX_SRC, big_font, "The Spiral Death Trap."); case 200 : case 240 : case 40 : case 20 : moving = LEFT, drawing = 1; when 110 : case 55 : case 30 : moving = RIGHT; when 126 : case 65 : case 35 : moving = UP; when 95 : case 45 : case 25 : moving = DOWN; } goto movit; when SHOW_SPIRAL : if (fuse) { /* when we die, fuse will be NULL */ time_left = 2; goto movit; } else if (region) { move_fuse(fuse = NULL); rm_cur_line(PIX_SRC); } when SHOW_POINTS : { char buf[5]; switch (time_left) { when 270 : msg("Use LEFT mouse button for Fast Draw."); drawing = fast = 1, moving = UP; score = 0; when 170 : msg("Use MIDDLE mouse button for Slow Draw."); drawing = 1, fast = 0, moving = UP; score = 0; when 250 : case 130 : moving = RIGHT; when 230 : case 90 : moving = DOWN; when 210 : drawing = 0, moving = RIGHT; pw_text(draw_win, convert_x(pen_x - 12), convert_y(pen_y - 25), PIX_SRC, big_font, sprintf(buf, "%d", score)); when 49 : /* make sure region is closed */ msg("Use RIGHT mouse button to STOP movement."); pw_text(draw_win, convert_x(pen_x - 12), convert_y(pen_y - 25), PIX_SRC, big_font, sprintf(buf, "%d", score)); when 15 : drawing = 0, moving = RIGHT; } goto movit; /* avoid moving qix and sparks */ } } } if (play_mode != DEMO) goto done; } if (move_qix() == -1) { change_life(DIE); return; } if (move_sparks() == -1) /* player got hosed */ return; /* don't restart timer */ movit: draw_joystick(); if (moving == STOP) { if (!cur_coord || move_fuse(&fuse) != -1) /* -1: fuse caught up */ start_timer(); return; } /* this forces the last fuse to go away */ (void) move_fuse((struct region *)NULL); /* this can't return -1 */ if (drawing && !fast && board[pen_x][pen_y] & NEW_LINE && (slow_draw = !slow_draw)) goto done; /* * x,y will be the new (proposed) position if the following is true... * if not drawing, then check to see if the current cell we're at connects * with the proposed new position. Logic says that it will connect if * it "points" that way.. f'rinstance, you can't move left if the current * cell doesn't have the "cell-line-left" (CL_LN_LF) attribute. Also, * check to see if the current cell has the NEW_LINE attribute. If so, * user should be drawing. If he isn't, the fuse starts. */ switch (moving) { when LEFT : if (check_painted(x, y, CL_PNT_LEFT) || !drawing && !(board[x][y] & (CL_LN_LF|NEW_LINE))) { if (play_mode == DEMO) time_left = 1; goto done; } x--; when RIGHT : if (check_painted(x, y, CL_PNT_RIGHT) || !drawing && !(board[x][y] & (CL_LN_RT|NEW_LINE))) { if (play_mode == DEMO) time_left = 1; goto done; } x++; when UP : if (check_painted(x, y, CL_PNT_TOP) || !drawing && !(board[x][y] & (CL_LN_UP|NEW_LINE))) { if (play_mode == DEMO) time_left = 1; goto done; } --y; when DOWN : if (check_painted(x, y, CL_PNT_BOT) || !drawing && !(board[x][y] & (CL_LN_DN|NEW_LINE))) { if (play_mode == DEMO) time_left = 1; goto done; } ++y; } old_value = board[pen_x][pen_y]; new_value = board[x][y]; /* * If drawing, you can't move onto yourself (a "new" line). [start fuse] * You can alwasy move onto an old line (completing a region if drawing). * If not drawing, you must be on an old line and moving * onto another old line. If we're not drawing and *should* be drawing * (determined by old_value's NEW_LINE bit set), start a fuse. * Also, player can't cheat by fast drawing and suddenly changing to * a slow draw just to close a region. Test to see if start_fast is * set correctly by testing "region" first. */ if (drawing && (new_value & NEW_LINE) && !(new_value & OLD_LINE) || !drawing && (old_value & NEW_LINE)) { if (!fuse) /* if a fuse isn't going, ignite one */ fuse = region; if (play_mode == DEMO) time_left = 1; else moving = STOP; goto done; } /* erase the pen_image, move, reset pen_image, draw line */ place_pen(); /* next, determine that if we are drawing, ignore that fact if we * are attempting to draw on top of an already drawn line. If we * are creating a new line, then go ahead and create it. */ if (drawing) { switch (moving) { when LEFT : if (board[pen_x][pen_y] & CL_LN_LF) goto redraw_pen; board[pen_x][pen_y] |= CL_LN_LF; board[x][y] |= CL_LN_RT; when RIGHT : if (board[pen_x][pen_y] & CL_LN_RT) goto redraw_pen; board[pen_x][pen_y] |= CL_LN_RT; board[x][y] |= CL_LN_LF; when UP : if (board[pen_x][pen_y] & CL_LN_UP) goto redraw_pen; board[pen_x][pen_y] |= CL_LN_UP; board[x][y] |= CL_LN_DN; when DOWN : if (board[pen_x][pen_y] & CL_LN_DN) goto redraw_pen; board[pen_x][pen_y] |= CL_LN_DN; board[x][y] |= CL_LN_UP; } draw(convert_x(x), convert_y(y), convert_x(pen_x), convert_y(pen_y), PIX_SRC); if (!region) { saved_edge = old_value; add_to_line(pen_x, pen_y); old_value = (board[pen_x][pen_y] |= NEW_LINE); } /* if drawing from a newline onto an old line, a region is completed */ if ((old_value & NEW_LINE) && (new_value & OLD_LINE)) { int new_level = close_region(x, y); if (!new_level) update_score(); if (new_level || (int)(((double)area_closed/TOTAL_AREA)*100) >= 75){ if (!new_level) { int percent_closed = (int)(((double)area_closed/TOTAL_AREA) * 100); msg("Closed %d%% of the board.", percent_closed); if (percent_closed > 75) { score += (percent_closed - 75) * 1000; update_score(); msg("1000 bonus points for each percent over 75%%"); msg("BONUS: %d", (percent_closed - 75) * 1000); } } else level++; sleep(3); clear_board(); /* removes msgs also */ change_life(LIVE); stop_timer(); if (level < 0) level++; if (level == 0) { msg("Split the 2 qix to advance score multiplier."); sleep(2); remove_msgs(0); } start_timer(); return; } } else if (new_value == 0) { board[x][y] |= NEW_LINE; add_to_line(x, y); } } redraw_pen: pen_x = x, pen_y = y; place_pen(); /* set the new pen image */ done: start_timer(); } draw_joystick() { Pixrect *image = moving == LEFT? &joystick_left : moving == RIGHT? &joystick_right : moving == UP? &joystick_up : moving == DOWN? &joystick_down : moving == STOP? &joystick_stop : &ready_icon; pw_rop(joystick_win, BOARD_WIDTH_IN_PIXELS/2-32, 2, 64, 64, PIX_SRC, image, 0,0); pw_rop(joystick_win, 100,32, 16,23, PIX_SRC, (drawing && fast)? &ms_fast_on : &ms_fast_off, 0, 0); pw_rop(joystick_win, 150,32, 16,23, PIX_SRC, (drawing && !fast)? &ms_slow_on : &ms_slow_off, 0, 0); } /* * if "see_it" -- then show the mouse cursor and stop moving mouse to middle * of window allowing allow player to grab beer. If "see_it" is * false, then the user is ready to move around, so make cursor go away, * and force all mouse moves to return to the middle of window. */ reset_joystick_win(see_it) { static int oldop; Cursor cursor = (Cursor)window_get(Draw, WIN_CURSOR); if (!see_it) { /* we don't want to see the cursor, so get rid of it */ /* get the current cursor and make it invisible */ oldop = (int)cursor_get(cursor, CURSOR_OP); cursor_set(cursor, CURSOR_OP, PIX_DST, 0); moving = STOP; draw_joystick(); } else { /* cursor_set(cursor, CURSOR_OP, oldop, 0); */ moving = NO_MOVE; draw_joystick(); } window_set(Joystick, WIN_CURSOR, cursor, 0); window_set(Draw, WIN_CURSOR, cursor, 0); }