📜 ⬆️ ⬇️

Review of physics in Sonic games. Part 1: hard tiles

image

From the translator : this post is a translation of one of the parts of the large-scale physics review (Sonic Physics Guide) in the Sonic the Hedgehog games for Sega Genesis / Mega Drive and Sonic CD . The following sections deal with such topics: running, jumping, spinning, loss of rings, underwater behavior, super speed, special features, camera, animations, and some others. Since there are a lot of parts ( 14 pieces ), I added a poll at the end of the post. Is it worth it to continue - you decide.

Links to other parts of the series:
Part 2: Running
Parts 3 and 4: Jumping and Spinning
Parts 5 and 6: the loss of rings and being under water
Parts 7 and 8: springs and gizmos, super speeds


')
Note

The article describes the collisions and interactions of Sonic with solid tiles. Solid objects, such as monitors, moving platforms and blocks, have their own procedures for handling collisions with Sonic, which do not necessarily coincide with the behavior of solid tiles.

Introduction

What are hard tiles? In the zones (levels) of which Sonic games consist, there are a lot of solid objects, so the zone would require too much memory if the environment were entirely made up of solid objects, each of which occupies 64 bytes of RAM. A smart move was made - the zone is created from tiles, so all that is required is to know whether the tile is solid (impenetrable) or not.

You may know that the zones are divided into blocks of 128x128 pixels (or 256x256 pixels in Sonic 1 and Sonic CD ), which, in turn, are divided into tiles of 16x16 pixels; they are also broken into smaller tiles of 8x8 pixels. All the magic of processing solid elements occurs at a 16x16 tile level, so in this review we will be interested only in them.

Sonic's interactions and collisions with these hard tiles form the basic game engine. They define the way to work with floors, walls, ceilings, ramps and hinges. Since this is a voluminous and complex topic, my review will be different from other manuals on the physics of Sonic games, but I will try to limit the reasoning to a minimum.

Standing

image

If we take the position of the earth on the Y axis equal to 736 ($ 02E0), then Sonic is standing above it in the coordinate 716 ($ 02CC). This is 20 pixels above ground level.

Pushing

Sonic should stop when hitting the wall. This can be achieved by checking the line collision. The collider line ( from the translator: here and further in the article the term sensor is used, I chose, I think, an adequate analogue ) should not be in its position on the Y axis, but slightly lower, otherwise it “will not notice” short steps. She also can not be too low, otherwise she will "notice" the slopes and curves, from which Sonic should not make a start. Its location in the Y + 4 coordinate from the location of Sonic is sufficient, because usually there are no stairs below 16 pixels in height (when there are such stairs, they consist of solid objects, and not tiles).

How wide should the collider line be?

image

If we take the X coordinate of the left side of the wall to be 704 ($ 02C0), then Sonic should not be closer than 693 ($ 02B5). If we take the X coordinate of the right side of the wall to be 831 ($ 033F), then Sonic should not be closer than 842 ($ 034A). This is an 11 pixel difference in both directions.

Therefore, the line of the collider must have a width of 20 pixels, and be stretched from X-10 to X + 10 of Sonic. Every time a hard tile is detected, Sonic should be “pushed out” by setting the coordinate of the tile minus (or plus) 11, and the speed of movement along the ground should be reset. (It cannot be pushed out only 10 pixels, otherwise the point with coordinates X + 10 will still be inside the border pixel of the tile. A permanent collision will be registered and it will stick to the wall.)

Since the border of the tile minus the position of Sonic should be 11, there are only 10 free pixels between the center of Sonic and the border of the tile. The eleventh pixel from Sonic will be the very border of the tile. Therefore, Sonic actually has a width of 20 pixels.

The fall

Sonic should be able to run off the pads. He cannot act like a coyote from Wile E. Coyote from cartoons, not noticing that there is nothing under him.



