Catégories
Jeu vidéo ROBLOX

Création d’une boutique

Améliore ton jeu par des dispositifs comme par exemple une boutique.


Créer une boutique

Dans beaucoup de jeux, les joueurs peuvent acheter des objets, des vêtements, des pouvoirs ou des accessoires. La boutique sert donc à donner plus d’objectifs au joueur : gagner de l’argent dans le jeu, choisir quoi acheter et améliorer son personnage. Une boutique rend aussi le jeu plus vivant et plus intéressant.

Dans Roblox Studio, on peut construire des décors, placer des objets et ajouter des menus à l’écran. Avec le langage de programmation Lua, nous apprendrons à donner des actions aux objets et à créer les règles du jeu.

La démarche pour la construction de ta boutique sera progressive :

  • D’abord, nous apprendrons à créer l’interface de la boutique : une fenêtre avec des boutons et les noms des objets à vendre.
  • Ensuite, nous programmerons l’argent du joueur avec une variable. Puis, nous coderons les achats : lorsqu’un joueur clique sur un bouton, le programme vérifie s’il a assez d’argent. Si oui, il paie et reçoit l’objet. Sinon, un message lui indique qu’il lui manque des pièces.

Ce projet te permettra de découvrir plusieurs notions importantes en programmation : les variables, les conditions, les événements, les fonctions et l’organisation d’un vrai projet numérique. À la fin, tu disposeras d’une boutique fonctionnelle dans Roblox.

Création de la boutique :

Pout ta boutique crée :

  • une fenêtre sur ta boutique avec les options à acheter
  • un bouton pour ouvrir et fermer la fenêtre de ta boutique
  • un localscript pour gérer l’ouverture de ta boutique

Création d’un écran utilisateur pour représenter la boutique, sous StaterGui demande la création d’un ScreenGui

Sous ScreenGui crée un Frame :

Déplace et agrandit le Frame pour prendre la place de ta boutique :

Modifie les propriétés, la couleur, le contour, la transparence du Frame :

Renomme les objets de ta botique :

Sous FrameStore rajoute un TextLabel pour le titre de ta boutique :

Dans le TextLabel rajoute le titre de la boutique :

Maintenant, tu vas rajouter des boutons pour chaque Item de ta boutique :

Tu dois obtenir ce résultat :

Tu peux rajouter une image pour certain élément de ta boutique :

Recherche une image dans la boîte à outil :

Récupère l’identifiant de l’image par un clic droit sur l’image :

Copie l’identifiant dans la propriété Image de ton ImageLabel :

Sous ScreenStore crée un ImageButton qui te permettra d’ouvrir ou fermer ta boutique :

Recherche dans la boîte à outil une image pour représenter ta boutique :

Par le clic droit demande à copier l’identifiant de l’image que tu colle dans la propriété Image de ton ImageButton :

Sous ScreenStore demande la création d’un LocalScript :

Renomme ton LocalScript et tu dois obtenir ce résultat :

Maintenant, tu peux modifier le script pour ouvrir ou fermer la boutique :

-- récupération du bouton pour ouvrir la boutique
local openButton = script.Parent.OpenButton
-- récupération du frame de la boutique	
local frameStore = script.Parent.FrameStore

-- on cache le frame de la boutique au lancement du jeu par defaut	
frameStore.Visible = false

-- on écoute l'événement de clic sur le bouton pour ouvrir ou fermer la boutique
openButton.MouseButton1Click:Connect(function()
	frameStore.Visible = not frameStore.Visible
end)

Crée un tableau de points

Objectif : Créé un tableau de scores de Points

Créer un script pour afficher un tableau de score au joueur sous ServerScriptService :

Renommer le script leaderstats :

Saisir le code suivant pour un affichage d’une barre de scores de Points :

-- récupérer le service sur les joueurs
local players = game:GetService("Players")

-- écouteur d'un nouveau joueur
players.PlayerAdded:Connect(function(player)
	-- créer un dossier leaderstats
	local leaderstats = Instance.new("Folder")
	leaderstats.Name = "leaderstats"
	leaderstats.Parent = player
end)

Si tu lances ton jeu une barre s’affiche :

Si le score ne s’affiche pas vérifie :

Rajoute à ton script un score à afficher :

-- récupérer le service sur les joueurs
local players = game:GetService("Players")

