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
Any chance you could link us to the code?
The post is in the Technical Archive: http://www.adventuregamestudio.co.uk/yabb/index.php?topic=9963
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:
int button_pressed=0;
Object *ob;
Then this in the rooms repeatedly_execute:
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.
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)
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:
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:
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.
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"Ã, Ã,Â
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.
(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)?
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).
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).