Hacker Newsnew | past | comments | ask | show | jobs | submit | more fleabitdev's commentslogin

I've wondered whether photorealism creates its own demand. Players spend hours in high-realism game worlds, their eyes adjust, and game worlds from ten years ago suddenly feel wrong; not just old-fashioned, but fake.

This is also true for non-photorealistic 3D games. They benefit from high-tech effects like outline shaders, sharp shadows, anti-aliasing and LoD blending - but all of that tech is improving over time, so older efforts don't look quite right any more, and today's efforts won't look quite right in 2045.

When a game developer decides to step off this treadmill, they usually make a retro game. I'd like to see more deliberately low-tech games which aren't retro games. If modern players think your game looks good on downlevel hardware, then it will continue to look good as hardware continues to improve - I think this is one reason why Nintendo games have so much staying power.

This has been the norm in 2D game development for ages, but it's much more difficult in 3D. For example, if the player is ever allowed to step outdoors, you'll struggle to meet modern expectations for draw distance and pop-in - and even if your game manages to have cutting-edge draw distance for 2025, who can say whether future players will still find it convincing? The solution is to only put things in the camera frustum when you know you can draw them with full fidelity; everything in the game needs to look as good as it's ever going to look.


Getting rid of subpixel AA would be a huge simplification, but quite a lot of desktop users are still on low-DPI monitors. The Firefox hardware survey [1] reports that 16% of users have a display resolution of 1366x768.

This isn't just legacy hardware; 96dpi monitors and notebooks are still being produced today.

[1]: https://data.firefox.com/dashboard/hardware


Even more strikingly, two-thirds are using a resolution of FHD or lower, and only around a sixth are using QHD or 4K. Low-DPI is still the predominant display situation on the desktop.


See also Linux Hardware Database (developer biased) [1] and Steam Hardware & Software Survey (gamer biased) [2].

[1] https://linux-hardware.org/?view=mon_resolution

[2] https://store.steampowered.com/hwsurvey


Last year, an interviewer asked Francis how he envisages hell. His response stayed with me: “It’s difficult to imagine it. What I would say is not a dogma of faith, but my personal thought: I like to think hell is empty; I hope it is.”


“I like to think Hell is empty” might be a hopeful statement, as in he hopes nobody ever actually goes to Hell but that everyone, no matter how evil, repents in their dying moments and accepts the path of truth.


I like to think hell is empty because the people who would have been sent there for being foul and wicked are actually people with no souls: they are just p-zombies wandering the world inflicting harm. Thus, when they die, there is no actual soul being released, their matter just ceases to function.

This could also explain why some simple creatures, with no real conscious experience, don’t overpopulate heaven or Hell: they have no souls with which to populate it with. They are just matter, temporarily constructed into some form resembling a living thing.

So hell is empty, and evil is the result of soulless automatons created by accident in our world. So if you die and nothing else happens for you after, then you were a p-zombie, with no soul.


Or that it is empty for eternity for each and all who are there. Endless solitude would be a hellish punishment.


That’s how I’ve read it firstly. Hard to imagine worse hell than this to me.

And then I realized the real meaning of the quote. Made me cry a little.


Same here, probably says a lot about us. Made me happy to finally understand what he actually mean.


It also made me realize what I truly value (community and people around) and made me a bit more hopeful about the future.


Nothing from the Bible indicates that hell is empty, so that is indeed an interesting response from the Pope.


The bible only has sparse and often contradictory references to hell - so it's very difficult to state "what the Bible says about hell" as if there's a unified picture laid out.


I've heard descriptions of hell of everything from the classic "fire and torture" we all know, to it being a total and complete detachment from god (in a disappointed and kicked out of the house by your parents kind of way). It's similar to descriptions of Satin. Everything from the horns and pitchfork all the way down to a "beautiful fallen angel" that he technically was explained to be in the bible.

I've always just assumed the descriptions that work to keep people fearful of leaving the religion as whatever is used at the time (saying this as somebody who is agnostic).


The modern concept of hell came from Dante's The Devine Comedy which was, ironically, a criticism of the contemporary church.


That's not exactly true. The main thing that is popularized by Dante is "demons are performing the punishment" (rather than being punished as in scripture ... but the general idea goes back to Gnosticism) ... and I guess "hell has circles" if we count those as significant.

"Hell is a place of fire and torment" is explicitly Biblical (Luke 16), even if there are also mentions of Hell without that (and some mentions of fire and torment without calling it "Hell").

Annihilationism vs Eternal Conscious Torment is the main point that isn't given a perfectly clear answer in scripture; there are verses that hint toward each.

