So has a kyr system been created?

Started by Imc7r, Tue 20/02/2018 16:55:52

Previous topic - Next topic

Crimson Wizard

#20
Quote from: Imc7r on Sat 10/03/2018 17:04:20
Can anyone tell me if I can do the script replacing the object name withing ObjectIDForScript with a string variable? Yes I have read the things about these vars.
Strings are not the same as actual object references, so you cannot use them to get object's data. Normally, in other engine/language, you would probably do something like GetObjectByName(string), but AGS does not provide such ability.

Then, putting something like "EnvProp[1]" in a string won't make that string an actual command that could be executed. AGS script is only compiled at the editing time, it cannot run commands created like that at runtime.


Quote from: Imc7r on Sat 10/03/2018 17:04:20
It is because I repeat this for several objects in a While loop and all objects are called ObjForDynamicSprite0, ObjForDynamicSprite1, ObjForDynamicSprite5, etc. So im trying to combine string (same name + i where i is the increasing increment)

Ok, what you need is to use an object array. There is "all objects in room" array already, called simply "object" (it's a global variable), which you may use to iterate through all objects in the room. It is refilled each time you change rooms.
So, for example, if you know that in your generated rooms you are using objects with IDs from 5 to 15, then you could make a loop:
Code: ags

int i = 5;
while (i <= 15)
{
    Display(object[i].Name); // displays every object's name in a sequence
    i++;
}


If you cannot do that for any reason, for example these objects are not sequential, or you want to have more generic program, like having generation script sepearated in a module (which may be reused in various rooms) you could create a separate array to store pointers to objects you need.
Crude example:
Code: ags

Object *ObjsForDynamicSprite[MAX_TREE_OBJECTS];


You fill this array in the beginning of a room with actual room objects
Code: ags

function room_Load()
{
    // explicit assignment
    ObjsForDynamicSprite[0] = ObjForDynamicSprite0;
    ObjsForDynamicSprite[1] = ObjForDynamicSprite1;
    // or, if these objects come in sequence
    int i = 5;
    while (i <= 15)
    {
       ObjsForDynamicSprite[i] = object[i]; // Note that this is not object copying, only pointer (reference) is being saved
       i++;
    }
}


Then you just use ObjsForDynamicSprite array during generation and other adjustments.



PS. Latest versions of AGS also support "for" loops (this is not mentioned in the online material, because its outdated, but you may find it in the offline manual which comes with AGS editor):
Code: ags

for (int i = 5; i <= 15; i++)
{
    // do something
}


Imc7r

^ Excellent explanations, these are the ones I was looking for, thanks. I might be able to do fine with the global var for objects, yes I was looking for conversion of reference to string but you explained it's absent and what I can use instead. I will be on with these and find my way with them. I saw 'for' worked but was unsure if it is implemented which you confirmed.

Imc7r

#22
Code: ags
for (int i = 0; i<=1; i++) {

propY[i] = Random(1080); //int var
propScaleX[i] = FloatToInt((propY[i] / 385) * 600, eRoundNearest); //int var
}


I have this weird thing, I want to convert the float to integer after doing some calculation but it tells me Error (line 62): Type mismatch: cannot convert 'int' to 'float'
isnt this what FloatToInt is about to convert, to make it an integer eventually?

I even tried putting all the decimal calculation in a float var and ends same error when I use FloatToInt
Code: ags
scaleReal = FloatToInt((propY[i] / 385) * 600, eRoundNearest); //float var


or
Code: ags
scaleReal = propY[i] / 385) * 600;
propScaleX[i] = FloatToInt(scaleReal, eRoundNearest);


Crimson Wizard

#23
Which of your variables are ints and which are floats?
AGS is very inconvenient in terms of conversions between types. You need to make sure types match in every single operation and every constant determine correct type.
For example, if you have "float f" and want to divide it by 100, you must write 100 as "100.0", explicitly telling that it's a float.

Snarky

Quote from: Crimson Wizard on Sun 11/03/2018 17:35:57
if you have "float f" and want to divide it by 100, you must write 100 as "100.0", explicitly telling that it's a float.

This is definitely the issue.

Imc7r

#25
^ yes indeed that was the issue, it doesnt want to do float = (int * 2.00)/0.0344 even though mathematically the result would be a float , had to be float = IntToFloat(my int var)) * 2.00/0.3456

Ok Im working on the system but I've some inaccuracies. So for a 1920x1080 room screen I wanted to make the whole displaying trees at random location using Dynamic Sprites so that:

