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 - EnterTheStory (aka tolworthy)

#61
I don't know if this topic belongs here, but I often search for help on topics like this, so maybe this thread will be helpful to others.

There have been several threads over the years about sound breaking up when changing large rooms on slow computers, and there was no general purpose solution (other than "don't use such large rooms"). So I wrote a workaround. It also works as a way to have almost unlimited custom room transitions (discussed at the very end).

I haven't made this into a module because it's really just a set of suggestions, and would benefit from being developed by a better coder than me (any expert module writers reading? I'm looking at you, SSH :)

The problem:
When loading large and complex rooms (e.g. more than, say, 2 Mb) on an old computer or cheap laptop, sometimes the room is not loaded before the music buffer or cache runs out, so the music struggles and users complain. I'm getting this more often with AGS3 than with 2.72, or perhaps I just never noticed before. It's my own fault for designing crazy rooms and having a cheap computer :)

The solution:
AGS compresses room background images, so a very large room will load very quickly if it uses just a few plain colors. Example: a 3000x480 room using a photographic background will result in a room size of over 2Mb, but the same photo when reduced to 4 colors (and still saved at 24 bit) is not much more than 400k. So load rooms with simplified graphics then add the full background in stages. Result: AGS can handle everything in small stages and the music runs smoothly, even on your old laptop. Hide the change behind a GUI with a copy of the previous background.

notes
You can go as wide as 10,000x480 before the simplified background grows over 1Mb (when the slowest computers start to stutter). All my standard rooms are 480 pixels high, and the code reflects that, but obviously you can adapt the code for any size.

All this might sound like extra work, and it is, but everything is automated except making the low color version of your original background and one stop to manually importing all sliced images as sprites, then taking a note of the resulting sprite numbers (maybe these steps can be automated too - can sprites be imported through code?). That takes about a minute per room and only need to be done once per room.

Preparation:
When making a background, make an extra copy with just four colors. Use this 4 color version in the editor, so you can see where to put floors, hotspots, etc. Then split the original copy into 640 pixel wide segments. AGS handles 640x480 images with ease on even the slowest machine. I wrote the following code for splitting images, but I'm sure that others can write something better.
Code: ags

DynamicSprite* spriteFromBmp;
function makeImageSlice(String imagename, int part)// part = 0,1,2,etc.
{ //------------------------ get bmp --------------------------------------
  String nameWithBmp =imagename;// for convenience I always give my source image the same name: "tosplit.bmp"
  if(nameWithBmp.IndexOf(".bmp")<0)nameWithBmp =nameWithBmp.Append(".bmp");// in case they forgot to add ".bmp"
  spriteFromBmp = DynamicSprite.CreateFromFile(nameWithBmp);// read it in
  if (spriteFromBmp == null){ Display("Sorry can't find '%s'",nameWithBmp);return 0;}
  if(spriteFromBmp.Height !=480){ Display("'%s' is only %d high",nameWithBmp, spriteFromBmp.Height);return 1;} 
  //------------------------ crop it --------------------------------------
  int x =part * 640;             // e.g. start at x=0,640,1280,etc.
  if(spriteFromBmp.Width <x) return 2; //already got to the end of the image?
  int width =640;
  if(spriteFromBmp.Width <(x +width)) width =spriteFromBmp.Width -x; //need to grab less than 640 pixels?
  spriteFromBmp.Crop(x,0,width,480);
  //------------------------ rename and save ------------------------------
  int nameLength =imagename.IndexOf(".bmp"); // make sure you have the name without the extension
  if(nameLength >0)imagename =imagename.Substring(0, nameLength);//e.g. 0123.bmp has length 4
  String suffix =String.Format("_%d",part); // e.g. "_0", "_1", etc.
  imagename = imagename.Append(suffix);
  nameWithBmp =imagename.Append(".bmp");// e.g. "tosplit_0.bmp" etc.
  spriteFromBmp.SaveToFile(nameWithBmp); return 3; // success
}
function trySplitting(String imagename) // call this from any convenient button or hotkey
{ int part =0; int result =3;
  while((part <=8)&&(result ==3))
  { if(result ==3)result =makeImageSlice(imagename,part);part++; }
  part--;// compensate for final not-followed loop
  Display("Split '%s' into %d parts",imagename, part);// you should now have a series of slices in your compiled folder
  spriteFromBmp.Delete();// release the memory
}

