Sub-Pixel-Walker v0.1: Testers not needed

Make games! Discuss those games here.

Moderators: Bob the Hamster, marionline, SDHawk

lennyhome
Slime Knight
Posts: 115
Joined: Fri Feb 14, 2020 6:07 am

Sub-Pixel-Walker v0.1: Testers not needed

Post by lennyhome »

This is a tech demo inspired by kylekrack's Pixel-Walker, but with the difference that all the calculations are done in fixed point arithmetic.

For the most part the idea is to have accurate Zelda-like controls but also Super Mario platform style controls and tank controls for vehicles. In this demo I've implemented only the first type but the other two can be obtained easily enough.

A generic slice (not the hero at least for now) is subject to inertia and it collides against the regular wall map. Acceleration and friction can be tuned from ice skating to mud and anything in between. The code itself turned out better than I though altough it's rather long because I had to type 8 collision cases (4 walls and 4 corners) individually, mostly due to limitations in the language.

So, if anybody's curious, here's is a precompiled demo and the source code. To modify the source code this compiler is needed, altough if you really want it shouln't be too hard to modify it to compile with the regular compiler.
Last edited by lennyhome on Tue Apr 28, 2020 7:24 am, edited 2 times in total.
User avatar
charbile
Metal Slime
Posts: 601
Joined: Tue Jun 21, 2011 6:18 am

somebody who was curious

Post by charbile »

What's the advantage of fixed point arithmetic?

Tried the demo--seems like a lot of code for something so simple. Kylekrack's had a lot of extra features, were those in here as well or were you saying one could edit the scripts to include them??

breaking out of the tile grid sure does feel nice
lennyhome
Slime Knight
Posts: 115
Joined: Fri Feb 14, 2020 6:07 am

Post by lennyhome »

First of all, I don't mean to compete with kylekrack. The title of the thread is an homage more than anythinge else. This is something different.
What's the advantage of fixed point arithmetic
Extra precision and fractional speeds. I guess you coud call it smoothness.
seems like a lot of code for something so simple
I had to replicate some functions that already are in the engine using scripting, so I could customize them.
lot of extra features
I'm never going to implement those. What I am probably going to do next are slopes and ice sheets just because those should be easy to do, but then again this is a very specific tech demo.
edit the scripts to include them
If you want to modify this script and re-compile it, you need a special compiler because it's not quite regular HSpeak.
User avatar
SwordPlay
Chemical Slime
Posts: 966
Joined: Sun Jan 22, 2017 9:32 am
Location: London, England
Contact:

Post by SwordPlay »

It would be great if you posted screenshots or a gif!

Always exciting to see new things. Love it!
"Imagination. Life is your creation."
User avatar
kylekrack
Liquid Metal Slime
Posts: 1242
Joined: Mon Jun 16, 2014 8:58 am
Location: USA
Contact:

Post by kylekrack »

Cool! I think what would really benefit this as a tech demo is a HUD with controls to tweak the parameters of movement. For instance, displaying the current acceleration, and allowing 2 keys (+ and - perhaps) to increase or decrease that value. If this is meant to show off the benefits of sub-pixel movement, real-time comparisons are important to convey that. You mention the difference between ice and mud, etc. Post another build with those terrains on. I'd love to see that in action.

If you ever find a spot where a segment of the pixel-walker scripts are useful here, feel free to copy stuff. I'm not sure how likely that is to be the case, just wanted to give that green light explicitly.
My pronouns are they/them
Ps. I love my wife
lennyhome
Slime Knight
Posts: 115
Joined: Fri Feb 14, 2020 6:07 am

Post by lennyhome »

It would be great if you posted screenshots
I didn't bother because this all about how the controls feel.
a HUD with controls to tweak the parameters of movement
Certainly. Also the ability to switch from Zelda controls to Super Mario controls to tank controls. I've already tried the tank controls, which use the sin/cos tables. They're fun. I didn't include it because I didn't have a sprite in 16 rotations at hand and I wanted to put out something.

I'm still trying to shake off the 'rona, but I should have more experiments coming.
just wanted to give that green light explicitly
Likewise of course.

----

I've added some patches to the right of the map where the physics are different. There's an attempt at ice and some slopes. It's based on zones. It checks which zone the player is in and adds a dummy acceleration (1-4) or reduces friction (5). But it could also be done by reading the tile.

