Posts: 5
Threads: 1
Joined: Nov 2017
Reputation:
0
As a hobby project, I'm making a C# rewrite of a classic DOS game.
Tilengine fits the game model almost perfectly, but I'm still struggling with some stuff:
- While it is possible to directly set pixels for the individual tiles, I couldn't find a way to initialize and fill sprite pixels per-sprite, without having to build a single-image spritesheet. It's not a problem when you ship the prepared resources with the executable, but I want to pick up the original game resources, and would like to avoid layouting the sprites in spritesheet.
- I can't find a way to enable "nearest neighbor" upscaling (aka "big square" pixels). If I disable CRT effect, the picture stays interpolated.
- Is it possible to change resolution (or, even better, re-initialize the whole engine) without having to re-create the window?
Posts: 673
Threads: 33
Joined: Jan 1970
Reputation:
13
Hello and welcome to the forums
- The spriteset memory layout is quite static. It would be easy to implement a method to update the pixels of a pre-allocated spriteset (just as you can do with a tileset), but you won't be able to add, remove or modify the sizes of sprites. You can already do it with tilesets because their layout is fixed. If this feature would be useful, you can open a GitHub issue with the feature request.
- Just as in the first question, if this feature would be useful please open another GitHub issue. This feature will only need changes to Window.c, which is open source.
- No, at this moment it's not possible. In fact switching windowed/fullscreen mode with Alt+Enter destroys the current window and creates a new one with the requested attributes. The engine and loaded resources keep loaded. It would be possible to implement changing the resolution of the engine, but keep in mind that the display target is independent from the engine itself. You'd be responsible of manually propagating te resolution change to the target display, be it the built-in window, or any surface you attach to it.
Posts: 5
Threads: 1
Joined: Nov 2017
Reputation:
0
12-04-2017, 07:58 AM
(This post was last modified: 12-04-2017, 08:00 AM by NeXT.)
Thanks for implementing nearest neighbor scaling and per-sprite pixel manipulation!
As for the window resolution changing -- ATM I'm not blocked, but in long-term perspective it'd be good to be able to switch the internal resolution without window flickering (and in fullscreen mode too), as it's natural for retro games to use multiple resolutions for different parts of the game.
Also, how it's currently supposed to deal with interface elements like panels?
I have a panel bitmap and want to draw it with overlayed hiscore, number of lives etc.
Can't init 1-tile tilemap and put panel there (it's too big to fit into a tile and the height is not divisible to 8).
Do I have to create a separate panel layer and a spriteset with panel plus all its overlayed sprites?
Posts: 673
Threads: 33
Joined: Jan 1970
Reputation:
13
You're welcome, feature requests are meant to be implemented :-) please add the dynamic change of internal resolution too, if not I will soon forget about it...
Interface elements: you can check the SuperMarioClone C# sister project, it has an overlaid interface like the one you want. It uses its own layer and tileset, and "printing" values is done updating the tilemap in realtime. Please check HUD.cs, and the smw_hud resource (tmx, tsx and png)
Let me know if you have success!
Posts: 5
Threads: 1
Joined: Nov 2017
Reputation:
0
(12-04-2017, 08:44 AM)megamarc Wrote: Interface elements: you can check the SuperMarioClone C# sister project, it has an overlaid interface like the one you want. It uses its own layer and tileset, and "printing" values is done updating the tilemap in realtime. Please check HUD.cs, and the smw_hud resource (tmx, tsx and png)
This approach works well when you can fit the interface into small tiles and your interface elements are aligned to the tile dimensions.
In my case I have a big panel bitmap (320x23) and a bunch of HUD sprites that need to be put on top of that.
The sprites are small (16x12) but need to be put at the non-aligned places and can overlap each other (so I can't init them as tiles).
Actually, after you've implemented sprite pixel manipulation, I can create a layer with fake empty tilemap and one panel sprite, and just redraw my elements directly to that sprite when needed.
Or put the HUD elements on top of the panel as separate sprites.
Will give it a try.
Posts: 673
Threads: 33
Joined: Jan 1970
Reputation:
13
All VDP-based systems (like arcade boards or console) used either tiled backgrounds or sprites to build the HUD. Direct pixel access is not possible in these systems easily -some creative trickery is needed-.
If you're remaking a DOS game, the PC didn't have a VDP, it had a framebuffer with direct pixel access. You have to stick to the characteristics of the target medium: use aligned tiles or sprites. Arcade/console game developers had this in mind, as direct pixel was not an option. PC/DOS was a very different medium and so was the way games were developed. You can't easily port a framebuffer-based game to a VDP-based medium (and the opposite).
I think your best option to get unrestricted position and size draw is using sprites. However interface elements don't need to fit into small tiles, it is common to use bigger fonts or items composed of several tiles each glyph.
Posts: 5
Threads: 1
Joined: Nov 2017
Reputation:
0
I've finally had the time to check the Nearest Neighbor upscaling and there are some problems.
While the picture looks exactly as expected in non-CRT mode, the absence of vertical smoothing essentially breaks default CRT mode, making unwatchable aliasing artifacts.
It happens because current CRT emulation doesn't take into account the fact that its shadow mask RGB pixel columns are shifted vertically for 1/2 height.
Due to this shift, in reality, a horizontal line won't have sharp edges, but current CRT processing doesn't care about that, and some pixels will have different colors for their top and bot parts.
Previously, it was alleviated by vertical interpolation, making the picture smoother, and the above effect wasn't noticeable at all, but it's not the case when Nearest Neighbor upscaling is enabled.
The cheap workaround would be to ignore Nearest Neighbor upscaling flag when CRT mode is enabled, and apply it only when disabled.
I think that'll be enough to not to bother implementing better approaches (at least, for now).
Posts: 673
Threads: 33
Joined: Jan 1970
Reputation:
13
You're right, correct CRT emulation is quite complex. I just implemented a cheap one that runs on modest hardware and does a decent job, but of course it's far from accurate. I would recommend to bypass the built-in windowing feature and use another framework with powerful multi-pass shader capabilities to do post-processing.
However the built-in CRT effect is quite configurable, with different overlays and you can even provide your own. Check documentation for TLN_EnableCRTEffect() function, this is the C API but the C# binding uses the same parameters. By default, the configuration used at startup is this:
Code: TLN_EnableCRTEffect (TLN_OVERLAY_APERTURE, 128, 192, 0,64, 64,128, false, 255);
Posts: 5
Threads: 1
Joined: Nov 2017
Reputation:
0
Sure, correct CRT emulation is VERY complex, and I'm not suggesting to pursue that task, as current implementation (before v1.19) was OK by me.
The only problem is that in v1.19 Nearest Neighbor (NN) upscaling activates for both CRT and non-CRT modes, making annoying artifacts in CRT mode for some patterns.
What I'm suggesting is to change NN flag to apply to non-CRT mode ONLY, and make CRT mode ignore that flag.
|