## I god a bold question, can somebody enhance my code and/or give me hints to code better?

General discussion about LÖVE, Lua, game development, puns, and unicorns.
weitnow
Prole
Posts: 18
Joined: Mon Oct 31, 2016 4:49 pm

### I god a bold question, can somebody enhance my code and/or give me hints to code better?

Hello together

My name is christian. I am swiss, so forgive me my bad englisch. I got a bold question. Since I am a kid, it was my dream to code a own game. I have no education in computer-science/programming. I just started to teach myself python some months ago, then changed to java/libgdx. It became to difficult and i abandoned my project. Then i found lua and love....an i started coding my first game. Its now in very early alpha stage...As a beginner I choose a simple super-mario like platformer. I tried to code as much as possible by myself, without following a tutorial. Now i got the feeling, that my code is very very messy....and there are probably plenty ways to do it better...but without advice, its difficult to improve. So I wonder, if somebody could look through my code and give my any hints how i could to it better. I will attach my small prototype (game.love). If you jump on the enemy, the enemy gets killed and the screen will shake (buggy). If the enemy runs into you, you get killed and game over.

here is a link to a short Video of the game: https://drive.google.com/file/d/0B9MAaF ... Vna3c/view

main.lua

Code: Select all

require ("assets.ProtoPlattform")
require ("assets.ProtoPlayer")
require ("assets.Visualeffects")
require ("assets.Killenemy")
gameover = false
test = 0
shakeron = false

player_contact_enemy = function (self, dt, enemies)
local contact = false
for k, v in pairs(enemies) do
if self.x2 > v.x and self.x < v.x2 and self.y2 > v.y and self.y < v.y2 then
contact = true
end
end
return contact
end

draw_gameover_screen = function()
love.graphics.setColor(255,0,0)
love.graphics.rectangle('fill', 0, 0, love.graphics.getWidth(), love.graphics.getHeight())
love.graphics.setColor(0,0,0)
love.graphics.print('game over!', love.graphics.getWidth()/2 -150, love.graphics.getHeight()/2, 0, 4, 4)
end

player = ProtoPlayer.new(love.graphics.getWidth() / 2, love.graphics.getHeight()-160)
player.setcolor('green')

enemy = ProtoPlayer.new(love.graphics.getWidth() / 2, 20)
enemy.setcolor('red')
enemy.speed = 80

enemy2 = ProtoPlayer.new(50, 20)
enemy2.setcolor('red')
enemy2.speed = 50

enemy3 = ProtoPlayer.new(love.graphics.getWidth() -100, 20)
enemy3.setcolor('red')
enemy3.speed = 100

enemies = {enemy, enemy2, enemy3}
plattforms = {
ProtoPlattform.new(300, 500, 500, 20, 'plat1'),
ProtoPlattform.new(0, 370, 200, 20, 'plat2'),
ProtoPlattform.new(400, 280, 200, 20, 'plat3'),
ProtoPlattform.new(50, 200, 200, 20, 'plat4'),
ProtoPlattform.new(500, 100, 200, 20, 'plat5')
}
end

function love.update(dt)

if (shakeron) then
shake(dt)

end

player:move(dt)
player:physic(dt, plattforms)

for _k, e in pairs(enemies) do
e:physic(dt, plattforms)
e:ai(dt, player, plattforms) end

checkifkill(player, enemies, dt)
if (player_contact_enemy(player, dt, enemies)) then gameover = true end

end

function love.draw()

for k, v in pairs(plattforms) do
v:draw()
end

for k, v in pairs(enemies) do
v:draw()
end
player:draw()

if gameover then draw_gameover_screen() end

end

ProtoPlayer.lua

Code: Select all

ProtoPlayer = {}

ProtoPlayer.new = function(x, y)
local self = {}
self.name = 'noname'
self.x = x
self.y = y
self.width = 50
self.height = 50
self.x2 = self.x + self.width
self.y2 = self.y + self.height
self.speed = 200
self.y_velocity = 0
self.jump_height = -400
self.gravity = -500
self.color = {255, 0, 0}
self.direction = 1
self.hightesplat = love.graphics.getHeight() + 150
self.hightesplat_height = 0

self.draw = function ()
love.graphics.setColor(unpack(self.color))
love.graphics.rectangle('fill', self.x, self.y, self.width, self.height)
love.graphics.setColor({0,0,0})
love.graphics.print( 'x: ' .. round(self.x,0), self.x, self.y)
love.graphics.print( 'x2 ' .. round(self.x2,0), self.x, self.y +10)
end

self.setcolor = function (color)
if color == 'blue' then
self.color = {0, 0, 255}
elseif color == 'red' then
self.color = {255, 0, 0}
else self.color = {0, 255, 0} end
end

self.move = function (self, dt)
if love.keyboard.isDown('d') then
if self.x < (love.graphics.getWidth() - 50) then
self.x = self.x + (self.speed * dt)
end
elseif love.keyboard.isDown('a') then
if self.x > 0 then
self.x = self.x - (self.speed * dt)
end
end

if love.keyboard.isDown('space') then
if self.y_velocity == 0 then
self.y_velocity = self.jump_height
end
end
end

self.physic = function (self, dt, plattforms)

if self.y2 > love.graphics.getHeight() then gameover = true end -- if player falls below the screen = gameover

self.x2 = self.x + self.width -- update self.x2
self.y2 = self.y + self.height -- update self.y2

self.y = self.y + self.y_velocity * dt
self.y_velocity = self.y_velocity - self.gravity * dt
self.highestplat = love.graphics.getHeight() + 150
for _k, plat in pairs(plattforms) do
if self.x2 > plat.x and self.x < plat.x2 then
if self.y + self.height <= plat.y + plat.height then
if plat.y < self.highestplat then self.highestplat, self.highestplat_height = plat.y, plat.height end
end
end
end
if self.y + self.height >= self.highestplat then
self.y_velocity = 0
self.y = self.highestplat - self.height
end
end

local emptyplatform = ProtoPlattform.new(0,0,0,0, 'no ground') -- create empty platform object for return with self.contact if there is no valid real platform
self.contact = function (self, dt, plattforms)
local platobject
for k, v in pairs(plattforms) do
if self.x2 > v.x and self.x < v.x2 and self.y <= v.ground then
platobject = v
end
end
if platobject == nil then platobject = emptyplatform  end
return platobject
end

self.switchdirection = function(self)
if self.direction == 1 then self.direction = -1
else self.direction = 1 end
end

self.ai = function (self, dt, player, plattforms)
local platobject = self:contact(dt, plattforms)

if self.x < platobject.x or self.x2 > platobject.x2 then
self:switchdirection()
end
-- walking
self.x = self.x + self.direction * (self.speed * dt)

end

return self
end

ProtoPlatform.lua

Code: Select all

ProtoPlattform = {}

ProtoPlattform.new = function(x, y, width, height, name)
local self = {}
self.name = name
self.width = width
self.height = height
self.x = x
self.y = y
self.x2 = x + width
self.y2 = y + height
self.ground = self.y
self.draw = function()
love.graphics.setColor(0, 255, 180)
love.graphics.rectangle('fill', self.x, self.y, self.width, self.height)
--debug points
--x/y
love.graphics.setColor(0, 0, 255)
love.graphics.rectangle('fill', self.x, self.y, 2, 2)
--x2/y2
love.graphics.setColor(255, 0, 0)
love.graphics.rectangle('fill', self.x2, self.y2, 2, 2)
--ground
love.graphics.setColor(0, 255, 255)
love.graphics.rectangle('fill', self.x + width/2, self.ground - 1, 2, 2)
-- x/y numbers
love.graphics.setColor(0, 0, 0)
love.graphics.print( 'x: ' .. round(self.x,0) .. ' x2: ' .. round(self.x2,0), self.x, self.y)
-- print plat name
love.graphics.setColor(0, 0, 0)
love.graphics.print(self.name, self.x + 100, self.y)

end

function round(num, numDecimalPlaces)
local mult = 10^(numDecimalPlaces or 0)
return math.floor(num * mult + 0.5) / mult
end

return self

end

KillEnemy.lua

Code: Select all

function checkifkill(player, enemies, dt)
for index, enemy in pairs(enemies) do
if player.x2 > enemy.x + 15 and player.x < enemy.x2 - 15 and player.y2 > enemy.y - 40 and player.y < enemy.y2 - 40 then
table.remove(enemies,index)
shakeron = true
end
end

end

Visualeffects.lua

Code: Select all

local counter = 1
local shaketime = 100

function shake(dt)
for _k, plat in pairs(plattforms) do
if counter > 5 then
plat.x = plat.x - (200 * dt)
plat.x2 = plat.x2 - (200 * dt)
else
plat.x = plat.x + (200 * dt)
plat.x2 = plat.x2 + (200 * dt)
end
end
counter = counter + 1
shaketime = shaketime - 1
if counter == 10 then counter = 1 end
if shaketime < 1 then shakeron = false shaketime = 100 end
end


Attachments
game.love

CaptainMaelstrom
Party member
Posts: 157
Joined: Sat Jan 05, 2013 10:38 pm

### Re: I god a bold question, can somebody enhance my code and/or give me hints to code better?

You're on the right track by starting small with the scope of your game. The reason why I can't enhance your code is because I don't know what you want it to do better.

Do you want it to be less buggy? Then pick 1 bug at a time and fix it. If you don't know how, you can google the bug or maybe post a topic in the help subforums about what specifically is wrong.

