Skip to main content

The Move

I'm going to get started on the level editor now. I'll start off simple with object selection and re-positioning using the mouse.


Before I get to the editor code itself, there are a couple of things that I need to add first..

Input Manager

Before I can start editing with the mouse, I need to actually capture the mouse input. I created a new object, InputManager, that takes care of this. I was already doing some keyboard input but I've also moved that under the new manager to keep all input handling code in one place.

Keyboard and mouse input comes in the form of events from the browser, so all I need to do is to register to listen to them. Once I receive an event that I'm interested in, I store it in another (my own) event queue, this time inside the input manager. Here's the constructor of InputManager:


Then, at the start of each frame, I go through this queue and process it. I have a number of properties in the input manager to store the state of the mouse and keyboard inputs - you can see these at the start of the constructor above. I update these from within the update() function, where all of that happens:

Now I can easily access a consistent keyboard and mouse state from anywhere else in the code. The available keyboard states are keysHeld (a Set of keys that are currently held down), keysPressed (keys that were pressed this frame) and keysReleased (keys that were released this frame. The pressed/released properties make it simple for code to perform an action only on key down or key up. The mouse has a similar held/pressed/released flag for the button as well as mouseX and mouseY to access the position of the pointer.

No ID, No Entry

Another thing I need to add is object IDs. I need a way to reference an object from outside of the object manager, and the best way to do this is by assigning each and every object with it's own unique ID. This is pretty easy to achieve - objects can only be added through the add() function, so I simply generate a unique ID at that point and store it along with the object itself:


I could generate a proper Universally Unique Identifier (UUID) for each object, but actually I don't need to be that extreme. I would only really need to do that if I wanted to make sure that the object IDs weren't predictable - something I would need to do if they were exposed to the outside world where an attacker might be able to do something malicious if they could easily guess one ID based on the value of another. Here I'm just using an integer counter, which starts at 0 for the first object and increases by 1 with each new object.

Now that I can easily reference objects, I can add functions to the object manager like setObjectPosition(objectId, x, y) which I'll use later.

Level Editor

Now that I've got mouse input and a way to identify objects, the basic level editor will be pretty simple. First I need to get all objects from the object editor so that I can draw selection boxes around them and check for interaction with the mouse cursor. I get this info object from the object manager:

From this function I get the ID and position (x, y, width and height) of every object. I can easily check if the mouse cursor if over any of the boxes, and if the mouse button is pressed then an object has been selected - and then I just need to remember the ID of it. If the mouse is now moved on subsequent frames, I can use the new setObjectPosition() function to move the selected object.

The level editor loads a level in exactly the same way as the standard game state does - using the new level loading code that I wrote in the last post. From there I can use the same update() and render() functions from the object manager to run the game as normal. Of course, there's no timer or game over sequence in the editor and I only update the objects if updateActive flag is set - you can toggle that flag by pressing the space bar.

You can check out the full code to the level editor state in BitBucket.

Wrap Up

In this post I started on the basics of a level editor. I added object IDs so that object can be uniquely identified and referenced outside of the object manager. And I tidied up the handling of input by adding a new InputManager class.

Next Time

Moving things around is fun... maybe too much fun. What happens if you accidentally move an object that you didn't mean to move? You'll probably want to press the undo button. Well.. I think I'd better implement undo and redo in the next post then.

In the meantime, thoughts/comments/questions are welcome, either here on the blog or over on Twitter to @evilpaul_atebit.

Comments

Popular posts from this blog

Set The Controls For The Heart Of The Sun

When we last met, I had just started work on a level editor. I'd got as far as adding the ability to select an object and move it around, and then I added an undo/redo system using the command pattern. That was a good start, but dragging items around the level is only fun for so long. What I really want to be doing is.. ..editing the properties of the bullet spawners! And I want to be doing this in realtime as the game plays so that I can immediately see what effect my changes have made to the gameplay of the level.

World In Motion

In the last post I touched on how easy it is to score in this game - you can just camp out on the score bullet spawner and watch the points rack up. I'm going to add a little delay to the score bullets so that they start out in a deactivated and uncollectable state, and then change to active and collectable after a short time - say, half a second. To make it clear what state they are in I'm going to add code to let me change the look of Objects and allow them to be animated.

The Long And Winding Road

I started this blog back in November of last year. My aim was to document the development of a Bullet Hell shoot-em-up, written in JavaScript. Here we are, six months later, and lots has happened. With 20 posts already written, I thought that now would be a good time to take stock of what I've already done, and to look to the future and see what's to come.