Make a sprite folder called 'wide rooms' and a sub folder with the room number, import those sliced images as sprites, and make a note of their numbers.

When leaving a room:
You'll need to create your own 'player change room' function, e.g. 'changeRoom2(where,x,y)' and always use it instead of player.changeRoom.  Having your own change room code is probably a good idea anyway, as it lets you check for things like queued room changes (which could crash 2.72, don't know about 3.x), or for rooms that are not accessible early in the game, or costumes that need to change between rooms, etc.  Just before you change to a large room, call the following code.
Code: ags

DynamicSprite* roomFreeze; export roomFreeze; // a copy of the background to hide the change
function hideRoomChange()
{ roomFreeze = DynamicSprite.CreateFromScreenShot();
  gRoomChanger.BackgroundGraphic =roomFreeze.Graphic; // you'll need to create this GUI
  gRoomChanger.Transparency =0;// one of the many good things about AGS3 is transparent GUIs
  gRoomChanger.Visible =true;
}

To avoid confusion, I use it on every room just in case. Set the default room change to instant, as nobody will see it anyway, hidden behind the GUI.

when entering a new room
I don't think on_event handles "after fade in," so you'll need to refer to this code on every room:
Code: ags

function drawBackground(int slot1,int slot2,int slot3,int slot4,int slot5,int slot6,int slot7,int slot8)
{ DrawingSurface *surface = Room.GetDrawingSurfaceForBackground();
  if(slot1 >0){Wait(1);surface.DrawImage(0,0,slot1);Wait(1);} //'wait' to avoid stuttering on the slowest machines
  if(slot2 >0){surface.DrawImage(640,0,slot2);Wait(1);}
  if(slot3 >0){surface.DrawImage(1280,0,slot3);Wait(1);}
  if(slot4 >0){surface.DrawImage(1920,0,slot4);Wait(1);}
// etc., etc.
  surface.Release();//finished drawing, tells AGS it can use the changed image
}
function checkBackground() //safe to use for EVERY room, as only wide rooms trigger any response
{ if(player.Room ==3)drawBackground(56, 57, 58, 59, 60, 0, 0, 0);// the sprite numbers you noted earlier: your will be different of course
}
function fadeInRoom()
{ checkBackground();
  if(!gRoomChanger.Visible)return; // you didn't use the new code? shame on you!
  int trans =0;  while(trans <100) // I like my rooms to fade in
  { trans = trans +4;if(trans >100)trans =100;
    gRoomChanger.Transparency =trans; Wait(1);
  }gRoomChanger.Visible =false;
  if(roomFreeze !=null)roomFreeze.Delete();// releases the memory it was keeping (e.g. the big temporary image)
}


How to add your own custom transitions
Another advantage of this code, apart from making transitions easy, is you can add your own custom transitions. When you get to the new room just replace 'gRoomChanger' with a character having a full screen animated view of your choice.

By messing with surfaces and dynamic sprites you can add special features and transparency to this image: automatically create frames to change rooms by turning a page, breaking a window, exploding a nuclear bomb, the wind blowing sand over the screen, or whatever. Remember to use y and z values to ensure your transition character is in front of everything else.

Animating the image itself.
If you want to be really creative, don't use a full screen image at all, split it up into many different strips or squares, using 'CreateFromDrawingSurface.' Or make them irregular shapes by pasting on the transparent color. Then your room transitions can involve the previous room blowing up, dripping Matrix-like, roll up like a roller blind, or whatever. That last idea would be relatively simple as it only needs a few horizontal strips. Or use some more subtle transition that fits your game.

pseudo-3D transitions
If you break the screen into enough parts, and resize, flip, and rotate in the right way, you could have a crude 3D effect. Tint the segments to give a shadow effect. it wouldn't be perfect, but most room transitions take less than a second so the suer wouldn't have time to notice the rough edges.

interactive transitions
Why not make the screen segments react to the position of the mouse? The user push or slice or hack into the new room: parts of the screen could warp, explode or fall away depending on the mouse position. Anything is possible.

