Trying to implement physics from the Sonic Physics Guide... issue

Discussion in 'Fangaming Discussion' started by Travelsonic, Oct 6, 2013.

  1. Travelsonic

    Travelsonic

    Member
    819
    17
    18
    As the topic description says, I feel like a complete blooming idiot right now.

    For fun I wanted to see if I could implement the physics as describe in the physics guide in a Megadrive era Sonic engine of my own using C++.

    I made Sonic his own class. In the Sonic class, I have friction, max speed, acceleration, and deacceleration set up pre-defined [but not as constants, as underwater ALL OF these values are different if I recall correctly]. For movement, I have a function that takes in an integer representing the key pressed, allowing me to keep the class independent of the graphics/gaming libraries I am using for longer during testing.

    [Basically, the "if the player is pressing left," " if the player is pressing right" is now down to a switch statement based on the integer passed as an argument]

    The function then checks that code, and for left/right movement, handles it exactly like it was laid out in the guide for when Sonic is running on a flat surface:

    Only not pseudo code, of course, and with an additional condition where if the X speed is 0 then it adds [if moving right] or subtracts [if moving left] the acceleration, and if nothing is being pressed, the friction is applied appropriately.

    Now the problem.

    I wanted to test how, when implemented, how a change in X position would look [as opposed to just the X speed]. Like with the X speed being displayed on screen, I then made it so it also showed X position on screen, and I can't help but feel like I am doing something wrong, as the rate of change is absolutely insane.

    Ugh.
     
  2. SF94

    SF94

    Tech Member
    776
    3
    18
    Utah
    SA1/2 hax
    Is it running above 60FPS without delta timing? Maybe a stupid suggestion, but if it's running at like, 300 frames per second, you're applying those changes at a rate of once per frame (about every 3ms at 300FPS, for example) without delta timing, and as you could probably guess, that means everything applies too quickly.
     
  3. JustinTU

    JustinTU

    Member
    5
    0
    0
    Montgomery, Alabama
    SADE Engine (C++)
    Like Morph said, the values for the various properties of the player's movement are in terms of displacement per frame, so if your values are increasing or decreasing too fast, then you simply need to lock your frame rate or lock just the physics to a certain frame rate. There many ways to do it, some of which are inefficient and effect the smoothness of the gameplay. I would recommend taking a look at this guide (link). My own engine uses a modified version of the method described in that guide that works pretty well for me.
     
  4. Travelsonic

    Travelsonic

    Member
    819
    17
    18
    Told you I feel like a blooming idiot. The framerate... fuck me....

    For the time being, I merely moved the decimal point over one place for each variable's value [accel, deaccel, friction, etc] and that made things work beautifully until I can be arsed enough to do a better tweak should I actually need to do better as I will be busy as hell on my Android app development and whatever else thrown my way from working for my 'rents. :argh:
     
  5. winterhell

    winterhell

    Member
    1,165
    7
    18
    Can you just slap something like Sleep(14) for the time being? That'd stabilize your fps. Or activate vSync.
     
  6. Travelsonic

    Travelsonic

    Member
    819
    17
    18
    In the game loop I implemented some rest similar to what you, winterhell, suggested for the time being - works good now. :D

    [Don't lock thread, powers-that-be, as I may still have plenty of questions going into all this.]
     
  7. kazade

    kazade

    Member
    64
    0
    0
    A 2D Physics Engine
    In my engine I've multiplied each constant by 60 (e.g. the change per second) and then each update add the value multiplied by a delta time value. Seems to work great!
     
  8. Travelsonic

    Travelsonic

    Member
    819
    17
    18
    I'm glad this thread is not locked/is still on page 1.

    For shits and giggles purely, I decided to see if I could make this using only HTML5, javascript, and JQuery - no libraries for sound, graphics, or game physics.

    I have made it so Sonic's horizontal movement on flat surfaces works as it should. I also implemented jumping, falling, air drag, and variable jump height (ALL WITHOUT having to fudge the constants like with my last attempt at implementing this stuff :D ). I've also *sorta* implemented bumper collisions, though that still isn't quite right.

    Now I gotta figure out the best way to handle tiles.

    I've added, to my Sonic object, an array values, X and Y coordinate, representative of the positions of the sensors used in ground/wall collisions.

    What is tripping me up is the best way to actually represent each tile, handle going through and checking collisions with the tiles, as I wanna follow the SPG as closely as I can, including the use of the height masks, and feel in looking at what I have to do, I may be overthinking the hell out of what I need to do. >_<

    Maybe first I should figure out why my bumper objects are fubar.

    EDIT: Derrr, bumpers work now, so nevermind. XD
     
  9. winterhell

    winterhell

    Member
    1,165
    7
    18
    The classics use a heightmap for the collision tiles. 16 adjacent values for the height of the pixel columns. This is for vertical collision. There is also a similar horizontal heightmap. They both represent the exact same 16x16 collision mask. If you expand the heightmap to a regular 16x16 boolean collision array you'll be fine. It doesn't really matter which way you implement it, you won't be able to measure a performance difference no matter how hard you try. So just do itâ„¢
     
  10. Techokami

    Techokami

    For use only on NTSC Genesis systems Researcher
    1,336
    21
    18
    HoleNet!
    Sonic Worlds Next
    You could implement the collision mask as a 3D array; that is, an array of 2D arrays containing the boolean values for a 16x16 collision mask. Then you just use some division and the mod operator on the player's coordinates to figure out what tile the player is in; divide by chunk size to get the chunk position to pull from the level layout, which gives you the ID of the chunk, then mod by the chunk size, then divide by 16 to get the 16x16 tile in the chunk, which can be referenced from the chunk data, which gives you the 16x16 tile (and therefore the collision tile to reference), then mod by 16 to get the position in the tile to check.

    Well, that's how I would do it. There's probably a smarter way to do it, but I'm not sure what it would be. It'd probably help if someone could unroll the loops from the disassemblies or something.
     
  11. Travelsonic

    Travelsonic

    Member
    819
    17
    18
    Another dopey Q:
    This time, regarding bumpers:
    So basically, this is irrespective of his x velocity, or y velocity? So basically, he could collide with whatever combination of X/Y velocities, and this formula will not change at all?

    If so, time for me to look at my collision routine for the bumper, as something goes wrong. When I hit the bumper, it doesn't always bump me in the right direction, as in, hitting it from its right side works, but hitting it from its left side propels sonic in the same direction as if he hit it on the other side.

    EDIT: Yay, post 666. :D
     
  12. winterhell

    winterhell

    Member
    1,165
    7
    18
    It certainly looks that way.

    If you want to see if your values are correct you can print/log the character and bumper positions at the time of the collision and the calculated angle and new speed.

    I imagine to get the angle you are using Atan2 of the character and bumper positions, right?
     
  13. Travelsonic

    Travelsonic

    Member
    819
    17
    18
    Yes, measured from the middle of Sonic to the middle of the bumper, used atan2 to get the angle.

    EDIT: OK, so I got it working at last. A logic error in my collision function.

    Next question probably coming soon. :D :P
     
  14. Travelsonic

    Travelsonic

    Member
    819
    17
    18
    OK, next question: on ground speed, and angles:
    Question is, what values would I use to get the angle that I use in calculating the x speed, and y speed? Of course, I assume like with bumper collisions, I am gonna use atan2.
     
  15. Techokami

    Techokami

    For use only on NTSC Genesis systems Researcher
    1,336
    21
    18
    HoleNet!
    Sonic Worlds Next
    Angle data is... actually stored as part of the collision data. So instead of calculating the angle on the fly, it's done for you, and you just use a lookup table.
     
  16. Travelsonic

    Travelsonic

    Member
    819
    17
    18
    oh. duh... XD been brainfarting my way through this project, guess this is one more example of that. :P
     
  17. winterhell

    winterhell

    Member
    1,165
    7
    18
    The angle is the first and last value in the collision mask, for example FE. Its a number between 0 and 255. Then you convert it to radians.
     
  18. Travelsonic

    Travelsonic

    Member
    819
    17
    18
    Eh, rather than calculate it, just went into SonED, and looked at the collision arrays (and their respective angles), which will allow me to take an array of values and make a tile map before the level is initalized.

    Now I have a stupoid not-sonic-specific problem that is puzzling the hell out of me.

    In my Sonic entity, I have 12 values. 4 representing the X/Y of 2 ceiling sensors, 4 representing the X/Y of 2 horizontal / midline sensor bars, and 4 representing the X/Y of 2 floor sensors. (ceiling 1 X, ceiling 1 Y, ceiling 2 X, ceiling 2 Y, midline 1 X, midline 1 Y, midline 2 X, midline 2 Y, floor 1 X, floor 1 Y, floor 2 X, floor 2 Y, in that order)

    I have it in my collision function for my tile object so if the X and Y of either floor sensor is within the tile, Sonic is stopped. Problem is, I am missing something, since after walking on a couple of tiles, sonic sinks into and through the tile.

    Been trying to figure out how to remedy this, but to no avail. What would cause something like this, and what are some ideas that could help? >_< BTW: The tiles are 16x16, pretty much ensuring, I hope, that at least one sensor is in a tile.
     
  19. winterhell

    winterhell

    Member
    1,165
    7
    18
    To be sure, leave only the floor sensors. Are you able to record a log or gameplay video with values overlay? This would be the fastest way to determine what is going wrong.

    Also at first maybe try with just 1 floor sensor in the character center. If that works, then work with 2 and take whichever is higher.

    Wild guesses would be that you are getting below the recommended 16-20 pixel floor step, or most likely stepping on a FF tile and calculating its angle wrongly.
     
  20. Travelsonic

    Travelsonic

    Member
    819
    17
    18
    Seems my biggest issue might be with my collision functions, and transitioning from one mode to the other - and whether or not that is happening at the right time or not is perhaps one thing I need to look at so far as my issue, since Sonic's behavior **seems** to show a continuous changing between floor and air states even when one of the floor sensors is actually on the tile. Definitely got some investigating to do.


    Stupid Q #X I've also been confused about x position for sensor placement, since it seemed to me that this info, unlike Sonic's heights, and his Y position being where it is, X pos, width stuff seems absent. For now, I had just been using an X pos, and a width based on Sonic's sprite width to derive an X midpoint, and using that to derive horizontal placement of my sensors relative to Sonic/some horizontal midpoint, but am not sure if this is accurate, or contributing to my sensor collision woes.
    I feel stupid asking these Qs, though I really had made a shit tone of progress in implementing Sonic's physics - spikes, bumpers, springs, movement on a solid floor, jumping/falling, drowning, etc.

    Also had what is either a stroke of genius, or a stroke of derpitude:
    Sonic Sonic has slightly different constants for moving under water, versus on the ground, I decided to have 2 arrays.
    - one with his above-water movement constant values,
    - one with his under-water movement constant values

    I have a third, which holds the "current" set of constants, and whose values get applied to xSpeed/ySpeed (or gSpeed if on solid ground), and gets switched from one set to the other when Sonic enters or exits the water. I did this so I can just have functions with values being applied, instead of wasting time checking for if Sonic is either above, or under water, further adding to function complexity, if that makes any sense.