home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ISV Strong Games
/
ISV_STRONG_GAMES.iso
/
desktop
/
polysaw
/
!PolySaw
/
source
/
c
/
dragging
next >
Wrap
Text File
|
1990-07-30
|
12KB
|
551 lines
/*
herein are functions called in response to a left button drag
or right click in window "board", in mode Play.
*/
#include "wimp.h"
#include "wimpt.h"
#include "win.h"
#include "event.h"
#include "werr.h"
#include "bbc.h"
#include "coords.h"
#include <stdlib.h>
#include "Polysaw.h"
/* data structures for dragging */
static DragState drag;
static Polymo dragged;
/************************ FUNCTIONS ************************/
static void flip_piece(void);
static void set_drag_state(coords_pointstr w, coords_pointstr m);
static void start_drag(void);
static void start_move_drag(void);
static void start_spin_drag(void);
static void update_move_drag(void);
static void update_spin_drag(void);
static void put_down_after_move(int wrk_x, int wrk_y);
static void put_down_after_spin(coords_pointstr mse);
static void eor_draw_moving_piece(int x, int y);
static void eor_draw_spinning_piece(coords_pointstr);
static void put_down_poly(void);
static BOOL room_for_dragged(void);
static void find_spin_angle(int *sin, int *cos, coords_pointstr origin, coords_pointstr from, coords_pointstr to);
/*_____________________________________________________________*/
void deal_with_play_but(coords_pointstr wrk, coords_pointstr mse, wimp_bbits mse_b, wimp_box box)
{
wimp_dragstr dragstr;
if (mse_b & wimp_BRIGHT)
{
if (which_piece(wrk) < MAX_PIECES)
{
drag.piece = which_piece(wrk);
dragged = piece[which_piece(wrk)];
flip_piece();
}
}
if (mse_b & wimp_BDRAGLEFT)
{
set_drag_state(wrk, mse);
dragstr.window = board_wh;
dragstr.type = 7;
dragstr.parent = box;
wimpt_noerr(wimp_drag_box(&dragstr));
start_drag();
}
}
void flip_piece(void)
{
int i;
for (i=0; i<dragged.nofunits; i++)
{
dragged.units[i].x = -dragged.units[i].x;
}
dragged.rotflipstate = 9 - dragged.rotflipstate;
put_down_poly();
}
void set_drag_state(coords_pointstr w, coords_pointstr m)
{
int p, i;
coords_pointstr pt;
drag.start = m;
drag.old = m;
for (p=0; p < nofpieces; p++)
{
pt.x = w.x - piece[p].cog.x;
pt.y = w.y - piece[p].cog.y;
/* pt is offset to centre of piece, as all piece info is rel. cog */
if ( coords_withinbox(&pt, &piece[p].box) )
{
for (i=0; i < piece[p].nofunits; i++)
{
if ( abs(pt.x - piece[p].units[i].x) <= HS &&
abs(pt.y - piece[p].units[i].y) <= HS )
{
drag.piece = p;
dragged = piece[p];
if ( (pt.x)*(pt.x) + (pt.y)*(pt.y) < piece[p].movespin_rad )
drag.kind = 1;
else
drag.kind = -1;
return;
}
}
}
}
drag.kind = 0;
drag.piece = MAX_PIECES+1;
return;
}
void start_drag(void)
{
event_setmask((wimp_emask)0);
if (drag.kind == 1) start_move_drag();
if (drag.kind == -1) start_spin_drag();
}
void start_move_drag(void)
{
wimp_redrawstr r;
int more;
r.w = board_wh;
r.box = board_windefn->ex;
wimpt_noerr(wimp_update_wind(&r, &more));
while (more)
{
eor_draw_moving_piece(drag.old.x, drag.old.y);
wimpt_noerr(wimp_get_rectangle(&r, &more));
}
}
void start_spin_drag(void)
{
wimp_redrawstr r;
int more;
int i;
/* fill in outline defns in drag.lines[]. */
for (i=0; i < piece[drag.piece].nofunits; i++)
{
drag.lines[4*i+0].x0 = piece[drag.piece].units[i].x + HS;
drag.lines[4*i+0].y0 = piece[drag.piece].units[i].y + HS;
drag.lines[4*i+0].x1 = piece[drag.piece].units[i].x + HS;
drag.lines[4*i+0].y1 = piece[drag.piece].units[i].y - HS;
drag.lines[4*i+1].x0 = piece[drag.piece].units[i].x + HS;
drag.lines[4*i+1].y0 = piece[drag.piece].units[i].y - HS;
drag.lines[4*i+1].x1 = piece[drag.piece].units[i].x - HS;
drag.lines[4*i+1].y1 = piece[drag.piece].units[i].y - HS;
drag.lines[4*i+2].x0 = piece[drag.piece].units[i].x - HS;
drag.lines[4*i+2].y0 = piece[drag.piece].units[i].y - HS;
drag.lines[4*i+2].x1 = piece[drag.piece].units[i].x - HS;
drag.lines[4*i+2].y1 = piece[drag.piece].units[i].y + HS;
drag.lines[4*i+3].x0 = piece[drag.piece].units[i].x - HS;
drag.lines[4*i+3].y0 = piece[drag.piece].units[i].y + HS;
drag.lines[4*i+3].x1 = piece[drag.piece].units[i].x + HS;
drag.lines[4*i+3].y1 = piece[drag.piece].units[i].y + HS;
}
r.w = board_wh;
r.box.x0 = piece[drag.piece].cog.x + 3*piece[drag.piece].box.x0/2;
r.box.y0 = piece[drag.piece].cog.y + 3*piece[drag.piece].box.y0/2;
r.box.x1 = piece[drag.piece].cog.x + 3*piece[drag.piece].box.x1/2;
r.box.y1 = piece[drag.piece].cog.y + 3*piece[drag.piece].box.y1/2;
wimpt_noerr(wimp_update_wind(&r, &more));
while (more)
{
eor_draw_spinning_piece(drag.start);
wimpt_noerr(wimp_get_rectangle(&r, &more));
}
}
void update_drag(void)
{
if (drag.kind == 1) update_move_drag();
if (drag.kind == -1) update_spin_drag();
}
void update_move_drag(void)
{
wimp_mousestr m;
wimp_redrawstr r;
int more;
int wrk_x, wrk_y;
wimpt_noerr(wimp_get_point_info(&m));
r.w = board_wh;
r.box = board_windefn->ex;
if (m.bbits)
{
drag.new.x = m.x;
drag.new.y = m.y;
wimpt_noerr(wimp_update_wind(&r, &more));
while (more)
{
eor_draw_moving_piece(drag.old.x, drag.old.y);
eor_draw_moving_piece(drag.new.x, drag.new.y);
wimpt_noerr(wimp_get_rectangle(&r, &more));
}
drag.old = drag.new;
}
else
{
wimpt_noerr(wimp_update_wind(&r, &more));
while (more)
{
eor_draw_moving_piece(drag.old.x, drag.old.y);
wimpt_noerr(wimp_get_rectangle(&r, &more));
}
wrk_x = coords_x_toworkarea(drag.old.x, (coords_cvtstr *)&r.box);
wrk_y = coords_y_toworkarea(drag.old.y, (coords_cvtstr *)&r.box);
put_down_after_move(wrk_x, wrk_y);
}
}
void update_spin_drag(void)
{
wimp_mousestr m;
wimp_redrawstr r;
int more;
int wrk_x, wrk_y;
wimpt_noerr(wimp_get_point_info(&m));
r.w = board_wh;
r.box.x0 = piece[drag.piece].cog.x + 3*piece[drag.piece].box.x0/2;
r.box.y0 = piece[drag.piece].cog.y + 3*piece[drag.piece].box.y0/2;
r.box.x1 = piece[drag.piece].cog.x + 3*piece[drag.piece].box.x1/2;
r.box.y1 = piece[drag.piece].cog.y + 3*piece[drag.piece].box.y1/2;
if (m.bbits)
{
drag.new.x = m.x;
drag.new.y = m.y;
wimpt_noerr(wimp_update_wind(&r, &more));
while (more)
{
eor_draw_spinning_piece(drag.old);
eor_draw_spinning_piece(drag.new);
wimpt_noerr(wimp_get_rectangle(&r, &more));
}
drag.old.x = drag.new.x;
drag.old.y = drag.new.y;
}
else
{
wimpt_noerr(wimp_update_wind(&r, &more));
while (more)
{
eor_draw_spinning_piece(drag.old);
wimpt_noerr(wimp_get_rectangle(&r, &more));
}
wrk_x = coords_x_toworkarea(drag.old.x, (coords_cvtstr *)&r.box);
wrk_y = coords_y_toworkarea(drag.old.y, (coords_cvtstr *)&r.box);
put_down_after_spin(drag.old);
}
}
void eor_draw_moving_piece(int x, int y)
{
int i;
wimpt_noerr(wimp_setcolour( (0<<7) | (3<<4) | 2));
for (i=0; i < piece[drag.piece].nofunits; i++)
{
wimpt_noerr(bbc_rectangle(x + piece[drag.piece].units[i].x - HS, y + piece[drag.piece].units[i].y - HS, 2*HS-1, 2*HS-1));
}
}
void eor_draw_spinning_piece(coords_pointstr mse)
{
int sin, cos; /* use binary point at bit 12 */
int a, b, x0, y0, x1, y1, i;
coords_pointstr cog;
wimp_wstate winstate;
wimpt_noerr(wimp_get_wind_state(board_wh, &winstate));
cog = piece[drag.piece].cog;
coords_point_toscreen(&cog, (coords_cvtstr *)&winstate.o.box);
/* now cog, drag.start, mse are in screen coords */
find_spin_angle(&sin, &cos, cog, drag.start, mse);
/* draw rotated lines */
for (i = 0; i < 4*(piece[drag.piece].nofunits); i++)
{
a = drag.lines[i].x0;
b = drag.lines[i].y0;
x0 = (int) ( ((a*cos)>>12) - ((b*sin)>>12) ) + cog.x;
y0 = (int) ( ((a*sin)>>12) + ((b*cos)>>12) ) + cog.y;
a = drag.lines[i].x1;
b = drag.lines[i].y1;
x1 = (int) ( ((a*cos)>>12) - ((b*sin)>>12) ) + cog.x;
y1 = (int) ( ((a*sin)>>12) + ((b*cos)>>12) ) + cog.y;
wimpt_noerr(wimp_setcolour( (0<<7) | (3<<4) | 2));
wimpt_noerr(bbc_move(x0, y0));
wimpt_noerr(bbc_draw(x1, y1));
}
}
void put_down_after_move(int wrk_x, int wrk_y)
{
int cogmodgrid;
cogmodgrid = dragged.cog.x % (2*HS);
dragged.cog.x = roundtonearest(wrk_x - cogmodgrid, 2*HS) + cogmodgrid;
cogmodgrid = dragged.cog.y % (2*HS);
dragged.cog.y = roundtonearest(wrk_y - cogmodgrid, 2*HS) + cogmodgrid;
put_down_poly();
}
void put_down_after_spin(coords_pointstr mse)
{
int sin, cos;
int i, ang, qtsin, qtcos;
coords_pointstr cog;
wimp_wstate winstate;
wimpt_noerr(wimp_get_wind_state(board_wh, &winstate));
cog = dragged.cog;
coords_point_toscreen(&cog, (coords_cvtstr *)&winstate.o.box);
find_spin_angle(&sin, &cos, cog, drag.start, mse);
if ( abs(sin) < (int) (0.7*4096) )
{
qtsin = 0;
if (cos < 0)
{
qtcos = -1;
ang=4;
}
else
{
qtcos = 1;
ang=0;
}
}
else
{
qtcos = 0;
if (sin < 0)
{
qtsin = -1;
ang=6;
}
else
{
qtsin = 1;
ang=2;
}
}
if (ang==2 || ang==6)
{
int xfidget, yfidget;
xfidget = dragged.cog.x % (2*HS);
yfidget = dragged.cog.y % (2*HS);
dragged.cog.x = roundtonearest(dragged.cog.x, 2*HS) + yfidget;
dragged.cog.y = roundtonearest(dragged.cog.y, 2*HS) + xfidget;
}
dragged.rotflipstate += ang;
dragged.rotflipstate &= 7;
for (i=0; i < dragged.nofunits; i++)
{
int x, y;
x = dragged.units[i].x;
y = dragged.units[i].y;
dragged.units[i].x = x*qtcos - y*qtsin;
dragged.units[i].y = x*qtsin + y*qtcos;
}
put_down_poly();
}
void put_down_poly(void)
{
int i, p, x, y;
p= drag.piece;
event_setmask((wimp_emask)1);
/* delete poly from grid[][] */
for (i=0; i<piece[p].nofunits; i++)
{
x = piece[p].cog.x + piece[p].units[i].x;
y = piece[p].cog.y + piece[p].units[i].y;
grid[(-y-HS)/(2*HS)][(x-HS)/(2*HS)] &= ~PIECE_BIT;
}
if (room_for_dragged())
{
force_piece_redraw(drag.piece); /* clear old position */
piece[drag.piece] = dragged;
force_piece_redraw(drag.piece); /* draw new posn */
}
else
bbc_vdu(7);
/* put poly back in grid, in new or old posn */
for (i=0; i<piece[p].nofunits; i++)
{
x = piece[p].cog.x + piece[p].units[i].x;
y = piece[p].cog.y + piece[p].units[i].y;
grid[(-y-HS)/(2*HS)][(x-HS)/(2*HS)] |= PIECE_BIT;
}
drag.kind = 0;
}
BOOL room_for_dragged(void)
{
int x,y,g,i, row, col;
for (i=0; i<dragged.nofunits; i++)
{
x = dragged.cog.x + dragged.units[i].x;
y = dragged.cog.y + dragged.units[i].y;
col = (x-HS)/(2*HS);
row = (-y-HS)/(2*HS);
if (col<0 || row<0 || col>=MAX_BOARD || row>=MAX_BOARD)
return FALSE;
g = grid[row][col];
if ( g & (PIECE_BIT | SQUARE_BIT) )
return FALSE;
}
return TRUE;
}
void find_spin_angle(int *sin, int *cos, coords_pointstr origin, coords_pointstr from, coords_pointstr to)
{
int c, d;
int fx, fy, tx, ty;
/* a bit of trig.
*
* origin
* *---------------to
* \ angle
* \
* \
* \
* \
* \from
*/
fx = from.x - origin.x;
fy = from.y - origin.y;
tx = to.x - origin.x;
ty = to.y - origin.y;
c = integer_sqrt(tx*tx + ty*ty);
d = integer_sqrt(fx*fx + fy*fy);
d = c*d;
if (c <= 8)
{
*sin = 4096;
*cos = 0;
}
else
{
*sin = ((fx*ty - fy*tx)<<12)/d;
*cos = ((fx*tx + fy*ty)<<12)/d;
}
}