Showing posts with label love2d. Show all posts
Showing posts with label love2d. Show all posts

Thursday, September 24, 2020

Simple Platformer - part 5

Getting started with Love2d - part 5

Introduction

Welcome to part 5 of my Love2d tutorial. In this part we are going to add tiles to the game.

Adding tiles

The first thing we need to do is to create three tile pieces. For this i used GIMP and made three simple squares.
Next create a directory called images and place the three tile pieces there.

Tile 1
Tile 2
Tile 3

The next thing to do is to create a file Tiles.lua.
Inside this file, the first thing to do is to create a tile map.
This is a 2d array using numbers to represent location of the tiles on the map

  • 0 represents empty space
  • 1 represents tile 1
  • 2 is tile 2
  • 3 is tile 3
Tile Map

For the next part, the steps are:

  1. Create an Icon object to hold icons. it should store:
    • icon for the tile created with love.graphics.newImage()
    • width of icon using getWidth()
    • height of icon. Use the function getHeight()
  2. Create Icon list.This is a list to hold the Icon objects.
  3. Create a function which populates the icon list with the three icons tile1, tile2, and tile3.
  4. A function to loop through the tile map and print each tile.
    • We use a nested for loop to loop through the tile map.
    • If the tile isn't zero then we print the corresponding icon from icon_list using the number in Tile_Map.
Tile objects and Tile list

Modifying main.lua

We now need to make a few changes to main. We need to call our new code and we clean up a few things we previously added.

New stuff to add

  • Icon_List:populate we call the populate function in our love.load() function.
  • drawTileMap() We add this function to love.draw() in order to draw the tiles on each update.

Cleaning up older stuff

We now clean up some of our older code to improve our main.lua file.

  • we change our player construct function to use an image icon using love.graphics.newImage().
  • we change our enemy construct function to use an image icon directly.
  • we change the values for WIDTH and HEIGHT to accommodate our new tile map.
updated main.lua

Updating Characters.lua

We now make a few changes to our Characters.lua file.

  • o.icon = icon we set the objects icon to the icon we pass to it. No more calling love.graphics.newImage()
  • o.y = y - o.oy we adjust the y position to account for the y offset.
Updated Characters.lua

Friday, August 28, 2020

Simple Platformer - Part 4

Getting started with Love2d - part 4

Introduction

Welcome to part 4 of my ongoing series about game dev using Love2d.
In this part we will expand upon the work we did previously.
First we will slightly alter how we draw images to screen.
Then we will better organize our code to move the player.
Lastly we will add the ability to run into enemies and destroy them.

Working with offsets

The typical way that love2d draws an image onto screen is to use x,y coordinates.
So far the way we have been using them, love2d has been using x,y as the upper left corner of the image.
We would like to change this so that x,y refer to the center of the image.
We will place the offsets in two variables in CHARACTER class as ox, and oy.
We will set the value to these variables using the love2d functions getHeight() and getWidth()

Updated CHRACTER constructor
New variable in CHARACTER class

We will now update our draw function to accommodate these offsets.
As you can see from the image below, .draw() now has a bunch of new arguments.
If you want to know what each of them are, please see the Love2d reference

udated draw function
Updated draw function

You will now see that the program draws the player character a bit off screen.
You can fix this by adjusting the x and y values you use when creating him.
You will also notice that our bounds checking is slightly off now. Don't worry, we will soon fix this.

Improving movement

The first thing we are going to do is break up our current keypress function into smaller functions.
We are going to create one function per direction: up,down,left,and right.
Since no other object in the game uses these functions, we make them belong to PLAYER class.
We place these functions in our Characters.lua file.

new player movement functions
Player movement functions

We can now clean up our keypress function.
We can simply call the corresponding function to move player that direction.

Updated keypress function
Updated keypress function

If you test it out, this now works just as before, but much better organized.
But wouldn't it be nice to be able to move around by holding down the key?
I think it would, so we can replace our love.keypress() by a new function.
We make our keyboardInput() and use the function love.keyboard.isDown("key").
After making keyboardInput we call it at the end of love.update()

keyboardInput function
our new keyboard input function

