Show Posts

You can view here all posts made by this member. Note that you can only see posts made in areas to which you currently have access.

Topics - eri0o

Pages: [1] 2 3

I would like to suggest moving the default ags manual to a online help, and f1 just running a search on this online help in the user own browser. Most softwares uses online manuals these days.

We are hitting some hard issues to support using the current .chm help with easier to edit and maintain help. The new help gives per topic markdown files that can be edited online instead of the old 22k lines of LaTeX text file and a ton of magic.

Here is how is the online manual now:

And here is the repository for it:

Engine Development / Running an AGS game on Steam OS
« on: 19 Aug 2018, 03:26 »
So, I was trying to run my AGS game on Steam OS and for some reason it kept failing on missing . Now, for the 64-bit version, I use the sdl2 port and use the regular on 32-bit. No matter what I did, the ALLEGRO_MODULES variable wasn't recognised on SteamOS, for the , so I solved by passing the LD_LIBRARY_PATH - since lib32 / lib64 include the . I also place the ags binary inside the lib32 / lib64 directories.

Below is what I got that worked consistently across my Linux PCs, through Steam. I pass the full screen modifier because it's needed now in the sdl2 port for some reason.

Code: Adventure Game Studio
  1. #!/bin/sh
  2. SCRIPTPATH="$(dirname "$(readlink -f $0)")"
  4. if test "x$@" = "x-h" -o "x$@" = "x--help"
  5.   then
  6.     echo "Usage:" "$(basename "$(readlink -f $0)")" "[<ags options>]"
  7.     echo ""
  8. fi
  10. if test $(uname -m) = x86_64
  11.   then
  13.     ALLEGRO_MODULES="$SCRIPTPATH/lib64" "$SCRIPTPATH/lib64/ags_sdl2_64" --fullscreen "$@" "$SCRIPTPATH/"
  14.   else
  16.     ALLEGRO_MODULES="$SCRIPTPATH/lib32" "$SCRIPTPATH/lib64/ags32" "$@" "$SCRIPTPATH/"
  17. fi

I am not very smart and have some trouble understanding documentation. I am trying to release a game on one of those gaming stores.

- should the game installer also install DirectX? This specific store has a redistributable option where I can just select it. It didn't seem to hurt.

- which folder should contain the savegames on Win/Linux/MacOS ? I need to watch them so they can be synced accross computers.

Recruitment / [AGS HELP WANTED] Look for volunteers for alternative AGS Help
« on: 19 Jul 2018, 03:17 »
The AGS Help - a candidate for leading the future in the online help and the Manual!

I and Morganw have been working a possible candidate for the future of AGS Help.
The still in evaluation help project is hosted in this Github repository.
Discussion on the text and new texts and alterations is done using the repository issues.
The editing of the texts is done through the project wiki. The reading of the texts can be both throught the wiki and the webpage.

