Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
A simplified version of the "Learn Craft" project included with Codea
--# Scene
-- Craft Scenes
function setup()
-- Create a new craft scene
yourScene = craft.scene()
-- Activate sidebar controls
setParameters()
end
-- Called automatically by Codea
function draw()
-- No need to clear the background, a scene does that for you
-- Update the scene
yourScene:update(DeltaTime)
-- Draw the scene
yourScene:draw()
-- Do any 2D drawing last
drawStepName("Scene 🎬")
end
function setParameters()
-- Define this scene's individual sidebar controls
Note = "There are six lessons. You may need to scroll down to see them all."
parameter.watch("Note")
end
function PrintExplanation()
output.clear()
print("Where is everything?")
print("This is a blank scene right now, but it can hold amazing things.")
print("It just takes 3 steps to start one.")
print("Create it using craft.scene(), then with it call update(DeltaTime) and draw() inside the draw function.")
end
function cleanup()
if viewer then
touches.removeHandler(viewer)
viewer = nil
end
yourScene = nil
collectgarbage()
end
--# Entities
-- Craft Entities
function setup()
-- Create a new craft scene
yourScene = craft.scene()
-- Use that scene to create a new entity
cube = yourScene:entity()
-- Define a size for the entity
size = vec3(1,1,1)
-- Use that size to make the entity a cube
cube.model = craft.model.cube(size)
-- Give the entity a material, which lets it have an image
cube.material = craft.material("Materials:Standard")
-- Assign it an image or "skin" using material.map
cube.material.map = readImage("Blocks:Dirt")
-- Position it (these values are also set in the sidebar controls)
cube.x = 0
cube.y = 0
cube.z = 4
cube.eulerAngles = vec3(200,180,0)
-- Activate sidebar controls
setParameters()
end
-- Called automatically by Codea
function draw()
-- For convenience you can give scene updates their own function
updateScene()
-- Draw the scene
yourScene:draw()
-- Do 2D drawing last
drawStepName("Entities 👻")
end
function updateScene()
-- Update entity position based on sidebar controls
cube.x = x
cube.y = y
cube.z = z
cube.eulerAngles = vec3(eulerAnglesX, eulerAnglesY, eulerAnglesZ)
-- Update skin setting based on sidebar controls
if cube.material.map and not skin then
cube.material.map = nil
elseif not cube.material.map and skin then
cube.material.map = readImage("Blocks:Dirt")
end
-- Update the scene (physics, transforms etc)
yourScene:update(DeltaTime)
end
function setParameters()
-- Define this scene's individual sidebar controls
DontPanic = "The lesson buttons are still here! Just scroll down to see them."
parameter.watch("DontPanic")
parameter.boolean("skin", true)
parameter.number("x", -2, 2, 0)
parameter.number("y", -2, 2, 0)
parameter.number("z", 0, 8, 4)
parameter.number("eulerAnglesX", 0, 360, 180)
parameter.number("eulerAnglesY", 0, 360, 200)
parameter.number("eulerAnglesZ", 0, 360, 180)
end
function PrintExplanation()
output.clear()
print("Entities are flexible objects used for displaying 3D models, simulating physics, and more.")
print("Create an entity inside a scene using yourScene:entity().")
print("To see it, give it a model (and a material or \"skin\" to jazz it up).")
print("Its x, y, z, and eulerAngles properties are just a few of the ways to position it onscreen.")
end
--# Models
-- Craft Models
function setup()
-- All the code from the previous lessons (cube's position adjusted)
yourScene = craft.scene()
cube = yourScene:entity()
size = vec3(1,1,1)
cube.model = craft.model.cube(size)
cube.material = craft.material("Materials:Standard")
cube.material.map = readImage("Blocks:Dirt")
cube.x = 0
cube.y = -8.4
cube.z = 41
cube.scale = vec3(35,0.6,34)
-- Make the cube's texture smaller and repeated (looks a bit nicer)
cube.material.offsetRepeat = vec4(0,0,5,5)
-- Make a new entity and give it the robot model
robot = yourScene:entity()
robot.model = craft.model("Blocky Characters:Robot")
-- Position the robot
robot.y = -8.2
robot.z = 41
-- Set the robot's eulerAngles (these are also set in the sidebar)
-- Basically we're just turning it to face us.
robot.eulerAngles = vec3(0, 180, 0)
-- Activate sidebar controls
setParameters()
end
-- Called automatically by Codea
function draw()
-- For convenience scene updates can be a separate function
updateScene()
-- Draw the scene
yourScene:draw()
-- 2D drawing goes here
drawStepName("Models 🤖")
end
function updateScene()
-- Update Robot eulerAngles based on sidebar controls
robot.eulerAngles = vec3(RobotEulerX, RobotEulerY, RobotEulerZ)
-- Update the scene (physics, transforms etc)
yourScene:update(DeltaTime)
end
function setParameters()
-- Define this scene's individual sidebar controls
DontPanic = "The lesson buttons are still here! Just scroll down to see them."
parameter.watch("DontPanic")
parameter.number("RobotEulerX", 0, 360, 0)
parameter.number("RobotEulerY", 0, 360, 180)
parameter.number("RobotEulerZ", 0, 360, 0)
end
function PrintExplanation()
output.clear()
print("The last lesson showed a cube model, but models can be much more complex than that.")
print("This entity uses a built-in Codea model called \"Blocky Characters:Robot\".")
print("The ground is actually the same cube from the last scene, just flattened out.")
end
--# Cameras
-- Craft Camera
function setup()
-- All the code from the previous lessons
yourScene = craft.scene()
cube = yourScene:entity()
size = vec3(1,1,1)
cube.model = craft.model.cube(size)
cube.material = craft.material("Materials:Standard")
cube.material.map = readImage("Blocks:Dirt")
cube.y = -8.4
cube.z = 41
cube.scale = vec3(35,0.6,34)
cube.material.offsetRepeat = vec4(0,0,5,5)
robot = yourScene:entity()
robot.model = craft.model("Blocky Characters:Robot")
robot.y = -8.2
robot.z = 41
robot.eulerAngles = vec3(0, 180, 0)
-- Set the position of the scene's built-in camera (also set in the sidebar)
yourScene.camera.eulerAngles = vec3(0, 0, 0)
yourScene.camera.position = vec3(0, 0, 0)
-- The camera component lots of other camera settings, like fieldOfView
cameraSettings = yourScene.camera:get(craft.camera)
-- fieldOfView is similar to zoom (this value is also set in the sidebar)
cameraSettings.fieldOfView = 60
-- Activate sidebar controls
setParameters()
end
function setParameters()
-- Define this scene's individual sidebar controls
DontPanic = "The lesson buttons are still here! Just scroll down to see them."
parameter.watch("DontPanic")
parameter.number("CameraX", -20, 20, 0)
parameter.number("CameraY", -20, 20, 0)
parameter.number("CameraZ", -20, 20, 0)
parameter.number("CameraEulerX", 0, 360, 0)
parameter.number("CameraEulerY", 0, 360, 0)
parameter.number("CameraEulerZ", 0, 360, 0)
parameter.number("FieldOfView", 20, 90, 55)
end
function updateScene()
-- Set the camera position based on sidebar controls
yourScene.camera.eulerAngles = vec3(CameraEulerX, CameraEulerY, CameraEulerZ)
yourScene.camera.position = vec3(CameraX, CameraY, CameraZ)
-- Set the field of view based on sidebar controls
cameraSettings.fieldOfView = FieldOfView
-- Update the scene (physics, transforms etc)
yourScene:update(DeltaTime)
end
-- Called automatically by Codea
function draw()
-- For convenience scene updates can be a separate function
updateScene()
-- Draw the scene
yourScene:draw()
-- Do any 2D drawing last
drawStepName("Cameras 🎥")
end
function PrintExplanation()
output.clear()
print("Each scene contains a built-in camera that you can move around")
print("It's part of an entity, so you can position it like any other entity")
print("Cameras also have settings like fieldOfView (basically a zoom)")
print("Access these on the camera component directly by calling camera:get(craft.camera) from your scene")
end
--# Viewers
-- Craft Viewers
function setup()
-- The code from the previous lessons, save Cameras (replaced below)
-- Some positions and sizes have been adjusted
yourScene = craft.scene()
cube = yourScene:entity()
size = vec3(1,1,1)
cube.model = craft.model.cube(size)
cube.material = craft.material("Materials:Standard")
cube.material.map = readImage("Blocks:Dirt")
cube.position = vec3(-3.03,-8.4,81.39)
cube.scale = vec3(136.13,0.6, 128.27)
cube.material.offsetRepeat = vec4(0,0,10,10)
robot = yourScene:entity()
robot.model = craft.model("Blocky Characters:Robot")
robot.position = vec3(4.55,-8.0,36.80)
robot.eulerAngles = vec3(0, 180, 0)
-- Hey let's add a trebuchet! Trebuchets are cool.
trebuchet = yourScene:entity()
trebuchet.model = craft.model("CastleKit:siegeTrebuchet")
trebuchet.eulerAngles = vec3(0, 180, 0)
trebuchet.position = vec3(-15.15,-8.66,100)
trebuchet.scale = vec3(1,1,1)*4.22
-- An OrbitViewer from Cameras (a dependency added via the + button)
-- parameters: (viewer type, target, distance, min dist, max dist)
local target = trebuchet.model.bounds.center
viewer = yourScene.camera:add(OrbitViewer, target, 30, 20, 100)
-- Activate sidebar controls
setParameters()
end
function updateScene()
-- Update the scene (physics, transforms etc)
yourScene:update(DeltaTime)
end
-- Called automatically by Codea
function draw()
-- For convenience scene updates can be a separate function
updateScene()
-- Draw the scene
yourScene:draw()
-- Do any 2D drawing last
drawStepName("Viewers 👀")
end
function setParameters()
-- Define this scene's individual sidebar controls
parameter.watch("Note")
Note = "You may need to scroll down to see all the lessons."
end
function PrintExplanation()
output.clear()
print("To simplify camera setup, Codea offers a couple pre-configured cameras or \"Viewers\"")
print("This scene uses OrbitViewer, which lets you control the camera with gestures. Try it!")
print("To use Viewers set the Cameras project as a dependency")
print("Also, because everyone needs a trebuchet, we added a trebuchet")
end
--# Sky
-- Craft Sky
function setup()
-- All the code from the previous lessons, adjusted here and there
yourScene = craft.scene()
cube = yourScene:entity()
size = vec3(1,1,1)
cube.model = craft.model.cube(size)
cube.material = craft.material("Materials:Standard")
cube.material.map = readImage("Blocks:Dirt")
cube.position = vec3(-3.03,-8.4,81.39)
cube.scale = vec3(136.13,0.6, 128.27)
cube.material.offsetRepeat = vec4(0,0,10,10)
robot = yourScene:entity()
robot.model = craft.model("Blocky Characters:Robot")
robot.position = vec3(31.42,-8.0,36.80)
robot.eulerAngles = vec3(0, 180, 0)
trebuchet = yourScene:entity()
trebuchet.model = craft.model("CastleKit:siegeTrebuchet")
trebuchet.eulerAngles = vec3(0, 180, 0)
trebuchet.position = vec3(-15.15,-8.66,100)
trebuchet.scale = vec3(1,1,1)*4.22
-- A wall made with a preset texture, just for the heck of it
wall = yourScene:entity()
wall.model = craft.model.cube(vec3(2,2,2))
wall.material = craft.material.preset("Surfaces:Basic Bricks")
wall.material.normalScale = vec2(-1,-1)
wall.material.offsetRepeat = vec4(4,4,3,3)
wall.eulerAngles = vec3(0, 180, 0)
wall.scale = vec3(68.71,13.09,6)
wall.position = vec3(-3,4.96,145.45)
-- A kludge used for having the viewer start in a nonstandard place
viewerKludge = yourScene:entity()
viewerKludge.position = vec3(42.513,-5.765,2.033)
viewer = yourScene.camera:add(OrbitViewer, viewerKludge.position, 0.005, 0.0005, 10000)
-- Viewer eulerAngles are set with .rx, .ry, .rz
viewer.rx = -10.75
viewer.ry = -24.125
-- Activate sidebar controls
setParameters()
end
function updateScene()
-- Update the scene (physics, transforms etc)
yourScene:update(DeltaTime)
end
-- Called automatically by Codea
function draw()
-- For convenience scene updates can be a separate function
updateScene()
-- Draw the scene
yourScene:draw()
-- 2D drawing goes here
drawStepName("Sky ☁️")
end
function setParameters()
-- Define this scene's individual sidebar controls
parameter.watch("DontPanic")
DontPanic = "The lesson buttons are still here! Just scroll down to see them."
parameter.boolean("SkyActive", true, function(b)
yourScene.sky.active = b
end)
parameter.color("SkyColor",
color(70, 151, 234, 255),
function(c)
yourScene.sky.material.sky = c
end)
parameter.color("Horizon",
color(152, 204, 223, 255),
function(c)
yourScene.sky.material.horizon = c
end)
parameter.color("Ground",
color(37, 37, 37, 255),
function(c)
yourScene.sky.material.ground = c
end)
local sunny = readText("Environments:Night")
local env = craft.cubeTexture(json.decode(sunny))
parameter.boolean("EnvMap", false, function(b)
if b then
yourScene.sky.material.envMap = env
else
yourScene.sky.material.envMap = nil
end
end)
parameter.color("CameraClearColor",
color(0, 0, 0, 255),
function(c)
-- Get the camera component to change camera settings
yourScene.camera:get(craft.camera).clearColor = c
end)
end
function PrintExplanation()
output.clear()
print("A custom sky is a powerful way to set the stage for a scene")
print("Craft's built-in sky is highly customizable on its own, and can also display pre-rendered images")
print("Play with the parameters above to see it in action")
print("If you've been through all the lessons, now you know the basics of Codea Craft!")
end
--# Main
-----------------------------------------
-- Learn Craft
-- Written by John Millard
-- Special thanks to Ignatz for the MultiStep project template
-----------------------------------------
-- Description:
-----------------------------------------
supportedOrientations(ANY)
displayMode(STANDARD)
function setup()
startTab("Scene")
setButtons()
end
function drawStepName(name)
fill(255, 255, 255, 255)
font("Inconsolata")
fontSize(40)
textAlign(LEFT)
textMode(CORNER)
text(name, 30, HEIGHT - 60)
end
function setButtons()
parameter.action("Scene 🎬", function () startTab("Scene") end)
parameter.action("Entities 👻", function () startTab("Entities") end)
parameter.action("Models 🤖", function () startTab("Models") end)
parameter.action("Cameras 🎥", function () startTab("Cameras") end)
parameter.action("Viewers 👀", function () startTab("Viewers") end)
parameter.action("Sky ☁️", function () startTab("Sky") end)
end
function startTab(tabName)
if cleanup then cleanup() end
parameter.clear()
loadstring(readProjectTab(tabName))()
if PrintExplanation then PrintExplanation() end
setup()
setButtons()
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment