2D Gun game based off of Space Invaders
Key RequiredUniversal

2D Gun game based off of Space Invaders

Universal ScriptDcruzRaceDcruzRace 1.4K views 44 executesUpdated Oct 10, 2025
5.0/ 5(1 votes)
10100% Positive
Lua Script•308 lines (9393 chars)
local player = game.Players.LocalPlayer
local gui = Instance.new("ScreenGui", player:WaitForChild("PlayerGui"))
gui.Name = "Gun2DGame"
gui.ResetOnSpawn = false


local gameFrame = Instance.new("Frame")
gameFrame.Size = UDim2.new(0, 600, 0, 400)
gameFrame.Position = UDim2.new(0.5, -300, 0.5, -200)
gameFrame.BackgroundColor3 = Color3.fromRGB(25, 25, 25)
gameFrame.BorderSizePixel = 2
gameFrame.Parent = gui


local playerBox = Instance.new("Frame")
playerBox.Size = UDim2.new(0, 30, 0, 30)
playerBox.Position = UDim2.new(0, 285, 0, 350)
playerBox.BackgroundColor3 = Color3.fromRGB(0, 150, 255)
playerBox.Parent = gameFrame


local playerHP = 3
local hpText = Instance.new("TextLabel")
hpText.Size = UDim2.new(0, 100, 0, 30)
hpText.Position = UDim2.new(0, 0, 0, 0)
hpText.BackgroundTransparency = 1
hpText.TextColor3 = Color3.new(1, 1, 1)
hpText.TextScaled = true
hpText.Text = "HP: " .. playerHP
hpText.Parent = gameFrame


local score = 0
local scoreText = Instance.new("TextLabel")
scoreText.Size = UDim2.new(0, 150, 0, 30)
scoreText.Position = UDim2.new(1, -160, 0, 0)
scoreText.BackgroundTransparency = 1
scoreText.TextColor3 = Color3.new(1, 1, 1)
scoreText.TextScaled = true
scoreText.Text = "Score: 0"
scoreText.Parent = gameFrame


local canShoot = true
local shootDelay = 0.5
local shieldActive = false
local alive = true
local enemiesEscaped = 0
local maxEscapes = 4
local maxScore = 50


local buttonSize = 60
local leftButton = Instance.new("TextButton", gui)
leftButton.Size = UDim2.new(0, buttonSize, 0, buttonSize)
leftButton.Position = UDim2.new(0.05, 0, 1, -200)
leftButton.Text = "←"
leftButton.TextScaled = true
leftButton.BackgroundColor3 = Color3.fromRGB(0, 0, 255)

local rightButton = Instance.new("TextButton", gui)
rightButton.Size = UDim2.new(0, buttonSize, 0, buttonSize)
rightButton.Position = UDim2.new(0.15, 0, 1, -200)
rightButton.Text = "→"
rightButton.TextScaled = true
rightButton.BackgroundColor3 = Color3.fromRGB(0, 0, 255)

local upButton = Instance.new("TextButton", gui)
upButton.Size = UDim2.new(0, buttonSize, 0, buttonSize)
upButton.Position = UDim2.new(0.10, 0, 1, -270)
upButton.Text = "↑"
upButton.TextScaled = true
upButton.BackgroundColor3 = Color3.fromRGB(0, 0, 255)

local downButton = Instance.new("TextButton", gui)
downButton.Size = UDim2.new(0, buttonSize, 0, buttonSize)
downButton.Position = UDim2.new(0.10, 0, 1, -130)
downButton.Text = "↓"
downButton.TextScaled = true
downButton.BackgroundColor3 = Color3.fromRGB(0, 0, 255)

local shootButton = Instance.new("TextButton", gui)
shootButton.Size = UDim2.new(0, 80, 0, 80)
shootButton.Position = UDim2.new(1, -100, 1, -180)
shootButton.Text = "Shoot"
shootButton.TextScaled = true
shootButton.BackgroundColor3 = Color3.fromRGB(255, 0, 0)


