EveHeader

Pathfinding is getting close to wrapping up I think. I’ve got the path selection algorithm working, and I think it’s properly detecting when there’s something blocking a chosen path and redirecting around it just as it should. However, testing has revealed some flaws in the initial generation of the level navigation map, with some ground nodes not connecting to others which they logically should, and sometimes connecting when they shouldn’t as well.

With another day or two I should be able to fix that problem and make the nav map as perfect as I thought it was until a couple of hours ago. After that, assuming that doesn’t lead me to discover a new algorithmic problem, I move on to stage three of pathfinding, which will I think be the easiest: Taking the waypoints generated by the pathfinding algorithm, giving them to the entity, and having the entity use them to traverse the level. I’m kind of wondering whether it would be better to have the entity actually moving and jumping like the player character does, and hope that all the calculations are accurate enough that it doesn’t find itself obstructed in an unexpected way, or to just generate a high resolution series of interpolated waypoints and just move the entity along that like a roller-coaster track, playing the appropriate animations to make it look like it’s moving the normal way. The latter definitely seems less likely to break, but more likely to look weird or conflict with something else.

I guess probably the way to go is to start out doing it the legit way, like an AI-controlled little player navigating the level, and then if that doesn’t work well I can keep the track-path method as a backup. In any case, I hope to have these guys moving around by the end of the week, at which point I can go in and add a bit more nuance to their behavior and start working on their prototype animations for real.

 

DarkSign

Dark souls is frequently described as masochistically difficult. I don’t think this is very apt: Masochism implies a state of being acted upon, of being made to suffer by an outside force. Dark Souls never makes you do anything, only invites you to do it to yourself. Dark Souls is a raw onion, a bottle of sriracha placed suggestively next to the sandwich fixings on the table. Nothing is required of you, but the challenge is implied.

The distinction becomes clear when you compare it with other games described as masochistically difficult, such as I Wanna Be The Guy. IWBTG acts upon the player, manipulates their expectations only to betray them. It pulls the carpet out from under the player, instead of laying out a carpet of spikes and inviting the player to walk upon it. Dark Souls isn’t hard just to fuck with you – well, usually. It’s hard because that difficulty is the only way to convey the oppression and disease that is endemic to the story it is trying to tell.

Dark Souls is a game that shows more than it tells, but it’s also a game that listens more than it speaks. Playing most games is like a conversation with someone who you can tell is listening to you just long enough to construct and express the thoughts that are in their head. They tell the player who they are, how they act, why they’re there, and why that’s awesome. Dark Souls is content to let the player be who they are and act as they will. It doesn’t care why they’re there, and it doesn’t think that it’s particularly awesome that they are. It just presents itself, and waits, and lets the player occupy that space in whatever way suits them.

The silence and withholding stoicism of Dark Souls isn’t just about minimalism or about telling a story through gameplay, it’s about giving the player room to make that world their own.

Games lost something for me when the characters started talking — at first in little yips and exclamations, then in progressively longer-winded cutscenes. The more they talked, the less room there was for me. When a character speaks through text lines, we’re still part of the process, we’re the reader, the interpreter, parsing the sequential art and the dialogue into a coherent narrative. As technology has progressed, as we’ve been able to add more life and detail to our worlds, we’ve reduced the ability for our players to invest them with a life of their own.

I think part of the reason why people think of Dark Souls as a vaguely retro, old-school game, isn’t because of its punishing difficulty, or its structure, but because it’s willing to shut the fuck up for a moment in the way that those games were pragmatically required to by the limits of technology.

The only part of Dark Souls that never shuts up is the people who love it.

Fuckin’ Dark Souls, man.

EveHeader

Spent all week working on pathfinding stuff. This is, realistically, probably something I shouldn’t be spending this much time on. I’m getting sidetracked. Still, getting sidetracked like this on difficult but interesting problems is good for me, at least in small portions. It helps me keep on learning instead of settle into the same grooves, makes me in general a better artist even if, in specific, a bit worse at producing this specific piece of art. So I don’t begrudge myself the time.

As I understand this problem now, it’s basically split into three parts: First, mapping the terrain. Though the terrain is already in a format easily read and perfectly suitable for simple interactions, understanding the layout of a whole bunch of undifferentiated tiles is something that’s difficult to teach a computer to do. This is mostly what I’ve been spending the last week on, putting together the best map of the terrain I can, as detailed as necessary without any false or extraneous information. This is what it looks like now for a simple level:

Pathfinding02

The lines show where each node is looking for possible connections for where to move next. Note that the nodes underneath the platform don’t try to connect directly to it, since it would be impossible to reach there with the solid platform in the way. Unfortunately, for a more complex level this map takes about a second to generate, which is too long to do in real-time every time a level is loaded. Thus, I’m probably going to have to make these nav maps get saved alongside the map tile data, and just get generated whenever the level is modified or loaded.

