bracket-lib icon indicating copy to clipboard operation
bracket-lib copied to clipboard

Fancy Console glyphs persistent across renders?

Open tobyhede opened this issue 4 years ago • 19 comments

This is possibly me not understanding or doing something wrong.

I am using the fancy console. In my code I have a condition that determines if a glyph is rendered.

if condition {
   draw_batch.set(offset_pos, render.color, render.glyph);
} else {
   println!("false");
}

The issue I have is that the glyph is being rendered even when the condition is false. I added an else condition and println! and can see that output in my terminal, but the glyph will appear in the last location it was rendered.

Is this expected behaviour for the fancy console?

My current workaround has been to render an empty glyph at 0,0 - that is the only way I've been able to get the original glyph to disappear.

tobyhede avatar Jan 09 '22 03:01 tobyhede

I believe it is expected that you call .cls () every frame.

Checkout the fancy example.

It is an immediate mode app, meaning, it is expecting to redraw everything every iteration, so clearing the screen is standard.

Somewhat related...

The sparse console, for example, continues adding to its list of tiles even if one already exists at the same location, causing the list to get very long and everything slows way down. (try removing .cls() in textsprites example)

I addressed the issue with sparse console on my fork here: https://github.com/jasonjmcghee/bracket-lib/commit/f7eb82c9a00f0e4d07b2a9957db9094fccaee7e6

(But fancy console isn't as simple to fix.)

But, my point of bringing this up is that it is clear that .cls() is intended to be called every frame.

jasonjmcghee avatar Jan 10 '22 05:01 jasonjmcghee

Thanks @jasonjmcghee ... I was calling ctx.cls() in my tick function.

I think I isolated the issue ... I was using set to draw rather than set_fancy. It works correctly with the .cls() call and set_fancy. Will do some digging to see what the difference might be.

tobyhede avatar Jan 12 '22 10:01 tobyhede

Turns out no, not fixed. Still happening with cls and set_fancy.

tobyhede avatar Jan 13 '22 22:01 tobyhede

I have the same issue here. I am working still pretty closely to the code from the HandsOn book, but switched everything to using fancy consoles and set_fancy. I clear all consoles using cls() in the tick function. However, when switching TurnState all glyphs rendered in the previous TurnState persist on the screen.

I am trying myself at displaying a minimap, which looks cool, but I cant get rid of it once its activated :)

jancrichter avatar Jan 21 '22 13:01 jancrichter

Make sure to set the active console to be the fancy console before clearing the screen.

This means likely ctx.set_active_console(1) if your fancy console is the second.

Or if you're using draw batches .target(1)

https://github.com/amethyst/bracket-lib/blob/5e35a050f5181892155a2eb4641af7445273a6f3/bracket-terminal/examples/fancy.rs#L13

I've used fancy consoles and have never seen the issue being described personally.

jasonjmcghee avatar Jan 21 '22 15:01 jasonjmcghee

like I mentioned, I am operating VERY close to the code from https://github.com/thebracket/HandsOnRust/blob/main/Loot/better_combat/src/main.rs

The core difference is that I switched all consoles to fancy. For the main part of the game this works a charm, there are no render artifacts and no flickering. All consoles are cleared just fine.

The problem only occurs when I switch the TurnState. For example on the Victory and Defeat screens also present in the example mentioned above, all content rendered in the previous TurnState remains on the screen in addition to the stuff rendered for the Victory/Defeat screens.

All consoles are switched to and cls()'d in the tick function just as in the example above.

I have tried various methods of clearing the consoles, e.g. adding more activating and clearing them from within the Victory and Defeat functions and alspo implementing a system to clear them. The former with NO effect, the latter with very unpredictable effects and lots of artifacts and flickering.

It seems to me that cclearing from the tick function should really just work :/

jancrichter avatar Jan 21 '22 16:01 jancrichter

If you provide a gist or repo with your code, I can take a look and see if anything jumps out!

jasonjmcghee avatar Jan 21 '22 16:01 jasonjmcghee

Thanks, man, appreciate it.

https://gitlab.com/sybr/crawler/