Limbo and Purgatory are not in the Bible, but predate Dante. "Deal with the Devil" predates Dante and is only weakly founded in scripture. "Devils" (plural, as opposed to "the Devil") being distinct from "Demons" is a translation artifact, popularized by Dungeons & Dragons. There being various types of demons long precedes Dante. Variants of Universalism (including "Nobody goes to Hell" and "it's possible to escape Hell") are explicitly rejected in scripture.

Those are all the aspects of "modern concept of hell" that I can think of (let me know if you can think of more), and the connection to Dante seems pretty weak.


I highly recommend the youtube channel hochelaga. He's the one behind "biblically accurate" stuff


The concept and nature of an afterlife, divine justice and punishment, and the existence of "Hell" (which is mostly a Christian invention) has evolved over the millennia of text which make up Biblical canon.

It's always a mistake to assume the Bible has a singular, coherent, intentional narrative. Parts of it were written before the Israelites were even monotheists. It has as many Gods as it has authors.


Why would that be? There is a rich tradition of theology outside the Bible. Most popes are able to have a thought on a subject without quoting it.


its not biblical but its very catholic, its optimistic. I've heard it from other catholics, its just a hope that at the end of everyones life they accepted jesus and made it into heaven.


Yes - I think it caught my attention because it was such a mystery. It was a welcome thing to hear from one of the most powerful people in the world, but it came like a bolt from the blue. As far as I know, he never revisited the topic.


The Bible has very little to say about hell in general.


Catholicism isn't Protestantism. The idea that the Bible is the only source of truth is a Protestant idea and thus is very visible in the US. Catholicism, however, teaches that tradition and church teachings are sources of truth on par with the Bible. As such, for many teachings, especially those like Hell where the Bible is unclear, what it says isn't very relevant to Catholic doctine.


Gonna disagree with you there.

https://www.openbible.info/topics/hell


It's not that simple, because there are multiple concepts and Hebrew and Greek words that were translated as "hell". And many of those passages don't mention hell at all, but are just interpreted as such by readers.

https://en.wikipedia.org/wiki/Hell_in_Christianity


Modern academic scholarship paints a very complex picture: https://www.bartehrman.com/hell-in-the-bible/

I would argue that reading random quotes without context can be misleading. Unless of course you believe in a univocal, consistent and divinely inspired bible - which is a fairly extreme position to take.


> I would argue that reading random quotes without context can be misleading. Unless of course you believe in a univocal, consistent and divinely inspired bible - which is a fairly extreme position to take.

Those two statements don't follow. You can believe in a univocal, consistent and divinely inspired Bible and still think taking random quotes out of context is bad exegesis.


I see what you mean but I wasn't making a formal logical argument. Rather I meant something like "These particular quotes are more likely to be regarded as inherently meaningful on their own by someone who believes in a univocal, consistent and divinely inspired Bible"

Not my best-crafted piece of self-expression I will admit.


Most of what we know as hell comes from depictions by Dante and Milton. Things like fallen angel Lucifer, battles between heaven and hell, the apocalypse and rapture, etc. are noncanonical.


Did you read these? I think they actually go against what you argue. One of the passages about "hell" is John 3:16, which could not be less about hell if it tried (IMO). Also the passages that actually mention hell/hades are extremely sparse on details: it's separate from god, there will be fire and it will be unpleasant. Considering the length of the bible, I think this list shows that the bible has "very little" to say about hell in general.


Yes, the Bible is long, but it talks about many topics. The only thing that is mentioned a lot is Yahweh and Jesus. Beyond that you're not really gonna get a lot of consistency on topics.

This is a random Bible search website to show some verses about hell. I was not implying that all of these verses are definitive treatments of hell or anything similar.

However you will notice that what is said in these verses is generally not "hell is just emptiness". So even if very little is said about hell, to me the appropriate response to that is not "it doesn't say much so I'm just gonna believe whatever I want" (if you also claim the Bible is divinely inspired and the underpinning of your entire religion).


I guess if you wanted to argue that the fact that it doesn't say much should not be mistaken for being able to pick and choose your understanding, you should have said that before. Instead you contradicted "The Bible has very little to say about hell in general." - and linked that list of passages. I would say that ~10 passages there clearly describe "hell" and that, because the bible is a long book, that absolutely qualifies as it having "little to say" about hell.

> Beyond that you're not really gonna get a lot of consistency on topics.