This means that Sonic must also check for hard tiles below him. This can be achieved by adding two more lines of colliders directed downwards. One (A) should be on the left side of Sonic, at coordinate X-9. The other (B) is on the right side, at X + 9. They must begin with its position along the Y axis and descend not less than 16 pixels below its feet at ground level, which is located in Y + 20 (but not too low, or it will fall off when descending from low steps or stairs, we would not want to).

If colliders A and B do not detect solid tiles, Sonic "falls" - a flag is set, informing the engine that it is in the air.

We remember that when faced with walls Sonic has a width of 20 pixels. However, earth detection colliders are only 18 pixels from the center. It turns out that Sonic is “thinner” by 2 pixels when running down from the pads than when hitting the walls.

Edge balancing

Good detail - Sonic goes into the balancing animation, being close to the edge of the pad. This happens only when he has stopped (his speed on the ground is 0).

How does the engine know about this? It's simple - at the moment when only one of the colliders is active, the Sonic is on the edge. If A is active and B is not, then the pad is to the right of it. Otherwise the playground is on the left.

However, if Sonic starts to balance, as soon as one of the colliders finds anything, he will start balancing “early” and it will look silly. Therefore, this happens when only one collider is active, and its position along the X axis is greater than the boundary of the solid tile detected by the active collider.



If we accept the coordinate of the right edge of the pad equal to 2655 ($ 0A5F), Sonic will begin to balance only at 2656 ($ 0A60). It will fall at point 2665 ($ 0A69) when both colliders detect nothing.

In Sonic 2 and Sonic CD, if the pad is in the opposite direction from Sonic's view, then the second animation of balancing is turned on.

In Sonic 2 , Sonic 3 and Sonic & Knuckles, Sonic has a third balancing animation when he is even closer to the edge of the court. Given the values ​​set above, it turns on when it is at coordinate 2662 ($ 0A66).

Note: while balancing, some possibilities are not available (pressing to the ground, looking up, rotating, etc.). In Sonic 3 & Knuckles, a player can snuggle up to the ground and rotate (but not look up) when balancing on the ground, but not when balancing on an object.

Ramps and curves

Sonic the Hedgehog was one of the first games to use curved surfaces and loops with a 360-degree turn. In most games of that era, the environment was completely created from blocks (and sometimes from the slopes).

The ability to work with smoothly changing shape objects is one of the fundamental aspects of the novelty and attractiveness of Sonic games. Unfortunately, this is probably the most difficult aspect to recreate in fan games.

How does it work?

Height masks

Each time Collider A or B detects a solid tile, they return the height of that tile.

How is the height of the tile?

Each tile has an associated value associated with a mask stored in memory. A mask is a simple array of 16 heights ranging from 0 ($ 00) to 16 ($ 10) and angle values.



For example, this height mask has an array of heights 0 0 1 2 2 3 4 5 5 6 6 7 8 9 9 and an angle of 232 ($ 00 00 01 02 02 03 04 05 05 06 06 07 07 09 09 09 and an angle of $ E8).

What is the value of the array of heights? Subtract the position of the X tile from the position X of the collider. The result will be the height index used by the array.

If the height value found is 16 ($ 10), then the collider must check another tile higher than the first one found, and determine its height value.

Whichever collider finds the greatest height, the Sonic Y coordinate is set equal to this height minus 20 pixels. Its angle is also set to the angle of the solid tile that returned the greatest height.

If the collider does not detect a solid tile, the leg level is returned by default (Y + 20).

Errors when using this method

Unfortunately, due to the use of this method in the original engine there are a couple of annoying bugs.

If Sonic is standing on an inclined platform, one of the colliders will not detect the tile, and will return the height of the legs. This leads to the fact that Sonic is in the wrong position.



Sonic rises with Collider B when moving to the right. When B “falls” off the landing, Sonic defaults to the level of collider A. Then he rises along with collider A as he continues to move to the right. Therefore, he will first rise, fall and rise again when running down from the platform.

There are only a few areas in which this is noticeable, but such a bug is present in all parts of the game for Genesis / Mega Drive, and it looks rather sloppy.

The second bug occurs when there are two tiles of opposite slopes of one above the other, such as low hills at the levels of the Green Hill Zone and Marble Zone .



