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

Topics - EnterTheStory (aka tolworthy)

#1
Hi Guys!
I just thought I'd let you know about my new super-simple game engine.

After releasing five AGS games, people kept asking me if my games were available on the iPad. So I decided to code my own javascript based game engine that would work on anything. I am the world's slowest coder, so the games are simple and the engine is simple too.

Finished games:
The Picture of Dorian Gray
Journey To The Center of the Earth
The First Men In The Moon
Romeo and Juliet
Macbeth
Frankenstein

How to make your own games


I plan to add one per week for the next 20 years (making 1000 new games). See what you think.

#2
The Count of Monte Cristo will be released at the end of this week, just as soon as I get the demo version made and do other housekeeping stuff. If you want a pre-release copy right now, for free, all you have to do is promise to review it on your blog, or write an official AGS review, or review it on on any site that reviews stuff - not just sites for games, as this is aimed at anyone who likes stories.

It won't take too long to play, as it's stuffed with hints and help if you want it. And it contains a lot of improvements over previous games, so who knows, you might even enjoy it.  Go on, you know you want to. Just PM me.

What's new compared with my earlier games:

* better early feedback from testers - I'm finally getting there.
* More polish: The Count of Monte Cristo has been tested and re-tested more than the other games, with more improvements added as a result of previous game reviews.
* More natural: The game now focuses on just on one character, meaning dialog is more natural and less generic.
* More detail: The full text of the original novel is now available in the game - visit the in-game library, or press B to read the book.
* Easier controls: just click. That's it! Simples.
* More natural movement: In early games, only one or two characters had full movement. With The Count of Monte Cristo, there are now fifty different fully mobile sprites. Also, walking code has been rewritten and improved.
* Lots of other improvements: no jumping around for clues, more favorite locations, more classical music, more access to that music, better space bar behavior, better books in the library, more relevant clues, the list goes on!
* A faster story. Early reviewers complained that the game felt too slow. Well not any more.

Don't worry, I don't expect a finished review by the end of the week. I know that reviews can take months. But the goal of this project is to adapt a new classic novel every few months, so I'm itching to release Mont Cristo and get working on The Picture of Dorian Gray.

PM me if you need a review copy.
Thanks for reading!
#3
I'm getting some pleasing early reviews, and the game should be ready for release later this week... all going well. :)


http://www.enterthestory.com/blog/
and as a bonus, the blog contains early concept art for the next game,The picture of Dorian Gray!
#4
Could extreme usage of String.Format or a GUI label cause a game to freeze?

Once every few months someone comments that my game freezes when my "recent dialog" screen pops up. It uses this code:
Code: ags

String memoryDialog[115]; // records every line of dialog as it is spoken
String dialogText; // temporary
function updateDialogLabel(int line) // adds lines from "memoryDialog" to the end of  "dialogtext"
{	String text ="";
	if((line >=0)&&(line <101)) // elsewhere the contents of memoryDialog are looped after line 100
	{ if(memoryDialog[line] !=null)
		dialogText =String.Format("%s[%s", dialogText, memoryDialog[line]);
	}
}
function showMemoryDialog()
{ int line = memoryDialogBot -8;					// start 8 lines before current line
	dialogText ="";
	updateDialogLabel(line);
	int i =0; while(i<9){ line++;updateDialogLabel(line);i++;} // adds 9 recent lines 
	dialog0.Text =dialogText;
	if(memoryDialogBot >5)dialogUp.Visible =true; else dialogUp.Visible =false; // up and down arrows on the GUI
	if(memoryDialogBot <memoryDialogNow)dialogDown.Visible =true; else dialogDown.Visible =false;
}

I know there is a limit of 2000 characters and 35 lines, but I think it's unlikely I reach those limits. Is there anything else about this code that shouts 'potential freeze'?
#5
My new game, The Count of Monte Cristo, could do with some testing - any volunteers? I'm also looking for suggestions for how to improve it, so any feedback at all is welcome! PM me and I'll send you a link.

Thanks in advance.



#6
This thread says a String parameter can have a default value, e.g.
Code: ags
function myFunction(String optional =0)
{ if(optional !=0){ runCode();}
else{return;}
}