So that’s the first part. The second part is finding a path through that map, getting from the start tile to the goal tile. This is what I’m working on now. To start with it’s simple enough, just chain through the connected nodes and find the closest to the start and the goal, and continue until you either reach the goal or fail to do so. That’s the part I have done. The tricky part is that in between each connection I need to make sure that the path isn’t blocked, which means projecting the character movement as they walk or jump from one block to the next, make sure their jump is powerful enough to bridge any gaps, make sure that when attempting to jump across they won’t be blocked by the terrain. That parts a bit complex, and is what I’ll be tackling tomorrow.

The third part I haven’t tackled at all yet, and that’s converting the path through the level into a set of instructions for the entity to move through, and making sure it executes them perfectly enough that it doesn’t, say, miss a jump and fall into a completely different part of the level and generally muck things up. I don’t think that part will be too hard, but I’ve certainly been surprised by that sort of thing before.

I’m hoping that within the next few days I can have a simple case of this running, a basic enemy that just follows the character around using this pathfinding algorithm, before I built it out into something a bit more nuanced. Either way, once I have this, if I do it right it’s something I should be able to use for years to come, for basically any game built on this same kind of 2d platformer movement system. Implementing enemies in general will become much easier in the future, since I can just pass all level navigation tasks down to this algorithm.

I ran out of time and the work I had wasn’t coming together so no post today. Here’s another compensatory music that I made last month.

EveHeader

Progress has been going slow, but it’s progressing. I’ve been slowly building up the behavior code for this enemy type, but I realized a couple of days ago that I’m probably going to need a robust pathfinding solution rather than something kind of half-assed, so the last few days have mostly been research into how pathfinding works, specifically within the context of a 2d platformer.

I’ve got a pretty good idea of the kind of approach I want to use now. This is taking a long time and it’s been a week or two since I’ve made visible progress in the game. which is frustrating: But, the good news is that whatever I come up with here should be highly generalized and reusable for pretty much any 2d platformer I make in the future.

Here’s the algorithm I’m currently planning on using, (copied largely from the daily devblog, where I came up with this approach yesterday):

Step 1: When each level is loaded, generate a navmesh. This is basically just a fancy name for a grid with every ground tile marked, a ground tile being defined as any tile with a slope of 1 or less that doesn’t have a solid tile of some sort directly above it.

Step 2: Run the A* algorithm as described in this video with the start value of the ground tile beneath the entity and the goal of the ground tile beneath the player. Non-ground nodes are disregarded for parenting purposes, so ground surfaces are parented to whatever the last ground surface was navigated from to reach them rather than the closest non-ground tile.

Step 3: When a path is completed to the player, perform the following tests to make sure that it’s valid:

  1. Above each ground tile, ensure that there’s enough clearance above to allow the entity through. I realized today that I can speed this up by storing the available clearance above each tile in the navmesh generation phase.
  2. At each gap between ground tiles, ensure that the entity’s jump is powerful enough to reach the other side of the gap
  3. Ensure that, if jumping, the minimum-possible jump will not be obstructed. It doesn’t matter if the maximum jump is obstructed: If the minimum is obstructed and the obstacle is possible to jump over, it should have its own ground surface nodes that can be navigated by jumping and get caught in subsequent passes. This assumes that all ground surfaces are navigable.

Step 4: If any of those tests are failed, revert the path to its earliest failure point, mark that node connection as intraversible, and try an alternate path.

It’s entirely likely that I’ve overlooked something with this algorithm, but it’s a good solid plan to get started with.

FallingDown

America has a relationship with violence that is, let’s say, a little too friendly. That’s not to say that the American mindset is violent necessarily, that we are predisposed to do violence, but that so much of our outlook is defined in terms of violence. The distinction isn’t obvious, but here’s where games provide a useful demonstration: Most games are about shooting things, of course, and that’s partially habit and fashion at work, but when we make games about choices those choices are themselves framed in violence. To kill or not to kill, that is the question that so many games boil down to, even when they tout their freedom.

It’s not just games. We construct this dichotomy everywhere. Either suppress the riot with brutal force or do nothing. Either invade a country or do nothing. These are the nails for our hammer. Other solutions are not even dismissed, so much as never even considered. We have constructed a vocabulary of violence, of do or die, and forgotten that any words exist beyond it. Questioning the decision to use violence is similarly always contextualized as an argument to do nothing, “So you’d rather let the terrorists do whatever they want?” Ignoring the wide realm of options in between doing nothing and violent enforcement.

We question the necessity of violence, but rarely its utility. We have violence defined as The Thing That Works in our minds: If you can’t pick the lock you kick the door down, if the vending machine doesn’t work you knock it over, if the ants get in your house you poison them. For simple problems, sometimes it does work. But simple problems aren’t really problems, and by saving violence as a last resort we are frequently reserving our least effective option for our most desperate moments. This is most egregiously apparent when it comes to the many justifications our government has recently, shamefully, deployed in service of its ongoing torture and interrogation programs, violent acts which are of little demonstrable security benefit. People who defend these programs do so by balancing the lives of these torture victims against hypothetical lives saved, neatly eliding the questions of whether those lives are actually saved by these acts, whether there would be any more effective way to save those same lives, or whether more other lives are lost because of consequences of systemic state-implemented torture.

We American’s love justified war. Every narrative centers around it. He killed my family, so I can kill him now. He’s going to blow up a building, so I can kill him now. This is every fucking movie and every fucking game, the story of how the bad guy did a bad enough thing that it’s okay to kill him now, and the journey of how he and everyone who works for him gets killed by the main character, and maybe there’s some kind of prize at the end for doing such a good job with the killing. If it’s a kid’s show then instead of killing them he just beats them up and they do it once a week, each week a different justification for the inevitable ass-kicking. What’s the first thing everyone talks about doing with a time machine? Assassinating Hitler. Trying to prevent the greatest massacre in history by murdering someone. Not only is it unlikely to work, since Hitler was the product of his environment and someone would likely have filled his role if he weren’t there, but it’s also just one of many ways to approach the problem. Why not just sit him down and explain the tragedy that will occur if he follows his current course? Why not provide him another path in life? Why not get him into art school? Of course, it’s a bit galling to do favors for Hitler, but at the point where you would presumably contact him using your time machine he would not yet be Hitler, just one Adolf among many. More likely, a serious attempt to prevent the tragedies of the second world war wouldn’t involve Hitler at all, but trying to sow the seeds that unravel the national socialist movement before it gained its murderous momentum.

We so desperately want to kill Hitler, though. We so desperately want to be the unequivocal good guy kicking the shit out of the definitely bad guy, we will do whatever we can to construct those bad guys and turn ourselves into good guys. We want to win world war 2, over and over again, more than we want to prevent that war from ever happening.

This maybe sounds like some ‘won’t someone think of the children’ Jack Thompson horse shit, but this isn’t about the violence itself being damaging or immoral: It’s about the narrative we construct to say that our violence is justified — and I’m not even saying that it isn’t, that violence isn’t ever justified or anything like that, merely that boiling every conversation about the usage of violence to whether it is or isn’t morally okay in this circumstance is completely myopic and misguided. Sometimes the relevant question isn’t whether it’s okay to put a sledgehammer through your wall, but whether it’s useful for your goals.

People in power all over the world tend to have a child’s understanding of violence. Like gangsters, they want to ‘make a problem go away’, and by their lauded power and influence they believe that because they can make that ethical compromise that they should, because that’s the kind of big weighty decision that big weighty men make. Add to that a national desire to be the cowboy who wears the white hat, who everyone knows is right because he’s on the side of justice and has a shiny badge, and you have an explosive mixture. It’s just now starting to really mature, and the explosions are only going to get bigger.

EveHeader

As alluded to yesterday, I’ve been feeling somewhat off of my game recently. The good news is that, while I thought there were two major bugs in the collision detection system, they may have had a common cause since fixing one appears to have fixed the other. I won’t quite commit to saying the collision detection is done, and I definitely won’t say it’s perfect, but it may be at a quality suitable for a finished game. I’ve seen worse in released games, for what that’s worth.

The bad news is that I haven’t gotten much more than that done this week. I spent a day tidying up and making minor improvements to my first simple enemy type, and since then I’ve been nibbling around the edges of creating a second far more sophisticated enemy type. This enemy needs to have some basic understanding of its environment to do some minor navigation, and that kind of generalized perception, as easily as it comes to us humans, is a real bitch to program. I’ve got a simple line of sight function which re-uses a bunch of collision code which I can now use to detect whether the enemy sees the player or not, but the hard part is trying to get this enemy to get close to the player so it can attack without getting stuck on terrain or falling into a section of map it shouldn’t be on.

Honestly, I don’t think many 2d platformers have enemies with this kind of behavior, which is something I’ve been thinking about. Is this kind of behavior rare because it’s difficult to implement, or because it’s unnecessary, or because it’s unfun? I feel like adding some basic navigation will make these enemies feel a lot more alive and interesting, but at the same time it’s sometimes important for enemy behavior to be simple and predictable in games so the player doesn’t feel like the carpet’s being pulled out from under them. Realistically, there’s probably no way to ensure that this will work aside from just implementing it, but that means that if it ends up being shitty I’m out a lot of work hours.

Oh well. We’ll see, I’m pretty sure it will work in some form; as with most such things, it depends on the execution of the idea more than the idea itself.

Follow

Get every new post delivered to your Inbox.

Join 5,569 other followers