Sorry your browser is not supported!

You are using an outdated browser that does not support modern web technologies, in order to use this site please update to a new browser.

Browsers supported include Chrome, FireFox, Safari, Opera, Internet Explorer 10+ or Microsoft Edge.

AppGameKit Classic Chat / Best way to scroll in platformer?

Author
Message
Mmarzex
11
Years of Service
User Offline
Joined: 26th Feb 2013
Location:
Posted: 11th Mar 2013 22:20
So The game I am working on is a platformer. I have most of the mechanics done and now just need to actually make it that my map scrolls. So In tier 2 my initial idea was to anytime the player move use setViewOffset() and give it my spriteX as its parameter. When I do that it moves but is really jumpy and shaky. Is there a better way of scrolling the screen?
Digital Awakening
AGK Developer
21
Years of Service
User Offline
Joined: 27th Aug 2002
Location: Sweden
Posted: 11th Mar 2013 22:26
SetViewOffset is what you should use. There is something in your code that causes this. First off, you should use floats whenever you are dealing with anything that should move smoothly. And make sure you are only using world coordinates and not mixing in screen coordinates.


Demo 3 is out now!
Mmarzex
11
Years of Service
User Offline
Joined: 26th Feb 2013
Location:
Posted: 12th Mar 2013 01:40
Okay So if I use this line of code for it is it correct


Also I'm trying to have it that when the player moves to the right it scrolls. But when I use this code it doesn't work so well and the sprite get's left behind as it scrolls.
Digital Awakening
AGK Developer
21
Years of Service
User Offline
Joined: 27th Aug 2002
Location: Sweden
Posted: 12th Mar 2013 09:27
You do not have to convert the sprite's coordinates into world coordinates. Sprites use world coordinates by default. Also make sure that you DO NOT use FixSpriteToScreen on the player sprite. That makes a sprite stick to the screen and use screen coordinates.

If you have problems with something like this, my advice is to create a small test program. It is useful to make a program with as little code as possible to test things out. Without having any other code interfering.


Demo 3 is out now!
TrezSoft
AGK Tool Maker
11
Years of Service
User Offline
Joined: 8th Nov 2012
Location: UK
Posted: 12th Mar 2013 10:04
Take a look at this small 2d camera lib, its T1 but should give you the basic idea on how to get smooth player camera tracking in a platform game.

http://forum.thegamecreators.com/?m=forum_view&t=203532&b=41
Mmarzex
11
Years of Service
User Offline
Joined: 26th Feb 2013
Location:
Posted: 12th Mar 2013 14:40
I'm not fixing the sprite to the screen. What I am doing is whenever I press the right arrow it is suppose to scroll but instead it is just scrolling faster than the sprite so the sprite is always to the left of what can actually be seen now.
Digital Awakening
AGK Developer
21
Years of Service
User Offline
Joined: 27th Aug 2002
Location: Sweden
Posted: 12th Mar 2013 19:22
You want to set the offset to the left of the player. Use the player X position - half of the screen's width + half the width of the player sprite. This should put the player sprite in the center.


Demo 3 is out now!
Mmarzex
11
Years of Service
User Offline
Joined: 26th Feb 2013
Location:
Posted: 13th Mar 2013 05:03
That works Thanks! Is there a way to have it not scroll past a certain point?
Digital Awakening
AGK Developer
21
Years of Service
User Offline
Joined: 27th Aug 2002
Location: Sweden
Posted: 13th Mar 2013 08:33
Use an if statement to check if it's past a specific value and cap it. You should store the coordinate in a variable so you can easily modify and compare it. Then use it to offset the view at the end of your loop before you sync.


