drawing "elastic" lines

Started by spook1, Mon 15/03/2004 08:58:44

Previous topic - Next topic

spook1

Hi there, again i have a question for dieas on my electricity game.

I try to preent the situation where I have an electric circuit board and plug in the componenets at obvious places. Instead I would prefer a workspace in which I can place my components at random places and connect them by flexible wires. Like the cords in "The incredible machine".
I would like to point out the starting point for a linem(click) and then draw the line to its end (click again). By checking the mouse.x and mouse.y at the clicks I can check if the wires is actually connected to a component. if not, the drawing will not take place.

I am thinking about the rawdraw functions, but I am not sure if it will work. I would have to draw the complete wiring at each cycle I am afraid.

can anyone refelct on this one?
I am not such a fast programmer that I have tried it already. If you tell me that it is not likely to succeed, i will look for other solutions..

Martijn

RickJ

#1
Example 3-17-04
I debugged my first example and have listed the script below.  
//===================================================================
// AGS ROOM SCRIPT
//
// PROJECT: AGS Tutorials
//
// ROOM:    Drawing Wires
//              
// ABSTRACT:
// This is a basic wire drawing example. Operation is as follows:
//
//    Draw Wire - Press and hold left mouse button while moving 
//                mouse.  Release mouse button to complete wire.
//
//    Select Wire - Position cursor over wire and left click.
//
//    Erase Wire - Position cursor over selected wire and left click.
//
// REVISION HISTORY:
// 03-17-03 RJJ   Original version
//
//===================================================================

//===================================================================
// Constant Definitions (i.e. #define)
//===================================================================
#define NONE -1
#define ALL  -2

//===================================================================
// WIRE LIST
//
// A wire list is needed to hold the coordniates of the wires/lines to 
// be drawn.  The drawing of a wire requires four coordniates.  It 
// would be convenient if  there were a variable type that could 
// hold all four coodniates.  Since there is not such a variable type
// built-in to AGS we can make one of our own using "struct"
//
// This constant define the maximum number of wires that may be in 
// the system.  The value below may be modified as needed.  The 
// more wires the more work AGS has to do.  
       #define MAX_WIRES                 3
//   
// The following constant defines the normal wire color.  It is used 
// to show  completed wire.
       #define  WIRE_NORMAL_COLOR        0
//   
// The following constant defines the normal wire color.  It is used 
// to show a selected line.  
       #define  WIRE_SELECT_COLOR        63488
//
// The following constant defines the drawing wire color.  It is used 
// to show a line that is the process of being drawn.
       #define  WIRE_DRAW_COLOR          65472
//
// The following constant defines the distance between the cursor and a 
// wire when attempting to select.
       #define  WIRE_SELECT_RANGE        10
//
//===================================================================

// Create a "wire"  variable data type definition, WIRE_DEF can then 
// be used as is "int", "string", "char", etc.
struct WIRE_DEF {
   int active;              // 0=don't draw, 1=draw this line
   int xcolor;              // line color
   int from_x;              // line coordinates
   int from_y;
   int to_x;
   int to_y;
   int dx;
   int dy;
   int m;
};

// Declare an array variable of type WIRE_DEF
WIRE_DEF wire[MAX_WIRES];

//===================================================================
// DrawWires
//
// Draw all the wires in the wire list, wire.  
//===================================================================
function DrawWires() 
{
   int i;

   // Erase the wires first
   RawRestoreScreen();

   // Draw the wires
   i=0;
   while (i<MAX_WIRES) {
      if (wire.active) {
         RawSetColor(wire.xcolor);
         RawDrawLine(wire.from_x,
                     wire.from_y,
                     wire.to_x,
                     wire.to_y);
      }
      i++;
   }
}

//===================================================================
// EraseWire
//
// Erase the wire specified by id, the wire array index.  If 
// an invalid id, such as -1, is specified then all wires are 
// erased.
//===================================================================
function EraseWire(int id) 
{
   int i;
   if ((id >= 0) && (id < MAX_WIRES)) {
      wire[id].active = 0;
   }
   else if (id==ALL) {
      i = 0;
      while (i<MAX_WIRES) {
         wire.active = 0;
         i++;  
      }
   }
}

