Drag Puzzle (Solved)

Started by Maverick, Tue 06/12/2005 19:29:29

Previous topic - Next topic

Maverick

I need some help on a drag puzzle where you have to drag the different pieces of the puzzle into position with the mouse. The only info I could find on this topic was a post by OnlyOneKanobi some time back. The script was done in an older version of AGS and I tried to convert it to 2.71 but cannot seems to get it to work. The code was set up by Scorpiorus and I if I knew how to include the thread I would. The best I can do is thisÃ, 

http://www.adventuregamestudio.co.uk/yabb/index.php?topic=9963.msg121209#msg121209

Thanks

Ashen

Any chance you could link us to the code?
I know what you're thinking ... Don't think that.


Ashen

#3
OK then, how about what have you tried, and what isn't working?

From Scorpiorus' code, I tried this:

Thisa t the top of the room script:
Code: ags

int button_pressed=0;
Object *ob;


Then this in the rooms repeatedly_execute:
Code: ags

  if (mouse.IsButtonDown(eMouseLeft)) {
    if (button_pressed==0) {
      button_pressed = 1;
      ob = Object.GetAtScreenXY(mouse.x, mouse.y);
    }
  } else {
    button_pressed=0;
    if (ob != null) {
      ob.Baseline = 0;   
      ob = null;
    }
  }
 
  if (ob != null) {
    int width  = GetGameParameter(GP_SPRITEWIDTH, ob.Graphic, 0, 0);
    int height = GetGameParameter(GP_SPRITEHEIGHT, ob.Graphic, 0, 0);
    ob.Baseline = game.room_height;
     ob.SetPosition(mouse.x-width/2, mouse.y+height/2);
  }  
}


And it seems to work OK.
I know what you're thinking ... Don't think that.

Maverick

Thanks Ashen. The move object part works fine. The problem is that the object needs to be placed in a specific Hotspot which would then check whether or not it is in the correct position. Thats is the part I'm havingg trouble with. The code posted in the thread I referrenced was done prior to the solution given by Scorpiorus in his example puzzle and therefore does not cover the entire issue

The actual final script:

// room script file

// total number of objects (including object number 0 which isn't used)
#define _THE_NUMBER_OF_OBJECTS_YOU_HAVE_ 10Ã, 

// called when the puzzle is solved:
function on_puzzle_solved() {
Ã, 
Ã,  Display("Puzzle has just been solved!");
Ã, }
int button_pressed=0, ob=-1;
int correct = 0;

