Writing better code: The self taught coder

How is this even possible if you’re doing a >= comparison of elapsed hours vs hours in a day?

I don’t know, I thought it might have something to do with discrepancy/conflict between the ‘step’ event (game checks status X times per second) and the keyboard input event. But I haven’t dug into it yet, and may not have to if I end up using different logic.

I would try placing all of your movement code and anything else related to pressing those keys right into the step event.

I recall some of my students having issues where they did a keyboard check in the step event to take care of movement, but then used the input event (for the same keys) to do other things. It would sometimes mess things up.

I’m interested in your line of sight solution. Are you blacking out the tiles or are you drawing over them with a surface?

I’m using the gamemaker ‘draw event’ to draw a black square over the affected tiles. The logic lives in a control object which, at the moment, just sends a “for” loop in the 4 cardinal directions to look for an obstruction, then if it finds one, calls a function to draw the darkness cone at that X or Y position. Grafted on to that is the ‘adjacency check’ which, if an obstruction is found in a cardinal direction, asks ‘is there another obstruction adjacent to this one?’ and if so draws a darkness cone behind that one too, repeat until no more adjacent obstructions. This is obviously an incomplete solution, and I’m still puzzling out the details. For certain obstruction arrangements it perfectly matches the Ultima III model, but those diagonals are still outsmarting me.

I had earlier dabbled with an approach that put the logic inside each map tile, saying “is there an obstruction on a direct line between me and the player?” and then, if yes, changing the sprite to a black square, but the resulting darkness patterns were a bit weird and anyway it was way too processor intensive.

Roguebasin has some articles on field of view and different algorithms. One that I’ve successfully implemented is shown here: http://www.roguebasin.com/index.php?title=FOV_using_recursive_shadowcasting

Yes, I’d go straight for some simple raycasting here. Just project a ray from the middle to each of the squares on the outermost edge of the frustum, and Colorado all the ones between a collision and the edge in black.

I’m not sure how much game.maker helps you out here. Does it have collision detection stuff?

I said this previously and I’ll say it again: but this sounds very wacky :) You basically have two parallel sources on input trying to mutate the same state. I don’t know how game maker works and if e.g. it forces that timer even to run on the main thread, but even if it doesn’t it seems a bit odd.

You said time only moves when the player does, so how come you have this event firing every second to check the status of things?from what you explained the explained the state can only ever change in direct response to player input/moving, so therefore all state handling code should ultimately be trigger from player input/moving.

Actually maybe I don’t have a step event for that. I need to check the code again.

Sadly, from what I’ve read about raycasting it doesn’t seem all that simple, but the only way to learn is to dig in…

I was hoping Game Maker would have stuff to help you project lines across a 2d grid and tell you when you hit stuff. (You could even keep a different “visibility surface” that is simply black/white if it can only do that stuff in a graphical sense)

At it’s heart you’re just drawing a line from your player to the edge squares and quantising the line into square-steps and saying “for each step, which square is it in?” If you have to make your own, try here:

https://www.redblobgames.com/grids/line-drawing.html
https://www.redblobgames.com/articles/visibility/

You can raycast in Gamemaker. I think they’re called collision lines.

Yeah, I tried using the built-in collision line function but the results were not pretty, just kind of weird and wonky.

I’m interested in solving the puzzle of exactly recreating the Ultima III line of sight, haven’t quite given up on that yet. It was already changed for Ultima IV – in III, if you see a single opaque tile (e.g. mountain, forest, wall) in a cardinal direction, it casts a cone of darkness behind that tile.

u3-eastwestobstr

Whereas in Ultima IV it just casts a single line of darkness. It’s interesting to try to reverse engineer this stuff.

u4-darkness4

I also assume those systems were very processor-efficient given the limited computing resources of the day.

Anyway the cardinal directions are easy, the not-quite-diagonals are where it gets a bit more complex.

If I can’t figure it out, I’ll come at it with another approach, either some kind of raycasting from the Roguelike book, or just go with flood fill. But I’m still having fun poking around.

I suspect it’ll be harder to copy the Ultima 3 one than to do it “naturally”, as the U3 one is obvious designed to be performant on an ancient 8bit machine rather than correct.

Ever thought about decompiling the game and inspecting the LOS code?

Luckily the reverse engineering has already been done: http://crpg.adamantyr.com/article_04.htm

Edit: fixed link, was posting from a phone.

Wow, great link, thanks!

Ever thought about decompiling the game and inspecting the LOS code?

This is a bit over my head. Somebody did post U3 (DOS version) source code on Sourceforge, but it’s assembly language and only the comments are of any use to me. I didn’t find any relating to the line of sight when I went through it.

I vaguely remember implementing this for omega 30 years ago… Now what did I use? Probably Bresenham line-drawing to every point in range, inefficient as that may have been, but maybe orthogonal+diagonal…

You worked on Omega? Cool!

omega the roguelike, not omega the programmable tank, however.

Good find! I did a quick bit of googling for U3 remakes and for articles about the LOS, but didn’t come across that page. That entire site seems to reverse engineer every aspect of the game.

Depending on what you want to get out of making this game, @Gordon_Cameron, it bight be a bit too “spoilery” for you? :)

@Miramon It looks like people still work on Omega. Do you contribute, or did you pass the torch to someone else?

Just for the heck of it I decided to try again with the ‘collision_line()’ function which checks if a particular type of object is found between two points.

I made a 2D array containing the coordinates of all tiles around the edge of the visible screen, and then loop through this array and use collision_line() to check if there is an obstruction between each border tile and the player.

I haven’t gone beyond that to actually draw the darkness tiles behind the obstructions, but I have written code that puts a cat on each obstructed border tile!

No one works on it so far as I know; they just pretend to. It’s PD. I haven’t touched it since the 80s, myself. My first real C program.

I haven’t played it but the CRPG Addict’s response certainly intrigues me…

Within about 10 minutes, Omega went from being a game that I was going to blow through to get to Pool of Radiance to a serious contender for the most intriguing discovery since I started this blog.