Fort Knight post-mortem #js13k

Play the 2023 entry here: https://js13kgames.com/entries/fort-knight

The post-mortem is usually a quick look through the gifs tweeted during the game jam, 30 days of steady progress for the engine and art plus some funny bugs; for my 2023 write up Id like to go into more detail and talk about some of the highs and lows and my overall approach to the jam.

Over the past four years, I’ve been on a journey of continuous improvement in my game jam entries. In 2022, I achieved a significant milestone by securing fourth place. However, my primary goal this time around was to enhance the quality of my entry and craft a game that offers an enjoyable experience.

Previous Entries

The idea

The theme in 2023 was 13th Century, I decided on day 2 that I would make a wave attack type game and the graphics would be isometric. Here is the original idea with coffee stains and all:

isometric island surrounded by sea, there are trees and a castles, a hero stands guard.

Approach

Over the previous years I have built up a template that I strip back to the bare bones, its handles all of the basics of a simple ‘engine’ to allow me to start directly on a game idea, in the first year a lot of time was taken up learning these basics with the Canvas API. The main JS files are loaded into a html file using some JS code:

<script type="application/javascript">
    version = Math.floor(Math.random() * 1000);
    var files = ["projectile","menu","audio","camera","particle","keys","entity","hero","enums","tile","utility","mob","level","cart","game","sound"];
    for (f of files) {
      document.write("<script type='application/javascript' src='assets/js/" + f + ".js?" + version + "'\><\/script>");
    }
 </script>

When ever I add a new file I add it to the array of files, my workflow is very simple, code, F5 and test, I use a python to run the game (“python3 -m http.server”) to avoid isues with cross origin:. There are probably better ways to do this but its a simple way to load the JS files and tag on a random id to stop the browser caching the code. I use the developer console to output messages and play with the code in real time. If I have settings I want to test like speed Ill edit them in console and have current values written to the screen.

