Indie game storeFree gamesFun gamesHorror games
Game developmentAssetsComics
SalesBundles
Jobs
Tags

[Devlog] Arcane - a tile-based puzzle game

A topic by rabbit created Feb 02, 2019 Views: 1,690 Replies: 23
Viewing posts 1 to 16
Submitted (1 edit) (+1)

Hello, my name's Alex! I'm here to make a game and have a good time!

This is actually my second game jam, because I participated in the Winter 2018 My First Game Jam. But I didn't complete it because my computer broke. I'm hoping to use this jam to relearn my way around GameMaker Studio and to learn a few new tricks along the way.

I'm going to do this by making a puzzle game!

ARCANE

I want to make an old-fashioned puzzle adventure game, like DROD or Chip's Challenge or Adventures of Lolo. Games like this appeal to me because they're full of ideas and full of personality. I think the top-down character control of these games will be easy enough to program from past experience, and easy to build on and extend.

I'm calling my game Arcane for now. This will be an occult-themed turn-based puzzle adventure with a block-moving gimmick. The player controls a character with the keyboard, Chip's Challenge-style, but can rearrange certain blocks in the room with the mouse, to clear or block paths, weigh down switches, etc. I'd like each level to be an assemblage of individual puzzle rooms as in DROD, so that levels can be easily rearranged and puzzles can be swapped in or out, and so that the player can tackle puzzle in a non-linear order.