Bouncing off walls is disabled at the moment, but it can be done. I may have enough to make a little top-down car racing game. We'll see.
Last edited by lennyhome on Tue Apr 28, 2020 12:29 am, edited 3 times in total.
User avatar
SwordPlay
Chemical Slime
Posts: 966
Joined: Sun Jan 22, 2017 9:32 am
Location: London, England
Contact:

Post by SwordPlay »

I tried it out and it feels really good.

You have to use an inverted wallmap? That's pretty crazy!
Can this work with other collision maps (other than wallmap) and different sizes for the player?
This could be really neat for extending the engine's capabilities to make new games. But you won't be able to take advantage of built-in A* or other commands :(
I guess it doesn't matter if you're making a platformer or top-down shooter or something.
"Imagination. Life is your creation."
lennyhome
Slime Knight
Posts: 115
Joined: Fri Feb 14, 2020 6:07 am

Post by lennyhome »

You have to use an inverted wallmap?
Is it inverted? The walls have a direction in my implementation because I need to know which side is the "out" side. It could proably be implemented differently. I don't know. I've never written a game for this engine.
Can this work with other collision maps
Yes. With enough effort you can collide anything with anything.
different sizes for the player
In principle yes, but for simplicty right now I'm considering the player to be a 9 pixels radius circle placed at the bottom of the sprite, just because it works well with the tile size. Can be changed and made so certain characters are able to go through certain passages and others can't.
built-in A* or other commands
Several features that are in the engine can't be used. This is a "forward looking" experiment and to some extent it's also an abuse because many story-driven games don't need anything like this.
Last edited by lennyhome on Tue Apr 28, 2020 12:54 am, edited 1 time in total.
User avatar
kylekrack
Liquid Metal Slime
Posts: 1242
Joined: Mon Jun 16, 2014 8:58 am
Location: USA
Contact:

Post by kylekrack »

Aha, I didn't see the other patches of terrain. Those feel quite good. I also just realized I think this is running at the default FPS. I would recommend bumping that up to 60 fps. One of the big problems with using pixel-movement is that even 1-pixel/tick speed is quite fast at 60fps, and there's nothing slower. That's a big reason sub-pixel movement is such a big deal.
My pronouns are they/them
Ps. I love my wife
lennyhome
Slime Knight
Posts: 115
Joined: Fri Feb 14, 2020 6:07 am

Post by lennyhome »

bumping that up to 60 fps
I've just tried it to run it at 60 fps and it works but it stretches the limits of the arithmetic a little bit. The units of measurement for the acceleration are "pixels per fps squared" or something like that, so eventually you run into trouble if you try to run it too fast.
Last edited by lennyhome on Tue Apr 28, 2020 7:25 am, edited 2 times in total.
TMC
Metal King Slime
Posts: 4308
Joined: Sun Apr 10, 2011 9:19 am

Post by TMC »

Oh, nice. Very smooth. Sub-pixel velocity really does help for physics, otherwise the minimum possible acceleration 1px/tick^2 is pretty high.

It would be possible to use the "check wall collision x/y" commands to do the wallchecking instead of having to script it, however that results in a square hitbox while you use a circular one, and also wrote it so that just nicking a wall pushes the player sideways around the obstacle, aligning the player with the wall grid. I can't immediately see how the scripts do that, I'll examine . Unfortunately "check wall collision x/y" can't do that, though it's something I want to add (I have also scripted such a system in the past, for Blood Ledger). Maybe someday circular hitboxes too.

It's possible to store acceleration in higher precision than position or velocity, either using an accumulation buffer, or much easier, using temporal dithering. E.g.:

Code: Select all

acceleration = (acceleration_times_8 + (3*tick % 8)) / 8)
The 3* results in the dither pattern [0, 3, 6, 1, 4, 7, 2, 5].
But I think you still have more than enough precision at 60fps... acceleration on ice would still be 9/256 px/tick^2?

Moogle's Sidescroller 101 scripts also use subpixel velocity/acceleration (the unit of measurement is a tenth of a pixel), and most OHR sidescrollers are based off those scripts. I vaguely remember at least one game adapting them for top-down movement too.

I actually soon want to make the engine use subpixel positioning of NPCs and heroes internally, to be used for fractional walk speeds. Nothing would change from the point of view of existing scripts, but I could add some new commands to get/set the fractional position.

