The player falls through the floor

Started by Blondbraid, Fri 06/05/2016 11:10:23

Previous topic - Next topic

Blondbraid

Hi everybody!
A while ago I had some difficulty making a room with two walkable areas and hotspots for the player to interact with, but managed to solve it (with quite a lot of help! ;) ) (here is a link: http://www.adventuregamestudio.co.uk/forums/index.php?topic=52893.msg636525341#msg636525341).
Anyway, this room has two floors, and the player can interact with two hotspots on the top floor (walkable area 2), a piano and a wall-cupboard. The wall-cupboar works as it should (the player walks to the hotspot, does an interaction and then remains where he walked when the player regains control), but when the player uses the piano, at first the script performs the actions, but immediately afterwards the player falls through the floor to the walkable area below (walkable area 1). I don't understand what I've missed...
Here is the part of the script when the player clicks on the piano:
Code: ags
function hpiano_Interact() //using the piano
{
  int someObjectWalkableArea = 2;
  int playerWalkableArea = GetWalkableAreaAt(player.x - GetViewportX(), player.y - GetViewportY());
  if(playerWalkableArea != someObjectWalkableArea) {
     region[1].Enabled = false;
     region[2].Enabled = false;
    player.Walk(322,462,eBlock);
player.Move(598, 225, eBlock, eAnywhere);
SetWalkBehindBase(2, 1);
     region[1].Enabled = true;
     region[2].Enabled = true;
  }
if (player.HasInventory(iwire))
{
  player.Walk(283, 215, eBlock, eWalkableAreas);
  player.FaceLocation(207, 156);
cspotter.LockView(16);
cspotter.Animate(cspotter.Loop, 5, eOnce);
cspotter.UnlockView();
aPiano_A0.Play(eAudioPriorityHigh, eOnce);
player.x = 283;
player.y = 215;
}
else
{
  if (player.HasInventory(ihairoil)) {
    player.Say("I don't think I need any more piano-wires at the moment.");
  }
  else {
  player.Walk(283, 215, eBlock, eWalkableAreas);
player.FaceLocation(207, 156);
cspotter.LockView(16);
cspotter.Animate(cspotter.Loop, 5, eOnce);
cspotter.UnlockView();
player.Say("I'll just take one of the piano-wires.");
player.AddInventory(iwire);
}
}
}

(The script name I used for the player character is cspotter)


Snarky

Maybe I'm just in a bad mood, but I get a little depressed looking at this code. I see that I failed to get key points across in the earlier thread, notably the idea of abstraction and reusability by putting boilerplate code in helper functions. And please, for your own sake, learn to indent properly.

I'm pretty sure the immediate problem here is that you're disabling regions rather than walkable areas. But the logic is wonky in the first place. You're disabling both of them just for while the character is walking over, and then restoring both of them? Why. So, yeah...

Blondbraid

Quote from: Snarky on Fri 06/05/2016 21:18:57
Maybe I'm just in a bad mood, but I get a little depressed looking at this code. I see that I failed to get key points across in the earlier thread, notably the idea of abstraction and reusability by putting boilerplate code in helper functions. And please, for your own sake, learn to indent properly.

I'm pretty sure the immediate problem here is that you're disabling regions rather than walkable areas. But the logic is wonky in the first place. You're disabling both of them just for while the character is walking over, and then restoring both of them? Why. So, yeah...
I'm sad to hear this, all I can say is that I had no previous experience with coding when I started on this project, and in retrospect I now see how poorly planned much of my code is...

When it comes to disabling regions, the layout of the room meant that the player would move from the first region to the second region and then stop a little bit to the side of the second region.
I disabled them so that the player wouldn't trigger the second region and get stuck in a loop moving to and forth between the two regions, and then re-enabled them afterwards so that the player could return using the same route in reverse.
It seemed like a good idea at the time. :(

The code works in the sense that it does what I wanted it to do in the game, and the other of the two hotspots doesn't make the player fall through the floor. I don't understand why, for the code is almost the same apart from the coordinates and the words the character say.


Cassiebsg

In that case, I would say "check that you have the correct coordinates". Just in case you haven't found this yet, you can use the middle mouse button to grab coordinates from the room in the editor. ;)
Or if you have any event in like rep_exe that would move your character to other coordinates once you done with that.
When in doubt add display text along your code to help you figure out exactly where it's failing. (it's a great way for self-debugging).
There are those who believe that life here began out there...

Blondbraid

Quote from: Cassiebsg on Sat 07/05/2016 00:05:40
In that case, I would say "check that you have the correct coordinates". Just in case you haven't found this yet, you can use the middle mouse button to grab coordinates from the room in the editor. ;)
Or if you have any event in like rep_exe that would move your character to other coordinates once you done with that.
When in doubt add display text along your code to help you figure out exactly where it's failing. (it's a great way for self-debugging).
Thanks for the tip, I didn't know about the middle mouse button! ;-D
Anyway, I double checked to make sure that the coordinates were on an walkable area, and the player is standing on a walkable area when he falls through the floor.
I tried going by your tip with the display command, and the problem is that the character falls when the script ends, so even if I try to move the character to other coordinates, he still falls once he's moved there.