Demo 3 is out now!
Mmarzex
11
Years of Service
User Offline
Joined: 26th Feb 2013
Location:
Posted: 14th Mar 2013 01:40
Thanks For all your help! I just have one more question on it. I can't seem to figure this one out. Once I get past the boundary of my originally drawn background I can only move right but not left.
Digital Awakening
AGK Developer
21
Years of Service
User Offline
Joined: 27th Aug 2002
Location: Sweden
Posted: 14th Mar 2013 08:16
That description is not enough to go on. But somewhere in your code you are probably blocking user input or movement depending on x coordinates.


Demo 3 is out now!
Mmarzex
11
Years of Service
User Offline
Joined: 26th Feb 2013
Location:
Posted: 14th Mar 2013 13:52
Sorry. Here is my code for movement


if(agk::GetRawKeyState(65) == 1)
{
agk::SetSpritePhysicsImpulse(playerID, x, y, x -speed, y);
float mathStuff = agk::GetSpriteX(playerID) - (agk::GetVirtualWidth() / 2) + (agk::GetSpriteWidth(playerID) / 2);
agk::SetViewOffset(mathStuff, 0);
}
if(agk::GetRawKeyState(68) == 1)
{
agk::SetSpritePhysicsImpulse(playerID, x, y, x + speed, y);
float mathStuff = agk::GetSpriteX(playerID) - (agk::GetVirtualWidth() / 2) +(agk::GetSpriteWidth(playerID) / 2);
agk::SetViewOffset(mathStuff, 0);
std::cout << "Player X Velocity: " << agk::GetSpritePhysicsVelocityX(playerID) << std::endl << std::endl;
}

So I don't see why movement would stop once I go past the initial originally drawn section of the screen.
Digital Awakening
AGK Developer
21
Years of Service
User Offline
Joined: 27th Aug 2002
Location: Sweden
Posted: 14th Mar 2013 14:06
You are using the built in physics so I bet it's the built in screen boundaries. I'm on my phone so I can't look up the code for that. But if you can't find the command then perhaps someone else can find it before I Get home.


Demo 3 is out now!
Mmarzex
11
Years of Service
User Offline
Joined: 26th Feb 2013
Location:
Posted: 14th Mar 2013 14:40
I already have the physics walls turned off by default since I'm moving the view with setviewoffset though. Is it the way I'm finding how to set the offset when trying to go to the left?
Ancient Lady
Valued Member
20
Years of Service
User Offline
Joined: 17th Mar 2004
Location: Anchorage, Alaska, USA
Posted: 14th Mar 2013 15:52
Mmarzex, I would recommend pre-calculating the following and placing them in accessible variables for just a little faster performance, and make sure to use floats properly:


I also made the second 'if' an 'else if', since you shouldn't be pressing both keys at the same time. And I moved the output statement outside of the second 'if' statement so that it appears for either direction.

You might also want to use SetSpritePhysicsVelocity instead of SetSpritePhysicsImpulse. You get a more immediate reaction with velocity instead of impulse.

I'm not sure about whether you are calculating the offset correctly or not, I have not worked with this type of scroller yet.

But keep in mind that the actual position of the player sprite won't change in the same frame as when you apply the impulse. Its change will be apparent in the next frame after Sync() has been called to updated the physics.

Cheers,
Ancient Lady
AGK Community Tester and AppGameKit Master
Mmarzex
11
Years of Service
User Offline
Joined: 26th Feb 2013
Location:
Posted: 15th Mar 2013 06:10
I did your changes Ancient Lady. That does make more sense. There is still the issue of only being able to move right after passing past the original right boundary of the screen.
Ancient Lady
Valued Member
20
Years of Service
User Offline
Joined: 17th Mar 2004
Location: Anchorage, Alaska, USA
Posted: 15th Mar 2013 15:04
As I've said, I haven't tried this before.

Does the background move to the left (the player going right) at all?

Cheers,
Ancient Lady
AGK Community Tester and AppGameKit Master
Mmarzex
11
Years of Service
User Offline
Joined: 26th Feb 2013
Location:
Posted: 16th Mar 2013 01:50 Edited at: 16th Mar 2013 01:54
The background does not move. It is stationary. I will need to make it stretch the level which I plan to do . I don't understand how that would change or affect it moving it though.

