Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Craft 2D Canvas/Drawing Example - A system to easily draw 2D images within a 3D space.

edited January 19 in Code Sharing Posts: 51

Add this component to an empty entity and it will create a plane, and an empty image with the resolution you desire as that plane's material map. It's really simple stuff, but it helps out when you want to add text that follows a character, etc. You can probably even make an entire game like this.

Just add the component, and call this in the draw function

yourCanvas:draw(function()
  -- do your drawing here
end)
canvas = class()

function canvas:init(entity,w,h,c)
    self.entity=entity
    entity.model = craft.model.plane(vec2(40,20))
    entity.material = craft.material(asset.builtin.Materials.Basic)
    entity.eulerAngles=vec3(-90,0,-180)
    entity.material.blendMode = NORMAL
    entity.w=w or 500
    entity.h=h or 200
    entity.w2=entity.w/2
    entity.h2=entity.h/2
    entity.bg=c
    entity.image=image(entity.w,entity.h)
    entity.material.map = entity.image

    self.entity.fill=function(entity)
        setContext(entity.image)
        background(entity.bg)
        fill(0, 0)
        stroke(0, 0)
        rectMode(CORNER)
        strokeWidth(8)
        rect(0,0,entity.h)
        setContext()
   end

    self.entity.draw=function(entity,cb)
        entity:fill()
        if cb~=nil then
            setContext(entity.image)
            cb()
            setContext()
        end
    end

    self.entity.obj=function(entity,obj)
        setContext(Canvas.image)
        obj:draw()
        setContext()
    end
end

In order to do the drawing, I usually just reuse some very simple functions.

--quick 2D
function drawRnd(x,y,w,h,c)
    pushStyle()
    w = w or 1
    h = h or 1
    c = c or color(255)
    fill(c)
    stroke(c)
    ellipse(x,y,w,h)
    popStyle()
end
function drawRect(x,y,w,h,c)
    pushStyle()
    w = w or 1
    h = h or 1
    c = c or color(255)
    fill(c)
    stroke(c)
    rect(x,y,w,h)
    popStyle()
end
function drawLine(x,y,w,h,c)
  pushStyle()
    w = w or nil
    h = h or nil
    c = c or color(255, 0, 0)
   -- fill(c)
    stroke(c)
    strokeWidth(1)
    line(x,y,w,h)
    popStyle()
end
function drawSprite(x,y,a)
    pushStyle()
    local x=x or WIDTH/2
    local y=y or HEIGHT/2
    sprite(a,x,y)
    popStyle()
end
function drawTextUI(x,y,words,c,s,fo)
    pushStyle()
    fo = fo or "SourceSansPro-Bold"
    font()
    s = s or 60
    fontSize(s)
    a = a or CENTER
    textAlign(a)
    c = c or color(255)
    fill(c)
    text(words, x, y)
    popStyle()
end

Anyways, have a good one! If you make any changes, please share them! i'd love to improve upon this functionality.

Tagged:

Comments

  • Posts: 298

    Thanks for your share, but how to use it?

    like this:

    function setup()
        -- Create a new craft scene
        scene = craft.scene()
    
        -- Create a new entity
        e = scene:entity()
        myCanvas = e:add(canvas,100,200,color(83, 80, 233))
    end
    
    function update(dt)
        -- Update the scene (physics, transforms etc)
        scene:update(dt)
    end
    
    -- Called automatically by codea 
    function draw()
        update(DeltaTime)
    
        -- Draw the scene
        scene:draw()    
        e:draw(12,23,10,10,color(227, 233, 80),drawRnd)
    end
    
    function drawRnd(x,y,w,h,c)
        pushStyle()
        w = w or 1
        h = h or 1
        c = c or color(255)
        fill(c)
        stroke(c)
        ellipse(x,y,w,h)
        popStyle()
    end
    

    I have not see the plane. I guess I wrote it wrong. Can you show the whole code? Thanks

  • edited January 19 Posts: 51

    You may have to rotate the plane, I have all my default scenes flipped due to personal preferences. Move the camera back as well.

    The only other thing I can see is where you call e:draw()

    I would do

        e:draw(function()
        --drawing here
        drawRnd(e.w2,e.h2,32,32,color(0,255,0,255)
        end)
    

    e.w2 being the width of the canvas image cut in half. @binaryblues

  • Posts: 51

    I'll post a detailed example in a moment! (:

  • edited January 19 Posts: 51

    You should see a white circle with a red background!

    function setup()
        -- Create a new craft scene
        scene = craft.scene()
    
        -- Create a new entity
        e=scene:entity()
    
        -- Add the canvas
        e:add(canvas,500,200,color(255, 0, 0))
    
        -- Move the camera forward and flip it.
        scene.camera.position=vec3(0,0,10)
        scene.camera.eulerAngles=vec3(0,-180,0)
    
        parameter.number("tx",-360,360)
        tx=-90
    end
    
    function update(dt)
        scene:update(dt)
        e.eulerAngles=vec3(tx,0,-180)
    end
    
    function draw()
        update(DeltaTime)
    
        -- Draw the scene
        scene:draw()
        -- Draw the canvas and the things with in it
        e:draw(function()
            drawRnd(e.w2,e.h2,32,32,color(255))
        end)
    end
    
  • Posts: 298

    @arismoko My guess is that it’s the camera settings. When you’re working with Craft 3D graphics, you can’t see anything if you change the camera parameters, so the best thing to do is to use all the camera parameters you’ve tested. I look forward to your complete example

  • Posts: 51

    @binaryblues bingo that's exactly what it was after I tested it for a bit :blush: i'll definitely keep that in mind for any future sharing i do

  • edited January 19 Posts: 298

    There is an easy way is to pack your project, send a compression package, will also avoid a lot of problems, the following is a demonstration of my operation.

    https://youtu.be/rTW21rUf_QU

    If you have dependencies in your project, the package will miss the dependencies, so you can first create a template based on the project, and then use the template, will automatically include the dependencies, which is what @Bri_G taught me, it worked like a charm.

  • Posts: 51

    I'm planning on releasing all the utilities I've made eventually so this will definitely come in handy, especially the part about packing the dependencies. So i'd take my large project with multiple dependencies and make a template using it, and then if I export that template my dependencies will remain? If i understand correctly, that should be easy. Thanks for the heads up! @binaryblues

  • Posts: 298

    @arismoko You need to create a new template based on your current project, which has been include the dependencies in it, then create a new project based on the template you made right now, then the new project will take the dependencies together when you export it

  • edited January 20 Posts: 313

    maybe this would really be the isometric solution i’m looking for

Sign In or Register to comment.