AGS v2.7 Final: Yet Another Edition

Started by Pumaman, Sat 13/11/2004 21:02:00

Previous topic - Next topic

Pumaman

Well basically, I'm happy to add icons to any of the main menu options if people come up with suitable ones.

Pau

Quote from: Snarky on Mon 06/12/2004 22:18:40
Sweet! AGS is becoming quite the powerful programming language...
That make me think if embedding javascript* would bring more or less problems than extending the AGS script with objects and pointers.


I'm not saying that's a better option nor trying anyone how things should be made. I just have curiousity if there are technical, license, or personal  reasons that makes the adoption of a general script language a worse option.

*I've put the example of javascript because it's very similar to the idea of OO that has been explained in this thread and has similar syntax to AGS script (as far as I know because I'm not a javascript expert).
paused -- get the startup menu creator (version 1.1) for AGS games. (Use save target as..)

Pumaman

Generally, using an existing script engine isn't a good idea. Early versions of AGS did so, but in the end I had to write my own.

Some reasons are:
* most script languages are interpreted rather than compiled, which makes them slow
* most languages do not provide a means to save the script state to disk (for a Save Game feature)
* most script languages are not cross-platform
* most script languages are either not powerful enough, or are too confusing, to use as a game script language
* most don't integrate with the game engine in the way that AGS works best

Therefore, using an existing scripting engine is not really viable. However, AGS does attempt to emulate the syntax of C (and therefore also Java, C#, etc) as closely as possible so that people already familiar with these languages can pick it up easily.

Pau

Ok, thanks for your explanation. And thanks for the great effort to move AGS towards OO in order to make our scripting easier.
paused -- get the startup menu creator (version 1.1) for AGS games. (Use save target as..)

Radiant

Two small bugs entirely unrelated to the entire scripting system,

when you do 'show usage' on a sprite, it says 'gui button 54' rather than, say, 'button 3 on gui 18'.
when you do 'export GUIs', I get an error that 'sectionstart interface_click' is not found - even if it actually does exist in my global script.

Pumaman

Quotewhen you do 'show usage' on a sprite, it says 'gui button 54' rather than, say, 'button 3 on gui 18'.

That's not a bug, it's a showcase of my extreme laziness at the time I implemented it ;)

Quotewhen you do 'export GUIs', I get an error that 'sectionstart interface_click' is not found - even if it actually does exist in my global script.

I'll take a look.

Radiant

Also, some very low-numbered sprites are sometimes labeled as used on a certain GUI, when in fact they aren't. This is most obvious for sprite #0... but it seems that sometimes a font number is mistaken for a sprite number, or something. This isn't important, of course.

Something else that is a bit more important - when importing all frames of an animated GIF, sometimes two colors turn transparent (the first is the color of the upper left pixel, which is pure pink, the second is a black color). The effect, needless to say, messes up the transparency. For reference, try multi-frame-importing this image, courtesy of InCreator.


RickJ

#107
StrSetCharAt()
If the char position is larger than the length of the string a runtime error is generated.  Have you considered just appending the char to the end of the string in this case instead of generating a runtime error?   

Compiler and Objects
The compiler doesn't seem to check that the object and function definitions match.      I don't know if you are aware of this or not so I thought I would mention it.

// Script Header
struct IniFile  {
    :
    import function GetInt(string section, string option, int value);
    :
};

// Global Script
function IniFile::GetInt(string section, string option) {
    :
    :
}

*** Edit ***
Corrected format above

Gilbert

#108
Quote from: RickJ on Thu 09/12/2004 00:26:32
StrSetCharAt()
If the char position is larger than the length of the string a runtime error is generated. Have you considered just appending the char to the end of the string in this case instead of generating a runtime error?

I think the better way is the scripter himself to be more aware of it and use StrLen() to check for it if required. If he really needs to append something just use StrCat().
If it's set to append the character, in my opinion it's even harder to spot bugs as it won't generate an error and it may be doing something you don't want to (well maybe it can generate an error to warning.log though), the problem is, when you, say, set a character to the 10th position of a string which is only 5 characters long, what should the behaviour be? Add that character to the 6th position? Or add it to the 10th position and pad the inbetween characters with some other things?

RickJ

StrSetCharAt()
Quote
I think the better way is the scripter himself to be more aware of it and use StrLen() to check for it if required.  ...  If it's set to append the character, in my opinion it's even harder to spot bugs as it won't generate an error and it may be doing something you don't want to (well maybe it can generate an error to warning.log though)
I pretty much agree with this until the game is released and distributed.  After  that point I think it would be better to not have a runtime error that crashes the game in response to this situation, IMHO.

Quote
... the problem is, when you, say, set a character to the 10th position of a string which is only 5 characters long, what should the behaviour be? ...
As you suggest there is not really a correct behaviour but just appending to the very end and making an entry in the warning.log file, as you suggest would probably better than completely bailing out of the game.

Quote
If he really needs to append something just use StrCat().
Except that strings can't be defined as a member of a struct and char[] is the workaround and StrSet/GetCharAt() is the conversion mechanism.

Compiler error message generated without line number
When I incorrectly wrote this (in the proper context  in the global script of course):

len = seclen + 3 + this.length;

instead of this:

len = seclen + 3 + this.length();

the compiler correctly complained about a missing '(' but didn't give a line number.

Pumaman

QuoteAlso, some very low-numbered sprites are sometimes labeled as used on a certain GUI, when in fact they aren't.

Can you provide an example? What does it say that the sprite is, the GUI background image?

QuoteSomething else that is a bit more important - when importing all frames of an animated GIF, sometimes two colors turn transparent

Well spotted yes, if one of the colours in the image has the same RGB as the transparent colour then it will also be made transparent. I'll get it fixed. A workaround for now would be to change the colour of the background.

QuoteIf the char position is larger than the length of the string a runtime error is generated.  Have you considered just appending the char to the end of the string in this case instead of generating a runtime error?   

I'm not sure that this is a good idea, it would seem better to inform the user of their mistake.

QuoteThe compiler doesn't seem to check that the object and function definitions match.      I don't know if you are aware of this or not so I thought I would mention it.

Hmm good point, I'll look into it.

QuoteExcept that strings can't be defined as a member of a struct and char[] is the workaround and StrSet/GetCharAt() is the conversion mechanism.

StrSet/GetCharAt are not intended as a conversion mechanism in any way. You can use StrCopy to copy a string to/from a char[]

Quotethe compiler correctly complained about a missing '(' but didn't give a line number.

Well spotted, I'll get that fixed.

RickJ

#111
StrCopy() nd Objects
Quote
You can use StrCopy to copy a string to/from a char[]
StrCopy generates runtime errors when trying to pass a char[] as a parameter
when the char[] is defined within an object.  A similar and possibly related
situation occurs when attempting to pass char[n] as a parameter to StrCopy(). I  mentioned this problem earlier but mis-communicated by referring to character arrays when I meant to say char[], sory for the confusion.

Exporting/Importing Objects
CJ, did you intend that it be possible to create an instance of an object in the global script and then be able to access it from a room script?

I unsuccessfully tried to do this.  I defined the struct in the script header and placed the functions in the global script file as you instructed.   I created an instance of the object in the global script file.   I was able to access and test everything by placng my object.function() calls in the GUI interface_click() interaction.  Next I tried to export the instance of the object and got a compiler error.

Global Script:
IniFile Config;
export Config;

Script Header:
import Config;

File I/O
Works great!! 

IniFile Module
CJ, here is a link to the user module I created.  It implements the ability to
work with INI configuration files.  I used this try out the OO stuff and thought you may want to have a look.  There is also a comment file I made while working on the module containing some of my thoughts you may find amusing. 

Everyone else is welcome to take a look as well.  I plan on making a general release after an official AGS OO release is announced.   I am happy to take C&C but I think we should start another thread for that.   Well anyway it's an example of how to make your own oobjects.

http://www.gaia-spa.com/project/ags/modules/IniFile001.zip

object vs object
How can we avoid confusion between object-oriented obnjects and room objects when discussing things in the forums or writing about them in docs or tutorials?  Should we consider some kind of convention like oobject  for OO objects and just object for room objects?  Just curious! 

*** Edit ***
$$
I incorrectly typed $$ instead of &&.  The compiler error correctly identified the line number but the error message, "How did we get here?", was amusing.  Just out of curiosoity does $$ have a meaning relative to this message or is that message  just a polite way of saying "You're a bloom'in idiot!!" because that's how it made me feel  :-[

Rui 'Trovatore' Pires

It does not. I got that error after royally screwing up some parenthesis. ;D
Reach for the moon. Even if you miss, you'll land among the stars.

Kneel. Now.

Never throw chicken at a Leprechaun.

Radiant

CJ -> for instance,

Quote
Sprite 2 is used in the following places. It may also be used in text script commands and in rooms (for example, room object graphics); we cannot detect those uses automatically.

View 6, loop 0, frame 0
View 6, loop 0, frame 5
View 10, loop 0, frame 3
View 10, loop 1, frame 4
View 25, loop 1, frame 0
View 25, loop 1, frame 7
Mouse cursor 7 (Wait)
GUI button 15
GUI button 67
GUI button 68
GUI button 69
GUI button 70
GUI button 71
GUI button 72
GUI button 73
GUI button 74

Sprite #2 is an empty sprite (1x1 pixel) and I'm certain I'm not using it on any GUI buttons.
(also, btw, an image that is used as an edge image for a textbox GUI, is falsely named a button image by the usage list)

Pumaman

QuoteStrCopy generates runtime errors when trying to pass a char[] as a parameter
when the char[] is defined within an object.

I tried this:

struct TestStr {
  char thestring[200];
};

function test_str() {
  TestStr tstr;
  StrCopy(tstr.thestring,  "Jibble!");
}

and it worked fine. How do you get a compile error?

QuoteScript Header:
import Config;

It needs to be:
import IniFile Config;

import lines need to include the variable type.

QuoteIniFile Module

Looks good, that's some handy work with the OO functionality :)

QuoteExample: #define NONE -1
            enum  {NONE, eSOME, eMUCHO};

Because #define is a preprocessor thing that replaces all instances of "NONE" with "-1", the error message here was correct. This is one of the problems with using #defines, which is why hopefully enum support can go some way to removing the need for them.

QuoteUsing Display() to display the value of an enum using %d seems to  work fine; the numeric value is displayed.  Using %s causes a fatal error.  It would be pretty slick to use %s to display the value in  text form, especially while in debug mode. 

That would be handy; but because the enum is compiled into numeric values, it's not possible for the runtime to know the enum names. Of course, there's the wider issue of having the ability to include debug information in the script to assist things like this, but that's not something I'm looking into at the moment.

QuoteStrCopy(name[7], filename);           // Doesn't work

That won't work because a string can't be copied into a single character.

QuoteStrCopy(this.filename, filename);     // Doesn't work

This could well be because of the use of "filename" as the variable name in the struct and for the parameter -- try changing the name of the funciton's parameter and see if that fixes it. If so, I'll have to add some sort of compiler check for this.

QuoteIs there any kind of "break" instruction, to break out of a loop, other than using the while's conditional expression?  It would be  convienient to have on ocassion. 

Not currently, no ... the only thing you could do would be a "return" but that breaks out of the whole function.

QuoteHow can we avoid confusion between object-oriented obnjects and room objects when discussing things in the forums or writing about them in docs or tutorials?

Good question, there is ample room for confusion there. We'll have to think about that.

Quote$$
I incorrectly typed $$ instead of &&.  The compiler error correctly identified the line number but the error message, "How did we get here?", was amusing.

Strange, what did your script look like? I just tried this:
if (i $$ 2) { }

but it just gave a standard Parse Error.

QuoteCJ -> for instance,
GUI button 68
GUI button 69

Hmm ok, well the best thing here would be for me to fix it to display the GUI/button number rather than "gui buttn 68" then we'd have a clearer idea where the problem was.

RickJ

Quote
Strange, what did your script look like? I just tried this:
if (i $$ 2) { }
When I did the following I got the unny error message.

while ((i<INIBUFSIZE)$$(status==ININONE)) {

}

Quote
Good question, there is ample room for confusion there. We'll have to think about that.
;)  Probably before you spring this on everyone ,,,