I tried increasing the size of the background and it didn't do anything. I think it is somehow tied to the dimensions of the original window but I don't know why that would be.
Ancient Lady
Valued Member
20
Years of Service
User Offline
Joined: 17th Mar 2004
Location: Anchorage, Alaska, USA
Posted: 16th Mar 2013 04:09
Typically, if you are using ViewOffset, you are moving the background and leaving the player in place (making it look like the player is moving) and that is what your sample code has been doing.

And it is usually necessary to use more than one background image as a result (since you are limited to the actual size of most images). Many people use a series of tiles to build the background so that it extends past both sides.

Cheers,
Ancient Lady
AGK Community Tester and AppGameKit Master
Mmarzex
11
Years of Service
User Offline
Joined: 26th Feb 2013
Location:
Posted: 16th Mar 2013 04:17
How could I do that method then? I'm a little confused on why that would change anything. And how would I move enemies and computer controlled things if the basic principle is to not move the character. I guess I don't see how that works.
lilpissywilly
AGK Developer
13
Years of Service
User Offline
Joined: 10th Sep 2010
Location: Office Chair
Posted: 16th Mar 2013 09:26
Quote: "Typically, if you are using ViewOffset, you are moving the background and leaving the player in place (making it look like the player is moving) and that is what your sample code has been doing."


Isn't it the other way around?

The way I would do it is paste the background, preferably tiled if you want it big, and then change viewOffset to follow the player.

Which it looks like you've done earlier Mmarzex. Print player X while you trial so you can see if it does indeed not move left after you've passed the boundary of the background. Sounds odd

My hovercraft is full of eels
Mmarzex
11
Years of Service
User Offline
Joined: 26th Feb 2013
Location:
Posted: 16th Mar 2013 16:11 Edited at: 16th Mar 2013 16:13
I printed out the X coordinates and it moves left and right with in the original boundaries of the screen. But as soon as I try to move left outside that range it will not move left but it still increases going right.

When I go to the right a certain point it continues to take me to the right when I press left even. I am at a lose to this right now.
lilpissywilly
AGK Developer
13
Years of Service
User Offline
Joined: 10th Sep 2010
Location: Office Chair
Posted: 16th Mar 2013 18:25
Have you tried turning on "SetPhysicsDebugOn" to make sure nothing is in the way of your physics body?

My hovercraft is full of eels
Ancient Lady
Valued Member
20
Years of Service
User Offline
Joined: 17th Mar 2004
Location: Anchorage, Alaska, USA
Posted: 16th Mar 2013 18:25
Quote: "Isn't it the other way around?"

You are probably right. As I've said, I've not done this yet and am only going on what I've seen others post.

What I meant was that the player appears to be non-moving in the center of the display while the background is changing. The Player position is changing, but the use of view offset makes it look like it is sitting still within the display area.

Cheers,
Ancient Lady
AGK Community Tester and AppGameKit Master
lilpissywilly
AGK Developer
13
Years of Service
User Offline
Joined: 10th Sep 2010
Location: Office Chair
Posted: 16th Mar 2013 18:27
Quote: "What I meant was that the player appears to be non-moving in the center of the display while the background is changing. The Player position is changing, but the use of view offset makes it look like it is sitting still within the display area."


Yes that makes complete sense. Sorry I was nitpicking

My hovercraft is full of eels
Digital Awakening
AGK Developer
21
Years of Service
User Offline
Joined: 27th Aug 2002
Location: Sweden
Posted: 16th Mar 2013 18:28
The only solution I can see is that you create a new test project using the minimum amount of code. Like only a player sprite, only the controls and the setviewoffset command and turning off the walls. Then print the x value.