- the lower the image displayed on the screen, the bigger they look, the more on the top of the screen, the smaller the scale. What im really missing is the ability to get sprite width and height. The logic of my code is like that:

set Int var for Position X (random number between 0-1920), set int var for position Y (random number between 0-1080). This is because I have no other way to track their location that I want to make the scaling depend on. So based on the code I have so far:

Crimson Wizard

Quote from: Imc7r on Mon 12/03/2018 15:22:34What im really missing is the ability to get sprite width and height

For static sprites:
Game.SpriteWidth[sprite_number] - returns width for sprite by its ID
Game.SpriteHeight[sprite_number] - returns height for sprite by its ID

For dynamic sprites: DynamicSprite.Width, Height.

Imc7r

#27
^ Thanks this was handy and I found a relation between the sprite height and Y position to make the images larger at the bottom.

Code: ags

    propScaleReal[i] = (IntToFloat(propY[i])* IntToFloat(Game.SpriteHeight[prop[i]]))/376.71; //propY is int to determine the random Y across the screen, prop[] is the ID of the sprite
    propScale[i] = FloatToInt(propScaleReal[i], eRoundNearest);


However, the images still appear either squished (as if only X was decreased), small and not big at the bottom of the screen. I assign to Objects that are 1920x1080 alpha channel images with X 0 and Y 1080 to cover the whole screen.

Code: ags
    EnvProp[i] = DynamicSprite.Create(Room.Width, Room.Height,  true);
    EnvPropSurface[i] = EnvProp[i].GetDrawingSurface();
    EnvPropSurface[i].DrawImage( propX[i], propY[i], prop[i]);
    EnvProp[i].Resize(propScale[i], propScale[i]); 
    object[i].Graphic = EnvProp[i].Graphic;
    EnvPropSurface[i].Release();   
    //EnvProp0.Delete();


Is this code giving them different scale because it is a Room.Width/Height sheet? Or maybe my EnvProp.Resize(propScale[], propScale[]); needs to be made differently to scale the sprites properly?

(A side question, is there a way in the Editor to select between objects placed in the room the way you can see characters? The item tree of all elemnts does not show them and if you place the objects on top of one another you cannot select between them when they cover the whole room)

Crimson Wizard

#28
Quote from: Imc7r on Mon 12/03/2018 18:33:52
However, the images still appear either squished (as if only X was decreased), small and not big at the bottom of the screen. I assign to Objects that are 1920x1080 alpha channel images with X 0 and Y 1080 to cover the whole screen.

I do not have time to investigate right now, but one thing to check out that comes to mind: the coordinates you are passing to DrawImage are top-left coordinates of an image, which is different from how objects are normally placed in pseudo-3d, where bottom line defines their visual position.
Depending on perspective rules you are emulating, "closer" objects, which are also larger, may need their top-left coordinate also be closer to the top of the screen, and hence use smaller Y (closer to 0) when you draw them.

Hope my explanation makes sense...

Since the meaning of "propY" is probably the position of the tree trunk where it touches ground, perhaps try to introduce new variable called "propHeight" and when drawing a prop, do something like DrawImage( x, propY - propHeight );


Quote from: Imc7r on Mon 12/03/2018 18:33:52
(A side question, is there a way in the Editor to select between objects placed in the room the way you can see characters? The item tree of all elemnts does not show them and if you place the objects on top of one another you cannot select between them when they cover the whole room)

Using the list on the properties pane.
Alternatively you may try the new experimental version of an Editor which has a "navigation bar" in the room editor: http://www.adventuregamestudio.co.uk/forums/index.php?topic=55829.0


EDIT: Oh, I just realized, you are making objects all room large. Another solution is to make smalls object with dummy gfx, and arrange them only to make it convenient to select them. Then in "room load" event you set correct gfx and positions.

Imc7r

#29
Code: ags
EnvProp[i].Resize(propScale[i] + EnvProp[i].Width, propScale[i] + EnvProp[i].Height);

adding the original width and height made the squished images look correct actually and it was about making the trees appear larger than the char, now it's proper aspect ratio of each image and acceptable sizes of trees. Scaling arent exactly always shrunk at the top screen but it doesn't matter much. I use for object Baseline propY*(-1) so I made it work so that lower screen objects would appear in front of ones at the top.


The white underlines things that need fixing.