Quote
This could well be because of the use of "filename" as the variable name in the struct and for the parameter -- try changing the name of the funciton's parameter and see if that fixes it. If so, I'll have to add some sort of compiler check for this.
No I still get the type mis-match error.  Here is a code snippet.  I am also going to zip up a copy of the game where this and the above $$ error occur. 
Code: ags

//===================================================================
function IniFile::setfilename(string xname) {
//  	
// Copy the filename from the parameter to the object. The status of 
// the operation is returned as follows:
//
//    INIOK  - successfully completed operation
//    INIERR - N/A 
//===================================================================
   int i, len;
   string filename;

   len = StrLen(filename);
   while ((i < len)&&(i < ININAMSIZE)) {
      this.filename[i] = StrGetCharAt(filename,i);
      i++;
   }
   this.filename[i] = 0;
   i=0;
   StrCopy(this.filename,  xname);
}


Here is a game that contains the above two problems.  Just uncomment  lines 97 and line 249.

http://www.gaia-spa.com/project/ags/modules/IniFileGame.zip


Quote
Re: break -  Not currently, no ...
That's what I thought but after seeing my little IniFile module you probably know why I mentioned it.

Quote
re: StrCopy(name[7], filename);           // Doesn't work
That won't work because ...
I understand.  I was trying to see if I could use StrCopy() to grab part of the buffer.  Damm I'm lazy ;)