Demo 3 is out now!
Mmarzex
11
Years of Service
User Offline
Joined: 26th Feb 2013
Location:
Posted: 16th Mar 2013 23:45
I tried that too and once it gets to that certain point it will just move to the right even when I press left. Would it have something to do with how the offset is set? Also what command turns off walls? I thought they turn off when you use setViewOffSet
lilpissywilly
AGK Developer
13
Years of Service
User Offline
Joined: 10th Sep 2010
Location: Office Chair
Posted: 17th Mar 2013 08:41 Edited at: 17th Mar 2013 09:56
If you turn PhysicsDebugOn you would see potential walls.

You'll find the commands for walls in the help files by 2d physics

My hovercraft is full of eels
Digital Awakening
AGK Developer
21
Years of Service
User Offline
Joined: 27th Aug 2002
Location: Sweden
Posted: 17th Mar 2013 09:46
Quote: "If you change the view offset using SetViewOffset the walls will not move with it, they are fixed to the world, so they will be disabled automatically."


Had forgotten about that part. Post the code of your test project. You must be doing something wrong somewhere. Or nobody have tried doing this in tier 2.


Demo 3 is out now!
Mmarzex
11
Years of Service
User Offline
Joined: 26th Feb 2013
Location:
Posted: 17th Mar 2013 16:50
Here is my code for the test project.


The only I can think of that affects it must be how the offset is set but I don't see why.
lilpissywilly
AGK Developer
13
Years of Service
User Offline
Joined: 10th Sep 2010
Location: Office Chair
Posted: 17th Mar 2013 17:36
There's a couple of things I see that are a bit odd, maybe it won't fix your problem.

First of all (which might be your problem):
agk::SetSpritePhysicsImpulse(playerID, x, y, x -speed, y);

You correctly put ID, x and y. But "x - speed" and the other "y" is supposed to be vectors and don't need the coordinates of your sprite.
For example: ...impulse(playerID, x, y, -100, 0) would give your sprite an impulse force of 100 leftwards.
This would mean that if your players X is 1000 the impulse would be zero.

Secondly, when putting force on a sprite continuously like this the preferred method is setSpritePhysicsForce. Impulse is generally used in a one time hit, like say a jump. You can pull it off anyway of course.

Thirdly, you calculate "mathStuff" and apply it only when you press two different buttons. Which means if your ship is moved any other way than by the player using these buttons the camera won't follow.

I would put


at the end of the loop instead of in each IF statement.

And setSpritePhysicsVelocity(ID, 0, 0) will completely stop your sprite dead, which I of course assume you want. Which would mean that if your hold "d" to go right and then "w" to go up your sprite will stop when you let go of "w".

Just my 2 pennies innit

My hovercraft is full of eels
Mmarzex
11
Years of Service
User Offline
Joined: 26th Feb 2013
Location:
Posted: 17th Mar 2013 18:42
The player is only meant to move left and right and jump slightly in place so The way I'm doing it is the way it makes sense for the game logic. I will try making those parameters into vectors. I still am confused by all of this and why the walls would matter since aren't they disabled by default when you change the offset?
lilpissywilly
AGK Developer
13
Years of Service
User Offline
Joined: 10th Sep 2010
Location: Office Chair
Posted: 17th Mar 2013 18:47
The walls should be off yes. But I still urge you to turn "PhysicsDebugOn" on to see anything hidden that is physical.

To make them vectors just remove the "x" and "x +" in the third field in the impulse. You still need the "-" for going left, that's all.

My hovercraft is full of eels
Mmarzex
11
Years of Service
User Offline
Joined: 26th Feb 2013
Location:
Posted: 17th Mar 2013 19:24
Debug shows me nothing. There are no walls or anything that would be causing the problem.
Ancient Lady
Valued Member
20
Years of Service
User Offline
Joined: 17th Mar 2004
Location: Anchorage, Alaska, USA
Posted: 17th Mar 2013 19:42
I also see that you check for key 65 and 68 twice. The second check will change your sprite behavior, stopping it completely and wiping out any settings from the first time.

