I'm pretty new to OOP but I understand the basic concepts. I'm just wondering if I'm using objects in an optimal manner in terms of making my code modular and easy to modify or add to. If anyone could take a look through it and give me a few pointers it would be appreciated.
Also, increasing the speed at which my player moves only seems to have an effect in specific increments (i.e. increasing Player.speed from 1 to 100 has no effect, but as soon as you increase it from 100 to 101, the player moves noticeably faster). I essentially copy-pasted it from an earlier version of this .love which wasn't using middleclass and it worked fine without it. Player.speed is set to 50 by default in the .love that is attached, and pressing left shift makes the player sprint, increasing movement speed by twenty percent, but not having any actual effect on movement.
Thanks for any help.
Need some help with OOP and clean coding
Forum rules
Before you make a thread asking for help, read this.
Before you make a thread asking for help, read this.
Need some help with OOP and clean coding
- Attachments
-
- New.love
- (425.97 KiB) Downloaded 104 times
- kikito
- Inner party member
- Posts: 3153
- Joined: Sat Oct 03, 2009 5:22 pm
- Location: Madrid, Spain
- Contact:
Re: Need some help with OOP and clean coding
Hi there!
That's because good code is about tradeoffs. A simple example: you have a version of a function that does a simple thing (say, move the player around) in a very simple way. Then you have another option which is very flexible, but adds lots of complexity to the code. Which one is better?
Well, it depends. If you need a lot of flexibility in your code, then the flexible solution is better. But if you don't, then it's overkill.
Now, the conclusion would be: "get the requirements right, and you can get optimal code".
... well, actually, no.
That misses one important characteristic of requirements. They change all the time. No matter how "set in stone" they are, reality always seems to find a way to need them changed.
This actually changes priorities. With that characteristic in mind, the important thing is not finding "the optimal code to satisfy the requirements". It's far more important to make code that is able to adapt to changing circumstances without a lot of pain. That is what clean code is about.
One of the most obvious ways to do that is to divide stuff up in smaller parts. Big classes and functions are more difficult to move around, change and reuse than small ones. When I say "big" I don't only mean "with lots of lines of code", I also mean "doing too many different things". Splitting them up into several parts is usually a good idea.
I say it is a good idea not because the resulting code will be simpler (it will not) but because it will be more adaptable to changes in requirements.
One particular example I see is the player class. It handles too many things: animations, keypresses, health. I see lots of trouble there when you want to change some things:
Right after Player is defined as a class, it's redefined as a common Lua table
Well, that's a bit of engineering's dirty secret. There is no such thing as Optimal Code. At least not in absolute terms. It is very rare that a piece of code is just "better" than another piece of code. It is usually better "according to certain criteria".I'm just wondering if I'm using objects in an optimal
That's because good code is about tradeoffs. A simple example: you have a version of a function that does a simple thing (say, move the player around) in a very simple way. Then you have another option which is very flexible, but adds lots of complexity to the code. Which one is better?
Well, it depends. If you need a lot of flexibility in your code, then the flexible solution is better. But if you don't, then it's overkill.
Now, the conclusion would be: "get the requirements right, and you can get optimal code".
... well, actually, no.
That misses one important characteristic of requirements. They change all the time. No matter how "set in stone" they are, reality always seems to find a way to need them changed.
This actually changes priorities. With that characteristic in mind, the important thing is not finding "the optimal code to satisfy the requirements". It's far more important to make code that is able to adapt to changing circumstances without a lot of pain. That is what clean code is about.
One of the most obvious ways to do that is to divide stuff up in smaller parts. Big classes and functions are more difficult to move around, change and reuse than small ones. When I say "big" I don't only mean "with lots of lines of code", I also mean "doing too many different things". Splitting them up into several parts is usually a good idea.
I say it is a good idea not because the resulting code will be simpler (it will not) but because it will be more adaptable to changes in requirements.
One particular example I see is the player class. It handles too many things: animations, keypresses, health. I see lots of trouble there when you want to change some things:
- What happens when players demmand to be able to customize the key settings?
- What happens when the player wants to use a joypad to move the player around
- What if later on you decide that you want to use the mouse instead?
- What if you need to create the player animations dynamically (say, show a helmet he's wearing)?
I suspect that your problems come from the fact that Player isn't really a middleclass class. I see this code:I essentially copy-pasted it from an earlier version of this .love which wasn't using middleclass and it worked fine without it.
Code: Select all
Player = class('Player', Entity)
Player = {
self = "",
map = test,
x = 0,
y = 0,
pic = love.graphics.newImage("assets/game/player.png"),
speed = 100,
currentHealth = 10,
maxHealth = 10,
currentMana = 10,
maxMana = 10,
currentStamina = 10,
maxStamina = 10,
facing = "down",
width = 64,
height = 64,
}
When I write def I mean function.
Re: Need some help with OOP and clean coding
Your sprint dosent work because of floor()
your movment is 1
btw here is a tips for draw range:
your movment is 1
btw here is a tips for draw range:
Code: Select all
Map:autoDrawRange(-(Player.x-(love.graphics.getWidth( )/2)), -(Player.y-(love.graphics.getHeight( )/2)), 1, -50)
Re: Need some help with OOP and clean coding
Hello! I'd like to ask something somewhat related to SudoCode's original questions. This has been bugging me for sometime now, and I can't seem to find a clear answer so far.
The “if-then” statement attempts to compare both values of self.x and self.xMax, however, lua will state that boths variables are nil inside the player:update function block, failing to execute the comparision.
Of course, if I change the code to this:
The if statement evaluation will be successful. So, what's going on here? Is this a variable scope issue?
Suppose I have the following piece of code:I suspect that your problems come from the fact that Player isn't really a middleclass class
Code: Select all
player = class:new()
function player:init()
self.x = 0
self.xMax = 0
...
end
...
function player:update(dt)
if self.x >= 0 and self.x < self.xMax then
player:moveRight(dt)
end
end
Of course, if I change the code to this:
Code: Select all
player = class:new()
function player:init()
player.x = 0
player.xMax = 0
...
end
...
function player:update(dt)
if player.x >= 0 and player.x < player.xMax then
player:moveRight(dt)
end
end
- bartbes
- Sex machine
- Posts: 4946
- Joined: Fri Aug 29, 2008 10:35 am
- Location: The Netherlands
- Contact:
Re: Need some help with OOP and clean coding
Middleclass' initializer isn't called 'init', it's called 'initialize'.
- kikito
- Inner party member
- Posts: 3153
- Joined: Sat Oct 03, 2009 5:22 pm
- Location: Madrid, Spain
- Contact:
Re: Need some help with OOP and clean coding
No, you are mistaking the player class with the player instance.
The bit that you are missing is that, somewhere else, there have to be these other two lines:
and
A class is a definition. It says how one or more "things" act. Once you have a class, you can use it to create things. These things you create are called instances. That's what the "new" and initialize methods are for.
You can have more than one instance of the same class. I usually name instances in lowercase, and classes in uppercase, to make the distinction more obvious:
Instances use the methods defined by a class as if they were their own. In other words, if the Player class has a method called think, when you do player:think() - notice the lowercase - then "self" will be the player instance, not the player class.
I hope this clarifies it. If you have more questions, I suggest opening a different thread, otherwise it'll be too much off-topic.
The bit that you are missing is that, somewhere else, there have to be these other two lines:
Code: Select all
-- usually inside love.load
p = player:new()
Code: Select all
-- usually inside love.update
p = player:update(dt)
You can have more than one instance of the same class. I usually name instances in lowercase, and classes in uppercase, to make the distinction more obvious:
Code: Select all
-- class definition
Player = class('Player') -- notice the uppercase
function Player:initialize()
...
end
...
-- class instantiation (cration of an instance)
player = Player:new(...)
I hope this clarifies it. If you have more questions, I suggest opening a different thread, otherwise it'll be too much off-topic.
When I write def I mean function.
Re: Need some help with OOP and clean coding
The problem with removing math.ceil and math.floor from the movement is now tiles have rough edges when you move.Zeliarden wrote:Your sprint dosent work because of floor()
your movment is 1
btw here is a tips for draw range:Code: Select all
Map:autoDrawRange(-(Player.x-(love.graphics.getWidth( )/2)), -(Player.y-(love.graphics.getHeight( )/2)), 1, -50)
- Attachments
-
- New.love
- (425.87 KiB) Downloaded 68 times
Who is online
Users browsing this forum: Ahrefs [Bot] and 58 guests