Creating Interactive Coin Objects using OOP

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:

3 Likes