Just an idea. I've only tested the non-stutter code, the rest is just thinking aloud.
#62
Quote from: Dualnames on Sat 27/03/2010 12:03:16can you see the statistics of your game/s and print screen and show them for us? I'm pretty curious.
No problem!

Les Miserables:
---------------------------
Total sprites:   4713 / 30000
Sprite folders:   55
Total views:   469
Total GUIs:   26
Inventory Items:   2 / 300
Characters:   300
Dialog topics:   1 / 500
---------------------------
The Divine Comedy:
---------------------------
Total sprites:   4212 / 30000
Sprite folders:   181
Total views:   470
Total GUIs:   28
Inventory Items:   2 / 300
Characters:   300
Dialog topics:   1 / 500
---------------------------
Genesis of The Gods:
---------------------------
Total sprites:   3103 / 30000
Sprite folders:   171
Total views:   470
Total GUIs:   32
Inventory Items:   2 / 300
Characters:   300
Dialog topics:   1 / 500
---------------------------
A Tale of Two Cities (not finished)
---------------------------
Total sprites:   2432 / 30000
Sprite folders:   136
Total views:   470
Total GUIs:   30
Inventory Items:   2 / 300
Characters:   178
Dialog topics:   1 / 500
---------------------------
and of course the bookshelf front end:
---------------------------
Total sprites:   91 / 30000
Sprite folders:   12
Total views:   20
Total GUIs:   8
Inventory Items:   2 / 300
Characters:   103
Dialog topics:   1 / 500
---------------------------
Combined total for the game world so far (if my adding is right):
---------------------------
Total sprites:   14551 / 30000
Sprite folders:   555
Total views:   1899
Total GUIs:   124
---------------------------

File sizes:
124MB
150MB
168MB
80MB (so far)
19MB
Music.vox: 145MB
total 689MB

Number of rooms:
81
44
46
41
1
total:
213

Notes:
There will be some duplicate characters between games of course. My goal is to get a complete cast of reusable fully animated characters, a kind of "Kings' Men" or "Mercury Theater," to star in future games.

A couple of future games will have hundred of rooms (e.g. games based on caves or oceans) but generally I expect the number to go down due to re-use. Although games currently only have 40 or so rooms, some rooms are 3000 pixels wide.

I don't use an inventory: the whole world is the inventory. Any character from any game can interact with any character or hotspot in any other game.

It took ten years to finish the first game, 8 months to do the second, 5 months for the third, and the current one should take 3.5 months. The increase in speed is due to the learning curve, and re-using resources. I estimate that by the end of this year I should be able to produce a new story every two months. I expect the game to expand by another 600 Mb in the next 12 months, then maybe 400MB a year thereafter, resulting in a final size of something like 8GB, 3,000 rooms and 100 complete stories by 2030. So far I'm on track. :)
#63
Quote from: SpacePaw on Sat 27/03/2010 02:13:37
Show me an ags game...no wait...any adventure game THAT large...

Keep checking EnterTheStory.com. By next month the combined game will be nearly 800 MB, 240 rooms and 4 stories.  I'll pass the gigabyte barrier at the end of this year, and should pass the 1000 room barrier in about four years. I'll be adding another story (averaging forty rooms and 150 MB of content) every four months for at least the next twenty years. You ain't seen nothin' yet. :)
#64
Quote from: Calin Leafshade on Fri 26/03/2010 17:59:57
In fact I find it difficult to think of a use for RunAGSGame.

What could you not do without it?

Make large games.

The larger the game, the longer it takes to compile, and the bigger the risk to the developer. RunAGSGame allows you to develop games in manageable stages. I'm talking gigabyte plus games with thousands of rooms and dozens of subplots. Not everyone wants that kind of game of course, but I do.
#65
Quote from: Pumaman on Thu 25/03/2010 21:33:06Can you clarify whether you're mixing games with low-res and high-res co-ordinates with RunAGSGame? There might well be a bug with that, I can look into it.

Thanks. My first three games were made with 2.72 using low res (640x480, but internal units are 320x240). I imported them to 3.12 using the "scale script coordinates" option. My latest game and the front end are made using high res.