You should now be able to move the player character around by holding down a movement key.
The speed at which he moves is governed by the speed variable inside of CHARACTER class.
We next need to slightly adjust our enemy move function to account for the offsets.
Once that is done you should now see the game working as it should.

Updated enemy move function
Updated ENEMY:move()

Collision detection

We are now going to add the ability to collide into an enemy.
When player character collides into an enemy, the enemy is removed from the game.
We need to check for four conditions to account for a collision:

  • player's head is above the enemy's feet.
  • The player's feet are below the enemy's head.
  • Player's left side is to the left of the enemy's right side.
  • Player's right side is to the right of the enemy's left side.

If you walk through these four steps, maybe even draw out a diagram, you will see that it accounts for a collision between the player and enemy.
We will add a function in Character.lua to account for this.
We make this function belong to ENEMY class.
You can see that it checks for a collision and returns true if player and enemy collide.

function which checks for a collision with an enemy
function to check for a collision

Now that we can check for a collision between a player and a single enemy, we need to expand this for all enemies.
We accomplish this by writing a function in main.lua to loop through ENEMY_LIST.
This functions checks for collision with the player on each and every enemy in ENEMY_LIST.
If a collision is detected with an enemy, we remove that enemy object from ENEMY_LIST.
Once we have this function, we need to call it at the bottom of our love.update() function.

Checking each enemy for a collision
function to check all enemies for a collision

With everything in place we should now be able to touch an enemy and have them removed from the game.

Final remarks

Thank you for checking our part 4 of my series on Love2d.
Continue on to part 5
As always, you can get the complete code from github.

Thursday, August 27, 2020

Simple Platformer - Part 3

Getting started with Love2d - part 3

Introduction

This is part 3 of my ongoing series on making a simple platformer using Love2d.
For this part we are going to continue our adventure into OOP and further improve our code.
We will make a dedicated player class,start doing some polymorphism, and create some more enemies.

get organized

The first thing we will do is get better organized.
In the directory where main.lua is, make a new directory named 'images'
We will now put our character images here to help keep us organized.
In the code where we load images, we need to change 'player.png' to '/images/player.png'
Do the same for the enemy image as well.

making a player class

The next thing we need to do is create a player class. This is identical to how we made an enemy class
So far we have no unique variables or functions for player but we will change that later on.

Player class
player class

Now that we have a player class we need a constructor functions.
This is also similar to what we did with enemy class.

constructor for player objects
player constructor

We now need to change one line in main.lua to make player a PLAYER object.

updates love.load()
making player object in main.lua

We now have a working separate class for our player

Making multiple enemies

We will now make multiple enemies in our game.
To easily handle this we are going to create a table to hold enemy objects.
And to make this even easier, we make a function to populate this list for us.
So we have ENEMY_LIST to hold our enemies and makeEnemies() to populate our table with enemy objects

tabel to hold multiple enemy objects.
making list of enemies

We now have multiple enemies in our game. This can easily be expanded to make as many as we want.
Notice that the i*100 in our function just places the enemies 100 pixels a part.
Also notice that the WIDTH has been increased to accommodate these new enemies.

Drawing characters

We will now go further with our OOP adventure.
To do this we need to create a function to draw character objects to screen.
Since both player and enemy are subclasses of character, this function will work for both of them.
Hurray for polymorphism.

function to draw character to screen
function to draw character objects to screen

We now need to make a function to go through enemy_list and print each enemy to screen.
To accomplish this we just need a loop to go through enemy_list, pretty simple stuff.
Notice we make use of our newly made draw function.

loop through enemy_list and draw each enemy to screen
function to draw enemies to screen

Now that we have our function to draw objects to screen and a loop to go through each enemy, we need to update love.draw().
With just these two lines we can now print both the player and all the enemies to screen on each frame.

updated love.draw()
updated our love.draw() function

We now have the capability to print a player and any number of enemies to screen.
so far the enemies don't do anything, but we are about to change that.

Moving Enemies

We will now make our enemies move back and forth as we previously did with a single enemy.
To do this we need a function to go through ENEMY_LIST.
With each enemy object in the loop we call the move function which we previous made