Do you want to add a feature? Define what it is you want to add and try to implement it. If it causes bugs, see step 1.

If it's your dream to program your own video game, you will have to get really good at steps 1 and 2.

ivan
Party member
Posts: 1546
Joined: Fri Mar 07, 2008 1:39 pm
Contact:

### Re: I god a bold question, can somebody enhance my code and/or give me hints to code better?

Hello and welcome to the Love2d forums.
Learning any programming language takes time so don't get discouraged by criticism.
Ok, so briefly going over the code, I have to say that it needs more work.
First of all you want to get rid of the globals - they make it harder to tell what's going on since they can be called from anywhere.
Ideally you want to be able to look any Lua file and understand the script without referring to external files.
Your object-orientation code could be much cleaner if you learned to use metatables.
Level data such as the following should be separated from the rest of the code:

Code: Select all

        ProtoPlattform.new(300, 500, 500, 20, 'plat1'),
ProtoPlattform.new(0, 370, 200, 20, 'plat2'),
ProtoPlattform.new(400, 280, 200, 20, 'plat3'),
ProtoPlattform.new(50, 200, 200, 20, 'plat4'),
ProtoPlattform.new(500, 100, 200, 20, 'plat5')
You need to study how tables, work: generally we use table.remove for lists and pairs for indexed tables.
But we never use both like the following example:

Code: Select all

for index, enemy in pairs(enemies) do
...
table.remove(enemies,index)
In this case, you probably need reverse iteration: for index = #enemies, 1, -1 do

These are just a few things off the top of my head.
It's not a big deal as long as your project is small, but if you want to make something bigger then these suggestions might be helpful.
Good luck!

weitnow
Prole
Posts: 18
Joined: Mon Oct 31, 2016 4:49 pm

### Re: I god a bold question, can somebody enhance my code and/or give me hints to code better?

Hello CaptainMaeistrom, hello ivan

Thank you both for your response

@CaptainMaeistrom:
Hm, i guess i am looking for general advice. I try to split up my code in diffrent lua-files. If the project grows, that is still manageble. But to be honest, i have no Idea, how to split up the code in the best way. ivan gave some good and general advice. I hope to get more of them.

@ivan:
Thank you. I will try to change the code according what you told me. What I still do not really understand, how to split up the code. For example, should i make a Levelfile with the data like:

Code: Select all

ProtoPlattform.new(300, 500, 500, 20, 'plat1'),
ProtoPlattform.new(0, 370, 200, 20, 'plat2'),
ProtoPlattform.new(400, 280, 200, 20, 'plat3'),
ProtoPlattform.new(50, 200, 200, 20, 'plat4'),
ProtoPlattform.new(500, 100, 200, 20, 'plat5')
and then a file with data like the enemies in form of a table? If so, how would I for example delete an enemy from a table in enemy.lua without using global variables if the code for killing an enemy is in annother lua-file.

ivan
Party member
Posts: 1546
Joined: Fri Mar 07, 2008 1:39 pm
Contact:

### Re: I god a bold question, can somebody enhance my code and/or give me hints to code better?

Typically, you want to have some sort of level format, so that your level data is not dependent on your game's API.
Level data should be just that: data and you should hopefully be able to easily edit each level (either through an editor or the file format should be human-readable).
The idea is to read that data and initialize the level based on that - ideally separating data from code.

As for reducing the use of globals you can use the following technique:
enemy.lua (encapsulation):

Code: Select all

local enemyManager = {}
...
return enemyManager
game.lua (nesting):

Code: Select all

local game = {}
game.enemies = require('enemy')
return game
main.lua (example):

Code: Select all

myGame = require('game')
myGame.enemies:doStuff()
Note that you only need to require each of these files only once -
WHERE you require each file determines the scope or what is accessible.

weitnow
Prole
Posts: 18
Joined: Mon Oct 31, 2016 4:49 pm

### Re: I god a bold question, can somebody enhance my code and/or give me hints to code better?

Thank you ivan...I apreciate the time you took to help me. I have the feeling, I start understandig how I should do it. I will try your concept and will post my updated code. Have a great day

weitnow
Prole
Posts: 18
Joined: Mon Oct 31, 2016 4:49 pm

### Re: I god a bold question, can somebody enhance my code and/or give me hints to code better?

hello together

I found a good tutorial for my problem. I realized, that my previous code was somehow badly organized. The main problem was, that when the project grows, the code will become messy. I found a good tutorial: https://www.youtube.com/channel/UCSs-Hz ... RQCdHuAxAg
There is a video about how to build an entity-system. I am trying now to recode my simple game and using this approach, which should make my game more future-proof when more enemies, more platforms etc will be added.

### Who is online

Users browsing this forum: Google [Bot] and 2 guests