-- écouteur d'un nouveau joueur
players.PlayerAdded:Connect(function(player)
	-- créer un dossier leaderstats
	local leaderstats = Instance.new("Folder")
	leaderstats.Name = "leaderstats"
	leaderstats.Parent = player
	-- créer un score de Points
	local score = Instance.new("IntValue")
	score.Parent = leaderstats
	score.Name = "Points"
	score.Value = 10
end)

Le score s’affiche si tu lances ton jeu :


GAGNER DES POINTS

Créer un Part avec un ClickDetector afin que le joueur puisse gagner des points, exemple à reproduire sur tous les objets que tu souhaites dans ton jeu :

Exemple d’un script pour augmenter le score si le joueur click sur un ClickDetector :

Sasie le code suivant- dans le script :

-- récupérer le ClickDetector du Part
local clickDetector = script.Parent.ClickDetector

-- écouter l'événement de clic du Clickdetector
clickDetector.MouseClick:Connect(function(player)
	-- ajouter 10 Points au joueur
	player:WaitForChild("leaderstats").Points.Value += 10

end)

Lance ton jeu, maintenant à chaque clic le score de points augmente de 10 :


Acheter

Sur l’écran de sa boutique, le joueur clic sur l’item de son achat. Le LocalScript de la boutique demande via une RemoteFunction la possibilité de l’achat de l’item. Un script sur le serveur vérifie le nombre de point et la disponibilité de l’item.

Mis en place de l’échange entre le Localscript de la boutique et le serveur par un RemoteFunction :

Renomme RemoteFunction par RemoteBuy :

Puis modifie le script StoreScript lié à ta boutique :

-- récupération du bouton pour ouvrir la boutique
local openButton = script.Parent.OpenButton
-- récupération du frame de la boutique	
local frameStore = script.Parent.FrameStore

-- on cache le frame de la boutique au lancement du jeu par defaut	
frameStore.Visible = false

-- on écoute l'événement de clic sur le bouton pour ouvrir ou fermer la boutique
openButton.MouseButton1Click:Connect(function()
	frameStore.Visible = not frameStore.Visible
end)

-- on récupère le bouton de la lampe dans la boutique
local lampButton = script.Parent.FrameStore.LampButton
-- on récupère le RemoteEvent pour acheter la lampe
local remoteBuy = game:GetService("ReplicatedStorage"):WaitForChild("RemoteBuy")
-- on écoute le clic sur le bouton de la lampe pour l'acheter
lampButton.MouseButton1Click:Connect(function(itemName)
	-- on envoie une requête au serveur pour acheter la lampe
	local success, message = remoteBuy:InvokeServer("lamp")
	-- on affiche le message de retour du serveur 
	print(success, message)	
end)

Puis demande à créer un Script sur le serveur sous ServerScriptService afin de valider l’achat :

Renomme ton Script en storeScript:

Ecris ce code dans le script storeScript :

-- récupérer le RemoteFunction RemoteBuy
local remoteBuy = game:GetService("ReplicatedStorage"):WaitForChild("RemoteBuy")

-- écouter l'événement de requête d'achat du joueur
remoteBuy.OnServerInvoke = function(player, value)
	-- vérifier si le joueur a assez de points pour acheter l'objet
	local points = player:WaitForChild("leaderstats").Points.Value
	
	return true, " Achat confirmé !"
end

Lance ton jeu pour vérifier le bon fonctionnement de l’achat, tu trouveras le message de l’acquittement de l’achat dans la console.

Modifie le script storeScript pour vérifier si le joueur dispose d’assez de points pour l’achat et la disponibilité du stock :

-- récupérer le RemoteFunction RemoteBuy
local remoteBuy = game:GetService("ReplicatedStorage"):WaitForChild("RemoteBuy")

local ITEMS = {
	["lamp"] = { price = 5, stock = 2 },
	["run"] = { price = 10, stock = 1 },
	["visible"] = { price = 15, stock = 1 }
}

-- écouter l'événement de requête d'achat du joueur
remoteBuy.OnServerInvoke = function(player, value)
	-- vérifier si le joueur a assez de points pour acheter l'objet
	
	local item = ITEMS[value]

	-- Vérification stock
	if not item or item.stock <= 0 then
                return false, value .. " : Item indisponible "
	end

	-- Vérification points du joueur
	local points = player:WaitForChild("leaderstats").Points.Value
	if points < item.price then
		return false, "Points insuffisants (" .. points .. "/" .. item.price .. ")"
	end

	-- Transaction confirmée
	player.leaderstats.Points.Value -= item.price
	item.stock -= 1
	return true, "Achat confirmé !"
	