#sectionstart room_aÃ,  // DO NOT EDIT OR REMOVE THIS LINE
function room_a() {
Ã,  // script for room: Repeatedly execute
Ã, 
Ã, 
Ã,  if (IsButtonDown(LEFT)) {
Ã,  Ã,  if (button_pressed==0) {
Ã,  Ã,  Ã,  button_pressed = 1;
Ã,  Ã,  Ã,  ob = GetObjectAt(mouse.x, mouse.y);
Ã,  Ã,  Ã, 
Ã,  Ã,  Ã,  if (ob!=-1) {
Ã,  Ã,  Ã,  Ã,  Ã,  int widthÃ,  = GetGameParameter(GP_SPRITEWIDTH, GetObjectGraphic(ob), 0, 0);
Ã,  Ã,  Ã,  Ã,  Ã,  int height = GetGameParameter(GP_SPRITEHEIGHT, GetObjectGraphic(ob), 0, 0);
Ã,  Ã,  Ã,  Ã,  Ã, 
Ã,  Ã,  Ã,  Ã,  Ã,  //MoveObjectDirect(ob, mouse.x-width/2, mouse.y+height/2, 7);
Ã,  Ã,  Ã,  Ã,  Ã,  //while (IsObjectMoving(ob)) Wait(1);
Ã,  Ã,  Ã,  Ã,  Ã, 
Ã,  Ã,  Ã,  }
Ã,  Ã,  Ã, 
Ã,  Ã,  }
Ã,  } else {
Ã,  Ã,  button_pressed=0;
Ã,  Ã,  if (ob!=-1) {
Ã,  Ã,  Ã,  SetObjectBaseline(ob, 0);Ã,  Ã,  Ã, 
Ã,  Ã,  Ã,  ob=-1;
Ã,  Ã,  Ã, 
Ã,  Ã,  Ã,  int i = 1; correct = 1;
Ã,  Ã,  Ã,  while (i < _THE_NUMBER_OF_OBJECTS_YOU_HAVE_) {
Ã,  Ã,  Ã,  Ã,  int widthÃ,  = GetGameParameter(GP_SPRITEWIDTH, GetObjectGraphic(i), 0, 0);
Ã,  Ã,  Ã,  Ã,  int height = GetGameParameter(GP_SPRITEHEIGHT, GetObjectGraphic(i), 0, 0);
Ã,  Ã,  Ã,  Ã,  correct=correct*(GetHotspotAt(GetObjectX(i)+width/2, GetObjectY(i)-height/2)==i);
Ã,  Ã,  Ã,  Ã,  //Display("object number %d (correct=%d)", i, correct); //debug
Ã,  Ã,  Ã,  Ã,  i++;
Ã,  Ã,  Ã,  }
Ã,  Ã, 
Ã,  Ã,  Ã,  if (correct == 1) {
Ã,  Ã,  Ã,  Ã,  on_puzzle_solved(); //call an event function
Ã,  Ã,  Ã,  }
Ã,  Ã, 
Ã,  Ã,  }
Ã,  }
Ã,  Ã, 

Ã,  if (ob != -1) {
Ã,  Ã,  int widthÃ,  = GetGameParameter(GP_SPRITEWIDTH, GetObjectGraphic(ob), 0, 0);
Ã,  Ã,  int height = GetGameParameter(GP_SPRITEHEIGHT, GetObjectGraphic(ob), 0, 0);
Ã,  Ã,  SetObjectBaseline(ob, game.room_height);
Ã,  Ã,  SetObjectPosition(ob, mouse.x-width/2, mouse.y+height/2);
Ã,  }

My conversion to 2.7

#define NUMBER_OF_OBJECTSÃ,  Ã,  Ã,  11


//===================================================
// Function is called when puzzle is solved

function on_puzzle_solved() {
//----------------------------------------------------

Display("Puzzle solved");
}


int button_pressed=0; //problem as ob must be = -1
Object*ob;

int correct=0;

Ã,  // script for Room: Repeatedly execute
Ã, 
if (mouse.IsButtonDown(eMouseLeft)) {
Ã,  Ã,  if (button_pressed==0) {
Ã,  Ã,  Ã,  button_pressed = 1;
Ã,  Ã,  Ã,  ob= Object.GetAtScreenXY(mouse.x, mouse.y);
Ã,  Ã,  Ã, 
Ã,  Ã,  Ã,  if (ob!= null) {
Ã,  Ã,  Ã,  Ã,  Ã,  int widthÃ,  = GetGameParameter(GP_SPRITEWIDTH, ob.Graphic, 0, 0);
Ã,  Ã,  Ã,  Ã,  Ã,  int height = GetGameParameter(GP_SPRITEHEIGHT, ob.Graphic, 0, 0);
Ã,  Ã,  Ã,  Ã,  Ã, 
Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã, 
Ã,  Ã,  Ã,  }
Ã,  Ã,  Ã, 
Ã,  Ã,  }
Ã,  } else {
Ã,  Ã,  button_pressed=0;
Ã,  Ã,  if (ob!=null) {
Ã,  Ã,  Ã,  ob.Baseline = 0;Ã,  Ã,  Ã, 
Ã,  Ã,  Ã,  ob=null;
Ã,  Ã,  Ã, 
Ã,  Ã,  Ã,  int i = 1; correct = 1;
Ã,  Ã,  Ã,  while (i < 11) {// Objects in room = 11 although object 0 is not part of the puzzle
Ã,  Ã,  Ã,  Ã,  int widthÃ,  = GetGameParameter(GP_SPRITEWIDTH, ob.Graphic, 0, 0);
Ã,  Ã,  Ã,  Ã,  int height = GetGameParameter(GP_SPRITEHEIGHT, ob.Graphic, 0, 0);
//Ã,  Ã,  Ã,  Ã,  correct=correct*(Hotspot.GetAtScreenXY(ob.X+width/2, ob.Y-height/2)==i);
Ã,  Ã,  Ã,  Ã,  i++;
Ã,  Ã,  Ã,  }
Ã,  Ã, 
Ã,  Ã,  Ã,  if (correct == 1) {
Ã,  Ã,  Ã,  Ã,  on_puzzle_solved();
Ã,  Ã,  Ã,  }
Ã,  Ã, 
Ã,  Ã,  }
Ã,  }
Ã,  Ã, 

Ã,  if (ob != null) {
Ã,  Ã,  int widthÃ,  = GetGameParameter(GP_SPRITEWIDTH, ob.Graphic, 0, 0);
Ã,  Ã,  int height = GetGameParameter(GP_SPRITEHEIGHT, ob.Graphic, 0, 0);
Ã,  Ã,  ob.Baseline = game.room_height;
Ã,  Ã,  ob.SetPosition(mouse.x-width/2, mouse.y+height/2);
Ã,  }

I know it has something to do with the variables but I have no idea how to fix it (no script knowledge at all)

Ashen

#5
Code: ags
 correct=correct*(Hotspot.GetAtScreenXY(ob.X+width/2, ob.Y-height/2)==i);

You've commented this line out - I guess you realised it's where the problem is?

Hotspot.GetAtScreenXY()  returns a pointer (hDoor, for example), not a number as you need (and as GetHotspotAt() used to). Try replacing that line with:
Code: ags

Hotspot *myHot = Hotspot.GetAtScreenXY(ob.X+width/2, ob.Y-height/2);
correct=correct*(myHot.ID==i);


EDIT:
This is what I get for not reading things through properly .....

You need to change the while loop some, to this:
Code: ags

      while (i < 11) {// Objects in room = 11 although object 0 is not part of the puzzle
        int width  = GetGameParameter(GP_SPRITEWIDTH, object[i].Graphic, 0, 0);
        int height = GetGameParameter(GP_SPRITEHEIGHT, object[i].Graphic, 0, 0);
        Hotspot *myHot = Hotspot.GetAtScreenXY(object[i].X+width/2, object[i].Y-height/2);
        correct=correct*(myHot.ID==i);
        i++;
      }


As it is, you're alway checking the hotspot under ob, which obviously doesn't change with i - meaning correct will usually be 0, even when everything is in the righ place.
I know what you're thinking ... Don't think that.

Maverick

correct=correct*(Hotspot.GetAtScreenXY(ob.X+width/2, ob.Y-height/2)==i);
You've commented this line out - I guess you realised it's where the problem is?

Yes I did so I commented it out to be able to save and exit program.

I've changed the code but the puzzle does not run the way it should. Unlike the test puzzle by Scorpiorus mine is not made up from perfect squares.Ã,  It represents fragment of a letter (different shapes and sizes). I don't know if this would have anything to do with the corresponding hotspots. Should the hotspots be identical in shape and size as the objects to work?

The move with mouse works fine but I don't get "Puzzle has just been solved"Ã,  Ã, 


Ashen

Yes, the different sized shaped pieces could be the problem ...

I don't think the hotspots need to be exactly the same shape as the pieces - roughly the same shape would be useful, but not vital. The code decides if the piece is in the right place based on this bit:
Hotspot.GetAtScreenXY(ob.X+width/2, ob.Y-height/2)

I.e. - what hotspot is under the middle of the sprite, so it's possible your odd-shaped sprites are missing the needed hotspot. If you can work out where the middles of your sprites are going to be (the easiest way would probably be to assemble the letter in the room editor, get the coords for each object and do the math), then you know where your hotspots need to be - small circles or squares (not too small, depending on how accurate you want the player to have to be) around those 'centre' coords would do it.

Is this making sense? I do know what i'm talking about, promise, but I'm not sure I'm explaining it very well.
I know what you're thinking ... Don't think that.

Maverick

(the easiest way would probably be to assemble the letter in the room editor

That's exactly how I set up the hotspots and I made them the same shape as the graphic.

Let's see if I understand this correctly.
Even though the pieces of the letter are erratic in terms of shape the actual sprite that is used is rectangular in shape so the coords for the object will always be the centre of the rectangle represented by the width and height of the sprite? That means that if I used the document from which I cut the sprites as a template for setting up the hotspots it may not line up with the centre of the sprite (the actual image)? 

Ashen

Quoteif I used the document from which I cut the sprites as a template for setting up the hotspots it may not line up with the centre of the sprite

If you use the whole document as a template for the pieces? Huh? Sorry, I'm getting confused now ...

Since you've made the hotspots the same shapes as the pieces, there shouldn't be a problem unless the pieces are really oddly shaped, or have a lot of transparent space around them (i.e. the sprites 'center' isn't actually on the visible part of the sprite).
I know what you're thinking ... Don't think that.

Maverick

#10
If you use the whole document as a template for the pieces? Huh? Sorry, I'm getting confused now ...

I should have been more clear on this. I took the complete letter and cut and paste the individual pieces to different files to create the sprites. When you cut the piece away its exact shape remains on the original document as a blank space hence I could easily use this as a template for the hotspots. the idea is to have the puzzle change into the original letter on "solved"


(i.e. the sprites 'center' isn't actually on the visible part of the sprite).

Yes it is true that some of the sprites are oddly shaped and have a lot of transparent space around them and as I understand it this could cause a problem.

How would I go abot solving that without changing the sprites I.e how do I calcalute the centre?Ã,  50% of width and 50% of height

Edit:

I changed the sprites into rectangular strips (like paper from a shredding machine) and also the hotspots but still no go. Must be the code where it checks whether the puzzle is solved. I've been over it so many times but I don't see the problem (not that I know that much about scripting).

SMF spam blocked by CleanTalk