(People who were around for My First Game Jam Winter 2018 might remember me doing something similar last year. I made most of the battle system for a puzzle RPG I wanted to make, which also involved shuffling blocks around. I still want to make that, but I think the programming I've done needs to be redone from the ground up, since it's very patchwork, borderline unreadable, and impossible to extend without breaking everything else. This game is being coded from scratch using a different way of handling blocks - perhaps I'll learn something from this which I can bring into the puzzle RPG!)


Goals (in rough order of what I want to do)

This is the minimum I want to accomplish to make a functioning puzzle game:

- Get a character moving around a room and colliding with objects and walls
- Get a system of picking up and placing blocks and objects with the mouse working
- Get the character-moving and the block-moving working together (e.g. make sure that the player can't place blocks on their character)
- Add an objective for the player (I haven't decided what yet - collect things? Reach a goal tile?)
- Add a simple enemy type, whose AI is integrated into the turn-based system (probably nothing more complex than "is the player in Direction X? If so, move in Direction X")
- Add one or two other basic puzzle elements (e.g. floor tiles which blocks can't be placed on)
- Build some basic puzzles
- Make a nice HUD / menu

Once the basic game is functioning, if I have time, I can work on some bonus features:

- Make the player able to move from room to room
- Add some extra puzzle elements as I think of them
- Add some simple NPCs (nothing more than walls with dialogue, really)
- Make pretty tilesets and scenery objects
- Make some good tunes to listen to while the player solves puzzles
- (advanced) Get checkpoints working so that the player can save progress in a room and doesn't have to start over if they make a mistake
- (really advanced) Figure out how to save games! If this idea is good and I want to make a full game out of it, I want to know how to work with save data


UPDATE 1

First big decision is how big to make the game screen. I want to have a main window where the puzzle lives, and a sidebar to display game information and menu options. This suggests that a widescreen ratio would be best, so I'm working with a resolution of 640x360 (to be blown up to 1280x720 when you play, so that you're not squinting at the screen).

Normally you'd work with 32x32 sized tiles in Game Maker and other applications. Here, I'm working with 20x20 tiles. This allows me to fit more puzzle space onto the screen - my puzzle window is now 24x16 tiles, leaving space for a border and a sidebar. The small tile size lends itself to simple chunky pixel art, which is probably good for making the levels as readable as possible. You can't divide a 20x20 tile as neatly as 32x32, but because everything in this game is going to snap to a grid, that shouldn't be an issue.

With this decided, I made a little player character to control.

Player character screenshot

here she is!

I want an occult theme for my game, so I made the PC a black cat for now. The sprite is 20x30, with a 20x20 hitbox, so that the top of the PC's head overlaps the tile above without colliding with it. I've done this because I think it looks neat.

Next step was to make the PC move. I've forgotten how to code in Game Maker, so the programming here is not so good, but here's where I ended up:

PC movement

there she goes!

The game adds or removes 20 pixels to the PC's coordinates depending on what you press, so that she stays snapped to the grid. You can use WASD or the arrow keys here. (Something I need to think about is how to set up different control schemes or let users define their own controls, since I know that WASD doesn't work for every keyboard!)

Walls next. Wall obejcts are just big purple rectangles in the room editor .The game canels your control input if your move puts the PC on a wall. I tried using tilesets here, a skill which I've never tried in Game Maker without a tutorial; I made some simple wall sprites which I painted over the top of the actual walls.The game looked like this when I was done:

PC wall collision


This looks surprisingly pretty, imo! The advantage of tilesets seems to be that you can add extra sprites and make your levels look fancy while keeping the number of objects to check for collisions with low. My main concern is that if I use a lot of tilesets at this early stage, it'll be more work rearranging levels when I need to test something. I ended up removing the tiles for now, to be put back when I've built the engine up more and can start thinking about puzzle design - you'll see the base purple walls in the next GIF.

The PC is functioning. Time for blocks.

In my last game jam project, I did a puzzle RPG battle system about moving tetrominoes to match a larger shape as closely as possible. Each tetromino was generated from individual blocks whose coordinates were stitched together into an array representing the entire tetromino. This allowed randomisation of tetrominoes, reduced the number of sprites and objects I had to code, and was good for the shape-matching system I created, but the code was dreadful to write and read. I commented it as well as I could, and I still don't know how it works now.

This game will require hand-crafted puzzles rather than randomisation. So this time around I'm going to make block shapes individually. This will mean a lot more sprite work, but the game engine isn't complex, so the code should be far neater. In fact, I can set up a basic block as a parent object, and all other blocks as children no matter what their shape is. It also allows me to expand the types of puzzle possible in this engine - for example, locks could be sprited as jigsaw pieces to make a picture.

I've started with a basic 1-tile block, which will carry the code that all other blocks inherit:

block


Most of the sprites in Arcane are flat saturated colours so far, so I think this greyscale gradient is an interesting contrast. Hopefully it'll be easy to spot in a busy puzzle room.

I coded a state machine for the block that tells it whether it's being picked up for stationary, and a state machine for the PC that tells her whether she can move or not. Clicking on a block picks it up, and disables the PC until the block is placed again. Thinking about it now, this probably should be one game-wide state machine rather than individual state machines talking to each other. But I worry if if I try to do everything in one state machine, I won't be able to disambiguate between blocks (that is, if I try to pick one block up, all of them end up moving).

Right now, all that happens is that a moving block sticks to the mouse until you click again to place it. The result looks like this:

block movement

i'm not sure why the cursor is so far away from the blocks in the recording.  You click on the blocks directly to move them. Also no tileset anymore in case I need to rearrange the walls for testing later

It's clearly unfinished - the blocks don't snap to the grid and don't collide with anything. But it's a start!

There's another problem with this, actually. Clicking on a block seems unresponsive - it feels like it takes a quarter of a second to register (whereas moving the PC with the keyboard feels much quicker). Perhaps this is because the block is using precise collision checking, which checks the sprite exactly rather than using a hitbox. (This is an investment in later collision detection with more complex block shapes, where using a simple hitbox won't do the job right.) Or perhaps it's because the code for picking up blocks is a twelve-car pile-up of if conditions.


I think I might be the coding equivalent of those people in infomercials who throw bowls of popcorn all over the floor and turn to the camera like "there's GOT to be a better way!!!" Anyway, I'm worried about how slow it feels to pick up blocks, but once they've been picked up they move around responsively. And it's only a turn-based game, so it's not like any lag spikes are going to trip players up. But if it gets significantly slow, I'm going to have to rethink the engine a bit.

Anyway, that's where I'm at, 8 hours into the game jam! So far so good!

Submitted

Update 2

Did some more work on moving blocks. Now they snap to the grid, it's obvious when they're being carried, and they won't be placed on walls or other blocks.

good block movement

by the way, the floor is a little prettier because I got bored and redid the floor bg

Obstacle detection tripped me up. I wrote code so that a block couldn't be dropped if there was a block at that point, but it kept detecting itself and refusing to be placed. Tip for Game Maker devs, if you're using position_meeting for collision detection and your code isn't working, try using place_meeting instead - that's the one that checks collisions for your object instance rather than a single point.


The next step is to rotate blocks. When the player clicks the right mouse button while holding the block, I want to rotate it by 90 degrees.

I'm completely stuck now, though. When I rotate a block's sprite, the collision mask changes in a way that doesn't match the rotation but which I can't figure out. Like so:

block rotation mistakes

I don't know why the player character is blinking in these GIFs - I don't think she's doing that in the actual game?

I suspect the sprite is rotating around the origin point incorrectly, or that the mask is cut off by the changed dimensions of the rotated sprite. The origin is in the top-left corner of the unrotated sprite, which is why it moves so much when it rotates.

But I can't figure out how to fix it. I can't find any helpful documentation or tutorials online, maybe because they're focusing on I could make separate sprites which are the original sprite rotated by 90, 180 and 270 degrees and change to those, but then I'd have to do that for every single type of block, and write arrays for each block to read to figure out what sprite to change to next. That doesn't appeal to me.

The simplest solution would be to not let the player rotate blocks. That would be fine, and probably easier to design puzzles around, but it's not quite as exciting. I'll sleep on this, and if I don't get any ideas, I'll just cut out block rotation press on with developing the rest of the game.

Submitted

Update 3

I gave up on getting blocks to rotate for now, and started working on other things.

I think I want the player to collect things in each puzzle. So I've been drawing gemstones this morning. Here's a quick puzzle room I threw together to show off how the game is looking.


(I don't know why ShareX thinks the mouse cursor is that far to the left. I'm clicking on the blocks, I swear.)

The big red gemstone is the goal of each puzzle. For now, collecting it just resets the room. I've also added little green square gems that essentially act as keys - collect them all to open the doors marked with a square. The doors lose their collision mask when opened, so that you can put blocks where they used to be.

I also added the beginnings of a sidebar menu. Only the reset button does anything, and it just restarts the room for now.

The Save State and Load State buttons are for an idea I've had. I want the player to be able to save the state of a puzzle anywhere while solving it. To do this, I think I'm going to have the game save the coordinates of each item in the room, and restore them when the state is loaded. This means keeping all the objects in play somehow, so that when you restore a state the game doesn't crash trying to find the coordinates of an item which has been destroyed. To avoid this when I try to implement this, when you collect gems, they're not actually collected - they just get moved way offscreen where the player can't get them. This feels dumb, but it seems to work!

I've spent most of my time since this doing programming grunt work. I want to get a control object which can keep track of every significant object in a room, so that I can have it run most of the scripts in the game. Right now, keys and doors are completely separate, and the door has to keep checking every frame to see if it should open. I want the control object to keep track of both keys and doors, making it easier to run the door opening script only when needed. So I started on that this afternoon, also setting it up to save object data for the save-state thing I want to do. It'll probably be another day or two until this is all up and running!

I've also done some work on sprites and music whenever I got bored of the coding, but none of that's ready to show off yet.

Host(+1)

dang i was gonna say your icon looked so familiar! it's great to have you back. it looks like you've made some really solid progress so far too. i love the tilesets.

i'm not too familiar with gm unfortunately so i'm not sure how to solve the rotating issue--maybe if there's a way to set the origin on a sprite differently or something...? i did a quick google search but im not sure if this would be helpful: https://forum.yoyogames.com/index.php?threads/attach-object-on-a-fix-rotation-po...

best of luck with your game!

Submitted(+1)

Thank you, J! (My icon is the rabbit character in TeeKO, objectively the best character)

That's a helpful link, thanks for finding it! It looks like "offset" was the word I was looking for, not origin. I think I'll ignore getting rotation to work for now while I work on other bits of the game, but I'll come back to this later!

Host(+1)

sweet! glad it could be helpful

Submitted(+2)

Update 3.5

Very little progress today! Busy working on my CV and job applications.

I realised I don't really have a clear idea of how I want to structure the core game loop. So pretty much all the game jam work I've done today has been planning game states on a flowchart:


I think when the player moves, the initial collision checking is just to check if the control phase needs to do something. For example:

- player picks up key
- that key's "collected" state is switched on
- enemy objects move
- the game checks all the keys: all "collected" keys get moved offscreen, and if all keys are "collected", the game makes a note for when it moves on to checking if the doors need to be opened

This flowchart needs refining a bit (here, the player can die when a door closes on them, but the player needs 2 turns to move to the other side of a 1-tile-wide door - that means fewer opportunities for puzzles which require precise timing, so that idea wants tweaking). But it gives me a stronger basis from which to work. I have a better idea of what code should go where, and how to control the player's movement.

Boy, I have a hard time with programming. I get why some aspiring game devs just want to be idea guys.

I spent my free time replaying The Talos Principle instead. I'm going to pretend this is game jam research because the Talos Principle does something that a lot of great puzzle games do - its puzzles are based on consistent sets of elements, and solutions come from figuring out the implications of these elements. Like how a cube hexahedron can weigh down a pressure plate, or act as a platform or a stepping stone, or block a laser beam, or slow down the player's movement. DROD does this better than any other game, I think - every element has some kind of logical interaction with almost every other element which you can either intuit or experiment with ("if my sword can reflect the aumtlich's laser beam, maybe I can lure an enemy with a sword  to stand in the right place to reflect  it while I do something else on the other side of the room...") With as a strong and varied a library of game elements as DROD has, there's so many opportunities for puzzles to test spatial reasoning, lateral thinking, and so on. I don't think I have the time to implement many different game elements, but I'd love to get a few different ideas working in Arcane before I have to knuckle down and get the game finished.

Also the Talos Principle does my favourite thing in puzzle games, which is puzzles that completely disregard the structure of the game and force you to think outside of the box. No one solved that Sphinx puzzle by themselves.

Okay, more progress tomorrow, I hope. I have to get back to writing a personal statement explaining why I'm suitable for a job I'm unsuitable for.

Submitted(+1)

I need to learn at your feet. A flowchart for planning things out, I love it.


Gotta say, really looking forward to your game, my friend. Keep it up.

Submitted

Wow thank you!! Please do not learn at my feet, I have no idea if anything I'm saying will work!

Submitted(+1)

Even if the specifics don't work out, a flowchart itself is a good idea to plan out the process.

Submitted(+1)

This is looking great so far!! If you need any help with GameMaker stuff, let me know, I'll help you out! 

Submitted

Aaa thank you for the offer!

Host(+1)

"I get why some aspiring game devs just want to be idea guys." hahaha... it is true. also wow this is graph is such a great idea for getting down all the game steps. it's so clear and well thought out :O !!!

Submitted

Thank you!! I hope it actually works!

Submitted

Update 4

All the work I've done today has been programming, so this is going to be a dry update. I've made good progress today, but don't have anything visually exciting to show off. 

Today's job was to start implementing that flowchart I made yesterday. A lot of the flowchart's work will be done by the Control object, which will process the result of the player's last turn and decide how enemies will move, which doors need to be opened, etc. The turn-based part is controlled easily with a yes/no variable which the player character and the Control object look at to decide if they can do anything yet.

Since I already had keys and doors prototyped, I worked on getting the Control to keep track of keys.


The above is for when the room the player is in starts. The Control looks for all the instances of square keys and dumps their data in a big horrible array. This does not feel neat, but it's preparing for when I implement a save state. When the player saves their progress, I want this array to update itself with the present coordinates and status of the keys, so that they can be put back how they were when the player loads state. (This array is initialised elsewhere, and it's 384 elements long. This is the maximum amount of keys that can fit into a 16x24 puzzle room, assuming there's nothing else in the room. I just want to be prepared for edge-case scenarios.)

Then I implemented the beginnings of the Control turn, where it goes through the keys and checks if the square doors should be opened. This is some of the most difficult programming I've done so far, and I got stumped for a while. To help myself get to grips with this, I wrote down what I wanted to happen in plain text:


(if you're curious, "new 1" is a personal statement for a job application and gostak-dictionary.txt is my notes for The Gostak, a great text adventure I started a week or two ago that's like a cross between reading Jabberwocky and being concussed)

Writing down the logic I needed to follow turned out to be a huge help! I recommend trying this if any other game jammers are having trouble with coding. if I think it's probably the same principle as the Rubber Duck method of troubleshooting, where just talking about what you're stuck on helps you realise what you've done wrong.

Here's what that text looks like in Game Maker Language, with a few tweaks on the fly:


I'm being VERY careful with commenting my code this time. This is going to get messy if I add other types of key - I'll have to optimise this into one template function which can read a type of key and figure out all the variables and objects it needs to check. For now, though, it's fine.

Programming this was scary because it's a lot of work without being able to test it until you're done. But I'm pleased to report there were only two bugs with this that I noticed! The first was a fatal error related to the big horrible array which I fudged a workaround for... but in writing this post and looking through the screenshots I took, I've just figured out what I did wrong:  line 14 in the first screenshot above misspells "square" as "sqaure." Oops. I'll fix that tomorrow. There's probably other bugs relating to the array and how it stores data, too but I won't find them until I'm handling save states.

The second bug is that when you restart the room, you stop being able to collect keys. I haven't fixed this yet, but it's something to do with Control being a persistent object, an object which sticks around when the room is changed or restarted - I think a second Control object appears when the room restarts, and the two Controls get in the way of each other. (Unchecking the "persistent" box for Control fixes the bug, but I want it to be persistent because I want it to eventually handle music as well without restarting the music whenever the room changes.)

That's basically everything so far. Thanks for reading all the words - if you're more of a programmer than I am, I hope it's interesting reading how someone less good at coding solves problems.

Submitted(+1)

It's so interesting to see your flowchart and thought process on character progression! And it's so fun to see the coding come together

Submitted

Update 5

I've created a monster!!


I've been working on an enemy today! I'm calling this little guy The Hungry. It wants to close the gap between it and the player, and will choose the move that makes this gap the shortest.


I liked spriting this little guy, but the design could be more exciting. I mentioned in the OP that I want Arcane to be occult-themed. Enemy design is a great opportunity for this, and I wanted to draw from medieval demonology, or maybe tarot cards. (Classic puzzle game The Fool's Errand does a great job of mining the Major Arcana for design and puzzle inspiration.) But I couldn't quite find anything that seemed simple enough, and I didn't want to spend all day on Wikipedia (not while I'm on a game jam time limit). I ended up subconsciously drawing from that most demonic of game series, Kirby - the Hungry is a lot like a ground-based version of Scarfy.

Programming was much more complex than I expected, and I spent all afternoon working on it. The Hungry's AI has to check four different possibilities for movement (east, north...) and find the two best, the second-best being a back-up for edge cases where the Hungry's preferred move is obstructed but another move would be acceptable. The Hungry discards moves that increase the distance to the player. This required a whole lot of mathematical problem solving. 


I ended up separating a lot of things into different functions - the Game Maker project gone from 8 different scripts to 14, most of which are little mathematical functions which will be helpful for other enemies in the future if I keep working past the game jam.

I'm quite proud of how the AI works with directions. I use the digits 0-3 to represent east, north, west and south in that order, and functions tell the game how to interpret the digit as changes to x and y coordinates. By representing directions as numbers, I can use a simple for loop to check all possible moves for the Hungry. (Yes, the numbering of directions starts from the east and goes counter-clockwise. This is the way angles are coded internally in Game Maker, for reasons unclear to me, so I'm doing it the same way just to be consistent.)

