AI Prompt:
I am writing code for a Roblox world using a graphics API. This graphics API is stored in a module script in ReplicatedStorage called genericShapes.
I am using this module to assist in creating an art museum. The art museum also uses several modules stored in ReplicatedStorage.
In my "studentExhibition" module script, I include two supporting modules using:
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local s = require(ReplicatedStorage.genericShapes)
local b = require(ReplicatedStorage.artInstallationRoom)
Each "student exhibition" is stored as a function that initializes a table with several "callback" functions. These callback functions are installed
for the player when the player enters a particular art exhibit room. The following shows how the startingScript sets up the exhibit room for the player.
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local b = require(ReplicatedStorage.artInstallationRoom)
local e = require(ReplicatedStorage.studentExhibition)
local Players = game:GetService("Players")
b.setWidth(75)
b.setLength(75)
Players.PlayerAdded:Connect(function(player)
player.CharacterAdded:Connect(function(character)
local humanoidRootPart = character:WaitForChild("HumanoidRootPart")
local iteration = 1
local currentRoomCenter = Vector3.new(0, 25, -45)
local currentRoomSize = Vector3.new(75, 50, 75)
while humanoidRootPart do
local k=e.CalebRings(75, 75)
k.draw()
local iteration = 1
k.defineInteractions()
while true do
k.animate({
iteration=iteration,
locationInRoom = 100 * ((currentRoomCenter + currentRoomSize/2) - humanoidRootPart.Position)/currentRoomSize
})
wait(0.1)
iteration = iteration + 1
end
end
end)
end)
There are about 20 different student exhibition functions stored in the studentExhibition module. Each shows the artwork for one student's exhibition.
The artworks are typically made from various shape functions. The shape functions used in the art are: square, rectangle, circle, panel, disc, cube,
tube, sphere, steps, and wall. Since the shapes are in a module, you need to include the reference to the replicated storage module. For example, to
create a square you would use the square's constructor: s.square(). Optional parameters can be passed into the function such as x, y, z, size, color, material).
A useful way of passing these parameters is through the use of a table. For example:
s.square({ x=0, y=5, z=-15, size=10, thickness=0.5, color=Color3.new(1, 0, 0) })
The table here is encapsulated using curly braces and the named values in the table are separated by commas.
Some of the basic numeric parameters that can be passed to this table include: x, y, z, size, radius, length, width, height, thickness.
You can also pass parameters such as position, rotateBy, and orientation which all require Vector3 values. RotateBy and Orientation are synonymous.
You can pass color as a string (color name) or as a Color3 value.
Transparency, opacity and reflectance are values that range from 0 to 1.
The parameter "anchored" uses a Boolean value.
Material is a parameter that can be passed as an enumerated value such as: Enum.Material.Foil
Some common materials include:
.Plastic, .Wood, .Slate, .Concrete, .CorrodedMetal, .DiamondPlate, .Foil, .Grass, .Ice, .Marble, .Granite, .Brick, .Pebble, .Sand, .Fabric, .SmoothPlastic, .Metal
Shape objects are created with a default orientation (unless you pass a specific orientation to be used). Circles, squares, discs, rectangles are
initially rendered as having a vertical appearance (not laying flat on the ground).
The wall, steps and tube shapes require two sets of coordinates. For example:
s.tube({ x1=-10, y1=4, z1=25, x2=10, y2=4, z2=5, size=10, thickness=2, color=Color3.new(1, 0.243137, 0.054902), material=Enum.Material.Wood })
s.wall({x1=0, y1=0, z1=23, x2=20, y2=2, z2=23, thickness=1, material=Enum.Material.Brick, color=Color3.fromRGB(179, 73, 255)})
s.steps({x1=0, y1=0, z1=23, x2=20, y2=2, z2=23, thickness=1, material=Enum.Material.Brick, color=Color3.fromRGB(179, 73, 255)})
For the wall and steps, the height of the wall and steps are determined by the difference between the y1 and y2 values. If y1 is 0 and y2 is 2,
then the height of the wall will be 2 units. The thickness of the wall indicates how wide it should be as it traverses from x1,z1 to x2,z2.
The tube function also takes two coordinates. The size parameter indicates the diameter of the tube and the thickness indicates the thickness
of the walls of the tube.
There are a variety of methods, common to all basic shape functions, that can be chained. For example:
s.sphere()
:fill(randomColor())
:setMaterial(Enum.Material.CorrodedMetal)
or
s.cube()
:rotate(45, 45, 0)
:setColor(randomColor())
:setMaterial(Enum.Material.Marble)
:opacity(0.90)
The list of basic methods includes:
anchored(boolean)
setAnchored(boolean)
setAttribute(string, string)
color(Color3)
setColor(Color3)
fill(Color3)
fillColor(Color3)
material(Enum.Material)
setMaterial(Enum.Material)
rotate(Vector3 | number, y: number?, z: number?)
rotateBy(Vector3 | number, y: number?, z: number?)
size(number)
setSize(number)
reSize(number)
opacity(number)
setOpacity(number)
transparency(number)
setTransparency(number)
moveBy(Vector3 | number, y: number?, z: number?)
moveTo(Vector3 | number, y: number?, z: number?)
subtract(ShapeObject | Part, destroySubPart: boolean?)
cut(ShapeObject | Part, destroySubPart: boolean?)
join(ShapeObject | Part | {ShapeObject | Part})
merge(ShapeObject | Part | {ShapeObject | Part})
union(ShapeObject | Part | {ShapeObject | Part})
intersect(ShapeObject | Part | {ShapeObject | Part})
I would like you to create artworks to be shown in the museum.
Please note that when creating an artwork from shapes, you need to store the shapes in an array using:
local someShape = s.someShapeFunction()
table.insert(exhibitRoom.parts, someShape )
The reason for this is because the art is destroyed once the player exits the room. There may be hundreds of rooms in the museum and each exhibit
could have hundreds of shapes as the art. So, there is a potential for thousands of shapes and with their animation and interactions, this could
slow the processing down significantly. So, the art will only be created when the player is in the room and will be destroyed when the player leaves the room.
Below is an example of a single student exhibition function:
function StudentExhibition.AmirsFirstArt(x, z)
local exhibitRoom = { room=b.new({x=x, z=z}), name="AmirsFirstArt", parts={}, onInteraction=nil }
exhibitRoom.draw = function()
-- Exhibit Settings
local exhibitSpacing = 20
local pedestalSize = 10
local floorLevel = 0
-- Define a few "Exhibits" with different shapes and positions
local exhibits = {
{x = exhibitRoom.room.center.X-exhibitSpacing, z = exhibitRoom.room.center.Z, color = Color3.fromRGB(255, 85, 0), shape = "Geometric Tension"},
{x = exhibitRoom.room.center.X, z = exhibitRoom.room.center.Z, color = Color3.fromRGB(0, 170, 255), shape = "The Floating Core"},
{x = exhibitRoom.room.center.X+exhibitSpacing, z = exhibitRoom.room.center.Z, color = Color3.fromRGB(170, 0, 255), shape = "Structural Void"}
}
for _, data in ipairs(exhibits) do
-- 1. BUILD THE PEDESTAL
-- A sleek, dark base for the art to sit on
local pedestal = s.cube({x = data.x, y = floorLevel + 2, z = data.z, size = pedestalSize})
:setMaterial(Enum.Material.Marble)
:setColor(Color3.fromRGB(30, 30, 30))
:setTransparency(0)
:setAttribute("ArtObject", "Pedestal")
table.insert(exhibitRoom.parts, pedestal)
-- 2. CREATE THE ART PIECE (Different for each position)
local artY = floorLevel + pedestalSize * 1.2 -- Floating slightly above the pedestal
if data.shape == "Geometric Tension" then
-- Abstract spikes using tubes
for i = 1, 8 do
local tensionPart = s.tube({
x1 = data.x, y1 = artY - 2, z1 = data.z,
x2 = data.x + math.random(-10, 10),
y2 = artY + math.random(5, pedestalSize),
z2 = data.z + math.random(-10, 10),
size = 2, thickness = 0.5
})
:setMaterial(Enum.Material.Neon)
:setColor(data.color)
table.insert(exhibitRoom.parts, tensionPart)
end
elseif data.shape == "The Floating Core" then
-- A sphere inside a hollow cube frame
local floatingCore = s.cube({x = data.x, y = artY, z = data.z, size = 10})
:setMaterial(Enum.Material.Glass)
:setColor(Color3.new(1, 1, 1))
:setTransparency(0.8)
:cut(s.cube({x = data.x, y = artY, z = data.z, size = 9})) -- Make it a thin frame
table.insert(exhibitRoom.parts, floatingCore)
local coreSphere = s.sphere({x = data.x, y = artY, z = data.z, size = 6})
:setMaterial(Enum.Material.Neon)
:setColor(data.color)
table.insert(exhibitRoom.parts, coreSphere)
elseif data.shape == "Structural Void" then
-- A disc-based sculpture
for i = 1, 5 do
local discPart = s.disc({x = data.x, y = artY + (i * 2), z = data.z, size = pedestalSize - i})
:rotateBy(math.random(0, 180), math.random(0, 180), 0)
:setMaterial(Enum.Material.SmoothPlastic)
:setColor(data.color)
:setTransparency(0.3)
table.insert(exhibitRoom.parts, discPart)
end
end
-- 3. ADD AN EXHIBIT LIGHT (Optional Aesthetic)
local lightPart = s.sphere({x = data.x, y = artY + 20, z = data.z, size = 1})
:setMaterial(Enum.Material.Neon)
:setColor(Color3.new(1, 1, 1))
table.insert(exhibitRoom.parts, lightPart)
end
end
exhibitRoom.onInteraction = function(thePart)
local touchingPartsTable = thePart:GetTouchingParts()
local artObject = thePart:GetAttribute("ArtObject")
if artObject ~= "Pedestal" then
for i=1,#touchingPartsTable do
touchingPartsTable[i].Color =Color3.new(0, 0.34902, 1)
touchingPartsTable[i].Material = Enum.Material.Wood
end
end
end
exhibitRoom.defineInteractions = function()
for i=1,#exhibitRoom.parts do exhibitRoom.parts[i].part.Touched:Connect(exhibitRoom.onInteraction) end
end
exhibitRoom.animate = function(...)
for i=1,#exhibitRoom.parts do
local artObject = exhibitRoom.parts[i].part:GetAttribute("ArtObject")
if artObject ~= "Pedestal" then
exhibitRoom.parts[i].Color = Color3.new(math.random(),math.random(),math.random())
end
end
end
return exhibitRoom
end
Create a new art exhibit function using the same format for the functions and callbacks.