This just seems like moving the goalposts to me. There's not a lot of consistency in talking about the "kingdom of heaven / god" but there are a LOT of passages that describe it. Many more than describe hell in any form. That doesn't mean that hell couldn't be a real thing but it's not a thing that's very present in the canonical text. Christian thought goes far beyond the contents of the traditional bible, but if you want to argue for a "paradise lost" hell or somesuch, you need to cast your lot with thinkers beyond the old and new testament authors.

That said, I don't think any of my sibling comments have responded with sources that ignore the biblical text. I think Ehrman is a bit liberal to stand in for all of christendom, but he's a respected scholar and I think his analysis is not in the category of "ignoring the text and inserting his own beliefs."


Nothing from the Bible indicates that hell exists in the way that Westerners perceive it.


It is impossible to reconcile the idea of an omnipotent god that is simultaneously good and permits people to be tortured for eternity.

Perhaps he chose the “god is good” over the “god, despite being able, will not prevent billions of reasonable and decent people from suffering eternally” fork in the road. You can’t logically choose both, and if you’re the pope, you probably had better have a belief in the goodness of god.


I've mentioned this before on HN but I find it interesting and valuable.

There is an older stream of christian thought on heaven and hell, still somewhat present in eastern christianity, that they are not separate places people are sent to.

In this view they are the same thing, simply the direct experience of the unattenuated light of god. A repentant person will experience this as mercy and all encompassing love, an unrepentant one will experience it as excruciating shame and terror. But they are both getting the same "treatment" so to speak.


People often think of hell as an active punishment form God, but for us humans it's not.

Hell, whatever it is, is where people end up when they'd rather be there than be with Christ.

God will never force you to love Him and accept Him. He gives you the choice, the rest is up to you.


Unless you live(d) in a time and place where Christian teachings were unavailable to you. Which accounts for a large majority of the humans who have ever lived.


Which is a problem for some Protestants who insist that only Christians can be saved... but not necessarily for Catholics. The belief that only Christians can be saved has actually been condemned by the Catholic Church as a heresy (Feeneyism, after the 20th century American priest, Leonard Feeney, who most famously espoused it)

According to Catholic teaching, non-Christians can be saved if (1) they are "invincibly ignorant" (i.e. their ignorance of the truth of Christianity is not their own fault), and (2) they have an "implicit desire" for the Christian God


This claim directly contradicts the teachings of the catholic faith.

Whatever your beliefs are, they aren’t catholicism.


I am not a Catholic.

I am not sure which label I should use for myself besides Christian as in 'follower of Christ', who tries to follow the Bible as accurately as possible, believing it to be the direct and absolute message from God.

Which indeed makes me incompatible with Catholicism.


Ah yes, "He/Him" - the original neo-pronoun if you will


A much more hopeful version than “Hell is empty, and all the devils are here”!


LOL Ill say! Far more positive


Interesting.

Is this a way of saying I don’t believe there is a place like hell?


The "threat" is there, but the hope is that everybody finds the "right" path at the very end.


It's difficult to design a language which has good usability both with and without a GC. Can users create a reference which points to the interior of an object? Does the standard library allocate? Can the language implement useful features like move semantics and destructors, when GCed objects have an indefinite lifetime?

You'd almost end up with two languages in one. It would be interesting to see a language fully embrace that, with fast/slow language dialects which have very good interoperability. The complexity cost would be high, but if the alternative is learning two languages rather than one...


I'm not saying you design a language with an optional GC, I'm saying the user can implement their own allocators i.e. large object pools nested in the GC-managed memory system. And then they get to avoid most of the allocation and deallocation overhead during runtime.


Sorry, I wasn't very clear - I think that using an object pool in a GCed language is like writing code in a dialect of that language which has no allocator.


Sure, but how is that any different than what you'd have to do in a regular GC-less lang to achieve good (allocation-avoiding) performance.


When half of a team are lone wolves because they see no other way to get things done, and the other half are rules lawyers who don't care whether things get done, I think that's a clear sign of management failure. Both of these personality types show up when team members have no faith that they can efficiently work together with their teammates: "drones" reject the idea of working efficiently, and "cowboys" reject the idea of working together.

There are lots of ways for management to go wrong, but if you feel like this article describes your small business, here are some low-hanging fruit:

- Have you sought out management coaching, or are you trying to become a good manager by trial and error?

- Do you treat your employees as trusted, respected professionals (meaning: people who might know better than you)? Do your employees treat one another that way? Do they give you that same respect?

- When you've made a mistake, big or small, how do you discover it? Do your employees and co-founders feel safe and secure enough to give you frequent negative feedback? Do they trust that you'll act on it?

- Do you have the time and resources to provide good management for all of the employees that you're directly responsible for? Have you been properly hiring, promoting and delegating to spread out that workload as the team grows?