After a few hours, I'd written the AI and incorporated enemies into the Control system. I also added a death state for the player, which just turns the player red and immobile, waits a second, and restarts the room. Again, this was all kind of stressful - I wasn't sure how much of this could be tested while writing it, so I just checked and double-checked everything, and typed carefully.

Here is the result of my first test (before I implemented the changing enemy sprite):


Oh! That's... very aggressive.

It turns out I made a coding goof on the first day of the jam. 


What I thought this did was register the player's keyboard input and move the PC appropriately. What it actually does is process every frame as an attempt to move the character, because there's nothing to check if the player is or is not pressing a keyboard key before this movement code runs. I fixed this, and took the opportunity to add a wait option, where the player skips a turn if they press the space bar.

(At some point, I need to replace that tower of if statements with a switch statement. But I'm not confident with those, and this works well enough for now. Bethesda once made a running train in their game by having a man run around underground wearing a giant train hat. If it works, it's fine.)

After this, the Hungry seems to be working fine! It's quite good at closing down the player, but the player has opportunities to trap it in corners and keep it at bay. There's two interesting unintended consequences of the Hungry's AI:

1) It always goes through possible moves in the same order. I'm not exactly sure, but I think this leads it to always prefer certain directions - if both are equal, it would rather move west than south, because west was the first to be selected the best direction to move. But it would rather move north than west if those are equal! Hold onto your butts because I'm about to talk about DROD again: in DROD, most monsters have a quality called "vertical preference" where if a monster chasing the player hits a corner, it would rather move north-south than east-west. This makes it absolutely predictable how a monster will move in a complex puzzle, and a few DROD designers exploit this behaviour in especially hard puzzles. Here, the Hungry's behaviour is a little more complex to predict, because you have to be aware of the order in which it checks directions. I wonder if that's a good thing? If it's too complex, I might be able to tweak it by changing the assignment of directions to 0-3.