Apparently this might, in theory, be potentially dangerous. Why? What might possibly go wrong? I'd like to use it in deeply embedded mission-critical functions, and I can't afford to take any chances.
#7
My translated games work fine, except for this code:
Code: ags
function rm(String st) // used for finding room numbers from names
{	if(st ==GetTranslation("London streets"))        return 3;

How it works is this: if a hotspot has the name of a room (e.g. "London streets" is room 3) the game can use "rm(name)" to return its room number. I also list room names in an array of recently visited rooms. This works fine in English, but in other languages it breaks. So I tried this:
Code: ags
function rm(String st) // used for finding exits from names
{	if(st ==GetTranslation("London streets"))        return 3;

But get the following error:
Code: ags
misc code.asc(369): Error (line 369): Type mismatch: cannot convert 'String*' to 'string'

Any suggestions?
#8
My computer recently died and I'm busy rebuilding a new one. I need a copy of 3.02 for compatibility reasons. any idea where I can find it? Thanks in advance.
#9
In keeping with the spirit of the AGS boards, Les Miserables: the game of the book is now freeware. Click over to http://enterthestory.com/ and look for the red "FREE" label.

The game sold well for a first game, but one of the composers who provided live music did so on the understanding that the game would be free one day, and now it is.

Over the last couple of years (and particularly since upgrading to 3.x) players have reported some minor bugs, and these should all be fixed now. As a first game the underlying code is pretty complex, so there may be still some rough edges but nothing too serious. I hope someone enjoys it.

Oh,and I'd like to upload it to other places beside my own site. Any suggestions? It's 135 MB if that's relevant. And if anyone else wants to upload it to their site you don't need to ask permission, I'd be flattered.
#10
I'm combining my games into one file: currently I have 900 characters in 4 stories, and when I complete my goal of 100 stories I expect to have around six thousand characters. Many of will them re-use views, so with some awkward fudging I could reduce the character count to maybe two thousand, and have them change rooms and names as needed. Is there likely to be any speed benefit in doing so?

E.g. is there anything about the built in AGS code that checks every character every frame? Or (worse) built-in code that compares every character to every other one (i.e. so a small increase in character numbers would have a big impact on game speed)?
#11
I'm experimenting with large games, and some of them take 30 seconds between clicking the icon and seeing the game - there's not even a black screen until then.* Preload.PCX only appears in the last half second, which sort of defeats its purpose. Am I doing it wrong?

Is there some other way to load a pre-load screen? I don't want to launch the game from some pre-loader, because my whole reason for combining games is to simplify the launch as much as possible.** But is there some way to let the user know that something is happening?

* I'm planning ahead for 100 games in one file, based on the size of the first 4 games. I tested the worst case scenario: 250 MB of text modules that all have to load before anything is seen.

** I've had reports of game shortcuts not working in some configurations, and I can't find any reason for it. Mostly it works, but occasionally it doesn't: so I'm not taking ANY chances with shortcuts, non-standard loads, etc.
#12
I'm considering combining all my games into one file. Right now it would only be 700 MB, but over the next 20 years it could easily push 10 gigabytes. Is there any practical limit to the physical size of AGS games?

EDIT: I've tried a 3 gig game, and it works OK, but obviously I haven't tested it thoroughly - it was just a fake game with giant rooms. I'd be interested to know if anyone has found slow downs when pushing everything to the limit.
#13
I'm having intermittent problems with Windows not finding files when using start menu shortcuts and RunAGSGame. For example:

Quote
I installed the games on D drive. I moved from game A to game B, then tried to move from game B to game C: The game crashed....over and over again. Same happened A to C to B.
.
Then I installed the game on my C drive...same computer....windows XP
Did the same things and this time everything worked perfectly, back and forth, back and forth...
.
...until the seventh time, then crash.
.
Then I installed the game on my laptop....windows vista. This time everything worked perfectly.
.
Then tried to start the game from a start menu shortcut (not the desktop shortcut) ...and it wouldn't.
.
I tried the same thing on the XP-machine...it did open eventually, after nine attempts....as if it finally found what it was looking for???
.
I tried again...it opened....tried again...tried about twelve times, it opened perfectly every time.

It sounds like Windows is having problems finding things. Is there any way that I can make the job easier? Like using certain folders (I install to My Documents), only using DOS 8.3 filenames, forcing the user to only start with the same game each time?

I am really stuck here. My game relies on frequent use of RunAGSGame, and if Windows can't always find files then I'm in serious trouble.
#14
I often get this crash when loading a saved game:
Code: ags
Crossfade: buffer is null attempting transition


This was mentioned a couple of years ago but I can't find any reference to a solution. I use eTransitionCrossfade as the default screen fade, so I imagine that is the problem?

I've tried calling 'SetNextScreenTransition(eTransitionInstant)' before saving a game but it makes no difference. Any ideas what I should do?
#15
A certain room causes a "more than 50 sprites" crash, but ONLY when run with non-standard settings (3x antialiasing, 100MB RAM for sprites, Direct3D9). That room was supposed to only have 49 sprites. Any idea what might be happening?
#16
My games often refuse to save or load in the editor. Until now rebooting the computer always fixed it, but no longer. Presumably this is due to some registry permissions thing? Is there a line in the registry (or some ini file) I can edit to allow me to run a game?

Here are sample error messages from two different games:
Code: ags

---------------------------
Adventure Game Studio
---------------------------
An error occurred whilst trying to load your game. The error was: 

The process cannot access the file 'C:\AGS\sandbox\GlobalScript.asc' because it is being used by another process.

If you cannot resolve the error, please post on the AGS Technical Forum for assistance.

Error details: System.IO.IOException: The process cannot access the file 'C:\AGS\sandbox\GlobalScript.asc' because it is being used by another process.
   at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
   at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy)
   at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share)
   at AGS.Types.Script.LoadFromDisk()
   at AGS.Types.Script..ctor(XmlNode node)
   at AGS.Types.Scripts..ctor(XmlNode node)
   at AGS.Types.Game.FromXml(XmlNode node)
   at AGS.Editor.AGSEditor.LoadGameFile(String fileName)
   at AGS.Editor.Tasks.LoadGameFromDisk(String gameToLoad, Boolean interactive)
   at AGS.Editor.InteractiveTasks.LoadGameFromDisk(String gameToLoad)