That might be your main problem.

Since you check for several keys, all but the first should be 'else if' to make sure you only trigger on one key at a time.

If the GetRawKeyLast command were to reset if no key pressed in a Sync cycle, you could use that value and a switch statement. Unfortunately, it will return the last key pressed even when nothing has been for a while.

Cheers,
Ancient Lady
AGK Community Tester and AppGameKit Master
Mmarzex
11
Years of Service
User Offline
Joined: 26th Feb 2013
Location:
Posted: 17th Mar 2013 19:52
They are called twice though so that the player stops. How else would I do that?
Ancient Lady
Valued Member
20
Years of Service
User Offline
Joined: 17th Mar 2004
Location: Anchorage, Alaska, USA
Posted: 17th Mar 2013 20:06
If you mean that the player is supposed to keep moving until the button is pressed again, then you use a toggle variable to indicate whether the player is moving. If not moving, then do the code that changes position. If moving then do the code that stops the player.

Cheers,
Ancient Lady
AGK Community Tester and AppGameKit Master
lilpissywilly
AGK Developer
13
Years of Service
User Offline
Joined: 10th Sep 2010
Location: Office Chair
Posted: 17th Mar 2013 21:09
I think he wants the player to stop dead as soon as no button is pushed.

Have you altered the impulses to remove "x" from the x-vector and still have the same problem?

I'll repeat:
That is the only thing I can see that would affect how your ship reacts to controls depending on where it is placed. You are using screen width and virtual resolution, so when you hit x = getSpriteX(playerID) = 1000-ish, depending on how wide the screen is you are testing on;
SetSpritePhysicsImpulse(playerID, x, y, x -speed, y);

would literally mean:
SetSpritePhysicsImpulse(playerID, x, y, 1000 -1000, y);
Which is no speed at all. Nada, zilch, zero

My hovercraft is full of eels
Ancient Lady
Valued Member
20
Years of Service
User Offline
Joined: 17th Mar 2004
Location: Anchorage, Alaska, USA
Posted: 17th Mar 2013 21:27 Edited at: 17th Mar 2013 22:04
Quote: "I think he wants the player to stop dead as soon as no button is pushed."

If that is the case, then after all the other 'else if's checking for specific keys, add a last 'else' that stops the player.

And I think you are probably onto the right problem with the value being used for the vector on the impulse.

EDIT: for some reason my next posts have not appeared. If, by some weird chance, my posts are being monitored, I apologize for the apparently double posts.

Cheers,
Ancient Lady
AGK Community Tester and AppGameKit Master
Mmarzex
11
Years of Service
User Offline
Joined: 26th Feb 2013
Location:
Posted: 17th Mar 2013 21:28
No the player stops as soon as the button releases which is what I thought I was doing.
Ancient Lady
Valued Member
20
Years of Service
User Offline
Joined: 17th Mar 2004
Location: Anchorage, Alaska, USA
Posted: 17th Mar 2013 21:46 Edited at: 17th Mar 2013 22:06
EDIT: deleted in favor of the other one that finally showed up.

Cheers,
Ancient Lady
AGK Community Tester and AppGameKit Master
Ancient Lady
Valued Member
20
Years of Service
User Offline
Joined: 17th Mar 2004
Location: Anchorage, Alaska, USA
Posted: 17th Mar 2013 22:03 Edited at: 17th Mar 2013 22:07
Rats! I just added a big post and it disappeared when I submitted it!

Try this code. I replaced the two calls to GetSpriteX when you move to just using the last x you retrieved. There will have been absolutely no movement since you called GetSpriteX at the top of the loop.



No matter how many things you do to a sprite, you won't see any changes until the Sync() is finished.

And you will speed up your overall performance by using global values for the the display and sprite widths used in your mathStuff calculations.

So, since you actually want to catch the changes made the previous frame, I moved your mathStuff calculation (using previously calculated values) and view offset to the top of the loop.

