Adventure Game Studio

AGS Support => Advanced Technical Forum => Topic started by: LostTrainDude on Wed 07/12/2016 17:25:49

Title: How to get to a pixel-perfect destination using Character.Walk()?
Post by: LostTrainDude on Wed 07/12/2016 17:25:49
As per subject, I'm trying to make a character reach a very specific destination, before performing an animation.
This is the line I've been using:
Code (ags) Select
player.WalkStraight(object[0].X+(Game.SpriteWidth[object[0].Graphic]/2), player.y, eNoBlock);

The result is that most of the time the character gets a few pixels off the target. For instance: while that specific x is 733, the Character reaches 732 or 731.

I tried using both Character.Walk() and Character.WalkStraight(), also I originally had just object[0].X for the x parameter of the function. The results are the same.
Is this something strictly related to the way those function work? Is it because of the walking animation, perhaps?

It is probably worth mentioning that the object[0] is placed everytime right outside the players' Viewport (whether the player moves to the right or to the left) with the following code:
Code (ags) Select
function RandomItem()
{
    // Choose which item to place
    int r = Random(2);

    // Check if any item is already in the viewport
    // if NOT, put one
    if (!isItemInViewport())
    {
        // Make all the items different than r invisible
        for (int i = 0; i <= 2; i++)
        {
            if (i != r)
    {
                object[i].Transparency = 100;
    }
        }

// Check which direction is the player taking
if (player.DestinationX < player.x) // LEFT
{
    object[r].SetPosition(playerViewportEdgeLeft-Game.SpriteWidth[object[r].Graphic], 278); // Then move it right outside the viewport
    object[r].Transparency = 0;
}
else if (player.DestinationX > player.x) // RIGHT
{
    object[r].SetPosition(playerViewportEdgeRight+Game.SpriteWidth[object[r].Graphic], 278);
    object[r].Transparency = 0;
}
    }
}