function to move enemies
function to move each enemy on screen

We now need to update our code in love.update to call this new function.

updated love.update()
updated love.update()

we should now have three enemies moving across the screen and a player who can also move around

The game so far.
Enemies moving around

Final remarks

With just a little bit of reorganizing and adding a tiny bit to our previous code we can now:

  • make multiple enemies in our game.
  • print them all to screen.
  • have each enemy move independent of each other.

It may not seem much, but it is progress we are making on our game.
The full code for this part is available on github
Thank you for checking out part 3 of my series on game dev.continue to part 4

Simple Platformer - Part 2

Getting started with Love2d - part 2

Introduction

This is part 2 of my ongoing journey to make a simple platformer utilizing Love2d.
In this part we will utilize basic OOP functionality and also make the enemy character move across the screen.

OOP

To improve upon our code, we are going to utilize basic principles of OOP(or as OOP as lua gets.)
The first thing we can do to improve our code is make a class for our characters.
The first step is to create a CHARACTER class followed by a constructor function:CHARACTER:new()
In the constructor we make a new character object then assign the variables in that object the correct values.
In a file called 'Characters.lua' we add the code:

Characters.lua
basic Character class

The next step is to make some changes in main.lua
When need to let lua know about our character class,so we add require "Characters"
Next we need to create character objects for the player and enemy, so we change the code in love.load()
The final bit of change is that we need to use the x and y in these objects therefore we alter the code in love.draw() and love.keypress()
The updated main.lua code can be seen below:

updated main.lua

Moving the enemy character

Now we can work on getting the enemy character to move left and right.
we want him to move right until he reaches the limit set by WIDTH, then have him move left till he hit the edge.then rinse repeat
To accomplish this we are going to add a function in Character.lua to handle this. CHARACTER:move() As long as move_r is true then the enemy should move to the right.
We employ the same bounds checking as we did in key.press in part 1.
When the enemy reaches the right hand boundary, we have to change his direction, that's where move_r = false comes into play.
And when the enemy reaches the left hand side, we simply set move_r back to true.
You can see the complete CHARACTER:move() function below.

moving enemy character
function to control enemy movement

We next need to update our code in main.lua
We need to use the function love.update()

  • This function updates at the start of each frame.
  • Put everything which needs to update or run with each frame here.

Inside this function we call the CHARACTER:move() function on the enemy object.
You can see our new function in the code below.

love.update()
love.update()

Improving our code further

To further improve our code we can employ encapsulation.
We can create an enemy class. The player character has no need for the move function nor move_r variable
So we create a class for the enemy object and attach that function and variable to it.
We have to modify our Characters.lua file to add the enemy class, constructor function, and a slight change to the move function.
We also need to make sure to set the metatable and index of the enemy class so that it is a subclass of the character class.
The code we added is below.

enemy class
Added enemy class

After adding our enemy class we need to make one slight change to our main.lua
just change the type of object for enemy in our love.load function.

making the enemy object
making enemy object

Final

We should now have a program which does the same thing as before, but now it is much more organize.
More importantly for our needs it can much more easily be expand and added to.
Using our class system we can now easily add many new objects and add or remove functions and variables to them.
as always, complete code can be found on github.

Thank you for sticking around for my part 2. Continue on to part 3

Wednesday, August 26, 2020

Simple Platformer - Part 1

Getting started with Love2d - part 1

Introduction

This is the first part of my atempt to learn Love2d by creating a small, simple platformer.

For this part, i set up a simple program which displays a player and enemies.
The player is then given the ability to move around.

Displaying characters to screen.

The first step to this program is creating and displaying the player character and enemies.

First thing is that i need to draw a character for the player and a character for the enemies.
I opened up GIMP and drew the characters.

For the player, i drew a simple stick man.

player
Player character

For the enemies, i drew a simple goomba looking dude.

enemy
Enemy character

To load the images, the Love2d code needed is love.graphics.newImage("path/to/image")
this loads image and allows you to save it to a variable.

To display the image, code needed is love.draw()
and also love.graphics.draw(icon,x,y,r,sx,sy,ox,oy)