However I don't want to also convert the whole slice system to support fractional pixel positions if I can avoid it. Too much of a headache. Well, fractional velocity is already possible with the "move slice to" and "move slice by" commands, which use X,Y accumulators for fractions of a pixel. (Which I think is ugly and inefficient compared to fixed point slice positions.) But it means we could add some script commands to get/set fractional slice positions and velocities which act on those accumulators, but not update any other slice code at all, meaning that translating a slice by half a pixel won't translate its children. That's probably better that way anyway: If you move a tree of slices across the screen, you want them to all move by an equal numbe of pixels without aliasing effects.
Last edited by TMC on Tue Apr 28, 2020 3:56 pm, edited 1 time in total.
User avatar
SwordPlay
Chemical Slime
Posts: 966
Joined: Sun Jan 22, 2017 9:32 am
Location: London, England
Contact:

Post by SwordPlay »

Is there a good overview of how sub-pixel stuff works? Or are you willing to give us a glimpse into some of the math?
Why wouldn't you just increase the resolution and sizes of everything? That's probably stupid, right?
"Imagination. Life is your creation."
User avatar
charbile
Metal Slime
Posts: 601
Joined: Tue Jun 21, 2011 6:18 am

Post by charbile »

Looked up fixed point arithmetic, my bad. Assumed kyle would have used that, kinda surprised. For ohr scripts, seems trivial to do with planning— like x /100 to get two deep fraction, ie 1234 becomes 12.34, with consistent rounding is as smooth as real thing because pixels on screen can never be fractions, edit: so it’s really about timing which have to delta or set to a fixed fps
Last edited by charbile on Tue Apr 28, 2020 6:29 pm, edited 1 time in total.
lennyhome
Slime Knight
Posts: 115
Joined: Fri Feb 14, 2020 6:07 am

Post by lennyhome »

use the "check wall collision x/y" commands to do the wallchecking instead of having to script it
We briefly touched on that at the end of kylekrack's thread. It's not enough to be able to tell if two shapes have an intersection. Long story short, you also need to know where the barycenter of the intersection is.
Is there a good overview of how sub-pixel stuff works?
You pretend that the playfield is much bigger than it is, you do your calculations and then you scale down the final results while leaving the partial results untouched. That's the idea. The rest is a forgotten art due to the fact that floating point numbers are supported everywhere now.
pixels on screen can never be fractions
In my cult once we reach the 33rd level we are taught how to use the dark arts of convolution to blit sprites at fractional coordinates. If you're interested I can send you a brochure.

----

Image
I hope this makes any sense. Initially I intended the corners to be circles but then I settled for that split-triangle geometry. As a consequece, the collision source is a diamond shape implicitly defined by (abs(x) + abs(y) < radius) and then split by (abs(x) > abs(y)). The red arrows represent the surface normals. The yellow lines represent the grid.
Last edited by lennyhome on Wed Apr 29, 2020 6:43 pm, edited 4 times in total.
TMC
Metal King Slime
Posts: 4308
Joined: Sun Apr 10, 2011 9:19 am

Post by TMC »

OK, thanks. Sorry, this time I actually studied the code, needn't have bothered you for an explanation.

I'm surprised that you used the L_1 norm for the distance (diamond shaped hitbox) instead of circular. Did you do that just to justify diagonal normals/bounce/repulsion angles? I don't think there's anything wrong with pushing the slice away diagonally even if the hitbox is a circle, but calculating the correct normal is trivial anyway except for rounding problems.
We briefly touched on that at the end of kylekrack's thread. It's not enough to be able to tell if two shapes have an intersection. Long story short, you also need to know where the barycenter of the intersection is.
This isn't something I've heard of before. I imagine you can use the barycenter to work backwards and get the point of collision, but beyond that, it might be useful for sliding past a glancing collision?
But whoops, I missed the discussion at the end of that thread. The "check wall collision x/y" commands don't just tell if there is an intersection, they tell how far along the displacement vector it is, which is enough for any use case I can think of except sliding past a glance.
In my cult once we reach the 33rd level we are taught how to use the dark arts of convolution to blit sprites at fractional coordinates. If you're interested I can send you a brochure.
Does the convolution incorporate a sharpening filter? Because sub-pixel shifting really wrecks pixel art with blur. ("Box" filtering looks 10x better than standard bilinear filtering for scaling pixel art, but I think it's equivalent for shifting.)
But this is very relevant to rotozooming too; I'd like to add optional filtering to fix up the result a little bit, like the well-known "rotsprite" algorithm, but in real time.
Last edited by TMC on Thu Apr 30, 2020 4:48 am, edited 2 times in total.
Post Reply