The combination of my changes removes up to four function calls, two divisions and one addition. Every little bit helps in making an app run smoother.

And, in Tier 2, user inputs (like key presses and tilts and such) are only checked once each app::Loop call, no matter how many Sync() calls you make.

So there is no point rechecking the position of a sprite (as you were in your outputs), that just takes up more processing time.

(I said this all much better the first time I typed it.)

Cheers,
Ancient Lady
AGK Community Tester and AppGameKit Master
Mmarzex
11
Years of Service
User Offline
Joined: 26th Feb 2013
Location:
Posted: 17th Mar 2013 22:53 Edited at: 17th Mar 2013 22:59
I don't understand how you make the impulse parameter a vector though. The parameter is meant to be a float.

I tried your code Ancient Lady but it still makes it that once it gets past a certain point the ship will only move to the right even when I press right.
lilpissywilly
AGK Developer
13
Years of Service
User Offline
Joined: 10th Sep 2010
Location: Office Chair
Posted: 17th Mar 2013 23:11 Edited at: 17th Mar 2013 23:25
Again,

Change:
agk::SetSpritePhysicsImpulse(playerID, x, y, x + speed, y);
agk::SetSpritePhysicsImpulse(playerID, x, y, x - speed, y);

Into:
agk::SetSpritePhysicsImpulse(playerID, x, y, speed, 0);
agk::SetSpritePhysicsImpulse(playerID, x, y, -speed, 0);

No more no less

I'm positive this is your problem. The other stuff is an issue of optimizing and making the code neat and upgrade-able, albeit a quite important one.

You could set a higher "setSpritePhysicsDamping" and your ship would stop fast if you put it high enough. This would require you to increase the force of which you move your ship for it to move like before, but you could remove all the setting velocity zero checks


Edited several times because I sounded way grumpy

My hovercraft is full of eels
Mmarzex
11
Years of Service
User Offline
Joined: 26th Feb 2013
Location:
Posted: 17th Mar 2013 23:58
Thanks that works finally. Thank you for your help so much. Now how would I scroll the background. I don't understand that exactly.
gsdblack
12
Years of Service
User Offline
Joined: 6th Dec 2011
Location:
Posted: 3rd Apr 2013 23:29
I know this may be a little off topic but from what I've read the game uses physics to move the player, and uses the player location to scroll.

What if you wanted the screen to continue to move even if the player runs into an object? How would you handle that? Think Mario levels where the screen can crush you.
lilpissywilly
AGK Developer
13
Years of Service
User Offline
Joined: 10th Sep 2010
Location: Office Chair
Posted: 4th Apr 2013 00:50 Edited at: 4th Apr 2013 00:53
just increase the x# value of the screen offset at a steady pace, if you want it like those mario levels.



My hovercraft is full of eels
gsdblack
12
Years of Service
User Offline
Joined: 6th Dec 2011
Location:
Posted: 4th Apr 2013 17:56
yeah but I want the screen to move as the same rate as the player. But player is being moved by physics and the screen by a float/percentage system. I will test this out when I get home from work.
lilpissywilly
AGK Developer
13
Years of Service
User Offline
Joined: 10th Sep 2010
Location: Office Chair
Posted: 4th Apr 2013 18:41 Edited at: 4th Apr 2013 18:41
Well then it's not like the super mario levels where you can get squashed, in those the screen moves at a set pace and you just follow it with the character.

So what I would suggest is something like having the screen move at a minimum rate, but also catch up if the player moves faster than this. I have something like this in a game that's on hold.

If you need code I could dig it up

My hovercraft is full of eels
gsdblack
12
Years of Service
User Offline
Joined: 6th Dec 2011
Location:
Posted: 15th Apr 2013 01:29
Thanks so much lilpissywilly it worked!!

Login to post a reply

Server time is: 2024-05-04 14:27:49
Your offset time is: 2024-05-04 14:27:49