---------------------------
OK   
---------------------------


---------------------------
Adventure Game Studio
---------------------------
An error occurred whilst trying to load your game. The error was: 

The process cannot access the file 'C:\AGS\Les Miserables\misc code.asc' because it is being used by another process.

If you cannot resolve the error, please post on the AGS Technical Forum for assistance.

Error details: System.IO.IOException: The process cannot access the file 'C:\AGS\Les Miserables\misc code.asc' because it is being used by another process.   
at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)   
at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy)   
at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share)   
at AGS.Types.Script.LoadFromDisk()   
at AGS.Types.Script..ctor(XmlNode node)   
at AGS.Types.Scripts..ctor(XmlNode node)   
at AGS.Types.Game.FromXml(XmlNode node)   
at AGS.Editor.AGSEditor.LoadGameFile(String fileName)   
at AGS.Editor.Tasks.LoadGameFromDisk(String gameToLoad, Boolean interactive)   
at AGS.Editor.InteractiveTasks.LoadGameFromDisk(String gameToLoad)
---------------------------
OK   
---------------------------

#17
I have a function for fading out GUIs, but what's the right terminology?  E.g.
Code: ags

function fadeGUI (int whatGUI){}//?
function fadeGUI (GUI* whatGUI){}//?
function fadeGUI (gui *whatGUI){}//?
function fadeGUI (what doIputHere){}//?

Sorry if this is a trivial question, but I can't find the syntax in the manual or the forums.
#18
I'm shooting irregular holes in my sprites. That is:
1. I use DynamicSprite to get the existing sprite as a mask
2. I draw a rectangle in COLOR_TRANSPARENT
3. the use DrawImage to fill in the rectangle with a nice shaped hole
4. Then use this as a transparency mask

This is fine for single holes, but is no good for overlapping holes because the edges of the hole are added each time.

What I'd really like to do is paste only the hole, then afterwards set the sprite transparent color to the hole color.
or...
just tell AGS to past the hole shape as transparent.
or...
flip the transparent and opaque pixels (using AND, NOT, etc).
Is any of this possible?
#19
Is it normal for 3.x translation files to have multiple identical lines? I'm updating a translation file and keep finding duplicate lines, usually instructions like "Save" and "Cancel." Is this normal? The first appearance is translated and the second is not (it only appeared in the update). Should I manually copy the translation of the first occurrence and paste it after the second occurrence as well?
#20
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.
SMF spam blocked by CleanTalk