end

Rajoute sur l’écran de ta boutique un message pour indiquer au joueur la confirmation de son achat ou non :

Renomme ton TextLabel en MsgLabel :

Modifie le script storeScript pour afficher le message :

-- récupération du bouton pour ouvrir la boutique
local openButton = script.Parent.OpenButton
-- récupération du frame de la boutique	
local frameStore = script.Parent.FrameStore

-- on cache le frame de la boutique au lancement du jeu par defaut	
frameStore.Visible = false

-- on écoute l'événement de clic sur le bouton pour ouvrir ou fermer la boutique
openButton.MouseButton1Click:Connect(function()
	frameStore.Visible = not frameStore.Visible
end)

-- on récupère le bouton de la lampe dans la boutique
local lampButton = script.Parent.FrameStore.LampButton
-- on récupère le RemoteEvent pour acheter la lampe
local remoteBuy = game:GetService("ReplicatedStorage"):WaitForChild("RemoteBuy")

local msg = script.Parent.FrameStore.MsgLabel

-- on écoute l'événement de clic sur le bouton de la lampe pour l'acheter
lampButton.MouseButton1Click:Connect(function(itemName)
	-- on envoie une requête au serveur pour acheter la lampe
	local success, message = remoteBuy:InvokeServer("lamp")
	-- on affiche le message de retour du serveur sur l'acran de la boutique
	msg.Text = message
end)

Lance ton jeu pour vérifier si le message s’affiche correctement après un achat :


Création d’un outil

A mettre à la main du joueur et à présenter dans la boutique

Sous Workspace créer un outil Tool :

Renommer Tool en Lamp :

Maintenant, dessine une lampe en utilisant plusieurs parts que tu assembleras :

Colorise et choisis tes matériaux pour tes parts qui composera ta lampe, puis crée un Union de tes parts et renome l’objet obtenu en Handle :

Rajoute un SpotLight à ta lampe :

Modifie les propriétés de SpotLight pour orienter correctement le faisceau lumineux de ta lampe :

Lance ton jeu, le joueur doit pouvoirt attraper la lampe et vérifie que celle-ci est correctement orientée :

Je constate que la lampe n’est pas correctement orientée, je modifie le Grip de mon Tool pour l’orienter correctement :


AFFICHER L’OUTIL DANS LA BOUTIQUE

L’objectif est de présenter la lampe dans la boutique.

Dans un premier déplace ton outil Tool lampe sous ReplicatedStorage :

Puis tu vas modifier l’écran de ta boutique.

Supprimer le ImageLabel et remplace par un ViewportFrame :

Modifie le LocalScript StoreScript de la boutique :

-- récupération du bouton pour ouvrir la boutique
local openButton = script.Parent.OpenButton
-- récupération du frame de la boutique	
local frameStore = script.Parent.FrameStore

