|
|
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);
}