- Leaders are just team members whose job is to produce decisions, in the same way that a software engineer's job is to produce code. Are you actually doing your job, by consistently producing high-quality decisions? Who's keeping track of that?

- Your most impactful responsibilities are hiring, firing, promotions, setting salaries, and choosing how to balance quality against speed. Are you giving all of those decisions the care and effort which they deserve?


>- Do you treat your employees as trusted, respected professionals (meaning: people who might know better than you)? Do your employees treat one another that way? Do they give you that same respect?

So many times it boils down to insecurities in the people managing. If you need to degrade the other to not feel inadequate, you shouldn’t manage people.


It's a nice thought, but internationalisation would make that difficult. On my system, the Noto international font weighs about 170 MiB compressed (gzip-compressed TTF, sans and serif styles, all weights, including symbols and colour emoji).

Even just focusing on Latin scripts, a few hundred fonts would roughly double the compressed download size for browsers and Electron apps.

It might be possible to come up with a better compression scheme which exploits redundancy between different typefaces, but as far as I know, that tech doesn't exist yet.


Here in the grim darkness of the future, every install of a general-purpose OS better be shipping with at least one font (or collection of fonts that operate via glyph fallback) to cover every Unicode codepoint for every language that isn't extinct yet. (In other words, apps that expect to be used with any arbitrary language, including browsers, should not be forced to ship with a font just to ensure basic coverage).

And then, once you have that system-provided codepoint coverage, you can make your font parametric in order to avoid needing to ship multiple copies of the font for different styles. It's not a perfect solution, but it's still pretty acceptable given the constraints.


To provide fonts for N different scripts would multiply the file size by roughly N, and there are a lot of scripts in common use:

https://en.wikipedia.org/wiki/List_of_writing_systems#/media...

Variable fonts would help, but I don't think it would be enough, especially if the goal is to provide a wide selection of fonts.


One day, I'd love to dive into stylised 3D graphics as an R&D project. There's been decent progress recently, but I think there's a lot of low-hanging fruit left to pick.

Some open questions:

- How do you reduce the detail of a toon-rendered 3D model as the camera zooms out? How do you seamlessly transition between its more-stylised and less-stylised appearance?

- Hand-drawn 2D animations often have watercolour backgrounds. Can we convincingly render 3D scenery as a watercolour painting? How can we smoothly animate things like brush-strokes and paper texture in screen space?

- How should a stylised 3D game portray smoke, flames, trees, grass, mud, rainfall, fur, water...?

- Hand-drawn 2D animations (and some recent 3D animations) can be physically incorrect: the artist may subtly reshape the "model" to make it look better from the current camera angle. In a game with a freely-moving camera, could we automate that?

- When dealing with a stylised 3D renderer, what would the ideal "mesh editor" and "scenery editor" programs look like? Do those assets need to have a physically-correct 3D surface and 3D armature, or could they be defined in a more vague, abstract way?

- Would it be possible to render retro pixel art from a simple 3D model? If so, could we use this to make a procedurally-generated 2D game?

- Could we use stylisation to make a 3D game world feel more physically correct? For example, when two meshes accidentally intersect, could we make that intersection less obvious to the viewer?

There are probably enough questions there to fill ten careers, but I suppose that's a good thing!


> Hand-drawn 2D animations often have watercolour backgrounds. Can we convincingly render 3D scenery as a watercolour painting? How can we smoothly animate things like brush-strokes and paper texture in screen space?

There are various techniques to do this. The most prominent one IMO is from the folks at Blender [0] using geometry nodes. A Kuwahara filter is also "good enough" for most people.

> When dealing with a stylised 3D renderer, what would the ideal "mesh editor" and "scenery editor" programs look like? Do those assets need to have a physically-correct 3D surface and 3D armature, or could they be defined in a more vague, abstract way?

Haven't used anything else but Blender + Rigify + shape keys + some driver magic is more than sufficient for my needs. Texturing in Blender is annoying but tolerable as a hobbyist. For more NPR control, maybe DillonGoo Studio's fork would be better [1]

> Would it be possible to render retro pixel art from a simple 3D model? If so, could we use this to make a procedurally-generated 2D game?

I've done it before by rending my animations/models at a low resolution and calling it a day. Results are decent but takes some trial and error. IIRC, some folks have put in more legwork with fancy post-processing to eliminate things like pixel flickering but can't find any links right now.

[0]: https://www.youtube.com/watch?v=ljjUoup2uTw

[1]: https://www.dillongoostudios.com/gooengine


