In the past week I’ve started learning how to add Object Oriented Programming (OOP) into my workflow. I thought I would spend some time tonight experimenting with it and by making coins for players to collect. Originally I was going to post this in #help-and-feedback:code-review but I wasn’t looking for any specific feedback.
All code is stored in ModuleScripts which has a simple bootstrapper running the init() function in both.
Coin Class Code
local CollectionService = game:GetService("CollectionService")
local Players = game:GetService("Players")
local TweenService = game:GetService("TweenService")
local leaderstats = require(game:GetService("ServerScriptService").Modules.Leaderstats)
local coinClass = {}
coinClass.__index = coinClass
coinClass.TAG_NAME = "Coin"
coinClass.COIN_VALUE = 5
coinClass.WAIT_TIME = 5
coinClass.CFRAME_OFFSET = CFrame.new(0,1,0)
coinClass.TWEEN_INFO_ANIMATION = TweenInfo.new(
1,
Enum.EasingStyle.Sine,
Enum.EasingDirection.InOut,
-1,
true,
0
)
coinClass.TWEEN_INFO_PICKUP = TweenInfo.new(
0.3,
Enum.EasingStyle.Sine,
Enum.EasingDirection.InOut,
0,
false,
0
)
coinClass.CoinObjects = {}
function coinClass.init()
for _,taggedInstance in ipairs(CollectionService:GetTagged(coinClass.TAG_NAME)) do
coinClass.new(taggedInstance)
end
CollectionService:GetInstanceAddedSignal(coinClass.TAG_NAME):Connect(coinClass.new)
end
function coinClass.new(coin)
local newCoin = setmetatable({},coinClass)
newCoin.coinObject = coin
newCoin.debounce = false
newCoin.defualtSize = coin.Size
newCoin.touchTrigger = coin.Touched:Connect(function(...)
newCoin:OnTouch(...)
end)
local tweenGoal = coin.CFrame:ToWorldSpace(coinClass.CFRAME_OFFSET) * CFrame.Angles(0,math.pi,0)
newCoin.animationTween = TweenService:Create(coin,coinClass.TWEEN_INFO_ANIMATION,{CFrame = tweenGoal})
newCoin.animationTween:Play()
newCoin.pickupAnimation = TweenService:Create(coin,coinClass.TWEEN_INFO_PICKUP,{Size = Vector3.new(0,0,0)})
newCoin.respawnAnimation = TweenService:Create(coin,coinClass.TWEEN_INFO_PICKUP,{Size = newCoin.defualtSize})
table.insert(coinClass.CoinObjects,newCoin)
return newCoin
end
function coinClass:OnTouch(collisionInstance)
if self.debounce then return end
local player = Players:GetPlayerFromCharacter(collisionInstance.Parent)
if player then
self.debounce = true
self.coinObject.PickupSound:Play()
self.pickupAnimation:Play()
leaderstats.rewardCoins(player,coinClass.COIN_VALUE)
wait(coinClass.WAIT_TIME)
self.respawnAnimation:Play()
self.debounce = false
end
end
return coinClass
Leaderstats Management
local Players = game:GetService("Players")
local playerScore = {}
function playerScore.init()
for _,player in ipairs(Players:GetPlayers()) do
playerScore.playerAdded(player)
end
Players.PlayerAdded:Connect(playerScore.playerAdded)
end
function playerScore.playerAdded(player)
local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
leaderstats.Parent = player
local coinCount = Instance.new("IntValue")
coinCount.Name = "Coins"
coinCount.Parent = leaderstats
end
function playerScore.rewardCoins(player,increment)
local currentCoinCount = player.leaderstats.Coins
currentCoinCount.Value += increment
end
return playerScore
Final Result: