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
Example 3-17-04I 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 ...
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();
}
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!