Collider B begins to descend from the slope to the right, but Sonic still by default focuses on the level of the previous slope detected by collider A. Since such slopes are rather low, this results in lowering Sonic in the middle by about 1 pixel.

But that is not all. Sonic gets the angle data from the highest located collider, so even if it looks like he should be at the angle of the slope to the right (because he is closer to him), he will still have the angle of the slope to the left. When jumping, he will jump at this angle, moving backwards, not forward, as expected.

Moving at angles

All this is very good and wonderful - Sonic moves smoothly over the surface with different heights. However, the engine needs to do something else. To be realistic, Sonic's speed should decrease on angled surfaces.

There are two ways in which angles can affect the speed of Sonic. The first one ensures that it does not run over a hill in the same time as on flat land of the same width. The second slows it down when moving up the hill and speeds it up when moving down. Let's look at each of them in turn.

Three variable speeds

If Sonic were a normal platformer using only blocks, he would need only two variable speeds: movement along the X axis ( Xsp ) and along the Y axis ( Ysp ), the horizontal and vertical components of the speed of Sonic. Acceleration ( acc ), deceleration ( dec ) and friction ( frc ) are added to Xsp ; jump speed ( jmp ) and gravity ( grv ) are added to Ysp (when Sonic is in the air).

However, when using slopes, when Sonic moves along the slope, it simultaneously moves horizontally and vertically. This means that both Xsp and Ysp have nonzero values. Simply adding acc , dec or frc to Xsp no longer works; Imagine that Sonic is trying to run up the wall - adding to the horizontal speed will be useless, because he is trying to move up.

The trick is to use the third variable speed (as the original engine does), let's call it the speed of movement on the ground ( Gsp ). This is Sonic's speed along the ground, regardless of the angle. The values acc , dec and frc are added to Gsp , not to Xsp or Ysp .

When on the ground, Xsp and Ysp are extracted from Gsp at each step before moving Sonic. I think an example in pseudocode would be appropriate here:

Xsp = Gsp*cos(angle); Ysp = Gsp*-sin(angle); X += Xsp; Y += Ysp; 

Regardless of the change in the angle, the speed of Gsp is preserved, so the engine always knows with what speed Sonic is “truly” moving.

Scat coefficient

Now Sonic can handle the interaction with any hills, keeping the exact speed. However, it still needs to slow down when climbing and accelerate while descending.

Fortunately, this is easily achieved by using the concept of a ramp coefficient ( slp ). We simply add slp * sin ( angle ) to Gsp at the beginning of each step. The value of slp when running is always equal to 0.125 ($ 0020), but differs during rotation. When Sonic rotates, climbing up a hill (the sign of Gsp is not equal to the sign of sin ( angle )), slp is equal to 0.078125 ($ 001E). When rotating down a hill (the sign of Gsp is equal to the sign of sin ( angle )) slp is 0.3125 ($ 0050).

Note: it seems that in Sonic 1 the slp value is not added if the Sonic stops and is in the stand / wait cycle. However, in Sonic 3 & Knuckles, the value of slp is added even in this case, so Sonic cannot stand on steep slopes - he has to go backwards on them.

Jumping at the corners

The angle at which Sonic stands at the moment of the jump also affects the jump. He cannot simply assign Ysp a value of jmp , he needs to jump from the angle at which he stands. Therefore, the jmp value needs to be assigned to both Xsp and Ysp , using cos () and sin () to get the correct values.

A little more pseudocode:

 Xsp -= jmp*sin(angle); Ysp -= jmp*cos(angle); 

Mode switching

So, Sonic can run on hills, slopes and grounds, and this is not bad. But this is not enough. He cannot travel from the ground to the walls and ceiling without an additional code.

Why? Land colliders A and B check for obstacles directly below them, finding the height of the ground. They can not handle the transition to the walls, because the whole scheme is designed to move exactly up and down along the Y axis.

How to solve this problem? Using four different driving modes. This requires a little explanation.

Four modes