1) In one of them, the stone probably has Baseline value lower than the tree (and btw the Y position of dynamic sprites or drawn images are taken from the top of the image, not the bottom). In such case Im trying to make it so
Code: ags
if ((Game.SpriteHeight[prop[i]] < 100)
&& (only the stones have such small height - this is the condition im missing - if 2/3 or top of the tree image is at the Y of the stone, then Set Baseline to e.g 1 or whichever higher value to hide BEHIND the tree crown - or even delete remove or hide the image since whats t he point of having it if hidden by the tree crown.

There is no (if something is in area of the screen). In my case using the propY as initially set position for every dynamic sprite, I can compare if it is around the propY of another sprite. But I want like
Code: ags
(if propY[i - currently taken integer] + (2/3 of Game.SpriteHeight[prop[i - 1]] or 2/3 of Game.SpriteHeight[prop[i + 1]]
etc) then set the baseline.

2) I see the BlockingHeight/Width property of objects but how can I detect the location of the trunk bottom or stone when the whole dynamic sprite is probably the whole screen while the stone or trunk area I want to block is part of it?
3) The stone in front of his face, perhaps the char.Baseline needs to be updated in a repeated event in the global script ?

Crimson Wizard

#30
Unfortunately image does not load up for me, it sais "image is no longer available".
Without being able to see the screenshot I cannot really understand everything you are refering to, nor the purpose of those formulas.

Quote from: Imc7r on Thu 15/03/2018 20:47:40and btw the Y position of dynamic sprites or drawn images are taken from the top of the image, not the bottom
All Ys in AGS are taken from the top. When you call DrawImage the Y coordinate is an offset from the top of destination surface, and when you set Object.Y the Y coordinate is also offset from the top of the room.

But the alignment of the item around that coordinate may be different: when you are drawing, the X,Y are coordinates to which the top-left corner of the copied image will be aligned, but when you are placing an object, X,Y are coordinates to which the bottom-left of the object will be aligned.
Afaik this difference is there because drawing usually assumes flat surface, while objects placing in room traditionally relate to pseduo-3d space, where the bottom lines of sprites define position (hence - baseline property).

Quote from: Imc7r on Thu 15/03/2018 20:47:40
2) I see the BlockingHeight/Width property of objects but how can I detect the location of the trunk bottom or stone when the whole dynamic sprite is probably the whole screen while the stone or trunk area I want to block is part of it?

If possible (number of objects is not too large) I'd rather suggest to have 1 sprite per object or very close set of objects.
As mentioned above, the objects are placed aligned to their bottom. Their "Height" is actually going upwards from Object.Y. This means that if you cut the dynamic sprite at tree's baseline, then you will be able to have Object's Y at where tree trunk's should be. This will make it easier to set up blocking width and height. (You probably won't need to set BlockingHeight to full height of a tree, just a little to simulate tree's depth).

Alternatively, you will have to code your own walking restrictions, if not whole pathfinding, which I won't recommend to do without serious reason.

Quote from: Imc7r on Thu 15/03/2018 20:47:40
3) The stone in front of his face, perhaps the char.Baseline needs to be updated in a repeated event in the global script ?
By default char.Baseline is updated automatically, synchronized with character's Y. That is unless custom Baseline value was set.

Imc7r

#31
QuoteUnfortunately image does not load up for me, it sais "image is no longer available".


Hopefully working now.

QuoteAlternatively, you will have to code your own walking restrictions, if not whole pathfinding, which I won't recommend to do without serious reason.

I would not do this, yes. Coded blocking can provide some weird blocking but I need to block the bottom of trees, so the char cant step over.

QuoteIf possible (number of objects is not too large) I'd rather suggest to have 1 sprite per object or very close set of objects.

Yes im using only 8 objects that use all that randomize code per room and each object is using one dynamic sprite. Each object is whole screen transparent image and the dynamic sprites uses room.width and height, so they do not get shrunk or cut off, currently whole images display so it's fine.

I fixed part of 1) By adding a
Code: ags
if (Game.SpriteHeight[prop[i]] < 100){ object[i].Baseline = myChar.Baseline + 1; }

It tells the stones with that low height of sprite to always appear behind the char cause they are on the ground, else appear in front of his face when he walks through them. My question was if I have a tree crown (upper part of the tree) and a stone generated in front of the tree crown to use a condition 'If the stone is within the tree image, put it behind the tree) - same as appearing in front of the face but this code my set it behind any tree anyway, so that's fine.