love.load()

  • callback function which loads things at the very start of the game.

love.draw()

  • call back function whcih draws to screen every frame.

love.graphics.draw(icon,x,y)

  • function which draws a given image to screen.
  • Arguments to function are:
    • icon
      • image to draw to screen.
      • image previously loaded with love.graphics.newImage
    • x
      • x postion of image
    • y
      • y image of image

combining all of these together into code, it should look a bit like this.

code to draw characters to screen
code which draws player and enemy to scren

giving us an output which looks like this:

two characters drawn to screen
player and enemy together on screen

Adding movement

Now that we can display the player onto the screen, we need to move him about.
To accomplish this, we will need to add a few things to our code.

The things needed are a variable for player x, a variable for player y.
We also need the function love.keypressed()

  • PLAYER_X and PLAYER_Y holds the location of player's x and y co-ordinates.
  • love.keypresed() function which handles keyboard input

We start by creating the global variables for player position. We next need to change the code in love.draw() to use these variables.

updated load and draw functions
updated load and draw functions.

the last thing needed is to set up the love.keypressed() function
We used the standard 'wasd' for movement.
We update the global variable for player x and player y when the corresponding key is pressed.

keypress function should look like:

keypress function
player can now move around

We next need to set boundary for the player. We don't want the player to wander off screen.
To accomplish this, we set up two global variables: HEIGHT and WIDTH
HEIGHT controls where the bottom of the screen is, and WIDTH controls where the right hand edge of screen is.
All we have to do is add an if statement to each of the movement keys checking if player is out of bounds.
The completed code should look like this:

final code
player can move around but can't go out of bounds.

full code can be found on github

Conclusion

We should now have a simple program which draws characters to the screen and allows the player to move around, but not to move out of bounds.We now know how to draw characters to screen, take in keyboard input, and use this keyboard input to update to change things in game.

Continue to part 2 of this walk through..

Simple Platformer - Introduction

Getting started with Love2d

Introduction

This is my journey to learn Love2d by making a very simplistic and basic platformer style game.
I'll document and talk about the parts of the game and my design decisions along the way.
This will mostly be for my benefit, but i hope that others can learn or gain something from it as well.

Why this stuff in particular?

Why did i choose to use lua and love2d for game dev?

Why lua?

  • I am fairly familiar with lua at this point.
  • I generally like working with lua. Liking the language is important when working on a decent sized project
  • I find the syntax of lua fairly easy to read. in general i like the syntax of lua.
  • There is a pretty well developed game dev ecosystem for the language.
    • Love2d is made for using lua. Since it is the framework i am using, it makes sense to use the language for it.

Why Love2d?

so why did i choose Love2d when there are other options?

  • I already have a tiny bit of knowledge and experience with Love2d.
    • Not much knowledge and experience though. Just what could be considered a hello world program for it.
  • It is a simple and easy to use framework.
    • Does what i need it to, and not much more.
    • It seems pretty straightforward. Nothing that even i couldn't understand.
  • Simple 2d games seem to be what it is intended for, and since that is what i'm making it seems the best tool to use.

Why a platformer

So why did i choose to make a platformer rather than a different genre of game.

  • It needed to be a 2d game
  • It needs to be more than a simple game that can be made in 200 lines of code or fewer.
    • If it is too simple of a game, I wont learn much or have much fun making it.
    • If it is too complicated, I will get burned out and not have fun making it.
  • The object isn't to make the funnest or most mind blowing game ever.
    • It needs to be something which I can handle. I'm no expert game dev nor expert programmer
    • It primarily serves as a learning opportunity for me.

So with all those criteria for the game, i decided that a platformer is the one which best fits my needs.It will not be the most advanced game ever made.
Nor will it be particular fun game to play, nor any revolutionary or breakthrough mechanics.
I cant even claim it will be programmed well or efficiently.
But i can say that it will definitely teach me a thing or two about game dev, programming, and using love2d.

Conclusion

Thank you for checking out my series on game dev. Please check back for the following articles where i will start developing the game.

you can view part 1 here

You can also view my quick start guide to using lua here