2) When the Hungry is right next to you (including diagonals), there's nothing you can do to lose it. That's surprisingly scary (I'm glad I gave the Hungry a scary face when it reaches the player), but also pretty exciting! How about a puzzle where you're chased by a Hungry as soon as you enter a certain chamber, meaning you have to set up movable blocks from outside because you won't have the time to move anything once you enter?

That's it for today! A lot of words, sorry, but I hope they were interesting ones!

Submitted

Update 6

Today, I've added three elements to Arcane!

Firstly, pressure plates:


All pressure plates in a room need to be pressed to open the grey doors. The doors close again if just one plate is released.

This was surprisingly easy to implement! Because pressure plates are fixed features of a room, I don't need to do anything to their coordinates or variables - I just have a few lines of code that run every turn and check if the doors need to be opened or closed.

In my flowchart, I had some idea that doors can close on objects and destroy them. I decided not to go this route, just because it was easier. I think the consequences of this are interesting when you put a pressure plate next to the door it opens:


The way that objects are processed right now is that players and blocks move before pressure plates and doors are checked. So if the player moves onto an open door and that door closes on the same turn, the player is standing on the door. This offers protection from enemies - closed doors are walls, and enemies can't move into walls! Similarly, a block can't be placed on closed doors, but it can be placed on an open door even when that door closes the same turn. There's some sneaky potential there for shuffling a block into a space it shouldn't be able to get to.

Speaking of places a block shouldn't get to, I made anti-block zones:


Just tiles that stop blocks being placed on them. This will help me to control what the player can do when I get around to designing puzzles. As seen in the GIF, they're made to complement pressure plates. This will lead to some cool situations in the actual game, I hope - maybe the player needs to lure an enemy to a pressure plate she can't get to but which can't be weighed down with a block?

Finally, I added another type of key, by copying the code for square keys, finding "square", replacing with "triangle." Here's a GIF of the triangle key in action, in a simple puzzle I mocked up using anti-block zones.


(I screwed up here and put the wall tileset on the wrong depth layer, which is why the top of the Hungry's head disappears as it eats the player. If I keep working on Arcane past the jam, I need to sort out depth. I'd want to code it so that objects south of over objects will always be in front, to preserve the faux-3D effect of the wall tileset.)

These are probably the last elements I'll add, other than different shapes of blocks (I'm planning to make a bunch of those this evening while I catch up on podcasts). I think I have enough elements now to make some cool puzzles with a bit of variety. At this point I want to take stock and think about the project as a game jam entry, and rescope it a bit.