It is quite logical to assume that if Sonic can move 360 ​​degrees, the engine handles all 360 degrees in about the same way. In fact, the engine divides the angles into four quadrants, which greatly simplifies the work.

For a better understanding of what I'm talking about, let's imagine a simpler platformer without complete loops, only with low hills and slopes. All the character needs to do after the horizontal movement is to move up or down until he reaches the floor level. Then you need to measure the angle of the floor. Angle is used to lower Gsp , and nothing more. The character will still always move horizontally and move strictly up and down to reach the floor level.

Basically the same thing happens in games about Sonic. Only if the angle gets too steep will Sonic change the “quadrant”, switching from floor mode to right wall mode (then to ceiling mode, left wall, and back to floor mode, and so on). At any given time and in any particular mode, Sonic behaves like a normal platformer. Magic occurs when combining these four modes with cleverly made smooth switching between them.

But how and when does Sonic switch between modes?

If, while in floor mode, an angle greater than 224 ($ E0) is detected, the slider switches to the right wall mode. Basically, everything remains the same, only the colliders check the right side instead of the bottom, and the Sonic moves to the “floor” level horizontally, not vertically.

If, while in the right wall mode, an angle of less than 224 ($ E0) is detected, the slider switches back to the floor mode.

Other transitions work in a similar way.

A fair question may arise - where are the earth's colliders when we are in the right wall mode? They are located there, but rotated 90 degrees. Collider A is located relative to the center of Sonic in Y + 9 instead of X-9. Collider B is in Y-9 instead of X + 9. The collider lines become not vertical, but horizontal, stretching 16 pixels beyond the level of his legs (which is now 20 pixels “lower” than Sonic, in the X + 20 coordinate).

Yes, since the colliders are moving, Sonic can be “pushed out” to a new position in the step where the mode is switched. However, the movement is only a few pixels, and in the usual game completely unnoticed.

Another aspect: as I said, solid tiles are made up of heights. The key word here is "height." How do they behave in the right wall mode? Quite surprisingly, it turns out that in the original engine, each solid tile has two complementary array of heights; one is used for horizontal and the other for vertical movement.

What about left wall and ceiling modes? Do not need four arrays of heights? No, because tiles of such a form use ordinary heights, only inverted. In ceiling mode, Sonic knows that the height value found should be used to move it down, not up.

Thanks to these four modes, Sonic can move around all kinds of contours, internal and external curves, and so on. Here are a couple of example images with angle values ​​that will tell you what we are talking about:





Falling off walls and ceilings

Being in the mode of the right wall, left wall or ceiling, Sonic falls when the absolute value of Gsp becomes lower than 2.5 ($ 0280) ( Gsp is equal to 0 at this moment, however Xsp and Ysp do not change, therefore Sonic can continue to move along its trajectory in the air ). This happens even when there is earth beneath it.

Slipping back

When Sonic falls as indicated above, the horizontal control lock timer is assigned a value of 31 ($ 1E) (the timer will not count down until Sonic touches the ground). While the timer value is not zero, and Sonic is on the ground, he does not allow the player to change Sonic's speed with the "right" and "left" buttons. The timer value is decremented by 1 with each step, so the lock lasts about half a second. During this time, only the slp and the speed with which Sonic fell to the ground affect the movement, so Sonic will slide down the ramp.

State of being in the air

When Sonic is in the air, no need to worry about the corners, Gsp , slp and so on. All that is needed is to move using Xsp and Ysp until contact with the ground is detected, and then go to the ground mode.

However, Sonic has an unusual set of colliders for movement in the air, which is worth considering in detail.

Airborne colliders

Horizontal collider

Sonic must hit the walls just as he does on the ground. Therefore, there is a line of the horizontal collider, coming from its Y position and stretching from X-10 to X + 10. When confronted with a hard tile, Sonic is “pushed out” to the border of a tile plus / minus 11, just like being on the ground.

The difference is that this line of the collider is wider than the vertical colliders A and B, which detect the presence of earth (we will return to them a little lower). This means that the line of the horizontal collider can detect the block that Sonic flies past, even if he doesn't have an Xsp at all. Therefore, it slips off solid objects when it strikes its outer edges.