Quote
That would be handy; but because the enum is compiled into numeric values, it's not possible for the runtime to know the enum names. Of course, there's the wider issue of having the ability to include debug information in the script to assist things like this, but that's not something I'm looking into at the moment.
If you ever decide to add debug info into the exe then perhaps this would deserve consideration then.  I can see why it's not much of a priority at the moment.

Quote
Because #define is a preprocessor thing ...
Understand.  Perhaps my confusion is worth remembering whenever you get round to explaining enums in the manual.

Quote
Looks good, that's some handy work with the OO functionality
Thanks for the kind comments.  Since the topic came of recently I thought that it would make for a good test of the OO stuff.   Do you think that you might devise an easy way of including or using such things, maybe something like the plugin-manager or just a simple directive in the header like use IniFile?  Maybe it will be part of the borader scoped import/export mechanism you mentioned.  Anyway just some thoughts here....

Quote
It needs to be:
import IniFile Config;
OOooooooooo!  :o      That makes my day!!!

Great work CJ, the OO stuff was easy and fun to work with. 

Pumaman

QuoteWhen I did the following I got the unny error message.

Thanks -- now that I know what causes it, I'll reword the error message to actually make sense ;)

QuoteNo I still get the type mis-match error.  Here is a code snippet.  I am also going to zip up a copy of the game where this and the above $$ error occur. 