Positions Available:
Right now we need a person with AGS experience to do good writing on the visual Editors (Room, Characters, Inventory...) and possibly tutorials. Also someone that can do a reading and find texts that are not correct for current stable version of AGS (

You can only work on a page of the manual. If you are interested, you can discuss and write your text directly in the Github Issue page!
Once a task is claimed, I will mark it here with an "x" on the corresponding item.

If you have interest in writing on a different topic, create an issue on the Github issue tracker detailing your interest!

I'm looking to have this written until mid August. I want the project to be considered either mature enough to be moved to the Github AGS organisation or a complete and utter failure so I can test a different solution.
I believe that content generate won't be lost, even though code on the help itself can end being thrown away.

Interested parties can reply to this thread or contact me via PM.

UPDATE (29th July):
Hey, the repository moved to the AGS organization on github and the wiki is opened for editing . I've updated the important links on the previous message.

was anyone ever able to recreate leaves animating in low resolution games (320x240 // 320x180) through code in success?

I am looking for an effect similar to the one in Owlboy.

Add spoiler tag for Hidden:

I looked over the Underwater module, because it's the most similar I could remember, but I don't understand yet how to modify until a flailing effect can be made.

Add spoiler tag for Hidden:
Code: Adventure Game Studio
  1. // new module script
  2. #define MAX_FRAMES 10
  4. #define MAX_BLOCKS 128
  7. int block_w;
  8. int block_h;
  9. int block_x[MAX_BLOCKS];
  10. int block_y[MAX_BLOCKS];
  12. bool Leaves_enabled = false;
  13. int original_graphic;
  15. float tt = 0.0;
  16. float t = 0.0;
  17. float a[MAX_FRAMES], b[MAX_FRAMES], c[MAX_FRAMES];
  19. DynamicSprite * dyn_spr;
  21. static void LeavesAnimation::SetBaseGaphic(int leavesGraphic){
  22.   if(dyn_spr!=null){
  23.     dyn_spr.Delete();  
  24.   }
  25.   original_graphic = leavesGraphic;
  26.   dyn_spr = DynamicSprite.CreateFromExistingSprite(original_graphic, true);
  27. }
  29. static int LeavesAnimation::GetGaphic(){
  30.   if(dyn_spr!=null){
  31.     return dyn_spr.Graphic;  
  32.   }
  33.   return 0;
  34. }
  36. static void LeavesAnimation::Enable() {
  37.   float scalar = 8000.0;
  38.   int i = 0;
  40.   int delta1 = Random(MAX_FRAMES-1);
  41.   int delta2 = Random(MAX_FRAMES-1);
  42.   int delta3 = Random(MAX_FRAMES-1);
  44.   while (i < MAX_FRAMES) {
  45.     a[i] = Maths.Cos(Maths.Pi*IntToFloat((delta1+i)%MAX_FRAMES)/IntToFloat(MAX_FRAMES));  //IntToFloat( Random(2000)*(Random(1)-1) )/scalar;
  46.     b[i] = Maths.Sin(Maths.Pi*IntToFloat((delta2+i)%MAX_FRAMES)/IntToFloat(MAX_FRAMES));  //IntToFloat( Random(2000)*(Random(1)-1) )/scalar;
  47.     c[i] = Maths.Cos(Maths.Pi*IntToFloat((delta3+i)%MAX_FRAMES)/IntToFloat(MAX_FRAMES));  //IntToFloat( Random(2000)*(Random(1)-1) )/scalar;
  48.     i++;
  49.   }
  51.   block_w = Game.SpriteWidth[original_graphic]/48;
  52.   block_h = Game.SpriteHeight[original_graphic]/24;
  54.   i = 0;
  55.   while (i < MAX_BLOCKS) {
  56.     block_x[i] = Random(Game.SpriteWidth[original_graphic]- 1 - block_w);
  57.     block_y[i] = Random(Game.SpriteHeight[original_graphic] - 1 - block_h);
  58.     i++;
  59.   }
  60.   Leaves_enabled = true;
  61. }
  63. static void LeavesAnimation::Disable() {
  64.   Leaves_enabled = false;
  65. }
  67. float get_gradient_x(int xi, int yi) {
  68.   float x = IntToFloat(xi)/160.0 - 1.0;
  69.   float y = IntToFloat(yi)/160.0 - 1.0;
  71.   float dx = 0.0;
  73.   int i = 0;
  74.   while (i < MAX_FRAMES) {
  75.     dx += a[i]*t*Maths.Cos(a[i]*t*x + b[i]*t*y + c[i]);
  76.     i++;
  77.   }
  78.   return dx;
  79. }
  81. float get_gradient_y(int xi, int yi) {
  82.   float x = IntToFloat(xi)/160.0 - 1.0;
  83.   float y = IntToFloat(yi)/160.0 - 1.0;
  85.   float dy = 0.0;
  87.   int i = 0;
  88.   while (i < MAX_FRAMES) {
  89.     dy += b[i]*t*Maths.Cos(a[i]*t*x + b[i]*t*y + c[i]);
  90.     i++;
  91.   }
  92.   return dy;
  93. }
  95. function offset_a_block(DrawingSurface *surf, int x, int y, int w, int h) {
  96.   int xoff = FloatToInt(1.0*get_gradient_x(x + w/2, y + w/2));
  97.   int yoff = FloatToInt(1.0*get_gradient_y(x + h/2, y + h/2));
  99.   xoff = Utils.clampInt(xoff, 1, -1);
  100.   yoff = Utils.clampInt(yoff, 1, 0);
  102.   //w = Utils.clampInt(w, Game.SpriteWidth[original_graphic]-x, 1);
  103.   //w = Utils.clampInt(w, Game.SpriteHeight[original_graphic]-y, 1);
  105.   DynamicSprite *ds = DynamicSprite.CreateFromDrawingSurface(surf, x, y, w, h);
  106.   //surf.DrawingColor = COLOR_TRANSPARENT;
  107.   //surf.DrawRectangle(x, y, x+w, y+w);
  108.   surf.DrawImage(x - xoff, y - yoff, ds.Graphic);
  109. }
  111. function repeatedly_execute_always() {
  112.   if (Leaves_enabled) {
  113.     if(dyn_spr==null){
  114.       return;
  115.     }
  117.    if(getCurrentFrame()%4!=0){
  118.       return;  
  119.     }
  121.     tt = tt + 0.01;
  122.     float k = Utils.clampFloat((2.0*Maths.Pi*Maths.Sin(tt)), 8.0, 0.0) ; ///8.0;
  124.     t=1.0;
  126.     if(dyn_spr!=null){
  127.       dyn_spr.Delete();  
  128.     }
  129.     dyn_spr = DynamicSprite.CreateFromExistingSprite(original_graphic, true);
  131.     //SetBackgroundFrame(0);
  132.     // repeatedly grab a random chunk from bg 1 and paste it to bg 0, slightly offset
  133.     DrawingSurface *surf = dyn_spr.GetDrawingSurface();  //Room.GetDrawingSurfaceForBackground(0);
  135.     int i = 0;
  136.     while (i < MAX_BLOCKS) {
  137.       if(Random(FloatToInt(k))==0){
  138.         block_x[i] = Random(Game.SpriteWidth[original_graphic]- 1 - block_w);
  139.         block_y[i] = Random(Game.SpriteHeight[original_graphic] - 1 - block_h);
  140.       }
  141.       //int x = Random(Game.SpriteWidth[original_graphic]- 1 - block_w);
  142.       //int y = Random(Game.SpriteHeight[original_graphic] - 1 - block_h);
  143.       offset_a_block(surf, block_x[i], block_y[i], block_w, block_h);
  144.       i++;
  145.     }
  147.     surf.Release();
  148.   }
  149. }
  152.     // draw some more around the player
  153.     // ViewFrame *frame = Game.GetViewFrame(player.View, player.Loop, player.Frame);
  154.     // int graphic = frame.Graphic;
  155.     // int height = FloatToInt(IntToFloat(Game.SpriteHeight[graphic]*player.Scaling)/100.0);
  156.     // int width  = FloatToInt(IntToFloat( Game.SpriteWidth[graphic]*player.Scaling)/100.0);
  157.     // int left = player.x - width/2;
  158.     // int top = player.y - height - player.z;
  160.     // i = 0;
  161.     // while (i < 32) {
  162.     //   i++;
  163.     //   int w = Room.Width/64;
  164.     //   int x = left - w/2 + Random(width - 1);
  165.     //   int y = top - w/2 + Random(height - 1);
  166.     //   if (x < 0) x = 0;
  167.     //   else if (x >= Room.Width - w) x = Room.Width - 1 - w;
  169.     //   if (y < 0) y = 0;
  170.     //   else if (y >= Room.Height - w) y = Room.Height - 1 - w;  
  172.     //   offset_a_block(surf, x, y, w);
  173.     // }

Code: Adventure Game Studio
  1. // new module header
  3. struct LeavesAnimation {
  5. import static void Enable();
  6. import static void Disable();
  7. import static void SetBaseGaphic(int leavesGraphic);
  8. import static int GetGaphic();
  10. };

Here is a different gif idea (but I still can't understand how to implement leaf animation on the bg...)
Add spoiler tag for Hidden:

Very weird question: sometimes I have to just sketch some weird math logic, and I build my game a thousand times just to read the result on a display function. Does an ags script interpreter for only the non graphical functions (maths and String I think) exists? A headless ags of sorts... Maybe AGS Script is based on something of same syntax...

Beginners' Technical Questions / A random game player
« on: 09 Jun 2018, 06:17 »
I was procrastinating researching the web and found the below post from Grumpy Gamer (misleading title). If you don't want to read it, go for the video.

I liked the idea of something randomly playing a game until it crashes and logging the crash. Has someone here ever devised such a tool for an AGS game? (I was'n sure where to place this question...)

Does a Mouse.Click should trigger a on_mouse_click event? If they are in different modules, does order matter? Does Mouse.Click holds button down (for Mouse.isButtonDown) for a single tick?

I need to tint a character portrait - single frame speech view, and no limp sync and no blinking.

I have thought about, but I am not sure how to do it. :(


I think since AGS 3.4.1 you can set the line spacing in fonts, over properties, inside AGS. It's awesome!

I just found a little bug, when editing a GUI in the editor (multiline label using [ character), the font LineSpacing is not considered for rendering the GUI in the Editor - but will be considered when the game runs in engine!

Just reporting for now.

Disclaimer: this an article that I sketched long ago, but didn't knew if it was good enough, so I am throwing here to see if ideas can come up to make it better because I want to address this general idea in my blog.

I noticed recently that during the week I am more keen on games that have story depth, but I can get tired if a game is too demanding skill wise. On weekends, I am usually well rested, and like to be challenged.

Once I saw a tweet by @gritfish that said:

"I honestly believe we need to  change the way games do difficulty / game modes to something like:

I'm here for the story
I'm here for challenge
I'm here for a second & harder playthrough
I'm here to take photos
I want to play with the settings and I'm okay if that breaks things

Well, I like this idea. But I am also slightly lazy, I am not coding different game modes.

I've read Designing Virtual Worlds, from Richard Bartle, and he talks about the 4 types of players he discovered while analyzing MUD: Achievers, who like to achieve defined goals; Socializers, who gets greatest rewards interacting with other people; Explorers, who likes to learn more about the virtual world; Killers, who like to dominate others. He goes on to explain how to create a virtual world that attracts each subset of players.

Players of Magic The Gathering may be familiar with this idea, it's R&D and Mark Rosewater divide players in three categories: Timmy, a social person who wants to have fun winning big (the RTS equivalent would be having a big base before unleashing a final gigantic attack); Johnny, who wants to express himself through the game; and Spike, who plays for the winning and competition. Recently they also started considering hybrids of these players.

On with adventure games. They are mostly known by stories, puzzles, the exploring and the pace on the control of the player. Psychographics can be defined as a quantitative methodology used to describe consumers on psychological attributes. Psychographics has been applied to the study of personality, values, opinions, attitudes, interests, and lifestyles.

I would like to propose here psychographics for Point and Click Adventure Games:

 - Stella, who plays for the Story;
 - Paula, who plays for the Puzzles;
 - Ezra, who plays to Explore;

So each time I create a room in a game, I try to look if I am leaving each of these players, something to play with, and also, I usually choose one of them to focus more on each room.


I need to get the current graphic from the player, I need to do this every instant, I am using this information to draw things on a surface, so at instant t=7 I need the player frame for instant t=7, and not t=6.

I decided to use the following:

Code: Adventure Game Studio
  1. int getPlayerGraphic(){
  2.   ViewFrame * ViewFrame_Player;
  3.   ViewFrame_Player = Game.GetViewFrame(player.View,  player.Loop, player.Frame);
  4.   return  ViewFrame_Player.Graphic;
  5. }

but apparently, this gets in the current instant, the graphic that was on screen on the previous instant, so using this information gets a slightly delay.

So I evolved to do the following thing:

Code: Adventure Game Studio
  1. int i_view;
  2. int i_loop;
  3. ViewFrame * ViewFrame_Player;
  5. function repeatedly_execute_always(){
  6.   i_view = player.View;
  7.   i_loop = player.Loop;
  8. }
  10. function late_repeatedly_execute_always(){
  11.   if(IsGamePaused() == 1  || !System.HasInputFocus){
  12.     return;  
  13.   }
  15.   ViewFrame_Player = Game.GetViewFrame(i_view,  i_loop, player.Frame);
  16. }
  18. static int PlayerViewframe::getGraphic(){
  19.   return  ViewFrame_Player.Graphic;
  20. }

which sometimes works, but in some rare occasions, crashes my software, because player.Frame sometimes is updated and i_view and i_loop isn't, and my loop for down and up have different frame count than left and right. And sometimes, it doesn't update correctly.

So is there a right way of getting the current graphic the player has ?

Engine Development / Let's build for Android!
« on: 08 Jan 2018, 00:35 »
I will try to explain what I did here, questions will arise, hopefully everything can be answered here and this will allow me to generate a guide.

So first two things are important:
 - Android port of the engine currently doesn't report correctly mouse.isButtonDown, so your game CAN'T BE USING THIS, use if(System.OperatingSystem == eOSAndroid) in your code to work for this.
 - I am using the latest prebuilt APK as libs, those were for the previous stable version, so your game must be built with that AGS.

1. You need to install the latest Android Studio, just download and install. .

2. You will also need JDK, NDK and Android SDK.

3. After installing Android Studio, download the repository I made here: . This is my modded version of Monkey's Android Studio Project.

4. Open the folder in Android Studio.

5. Building should generate my game .apk!

6. Ok, let's make YOUR game .apk. In the folder Android Studio placed the Sdk, there is a magical tool called jobb. I use Ubuntu, and the tool is in the folder ~/Android/Sdk/tools/bin/ in my computer. If you use Windows, then it's probably in %appdata%\Local\Android\Sdk . (if someone can confirm this information, it would be awesome!). This is just so you can understand what will happen next.

7. In your game Compiled folder, there is a YOURGAMENAME.ags file. Open a cmd.exe (windows) or bash terminal (Linux/OSX). Change Directory to the folder YOURGAMENAME.ags is.

In Windows (untested!)
Code: Adventure Game Studio
  1. cd YOURGAMENAME\Compiled\
  2. mkdir obb
  3. move YOURGAMENAME.ags obb\
  4. %appdata%\Local\Android\Sdk\tools\bin\jobb -d \obb\ -o -pn com.YOURSTUDIONAME.YOURGAMENAME -pv 3
In Linux/OSX
Code: Adventure Game Studio
  1. cd YOURGAMENAME/Compiled/
  2. mkdir obb
  3. mv YOURGAMENAME.ags obb/
  4. ~/Android/Sdk/tools/bin/jobb -d ./obb/ -o -pn com.YOURSTUDIONAME.YOURGAMENAME -pv 3

In the code above, 3 is simply the OBB version number. Every time you change the content of the OBB linked to your APK and release, you have to increase that number - and update in your Android Studio Project accordingly. Also make sure that YOURGAMENAME and YOURSTUDIONAME are correctly updated in your android studio project.

8. In the README there is a line called Setting up the project for your game. I will copy below:

-Update package name:

Open the project in Android Studio, then in the project tree navigate to app/java/com.mythsuntold.osd.scourge.
Right-click on this folder and select "Refactor -> Move...". When prompted, select "Move package 'com.mythsuntold.dungeonhands' to another package" (the default). You may receive a warning that multiple directories will be moved, select Yes. Type the parent name of your package, not the final package name (e.g., com.bigbluecup not, select "Refactor" and then click "Do Refactor".
Right-click on the new project folder in the project tree (e.g., com.bigbluecup.scourge) and select "Refactor -> Rename". Type the package name for your game (e.g., game), then select "Refactor" and click "Do Refactor".

Finally, delete the com.mythsuntold.dungeonhands folder.

- Update This file contains gradle settings related to your project. The application ID, version code, and version name need to be set to match your project settings (application ID is your package name).

- Update project.xml. This file contains resources for your project. The values there are described in that file.

- Update This file contains local data that should NOT be added to version control (.gitignore will ignore your changes to this file). You need to add your keystore path, alias, and passwords, and optionally the path to your copy of the AGS source (if you are rebuilding the engine native libraries). See the Java docs on keytool or use the Android Studio signing wizard to generate a keystore.

- Update private.xml. This file contains definitions for your RSA public key and an integer-array with bytes for your salt which is used by the ExpansionDownloaderService. These values are necessary if distributing your app via the Google Play Store. The RSA public key is provided in the Google Play Developer Console, and the salt bytes may be any number of values in the range [-128, 127]. You may need to upload an APK without the RSA public key first before the key is provided. That APK should not be public unless the OBB file is embedded.

- Update graphics resources (app/src/main/res). You can use the Android Asset Studio to easily generate graphics for your app, or use your preferred method. Everything in the drawable and various mipmap-* folders should be replaced with your resources.

I made this post with the intent to help Mehrdad, so please try this!

Adventure Related Talk & Chat / Pixel Font Resource
« on: 03 Jan 2018, 21:30 »
Just linking a website that has been very useful to me:

Site & Forum Reports / Is teamcity still online?
« on: 30 Dec 2017, 15:07 »
There are some links that goes to Teamcity bigbluecup, it looks like it is/was a pipeline part to build binaries. Is this still online? Are the scripts for build there public in any place?


I am making the opening scene of my game and I have a question. Playtesting showed that players prefer dialogs to be click to advance only instead of click + timer. In the opening scene though, I feel it would be better if the dialog used click to advance plus timer, because each looping state feel better under a time constraint.

Would keep my game click to advance and the opening click to advance + timer be a good or a bad idea?

I noticed the music position in ms is not updated every frame. Is this intentional?

I came up with the following code to fix this, where actualACMusMs has the true music position:

Code: Adventure Game Studio
  1. AudioChannel *acMusic;
  3. //fix to report correct music position, game in 60fps
  4. int frame;
  5. int acMusPreviousMs;
  6. bool startedRepeat;
  7. int frameWhenRepeatingStarted;
  8. int actualACMusMs;
  10. void playMusic(AudioClip * musicClip){
  11.   acMusic = musicClip.Play(eAudioPriorityHigh, eRepeat);
  12. }
  15. void repeatedly_execute_always(){
  16.   if(IsGamePaused()==1 || acMusic==null){
  17.     return;  
  18.   }
  20.   frame++;
  22.   if(acMusic.PositionMs==acMusPreviousMs){
  23.     if(!startedRepeat){
  24.       frameWhenRepeatingStarted=frame-1;
  25.     }
  26.     startedRepeat=true;
  27.     actualACMusMs = acMusPreviousMs+(frame-frameWhenRepeatingStarted)*16;
  28.   } else {
  29.     startedRepeat=false;
  30.     actualACMusMs= acMusic.PositionMs;
  31.   }
  33.   acMusPreviousMs = acMusic.PositionMs;
  34. }

I did this because I am experimenting with some music in my game that is active, like, I switch music depending on changes on the environment, and needed to correctly position the music when switching.

Also, imagine a graph:

(music 1)--->>(music 2)<< loop music 2 forever

How would you detect music 1 has ended and you need to proceed to music 2? Also if I have crossfade activated, how should I force crossfade to not happen then?

Advanced Technical Forum / Prevent alt+tab audio glitch
« on: 10 Dec 2017, 20:40 »
Hey! When I alt+tab an AGS game, the audio likely rolls a dice, and on a odd number, it glitches, producing looping sound that sounds like the previous 200ms of sound. Is there a way to prevent this? If I could detect from in game the loss of focus, I could try to lower the volume.

Hey, I have a code as below, my character cChara is correctly shown in screen. But SOMETIMES, I get an error on the line that has Game.GetViewFrame, stating Error: GetGameParameter: invalid frame specified.

Code: Adventure Game Studio
  1. ViewFrame * tvf;
  3. ...
  4. function late_repeatedly_execute_always(){
  5.   ...
  6.   tvf = Game.GetViewFrame(cChara.View, cChara.Loop, cChara.Frame);
  7.   ...
  8. }

The only thing I gathered is it happens when the character is walking to some direction and I click to force him walk down, and my walking down (and up) animation has one less frame then the walking right and left.

Advanced Technical Forum / Using Normal Maps (demo)
« on: 09 Dec 2017, 22:38 »
Ok, so today I lost some hours of my life coding NormalMap with AGS Script.

In case you want it, Download the Demo here!.

I don't think it looks good, I decided to ditch this idea, but maybe someone wants to try and test this.

I based my code on the code here.

If someone does make it better, faster, please share your enhancemets here!

Pages: [1] 2 3