Finally got fighting working. It needs balancing, but the core mechanics are there. The player has been able to attack the enemies for a while, but now the enemies can attack back too. The player and enemies both have health, and when it reaches zero they die. The player gets taken to a game over screen when they die.
BeepMini Dev Notes
I post experiments, fixes, and decisions, including things that never ship and what I am working on now that may not be public.
After a lot of confusion I finally have a simple ai system for the adventure game maker. Characters can now follow paths, and then break away from the paths to chase the player if they get too close. They can also then find their way back to the path if they lose the player. If an enemy has no path they wander around randomly, with the same chase behaviour as pathed enemies. I still need to make the enemies attack the player. There’s extensive use of A* pathfinding which is now a core BeepMini feature.
I worked out what to do for the game continue feature in the adventure game plugin. The plugin now stores the current map and player location, but reloads the map data so the player can continue from the last place they went. The important part is that I also change the core map data, so when doors are opened or chests are collected, that state is saved and reloaded too.
There is now a game over state in the adventure game maker. If you lose all your health you will be taken to a game over screen with a continue and menu option. Continue takes you back to the last entrance point you used and resets your health.
Currently all entities continue as theywere, so fire cotinues burning, and enemies maintain their current properties. I don’t know if this is good or bad. I should probably reset something else there’s little point having health and a game over if everything else continues as normal. I’m just not sure how best to handle this yet.
Probably more effort than I expected, but I’ve added fire, bombs and flammable elements to the BeepMini mapper plugin.
You can set items as flammable by adding a “Flammable” component to them. I’ve made doors flammable if they use certain tile icons (221). When something is on fire, its temperature increases over time, and when it reaches a certain threshold, it burns. This currently works for crates and wooden doors, and also enemies. Sometimes there are special cases, and these can use the type burnHandler to define custom burn behavior. I used this on the door to change it to an open door when it burns.
The code is a bit more complex than I’d like, I hope to revisit it once I have a few more flammable elements so I can make it fit different use cases better.
I’ve also added an outline VFX effect, which draws a colored outline around an animation. Because some effects need to be drawn on top of other elements I thought it would be good to add a border effect so that they stand out more. There is a demo of this in the examples.
Today I worked out a really simple way to define animations for the Tilemap system. This makes it easy to add simple VFX to tilemaps, such as water, fire, smoke, etc. You now define VFX using a vfx: prefix in the tile character mapping, and the tilemap renderer will automatically draw the appropriate animation at that tile’s position. This uses the existing Vfx system and built in animations, so it’s very lightweight.
Had problems with keyboard input contexts and async input functions interfering with each other. So I’ve made it so that async input functions always read from the active context, and readLine creates a temporary capture context while it’s running. This should prevent any interference between gameplay input and async input functions.
I changed the Vfx startTime parameter to accept future start times. This allows for delayed Vfx effects.
I also changed attacking so that it uses the A Button rather than relying on bumping into enemies. This allows players to both push, and attack objects. This will be useful when I add bombs since I plan to allow them to be pushed and pulled around, but also detonated by hitting them.
Did lots of work on the adventure game plugin today. This is what powers Key Kwest.
Fixed keyboard input so that dragging a crate does not run faster than walking. This was caused by the walk delay being reset when the character moves, but not being reset when the crate is dragged.
Added animations to player movement when dragging a crate.
I have been working on the adventure game plugin that powers Key Kwest.
I was adding hearts to the editor so that you can refill your health. I realized that the process for picking up hearts is almost the same as collecting coins and keys. So I made a generic “pickup” system that replaces a lot of the code for coins and keys. This will make future pickup objects a lot easier to add.
Each pickup has a location, a sprite (tile, and colours), and optional attributes, plus a callback function that runs when picked up.
Added visual effects animations to BeepMini. This makes it easy to add things like explosion animations, sword swipes etc. The animations are all tile-based.
The animations have a selection of frames that are specified in an array, the same as used for Actors. The animation has a defined speed (in frames per second) and can be set to loop or not.
You should draw the animation in your game loop by calling b8.Vfx.draw( animationId, startTime ) where startTime is the timestamp when the animation started (you can get this from b8.Core.now()).
When the animation finished b8.Vfx.draw will return false, so you can use that to know when to stop drawing it.
You can see a demo of the Vfx system in the BeepMini examples: Vfx Demo.
I have started adding a utility that generates tile paths for characters to follow in the mapper. This could actually be used for anything to follow, for example NPCs wandering around, or platforms moving.
It uses a string of directions like “UUDDLLRR” to indicate up, down, left, and right movements. You can also add numbers to indicate the object should repeat the movement.
You give it a start position and the string and the utility returns an array of tile coordinates that the object should move through. Initially this is going to be used for enemy movement patterns in the adventure game plugin, but it could be used for other things too.
You can read more about this in the Path docs.
I have added a reset system. All BeepMini modules can not implement a reset() function that will be called when the game is reset. This is useful for resetting game state without reloading the entire page.
Specifically I wanted this so that I could make the game preview system work in the adventure game editor. Without this that game state would be corrupted between previews since some of the code would still be active from the previous run.
I am not sure many people have used the adventure game maker yet but I have been making changes so am releasing version 2 of the file format.
Fortunately I considered this when starting so there’s actually a version number in the file. This means I can add a transform function to convert the old format to the new one.
The new format adds support for multiple levels. These levels could be different things in different games. It might be levels you complete in order, or different maps or areas in an adventure game. Or different floors in a building. How you use them is up to you.
I’ve decided to change the adventure game maker so that it is actually generic. This means I can make a bunch of config files that will change the apps behaviour to work for different games.
Obviously the first one is the adventure game format, but in the future I can make other formats that have different rules, objects, tiles, level layouts etc and customise it all in a single json file. This will make it easier to create new games without needing to change the code of the editor or even making a new editor.
I’ve moved the files for the b8.js example files. They used to be in the shared media folder but many aren’t actually used by default so I’ve moved them so they don’t need to be bundled/ removed from every project.
I’ve renamed everything to b8 or BeepMini from Beep8. I came up with the name a while back and bought the beep8.com domain, then 6 months later someone else made another fantasy console project with the same name and started promoting it heavily. I tried contacting them to see why they were using the name but got no response.
I decided it wasn’t worth the stress and confusion so I’ve renamed the project to BeepMini. The b8 prefix in the code remains as a nod to the original name, and as a shortening of BeepMini which contains 8 letters.
I have changed the CRT rendering to use a different format. I was using getImageData and then looping through every pixel to modify it. This worked but felt like it might be slow and didn’t work properly on some mobile browsers. Now I do 2 things. I draw a vignette gradient over the top of the canvas using a blend mode, and then I precalculate a 2 pixel image that adds the stripes. It’s a bit less accurate since theres no bleeding between pixels, but it is much simpler and hopefully more robust across different browsers and devices.
I have decided to add an ECS (Entity Component System) to Beep8.
I am making an adventure game maker and wanted to have emergent gameplay where objects can behave and interact with each other. I didn’t know how to do this, so did a lot of research and found out that an ECS would be a good fit.
ECS stands for Entity Component System. Using an ECS an entity is an object in the game world. A component is a piece of data that can be attached to an entity, like position, velocity, health, or a sprite. A system is a piece of code that runs every frame and updates entities that have certain components.
So, components hold data, and different entities can have similar components. For example, both a player and an enemy, and an NPC (non-player character) will have position/ location and sprite components. They can have a system that renders them to the screen. Traditionally I would have a list of player characters, enemies and NPCs and loop through each list to render them. This already simplifies things a lot.
But there’s more than this. Another example is I can have a “pushable” component that could be added to any entity that can be pushed around, and the push system will automatically handle everything. So I can easily add new objects and then decide I want them to be pushable, and just add the component without needing to change/ add any code.