Thanks for spotting this, it is a bug in the compiler and I'll get it fixed. I've also double-checked the variable naming thing and it should be fine to call the paramter "string filename", so feel free to change xname back to filename.

QuoteUnderstand.  Perhaps my confusion is worth remembering whenever you get round to explaining enums in the manual.

Well that's just it, it's not specific to enums. Using defines can cause this sort of strange error message to occur anywhere, wherever you use a define in the wrong way you'll get an error message that's not entirely obvious because of the macro expansion. Ideally I'd like to add const ints and scrap defines altogether because of this sort of problem.

QuoteThanks for the kind comments.  Since the topic came of recently I thought that it would make for a good test of the OO stuff.   Do you think that you might devise an easy way of including or using such things, maybe something like the plugin-manager or just a simple directive in the header like use IniFile?

Please understand that my first priority is to get all the built-in AGS functions working in an OO-fashion (specifically, all the GUI stuff). Once that's done I'll concentrate further on the user scripting side of things.

RickJ

Quote
Well that's just it, it's not specific to enums.  ...
Hehehe ... I'm too embarrassed to tell the silly things I have done to myself... but  #define is too useful to abandon.     

Quote
Please understand that my first priority is to get all the built-in AGS functions working in an OO-fashion (specifically, all the GUI stuff).   Once that's done I'll concentrate further on the user scripting side of things.
I understand completely :).  I think you do a really good job of listenig to ideas and setting priorities accordingly.  The cool thing about the AGS community is that you take inspiration from our ideas and then implement cool stuff  8).  That in turn inspires us to have more ideas which in turn inspires you to implement more cool stuff.   It's a real pleasure for me to participate in the process.   Thanks CJ.

Pumaman

Ok, beta 6 is now up.

Room objects now have script names, so that you can do:
oDoor.Animate( ... );
and so on, which is much more user friendly than the previous number-based approach. It also means that if you delete an object (and thus they get re-numbered), your script is unaffected.

The main thrust of this release is the new GUI stuff.
All GUI controls now have a "Script name" property, which allows you to give them a VB-style "lstSaveGames" or "btnCancel" type name.
Then, in the script you can do stuff like:
lstSaveGames.AddItem("Jibble");
rather than
ListBoxAdd(3, 6, "Jibble");
all much nicer the new way.

Also, GUI controls like the button and slider now have an event property at the bottom of the list, which allows you to assign a special event function to process clicks on that control. Again, this is like the way VB does it, so rather than forcing everything through interface_click you can have a seperate function to handle each different control. For buttons, you can also find out whether the left or right mouse button was clicked.

If you assign an event function then it will be called instead of interface_click; if you don't then interface_click will be called as usual.

Have a play and let me know of any issues.

Rui 'Trovatore' Pires

Chris, this new version is beautiful, just beautiful, but... yeah, there's a but...

You added the ability to change the listboxes' highlight color! That's great!

...but I wanted to set it to transparent. Which I can't. 0 should make it transparent, it makes everything ELSE transparent, but HERE just makes 'em black...
Reach for the moon. Even if you miss, you'll land among the stars.

Kneel. Now.

Never throw chicken at a Leprechaun.

SMF spam blocked by CleanTalk