local moveLeft, moveRight, moveUp, moveDown = false, false, false, false
leftButton.MouseButton1Down:Connect(function() moveLeft = true end)
leftButton.MouseButton1Up:Connect(function() moveLeft = false end)
rightButton.MouseButton1Down:Connect(function() moveRight = true end)
rightButton.MouseButton1Up:Connect(function() moveRight = false end)
upButton.MouseButton1Down:Connect(function() moveUp = true end)
upButton.MouseButton1Up:Connect(function() moveUp = false end)
downButton.MouseButton1Down:Connect(function() moveDown = true end)
downButton.MouseButton1Up:Connect(function() moveDown = false end)


local function showRestart(reason)
	if not alive then return end
	alive = false
	local msg = Instance.new("TextLabel")
	msg.Size = UDim2.new(0, 300, 0, 50)
	msg.Position = UDim2.new(0.5, -150, 0.4, 0)
	msg.BackgroundTransparency = 1
	msg.TextColor3 = Color3.new(1, 1, 1)
	msg.TextScaled = true
	msg.Text = reason
	msg.Parent = gui

	local restart = Instance.new("TextButton")
	restart.Size = UDim2.new(0, 200, 0, 80)
	restart.Position = UDim2.new(0.5, -100, 0.5, -40)
	restart.Text = "Restart"
	restart.TextScaled = true
	restart.BackgroundColor3 = Color3.fromRGB(255, 50, 50)
	restart.Parent = gui
	restart.MouseButton1Click:Connect(function()
		gui:Destroy()
	end)
end


local function shoot()
	if not canShoot or not alive then return end
	canShoot = false

	local bullet = Instance.new("Frame")
	bullet.Size = UDim2.new(0, 6, 0, 15)
	bullet.BackgroundColor3 = Color3.fromRGB(255, 255, 0)
	bullet.Position = UDim2.new(0, playerBox.Position.X.Offset + 12, 0, playerBox.Position.Y.Offset - 10)
	bullet.Parent = gameFrame

	task.spawn(function()
		while bullet and bullet.Parent and bullet.Position.Y.Offset > -10 do
			bullet.Position = UDim2.new(0, bullet.Position.X.Offset, 0, bullet.Position.Y.Offset - 10)
			for _, enemy in pairs(gameFrame:GetChildren()) do
				if enemy.Name == "Enemy" then
					if math.abs(enemy.Position.X.Offset - bullet.Position.X.Offset) < 20 and
					   math.abs(enemy.Position.Y.Offset - bullet.Position.Y.Offset) < 20 then
						enemy:Destroy()
						bullet:Destroy()
						score += 1
						scoreText.Text = "Score: " .. score
						if score >= maxScore then
							showRestart("You Win! 50 Kills!")
						end
						break
					end
				end
			end
			task.wait(0.03)
		end
		if bullet then bullet:Destroy() end
	end)

	task.wait(shootDelay)
	canShoot = true
end

shootButton.MouseButton1Click:Connect(shoot)


task.spawn(function()
	while task.wait(2) do
		if not alive then break end
		local enemy = Instance.new("Frame")
		enemy.Size = UDim2.new(0, 30, 0, 30)
		enemy.Position = UDim2.new(0, math.random(0, 570), 0, 0)
		enemy.BackgroundColor3 = Color3.fromRGB(255, 0, 0)
		enemy.Name = "Enemy"
		enemy.Parent = gameFrame

		task.spawn(function()
			while enemy.Parent and alive do
				enemy.Position = UDim2.new(0, enemy.Position.X.Offset, 0, enemy.Position.Y.Offset + 2)
				if enemy.Position.Y.Offset >= 380 then
					enemiesEscaped += 1
					enemy:Destroy()
					if enemiesEscaped >= maxEscapes then
						showRestart("You lost! 4 enemies escaped!")
					end
					break
				end
				task.wait(0.03)
			end
		end)

		task.spawn(function()
			while enemy and enemy.Parent and alive do
				task.wait(math.random(1, 3))
				if not alive or not enemy.Parent then break end

				local eb = Instance.new("Frame")
				eb.Size = UDim2.new(0, 5, 0, 10)
				eb.BackgroundColor3 = Color3.fromRGB(255, 200, 0)
				eb.Position = UDim2.new(0, enemy.Position.X.Offset + 12, 0, enemy.Position.Y.Offset + 30)
				eb.Parent = gameFrame

				task.spawn(function()
					while eb and eb.Parent and eb.Position.Y.Offset < 400 and alive do
						eb.Position = UDim2.new(0, eb.Position.X.Offset, 0, eb.Position.Y.Offset + 10)
						if not shieldActive and
						   math.abs(eb.Position.Y.Offset - playerBox.Position.Y.Offset) < 20 and
						   math.abs(eb.Position.X.Offset - playerBox.Position.X.Offset) < 20 and alive then
							playerHP -= 1
							hpText.Text = "HP: " .. playerHP
							eb:Destroy()
							if playerHP <= 0 then
								showRestart("You were defeated!")
							end
							break
						end
						task.wait(0.03)
					end
					if eb then eb:Destroy() end
				end)
			end
		end)
	end
end)


