Puzzling issue when character follows the mouse cursor - SOLVED

Started by johanvepa, Sun 25/09/2016 11:14:16

Previous topic - Next topic

johanvepa

In my little tower defense game, I want a feature where one can pickup items (made as Characters in AGS, not objects or inventory items) and drag them (mouse button held down) to another part of the screen, then drop them there (release mouse button). If the intended place for drop is not suitable, the item returns to its place of origin.

This is simple enough. I couldn't find a feature already in AGS that does this, so I did the following:

In globalscript:
Code: ags
Character *itemcarried;
export itemcarried;

function cTrashbin_PickUp()
{
itemcarried = cTrashbin;
}

function cBrikker2_Interact()
{
  if (itemcarried == cTrashbin)
  {
    cTrashbin.x = cBrikker2.x;
    cTrashbin.y = cBrikker2.y;
    itemcarried = null;
  }
}


In local script:
Code: ags

import Character *itemcarried;

function room_RepExec()
{

    //to pick stuff up and let it follow the mouse cursor
  if (mouse.IsButtonDown(eMouseLeft)) //if button is down, something is supposedly being carried
  {
    if (itemcarried == null) //in the instance nothing yet is assigned as the item carried :
    {
      if (IsInteractionAvailable(mouse.x, mouse.y, eModePickup))//if something is there to be picked up (in the globalscript this is possible for the cTrashbin):
      {
        ProcessClick(mouse.x,mouse.y, eModePickup); //in the event script for cTrashbin, this assigns cTrashbin as 'itemcarried', item will no longer be == null:
      }
      else //else if nothing is there to pick up, do no more about the mouse cursor pressed down:
      {
        return(0);
      }
    }
    else //if button is down and something is assigned as the item to be carried
    {
      //then each game cycle, the itemcarried's coordinates should be the mouse coordinates
      itemcarried.x = mouse.x;
      itemcarried.y = mouse.y; //The issue: when assigning the mouse y-coordinate as the itemcarried's room y-coordinate, the two does not match. I need to adjust value for the item's room y-coordinate
    }
  }
  else //if noone is holding the mouse button down
  {
    if (itemcarried != null) //in the instance a character is assigned as the itemcarried but the mousebutton is not down. This will happen if someone is releasing the mouse button after carrying stuff
    {
      if (IsInteractionAvailable(mouse.x, mouse.y, eModeInteract)) //if mouse coordinate (not item coordinate) is above a place where interaction is possible (in the script, a character that may be interacted with, i.e. the character cBrikker2)
      {
        ProcessClick(mouse.x,mouse.y, eModeInteract);//then run the eModeInteract script with that character
      }
      else //in the instance there is an item assigned to Character *item but there is nothing to interact with at the place the mouse button is released
      {
        itemcarried.Move(cBrikker1.x, cBrikker1.y, eNoBlock, eAnywhere); //move the item back to starting point
        itemcarried = null; //no 'item carried' any more
      }
    }
  }

//any other business
}


This works fine.


Issue
The background is larger than the screen to allow for characters walking in from outside the screen boundaries. So I have to add 95 to the y axis and lock viewport.

In order for 'Character *item' (in the example cTrashcan) to appear alongside the mouse cursor, and not 95 pixels away from it, I have to add to the y axis assigned to the coordinates of itemcarried in the above script.

And so, this part of the code
Code: ags
    else //if button is down and something is assigned as the item to be carried
    {
      //then each game cycle, the items ccordinates should be the mouse coordinates
      itemcarried.x = mouse.x;
      itemcarried.y = mouse.y; //Problem: when assigning the mouse y-coordinate to the item's room y-coordinate, the two does not really match. I need to add some value to the item's room y-coordinate
    }

could look like this to adjust the itemcarried's room coordinates:
Code: ags

    else //if button is down and something is assigned as the item to be carried
    {
      //then each game cycle, the items ccordinates should be the mouse coordinates
      itemcarried.x = mouse.x;
      itemcarried.y = mouse.y+110; //Problem: when assigning the mouse y-coordinate to the item's room y-coordinate, the two does not really match. I need to add some value to the item's room y-coordinate
    }


This should be simple. It works, meaning that itemcarried now appears alongside the mouse cursor. Problem: For some reason, the interaction with the character cTrashbin that in globalscript should trigger this:
Code: ags
function cTrashbin_PickUp()
{
itemcarried = cTrashbin;
}

just doesn't happen. Instead, the itemcarried returns to its poont of origin, as if there was nothing to interact with at the mouse coordinates.

If I take away "+110" from the itemcarried's room coordinates again, then it works fine.

Seemingly, the change in the room coordinates of 'itemcarried' changes how the mouse cursor interacts, but th emouse cursor's coordinates are not changed, only cTrashbins room coordinates are changes. I don't understand.


Crimson Wizard

#1
Quote
This is simple enough. I couldn't find a feature already in AGS that does this, so I did the following:

First of all, I think I will use this opportunity to shamelessly advertise my DragDrop module :tongue: which lets you drag everything in AGS, and even script dragging your custom entities:
http://www.adventuregamestudio.co.uk/forums/index.php?topic=53332.0

Your example, however, made me wonder if my module deals with scrollable rooms. Something I would need to check out.

As for your problem, I suspect that is because room objects and characters have their 0,0 coordinate at bottom. You need to take the height of their sprite into account.
For example, in my module I save the difference between object's origin and mouse coordinates at the moment of drag start, and then use it when moving/dropping to calculate proper object position.

Here is the example of how you get the character's height:
Code: ags

int GetCharacterHeight(Character *c)
{
  int sprite;
  ViewFrame* vf = Game.GetViewFrame(c.View, c.Loop, c.Frame);
  if (vf != null)
  {
    sprite = vf.Graphic;
    return Game.SpriteHeight[sprite];
  }
  return 0;
}

johanvepa

Wait, the problem was something else. I'm trying to ProcessClick at the character cBrikker2, but when the character being dragged (cTrashbin) is dragged by the mouse and is therefore at the same place as the mouse, naturally AGS is attempting to ProcessClick at the charcter cTrashbin instead of the character cBrikker2, since cTrashbin is above cBrikker2! cTrashbin is overshadowing cBrikker2.

How to solve this?

I could change the mouse cursor image to that of cTrashbin and make the real cTrashbin invisible. But that is somewhat impractical to code.

I could try to switch off cTrashbin. This was unsuccesful (same as line 31-34 of localscript in the code described earlier)=:
Code: ags
      if (IsInteractionAvailable(mouse.x, mouse.y, eModeInteract)) //if mouse coordinate (not item coordinate) is above a place where interaction is possible (in the script, a character that may be interacted with)
      {
        cTrashbin.Clickable = false;
        ProcessClick(mouse.x,mouse.y, eModeInteract);//then run the eModeInteract script with that character
        cTrashbin.Clickable = true;
      }



johanvepa

Wait, this time I got it (roll)

cTrashbin must be turned unclackable when it is picked up.

Two places must it be made clickable again: When it is 'placed' at cBrikker2, and when it is released and tgherefore returns to its place of origin.

This works.


Edit: I forgot to say thank you. Thank you Crimson    ;)

SMF spam blocked by CleanTalk