The best results I’ve seen at procedurally generated “old school” style pixel art sprites have come from highly LORA-ed diffusion models. You can find some on Civit AI.[1]

So the future here may be a 3D mesh based game engine on a system fast enough to do realtime stable-diffusion style conversion of the frame buffer to strictly adhering (for pose and consistency) “AI” pixel art generation.

[1] https://civitai.com/search/models?sortBy=models_v9&query=Pix...


ah that's very interesting. Will save that link for future reference.


Not 3D, but Stamen (a data visualization and cartography studio) made a beautiful watercolor map renderer:

https://maps.stamen.com/watercolor/#14/52.3718/4.8958


> Would it be possible to render retro pixel art from a simple 3D model?

Not exactly retro pixel art, or maybe it is since it's been 25 years (omfg) but in Commandos 2+ we had 3d models for the characters, vehicles, etc which we rendered at runtime to a 2d sprite which we then mixed with the rest of the pre-rendered 2d sprites and backgrounds.


A more modern example would be Dead Cells


One thing I've had to do while working on my 3D pixel art game is change the size of the pixels as the camera zooms out.

Low res: https://x.com/Navy_Green/status/1525564342975995904 Stabilization: https://x.com/Navy_Green/status/1693820282245431540


Pixel art from 3d models: see Dead Cells. https://www.gamedeveloper.com/production/art-design-deep-div...


The future of 3D graphics is going to be feeding generative NNs with very simple template scenes, and using the NN to apply almost all the lighting and styling.

It's kind of ridiculous that this occurs just as the dream of raytracing hardware approaches viability.


It's kind of ridiculous that this occurs

It hasn't 'occurred' at all. People extrapolated what they saw in the 50s to cars the size of houses, personal flying cars and robot helpers too.


There is certainly some erroneous ‘extrapolation’ going on here.


Right, that's why I pointed it out. There isn't any evidence this is something people even want to happen, let alone that it will.


No, it is you that doesn’t want it to happen and so are having a strangely extreme reaction to a simple observation.

Apparently you are not alone in that.


It isn't a "strangely extreme reaction" to say that something that hasn't happened hasn't happened.


Assuming English is not your first language your reaction is extreme for two reasons: firstly I was clearly referring to the future, and secondly it is happening anyway.

Sadly for you AI griefer bots are a thing, so that side of your reason to exist is also under threat, but you can deny the existence of those too if it will make you feel better.


I was clearly referring to the future

You said "It's occurring" which is the present.

Sadly for you AI griefer bots are a thing, so that side of your reason to exist is also under threat, but you can deny the existence of those too if it will make you feel better.

What is this supposed to mean? You think pointing out that was you said is happening right now isn't actually happening is 'griefing' you? You aren't being persecuted by someone replying to you. You can always avoid saying things that aren't true or give evidence that they are.

If you show me some sort of realtime hallucination that takes rough renders and outputs temporally coherent images in 16ms or less I'll say that you are right that this is happening.


> You said "It's occurring" which is the present.

Hallucination.


You said "It's kind of ridiculous that this occurs". This is the present tense.

I don't think you're hallucinating though, I think you just got mixed up with thinking a wild extrapolation was automatically coming true right now.


> You said "It's kind of ridiculous that this occurs". This is the present tense.

LOL! Convincing griefing requires a slightly larger context window!


This seems like you're trying to distract from backing up what you said with evidence. I think if you had some evidence you would have linked it already.


Ha! No troll ever resorted to asking for citations.

The question is what for? The original claims:

> The future of 3D graphics is going to be feeding generative NNs with very simple template scenes, and using the NN to apply almost all the lighting and styling.

> It's kind of ridiculous that this occurs just as the dream of raytracing hardware approaches viability.

Or what you extrapolated that to in your imagination:

> If you show me some sort of realtime hallucination that takes rough renders and outputs temporally coherent images in 16ms or less I'll say that you are right that this is happening.

These are not the same. If you think so you have serious comprehension problems.

You're a simple troll arguing against things you've imagined. Get back under your bridge.


I just asked for evidence and you instead of showing anything you go to name calling.


I just asked what you wanted evidence for, and you resorted to claiming persecution.

You go by the name CyberDildonics. You claim to think “is occurring” and “occurs” means the same thing, so your ability to understand is clearly limited. The world does not owe you an explanation just because you want one, and insulting those that point this out is classic trolling, so the label is deserved.


I just asked what you wanted evidence for

You can just explain why you think this is happening now, that would be at least some evidence. Are you asking what evidence is for at all? It's so that people don't just say what they want to be true without any checks to make sure it actually is true.