The key exisiting files are roughly as follows:

  • game (Handles listeners, inputs and calling the game loop with a delta)
  • cart (Sets up the game screen, generates levels, calls render & logic functions)
  • enums (a list of tile and mob types)
  • entity (class to handle all objects, position, hitboxes, setting image coords based on type)
  • hero (extends entity with all the functions for the main character)
  • level (generate a random level or load from file)
  • keys (key number mappings)
  • camera (simple class to track camera position)
  • audio (http://sb.bitsnbites.eu contains the song)
  • utility (general purpose functions like collisions etc)

These classes are stripped right back to the bare bones but really need a complete rewrite, I lose bytes from badly written code, do not split up entities into new classes and end up dumping code all over the place, during the jam its fresh in my mind but after its hard to come back and make changes.

The entity rendering starts out as simple render code but ends up littered with magic numbers and polluted as I just want to get something working. I have always enjoyed adding features and testing without a plan but I really need to organise next year given my spare time is so limited.

Building Final Code

During the first jam I have a process to minify and uglify the javascript code into a single JS file using a grunt file I use npm to install the packages required. Once grunt has run, I copy the code into Road Roller which saves a lot of space.

My final zip files are generated using 7-zip on Windows, it contains a minified html file, the js and image file. This year I used a new sound library from Frank Force, grunt could not handle the javascript version used which caused me a pain, I’d build the single compressed javascript without this one class and have to tag the code on after. The whole process needs updating and streamlining as it was clunky and adding new libraries is going to cause more issues.

Images

I load all my images into a single file and use a simple process to keep this small, https://imageoptim.com/mac to remove meta data and then https://tinypng.com/ to further compress; I run the image through the app and website several times.

Getting Started

The template is a decent starting point, I have last years song as a placeholder which also acts as a reminder to save those bytes for the new song, and the ability to start rendering a map very quickly, the hero can move up, down, left and right but there are no collisions, objects etc just background tiles and a moveable character. What I would like to address next year is the start size of the template, a poor build process and separation of code.

To move onto the stages of development for the game! I started out rendering a random map of tiles I had created in Photoshop:

It was not until the 18th I had written a slighty random map generator and started playing with the sea, I wanted some wave like movement to add some life to the game from the start:
This affect uses some simple code which can be seen here, setting an offset to the Y position based on the time, tile column, a movement amount and speed, you can quite easily have small slow waves or huge fast ones.

I really got carried away with different ways to move the tiles around, including creating mountains; while this was not going to be used in game it did end up as a transition between levels:

I put some effort into learning how to rotate the map which is something I had tried and failed to do previously, this was partially working through out the jam but removed to save space later on. This is where my unplanned approach falls over! I work on what I think is fun and will contribute to a better game but lose sight of the bytes and required features to deliver a final product.

At this point I was not really sure on the game play but kept working on generating an island which would have a castle, trees and rocks, that would likely be enough to add some type of game later on. I was not decided on if you were defending, destroying or saving the castle.

I worked on a function to create pillars, from these pillars I could create a castle, due to all objects being Y sorted I had to exclude the pillar from the object array to ensure the render order was correct, this later became a pain when entities were in front or behind it! I decided to make its alpha below 1 when you colided to simplify this, here is castle and a slighly crazy for loop to allow the tile orderingto be top to bottom or reversed in one function.

Music

An old friend makes game music for a living, they have been kind enough to help with creating a song since the last jam, this helped with the 4th place last time around for sure! If I make the top 100 will be buying Adam a tee shirt again so we both have one.

Weapons

To add some feel to the hero I created hands, I experimented with them moving while walking, idle and holding weapons; they reminded me of Rayman so I added a punch! I never really got a weapon movement for the sword that I liked, the punch is fun, the axe and hammer are fine but the sword is not great. Players have fed back on the attacks and they could have been improved.

Was quite worrying to be over two weeks into the jam and only have this much completed, I started making todo lists and focusing more on completing the basics than adding nice touches to working code.

Here is the sword powering up, a click of the sword grants 1 damage, powered up its 10, I wanted a nice visual for this; I lost some time adding this arc due to some issues with how I scale the screen and render entities, there is simple way right now to render debug boxes etc, this needs a total rewrite for next year its a mess.

September 4th, 6 days to go until I had to submit due to a holiday; I finally added mobs, I decided to improve my usual mob code and try to have them space out around the hero, maybe I should have made the weapons over powered and had bigger mobs!

At this point I was working the normal 8 hour day, spending time with the family until 11pm and then coding until 3am. This was pretty stressful, plus I am training for a half marathon and running 30-40 miles a week (I did cut back on running a little). I had to become more focued on the todo list and started making decisions on what could and could not be completed:

What i have not covered is that HP was added to entities and Skeletons and Goblins were added and given movement code, to save time I used an asset pack purchased on itch, please check it out: https://danieldiggle.itch.io/sunnyside

the skeletons chase you down and hurt you by making contact, the Goblins will hunt you down but try to stay a given number of pixels away from you, they periodically throw spears, these were going to be arrows but due to their size and the animation being simpler they are spears!

There has been feedback on the combat and mobs, people are a little confused on how to fight and commented on weapon changing, I should have created imporved and clearer tutorials. The game is quite simple, you destory rocks and trees to stop mobs spawning, and then clear the mobs to drop. abridge to. thenext level but this was still not clear enough. I should have allowed the mouse wheel to change weapons and also allowed the shield to toggle on/off. Skipping play testing really hurt me!

The final Stretch!

It is quite amazing to look back at the 9th September and see how much I had left to implement and realise I did manage to submit on the 10th. Huge compromises were made, no boss, no shield cool down, upgrades are random on breaking drops and so on. The mobs were not even doing damage at this point.

To show that defence has increased a skull helmet is added to our hero, the powerups really needed a larger pop up text so players understood what just happened and why.

You can check out the commits to the game here, I made an effort this year to commit small incremental changes so I could roll back any game breaking changes quickly. If I have had the final 3 days seeing what I managed on the 10th alone I could have improved combat and tutorials which may have dealt with many of the comments / issues.

Feedback

  • Gameplay is a little not obvious
  • When introducing each item it wasn’t clear that the text was the hotkey to use it and not the number of times I needed to use it. Having the number hotkey under the item’s icon would have help
  • I forgot shield key by the time I needed it, could use a reminder in the text what it was
  • It wasn’t exactly clear what was needed to clear each stage. I was stuck on stage 3 killing enemies and bridge never came. Took me awhile to think about destroying the tree to move on
  • I kept dying in stage 4 to constant knockback and getting pushed off the edge of the map
  • I couldn’t attack enemies from above / below, which lead to the previous problem of getting constant knockback from the skeletons when they were below me
  • Trying to hold the shield button while simultaneously trying to attack was very tiring. Would have liked a toggle for the shield or something
  • Got stuck on about level 4, with seemingly infinite baddies spawning
  • I just can’t get past the goblins no matter what I do. Blocking only gets me so far, and they just freaking keep coming, getting me stuck in the water, or other things. I never got past Stage 4

All of these are fair comments, people were kind also but I get their frustrations, I didnt test, balance and deal with teaching people how to play. Some comments mentioned not enough variation in levels, I may look at using code to generate the images next time to allow more variation.

Conclusion

While there are many improvements that need to be made next time around:

  • New template
  • Automated build process
  • Better screen resizing
  • Improved menus
  • Better rendering with debug options
  • Play testing
  • Tutorials
  • Mobile friendly

To name the key areas; there are plenty of positives I take from the jam, I completed a game in 30 days with limited time, added loads of features and within the 13kb limit plus I engaged with the community and gave some advice to others and had fun!

JS13k 2022 Game jam post-mortem #JS13k

Full play through of the game (https://js13kgames.com/entries/soul-jumper):

My fourth JS13k gamejam and fairly happy with how it has played out. Previous entries have been platformer, topdown / idle and a topdown shooter:

1. https://js13kgames.com/entries/quick-wins
2. https://js13kgames.com/entries/in-to-net-cafe
3. https://js13kgames.com/entries/space-kitty

I had no idea what I would make this time around, preferably I’d like to try new genres but when I heard the theme was death was keen to make a platformer where everything is out to kill you, similar to the speed run “Unfair Death” games that are popular on Youtube. I started out by cleaning out my last entry code until I had a workable template.

This is not an indepth look into any clever code or challenges I faced, more of a short look at how the game progressed. This year I had very little time to work on the game, only 88 commits were made to the repo, most days I would be lucky to find 2 hours spare to work on the game.

I had feedback on previous games which I wanted to address this year including screen size and coyote jumping (some grace time before graivity kicks in); I have been trying to improve the game and hopefully my postion each comp:

While I was setting up the basic concept and controls etc I thought it would be interesting to use a rewind feature and use your death as a platform; while many games use the body I’d not seen the ability to rewind; kind of like braile. At this point I gave up on the idea of lots of ways to die and focused on the rewind feature:

My first go at this tracked all the co-ordinates; far too many! I limited this to 10 steps eventually and also only tracked the postion every few ticks rather than 60 times per second.

Early on I put some effort into simple effects:

– Screen shake
– Blood splater when you die
– Blood drips on spikes if you hit them
– Dust from the hero when you run or hit the ground after a long fall
– Multi coloured explosions when you beat a level

These small details add a lot of feeling to a game, without feedback on jumping, falling or hitting objects a game lacks excitment or fun!

The level size was quite small, to allow larger levels I added a camera to allow the hero, added a little lerp so the movement was smooth. This is another feature that many games seem to lack, the character moves around a stand level which is less fun, movement is key to a fun platformer in my opinion.

Spinning character – I wanted to work out how to rotate spikes to save on sprites, they appear on walls, the floor and ceiling; I started by adding a few degrees to the hero every frame of the game to be sure it rotated around the centre point. Once I worked out how to do this correctly Id been playing the game with the spinning hero and thought it looked great and saved on animating!

If you stay idle for a while your character spins, I did have add in a jump at one point but it was possible to die!

After putting all the extra tiles; traps and features into place I was short of time and did not have enough hours to make sure the levels were well thought out, the current 10 only take 2-5 minutes to complete and are not too difficult. This is the area I would like to improve next year, more effort into the menu, add controller support and carefully design the levels. To give myself some credit the first few levels are teaching the player the basics, tool tips whcih you can turn off help you understand the controls.

Before the next JS13k jam I plan on spending time making a smaller and cleaner template with controller support and a better implemenation of full screen, also I will put more time into a fully working mobile version of the game.

See you in 2023!

JS13k 2021 Game Jam #JS13k

I spend my days managing a development team, dealing with projects, strategy, policy, security, operational issues and sometimes some development; so when JS13k comes along I like to just play with pixel art and Javascript, make it up as I go and see where I end up. The jam always brings some stress through running out of bytes or time but for the most part I can just have fun and follow other jammers on Twitter and Slack.

From the 2020 jam I had some code as a starting point and the script to minimise the classes, to save some time I stripped out all the game code and used this as a base. This blog post will be a short walk through my month of development with some gifs, nothing too in depth nor ground breaking compared with other entries.

I had several ideas early on all to do with SPACE of course but nothing I got excited about, I have been following https://twitter.com/orangepascal for sometime and did fancy making a top down shooter but more like Nuclear Throne than a turn based game.

After clearing up the game code and implementing a simple 2D array of tiles I started randomising rocks to give the levels at least some personality.

I had a basic list of objectives from day one and slowly worked through them, added the hero and allowed them to move around within the boundaries of the level, to keep things simple there is no moving camera and the level fills the canvas. Added a 3×3 array of rooms, like many shooters the room is locked until you kill all the mobs, this then opens up the doors for you to move on. Added a simple screen transition when the hero switches rooms and animated the doors so its obvious its possinle to move on.

Had a few issues with the old code, the mouse to map possition was incorrect, I had left some magic numbers behind rather than properly calculating the mouse position, lost some time working out why this was wrong and also went through collision code to check I had not incorrectly added hitboxes etc, when you are casually coding its so easy to make silly mistakes.

At this point I has a 3×3 map, animated doors, shooting, enemies that could be killed, breakable objects the game was progressing well, I always expect the game to form and become fun right at the end. I wanted to add a few types of shooting patterns, single, double, triple and so on, had a play about with Javascript on JSFiddle to work out the best way to achive this and be sure the math worked:

Up until now the enemies had been static, I did not really want to implement path finding; the enemies instead try to move toward the X and Y of the hero but if they are colliding with an object will try to move around it was a few seconds:

There were plenty of bugs throughout the jam but sadly this was about as entertaining as it got!

With around a week left I worked on a splash screen, adding some simple sounds and tried out the built in voice functionality. I played with randomising more parts of the game, the bullet colours, background colours of the level, the speed of the enemies and how fast their bullets travelled. The number of mobs per room is random and increases as you beat levels, a level consists of clearing all 9 rooms and then using the portal to move on, after beating 5 level you get a basic boss level which is just a room full of mobs.

To conclude, I enjoyed the month of developing Space Kitty, in the last few days I feel the game did become fun, I am super happy with the top 30 finish! I had some really good feedback which I will take into the next jam, better sounds and some background music, full screen mode, make it obvious that pickups can be collected – I saw some footage of people not collecting ammo and being frustrated, a melee attack would have been a good idea.

I look forward to the next jam! Thanks

JS13k Game Jam – Post Mortom #gamedev #js13k

For 30 days I took part in a JavaScript gamejam hosted by http://js13kgames.com

Js13kGames is a JavaScript coding competition for HTML5 Game Developers. The fun part of the compo is the file size limit set to 13 kilobytes. The competition started at 13:00 CEST, 13th August and ended at 13:00 CEST, 13th September 2019. Theme for 2019 was back.

View my entry here: https://js13kgames.com/entries/quick-wins

Decided on a gameboy style platformer, simple levels whereby you collect coins to open a portal which leads to the next level. Got the basics in place quite quickly, standard entity, camera, hero and tile classes.

With the basics in place I started implementing some levels and refactoring code, with very little space early on aiming to keep the byte count down.

I played around with several different types of blocks which reacted in different ways, ice blocks that melted that you moved down with but this spoiled being able to run over several of the blocks, these later changed to blocks that melt but dont move the player downward.

The colour scheme I had gone with was pretty boring but determined to keep it simpe I search the web for some inspiration.

Escalators seems like a neat way to control the players movement and would allow for some interesting levels.

Ladders were quite a challenge to put into the game but an essential part of any platformer.

Walls are solid and cannot be passed through but platforms can be jumped through, a simple test of the heros Y position against the platform Y position was used to check if a collision with the tile should be checked. Quite a simpe solution to what seemed complex at first.

Added in some dust affects to give some feedback to the players movement and a simple transition between levels. At this point the code did start to get messy, with 30 days of coding it would have been better to build some systems or a simple state machine rather than dealing with many IF statements, before taking part in the next Jam creating a basic engine would be really worth while.

dust

Originally I had planned to implement a Git menu, the idea behind this was playing a level and commiting the time taken to a branch or reseting, going back and retrying. The game would be about progressing once you had enough time to do so. This menu was a pain and was removed for something much simpler.

Early on I had time to work on features, test out colour schemes and mess with the UI, but later only being able to work the odd hour each evening I was running out of time, I dropped many ideas and polish to finish the menus and build levels. The game code did get messy and hard to work with which often lost me time.

Ther hero was always going to be updated to pixel art but as it reminded Lee of the Github contributor square, I left it as is:

I enjoyed the jam, having plenty of time was great but the keeping the game within 13kb compressed meant minifying to code and really limiting the sounds and graphics. Looking at other entries I could have added much more polish and tighened up the movement of the player. The music that was created by ModalModule really added to the quality of the game, I spent hours listening while testing the game.

The levels were put together very quickly and while there are a good number of them more time should have gone into testing them, a few more enemy and tile types could have made the levels more enjoyable, I probably didnt explore the use of the different tile types enough.

I used some of of Xem’s tools, a level and sound editor to help produce the game, there are so many talented coders taking part in the jam who are all really helpful and were often in the Jams Slack channels advising or just having a chat.

Over all a great jam, I am enjoying voting at the moment and look forward to seeing how I did!

Making a LibGDX Game – Part 14 – Firing Bullets #gamedev

To those who still check back for or are tracking the Github repo thank you for returning and checking out the tutorial! Thanks to @UmzGames for prompting me to add more! I would like to explore different bullet types and movement patterns but lets start with something simple.

pewpew

Check out the commit: Git commit for this tutorial

To fire our weapon we will use the spacebar, the control class requires a new boolean variable which we shall call “spacePressed”.

core/src/uk/co/carelesslabs/Control.java

  public boolean spacePressed;

The keydown function case statement will set the new variable to true:
Github code link

public boolean keyDown(int keyCode) {
...
...
    case Keys.SPACE:
        spacePressed = true;
        break;

The Enum class will need a new EntityType, we wont use this right now but it is usefull setting an entity type for checks later on or debuging.

core/src/uk/co/carelesslabs/Enums.java

public enum EntityType {
     HERO,
     TREE,
     BIRD,
     BULLET
 }

GameClass Updates
There are some changes to be made to the class that has the main game loop. When the hero update method is called we will now pass in our box2D instance, this will allow us access to the functions that allow new sensors to be created when a new bullet is added. Previously the call was hero.update(control).

Also a new method that checks and removes bullets is called, this will check which bullets are no longer active and should be removed from the game.

core/src/uk/co/carelesslabs/GameClass.java

  hero.update(control, box2D);

  // Clear travelled bullets
  hero.clearAmmo(box2D);

There was already a gun added to the Hero class, but now we will want to set an amount of ammo that the gun has. The Gun class should be refactored to allow the amount of ammo it has to be passed when its initiated or it could have a default number. Also
this could read “gun.addAmmo(10)”, not sure why I look it up in the ArrayList when its available after the gun variable is initiated. Its always good to read through your code and explain / document especially as a solo dev to find these issues, working in a team you have the luxury of code review with Pull Requests.

core/src/uk/co/carelesslabs/entity/Hero.java

public Hero(Vector3 pos, Box2DWorld box2d){
  ...

    // Weapon
    Gun gun = new Gun(1, -1, 7);
    weapons = new ArrayList();
    weapons.add(gun);

    // Add some ammo to the gun
    weapons.get(0).addAmmo(10);

On drawing the gun we can also call the tick method, we only draw and tick weapons that are active, a later tutorial will look at multiple weapons and weapon switching.

@Override
    public void draw(SpriteBatch batch){
        if(shadow != null) batch.draw(shadow, pos.x, pos.y, width, height);
        if(texture != null) batch.draw(texture, pos.x, pos.y, width, height);
        for(Gun g : weapons){
			if(g.active){
				g.tick(Gdx.graphics.getDeltaTime()); // New line
				g.drawRotated(batch);
			}
		}
    }

The update function of the Hero as mentioned previously now requires an instance of Box2DWorld to be passed, when looping the weapons and checking which are active an additional check will add a new bullet to the guns active bullet list if space was pressed, spacePressed is reset to false.

When space is pressed and the gun is active we generate a new SimpleBullet, the current gun and box2D is passed into this class, the instance of the bullet just created is then added to the guns active or fired ammo list.

* The guns ammo count should have been checked before generating a new SimpleBullet: if (control.spacePressed && g.ammoCount > 0We are generating a new bullet and not actually using it with the current version of the code.

Another new method “clearAmmo” will loop through all guns and call a method for that class “clearTravelledAmmo”; this is used to remove bullets.

view on Github

public void update(Control control, Box2DWorld box2D) {
...
    // Update weapons
        for(Gun g : weapons){
            if(g.active){
                g.updatePos(pos.x, pos.y);
            	g.angle = control.angle - 90;

            	if(control.spacePressed){
                    SimpleBullet bullet = new SimpleBullet(g, box2D);
            	    g.addActiveAmmo(bullet);
            	    control.spacePressed = false;
            	 }
            }
        }

    // New Method to loop all weapons and check its ammo.
    public void clearAmmo(Box2DWorld box2D) {
        for(Gun g : weapons){
            g.clearTravelledAmmo(box2D);
        }
    }

The new ammo class extends Entity and introduces some new variables:

  • range – how far the bullet can travel
  • damage – the damage this bullet inflicts
  • vector – the heading of the bullet, used to move it each frame
  • distMoved – the ditance the bullet has moved thus far

core/src/uk/co/carelesslabs/entity/ammo/Ammo.java

package uk.co.carelesslabs.entity.ammo;

import com.badlogic.gdx.math.Vector2;
import uk.co.carelesslabs.entity.Entity;

public class Ammo extends Entity {
	public float range;
	public float damage;
	public Vector2 vector;
	public float distMoved;

	public Ammo(){
		super();
		vector = new Vector2();
	}

	public void tick(float delta){

	}

}

SimpleBullet
The ammo class will be used to extend other bullet classes, starting with the most basic SimpleBullet. This bullet will travel along a vector for a given distance at a given speed. For this tutorial an existing image will be used to show the bullet place on the screen,
in another tutorial we can look at adding some graphics and rendering the bullet at the correct angle etc.

core/src/uk/co/carelesslabs/entity/ammo/SimpleBullet.java

package uk.co.carelesslabs.entity.ammo;

import uk.co.carelesslabs.Media;
import uk.co.carelesslabs.Enums.EntityType;
import uk.co.carelesslabs.box2d.Box2DHelper;
import uk.co.carelesslabs.box2d.Box2DWorld;
import uk.co.carelesslabs.weapons.Gun;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.BodyDef;

public class SimpleBullet extends Ammo {
    Gun gun;

    // A new bullet has some defaults set
    public SimpleBullet(Gun gun, Box2DWorld box2d) {
        super();
        this.gun = gun;
        type = EntityType.BULLET;
        texture = Media.close_menu;
        range = 50;
        damage = 1;
        width = 8;
        height = 8;
        speed = 60;
        active = true;
        setupBullet(box2d);
    }

    public void tick(float delta) {
        // only process if active
        if (active) {
            float dx = (delta * vector.x) * speed; // Calculate the x amount (+-)
            float dy = (delta * vector.y) * speed; // Calculate the y amount (+-)
            float dx2 = pos.x + dx; // Calculate the new X position
            float dy2 = pos.y + dy; // Calulate the new Y position

            // Compare the current postion and the new position
            // get difference in distance and add that onto distMoved
            distMoved += Vector2.dst(pos.x, pos.y, dx2, dy2);

            // Set the new postion of the bullet
            pos.set(dx2, dy2, 0);

            // Update the postion of the sensor
            sensor.setTransform(pos.x + width / 2, pos.y + height / 2, 0);

            // Check if bullet has travelled its range
            // We do not want bullets moving for ever
            if (distMoved > range) {
                // Remove Bullet
                remove = true;
                active = false;
            }
        }
    }

    // The bullet vector is along the line at which the gun is pointing at the moment the space bar was pressed.
    // A quick fix to move the bullet toward the end of the gun is setting the bullet x to match the gun and move it
    // along the heading by 10, we apply the same to the y position and it will move along its heading.
    //
    // We create a sensor which will be used for collision checking with Box2D.
    public void setupBullet(Box2DWorld box2d) {
        // Position
        float angleRadians = MathUtils.degreesToRadians * gun.angle;
        vector.x = MathUtils.cos(angleRadians);
        vector.y = MathUtils.sin(angleRadians);

        // Move bullet toward end of gun
        pos.x = gun.pos.x + (vector.x * 10);
        pos.y = gun.pos.y + (vector.y * 10);

        // Physics
        sensor = Box2DHelper.createSensor(box2d.world, width, height * .85 f, width / 2, height / 3, pos, BodyDef.BodyType.DynamicBody);
        hashcode = sensor.getFixtureList().get(0).hashCode();
    }
}

The only change left is to amend the Gun class; first we add an ammoCount, this will be used to check if the gun has ammo to fire, on firing we will need to decrease this value.
The new ArrayList activeAmmo will be used to track ammo that needs to tick each frame.

core/src/uk/co/carelesslabs/weapons/Gun.java

The ArrayList is initiated in the Public Gun method:

activeAmmo = new ArrayList();

Two new methods tick and addActiveAmmo; tick allows the gun to loop through its activeAmmo and call tick for each ammo item. addActiveAmmo will decrease a guns current ammo count and add a new bullet to the active list, this is the bullets that have been fired, if the variable name doesnt made sense feel free to rename it to firedAmmo for example. As already mentioned the ammoCount check should have occured before this function.

When the gun is empty of ammo at the moment we will just print line, later this can draw some graphic to the screen or play a sound.

public void tick(float delta) {
    for (Ammo a: activeAmmo) {
        a.tick(delta);
    }
}

public void addActiveAmmo(Ammo a) {
    if (ammoCount > 0) {
        activeAmmo.add(a);
        ammoCount--;
    } else {
        System.out.println("Clink");
    }
}

Drawing the bullet, the guns draw method simply loops through active ammo and as it extendings Entity can use its draw method.

public void drawRotated(SpriteBatch batch){
    ...
    for(Ammo a : activeAmmo){
        a.draw(batch);
    }
}

Simple method to add bullets, this can be used later on when we have collectables.

    public void addAmmo(int count) {
        ammoCount += count;
    }

This method "clearTravelledAmmo" is used to remove bullets that have travelled over their range and been marked for removal. The ammo must be removed from the activeAmmo array, any bodies/sensors removed from the Box2D World. We use an iterator as they allow the caller to remove elements from the underlying collection during the iteration, other loops will crash if you remove items while looping through.

public void clearTravelledAmmo(Box2DWorld box2D) {
    Iterator it = activeAmmo.iterator();
    while(it.hasNext()) {
        Ammo a = it.next();
            if(a.remove){
                a.removeBodies(box2D);
                box2D.removeEntityToMap(a);
                it.remove();
        }
    }
}

Lots of small changes and some new classes but we now have the ability to fire bullets, the next tutorial will look at the collision of these bullets with other entities. If you enjoy or find these tutorials useful feel free to let me know at Twitter: @CarelessLabs

There are improvements this code requires and you should carry these out yourselves and please let me know of any bugs!

Image

A Careless 2018 in #Gamedev

I have not been the most active in 2018, I have created some content though, here is a look at some of the highlights:

Black Hole
I have been tinkering with index painting for a while and came up with a technique to paint and convert to pixel art, was a pretty slow progress but helped generate some interesting results. Really happy with how this turned out.

Black Hole Pixel Art

What started out as a small pixel daily turned into a these tiny islands with fishing huts:

Island & huts pixel art

Made a running calculator http://carelesslabs.co.uk/run/

I do quite a lot of running and often like to work out the pace I will need for personal bests and so on so wrote a pace, speed and time calulator. The webpace uses Javascript / JQuery and was quite fun to do.

Wrote a tutorial
After failing to complete the LibGDX series of tutorials to the extend I would have been happy with, revistied this simple island game and added in a weapon with Nuclear Throne style movement / rotation. I do plan on making some smaller tutorials in 2019.

Had a popular Tweet
Not an achievement but a message I have pinned to my Twitter profile as a reminder to stick to one project.

Joined in the Pixel Dailies draw yourself 40k follower celebration

More Pixel Art

HTML5  http://carelesslabs.co.uk/game_a_month/
I started working on a game a month challenge but it closed down! I would like to enter a LudumDare with a simple JavaScript game one day but not enough spare time this year.

So there we have it, 2018 I was a little lazy with regards to game development although I have progressed a new topdown car game which I will be posted about soon!

Cars, skids, dust and smoke

I have been working again on a topdown car prototype, recently adding skid marks, dust and exhaust smoke to the car to improve the look and feel of the game.

dust_skid_smoke

Box2D is being used for the car physics, the car images are rendered using the position of the Body used for the vehicle. When its decided to render any decals (smoke, dust or skids) the Body could be at any angle. If the distance from the centre of the car to an edge is known then its possible to calculate its position (applies to front right/left and back right/left). When a new vehicle is created the radius of the circle that would hold the rectangle is calculated:

Screen Shot 2018-08-03 at 00.23.53

formula

x and y will be known when the car is created or could even be (0,0), x2 will be x + half the width of the car and y2 is y + half the length of the car, this radius value is held in the Car class. Math.pow and Math.sqrt are useful functions to complete the calculation.

Adding decals
When decals are added to be rendered the x and y positions can be calculated using the distance (radius) from the centre of the cars current position given an angle. The cars current angle must be taken into account

angle = car.body.getAngle() + angle;
decalX =  radius * cos(angle);
decalY radius * sin(angle);

Currently I am adding decals at the front two or back two wheels but hard coding the angles, in radians:

  • Front Right is 4.1f
  • Front Left is 5.1f
  • Back Right is 2.1f
  • Back Left is 1f

These values along with the cars current angle make sure the affects are rendered in the correct corners of the rectangle which is the car.

The smoke is rendered always at the back left of the car, dust is added to either the front, back or all tires, when the car is pulling off the dust is added based on the car being front or rear wheel powered. To add some realism to the dust 10% of the cars velocity is applies to the dust entity so while it is active it has some movement.

Next I will Calculate the angle to each of the corners of the rectangle rather than hard coding them, this tutorial will be updated once that is in place, I will also add some more detail on how I achieved the simple smoke and dust affects.

Nuclear Throne style weapon movement #LibGDX #Gamedev

I have published 11 tutorials on making a game from scratch, while the game was intended to be a rougue-like it has evolved away from the genre. I aim to add interesting features which might help others. While this may never be a fun to play or complete game it hopefully will aid others in producing their own games.

If you are interested in checking out the changes to the Chunk management and also the loading and saving methods then check out this pull request (I will create posts about these changes in the future.):

https://github.com/tyler6699/evoscape/pull/7

This tutorial will add a weapon to the Hero that points toward the mouse cursor position. The gun points right or left and swaps hands depending on the mouse position.

gun_anim

Full source code on Github

Entity Class
New variables are added to Entity that will allow rotation and horizontal flipping of
a texture, this means we only need one image for the weapon, also we will add an active flag and an array of guns called weapons. The active flag can be used later to determine if the gun or weapon has been drawn. The array will allow multiple weapons in a future tutorial.

The drawRotated method uses spriteBatch draw that will allow the angle and rotation point of our entity.

// New Variables
public float angle;
public Boolean flipX = false;
public Boolean flipY = false;
public boolean active;
public ArrayList weapons;

// New draw function which we will over ride
public void drawRotated(SpriteBatch batch){
  if(texture != null) batch.draw(texture, pos.x, pos.y, 0, 0, width, height,1, 1, angle, 0, 0, (int)width, (int)height, flipX, flipY);
}

All of the available parameters for the draw method we are calling.

x the x-coordinate in screen space
y the y-coordinate in screen space
originX the x-coordinate of the scaling and rotation origin relative to the screen space coordinates
originY the y-coordinate of the scaling and rotation origin relative to the screen space coordinates
width the width in pixels
height the height in pixels
scaleX the scale of the rectangle around originX/originY in x
scaleY the scale of the rectangle around originX/originY in y
rotation the angle of counter clockwise rotation of the rectangle around originX/originY
srcX the x-coordinate in texel space
srcY the y-coordinate in texel space
srcWidth the source with in texels
srcHeight the source height in texels
flipX whether to flip the sprite horizontally
flipY whether to flip the sprite vertically

Gun Class

At the moment the gun class is a basic entity that only draws to the screen, I will look at shooting in the next tutorial. What we care about is the position of the mouse retaliative to the hero, is it to the left or right side and at what angle.

The Gun class has x and y offsets for the origin and also the x position, these values allow us to move the gun into the hand of the hero. The gun can be set to the Hero’s x position by default and moved left or right accordingly, knowing the size of the gun and hero we can work out how far to move it so it appears in the correct position.

package uk.co.carelesslabs.weapons;

import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import uk.co.carelesslabs.Media;
import uk.co.carelesslabs.entity.Entity;

public class Gun extends Entity {
	float originXOffset; // OriginX Offset
	float originYOffset; // OriginY Offset
	float xPos;          // X offset for gun position
	float xMinPos;       // X Position offset facing left
	float xMaxPos;       // X Position offset facing right

	public Gun(float originXOffset, float xMinRight, float xMaxRight){
		texture = Media.gun;
		width = texture.getWidth();
		height = texture.getHeight();
		active = true;
		originYOffset = height/2;
		this.originXOffset = originXOffset;
		this.xMinPos = xMinRight;
		this.xMaxPos = xMaxRight;
	}

    public void drawRotated(SpriteBatch batch){
    	if(angle > 90 && angle < 270){ // 6 to 12 Clockwise or LEFT
    		xPos = xMinPos;
    		flipY = true;
    	} else { // 12 to 6 clockwise or RIGHT
    		xPos = xMaxPos;
    		flipY = false;
    	}
        // When the gun is to the right of the hero we move
        // the it by xMaxPos (7) and when
        // its to the left we move it byxMinPos (-1)
        if(texture != null) batch.draw(texture, pos.x + xPos, pos.y, originXOffset, originYOffset, width, height, 1, 1, angle, 0, 0, (int)width, (int)height, flipX, flipY);
    }
}

Hero Class

There is a new Vector3 added to the hero class, previously the hero was not aligned to the centre of the screen, this new variable will be updated to the hero position but half of the hero width +/- from the x value so that the hero appears centred.

A new ArrayList of ‘Gun’ called weapons is setup and initiated, we add a Gun to the list, the origin X Offset is set to 1 and the min and max x offsets set the -1 and 7. This sets up the rotation point and the left/right positions relative to the hero.

public Hero(Vector3 pos, Box2DWorld box2d){
  super();
  cameraPos = new Vector3(); // new variable
  type = EntityType.HERO;
  width = 8;
  height = 8;
  texture = Media.hero;
  speed = 30;
  inventory = new Inventory();
  reset(box2d, pos);

  // Weapon
  weapons = new ArrayList();
  weapons.add(new Gun(1, -1, 7));
}

Draw function

The Hero draw function now loops through the weapon array and will call drawRotated for any active gun.

The cameraPos variable is also updated in this draw method, it is set to the same as the hero position and then the x value has half of the Hero width added on.

@Override
public void draw(SpriteBatch batch){
  if(shadow != null) batch.draw(shadow, pos.x, pos.y, width, height);
  if(texture != null) batch.draw(texture, pos.x, pos.y, width, height);
// Loop all weapons and draw the active ones
  for(Gun g : weapons){
      if(g.active){
        g.drawRotated(batch);
      }
   }

...
     // Update Camera Position
     cameraPos.set(pos);
     cameraPos.x += width / 2;
}

Gun position
The gun by default is positioned at Hero.pos.x, it it was not moved using the x offset this is how it would look:
001_gun_hero_pos

Once it is in game and rotating you can see if flips but stay in the right hand of the Hero:gun_no_x_offset

The small yellow cross shows the point at which the entity rotates around, placing it here makes the movement seem more real than if it was centred.

When the gun needs to face right flip is set to false and it is rendered hero x + 7. When the gun is facing left the texture is flipped and moved left by 1. The texture flips from the x point so the flip alone moves the texture left by the width. If you change the origin X value you can see how it affects the rotation (Not all weapons would have the same rotation point)

 

Hero update

When the Hero update is called we should update all active weapons so they move with the Hero, we also update the angle, I found that the mouse angle from the centre of the screen did not match the draw function, taking 90 degrees away made these match.

public void update(Control control) {
  ....
  // Update weapons
  for(Gun g : weapons){
  	if(g.active){
            g.updatePos(pos.x, pos.y);
      	    g.angle = control.angle - 90;
  	}
  }

ENUMS

If you wanted a Hero that faced the mouse (8 directions) we can implement a mouse angle to compass position, while this is not used in the tutorial it may be useful to someone and we can use it in the future. Here are the ENUM values, the order of these is important.

/**
 * Compass directions
 */
public enum Compass {
    S,
    SE,
    E,
    NE,
    N,
    NW,
    W,
    SW
}

Control Class

The new angle and facing variables will be set/updated within the the Control class.  On mouseMoved we have the x and y values for the current mouse position which can be used to calculate the angle between the screen centre and the cursor:
angle = (float) Math.toDegrees(Math.atan2(screenX – (screenWidth/2), screenY – (screenHeight/2)));

if the angle is negative then we add 360:
angle = angle < 0 ? angle += 360: angle;

To turn this angle into a compass direction:
direction = (int) Math.floor((angle / 45) + 0.5) & 7;

This will produce 0 to 7 as a result, we can then pick N ENUM from the list, 0 is S 1 is SE and so on:
facing = Compass.values()[direction];

  // ACTIONS
  public boolean interact;
  public float   angle;
  public int     direction;
  public Compass facing;

  @Override
  public boolean mouseMoved(int screenX, int screenY) {
      float flippedY = screenHeight - screenY;
      mousePos.set(screenX, flippedY);

      // Set angle of mouse
      angle = (float) Math.toDegrees(Math.atan2(screenX - (screenWidth/2), screenY - (screenHeight/2)));
      angle = angle  0){
            Rumble.tick(Gdx.graphics.getDeltaTime());
            camera.translate(Rumble.getPos());
        } else {
            camera.position.lerp(hero.cameraPos, .2f); // use new Vector3 variable<span id="mce_SELREST_start" style="overflow:hidden;line-height:0;"></span>
        }

Hopefully there are a few useful snippets of code in the tutorial, remember there are always other ways to achieve a goal and often more efficient methods.

Next time I will add bullets and firing, thanks for reading!

LibGDX Tutorial series update #gamedev

loading.gif

I have been working recently on a game called EvoScape and producing tutorials as I progress it.

After making what would start out as simple save / load functionality many commits and changes were made that would need explaining for part 12 to be useful. I feel there is too much code to explain and it wont be useful to those who read it.

There are many tutorial ideas I have but feel it would be easier for people to follow if I were to create smaller or new projects rather than adding to EvoScape.

I will look back at the project and blog about changes made to it but not rely on this for all of the tutorials I will continue to write.

I have squashed the latest commits for part 12 into one large commit: EvoScape latest branch

If you are interested in the code changes please take a look, I have changed the chunk system to now deal with a 9 chunks (3×3) each chunk consisting of 32×32 tiles. GSON is used to convert the entities and chunks into JSON which is compressed and stored in a text file. I had some issues loading the JSON directly back into classes so wrote a custom loader. I will blog on some of the ideas in this commit as individual blog posts and in separation from the game soon.

Thanks for following this tutorial series and I hope you call back to check out the next set of new posts.

Making a LibGDX Roguelike Survival Game Part 11 – Custom menu / buttons #gamedev

Welcome to the 11th part in this game from scratch series, in this tutorial we look at changing the projection of our sprite batch to allow us to render a heads up display / menu and also create the classes which will allow us to generate interactive menus. The full source code is available on Github.

menu_tutorial

New Images

  • core/assets/gui/main_background.png
  • core/assets/gui/pink_button.png
  • core/assets/gui/square_menu.png
  • core/assets/gui/icons/build.png
  • core/assets/gui/icons/close_menu.png
  • core/assets/gui/icons/resources.png
  • core/assets/gui/icons/settings.png
  • core/assets/gui/selector.png

New classes

  • core/src/uk/co/carelesslabs/ui/BuildMenu.java
  • core/src/uk/co/carelesslabs/ui/Button.java
  • core/src/uk/co/carelesslabs/ui/Menu.java
  • core/src/uk/co/carelesslabs/ui/OnClickListener.java
  • core/src/uk/co/carelesslabs/ui/SquareMenu.java

Updated

  • core/src/uk/co/carelesslabs/Media.java
  • core/src/uk/co/carelesslabs/gameclass.java
  • core/src/uk/co/carelesslabs/Enums.java
  • core/src/uk/co/carelesslabs/Control.java

Custom menu

In this tutorial we will look at creating a custom menu for our game, this eventually will
allow the player to access/view build, settings and inventory. There are libraries available to handle all sorts of inputs (buttons, text boxes etc) such as Scene2D, but when the menu is basic and for learning LibGDX its interesting and sometimes simpler to create your own.

Rendering the menu

Whereas the main game camera moves around the map and can zoom / shake etc the menu view will need to be fixed.

The projection set for game screen is not fit for displaying the menu. Initially I created a new spriteBatch for the HUD (Heads Up Display) which was created using the screen size, this seemed less efficient than having just one spriteBatch, to use only one we will need to update the Matrix of the spriteBatch before rendering the HUD.

We can achieve this by updating the projection of the spriteBatch prior to rendering.

gameclass.java

// new class variable
Matrix4 screenMatrix;

@Override
public void create() {
    ...
    // Setup Matrix4 for HUD
    screenMatrix = new Matrix4(batch.getProjectionMatrix().setToOrtho2D(0, 0, control.screenWidth, control.screenHeight));

...

@Override
public void render () {
  ...
  // GUI
  batch.setProjectionMatrix(screenMatrix);

The screenMatrix will allow us to change to spriteBatch back to a view the size of the screen, co-ordinates 0,0 will be the bottom left of the screen. With the view being the same size as the screen it will be easy to position menu items as we can access the screen width and height.

Menu

Menu.java

The new menu class has a texture which is the background for the menu, a postiion, width and height used when rendering, a Rectanlge (hitbox)
and an array of buttons.

package uk.co.carelesslabs.ui;

import java.util.ArrayList;
import uk.co.carelesslabs.Enums;
import uk.co.carelesslabs.Enums.MenuState;
import uk.co.carelesslabs.entity.Entity;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector2;

public class Menu {
    public String name;
    public Vector2 pos;
    public Texture texture;
    public float width;
    public float height;
    public float scale;
    public MenuState state;
    public float time;
    public float coolDown;
    public Rectangle hitbox;
    public ArrayList<Button> buttons;

    public Menu(float x, float y, float scale, Texture texture){
        pos = new Vector2(x,y);
        this.texture = texture;
        width = texture.getWidth() * scale;
        height = texture.getHeight() * scale;
        buttons = new ArrayList<Button>();
        hitbox = new Rectangle(x,y,width,height);
        setActive();
    }

    // Render the texture and all of the button textures
    public void draw(SpriteBatch batch){
          if(texture != null) batch.draw(texture, pos.x, pos.y, width, height);
          for(Button b : buttons){
              b.draw(batch);
          }
    }

    // If the player has clicked the mouse then processedClick will be true
    // We check if the mouse position is contained within any of the button Rectangles
    public boolean checkClick(Vector2 pos, boolean processedClick){
        boolean processed = false;
        if(!processedClick){
            if(hitbox.contains(pos)){
                System.out.println("Hit: " + name);
            }

            // Check if a button has been clicked
            for(Button b : buttons){
                if(b.hitbox.contains(pos)){
                    if (b.listener != null) b.listener.onClick(b);
                    processed = true;
                    break;
                }
            }
        } else {
            return processedClick;
        }

        return processed;
    }

    // If the mouse is inside of the menu then check if its also inside of a button
    // When the mouse is inside a button then set its state to hovering
    // Else set all buttons to idle
    public void checkHover(Vector2 pos){
        if(hitbox.contains(pos)){
            // Check if a button is being hovered over
            for(Button b : buttons){
                if(b.hitbox.contains(pos)){
                    b.state = Enums.EnityState.HOVERING;
                } else {
                    b.state = Enums.EnityState.IDLE;
                }
            }
        } else {
            for(Button b : buttons){
              b.state = Enums.EnityState.IDLE;
            }
        }
    }

    // A function to add multiply buttons to our menu
    // It is possible to add any size grid of buttons with a certain sized padding
    public void addButtons(float offset, int columns, int rows, Texture texture, Texture select, int scale) {
        for(int i = 0; i < columns; i++){
            for(int j = 0; j < rows; j++){
                float bx = pos.x + (offset + ((i+1)*offset) + (i * texture.getWidth())) * 2;
                float by = pos.y + (offset + ((j+1)*offset) + (j * texture.getHeight())) * 2;
                float width = texture.getWidth() * 2;
                float height = texture.getHeight() * 2;

                Entity selector = new Entity();
                selector.texture = select;
                selector.width = selector.texture.getWidth() * scale;
                selector.height = selector.texture.getHeight() * scale;
                selector.pos.x = bx - ((selector.width - width) / 2);
                selector.pos.y = by - ((selector.height - height) / 2);

                buttons.add(new Button(bx, by, width, height, texture, selector));
            }
        }
    }

    // Check if the menu is active
    public boolean isActive(){
        return state == Enums.MenuState.ACTIVE;
    }

    // Set meny to active
    public void setActive(){
        state = Enums.MenuState.ACTIVE;
    }

    // Set menu to inactive
    public void setInactive(){
        state = Enums.MenuState.DISABLED;
    }

    // Toggle active state
    public void toggleActive() {
        if(isActive()){
            setInactive();
        } else {
            setActive();
        }
    }
}

Button.java

The Button class extends Entity, it adds an OnClickListener, a hitbox, an icon texture and a selector entity. The OnClickListener defines
what to do when the button is clicked, the hitbox allows us to test if the mouse position when a click occurs should interact with
button, the selector is a texture that is drawn when the button is being hovered over and the icon is a texture to help identify what
the button does.

package uk.co.carelesslabs.ui;

import uk.co.carelesslabs.Enums;
import uk.co.carelesslabs.entity.Entity;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.math.Rectangle;

public class Button extends Entity {
    public OnClickListener listener;
    public Rectangle hitbox;
    public Texture icon;
    public Entity selector;

    public Button(float x, float y, float width, float height, Texture texture, Entity selector) {
        super();
        this.texture = texture;
        this.selector = selector;
        this.pos.x = x;
        this.pos.y = y;
        this.width = width;
        this.height = height;
        hitbox = new Rectangle(pos.x, pos.y, width, height);
    }

    public void setOnClickListener(OnClickListener listener){
        this.listener = listener;
    }

    @Override
    public void draw(SpriteBatch batch){
        if(texture != null) batch.draw(texture, pos.x, pos.y, width, height);
        if(icon != null) batch.draw(icon, pos.x, pos.y, width, height);
        if(isHovered() && selector != null){
            selector.draw(batch);
        }
    }

    // Is button currently being hovered over by the mouse
    private boolean isHovered(){
        return state == Enums.EnityState.HOVERING;
    }

    // Updates the position and size of the hitbox (Rectangle)
    public void updateHitbox() {
        hitbox.set(pos.x, pos.y, width, height);
    }
}

OnClickListener.java

We can create an instance of this interface for each button and use it to create an over ride of the onClick function, within this function
we can write custom code that will run when onClick is called.

package uk.co.carelesslabs.ui;

public interface OnClickListener {
    public void onClick(Button b);
}

An example of setting the onClick function for a button

// Setting the onClick function for a button called button
// We can put any code here
btn.setOnClickListener(
        new OnClickListener(){
            @Override
            public void onClick(Button b) {
                // Declare code to run here
                System.out.println("This button was clicked.");
            }
        });

SquareMenu.java

The SquareMenu is the bottom left square shapped main menu, it has 3 icons at the moment, one for inventory/resources, a build menu and also an icon for settings.

This class extends menu, we set the position and background texture using super (calls the constructor for the extended class ‘Meny’), 4 buttons are added in a 2×2 grid.
The icons and onClick for each button is set, currently we set up only 3 of the buttons.

A new type of menu ‘Build’ is also added, this menu will be hidden by default and only shown when the build icon/button is clicked.

package uk.co.carelesslabs.ui;

import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.math.Vector2;
import uk.co.carelesslabs.Media;
import uk.co.carelesslabs.gameclass;

public class SquareMenu extends Menu {
    public BuildMenu build;

    public SquareMenu(final gameclass game){
        super(0, 0, 2, Media.squareMenu);

        int scale = 2;
        addButtons(3, 2, 2, Media.pinkButton, Media.selector, scale);

        Button btn = buttons.get(0);
        btn.setOnClickListener(
                new OnClickListener(){
                    @Override
                    public void onClick(Button b) {

                    }
                });

        btn = buttons.get(1);
        btn.icon = Media.iconSettings;
        btn.setOnClickListener(
                new OnClickListener(){
                    @Override
                    public void onClick(Button b) {
                        System.out.println("Settings.");
                    }
                });

        btn = buttons.get(2);
        btn.icon = Media.iconResources;
        btn.setOnClickListener(
                new OnClickListener(){
                    @Override
                    public void onClick(Button b) {
                        game.control.inventory = true;
                    }
                });

        btn = buttons.get(3);
        btn.icon = Media.iconBuild;
        buttons.get(3).setOnClickListener(
                new OnClickListener(){
                    @Override
                    public void onClick(Button b) {
                        build.toggleActive();
                    }
                });

        // BUILDING
        build = new BuildMenu(pos.x + width, 0, 2, Media.mainBack);
    }

    // Draw the extended menu and also the build menu.
    @Override
    public void draw(SpriteBatch batch){
        super.draw(batch);
        build.draw(batch);
    }

    // Check if the menu / build menu buttons are being hovered over.
    @Override
    public void checkHover(Vector2 pos) {
        super.checkHover(pos);
        build.checkHover(pos);
    }

}

BuildMenu.java

This class is another extended Menu class which is shown when the build menu button has been pressed. It has 14 columns and 2 rows which will be used
to add building options in another tutorial. Clicking these will allow items to be built/placed onto the map.

This class also adds another button which will call toggleActive(), basically this is a close menu button. The main build menu button will also close
menu when it is clicked and the build menu is currently active.

package uk.co.carelesslabs.ui;

import uk.co.carelesslabs.Media;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;

public class BuildMenu extends Menu {

    public BuildMenu(float x, int y, int scale, Texture mainBack){
        super(x, y, 2, Media.mainBack);
        addButtons(3, 14, 2, Media.pinkButton, Media.selector, 2);
        setInactive();

        // Add a close button
        Button close = new Button(0, 0, Media.close_menu.getWidth() * scale, Media.close_menu.getHeight() * scale, Media.close_menu, null);
        close.pos.x = x + width - (Media.close_menu.getWidth() * scale) - (6 * scale);
        close.pos.y = height - (Media.close_menu.getHeight() * scale) - (6 * scale);
        close.updateHitbox();
        close.setOnClickListener(
                new OnClickListener(){
                    @Override
                    public void onClick(Button b) {
                        toggleActive();
                    }
                });
        buttons.add(close);
    }

    // Only draw when the menu is active.
    public void draw(SpriteBatch batch){
        if(isActive()){
            super.draw(batch);
        }
    }
}

Enum.java

New ENUM list for menu/button states.

...
public enum MenuState {
    ACTIVE,
    DISABLED,
    HOVEROVER,
    CLICKED
}

Control.java

New Vector for the mouse position which is updated on mouseMoved.

...
public Vector2  mousePos = new Vector2();

...
@Override
public boolean mouseMoved(int screenX, int screenY) {
    mousePos.set(screenX, screenHeight - screenY);
    return false;
}

The menus are not yet complete but this gives us a decent foundation for completing / progressing our HUD.