task.spawn(function()
	while task.wait(8) do
		if not alive then break end
		local power = Instance.new("Frame")
		power.Size = UDim2.new(0, 20, 0, 20)
		power.Position = UDim2.new(0, math.random(20, 580), 0, math.random(50, 350))
		local isShield = math.random() > 0.5
		power.BackgroundColor3 = isShield and Color3.fromRGB(0, 255, 0) or Color3.fromRGB(255, 0, 255)
		power.Name = "PowerUp"
		power.Parent = gameFrame

		task.spawn(function()
			while power.Parent and alive do
				task.wait(0.05)
				if not alive or not power.Parent then break end
				local dx = math.abs(power.Position.X.Offset - playerBox.Position.X.Offset)
				local dy = math.abs(power.Position.Y.Offset - playerBox.Position.Y.Offset)
				if dx < 25 and dy < 25 then
					power:Destroy()

					local popup = Instance.new("TextLabel")
					popup.Size = UDim2.new(0, 120, 0, 30)
					popup.Position = UDim2.new(0, playerBox.Position.X.Offset - 40, 0, playerBox.Position.Y.Offset - 30)
					popup.BackgroundTransparency = 1
					popup.TextScaled = true
					popup.TextColor3 = Color3.new(1, 1, 1)
					popup.Parent = gameFrame

					if isShield then
						popup.Text = "Shield!"
						shieldActive = true
						playerBox.BackgroundColor3 = Color3.fromRGB(0, 255, 0)
						task.spawn(function()
							task.wait(5)
							if alive then
								shieldActive = false
								playerBox.BackgroundColor3 = Color3.fromRGB(0, 150, 255)
							end
						end)
					else
						popup.Text = "Rapid Fire!"
						local oldDelay = shootDelay
						shootDelay = 0.2
						task.spawn(function()
							task.wait(10)
							if alive then
								shootDelay = oldDelay
							end
						end)
					end

					task.spawn(function()
						for i = 1, 30 do
							popup.Position = popup.Position - UDim2.new(0, 0, 0, 2)
							popup.TextTransparency = i / 30
							task.wait(0.05)
						end
						popup:Destroy()
					end)

					break
				end
			end
			if power and power.Parent then
				task.wait(12)
				if power then power:Destroy() end
			end
		end)
	end
end)

 (Boundaries)
task.spawn(function()
	while task.wait(0.03) do
		if not alive then break end
		local x, y = playerBox.Position.X.Offset, playerBox.Position.Y.Offset
		if moveLeft then x = math.max(0, x - 5) end
		if moveRight then x = math.min(570, x + 5) end
		if moveUp then y = math.max(0, y - 5) end
		if moveDown then y = math.min(370, y + 5) end
		playerBox.Position = UDim2.new(0, x, 0, y)
	end
end)

Features & Information

Just like Space Invaders collect the power ups The Power ups are forcefield and Faster shooting the max of enemies you can let in is 5 Tell me if they're is any issues in the comments
#Spaceinvaders DcruzRace Trending Fun Staysafe

Community Comments (2)

DcruzRaceDcruzRaceOct 10, 2025

To win you gotta kill 50 enemies

blepblepOct 10, 2025

Deez nugget

More Scripts for Universal Scripts