But this where 3) comes in and yes his baseline is automatically updated though this is still seen, unless I need to base Baselines on other things not this code? So far it is the higher the object placed on the screen, the more behind it will appear. All bottom images appear in front of all and that's working but he still walks behind some upper images.
Code: ags
    object[i].Baseline = -1 * propY[i]; //propY[i] is the random generated Y position of the drawn dynamic sprite




and 2) is 
QuoteThis means that if you cut the dynamic sprite at tree's baseline, then you will be able to have Object's Y at where tree trunk's should be.

So if my image bottom is |___###___| where |___ and ___| are the alpha channel and ### is the trunk of a tree, im trying to make the unwalkable (it's OK if I have to calculate myself how many pixels of the beginning of the image, yes I will just block a small height above the tree say the bottom where it reaches the ground). Knowing that I calculate Y of object upward is good though it's more about how to detect the drawn part at the bottom of the image, should I just hard code for each image type how many pixels away?, like say |___# for each image is the distance.  )


Crimson Wizard

#32
Alright, sorry, but the issue I am having with this is that your formulas are way too confusing. I had a very hard time trying to understand the need for them.
In theory this all should be very simple to do, without need for weird conditions like "if (Game.SpriteHeight[prop[ i ]] < 100){ object[ i ].Baseline = myChar.Baseline + 1; }". Complex code like that is almost always a hint that logic is wrong.


EDIT: Erm... sorry, I just understood what you meant by doing that thing to stone. It's just that I was thinking about one problem, so I got confused by that.
Normally, for flat objects you can just set Baseline = 1, this way they will always be drawn behind characters.
But since you have stones and trees combined, that could be more complicated. In either case I don't recommend rely on character coordinates, because you may have more than 1 character in the room.


Now, your picture clearly indicates that you are setting wrong baselines for you tree objects.

QuoteSo far it is the higher the object placed on the screen, the more behind it will appear. All bottom images appear in front of all and that's working but he still walks behind some upper images.
This could mean that relation between generated objects' baselines may be correct, but in absolute room coordinates their baselines are wrong.

NOTE: to reply to comment about character's face and feet on the image. Whole character has the same baseline, its parts are not separate layers, so character is all behind the tree, so to say.


I'd suggest to focus on a single problem - object's baseline - and solve it first.
As I mentioned previously, normally you'd need to calculate the position of a tree trunk in the room and set that as a baseline.

Quote
object.Baseline = -1 * propY; //propY is the random generated Y position of the drawn dynamic sprite
Alright, but where in the room is this "propY"? Is it the Y coordinate you pass to DrawImage? If so, that's wrong, because that's a coordinate of a top of an image, while for the baseline you'd need coordinate of a bottom of an image in the room.

Crimson Wizard

#33
Ok, so I decided to make a small chart to help explaining what I mean. It displays a generic case, where you have an object in the room, and a picture (of tree) drawn on that object in random position:



The circles indicate the anchor position of X,Y the image has inside object's DynamicSprite, and X,Y the object has inside the room.

The red line is where tree's bottom is, and that is what you need to have as object's baseline. The baseline is a Y coordinate in room coordinate system.


The generic formula to calculate this baseline:

Code: ags

int baseline = object.Y - dynamicSpriteHeight + drawnImageY + drawnImageHeight;
//
// where:
// object.Y -- object's coordinate inside the room;
// dynamicSpriteHeight - the height of dynamic sprite you assign to an object;
// drawnImageY - the coordinate you draw tree sprite on object's dynamic sprite (this is coordinate in local dynamic sprite's coords!);
// drawnImageHeight - the height of that tree sprite.


To elaborate:
object.Y - dynamicSpriteHeight == this is object's top coordinate in the room.
above + drawnImageY == this is tree's top coordinate in the room.
above + drawnImageHeight == this is tree's bottom coordinate in the room.

Imc7r

#34
^ Ahh thanks! I got that the Dynamic sprs start increasing Y value from top to bottom while Object's coord system does that from below upward without the drawing above but it confirmed what I was thinking. I would not have got what was to be subtracted and added if it wasn't for you doing that. Now here is how my baseline code looks I just set it all without a baseline specific variable:

Code: ags
    object[i].Baseline = object[i].Y - Room.Height + propY[i] + Game.SpriteHeight[prop[i]];

Since it is all under (for each..i in 0...7 I use the [i)]. Room Height since  I do set the Dynamic sprite vars to room width and height.
Code: ags
EnvProp[i] = DynamicSprite.Create(Room.Width, Room.Height,  true);