--[[
*** Rendre le viewport 3D de la lampe visible dans la boutique	
]]
local replicatedStorage = game:GetService("ReplicatedStorage")
local lamp = replicatedStorage:WaitForChild("Lamp")
local viewport = script.Parent.FrameStore.ViewportFrame
-- Nettoyage
viewport:ClearAllChildren()
-- Clone de l'objet
local clone = lamp:Clone()
clone.Parent = viewport
-- Caméra
local camera = Instance.new("Camera")
viewport.CurrentCamera = camera
camera.Parent = viewport
local center
local size
-- Calcul de la position de la caméra (adapté à la taille de l'objet)
if clone:IsA("Model") then
	size = clone:GetExtentsSize()
	center = clone:GetPivot().Position
else
	size = clone.Size
	center = clone.Position
end
-- Position de la caméra (à adapter selon la taille de l'objet)
camera.CFrame = CFrame.new(
	center + Vector3.new(size.X, size.Y, size.Z) * 0.8,
	center
)

-- on cache le frame de la boutique au lancement du jeu par defaut	
frameStore.Visible = false

-- on écoute l'événement de clic sur le bouton pour ouvrir ou fermer la boutique
openButton.MouseButton1Click:Connect(function()
	frameStore.Visible = not frameStore.Visible
end)

-- on récupère le bouton de la lampe dans la boutique
local lampButton = script.Parent.FrameStore.LampButton
-- on récupère le RemoteEvent pour acheter la lampe
local remoteBuy = game:GetService("ReplicatedStorage"):WaitForChild("RemoteBuy")

local msg = script.Parent.FrameStore.MsgLabel

-- on écoute l'événement de clic sur le bouton de la lampe pour l'acheter
lampButton.MouseButton1Click:Connect(function(itemName)
	-- on envoie une requête au serveur pour acheter la lampe
	local success, message = remoteBuy:InvokeServer("lamp")
	-- on affiche le message de retour du serveur sur l'acran de la boutique
	msg.Text = message
end)

Orienter l’image de l’outil pour une présentation optimum au joueur :


Mettre l’outil dans l’inventaire du joueur

Lors de l’achat de la lampe, mettre celle-ci dans l’inventaire.

Afin d’optimiser notre code, éviter des erreurs de saisie, tu vas centraliser tout ce que on appelle constante. Ces constantes sont des valeurs fixes et utilisées dans plusieurs parties du code.

Sous ReplicatedStorage crée un ModuleScript pour stocker toutes tes constantes :

local Constants = {}

Constants.POWER_RUN_MORE = "Run more"
Constants.LAMP = "Torch"
Constants.VISIBILITY = "Visibility"
Constants.MAX_SPEED = 50

return Constants

Modifie le LocalScript StoreScript de la boutique pour rajouter l’appel aux constantes :

local Constants = require(game.ReplicatedStorage.Constants)

-- récupération du bouton pour ouvrir la boutique
local openButton = script.Parent.OpenButton
-- récupération du frame de la boutique	
local frameStore = script.Parent.FrameStore

--[[
*** Rendre le viewport 3D de la lampe visible dans la boutique	
]]
local replicatedStorage = game:GetService("ReplicatedStorage")
local lamp = replicatedStorage:WaitForChild("Lamp")
local viewport = script.Parent.FrameStore.ViewportFrame
-- Nettoyage
viewport:ClearAllChildren()
-- Clone de l'objet
local clone = lamp:Clone()
clone.Parent = viewport
-- Caméra
local camera = Instance.new("Camera")
viewport.CurrentCamera = camera
camera.Parent = viewport
local center
local size
-- Calcul de la position de la caméra (adapté à la taille de l'objet)
if clone:IsA("Model") then
	size = clone:GetExtentsSize()
	center = clone:GetPivot().Position
else
	size = clone.Size
	center = clone.Position
end
-- Position de la caméra (à adapter selon la taille de l'objet)
camera.CFrame = CFrame.new(
	center + Vector3.new(size.X, size.Y, size.Z) * 0.8,
	center
)

-- on cache le frame de la boutique au lancement du jeu par defaut	
frameStore.Visible = false

-- on écoute l'événement de clic sur le bouton pour ouvrir ou fermer la boutique
openButton.MouseButton1Click:Connect(function()
	frameStore.Visible = not frameStore.Visible
end)

-- on récupère le bouton de la lampe dans la boutique
local lampButton = script.Parent.FrameStore.LampButton
-- on récupère le RemoteEvent pour acheter la lampe
local remoteBuy = game:GetService("ReplicatedStorage"):WaitForChild("RemoteBuy")

local msg = script.Parent.FrameStore.MsgLabel

-- on écoute l'événement de clic sur le bouton de la lampe pour l'acheter
lampButton.MouseButton1Click:Connect(function(itemName)
	-- on envoie une requête au serveur pour acheter la lampe
	local success, message = remoteBuy:InvokeServer("lamp")
	-- on affiche le message de retour du serveur sur l'acran de la boutique
	msg.Text = message
end)

Modifie le script storeScript sous ServerScriptService pour rajouter le module des constantes :

-- récupérer le module Constants
local Constants = require(game.ReplicatedStorage.Constants)

-- récupérer le RemoteFunction RemoteBuy
local remoteBuy = game:GetService("ReplicatedStorage"):WaitForChild("RemoteBuy")

-- écouter l'événement de requête d'achat du joueur
remoteBuy.OnServerInvoke = function(player, value)
	-- vérifier si le joueur a assez de points pour acheter l'objet
	local points = player:WaitForChild("leaderstats").Points.Value
	
	return true, " Achat confirmé !"
end

Modifie le script storeScript sous ServerScriptService, pour rajouter le contrôle des points, rajouter un tableau de tous les item de la boutique :

-- récupérer le module Constants
local Constants = require(game.ReplicatedStorage.Constants)
-- récupérer le RemoteFunction RemoteBuy
local remoteBuy = game:GetService("ReplicatedStorage"):WaitForChild("RemoteBuy")

local ITEMS = {
	[Constants.LAMP] = { price = 5, power = 10 , stock = 2 },
	[Constants.POWER_RUN_MORE] = { price = 10, power = 10, stock = 2 },
	[Constants.VISIBILITY] = { price = 15, power = 10, stock = 1 }
}

-- écouter l'événement de requête d'achat du joueur
remoteBuy.OnServerInvoke = function(player, value)
	-- vérifier si le joueur a assez de points pour acheter l'objet	
	local item = ITEMS[value]
	
        -- Vérification stock
	if not item or item.stock <= 0 then
		return false, value .. " : Item indisponible "
	end

	-- Vérification points du joueur
	local points = player:WaitForChild("leaderstats").Points.Value
	if points < item.price then
		return false, "Points insuffisants (" .. points .. "/" .. item.price .. ")"
	end

	-- Vérification si le joueur possède déjà l'item
	local newitem = player.leaderstats:FindFirstChild(Constants.POWER_RUN_MORE)
	if not newitem then
		newitem = Instance.new("IntValue")
		newitem.Parent = player.leaderstats
		newitem.Name = value	
	end
	newitem.Value += item.power
	
	-- Transaction confirmée
	player.leaderstats.Points.Value -= item.price
	item.stock -= 1

	return true, "Achat confirmé !"
	
end

Modifie le script pour rajouter la lampe dans l’inventaire du joueur :

local Constants = require(game.ReplicatedStorage.Constants)

-- récupération du bouton pour ouvrir la boutique
local openButton = script.Parent.OpenButton
-- récupération du frame de la boutique	
local frameStore = script.Parent.FrameStore

--[[
*** Rendre le viewport 3D de la lampe visible dans la boutique	
]]
local replicatedStorage = game:GetService("ReplicatedStorage")
local lamp = replicatedStorage:WaitForChild("Lamp")
local viewport = script.Parent.FrameStore.ViewportFrame
-- Nettoyage
viewport:ClearAllChildren()
-- Clone de l'objet
local clone = lamp:Clone()
clone.Parent = viewport
-- Caméra
local camera = Instance.new("Camera")
viewport.CurrentCamera = camera
camera.Parent = viewport
local center
local size
-- Calcul de la position de la caméra (adapté à la taille de l'objet)
if clone:IsA("Model") then
	size = clone:GetExtentsSize()
	center = clone:GetPivot().Position
else
	size = clone.Size
	center = clone.Position
end
-- Position de la caméra (à adapter selon la taille de l'objet)
camera.CFrame = CFrame.new(
	center + Vector3.new(size.X, size.Y, size.Z) * 0.8,
	center
)

-- on cache le frame de la boutique au lancement du jeu par defaut	
frameStore.Visible = false

-- on écoute l'événement de clic sur le bouton pour ouvrir ou fermer la boutique
openButton.MouseButton1Click:Connect(function()
	frameStore.Visible = not frameStore.Visible
end)

-- on récupère le bouton de la lampe dans la boutique
local lampButton = script.Parent.FrameStore.LampButton
-- on récupère le RemoteEvent pour acheter la lampe
local remoteBuy = game:GetService("ReplicatedStorage"):WaitForChild("RemoteBuy")

local msg = script.Parent.FrameStore.MsgLabel

local player = game.Players.LocalPlayer

-- on écoute l'événement de clic sur le bouton de la lampe pour l'acheter
lampButton.MouseButton1Click:Connect(function(itemName)
	if not player then return end
	if not lamp then return end
	
	-- on envoie une requête au serveur pour acheter la lampe
	local success, message = remoteBuy:InvokeServer(Constants.LAMP)
	-- on affiche le message de retour du serveur sur l'acran de la boutique
	msg.Text = message
        -- ajouter la lampe dans l'inventaire du joueur
	if success then
		local backpack = player:WaitForChild("Backpack")
		lamp.Parent = player:WaitForChild("Backpack")		
	end
end)

Courir plus vite

Modifie le localScript ScreenStore pour générer le pouvoir courir plus vite :

local Constants = require(game.ReplicatedStorage.Constants)

-- récupération du bouton pour ouvrir la boutique
local openButton = script.Parent.OpenButton
-- récupération du frame de la boutique	
local frameStore = script.Parent.FrameStore

--[[
*** Rendre le viewport 3D de la lampe visible dans la boutique	
]]
local replicatedStorage = game:GetService("ReplicatedStorage")
local lamp = replicatedStorage:WaitForChild("Lamp")
local viewport = script.Parent.FrameStore.ViewportFrame
-- Nettoyage
viewport:ClearAllChildren()
-- Clone de l'objet
local clone = lamp:Clone()
clone.Parent = viewport
-- Caméra
local camera = Instance.new("Camera")
viewport.CurrentCamera = camera
camera.Parent = viewport
local center
local size
-- Calcul de la position de la caméra (adapté à la taille de l'objet)
if clone:IsA("Model") then
	size = clone:GetExtentsSize()
	center = clone:GetPivot().Position
else
	size = clone.Size
	center = clone.Position
end
-- Position de la caméra (à adapter selon la taille de l'objet)
camera.CFrame = CFrame.new(
	center + Vector3.new(size.X, size.Y, size.Z) * 0.8,
	center
)

-- on cache le frame de la boutique au lancement du jeu par defaut	
frameStore.Visible = false

-- on écoute l'événement de clic sur le bouton pour ouvrir ou fermer la boutique
openButton.MouseButton1Click:Connect(function()
	frameStore.Visible = not frameStore.Visible
end)

-- on récupère le bouton de la lampe dans la boutique
local lampButton = script.Parent.FrameStore.LampButton
-- on récupère le RemoteEvent pour acheter la lampe
local remoteBuy = game:GetService("ReplicatedStorage"):WaitForChild("RemoteBuy")

local msg = script.Parent.FrameStore.MsgLabel

local player = game.Players.LocalPlayer

local humanoid
local leaderstats
local walkSpeed
local MAXSPEED = Constants.MAX_SPEED or 50
local function setup(character)
	humanoid = character:WaitForChild("Humanoid")
	leaderstats = player:FindFirstChild("leaderstats")
	walkSpeed = humanoid.WalkSpeed
end

player.CharacterAdded:Connect(setup)

if player and player.Character then
	setup(player.Character)
end
-- on écoute l'événement de clic sur le bouton de la lampe pour l'acheter
lampButton.MouseButton1Click:Connect(function(itemName)
	if not player then return end
	if not lamp then return end
	
	-- on envoie une requête au serveur pour acheter la lampe
	local success, message = remoteBuy:InvokeServer(Constants.LAMP)
	-- on affiche le message de retour du serveur sur l'acran de la boutique
	msg.Text = message
        -- ajouter la lampe dans l'inventaire du joueur
	if success then
		local backpack = player:WaitForChild("Backpack")
		lamp.Parent = player:WaitForChild("Backpack")		
	end
end)

-- on récupère le bouton pour le pouvoir de courir plus vite
runButton.MouseButton1Click:Connect(function(itemName)
	if not player then return end
	if not leaderstats then return end
	-- on envoie une requête au serveur pour le pouvoir courir plus vite
	local success, message = remoteBuy:InvokeServer(Constants.POWER_RUN_MORE)
	-- on affiche le message de retour du serveur sur l'acran de la boutique
	msg.Text = message
end)

Vérifie que tu disposes bien du pouvoir de courir plus vite :


Ajouter le pouvoir de courir plus vite


Sur la boutique programmer le bouton « Courrir plus vite »

Objectif :

✔ programmer le bouton de la boutique « courir plus vite »
✔ envoyer une demande au serveur pour acheter le pouvoir
✔ recevoir une réponse succès ou pas
✔ activer un pouvoir avec le clavier par la touche R

Le principe du pouvoir :

Le joueur peut :

  • acheter un pouvoir “courir plus vite”
  • appuyer sur R pour l’activer
  • utiliser ce pouvoir un certain nombre de fois

Programme le clic sur le bouton « courir plus vite » :

Modifie le localScript StoreScript et ajoute en fin du script :

-- on récupère le bouton pour le pouvoir de courir plus vite
runButton.MouseButton1Click:Connect(function(itemName)
	if not player then return end
	if not leaderstats then return end
	-- on envoie une requête au serveur pour le pouvoir courir plus vite
	local success, message = remoteBuy:InvokeServer(Constants.POWER_RUN_MORE)
	-- on affiche le message de retour du serveur sur l'acran de la boutique
	msg.Text = message
end)

Programme pour que le joueur court plus vite sur l’appui de la touche R :

Modifie le localScript StoreScript et ajoute en fin du script :

--[[
	Traitement des touches du clavier pour activer/désactiver les pouvoirs du joueur
]]
-- Connecte l'événement du clavier
local UserInputService = game:GetService("UserInputService")
local runMore = false
-- Récupère l'évènement du clavier
UserInputService.InputBegan:Connect(function(input, gameProcessed)
	if not player then return end
	if not humanoid then return end
	-- Vérifie si l'évènement est un clavier
	if input.KeyCode ~= Enum.KeyCode.Unknown then
		-- Ferme l'écran de la boutique
		frameStore.Visible = false
		-- Vérifie si la touche appuyée est R
		if input.KeyCode == Enum.KeyCode.R and not gameProcessed then
			if runMore then
				runMore = false
				humanoid.WalkSpeed = walkSpeed
			else
				-- Vérifie si le leaderstats existe et le pouvoir de courir plus vite
				if leaderstats and leaderstats:FindFirstChild(Constants.POWER_RUN_MORE) then
					local run = leaderstats:FindFirstChild(Constants.POWER_RUN_MORE)
					-- si le pouvoir est actif
					if run.Value > 0 then

						humanoid.WalkSpeed = MAXSPEED
						run.Value -= 1
						runMore	= true
					end
				end
			end
		end

	end

end)

A chaque utilisation de la touche R pour courir plus vite, le pouvoir diminue :


Fermeture automatique de la boutique

Fermer automatiquement la boutique en cliquant en dehors de la fen,être de la boutique ou en utilisant une touche du clavier.

Crée un TextButton dans un Frame qui couvre tout l’écran :

Renomme le TextButton en Background.

Donne une priorité à la fenêtre de la boutique et aux boutons de la boutique :

Modifie le localScript StoreScript :

-- on récupère le background de l'interface de la boutique
local background = script.Parent.FrameBackground.Background
--[[
	Affichage ou non de la boutique sur l'appui de l'icone de la boutique 
]]
-- on cache le frame de la boutique au lancement du jeu par defaut	
frameStore.Visible = false
background.Interactable = false

-- on écoute l'événement de clic sur le bouton pour ouvrir ou fermer la boutique
openButton.MouseButton1Click:Connect(function()
	frameStore.Visible = not frameStore.Visible
	background.Interactable = frameStore.Visible
	frameStore.MsgLabel.Text = "Choisis ton option"
end)

background.MouseButton1Click:Connect(function()
	frameStore.Visible = false
	-- rendre non cliquable
	background.Interactable = frameStore.Visible
end)

et lors de l’appui d’une touche :

--[[
	Traitement des touches du clavier pour activer/désactiver les pouvoirs du joueur
]]
-- Connecte l'événement du clavier
local UserInputService = game:GetService("UserInputService")
local runMore = false
-- Récupère l'évènement du clavier
UserInputService.InputBegan:Connect(function(input, gameProcessed)
	if not player then return end
	if not humanoid then return end
	-- Vérifie si l'évènement est un clavier
	if input.KeyCode ~= Enum.KeyCode.Unknown then
		-- Ferme l'écran de la boutique
		frameStore.Visible = false
		background.Interactable = frameStore.Visible	
		-- Vérifie si la touche appuyée est R
		if input.KeyCode == Enum.KeyCode.R and not gameProcessed then
			if runMore then
				runMore = false
				humanoid.WalkSpeed = walkSpeed
			else
				-- Vérifie si le leaderstats existe et le pouvoir de courir plus vite
				if leaderstats and leaderstats:FindFirstChild(Constants.POWER_RUN_MORE) then
					local run = leaderstats:FindFirstChild(Constants.POWER_RUN_MORE)
					-- si le pouvoir est actif
					if run.Value > 0 then

						humanoid.WalkSpeed = MAXSPEED
						run.Value -= 1
						runMore	= true
					end
				end
			end
		end

	end

end)