I'm very happy with the progress I've made, but there's not much of an actual game yet. I want to set aside a lot of time to make some good puzzles for the game. Let's say 5 days to make at least 15 puzzles. So I want to be done with the game engine by Monday. And I'm planning to take Saturday off to rest and check out everyone else's projects (I haven't... been a very good community member so far.....), so that's only a couple of days to finish the heavy coding work.

I had a couple features I wanted to add. I wanted to let the player wander from room to room to solve puzzles in their own order, but I'm going to scratch this for now, since I haven't started on this idea yet and I don't know how to do it. I won't have game-wide save data for the same reasons, and the player probably won't need it anyway. On the other hand, I'll keep the idea of letting the player save state within a puzzle, since I've been working towards it for a while and it would be really nice to have.

Also I forgot that there needs to be a framework to interact with the game. So that means a title screen, some way to select levels, maybe an instructions screen and a victory screen, and a way to quit levels. Also I need to fix the menu I've got so that it's attached to the Control object, to make it easier to put it in levels.

Also I want to finish that music track that's half done, and maybe add sound effects if I have time.

So that's a lot still to do! I think I'll try to get the save system working tomorrow, and scratch it and move on if it doesn't work out. Maybe do some simple title screens and music work on Sunday to relax? I've never been good at timetabling.

Submitted

Update 7

Last night I drew blocks while catching up on MBMBaM.

blocks that matter

so many blocks

I think pentominos can wait for when I have a spare week.

Here's some of the new blocks being tested. This also shows off a rearranged menu, with a Quit button and a placeholder logo.

testing new blocks

Why, yes! Graphic design IS my passion!

The big sidebar and the black border around the whole thing are bothering me a little. I think the layout basically looks fine, but I was intending to use the black space for things which won't come together now. I was going to use the space at the top and bottom for level and room names, but I think they won't look good smushed between the puzzle and the edge of the window like that. The extra sidebar real estate was for talking to NPCs, but they won't be appearing in this game jam, so I might use that for level names or other tidbits.

So that was last night. Today was for working on save states, but I'm having one of those days where my brain is full of fluff, so I did some of the more fun creative work to begin with. I drafted a nicer logo:

logo drafting

logo so far

This looks mostly fine, but the outlines between the N and E run together into one thick line which bothers me a lot. Also I think the ends of the C look a bit too chunky? I'll probably tweak this again later.

I also finished the music track for the game. It's six minutes long and quite low-key, which I hope means it can loop indefinitely without annoying the player. Here it is if you want to listen:

https://clyp.it/xkiekay3?token=18759554a1c1e733e6c7da91799e79c8


Having run out of ways to put it off, I started coding the save system. First I rearranged the big horrible arrays so that they find all the objects they need to store first, and then grab their data. This allowed me to split the data grabbing off into a saving function which the player can use at any time.

The load state function is largely just the save state function with the variables swapped around, so that instead of changing an array value to an object's position, it changes an object's position to an array value. I then point it to the Control logic which checks keys and doors, so that it can close doors which shouldn't be open anymore. I think there's some redundant code here from the sloppy way I cut up and rearrange the code, but screw it.

Finally, I attached this code to the buttons, and made a testing ground.

The result - after a quick tweak to update enemy sprites correctly when loading state - looks good!

save state testing

ShareX thinks my mouse is about 50 pixels to the left of where it actually is. I'm clicking on the save and load buttons here.

I now have a system where the player can set their own checkpoint in a puzzle and rewind to it if things go bad. This is super nice to have for both the player, and for me testing puzzle ideas and elements (not that I'm going to add any more elements for now). I need to set player deaths to rewind to the last save state rather than just restart the room, and I need a proper victory state when the player reaches the gem, but other than this, I think I have a pretty good puzzle game engine ready to go!

With that, time to take a day off and forget how everything I've coded today works. More presentation work next time, I think!

Submitted(+1)

Update 8

Took the day off yesterday, kind of. I made a bunch of sound effects. The sound effects, like the music, were made in LMMS. In particular, I used the SFXR plugin that comes with LMMS. This means the sound effects are very NESsy compared to the rest of the game, but it's fine.

Today, I did a lot of little jobs:

I made a quick title screen, and started making a level select system for the title screen. I made a few new buttons, with the intention that the player will be able to scroll through a list of puzzles.

I made a music player and a mute button. Actually, this is a cheat: the mute button IS the music player. It's a persistent object you can click on to toggle the music, and it's going to decide whether or not sounds can play once I put them in the game.

Here's the current title screen:

title and level select

The black background and the shell of a level select system don't look impressive, and I probably won't spend much time on redesigning this screen, but there they are.

I've done some work on the main game, especially the side panel. For a start, I tweaked the menu buttons so that they don't respond if the player is carrying a block. This is to prevent exploiting the save states in any way (I don't know if it's possible, but I don't have to risk it!). This creates a new task: I need to grey out the buttons when the player is carrying a block, so that it's clear they can't save and load states in this situation.

The player character now has an actual win state, which pauses for two seconds and then brings up the next level. I added some text to pop up in the sidebar, but this needs revising, because it doesn't fit and overlaps some text I added later - I may put it across the main screen, Dark Souls YOU DIED-style.

I rearranged the sidebar a touch to look neater. The sidebar menu is created and placed by the Control object at the beginning of each room, and this same object now also draws a nice purple border around the two panes of the main game screen.

I made a template room, which I can duplicate to set up a canvas for puzzle design. I made a couple of puzzles in this just to get started on puzzle design, and to form a basis for my final job for the day, level information.

Each puzzle has a couple of variables in the room creation code, holding a level number, a name and a little blurb to tell players about new game elements. (I like when puzzles like names, as in the Talos Principle or Stephen's Sausage Roll. It adds a bit of character, and a hard puzzle becomes a nemesis when it has a name you can cuss at.) I wanted these variables to be drawn in the sidebar in the Control draw event (the same event which draws the new border around the sidebar), to fill the space a bit.

Would you believe that this is the programming task that completely defeated me? I could NOT get this working. The Control object was supposed to stitch these room variables together into a text string to print in the sidebar, but the compiler would swear blind that these variables didn't exist. I thought maybe it was to do with event order - like, the room creation code gets run after all objects are created and start being drawn, maybe - but I tried rearranging events and gating code with "if this variable exists" conditions... nothing. Then I realised that the error message said "Gem.(unknown variable) hasn't been defined." WHY ARE YOU TRYING TO READ THE GEM OBJECT. THE GEM IS NOT RELEVANT TO THIS TASK

I don't know what I was doing wrong (it might even be a problem with the Game Maker IDE), but I had to go for a hacky solution. Every room now has a RoomInfo object hiding just offscreen, which has the variables in a place which can be read without crashing the game. I don't like this because I wanted the variables to be directly connected to the room asset, so that the level select screen can read them. But I don't have the time or patience to keep troubleshooting this. I'd have coded this at the start of the jam if I'd known this was the hard part.

That's enough complaining. Here's what Arcane looks like now:

level 1

level 2???

Puzzle numbers and blurbs are temporary. I'll renumber them when I have more levels and a good order for them. That pressure plate one won't actually be the second level in the game.

Here's a GIF of the game in action, text glitches and all:

arcane so far

I'm a bit cranky after an hour of failed programming, but I've just been staring at this GIF for a few minutes thinking "wow... I made this." It's easy to focus on your failures, and I do that all the time, but I've achieved a lot so far, and I'm trying not to forget that.

I'm very pleased with myself. Which is good, because nobody else will be pleased with me when that nine-block shape-fitting puzzle makes it into the finished game.

Tomorrow, I'll poke at level select, sound effects and some bugfixes. Did I say I was going to do the level select today? I said I was bad at time management.

Submitted(+1)

Update 9

Today I accidentally deleted the notes I keep to tell me what I added since the last update, so this might not be complete.

The title screen looks nicer now, and has a functioning level select:

level select

As you can see, the logo outline is glowy now. I also added a cursor, more for fun than because it's necessary (there's like five other coding jobs I need to do before I'm completely happy with the engine).

The level select is just an array which finds the next X rooms in the resource tree and assigns a number to them. Because the automatic room data solution I was trying yesterday didn't work, I'll have to set X manually, as well as number all the rooms myself when I'm done. (I understand there's a thing called ds_list or ds_map that you can use to manage data like this? I think RPGs use these to manage enemies and inventory. But I don't understand how they work, and apparently you get big memory leaks if you don't handle them correctly, so I'll stick to my idiot solution for this game jam.)

As for the game itself, I added right-click to cancel block placement. I added a few sprites to the buttons; they feel more responsive to press now, and they're greyed out when you carry a block, to show that they can't be used in this situation.  I also tweaked the level complete and you died messages, so that they're legible and nicer to look at. (I forgot to get pictures of these.)

I was hoping to be done with programming today, but there's a couple of big jobs I need to do. I need to hook the sound effects up to objects and the mute button, and I need some kind of ending screen. I was going to have an instruction screen, but I'll just use the sidebar for tutorial information for now. I think there's a few other tweaks to make here and there if I have time, such as making the game font a touch smaller.  (It also looks really wonky in places, but from experience I think Game Maker just sort of does that to your fonts arbitrarily.) Other than this, it's all puzzle design until the deadline!

To round off today's devlog, here's a puzzle I made today. I finally figured out how to work the jam theme into my game!

Submitted

Update 10

Not much to report today, which is a good thing! All the programming is nearly done, and I've been putting energy into making puzzles and adapting the test puzzles I made during development.

I have about nine puzzles ready to go so far. Something I have to think about is how elements are introduced. I'd like to introduce puzzle elements one at a time, giving two or three puzzles for the player to get a handle on each one, and then a series of harder puzzles putting things together to test the player and finish the game. So in designing puzzles, I have to think about both the difficulty curve and teaching the player. This is tricky!

I'm ordering puzzles as I go to get the difficulty curve right, but the problem is, I made the puzzles, so I know how you're supposed to solve them. The player has to understand how an element works, and then how to apply that element to solve the puzzle. What seems natural to me may be obtuse to everyone else. I hope the level select mitigates the problem of difficulty spikes, and I hope that the sidebar text in early levels helps players to get to grips with the game engine itself. I also hope this isn't read as a lack of confidence in the player! I'm trying to explain how to control the game, and what things are, without giving away everything you can do with them. This is a surprising lesson: it's easy to made a hard puzzle, but it's really hard to make a puzzle that's easy but not trivial, that teaches the player without patronising them.

Here's a puzzle screenshot, to break up the text:


(This puzzle has a much harder iteration where you also have to weigh down four pressure plates outside of the box!)

I did a bit of work on the game engine too. I started adding sound effects, using a function which checks if the jukebox has been muted first. I was hoping that doing this would be quick, but I've had a few problems. All the sounds are very loud, so I've had to fiddle with their volumes. I've had to completely rework the sound effect for clicking, which was especially loud and sudden, like being punched in the ear. Also the door opening and closing sound effects play every turn, so I need to debug that.

I also made a little victory screen, just a few paragraphs thanking people for playing the game. With this, the game engine is basically complete! I just need to fix some sound effects, maybe add a couple more for picking up keys, and do a test export of the game to see if everything works. Things are looking good for a submission on Saturday!

Submitted (1 edit)

Update 11

Sorry for no update yesterday - a lot of real life things kept me busy, but I managed to fit in more gamedev.

I mostly fixed the door sounds! I don't like the solution, because it involves toggling variables to stop the game playing the sounds every turn and I had no idea where to put the variables. The code looks even messier now. I did my best to comment what I was doing in detail, but I can't help but feel that if I update this game past the jam, there's going to be some horrible audio bug in a year's time that has its roots here which I absolutely will not be able to track down. There's still a think where pressure plate door opening/closing sounds play when a state is loaded, which isn't consistent with other types of doors, but whatever, it's FINE.

I added a few more sound effects, including a jingle for the game end screen, a key collecting sound, and a little chirp for the Hungry when they chase you. I don't like this last one because it sounds very farty, so I may change it. Also I've stopped liking the name The Hungry, but that's how it's referred to throughout the code and it's too late to change it now.

I tweaked the player death state, so now it reloads the last saved state instead of restarting the room (and potentially undoing player progress). This should effectively restart the room if the player hasn't saved a state yet, since the Control object automatically reads the state of all objects to build itself. I also now have the enemy sprite on top of the player sprite during death, which I think looks better.

With all this, I think the game engine is done! There's nothing else I absolutely need to add or change. Now I can focus on puzzles. Looks like there'll be 17 levels in total.

This will probably be the last update until I finish and submit the game. Good luck as we enter the last few days, all!

Some last screenshots:


pressure plates

experimenting with odd room layouts


unfinished room

aw heck
Submitted

Submitted my game!

I got fed up of working on this, so I built the game and submitted it. Thank you to anyone and everyone who's been following this project! I'll do a postmortem in a few days, probably.