Menu

Show posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Show posts Menu

Messages - monkey0506

#241
Quote from: slasher on Fri 20/03/2015 13:13:17...this works for me:

In Global asc:
Code: ags
function on_event (EventType event, int data) {
 AudioChannel *bgm;
 void SetBGM(AudioClip *music) {
 if (bgm != null && bgm.PlayingClip == music) return; // don't if music is already playing
 bgm = music.Play();
} 
}

No it doesn't. AGS does not support nested functions, which is exactly what you've posted here. You're also (making an attempt at) "calling" this nested function every single time any event (that is handled by on_event, of course) occurs. Your nested function also would never do anything as you are creating a pointer (which defaults to null) immediately before checking that it is not null. Here's an amended version of what you were trying to suggest (for posterity's sake):

Code: ags
AudioChannel *bgm;

void SetBGM(AudioClip *music)
{
  if (bgm != null && bgm.PlayingClip == music) return; // don't play the music if it's already playing
  bgm = music.Play();
}

function on_event (EventType event, int data)
{
  if (event == eEventEnterRoomBeforeFadein)
  {
    SetBGM(aMusicName);
  }
}
#242
This actually makes me wonder if the default shouldn't just be set to 32-bit anyway. Modern versions of Windows actually have difficulty running applications that aren't 32-bit, so I'd say that the stigma of performance is beginning to lean in favor of 32-bit rather than away from it.
#243
Quote from: Lord Vetinari on Thu 19/03/2015 20:49:34it's hard for a newbie to understand to what extent you can push the engine.

That's a constantly evolving value though, and is entirely dependent on the version of AGS you're using as well as the END-user's hardware specs.

However, I'm fairly certain that even low-end computers should still be able to handle at least 20-30 characters on screen with recent versions of AGS, without incurring any performance hits. Test things out yourself early on and often (and on as many systems as you can), and you should be able to reasonably gauge if there's any bottlenecks.
#244
You could add a custom text property to the room and then use Room.GetTextProperty in the GlobalScript's on_event for eEventEnterRoomBeforeFadein:

Code: ags
// GlobalScript.asc
// Room property is created in the room editor - we'll call it "Name"
// Also in the GUI editor, add a GUI Label control to your icon bar - we'll call it "lblRoomName"

function on_event(EventType event, int data)
{
  if (event == eEventEnterRoomBeforeFadein)
  {
    lblRoomName.Text = Room.GetTextProperty("Name");
  }
}


And that's it! No additional code to have to remember to copy into room scripts or anything like that, just set the name for each room in the custom properties editor once and you're done.
#245
Engine Development / Re: Porting to Allegro 5
Fri 20/03/2015 16:10:59
I like VS as an IDE, but Microsoft's compiler is the Internet Explorer of compilers. It has no respect or compliance for the standard. I'm trying to use very simple features that were standardized by the C++11 standard, such as the noexcept keyword, but VS2013 doesn't support it. And it's not like they didn't know about the keyword beforehand, the noexcept keyword was officially proposed in 2010.

I probably will take a look at just using mingw instead.
#246
The InvWindow.ItemHeight and InvWindow.ItemWidth properties can also be changed in the script IIRC, so if it looks right in the editor, try searching for any usages of those properties in your scripts.
#247
I've actually thought about trying to come up with a system for breaking a Character apart like this. I've never actually tested anything like this, but the main concern would be memory consumption vs. runtime performance. Obviously if the memory consumption goes too high then it will, in fact, result in runtime performance issues, but that would be an exceptional case anyway.

Using a single character with different views for every single costume change would obviously take up the most memory (bloating your file size), but that may be the best route depending on your needs, though I wouldn't count on it. Using multiple characters will probably be best. What I might do in this case (single character) would be to treat the character's views as a (pseudo) three-dimensional array like this:

Code: ags
#define AI_HEAD_COUNT 5
#define AI_TORSO_COUNT 10
#define AI_ARMS_COUNT 3
int aiView[]; // pseudo 3D array, aiView[head][torso][arms], stores view number for head, torso, arms combination
int aiHead = 0; // AI current head
int aiTorso = 0; // AI current torso
int aiArms = 0; // AI current arms

int GetAIViewIndex(int head, int torso, int arms) // returns index of aiView[head][torso][arms]
{
  // TODO: validate parameters? (e.g., head > AI_HEAD_COUNT?)
  return (((head * AI_TORSO_COUNT) + torso) * AI_ARMS_COUNT) + arms;
}

int GetAIView(int head, int torso, int arms) // returns the actual view number of the matching view for head, torso, and arms
{
  // TODO: return AI_DEFAULT_VIEW + GetAIViewIndex(head, torso, arms);
  // see note below
  return aiView[GetAIViewIndex(head, torso, arms)];
}

void SetAIView(int head, int torso, int arms, int view) // sets the view number for this head, torso, arms combination
{
  // in fact, storing this in an array might be overkill (see note below)
  aiView[GetAIViewIndex(head, torso, arms)] = view;
}

function game_start()
{
  aiView = new int[AI_HEAD_COUNT * AI_TORSO_COUNT * AI_ARM_COUNT];
  // now, we'll initialize the views...
  int view = AI_DEFAULT_VIEW; // TODO: replace AI_DEFAULT_VIEW with the FIRST of your SEQUENTIALLY NUMBERED views
  // TODO: note, views should be numbered sequentially!
  // The way this works:
  // * Set the "normal" view to have the lowest view number
  // * Now, KEEPING the SAME head AND torso, set each change of the arms to the subsequent view number
  // * Now, KEEPING the SAME head, change to the next torso, then set each set of arms to the subsequent view
  // * Do this for each combination of THIS head, all torsos, and all arms
  // * Now, change to the next head, default torso, and iterate through all arms, setting the subsequent view...
  // That's probably confusing! I'm beginning to doubt you'll actually go for this route anyway...
  // You could also reduce memory consumption by NOT storing this in an array and just use AI_DEFAULT_VIEW + GetAIViewIndex(head, torso, arms) instead.
  // This is more conceptual to try and help visualize how the views should be ordered.
  int head = 0;
  int torso = 0;
  int arms = 0;
  while (head < AI_HEAD_COUNT)
  {
    torso = 0;
    while (torso < AI_TORSO_COUNT)
    {
      arms = 0;
      while (arms < AI_ARMS_COUNT)
      {
        SetAIView(head, torso, arms, view);
        view++; // assumes all views are sequentially numbered
        arms++;
      }
      torso++;
    }
    head++;
  }
}

void ChangeAIView(int head, int torso, int arms) // changes character cAI's View, based on head, torso, and arms (must be set with SetAIView first - see game_start)
{
  cAI.ChangeView(GetAIView(head, torso, arms));
}

void ChangeAIHead(int head)
{
  aiHead = head;
  ChangeAIView(aiHead, aiTorso, aiArms);
}

void ChangeAITorso(int torso)
{
  aiTorso = torso;
  ChangeAIView(aiHead, aiTorso, aiArms);
}

void ChangeAIArms(int arms)
{
  aiArms = arms;
  ChangeAIView(aiHead, aiTorso, aiArms);
}


That's really more less complicated than it looks, but the idea is to specifically control the order/numbering of the views so that you can then just offset from a default view number to get the view you need.

All of that said, unless you have dozens of characters on screen at the same time, having multiple Character objects representing the head, torso, and arms of a single character probably won't cause so much of a slow-down that you would need to resort to creating hundreds of separate views (and thousands upon thousands of images).
#248
Engine Development / Re: Porting to Allegro 5
Mon 16/03/2015 20:12:56
Just as an update on my progress...

I discovered something about ALLEGRO_USTR that I really can't agree with, which carried over into the ALX String implementation: a total lack of consistency between code point offsets and byte offsets when accessing a character in the string. Since ALLEGRO_USTR is a UTF-8 string, the characters are variably sized (1 to 4 byte) code points. However, I see no practical reason whatsoever why a string class should allow you to access a byte in the middle of a code point directly. If you absolutely need access to the raw bytes, then the underlying char* can be exposed as needed.

To this end, I completely revamped the String and String::CodePointRef classes. My working version of the String class refers to characters exclusively as String::CodePoint objects which represent the whole character. All offsets are code point offsets, not byte offsets. Overall I feel that this is a much better representation of what people think of when they speak of a String class.

There's also a problem with ALX's Bitmap::LockedRegion class, in that both Bitmap and Bitmap::LockedRegion can be used to unlock the Bitmap (the Allegro functions only permit the ALLEGRO_BITMAP* to be unlocked, not the ALLEGRO_LOCKED_REGION*). ALX's solution to this was to simply make the LockedRegion a non-owner of the Bitmap. The issue with this approach is that ALX's pseudo-shared Shared class had no way of telling if the object had been destroyed - ergo, the LockedRegion would have no way of knowing if the Bitmap had been destroyed. I spent some time looking into other approaches, but ultimately what seemed best was to just make the LockedRegion an owner of the Bitmap that in turn owns the LockedRegion. When the LockedRegion is unlocked (not necessarily destroyed), it releases its ownership of the Bitmap (allowing the Bitmap to be destroyed, if there are no other owners); when the Bitmap is unlocked, it releases its ownership of the LockedRegion (allowing the LockedRegion to be destroyed). This type of circular reference didn't seem particularly ideal, but with a proper Shared class it should work as intended.

This is all rather frustrating, but I feel that it will be worth it in the end...

I've noticed that some of the ALX classes really don't have any purpose anyway, like the EventSource class -- ALLEGRO_EVENT_SOURCE*s are never allocated or deleted by Allegro, so the pseudo-shared implementation ALX provided of that class could never have ownership of the pointer (well, it could allocate/delete a pointer itself, but it doesn't). I've parsed somewhere around half of the ALX files. I think I'll start building the program entry point and see how far I can get with that...

Oh, and Visual Studio is terrible. I'm on the verge of abandoning it because of its horrific implementation of the C++ standard. >:(
#249
Thanks for that clarification Snarky. I've never used more than 8-bit channels myself, so I didn't really know how to explain it that well. ;)
#250
Something seems wrong here. Images of any size can be imported at 32-bit with or without an alpha channel. A 1x1 image with alpha can be saved and imported into AGS correctly.

You do not need to downgrade your graphics to 16-bit.

You might need to check that your image is actually set to 8-bits per channel (32-bit RGBA leaves 8-bits per channel) - which it should be anyway if you're actually exporting a 32-bit image - because something is wrong with your image if it's not letting you save it as a PNG.
#251
The manual refers to this as the "viewport" of the room. If the room is wider than the game resolution, then the "camera" will automatically pan to follow the player character as they walk around the screen. For more precise control, you can use the SetViewport function. You may also have your room scroll up and down by having the room taller than the game resolution.

Example:

Game resolution is 800x600, room size is 1280x600. This room will scroll left and right.

Game resolution is 320x240, room size is 320x900. This room will scroll up and down.

As stated in the manual entry for SetViewport, you can call ReleaseViewport to allow the automatic panning to resume.
#252
I haven't looked at the code in a while and it was in an incomplete transitory state... so I'm not entirely confident as to the overall status of this. In that respect, I hereby introduce: the Libraries plugin v2 ALPHA 1 (with source).

This relies on hard-linking the script files and it's not feature-complete, but it should get the general idea across. Sorry I didn't get to devote the time to this that I meant to, but I wanted to actually release something.
#253
Drawing the borders should be relatively simple. I've never actually used a the Text Window feature of AGS, but assuming the corner sprites and the border sprites all have the same dimensions then it should be as simple as:

1) Calculate the text width (GetTextWidth), add any padding, and add 2x the width of your border sprites - this yields the area_width.
2) Calculate the text height (based on text width) (GetTextHeight), add any padding and add 2x the height of your border sprites - this yields the area_height.
3) Let max_x equal (area_width - sprite_width); let max_y equal (area_height - sprite_height).
4) Draw the corner sprites ((0, 0); (max_x, 0); (0, max_y); (max_x, max_y)).
5) In a loop from sprite_width to (max_x - sprite_width), incrementing by sprite_width, draw the top and bottom borders ((x, 0) and (x, max_y)).
6) In a loop from sprite_height to (max_y - sprite_height), incrementing by sprite_height, draw the left and right borders ((0, y) and (max_x, y)).