It works as I tested few times because he was able to walk in front of the same tree when too below and when he goes up he appears behind the same tree. As I said, it was the formula that I needed and you provided that thanks for it.

This solves the 1) and 3) as he walks behind and in front of the same trees correctly.

The issue 2) was about detecting not just the baseline which you are doing with the formula object.Y - dynamicSpriteHeight + drawnImageY + drawnImageHeight; but detecting the area within image. Using the baseline you have the height location of the bottom of the image. What should the width be? The difficulty comes to me since I did in my code:
Code: ags
    EnvProp[i].Resize(propScale[i] + EnvProp[i].Width, propScale[i] + EnvProp[i].Height);

which gives me the scalings I wanted but this may affect the values for finding that particular area. It could be a rough estimation of part of the image width but has to be. This is needed in the future as well, since I could base interaction, dialogs and others based on locating the drawn pixels so to say (meaning the part that is not transparent and bottom). Rocks are smaller images and should be entirely blocked.



Now please take your time as I am OK if it is looked another time, sorry if you feel too engaged with my part, I appreciate it, im trying to do on my own where I can but this system is the more complex, as the rest I have to do might be more standard interactions and things I look from existing stuff.

Crimson Wizard

#35
Quote from: Imc7r on Fri 16/03/2018 21:30:32
^ Ahh thanks! I got that the Dynamic sprs start increasing Y value from top to bottom while Object's coord system does that from below upward without the drawing above but it confirmed what I was thinking.

I have to make a correction: object's coord system does not increase Y from below upward. In AGS all coordinate systems go from top to bottom.
It's just that objects put their image above its "origin" coordinate, aligning image's bottom to that origin. So, if you have object at room's (X,Y), the object sprite's top-left corner is at room's (X, Y - sprite height).

In other words, the direction of Y axis is still towards the bottom, but you may think that in the room the object's image is shifted by (-height) pixels.

Imc7r

Hi, what about detecting part if the image for blocking height/width like I posted above with the image, considering the transparent object ius the whole screen and I need a particular part blocked,  how can I calculate that?

Crimson Wizard

#37
Quote from: Imc7r on Fri 20/04/2018 20:05:37
Hi, what about detecting part if the image for blocking height/width like I posted above with the image, considering the transparent object ius the whole screen and I need a particular part blocked,  how can I calculate that?

The problem really is not only how to calculate it, but how to apply. Because you cannot define a blocking rectangle with all 4 points, only width and height, and blocking area will start always at object's (X,Y), so it cannot be covering whole room.

This is why I kept suggesting making smaller dynamic sprites, exactly enough to draw an object. That should not be too hard to do, you know original sprite size, and necessary scaling.

If you still insist on having very large dynamic sprites, you will have to draw an object aligned to its left-bottom corner, which corresponds to object's origin.

Imc7r

Quote from: Crimson Wizard on Fri 20/04/2018 20:30:00

This is why I kept suggesting making smaller dynamic sprites, exactly enough to draw an object. That should not be too hard to do, you know original sprite size, and necessary scaling.

If you still insist on having very large dynamic sprites, you will have to draw an object aligned to its left-bottom corner, which corresponds to object's origin.

I see but it will kind of mess the scalings and all stuff that are somewhat acceptable to the way I wanted, so I will have to keep the dynamic sprites as they are.  Even if I was to use smaller sprites, a trees trunk would always be part of the image so.. Speaking of your last sentence, i dont understand it. I dont mind specifying the different width and height for each of the dynamic sprite since they use several different sprites, so I can do if sprite is e.g rock, set blocking width to 20 and height, if sprite is rock 2, set them to 25, etc. I will play around to see, or do you mean making new objects on top of the ones with dynamic sprites (like new small box objects just to cover the same as the parts I want blocked)?

Crimson Wizard

Quote from: Imc7r on Fri 20/04/2018 23:22:11
Even if I was to use smaller sprites, a trees trunk would always be part of the image so..

Ohhh right, I did not realize that, sorry, this means you probably cannot do this with same object anyway.

Quote from: Imc7r on Fri 20/04/2018 23:22:11or do you mean making new objects on top of the ones with dynamic sprites (like new small box objects just to cover the same as the parts I want blocked)?

No, but now when you said this, I am beginning to think that's the only way, except for scripting custom blocking/pathfinding.

SMF spam blocked by CleanTalk