Thanks in advance, everybody :)
Title: Re: How to get to a pixel-perfect destination using Character.Walk()?
Post by: Khris on Wed 07/12/2016 20:20:44
My guess is that the object is solid and thus cuts a rectangle out of the walkable area. So while AGS tries to get to the coordinates exactly (and usually succeeds) it can't. Try pressing Ctrl+A during the game to take a look.
Title: Re: How to get to a pixel-perfect destination using Character.Walk()?
Post by: LostTrainDude on Wed 07/12/2016 20:46:43
(http://i.imgur.com/N1nDzTz.gif)

I know that the walkable area is unnecessarily tall, but still... I'm not sure. The object appears below the player's walkable area (as it should be).

And, yes... I'm reverse-engineering Rags To Riches from the C64 (roll)
Title: Re: How to get to a pixel-perfect destination using Character.Walk()?
Post by: morganw on Wed 07/12/2016 21:06:14
I'm pretty sure it uses the character's speed to predetermine the distance it needs to move per frame, for the x and y directions. I think the offset you are seeing is probably because the speed is enforced so animation frames always look correct (rather than it snap the character to the destination at the end of the walk, at a speed that doesn't match the animation frames).

If you change the character speed to 1 pixel per frame, does it still miss the destination?
Title: Re: How to get to a pixel-perfect destination using Character.Walk()?
Post by: Khris on Wed 07/12/2016 21:20:01
I don't think this is a speed issue; afaik the character does indeed get moved to the exact destination at the end of the walk, provided the remaining distance is below the movement speed.

@LostTrainDude:
Try to use .Walk instead of .WalkStraight, and also try the eAnywhere option.
Title: Re: How to get to a pixel-perfect destination using Character.Walk()?
Post by: LostTrainDude on Wed 07/12/2016 21:25:31
Quote from: morganw on Wed 07/12/2016 21:06:14
If you change the character speed to 1 pixel per frame, does it still miss the destination?

I'm tracking the Character.X on screen and apparently it always walks 2 pixels at a time. Things I tried:

...Or is there another way to set it properly?

Quote from: Khris on Wed 07/12/2016 21:20:01
Try to use .Walk instead of .WalkStraight, and also try the eAnywhere option.

I tried that before but tried it again now. The same result, unfortunately.
I also tried making it an eBlock, instead. But no.
Title: Re: How to get to a pixel-perfect destination using Character.Walk()?
Post by: Cassiebsg on Wed 07/12/2016 22:06:42
Try checking General Settings->Use low-resolution co-ordinates in script-> false
Title: Re: How to get to a pixel-perfect destination using Character.Walk()?
Post by: LostTrainDude on Thu 08/12/2016 09:26:58
Quote from: Cassiebsg on Wed 07/12/2016 22:06:42
Try checking General Settings->Use low-resolution co-ordinates in script-> false

It was set to false already. I tried switching it to true but, as the disclaimer would say, it made all other coordinates go crazy (roll)
Title: Re: How to get to a pixel-perfect destination using Character.Walk()?
Post by: Crimson Wizard on Thu 08/12/2016 09:43:35
I do not have real ideas about what causes this at the moment, but I was thinking about workaround, what if you just force-move the character to the target destination when it is close to it? You could remember target coordinates yourself, or, if you are using AGS 3.4.0, there is Character.DestinationX and Character.DestinationY properties.

EDIT: btw, do you take image alignment into consideration? IIRC character's frames are centered at its position, which may make character look a bit "offset" if sprites are not fully symmetric.
Did you try displaying character's position on screen?
Title: Re: How to get to a pixel-perfect destination using Character.Walk()?
Post by: LostTrainDude on Thu 08/12/2016 10:52:47
(http://i.imgur.com/6jF1MEb.png)

Thankfully I did display them! It's the reason I found out what the problem was in the first place :)
Player X is a single pixel away from the Obiect[0] Mid position.
I also tried using the Object[0] X instead, but the results are the same.

This time, though, I also added the DestinationX and found out that when I click on the object it doesn't really send the character to the position I set up in the Character.Walk() function.
No matter where I click on the object, it always send it to a pixel away from the destination I'd like to send it.

It almost feels like it doesn't like odd numbers (laugh)

Quote from: Crimson Wizard on Thu 08/12/2016 09:43:35
EDIT: btw, do you take image alignment into consideration? IIRC character's frames are centered at its position, which may make character look a bit "offset" if sprites are not fully symmetric.

I had the feeling that characters' frames and sprites did not have the same "origin" point. If I understood correctly, characters have it in the center while objects at their left (that's why I'm calculating the character's destination to be the object.X + half of its sprite's length). Still, I'm not sure I have the logic needed to deal with the problem :(
Title: Re: How to get to a pixel-perfect destination using Character.Walk()?
Post by: Khris on Thu 08/12/2016 12:47:35
Wait, what is the basis for the Player Destination X value in the screenshot?
And what happens if you place the object at an even X coordinate?
Title: Re: How to get to a pixel-perfect destination using Character.Walk()?
Post by: Crimson Wizard on Thu 08/12/2016 12:49:51
Maybe this is a rounding mistake? either in script or pathfinder.
Title: Re: How to get to a pixel-perfect destination using Character.Walk()?
Post by: Snarky on Thu 08/12/2016 13:43:51
Isn't there a thing where the pathfinder only checks every third pixel to identify walkable areas? Could have something to do with that, maybe?

But if I understand correctly it's not working even if you're placing the character directly by setting the x/y coordinates? That really should always work: if positioning things with pixel accuracy doesn't work reliably then AGS has a serious problem.
Title: Re: How to get to a pixel-perfect destination using Character.Walk()?
Post by: Crimson Wizard on Thu 08/12/2016 13:47:59
Quote from: Snarky on Thu 08/12/2016 13:43:51
Isn't there a thing where the pathfinder only checks every third pixel to identify walkable areas? Could have something to do with that, maybe?
Yes it is something like that, but since LostTrainDude said that he tried eAnywhere flag before, I thought that should be something else.

BTW, what is game resolution?
Title: Re: How to get to a pixel-perfect destination using Character.Walk()?
Post by: LostTrainDude on Thu 08/12/2016 16:22:41
Quote from: Khris on Thu 08/12/2016 12:47:35
Wait, what is the basis for the Player Destination X value in the screenshot?

The displayed value is the one that the game sends when I click on the Object. It should get it from the player.Walk() function within the oBottle_Interact() one (which is the one I showed in the first post), but it always get it a pixel off.

But still, it works whenever I click somewhere on the screen. I noticed that wherever I click, the result is alwas an even number.

Quote from: Khris on Thu 08/12/2016 12:47:35
And what happens if you place the object at an even X coordinate?

I tried something simple (which may be wrong, of course):
Code (ags) Select
function oBottle_Interact()
{
    int p = object[0].X+(Game.SpriteWidth[object[0].Graphic]/2);
   
    if (p % 2 != 0)
    {
        p++;
    }
   
    player.Walk(p, player.y, eBlock, eAnywhere);
}


And, instead of adding 1, it adds 2 pixels :\

Quote from: Crimson Wizard on Thu 08/12/2016 13:47:59
BTW, what is game resolution?

As I'm currently just doing tests, it's a custom and temporary 608x304. Is it a problem?
Title: Re: How to get to a pixel-perfect destination using Character.Walk()?
Post by: LostTrainDude on Sat 10/12/2016 09:42:01
Of course the easiest workaround for me is to simply check whether the player walks in a position that is between the object origin and its center.
This puts a patch on the problem and basically solves it, but I don't know... Is this an AGS bug to report, anyway?

Thanks everybody for your help, up to now :)
Title: Re: How to get to a pixel-perfect destination using Character.Walk()?
Post by: Gurok on Wed 14/12/2016 00:32:04
Quote from: LostTrainDude on Thu 08/12/2016 09:26:58
Quote from: Cassiebsg on Wed 07/12/2016 22:06:42
Try checking General Settings->Use low-resolution co-ordinates in script-> false

It was set to false already. I tried switching it to true but, as the disclaimer would say, it made all other coordinates go crazy (roll)

You say it made all other coordinates go crazy. Aside from that, did it fix the problem? Were you able to achieve precise positioning with high-resolution coordinates?
Title: Re: How to get to a pixel-perfect destination using Character.Walk()?
Post by: LostTrainDude on Wed 14/12/2016 09:30:57
Quote from: Gurok on Wed 14/12/2016 00:32:04
You say it made all other coordinates go crazy. Aside from that, did it fix the problem? Were you able to achieve precise positioning with high-resolution coordinates?

You're right. I didn't really try.

I disabled all the scripts that involved object placement and manually placed an object on the screen. Displaying the Object.X, its "center" (object[a].X+(Game.SpriteWidth[object[a].Graphic]/2) and player.DestinationX I can tell it seems to work as I originally intended.

Now I wonder more about this setting, though. Is it best to enable it before doing anything else in the game, maybe?
I'm not sure if there is any specific "conversion" I should make in terms of XY coordinates in my scripts in order to make them work properly. Most rely on variables such as player.X+arbitrary_value_I_choose.

Is there anything that I can read about it?

Thanks for the heads up, Gurok!
Title: Re: How to get to a pixel-perfect destination using Character.Walk()?
Post by: Crimson Wizard on Wed 14/12/2016 09:57:59
IIRC enabling "Use low-resolution co-ordinates in script" makes your game use 320x200 coordinate grid regardless of your resolution. That means that precision of script commands will lower down. You won't be able to order any random coordinate anymore by script command, only coordinates inside 320x200 rectangle, which will be remapped to your WxH game by rough multiplication.

For example, if you have 640x400 game, "Use low-resolution co-ordinates in script" is enabled, and you do "player.Walk(100,100)" - that will result in character walking to (200,200) in reality instead.
On other hand, you won't make it walk to real (201,201) coordinates. (100,100) => (200,200), but (101,101) => (202,202). So the number of possible points you can set object position on screen is reduced.

Frankly I see no point in enabling this option. It was provided for backwards compatibility only, that is when you are loading very old project in newer version of AGS.


That said, it could maybe explain what is happening with your game if that option was enabled. But above you said it was false...

I think we need a proper test case, like a small game project with matching settings that lets you reproduce the problem. Ideally we would test your actual project, if you think it is okay to share it.
Title: Re: How to get to a pixel-perfect destination using Character.Walk()?
Post by: Gurok on Wed 14/12/2016 11:23:35
Sorry, I must have misread the text initially. Yeah, I don't recommend enabling "Use low-resolution co-ordinates in script" either. I somehow read that as you had set it to True and wanted you to try turning it off. That's what everything you describe is pointing to.

Anyway, it is very strange if you're experiencing things otherwise and I agree with CW about the test case.
Title: Re: How to get to a pixel-perfect destination using Character.Walk()?
Post by: LostTrainDude on Wed 14/12/2016 12:30:07
Please do :) Here is the whole thing (https://www.dropbox.com/s/fuo6ko27as7mqmp/20161214_rAGS-src.zip?dl=1) in a comfy zip format (laugh)

I called it rAGS because it made sense :P Of course nothing is final, as the background is one huge placeholder pasted from the original game.
It may be easy to get confused by which are actual objects and which are just part of the background, but if you look at them closely you find out that actual objects are uncompressed and better defined.

Also, I apologize in advance for the messy, spaghetti, useless or incomprehensible code you may find! Let me know if I you need anything!