//===================================================================
// WireIsSelected
//
// Return 1 if the specified wire is selected and 0 otherwise.
//
//===================================================================
function WireIsSelected(int id) 
{
   int status;
   
   if ((id>=0)&&(id<MAX_WIRES)&&(wire[id].xcolor==WIRE_SELECT_COLOR)) status=1;
   else status = 0;
   return status;
}

//===================================================================
// NewWire
//
// Search the wire array for an empty slot and create a new wire 
// in that slot.  The new line's start position will be set to the 
// current mouse position.
//===================================================================
function NewWire() 
{
   int i, id;

   // Find an empty slot
   id = NONE;
   i = 0;
   while (i<MAX_WIRES) {
      if (wire.active == 0) {
         id = i;
         i = MAX_WIRES;
      }
      i++;
   }

   // Set begin point of wire
   RefreshMouse();
   wire[id].active = 0;     //  don't make active until line length > 0
   wire[id].xcolor = WIRE_NORMAL_COLOR;
   wire[id].from_x = mouse.x;
   wire[id].from_y = mouse.y;
   wire[id].to_x   = mouse.x;
   wire[id].to_y   = mouse.y;

   // return id of new wire
   return id;
}

//===================================================================
// DragWire
//
// This function sets the specified wire's end point to the current 
// mouse position.
//===================================================================
function DragWire(int id) 
{
   RefreshMouse();
   if ((id >= 0) && (id < MAX_WIRES)) {
      wire[id].to_x   = mouse.x;
      wire[id].to_y   = mouse.y;
      wire[id].xcolor = WIRE_DRAW_COLOR;
      wire[id].active = 1;
   }
   else {
       Display("*** Error-DragWire, invalid id=%d specified",id); 
   }
}

//===================================================================
// CompleteWire
//
// This function completes the drawing of a wire.  It sets
// the specified wire's color to normal and calculates it's
// slope. 
//===================================================================
function CompleteWire(int id) 
{

   if ((id >= 0) && (id < MAX_WIRES)) {
      // Calculate line's slope
      wire[id].dx = (wire[id].to_x - wire[id].from_x);
      wire[id].dy = (wire[id].to_y - wire[id].from_y);
      if (wire[id].dx!=0) wire[id].m = ((wire[id].dy * 1000) / (wire[id].dx));
      else wire[id].m = 999999;

      // Set normal color
      wire[id].xcolor = WIRE_NORMAL_COLOR;

      // Set wire active 
      wire[id].active = 1;
   }
   else {
       Display("*** Error-CompleteWire, invalid id=%d specified",id); 
   }
}

//===================================================================
// SelectWire
//
// This function selects the specified wire's end point to the current 
// mouse position.
//===================================================================
function SelectWire(int sx, int sy) 
{
   int i, id, nx, ny, y, range, valid;
   int ymax, ymin, xmax, xmin, symax, symin, sxmax, sxmin;
   string buf;
   
   // Deselect any previously selected wire, onl allow one selectionat a time
   i = 0;
   while (i<MAX_WIRES) {
      if (wire.xcolor==WIRE_SELECT_COLOR) wire.xcolor = WIRE_NORMAL_COLOR;
      i++;
   }
 
   // Test each of the wires to see if the point sx,sy 
   // lies on or near the wire.
   id = NONE;
   i  = 0;
   while (i<MAX_WIRES) {

      // Validate selection coordinates
      valid = 1;
      if (wire.from_x > wire.to_x) {
         xmax = wire.from_x;
         xmin = wire.to_x;  
      }
      else {
         xmax = wire.to_x;
         xmin = wire.from_x;
      }
      if (wire.from_y > wire.to_y) {
         ymax = wire.from_y;
         ymin = wire.to_y;  
      }
      else {
         ymax = wire.to_y;
         ymin = wire.from_y;
      }
      sxmax = sx + WIRE_SELECT_RANGE;  
      sxmin = sx - WIRE_SELECT_RANGE;
      symax = sy + WIRE_SELECT_RANGE;
      symin = sy - WIRE_SELECT_RANGE;
   
      // Line segment fits within rectangular range of cursor
      if ((sxmax>xmax)&&(sxmin<xmin)&&(symax>ymax)&&(symin<ymin)) {
            wire.xcolor = WIRE_SELECT_COLOR;
            id = i;
            i = MAX_WIRES;
      }
      // Selection coordinates are within rectangular area 
      // containing line segment
      else if ((sx<=xmax)&&(sx>=xmin)&&(sy<=ymax)&&(sy>=ymin)) {

         // Normalize selection coordinates to from_x,y
         nx = sx -  wire.from_x;
         ny = sy -  wire.from_y;

         // Calculate (y = mx+b)  for normalized coordniate system
         y = (nx * wire.m)/1000;

         // Is y within range of ny ?
         range = y-ny;
         if (range < 0) range = -range;
         if (range < WIRE_SELECT_RANGE) {
            wire.xcolor = WIRE_SELECT_COLOR;
            id = i;
            i = MAX_WIRES;
         } 
      }
      i++;
   }
   return id;
}