Snarky

Yes, I was in a lousy mood last night. Sorry.

I do think it would be much easier for you to debug the code if:

-You moved all the moving-between-floors stuff into a separate function, so that you were guaranteed to be using the same code for every different interaction.
-Instead of putting "magic numbers" throughout your code, you gave the coordinates you need to use meaningful names (using #defines or variable definitions), so you could more easily see what you were doing.
-You would indent consistently, so it'd be immediately apparent under what conditions each line of code runs.

I'd also like to know what you mean by "fall through the floor". AGS doesn't have any sense of gravity built in, so nothing like that ought to happen. Does the character jump from one position to another, or seemingly walk, or move in a straight line without animation, or what?

The most obvious explanations for how this could happen are:
1. The second floor (or some coordinate you're putting the character on) is not a valid and enabled walkable area, and somehow you're calling PlaceOnWalkableArea().
2. Somehow you're calling a Walk() or Move() (with eAnywhere parameter) to a position on the first floor. (Possibly because the coordinate the character is standing on is inside the teleportation region?)

Each of these would give a different "falling" effect, so with a more precise description of what happens it will be easier to work out why.

Blondbraid

#6
Anyone can have a bad day, no harm done!

When I say "fall through the floor", what I think happens is that the character moves to the nearest part of the first walkable area, but in the game it looks like he sinks through the floor and lands on the floor below.
Since I haven't used PlaceOnWalkableArea() I think your second explanation is more likely, but I'm not sure.

The strange part is that I have another hotspot in the second walkable area, and I use just the same commands with the only difference being the coordinates and the words the player say, but he doesn't fall or move when the script for that hotspot ends.
I don't understand how it can work on one hotspot and not the other.

I also noticed that the player doesn't fall if I use the other hotspot first and then click on the piano.

Edit: I noticed that the player is moved to the same coordinates like the second region moves him to, but I made sure to have it disabled when the player moved across it for the interaction with the piano.


Joe

After doing everything Snarky said, if the problem persists, you could upload a minimal version of the game to reproduce the issue.
Copinstar © Oficial Site

Cassiebsg

Also make sure you check the function that runs after the interaction is over. If the problem is happening at the end of it, then the problem might be "what runs next" instead.
There are those who believe that life here began out there...

Haggis

#9
Can you post the code related to the other hotspot?

What regions does the player walk through to interact with hotspot 1 and separately hotspot 2? Do the regions have any associated code e.g.walks off, walks onto, while on? How do the regions map to the walkable areas?

Blondbraid

Here is the code for the other hotspot(a cupboard on the wall):
Code: ags
function hwallcupboard_Interact()
{
  int someObjectWalkableArea = 2;
  int playerWalkableArea = GetWalkableAreaAt(player.x - GetViewportX(), player.y - GetViewportY());
  if(playerWalkableArea != someObjectWalkableArea) {
region[1].Enabled = false;
region[2].Enabled = false;
player.Walk(322,462,eBlock);
player.Move(598, 225, eBlock, eAnywhere);
SetWalkBehindBase(2, 1);
region[1].Enabled = true;
region[2].Enabled = true;
  }
if (player.HasInventory(ihairoil)) {
player.Say("I don't need personal grooming items some stranger left behind!");
}
else {
player.Walk(749, 219, eBlock, eWalkableAreas);
player.FaceLocation(746, 76);
cspotter.LockView(16);
cspotter.Animate(cspotter.Loop, 5, eOnce);
cspotter.UnlockView();
player.Say("Locked! Whatever is in there must be either very valuable or very embarrasing.");
player.Say(" Either way, I want it!");
}
}

The player crosses both the first and the second region on his way to the hotspot, I can show the code for them too here:
Code: ags
function region1_WalksOnto()
{
player.Move(598, 225, eBlock, eAnywhere);
SetWalkBehindBase(2, 1);
}

function region2_WalksOnto()
{
SetWalkBehindBase(2, 469);
player.Move(305, 463, eBlock, eAnywhere);
}

I just don't understand why this code works and the other doesn't...


Haggis

Thanks - and, across all the functions provided, do any of the 'move anywhere' commands == the coordinates the player is being incorrectly moved to?

My only question at the moment (and i'm not a very good coder so this might be a silly question) is why do you subtract the viewport x/y at the start to determine the walkable area the player is on rather than just use the player x/y coordinates?

Blondbraid

Quote from: Haggis on Sat 07/05/2016 11:56:30
My only question at the moment (and i'm not a very good coder so this might be a silly question) is why do you subtract the viewport x/y at the start to determine the walkable area the player is on rather than just use the player x/y coordinates?
I wanted to determine which walkable area the character was on, rather than determine their coordinates.
I'm not good at coding and working on my project meant doing many new unfamiliar things at the same time.


Haggis

#13
I can completely relate to that - it will make it all the sweeter when it's all done and working.

Anyway, I only ask as I would have thought it might give an incorrect answer?

E.g. you want the walkable area the player is standing on, so you get the players x/y coordinates and check if that's on a walkable area. By subtracting the viewport x/y (assuming either is greater than 0) the location you're checking isn't actually where the player is standing. The greater the viewport values the greater the impact on the output. Not sure how well I explained that - and there might be a completely valid reason for doing it like that which i'm not seeing. Someone with more experience might be able to confirm if i'm being a dunce or not - maybe the GetViewport x/y values are always 0 and not the room x/y values for where it's positioned?

How about the move functions - do any of them equal where the player is being incorrectly moved to?

Cassiebsg

here's an idea to try and debug it with the code you currently have.

locate the first move anywhere, and comment it out with //
test the game and see what happens, then go back delete the // and locate the next line and comment it out, test it. Maybe you if you can find the line that is "making your character fall off" then you can figure out where the error is.

Alternative, add a test display to all the functions... like Display("executing: region2_WalksOnto"); etc

Or just wait for the big brains to figure it out. (laugh)
There are those who believe that life here began out there...

Blondbraid

I did follow your advice with the //, and now I think I have come up with a solution.
I think the problem was that the second region was accidentally triggered somehow, but by changing the code, so that instead of enabling the region again directly after the player moved, I only re-enabled the region at the very end of the script.

This means that the player no longer falls through the floor!
I think I noticed why it worked in one hotspot and not the other too, It seems like the character walked over the region on his way towards the piano hotspot, but since the other hotspot was in a different direction he didn't walk over it on his way there.

If nothing else this ordeal has really taught me the importance of layout. :-[

I don't see any more bugs in the game for now, and I want to thank you all for your help!


Haggis

Excellent news! Look forward to playing it! :-D

Cassiebsg

Happy that you manged to get it working! :-D
Looking forward to play the game soon.

Maybe time for Beta testing before releasing it?
There are those who believe that life here began out there...

Blondbraid

Quote from: Haggis on Sun 08/05/2016 09:29:07
Excellent news! Look forward to playing it! :-D
Quote from: Cassiebsg on Sun 08/05/2016 09:51:28
Looking forward to play the game soon.
I'm happy to hear this!
And now that all the bugs are gone, I might release the game very soon, keep an eye out in the AGS games in production page!


SMF spam blocked by CleanTalk