Not Understanding Button.Animate, and some lazy questions

Started by Jack Hare, Sun 01/03/2009 08:40:11

Previous topic - Next topic

Jack Hare

Well, I've tried a bushel of searches, but everything I've turned up seems to refer to AGS versions before the Button.Animate command was added -- I'm using v3.1.  Hope I haven't missed something blazingly obvious...

What I want seems simple enough: to have GUI buttons with a normal Image, a normal Pushed Image, and an animated Mouse Over image.  This is the code I've tried to accomplish the first step, getting the button to animate on Mouse Over (using just one button, InvUp, for testing):

Code: ags

function repeatedly_execute()
  {
    GUIControl *theControl = GUIControl.GetAtScreenXY(mouse.x, mouse.y);
    GUI *theGui = GUI.GetAtScreenXY(mouse.x, mouse.y);
    if (theGui == gMain) {
      mouse.SaveCursorUntilItLeaves();
      mouse.Mode = eModeSelect;
      mouse.ChangeModeGraphic (eModeSelect, 10); // the Select cursor changes color depending on which GUI it's over
      if (theControl == InvUp){
        InvUp.Animate (2, 0, 15, eRepeat);
      }
    }
    else if (theGui == gMenu) {
      mouse.SaveCursorUntilItLeaves();
      mouse.Mode = eModeSelect;
      mouse.ChangeModeGraphic (eModeSelect, 5);
    }
    else if (GetLocationType(mouse.x, mouse.y) != 0){
      mouse.SaveCursorUntilItLeaves();
      mouse.Mode = eModeAct;
    }
    else {
        mouse.Mode = eModeGo;
    }
  }


...but this doesn't start playing the animation until the mouse is taken off the button -- while the cursor is over the button, it changes to the first frame but doesn't animate.  From the Button.Animate description in the manual, I don't see why this is the case or how to change it.

After that, of course, I want to restore the regular graphics for default and Pushed Image, but again, from the description of what appears to be the right function, Button.NormalGraphic, I haven't been able to figure out how to construct a correct command line.

As for the "lazy questions", there's a huge list of things remaining on my figure-it-out stack, and as long as I'm posting anyway, maybe some of you old hands can point me in the right directions (or at least away from the wrong ones) -- these aren't 'real' questions yet, since I haven't done intensive research on any of them, just some things I want to accomplish and would appreciate any tips or feedback on:

* I have a black status bar that remains always visible on the lower edge of the screen, and I'd like to use this space to display several different types of thing:  game messages (such as @OVERHOTSPOT@ results, "Use Item on [object name]", and so forth); the Main Menu (which is a simple row of text buttons, "[ save ]  [ load ]  [ new ]" etc.); and several of the Menu options themselves (for instance, the Save "window" would just be a line of text, "Name this saved game: _________ [ ok ]  [ cancel ]", similar for Confirm Quit and Confirm Restart).

I can think of several ways to accomplish this, but I'm interested in hearing your thoughts on simple and elegant ways -- ideally, using the smallest possible number of different images, GUIs and buttons/labels stacked atop one another.

* I want to have a Map window in which one can zoom the view in and out (between three discrete scale images; it doesn't need to animate between them), and drag or scroll the map image around (ideally, by grabbing and dragging it in the manner of Google Maps); on the map I'd like the locations to highlight on Mouse Over, and be available for the "Look" and "Go" commands (with a routine to check whether your character has a clear path to "zip" to a new location).  Again, I do plan to work this out on my own, but there are so many sub-tasks involved that I'm finding the whole thing a little overwhelming -- any advice on how to get started with this particular complex of functions would be greatly appreciated.

[ edit: I looked up some map-related threads, and though I've gotten some ideas, the most specific issue I have is that I want to have the map visible through a window on the screen -- that is, NOT taking up the whole screen, and with the current room still visible around the edges of the GUI. ]

* Finally (for now), because this game involves a LOT of characters, objects and locations, I plan on constructing it as a series of Episodes, each being a self-contained game covering a given amount of the overall story.  To make that work, I want the player to be able to continue from their save of the previous chapter (structurally, the game is mapped out such that each chapter has a range of beginnings based on the possible endings of the preceding).  I don't EVEN know where to begin on this; is there a reasonably simple way to set up such a thing?  In particular, is there anything I should be considering right from the start with an eye toward making the game work this way?

Thanks for any help you feel like giving!   ;D
This post isn't self-referential, unless you count the signature line.

Trent R

Button.Animate: I have a feeling it's similar to putting a Walk() in rep_exec. Basically, it calls it everysingle frame, which actually doesn't make it walk at all. The manual entry for Button.Animate says "You can abort an animation at any time by setting the button's NormalGraphic property, or starting a new animation on the same button."

Button.NormalGraphic = 47; //Sets it to that spriteslot's number. Simple enough.

Status bar: @OVERHOTSPOT@ is great, but doesn't work for everything. Just keep in mind the GetAtScreenXY functions :) Also, you could try to dynamically change some of those controls in the script using Clickable, SetPosition, Visible, and other functions.

Map window: You'll often see suggestions for making a world map as a room, and enabling objects as you discover new locations. However, if you want it scrollable, I'd suggest a GUI. I'm not familiar with the code for click and drag (although I do know a forum search will help you), remember to create a function under rep_exec that bounds the edges to the viewport (so you won't see behind the GUI). Also, if you want buttons for look, travel, or even a legend, I'd suggest making a second GUI with a higher X-order so that it won't be dragged out too.

Episodic feature: A few ideas. 1)You could either create a game template once you set up characters, GUIs, InventoryItems, and rooms shared by all the games. 2) Export a file at the end of the game, which will then be loaded into the sequel. Quest For Glory does this because you have stats to raise, and can continue your character's development in the sequels. Check out the File functions in the manual. 3) Check out RUNAGSGame, but make sure you pay close attention to the manual and it's warnings. (such as the same AGS version,etc)