How about https://devblogs.microsoft.com/directx/enabling-neural-rende...

It's almost like some of us actually understand what's coming and aren't just being offensive asses.


This engine uses a Redux-like architecture. You have a State type (containing data like "the position of the black kingside rook") and a stream of in-game actions (like "knight to F3"). Each action is handled by a pure function which converts the current State to a new State. You can either transmit State deltas from the server to the client, or just transmit the actions themselves (https://longwelwind.net/blog/networking-turn-based-game/).

This design makes it easy to implement optimistic updates, rollback, replays, automated testing, and recovery after a disconnection. It's a surprisingly good fit for UI, too; you can render simple games as a React component which takes the current State as one of its props.

However, a stream of context-free actions can be a really inconvenient representation for some games. The rules of a board game are often like the control flow of a computer program: you'll see branching, iteration, local variables, function calls, structured concurrency, and sometimes even race conditions and reentrancy. When you try to represent all of this logic as a State object, you're basically maintaining a snapshot of a "call stack" as plain data, and manually resuming that "program" whenever you handle an action. It doesn't seem ideal.

I've been sketching a board game engine which would represent the game logic as normal code instead. It seems promising, but it really needs a couple of language features which don't exist in the mainstream yet, like serialisation of suspended async functions.


My main pain point with any sort of Flux-like state management is transitions [1]. The state of UI is not fully described by the state of the game [2]. If I play a card, the game state can be instantly updated to the next decison-making point, but in reality I want to show steps of the game through animations, some of which are concurrent and some of which are consecutive. That usually ends up in a mess; and I've never seen someone implement it nicely.

[1] And generally dynamic stuff like drag-n-drop, which is infinitely times simpler in any other architecture than in React.

[2] That is also true for business apps, but their animations are usually so simple you can simply use CSS.


The way I wanted to implement this in my turn-based game engine:

If you implement the deterministic update pattern to handle state synchronisation you can add "event" inside the logic that handles updates that pause the processing allowing your animations to be played. In JS, for example:

    async function handleUpdate(update) {
        if (update.type == "sell-items") {
            this.player.inventory[update.itemId] -= 1;

            await emitEvent("itemSold");

            this.player.money += 10;

            await emitEvent("moneyGain");
        }
    }
Server-side, "emitEvents" would be a no-op. Everything would resolve synchronously.

Client-side, the UI can listen to those events to pause the updating of the game state to see the intermediary state of the game and play animations. When the animation is done, it can resolve the promise, resuming the game updating logic.

If an update arrives while an update is being handled, it can be queued so it can be played after the current update finishes.


I toyed with an approach once that separated animations from game state updates.

Every player action could cause a cascade of updates, which would all be resolved “instantly” to the point no more cascaded updates were left to be processed.

While this is happening, any update that includes an animation pushes that to an “animation stack”, then the animations are played back one by one to show the player what happened. In this animation state most input in disabled and the game is effectively on hold until the animations complete (or are skipped by the player).

The “animations” were basically commands that the Model used to update the View, just with the option to apply them one by one over time. So the model is always up to date as fast as possible as possible, and the view just lags behind a bit and catches up.


I've found in the past its good to have the model updates in the queue so that the animation controllers can be simpler. The animations simply need to observe the model and react to changes, and post events when they complete.


The way I did this was to design a more-or-less monadic container `Result<A>` for all my game logic functions. It batches a sequence of animation steps with a result. It can also model error conditions (like not having enough resources for example). I can then instantiate it any concrete result type, such as a full game state or just the result of individual computations. It was very nice to concisely write complicated game logic with animations while retaining the happy path.

https://github.com/sjrd/barrage/blob/main/src/main/scala/be/...


Interesting. Unfortunately, your repo seems to be private.


Oh shoot, yes. I have imitation copies of the original game graphics in there, and so I can't make it public without violating copyright of their assets. :-(

Here is a public gist with the `Result` data structure, as well a good portion of the file handling all the game mechanics, which should show it gets used. https://gist.github.com/sjrd/34fe234d1b6232cf42ffda5d23292d3...


In my experience, the way to solve [1] and [2] is to design a game state that can also _fully_ describe the state of the UI, including animation cues.


(game dev) What I did in the past was having actions generate both a new state, and a stack of 'instructions' that update the UI, which was deliberately not a 1:1 representation of the game state for the exact reasons you described.

Then you can 'execute' the stack within a command VM of some sorts, where instructions can move sprites around, play sounds, etc. You can have 'high level' instructions ("display the enemy's death") implemented as a combination of low level instructions ('reduce that health bar count until it goes to zero' -> 'change entity X's sprite to dead sprite' -> 'give player 200 gold as reward' -> 'play sound' -> 'change text in the text bar to something' -> ...)

It ended up working waaay better than what I was expecting, felt very easy to reason about, wasn't hard to maintain, and scratched that itch of implementing an interesting solution. :)


I remember someone making a card game GALGA [1] in Haskell and compiling a high-level "rules" DSL to a low-level "animation" DSL and "primitive" DSL for handling animations and state changes respectively.

[1] https://roganmurley.com/2021/12/11/free-monads.html


I agree fully with [1], having recently experienced the pain of implementing a custom drag-and-drop UI in React.

I ended up using ref's heavily to avoid stale closure and async re-render issues. Which basically amounts to circumventing React and interacting with the DOM directly.


Yep, that's the exact issue I wanted to address with my own twist on the idea of an online boardgame engine - I was trying to actually persist the callstack of an async wasm vm function (game loop) execution into a database in rust. It is working in a sense that you can implement battle ships or tick tack toe, but I did not quite finish it. Happy to still make repo public if helpful.

To be more specific, async wasm function was implemented as a poll loop sync function exported to the caller, there was (at the time) no way to move wasm mv memory, so it was persisted while the game was live and replayed from a message log stored in a db after/if preemption.


I agree that asynchronous flows are hard to represent using a state object.

I chose to go with a monadic approach in boardgamelab.app (I'm not limited by language features since I'm designing it from the ground up for this use case). The language is pure and functional with managed effects. You can express things like:

  set of cards -> filter by action cards -> choose -> [card]
  do stuff with [card]
written in a synchronous style, while under the hood it:

1. suspends the rule.

2. waits for the user to make a choice.

3. resumes the rule with the choice made by the user.

(note: listed above is a simplified text representation. The Boardgame Lab structure editor uses a block-based visual language.)

If written in Haskell, the underlying monad would look something like this:

  {-# LANGUAGE ExistentialQuantification #-}

  newtype Rule a = Rule {fn :: State -> (RuleResult a, State)}

  data RuleResult a
    = Done a
    | forall x. Show x => Choose [x] (x -> Rule a)

  instance Monad Rule where
    m >>= k = Rule $ \state ->
      case fn m state of
        (Done a, state') -> fn (k a) state'
        (Choose list m', state') -> (Choose list (m' >=> k), state')
i.e. each rule returns either a completed result or a choice along with a continuation of the remainder of the rule past that choice.


Can you explain more what type of game would need a call stack snapshot? I've never developed a game, but it seems like as long as you store like the initial state and prng you could always get the current state by replaying the full history. All the other logic would be stored outside the state, and only added when "committed". As long as prng is stable and you start from the clean state every time, you'd get the same outcome.


I think I have a good example from Magic: the Gathering.

There’s a card called “Fact or Fiction”. You reveal the top five cards of your deck. Then your opponent splits the cards into two piles. Then you pick one of the two piles to take into your hand.

You’ll need to store structures representing the choices that are intermediary steps (split cards, pick stack) in your state, which is basically function calls and their params (a call stack). This example could get hairier - Magic also features cards with branching logic “choose 1: do a or b”. I can imagine designing cards with large and convoluted possible execution paths.

You could have the card define a schema for state transitions/params and represent all these choices as JSON encoded POJOs, but as a developer it sounds a lot nicer to just be able to suspend an async function every time a choice is made.


I had the same issue in AGoT:BG and I solved it by representing the state of the game as a tree. At any point of the game, the current game state is a leaf of the tree.

You'd represent this kind of choice as a child node. When the user has made their choice, the code can return to the parent node with the choice being made so it can continue with the next "step" of the game.


This is the correct response. Hearthstone is structured like this internally.

If you are curious about it, I wrote a cc0 spec which stores hearthstone game state in xml. It’s based on how hearthstone stores game state on the server and client, and it was the first time a replay format was created for hearthstone: https://hearthsim.info/hsreplay/

Incidentally the UI we wrote for hearthstone replays is a react app. It’s funny because looking back it was the first time I used react and typescript, and both were not at all adopted by the js community yet at the time.

https://github.com/hearthsim/joust


That's the exact approach I'm considering for the new engine I mentioned!

Although that strategy enables you to store and recover the state of a game, it doesn't give you the ability to inspect a snapshot of that state. How can you print the card which has just been played, if that data only exists as an argument in the call stack of a suspended async function? In the same way that you can't inspect the local variables captured by a closure, mainstream languages also provide no way to inspect a suspended stack frame.

This problem interferes with debugging, consistency checks (e.g. hashing the game state to check that two clients are in sync), and unit testing.


How does secret state fit in this? If you want each player hand to be secret, then each player has its own state?


boardgame.io only runs game logic on the server, and it censors the State just before sending it to each client. This strategy makes the UI feel less responsive, but it keeps things simple.

The Swords and Ravens blog post recommends resolving actions on the client when they don't require secret information, but resolving other actions on the server. You'd also need to resolve actions on the server when they involve RNG.


I don't recommend resolving actions on the server in any situation:

For actions that require secret information, you would filter the actions sent to the client of any secret information and make sure the code handling the action can handle both the action and the filtered actins.

For actions involving RNG, make all randomness rely on a seed. This seed would be stored server-side and passed along the action when sent to the client. This makes sure the clients can deterministically reproduce the update.


Interesting, would you share the link of this post please?



You're completely right, but I think it's worth adding that the O(n^2) to O(n) change isn't specific to React or UI. That same improvement is often seen when migrating other code from a mutating style to a pure-functional style.

"A pure function which transforms the entire input into the entire output" is obviously the simplest possible architecture for many programs, but people hesitate to use that architecture because of performance concerns. In practice, the baseline performance is often faster than they expect, and it can be made much, much faster using strategies like memoisation and fine-grained reactivity.


> "A pure function which transforms the entire input into the entire output" is obviously the simplest possible architecture for many programs, but people hesitate to use that architecture because of performance concerns. In practice, the baseline performance is often faster than they expect, and it can be made much, much faster using strategies like memoisation and fine-grained reactivity.

But before React came along, you just couldn't do this without major UX breaking bugs, because of how the DOM worked.

Say you have a form that you want to change depending on the state of the app. If the user is typing in a form field while an update to the app state comes, and a pure function that transforms (app state -> DOM/HTML output) resets the form (meaning removing the old out of state DOM and replacing it with the new DOM), the user loses focus on the form. So you have to add some kind of logic where the app remembers what form input the user was focused on, where in the field the focus was, etc. The more complex your app is, the more complex the DOM reset logic became, and you cannot abstract your way out of it with pure functions, because the DOM that relies on mutation slowly creeps into your pure functions anyway.

React changed this, because it gives you a pure function interface, but resets the DOM using mutation functions i.e. native DOM methods, surgically. This is achieved with the VDOM (Virtual DOM), by diffing VDOM states and then reflecting that to the actual DOM. This means when the DOM resets, there's no problem with elements getting removed and added back in, and the focus states etc. don't get thrown away with the DOM. Before React, nothing like this existed.


> If the user is typing in a form field while an update to the app state comes

Could you give a practical example of what you mean here? I can't quite wrap my head around what kind of interaction you're describing.

Do you mean some kind of scenario like a shared document with multiple people editing it? This is a very niche case.

> This means when the DOM resets, there's no problem with elements getting removed and added back in,

Could you give a practical example of this? I've been building web apps for a long time and I don't know what "when the dom resets" means.


The problem described by antris is that, if a developer were to naively tear down and rebuild the entire DOM tree on each state change, the browser would discard some important state which belongs to the old DOM nodes. This state includes the text selection, keyboard focus, mouse capture, scroll position, and the progress of CSS transitions and animations.

React solves this problem by building a virtual DOM, and then conservatively updating the actual DOM (sometimes just mutating individual HTML attributes!) so that this state is preserved.


React doesn't have this "pure function" feature what-so-ever. hooks are magic stateful functions, not pure functions. They behave differently the second time called and therefore have all kinds of side-effects and restrictions on when, where, and how they can be used.


Accumulative recursive functions also behave differently the second time they are called...

Hooks are a declarative DSL for accumulator arguments to the recursive function (the component).

If you would rather rewrite the render loop in continuation passing style, and have a 46 line recursive call expression which conditionally changes like 15 immutable parameters to set up the next render iteration for your component, I'd like to see the code when you are done.


We've been doing the O(n) thing forever with PHP and CGI since 1995, the issue is that it required constant whole-page reloads and was a poor experience that got worse the more interactive your webapps got. React let you do the same thing but made it fast(ish) with local updates

We actually see similar innovations on the FP side as well, with persistent data structures that allow structural sharing so your "copy and update" operations can be fast enough to be usable (even if still not nearly as fast as in-place mutation)


I last read that story nearly a decade ago, I think. This time around, it feels more real. The engineers follow silly instructions from people with money, and then...


This is not how I read the story... the people you are referring are monks in Tibet much more than "people with money".


The monks were just gig workers.


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: