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 - Monsieur OUXX

#1161
Quote from: Gurok on Mon 07/12/2015 23:50:39
I'd like to add to Monsieur OUXX's analysis that it should actually be possible to homogenise the output of the two algorithms. For us to maintain compatibility though, we'd have to look at rewriting FastLine.

Quote from: Snarkyquote author=Snarky link=topic=52978.msg636526561#msg636526561 date=1449502637]
I'm pretty sure you could without too much difficulty, but it's just not really worth it.

Both comments are true, but only if you have perfect understanding of how Allegro's drawing routine works internally. Because line-drawing algorithms are more subtle than one would think (for example: how to balance the step's extra pixels at the start and at the end of the line, that sort of decisions).

Therefore, this is dangerous business. Allegro could do this (I'm 99% certain that this is how they managed to suppress the second routine in Allegro 5: they simply merged the two algorithms) but... only because they know their own algorithm.

The real question is: if people think that the inaccuracy is insignificant, then yes, OK, let's use only one function that will switch to one algorithm or the other depending on the situation. I can't decide if this would be a source of problems for the end-scripter -- who could get confused trying to understand why his animated lines are sometimes slightly off. One thing is sure: it would be visible only in very low res.
You can have an idea of how visible it is by running this simulation (use the compiled file in "Compiled" unless you have the modified 3.3.5 posted by CW)

I'm against a general game option suggested by Gilbert.

#1162
Quote from: AnasAbdin on Tue 08/12/2015 06:45:08
I could do this as a 2D animation :-\

Edit: sorry Darth! I just realized this should have been in recruitment or pm :-[


General information: We don't want 2D animation because:
1) we might want to change the texture later on
2) We might want to readjust the shading later (for example: how much does it look like cell shading, for example)
That's not possible with hand-drawn 2D animation.
#1163
Quote from: Cassiebsg on Mon 07/12/2015 16:34:24
That said, feel free to send me the texture map if no one else volunteers. ;)

I've sent you a PM. Any other Blender/3DS/Maya wizards?
#1164
Quote from: Crimson Wizard on Mon 07/12/2015 15:13:22
Monsieur OUXX, is there a reason you chose to do 5 separate arrays instead of declaring a struct to group these custom GUI parameters?

Nope. Just old habits I keep from these times when one had to be paranoid about what CAN be array'ed or struct'ed and what cannot.
#1165
Quote from: Snarky on Mon 07/12/2015 15:34:21
You have to create that custom property first. Look up Custom Properties in the manual.

RadarG so that means that you had not been trying this piece of code before? So I'm lost : are all rooms meant to have exactly two backgrounds, or not? I have a feeling that you read only half the posts ;)
#1166
WE'RE NOT VERY GOOD AT 3D. (Blender and such)
Yes, that's sad, but that's how it is. :(
Well there was Erik who was awesome but we can't manage to contact him :(

Therefore, we do the same every time we feel like some cool, motivated people can do better than we can ever dream: We ask around. A game made by the community is way cooler, in my opinion. :)

So here's the challenge: We have this opening sequence where the drawing of a paper map is displayed full-screen. It's like this map is glued to the screen, but from the inside. ;) Then this map suddenly flies away. After some time I came to realize that the goal is to do pretty much like in the opening of MI3. Coincidence of reminicence? I'll never be sure sure what happened in my subconscious mind. I was sure we were being original. We'll consider it an hommage for now. :D

You can see what it looks like here, at 0:23 : VIDEO

Anyways, here are the details:
-  we would provide the texture for the map,
- you're able to produce this animation, either as a set of PNG frames, or as a Gif. We'd really, really prefer PNGs as our game is 32-bits and handles transparency. Everything behind the map is transparent.
- The cracks in the map are see-through. Not oo many cracks in the middle, but a few on the edges if you want
- Just like in MI, the animation must be rather short. The map should fly away quickly, BUT do a few movements first (like in the MI intro), so that the player has time to understand that it is a map he sees before it flies away. Talking about that, I think it would look better if one of the map's corners flapped a few times under the wind (before the map finallygets ripped from the screen and flies away), rather than the whole map just "ondulating" a few times like it's done in MI.
- the game is 320x200 running at 40fps.
- Your rendering is rather crisp. Not too much anti-aliasing please!

You're better than us, that makes no doubt. Special thanks for the 1000th time to Scavenger for the modules he made in the past. @CassieBg can you animate in Blander, or can you only model?

Of course, you'll be credited in the game! Don't be silly.
#1167
You cannot give them string names, however with a bit of work you can give them numbers. Provided you know what these numbers means, then it's as if you gave them a name.

If we imagine that you continue on your original design choice of having one hand-made Gui for each size requirement (instead of a dynamically resized gui -- I'm not judging, sometimes over-scripting things complicates things) then you can get inspiraiton from this:


Code: ags


//The 4 bubbles are 70,90,110 and 130.
#define NB_BUBBLES 4

int bubbleSizes[NB_BUBBLES]; //in this array we store the size of each bubble
GUI* bubbleGuis_Sx[NB_BUBBLES]; //in this array we store the pointer to each bubble GUI (Sx)
GUI* bubbleGuis_Dx[NB_BUBBLES]; //in this array we store the pointer to each bubble GUI (Dx)
GUI* bubbleGuis_Centre[NB_BUBBLES]; //in this array we store the pointer to each bubble GUI (Center)
GUI* bubbleGuis_OS_Sx[NB_BUBBLES]; // (OS Sx)

enum BubbleCustomSizes {
  eBubble70 = 0, //these are just arbitrary names. We give them zero-based values so that they can be used as indices in arrays. But just add "1" and it becomes the exact same thing as your "increment" variable.
  eBubble90 = 1, 
  eBubble110 = 2, 
  eBubble130 = 3
};



bool initOK;
void InitValues()
{
  if (!initOK) //we do all this only once, of course!
  {
    //We set all these values once and for all.
    //i.e. Everything that is arbitrary (and subject to change!) is centralized in this function
    bubbleSizes[eBubble70] = 70; 
    bubbleSizes[eBubble90] = 90; 
    bubbleSizes[eBubble110] = 110; 
    bubbleSizes[eBubble130] = 130; 
    
    bubbleGuis_Sx[eBubble70] = gBubble_dim_sx_70; 
    bubbleGuis_Sx[eBubble90] = gBubble_dim_sx_90; 
    bubbleGuis_Sx[eBubble110] = gBubble_dim_sx_110; 
    bubbleGuis_Sx[eBubble130] = gBubble_dim_sx_130; 
    
    bubbleGuis_Dx[eBubble70] = gBubble_dim_dx_70; 
    bubbleGuis_Dx[eBubble90] = gBubble_dim_dx_90; 
    bubbleGuis_Dx[eBubble110] = gBubble_dim_dx_110; 
    bubbleGuis_Dx[eBubble130] = gBubble_dim_dx_130; 
    
    bubbleGuis_Centre[eBubble70] = gBubble_centre_70; 
    bubbleGuis_Centre[eBubble90] =gBubble_centre_90; 
    bubbleGuis_Centre[eBubble110] = gBubble_centre_110; 
    bubbleGuis_Centre[eBubble130] = gBubble_centre_130; 

    bubbleGuis_OS_Sx[eBubble70] = gBubbleOS_sx_70; 
    bubbleGuis_OS_Sx[eBubble90] =gBubbleOS_sx_90; 
    bubbleGuis_OS_Sx[eBubble110] = gBubbleOS_sx_110; 
    bubbleGuis_OS_Sx[eBubble130] = gBubbleOS_sx_130; 
    
    initOK=true;
  }
}

//
//  [ ... ]
//
//  Now, in your function : 
//

InitValues(); //don't firget to call this!

short bubbleHeight;
short lblBubbleHeight;

BubbleCustomSizes size = increment-1; //size starts from 0, increment starts from 1

//Reminder: bubbleSizes[eBubble70] is 70, etc.
py = py - GetViewportY()-15-bubbleSizes[size];
bubbleHeight = bubbleSizes[size];
lblBubbleHeight = bubbleSizes[size]-50;


bool bubble_out = (py <= 30);
 
// three GUIs are declared in the global variables
GUI *gSideSx;
GUI *gSideDx;
GUI *gSideCentre;

 
if(is_centre
   gSideSx = bubbleGuis_Sx[size]; gSideDx = bubbleGuis_Dx[size]; gSideCentre = bubbleGuis_Centre[size];

else if(is_sx) {
    if(bubble_out) {
            gSideSx = bubbleGuis_OS_Sx[size]; gSideDx = bubbleGuis_Dx[size];

//    [ ... ]
#1168
YEah I have nothing against an enum parameter made optional to be sure it doesn't confuse anyone. If it's the very last one, then the chances that someone screws up with their values when typing all the preceding ones is very low, since this parameter is the most obscure of them all. My only regret is that, as demonstrated a few years ago, an extra parameter in AGS function calls is significantly slightly (yes, "significantly slightly", lol) slower. But, really no big deal. If it's an optional parameter then I don't know how the compiler works internally but with some luck it could just call the function without piling up that parameter in memory and without copying over its value. Hurray!

@Crimson Wizard: the accuracy issue is minor, and it's easy to understand why it happens : When the regular algorithm draws a line, you know that it shuffles the step with its own internal logic (e.g. : increase Y every 5 horizontal pixels). It all relies on internal calculations.
  Now, if you start your line outside the picture, imagine that it intersects your drawing surface from the top. You can't really predict where exactly the line will start "appearing" within your drawing surface (you could be one pixel off to the left or to the right), unless you draw the whole fucking line. But that's what you're trying to avoid.
  The Cohen Sutherland aproach is really naive (yet efficient) and that explains why it's the one both Allegro and I have been using. It's very easy to understand: You calculate on which borders your line intersect with the DrawingSurface, then you interpolate the coordinates of these inetresction poinst on the edges of the surface (it's simple maths really: y=ax+b )and in the end you draw a line between these intersections.
  However the intersection point predicted by "y=ax+b" is not exactly the same as the one evaluated by the drawing algorithm. So the start and end pixels of the simplified line might not be exactly the same as the regular line. And that's why your simplified line might be one or two pixels off, every few pixels.

@ollj : congrats, you're actually trying to recreate Cohen Sutherland from scratch ;)
#1169
Quote from: Monsieur OUXX on Mon 07/12/2015 13:17:42
HOEWEVER...
Genuine typo. I'm leaving it here because it's just too funny
#1170
Hello RadarG,

It didn't work with the other character because, indeed, CW's code snippet only deals with cMaggie (it might be on purpose because CW probably takes for granted that the background is reset to 0 every time the player re-enters the room). Therefore, your updated version of his script should work.

HOEWEVER...

I think it doesn't work because it's conflicting with CW's first piece of script (the one with the room property). CW specifically mentionned that you should use that first script only if some rooms don't have two backgrounds. You've been trying to be too smart for your own good.

- If all rooms are meant to have two backgrounds, then remove that piece of script that mentions the room property and I bet you that it will work (provided  you don't click on your gui in an unfinished room that still has only one background, or it will crash, as you can expect).

- If not all rooms are meant to have two backgrounds, then simply mix the first and second piece of script, to make it all work smoothly together:
Code: ags

function on_event (EventType event, int data) 
{
    if (event == eEventEnterRoomBeforeFadein)
    {
        if (GetRoomProperty("MustSwitchBackgrounds") == 1) //hey we're entering a room that has more than one background!
        {
            if (player == cMaggie)
                SetBackgroundFrame(0);
            else
                SetBackgroundFrame(1);
         }
         else //we're entering a room that only has one background
         {
             SetBackgroundFrame(0); //set it to zero. Probably unnecessary, but... just to be sure.
          }
    }
}



==========

About on_event: the meaning of "data" really depends on the actual event that triggered that function. All the meanings of "data" are explained in AGS' manual, in the page called "Predefined global script functions" (I found it by typing "on_event" in the search field) :

Quote
eEventEnterRoomBeforeFadein
      called just before room Player Enters Room event is run.
      DATA = new room number


By the way, CrimsonWizard, in my AGS 3.4, eEventEnterRoomBeforeFadein is missing in the "Built-in enumerated types" article. It should be added.
#1171
I've been watching that, and the end is hilarious, when they pretend to pitch the game to some producer.

However I can understand why Loom was such a success, and they never mentionned it in the video: It's fucking CINEMATIC. Like, all the time. If you look closely at the backgrounds and the special effects, there is a constant use of background, foreground, perspectives, themed lighting... I mentionned special effects: I don't know if you guys noticed, but there is a use of cast shadows and also in some scenes the characters get dissaturated (a.k.a. grey) when walking in the distance.

You don't see these things in Fate of Atlantis or Monkey Island. Loom is really, really cinema oriented.

Once again I'm not saying it's making it a good game, but instead a mind-blowing game (note the subtle difference) at the time it was released (it's fucking old compared to other games, don't forget that).
#1172
The cause could be a mixup between mouse modes (Talk, interact, etc.) or some faulty scripting in your dialogs, or even something else. You have all the symptoms of a breakpoint placed on that line but you say you have no red dot there (that's dubious to say the least!). We can't have an accurate idea of what's going on.

So if you want to investigate further into this (despite the issue being partially "fixed"), I suggest you zip up your game and upload it anywhere (Dropbox, mediafire, whatever). Then we'll be able to look into this.
#1173
AGS Games in Production / Re: 80'SQUEST
Mon 07/12/2015 09:47:24
QuoteDonny
...Or should we call him OceanSpirit Donny, considering his hair!
#1174
Quote from: Mandle on Sun 06/12/2015 08:48:48
@Monsieur: No problem man, December 8th it is.  Background looks really hot so far!

HEY WAIT!!! The 8th was the ORIGINAL dead line!!! I requested the deadline to be extended to the 13th!!! :(
#1175
....or maybe it's OK, but you'd need to add this to the documentation:

Quote
FastLine


DrawingSurface.FastLine(int from_x, int from_y, int to_x, int to_y,
                        optional int thickness)


A variation of function "DrawLine" that can draw the line faster under some specific conditions. Draws a line from (FROM_X, FROM_Y) to (TO_X, TO_Y) in the surface's current drawing colour.
The thickness parameter allows you to specify how thick the line is, the default being 1 pixel.

NOTE: The X and Y co-ordinates given are ROOM co-ordinates, not SCREEN co-ordinates. This means that in a scrolling room you can draw outside the current visible area.

When to use:

This function will make you gain speed only if the line is larger than the target DrawingSurface. For example, if you decide to draw a line that goes from (-100,-100) to (400,300) onto a 320x200 DrawingSurface.

When not to use:

This function will cause some accuracy loss in (from_x, from_y) and (to_x, to_y). In other words, a line drawn with DrawLine and a line drawn with FastLine will not overlap perfectly.
Here is a sample code that will demonstrate the accuracy loss. The dark red pixels show you where the lines don't exactly overlap.

DrawingSurface *surface = Room.GetDrawingSurfaceForBackground();
surface.DrawingColor = Game.GetColorFromRGB(100,0,0); //dark red
surface.DrawLine(-200, -200, 600, 400);
surface.DrawingColor = Game.GetColorFromRGB(0,100,00); //dark green
surface.FastLine(-200, -200, 600, 400);
surface.Release();

General example:

DrawingSurface *surface = Room.GetDrawingSurfaceForBackground();
surface.DrawingColor = 14;
surface.FastLine(-500, -500, 500, 500); //this line is larger than the target drawing surface
surface.Release();

will draw a line from the left top of the screen (0,0) to the middle of the screen (160,100);

See Also: DrawingSurface.DrawLine, DrawingSurface.DrawingColor


#1176
Quote from: Crimson Wizard on Fri 04/12/2015 15:28:48
Alright, please try this out:
http://www.mediafire.com/download/2qudq8c9qeh5g6n/ags-3.3.5--fastline-test.7z

I exported Allegro's fastline() function as DrawingSurface.DrawFastLine(). It reduces the Step 1 of your example to about 5 seconds.

Yes indeed, it's much faster.

However, I *HATE* to say that (trust me, I really do), but I'm not sure it's a good idea to have two DrawLine functions. The reason why the second one is faster might be lost to less "educated" scripters, and actually add confusion because they wouldn't know when not to use it (not to mention, maintenance: documentation, etc.). I know that if I was you, I'd be supremely annoyed that my immediate feature implementation is rejected by the very person who suggested it. But I'm really being honest.

I'd like to know the opinion of the community on this.
#1177
Quote from: Crimson Wizard on Fri 04/12/2015 14:43:49
If there were not, the pixels will be drawn outside of bitmap in memory...
Well yeah by my tests clearly show that the computing time is proportional to the actual length of the line, regardless of the boundaries. So I guess the test is done at the very end, after computing each pixel's coordinates individually.
#1178
It's very simple really :

1) They often looked awful because of poor compression quality and space limitations
2) They were often poorly written and looked more like soap opera than actual cinematics
3) They were often used as a substitute for gameplay and didn't fit.

If you overcome all that, then why not.
#1179
Quote from: selmiak on Thu 03/12/2015 19:32:06
maybe digging into the released sourcecode of the art of dying by dkh will help. The level editor is pretty nifty and had long line drawing functions.

I didn't know that the source code is public and never noticed it has a level editor! (the demo was too hard for me, I gave up) (I'm not good at platformers). I'm going to look into this.


EDIT: I looked at the source and didn't find any "long line" drawing routine. Only regular lines to draw short things like rectangles and such.
#1180
I'm currently working on a tool that requires me to draw very large straight lines onto a small drawing surface. For example, lines that go from coordinates (-5000,-5000) to (5000,5000), onto a 320x200 DrawingSurface. That allows me to draw a grid onto a canvas, as well as vanishing lines (they go very far on the sides of the image).

I've tested how long it takes to simply use DrawLine, and I came to the conculsion that it is very long, because there seems to be no clipping or coordinates checking built into AGS. All tests done in a 32-bits game with Direct3D9.

Here is the sample code:

Code: ags

    int limit = 500000;
    int i;
    bool hasAlpha = false;
    DynamicSprite* ds=DynamicSprite.Create(320, 200, hasAlpha);
    DrawingSurface* s = ds.GetDrawingSurface();
    
    //STEP 1 : takes 19s
    Display("Click when ready for step 1.");
    i=0;
    while (i<limit)
    {
       s.DrawLine(-3200,  -2000,  3200,  2000);
       i++;
    }
    
    //STEP 2 : takes 3s
    Display("Click when ready for step 2.");
    i=0;
    while (i<limit)
    {
       s.DrawLine(0,  0,  320,  200);
       i++;
    }

    //STEP 3 : takes 10s
    Display("Click when ready for step 3.");
    i=0;
    while (i<limit)
    {
       s.DrawLine2( -3200,  -2000,  3200,  2000,  COLOR_LIGHTGRAY);
       i++;
    }
    
    //FINISH
    Display("All over.");
    s.Release();
    ds.Delete();


As you can see, step 1 (with the big coordinates) takes 19s versus 3s with "clipped" coordinates. That's 6 times longer.
Now you'll see that I can reduce it to 10s (so about 50% performance gain) by using my very own clipping function, a.k.a. DrawLine2, relying on some C implementation that I've found on the web :

Spoiler

Code: ags



 
// "Cohen Sutherland" line clipping. 
//  It draws only the part of the line that is within the viewport.
//
// Originally found at http://electrofriends.com/source-codes/software-programs/c/graphics/c-program-to-implement-the-cohen-sutherland-line-clipping-algorithm/
// credits ???

enum outcode {
  TOP = 1, 
  BOTTOM=2, 
  RIGHT=4, 
  LEFT=8
};

int compute_outcode(float x, float y, 		float xmin, float ymin, float xmax, float ymax)
{
  int oc = 0;

  if (y > ymax)
    oc = oc | TOP;
  else if (y < ymin)
    oc = oc | BOTTOM;


  if (x > xmax)
    oc = oc | RIGHT;
  else if (x < xmin)
    oc = oc | LEFT;

  return oc;
}

void DrawLine2(this DrawingSurface*,  int xx1,  int yy1, int xx2,  int yy2,  int color)
{
  
    int c = this.DrawingColor;
    this.DrawingColor = color;
  
    float xmin = 0.0;  float ymin = 0.0; float xmax = IntToFloat(this.Width); float ymax = IntToFloat(this.Height); 
    float x1 = IntToFloat(xx1); float x2 = IntToFloat(xx2); float y1 = IntToFloat(yy1); float y2 = IntToFloat(yy2);
    
    bool accept = false;
    bool done = false;

    int outcode1 = compute_outcode (x1, y1, xmin, ymin, xmax, ymax);
    int outcode2 = compute_outcode (x2, y2, xmin, ymin, xmax, ymax);
    while (!done)
    {
      
        if (outcode1 == 0 && outcode2 == 0)
        {
            accept = true;
            done = true;
        }
        else if (outcode1 & outcode2)
        {
            done = true;
        }
        else
        {
            float x, y;
            int outcode_ex;
            if (outcode1!= 0) outcode_ex = outcode1; else outcode_ex = outcode2;
            
            if (outcode_ex & TOP)
            {
              x = x1 + (x2 - x1) * (ymax - y1) / (y2 - y1);
              y = ymax;
            }
       
            else if (outcode_ex & BOTTOM)
            {
              x = x1 + (x2 - x1) * (ymin - y1) / (y2 - y1);
              y = ymin;
            }
            else if (outcode_ex & RIGHT)
            {
              y = y1 + (y2 - y1) * (xmax - x1) / (x2 - x1);
              x = xmax;
            }
            else
            {
              y = y1 + (y2 - y1) * (xmin - x1) / (x2 - x1);
              x = xmin;
            }
            if (outcode_ex == outcode1)
            {
              x1 = x;
              y1 = y;
              outcode1 = compute_outcode (x1, y1, xmin, ymin, xmax, ymax);
            }
            else
            {
              x2 = x;
              y2 = y;
              outcode2 = compute_outcode (x2, y2, xmin, ymin, xmax, ymax);
            }
        }
    }
 
    if (accept)
      this.DrawLine(FloatToInt(x1), FloatToInt(y1), FloatToInt(x2), FloatToInt(y2));

}


[close]

Now I can't think of any possible scenario where that would be useful to ANYBODY (or maybe crazy people like Radiant, who make vector-based games ;) ) but I thought I'd share.
If some day the C++ team felt like implementing the boundaries check, then it's all ready to use, out of the box.

EDIT: I've gained less than 1 second by putting the code of "compute_outcome" inline (directly where it's called), so the benefit is insignificant.
SMF spam blocked by CleanTalk