When Sonic detects a collision with this line of a horizontal collider, his Xsp is reset to zero only if he moves towards the wall, and not from it. Otherwise, he would have stuck to the walls, flying past them.

Vertical Colliders

The colliders A and B of Sonic act in the air in about the same way as on the ground. The difference is that when detecting a solid tile, Sonic's height is not immediately set to the height detected for the tile, minus 20 pixels. Instead, such a height is set only when it is already below this height. Otherwise he would have stuck to the floor as he approached him.

If the colliders are stretched so much lower than his legs, why can't they discover the ground again in the step in which he jumps and not let him ever get off the floor? It's simple: he ignores them, except for those moments when Ysp is equal to or greater than zero, so he only detects the earth when it moves down.

Since the Sonic in the air can move both up and down, there must be two more colliders checking from above (C and D) so that he can hit the ceiling and the curves above it. (C and D are exact mirror reflections of A and B - they have the same position X and length, only directed not down, but up.) Sonic detects ceilings and pushes them away, moving both up and down, unlike floors that show up only when moving down. You can hit the “ceiling” (which is actually the bottom of the block) by moving down, leaning against a wall with a gap, or jumping to the side of the upper curve.

Jumps "through" the floor

There are platforms that Sonic can fly through through when jumping up. They are often found in hilly green areas such as the Green Hill Zone , the Emerald Hill Zone , the Palmtree Panic Zone and so on. Solid tiles that make up such sites are marked with a special type of engine, which can only be detected by colliders A and B. They are ignored by colliders C and D, as well as by the line of the horizontal collider.

Re-detection of land

When Sonic is on the ground, Xsp and Ysp are obtained from Gsp . When it falls or is otherwise lifted from the ground, Xsp and Ysp already contain the necessary values ​​to continue the trajectory in the air. But when Sonic lands, Gsp must be calculated from the Xsp and Ysp available at the time of landing. You might think that cos () and sin () are used to get the exact value, but this is not true. In fact, something much simpler happens, while the algorithms when hitting a curved ceiling and when landing on a curved ground differ, so I will consider them separately.

When moving down

If the angle of the detected earth is in the range of 240-255 ($ F0 ~ $ FF) (and their mirror reflections 0-15 ($ 00 ~ $ 0F)), Gsp is assigned the value Xsp . If the angle is in the range of 224-239 ($ E0 ~ $ EF) (16-31 ($ 10 ~ $ 1F)), Gsp is assigned the value of Xsp , but only if the absolute value of Xsp is greater than Ysp . Otherwise, Gsp is Ysp * 0.5 * -sign (cos ( angle )). If the angle is in the range of 192-223 ($ C0 ~ $ DF) (32-63 ($ 20 ~ $ 3F)), Gsp is equal to Xsp if the absolute value of Xsp is greater than Ysp . Otherwise, Gsp is assigned the value Ysp * -sign (cos ( angle )).

When moving up

If the angle of the detected ceiling is in the range of 160-191 ($ A0 ~ BF) (64-95 ($ 40 ~ $ 5F)), Sonic is attached to the ceiling, and Gsp takes the value Ysp * -sign (cos ( angle )). If the angle is in the range of 96-159 ($ 60 ~ 9F), Sonic hits his head, as if it were a regular ceiling, and does not attach to it. Ysp is reset, and Xsp does not change.

Help: Angle Conversion

Genesis / Mega Drive games use angles in hexadecimal format, from 0 ($ 00) to 255 ($ FF), so the circle is not divided into 360 parts, as we used to, but by 256. Worse, unlike angles in other languages, such as GML, they are counted counterclockwise, so 32 ($ 20) is not 45 ° as it should, but 315 °.

To convert the original hexadecimal angles into angles that can be used in GML, use this formula (written in pseudocode):

 return (256-hex_angle)*1.40625; 

Notes



Update: added decimal values.

Source: https://habr.com/ru/post/276669/


All Articles