When testing high res to high res everything seems fine, but testing high res to low res (e.g. launch the front end and select one of the first few games) then there are issues. E.g. initial character locations specified in the editor, and any command that uses system.viewport_width.
#66
Quote from: ProgZmax on Fri 26/03/2010 08:06:08
I'd happily use RunAGSGame() if there was a way to mark data to return to the previous game for use (like for keeping high score tables and separate savegames for marking progress).

With my games I do an autosave when leaving, so when you return to any game it remembers everything. As SpacePaw suggests, I also use a separate text file to record all the data I want to carry forward. Finally, I always enter games via a secret empty room which instantly forwards you any room you want, so you can enter and leave games at any point. It seems to work.

I love RunAGSGame. I can't imagine how anyone can make games without it. I love wandering between games. My first game is based in Paris, and my latest game doubles the size of the city. The next game will add even more little buildings and villages, and eventually you'll be able to explore whole countries. Making games withour RunAGSGame would be like living in a  room without any doors. For me it's the backbone of AGS.
#67
Quote from: monkey_05_06 on Thu 25/03/2010 02:51:44You should not report bugs directly to CJ via PM. You're supposed to post these in the Technical Forum.
I'll just leave it then. I've already posted about the system.viewport_width issue and the more serious repeatedly_execute_always bug and the Error creating window handle crash, the inability to start translated games and other issues. I'll see if those are accepted as bugs before posting any more. 

I looks like CJ waits to see if other people have the problem before fixing it - a perfectly reasonable approach. Most of my bugs are because I use RunAGSGame with large, complex games. Nobody else does, so we'll see if anything happens. I'll just carry on working around them.
#68
That's a good idea. Thanks. It's for a snow animation (where the sideways jittering is very noticeable when the flakes jump two pixels at a time). Presumably there would be memory implications if the fifteen separate full screen overlays suddenly became 30?
#69
Thanks. I'll do that. Maybe without the game files though - 150 MB is a bit much to attach to a PM :)
#70
How do I report offline? Is there an email address? My main computer isn't connected to the Net, but I can easily copy an error message onto a memory stick. Currently I need to reboot the computer about once every hour because AGS 3.12 decides it can't access some script.
#71
Sorry for posting so many questions lately. I'll go back to hibernation soon, promise :) But just one more:

I have some games that use low resolution coordinates in scripts. I have one object (an overlay) that would really benefit from moving 1 real pixel at a time. Is there any way to do that? I'd rather not convert the entire game to high res, as that would take several days.
#72
Quote from: Radiant on Wed 24/03/2010 13:38:22That's normal, and yes, you should tell CJ about it.

I'm not sure he'd be interested. I'm still using 3.12 and it looks like all the attention is on 3.2. CJ probably wants to know about bugs in the new product, not the old one.  I have to stay with the old version so my new games can interact with the old ones.