There's no need to use nested loops at all. In fact, it might even prove more useful to simply draw the background once, keep that stored in a separate DynamicSprite, and then draw the text onto a copy of that sprite instead. The copy (with text) would be deleted after you've created the Overlay, so you would only need to clean up the one background sprite when you're finished using it. You could easily handle that when the player leaves the region (and recreate it on-the-fly as needed - e.g., set the pointer to null when you're not using it, create a new one if the pointer is null and you need it).
#254
The best solution I can think of that would definitely work would be to create an overlay yourself.

You can use GetTextWidth and GetTextHeight to determine the actual size you need for your text area, then pad it out for your borders. Then you would call DynamicSprite.Create with the appropriate size. Using that DynamicSprite, call GetDrawingSurface and draw your text area background, the text, and the borders. Then call Release on the surface, Overlay.CreateGraphical using the DynamicSprite's Graphic, and finally call Delete on your DynamicSprite. Of course, this would all best be wrapped up in a nice helper function that would return the resulting Overlay.
#255
Jay, what was it about 3.4 that made it so unusable for you? Did you experience actual errors?

There are definitely breaking changes, but the current version should be pretty stable by now in terms of actual bugs.




In an unrelated note, I've actually added compile errors to the DataFileWriter class (the new game compiler) for the instances where I had inadvertently removed them (too many dialogs, too many inventory items, etc.). I'm reinstalling VS 2008 right now (formatted the computer recently) so that I can rebuild and make sure that I haven't mucked anything up, then I'll put in a pull request for it.
#256
Quote from: ET3D on Tue 10/03/2015 10:18:12monkey, why can't you use the same menu button code as the JJS version?

Because I don't recall ever changing it? :-\ I'll try and look back through the changes I made (which are all available as "my" version is the current master branch), but I don't recall changing this and I certainly wouldn't have intentionally broken it.
#257
What code do you have for clicking on the inventory? Is "Handle inventory clicks in script" enabled in the General Settings?
#258
Sorry, I may have been overthinking certain things on keeping module data in-sync. I will try to take a look at this next week during spring break. ;)
#259
Just as a reminder, I also need to go through the DataFileWriter class and reimplement some error messages if there are too many of certain items that are still limited on the engine side. Unless of course those limits are similarly removed as the others have been.

I have a week off of school, so I will try to take that opportunity to look at this.
#260
The default template for this version wasn't updated to match the API changes. In the meantime, as Snarky said just rename it to Room.ProcessClick. You can also export a template as a replacement for the default template (for now). The templates will of course be updated before a final release is put up (bear in mind this is an alpha, mistakes may be made :P).
SMF spam blocked by CleanTalk