continued ...

RickJ

Example (continued)
//===================================================================
// Event Handlers 
//
// The following functions are to be called by AGS event handler 
// routines. 
//===================================================================
int new_wire, sel_wire, tmp_wire;      // Wire id 
int debR, debL;                        // Mouse button debounce timers

function wire_start() {
   // Called when "Player Enters Room" 
   int i;
   
   RawSaveScreen(); 
   new_wire=NONE;
   sel_wire=NONE;
   tmp_wire=NONE;

   i=0;
   while (i<MAX_WIRES) {
      wire.active = 0;
      i++;
   }
}

function wire_execute() 
{
   int id;
   string buf;  

   // Use left button to draw a line, press left button and 
   // drag mouse.  Lift button to complete line.   
   if ((IsButtonDown(LEFT)==1)&&(new_wire == -1)) {      // Mouse Down - Create a new wire
      new_wire = NewWire();
   }
   else if (IsButtonDown(LEFT)==1) {                     // Mouse Drag - Drag the wire
      DragWire(new_wire);
   }
   else if ((IsButtonDown(LEFT)==0)&&(new_wire != -1)) { // Mouse Up - Complete the wire
      CompleteWire(new_wire);
      new_wire = -1;
   }

   // Use right button to select and delete lines.  Right 
   // click on a wire to selecte it.  Right click on a selected 
   // wire to delete it.  Right click anywhere but the wire to 
   // deselect it.
   if (IsButtonDown(RIGHT)) {  
      if ((WireIsSelected(sel_wire))&&(debR==0)) {
         EraseWire(sel_wire);
         sel_wire = NONE;
         tmp_wire = NONE;
      }
      else {
         sel_wire = SelectWire(mouse.x, mouse.y);
         debR = 10;
      }
   }
   else if (debR>0) debR--;

   
   // Update drawing changes
   DrawWires();

   // Debug messages
   StrFormat(buf,"Wire(%d) fx:%d fy:%d tx:%d ty:%d color:%d active:%d",
             id,
             wire[id].from_x,
             wire[id].from_y,
             wire[id].to_x,
             wire[id].to_y,
             wire[id].xcolor,
             wire[id].active);
   SetLabelText(0,0, buf);

   StrFormat(buf,"dx:%d dy:%d m:%d id:%d sw:%d tw:%d",
             wire[id].dx,
             wire[id].dy,
             wire[id].m, id, sel_wire, tmp_wire);
   SetLabelText(0,1, buf);
}

//===================================================================
// Event Handler Functions (i.e. function room_a())
//===================================================================
function room_a() {
  // script for room: Player enters screen (before fadein)
  GUIOff(MENU);
  wire_start();
  SetCursorMode(6);
  
}

function room_b() {
  // script for room: Repeatedly execute
  wire_execute();
}

spook1

Works great!

I have it implemented in a test-game and drawing lines works just perfect.

perfect script!! And well written and easy to understand. Great job!

SMF spam blocked by CleanTalk