Plus some of the bugs are so obvious that surely others have reported them? For example, the 3.12 editor crashes at least three times a day (or rather, it won't save files until I reboot the computer). It also leaves multiple yellow popup messages that Windows interprets as full screen applications (e.g try ALT-TAB to see one, select it and do a full screen grab). That's probably the reason for not saving - the editor creates some orphan processes that Windows thinks are busy using the program. If other people haven't reported that then it must be because of how I use the program, so I don't want to be a nuisance. And I can't just auto-report since my main computer isn't connected to the Net.

I do sometimes post threads on strange problems,(here and here for example) but seldom get many replies. I think I sound like someone who's constantly complaining, and I don't want to sound ungrateful since the product is free and most of the bugs have workarounds.
#73
I found a related issue with causes a similar problem, and it looks like system.viewport_width might be the problem. E.g.
Code: ags
Overlay.CreateGraphical((system.viewport_width- graphicWidth)/2,y,slot)


In the above example, running a low res game (old style coordinates) from a high res game will cause the graphics to be placed far off to the right. I'm guessing that a similar thing happens with startX and startY values.

The 3.12 help file says that system.viewport_width is in 320x200 coordinates, but this does not seem to always be the case.

If system.viewport_width is the problem then the solution is to never call it, and manually override any features that use it (e.g. startX and startY in the editor).

Does anyone know if there are other internal functions that use system.viewport_width?
#74
This is a problem I have all the time. As a rule of thumb, I don't touch anything that was made since 1900: even if something is out of copyright, you can still be sued. Lawyers can still bankrupt you even if you win.

There are several issues here:

1. Grandchildren. Successful authors (like Arthur Conan Doyle Edgar Rice Burroughs) have grandchildren who make a living off their famous ancestor. It doesn't matter that their works are technically out of copyright, they could still sue on trademark or a technicality.

2. The Internet is global. The 1923 rule is usually good for the USA, but in Britain it's life of author plus 70 years. Someone who wrote a book in 1900 might not have died until 1950. And in France there is a law against harming the spirit of a novel, and that never expires (it was recently used against an unauthorized sequel to Les Miserables where Javert survives).

3. Music has a writer AND performer AND arranger. Each one will claim ownership.

4. Art has to be copied or preserved in order for you to see it. The person or museum that copies it will often claim copyright on old images, based on the argument that they have an exception (for museums) or they have tidied up the image (for online collections).

What it comes down to is how much money you intend to make, or how likely somebody is to complain. If you're making a small scale freeware product then common sense should be fine - e.g. use obscure tracks and books from the 1950s or before. But if you're doing something high profile or commercial then don't touch anything that has any element from post 1900, unless you have a license in writing.

As you can probably tell, I think the present copyright laws stink. We have to live with it but we don't have to contribute to it. As a moral principle every game I make contains a license saying all my own stuff will be public domain after twenty years.

Anyway, good luck!
#75
I continually find bugs and crashes with AGS that nobody else seems to get, and I put it down to the fact that I seem to use the program in ways that nobody else does. For example, my games all link together so I make heavy use of RunAGSgame and often have multiple copies of the AGS editor open.

I've noticed that others also use AGS in unusual ways (for 3D games, etc.). So is it quite common to be "out on a limb" like this?
#76
I always pass '0.' Thanks for the reply. It seems I only visit the forum to bitch about problems that nobody else has, so I'm grateful for your patience!

EDIT: thanks for the suggestion - I swapped some modules around, and it's the number that matters, not the content. The first three modules cannot use rep_ex_always when the game is called from RunAGSgame.

I previously tried deleting a lot of code, and it made no difference, so it's not closely related to the amount of code.

I tried combining modules 3 and 4, and they were not used, so it's not closely related to the total number of modules.

I started migrating earlier rep_ex code into the global rep_ex, and found another interesting effect, which I'll discuss in the other thread on coordinates. Which lead to a hypothesis: the parent game had three modules before the global script, and the child game will not look in the first three modules for rep_ex-always. Are the two facts related? I wonder if Pumaman could give an opinion?
#77
I'm getting some really weird behavior when using RunAGSGame. Before a certain point in my game (the one being called, not the parent game), rep_ex_always does not work. When run on its own the game works perfectly. Any ideas what might be happening?

(edit) - as you can see, I've stripped out almost all the code in the previous module, but I can't get rep_ex_always to be recognized any further back. I also tried combining the two modules, but that just stopped rep_ex from being recognized anywhere in the combined one. You can put a rep_ex_always function in any module after the line and it will work perfectly. And if not using RunAGSGame you can put it anywhere at all.
#78
No, they all use low res. I've replaced all those initial values with scripted values and it seems to work, so far. I'm getting a lot of odd behavior when using RunAGSGame - see the other thread for an even bigger problem.
#79
I recently converted several 2.72 games to 3.12, using 'low resolution co-ordinates in script.' The character startX and startX coordinates were automatically scaled to high resolution.

When I then ran the game, the startX and startY values were automatically doubled, so all the characters disappeared off the screen. So I manually changed all the startX and startY values. But now the behavior has changed, so they all appear in the top left hand corner of each screen.

Has anyone had any success with converting large and complex 2.72 games to 3.12? It's looking like the only option is to go through the code, line by line, and convert everything manually to high res.

EDIT: the problem with coordinates seems to be related to using RunAGSGame. That is, a game will show characters in the right positions when run directly, but run it through RunAGSGame and all startX and startY character coordinates double.
#80
On a related note, the same thing happens when an idle view runs into more than one loop. In 2.72, the idle loop would carry on happily, but in 3.12 it causes the dreaded blue cup to appear where the character should be.
SMF spam blocked by CleanTalk