Hope I helped. :D
~Trent
To give back to the AGS community, I can get you free, full versions of commercial software. Recently, Paint Shop Pro X, and eXPert PDF Pro 6. Please PM me for details.


Current Project: The Wanderer
On Hold: Hero of the Rune

Jack Hare

Quote from: Trent R on Sun 01/03/2009 10:02:15
Button.Animate: I have a feeling it's similar to putting a Walk() in rep_exec. Basically, it calls it everysingle frame, which actually doesn't make it walk at all. The manual entry for Button.Animate says "You can abort an animation at any time by setting the button's NormalGraphic property, or starting a new animation on the same button."

Button.NormalGraphic = 47; //Sets it to that spriteslot's number. Simple enough.

A-HAH!  No, I WAS just being dumb on this one -- I tried several different 'phrasings' for the line, but what I didn't notice was that I'd been using == instead of = !  *headsmack*  That ought to solve stopping the animation and resetting the button's graphics, but I'm still not sure how to get it to play while the mouse is over the button.  Should that code go somewhere other than RepEx?  An on_event, perhaps?

QuoteStatus bar: @OVERHOTSPOT@ is great, but doesn't work for everything. Just keep in mind the GetAtScreenXY functions :) Also, you could try to dynamically change some of those controls in the script using Clickable, SetPosition, Visible, and other functions.

Right on -- I guess that a stack of buttons and labels in a single GUI really is the tidiest approach for what I'm doing with the status/menu bar (as opposed to creating multiple GUIs that display in the same location).  Nice to have some confirmation that I'm at least researching the right commands!

QuoteMap window: You'll often see suggestions for making a world map as a room, and enabling objects as you discover new locations. However, if you want it scrollable, I'd suggest a GUI. I'm not familiar with the code for click and drag (although I do know a forum search will help you), remember to create a function under rep_exec that bounds the edges to the viewport (so you won't see behind the GUI). Also, if you want buttons for look, travel, or even a legend, I'd suggest making a second GUI with a higher X-order so that it won't be dragged out too.

Yeah, a map room seems to be the most common approach; I just don't think it quite fits with the overall visual and structural scheme for this game.  Oddly enough, I've already found a script (which I'm using in a very different game) for clicking and dragging a character, which I believe I can adapt to dragging a map 'object' (not necessarily an Object in the scripting sense) -- maybe.  How to get it to display only within a certain box is the part I'm not too sure about, but I guess I ought to get all the GUI images drawn and the basic display functions coded before worrying about the map sub-functions!  :)

QuoteEpisodic feature: A few ideas. 1)You could either create a game template once you set up characters, GUIs, InventoryItems, and rooms shared by all the games. 2) Export a file at the end of the game, which will then be loaded into the sequel. Quest For Glory does this because you have stats to raise, and can continue your character's development in the sequels. Check out the File functions in the manual. 3) Check out RUNAGSGame, but make sure you pay close attention to the manual and it's warnings. (such as the same AGS version,etc)

I'm pretty sure #2 will best work for my purposes, but I'll be looking into all of these suggestions -- on closer analysis, I realize that I need to do a good bit more event-mapping on paper before I know for sure how much information a new game will need to continue from an old.  In any case, it's nice to know that the basic concept of episodic continuation isn't just ridiculous.

QuoteHope I helped. :D
~Trent

Sure did!   ;D  More than anything else, I just needed to get some input from real humans -- been working on this in isolation for too long, my brain is starting to feel as overheated as my hard drive.  Probably why I'm being so chatty and rambling here, too.

You've handed me a good bundle of threads to pull on -- I think I can start hacking away at the code again with a more certain footing.  But for right now I've got to haul myself to bed before my cortex melts.  Thanks!   8)
This post isn't self-referential, unless you count the signature line.

Khris

Since there's no Button.Animating property, you have to use a variable.
Above rep_ex, declare "bool btn_an[10];".
Instead of "InvUp.Animate (2, 0, 15, eRepeat);",
use:
Code: ags
    if (!btn_an[InvUp.ID]) {
      btn_an[InvUp.ID] = true;
      InvUp.Animate (2, 0, 15, eRepeat);
    }


If the mouse isn't over InvUp, set the var back to false and reset the button's NormalGraphic to halt the animation.
You can do this for several buttons, just note that they all have to have different IDs for this method to work, because I've used an array to store if they're currently animating or not.
If you want this to work for a button on another GUI, use another array/var.

About the map window: use a cropped & resized global DynamicSprite as GUI background upon opening and during dragging the map.
To highlight spots, keep their coords & names in a struct.
Code: ags
// header
struct strMapLoc {
  bool unlocked,
  int x,
  int y,
  String name,
  int room
};

// global script

strMapLoc MapLoc[20];

void SetMapLocs() {
  MapLoc[1].x = 123:
  MapLoc[1].y = 234;
  ...
}

// inside game_start
  SetMapLocs();


While the map is open and not dragged, rep_ex-go through all MapLocs, if they're unlocked, calculate their current screen position based on original coords, zoom and offset, calculate mouse distance (optionally using a radius value from the struct) and if below zoom*radius, draw their highlighted sprite on the map DynamicSprite before displaying it. Store the currently highlighted MapLoc to send the player to its room upon clicking it.

Jack Hare

Cool!  Sweet!  Thanks!   ;D

I've still got to bash together the map GUI graphics and at least a rough of the map itself before I can really start assembling that, but with this help I ought to be able to set up all the animating buttons today.  Kick.ash!  ;)
This post isn't self-referential, unless you count the signature line.

SMF spam blocked by CleanTalk