If you want to reproduce the problem: At the player's starting location there is an item on the ground. Pick it up with 'G' and activate it with '1'. It'll display the minimap. By hitting '1' again you can go back to moving around, but the minimap won't disappear unfortunately.

jancrichter avatar Jan 21 '22 17:01 jancrichter

That link is not publicly visible

jasonjmcghee avatar Jan 21 '22 17:01 jasonjmcghee

Sorry, should work now. Messed up the permissions a bit.

jancrichter avatar Jan 21 '22 17:01 jancrichter

Alright, I was able to fix it now. Purely by trial and error. I decided to not draw the minimap on its own console and instead used the same console that the player and NPCs are drawn on. It works well now.

I still have retention of in-game graphics on teh Victory/Defeat screens, which should not be the case, but its also not a problem, really.

Thanks anyway!

jancrichter avatar Jan 21 '22 23:01 jancrichter

The link you provided never resolved for me- happy to take a look, but it will need to be posted somewhere publicly available, like a gist.

jasonjmcghee avatar Jan 21 '22 23:01 jasonjmcghee

It did resolve after my post 7 hours ago, now it doesn't because the branch is merged. I fixed the link above now to go to the project main page.

jancrichter avatar Jan 22 '22 00:01 jancrichter

Just tried it.

I added this in your player_input.rs as no maps spawn on the player anymore:

VirtualKeyCode::M => {
    commands.push(
        (
            WantsOpenMap,
        )
    );
    Point::new(0, 0)
},

and I couldn't reproduce the issue you are seeing.

Have you tried putting a breakpoint (or print statement) here: https://gitlab.com/sybr/crawler/-/blob/main/src/systems/display_minimap.rs#L27 to see if the map is being re-drawn?

jasonjmcghee avatar Jan 22 '22 00:01 jasonjmcghee

Thanks for having a look. Like I said above though, the problem is fixed on 'main' now. The minimap behaves as intended. I removed the item spawn, as the intention is for the player to only get access to the map once they find a map item during play.

It's just the game graphics on the defeat/victory screens that I can't really explain. There should only be a black screen with text there.

jancrichter avatar Jan 22 '22 00:01 jancrichter

I've encountered the same problem, here is a minimal reproducible example - https://github.com/artem-karpenko/bracket-reproduce-fancy-issue. The code also includes a few commented-out lines which provide some insight into fancy console's behaviour - rather tricky, I must say :|

A workaround implied from that code is to call cls() and draw a space symbol with fancy console anywhere. Just like @tobyhede suggested initially :)

artem-karpenko avatar Feb 14 '22 18:02 artem-karpenko

Originally, not force-performing a CLS at the beginning of the frame was deliberate behavior. My thought process was that you might want to treat it like an old-school terminal, add/change as needed. With hindsight, I'm thinking that was a mistake. (There's a no_cls example showing the former intended behavior).

My thoughts now are: everyone clears and redraws anyway, GL and the graphical back-ends redraw anyway, and the console-based backends have dirty-updating built in. So auto-clearing should be the behavior.

I also need to double-check the fancy renderer, I think there's a bug with it not clearing if you then don't write something to it.

Sorry about the really slow replies. I just got my 2nd book off to layout (Rust Brain Teasers), and then a newborn arrived in the household (via foster/adopt, so we didn't have the usual several months of warning). I'll be doing my best to get caught up on issues as soon as I can - for now I get to steal some PC time in between feeding/changing!

thebracket avatar Feb 14 '22 20:02 thebracket

Possibly a related bug, if I use set_fancy to draw my glyph is rendered at y-1. As if the y axis is starting at index 1 instead of 0.

Will try and create a minimal example as a reference.

tobyhede avatar Feb 18 '22 03:02 tobyhede

With patchfx's help, the last commit should fix part of this: consoles do persist across renders unless you clear them (this was a deliberate design decision, since "real" consoles work that way - you can do additive rendering if you wish). cls wasn't working properly for fancy consoles - so that should be taken care of.

I'll look at the y position in a moment. I remember having some issues with exact glyph location when I created the code, so it may be off by one.

thebracket avatar Aug 10 '22 13:08 thebracket