Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Mini Polygon Maker
#1
[Image: bIl2Y.gif]


Code:
'======================
'
' Mini Polygon Maker
'
'======================

#win32
set window "Mini Polygon Maker", 850, 600
set redraw off

constant GRID_SIZE = 40      

visible vertices = []          ' [x0,y0,x1,y1,...]
visible selected = -1          ' index of selected vertex (-1 = none)
visible isDrag = false,dragX = 0, dragY = 0, isLeft = 0, isRight = 0
visible showCode = false, codeLines = []
visible centerX = 320, centerY = 240 'polygon center on screen


'-----------
' Main Loop
'-----------
while not keydown(KEY_ESCAPE, true)
    interact()
    render()
    redraw
    fwait 60
wend


'-----------
' Functions
'-----------
function interact()
    ' mouse interaction
    mx = mousex(); my = mousey()
    leftDown = mousebutton(0) ; rightDown = mousebutton(1)
   
    ' Only process clicks inside canvas
    if mx < 0 or mx >= 640 or my < 0 or my >= 600 then return
   
    ' Left click: add vertex OR select/drag vertex
    if leftDown and not isLeft then
        nearVertex = findNearestVertex(mx, my, 10)
       
        if nearVertex >= 0 then
            ' Drag individual vertex
            selected = nearVertex
            isDrag = true
            dragX = mx - vertices[selected*2]
            dragY = my - vertices[selected*2 + 1]
        else
            ' Add new vertex
            vx = mx ; vy = my
            vx = snapValue(vx, GRID_SIZE) ; vy = snapValue(vy, GRID_SIZE)
            vx = clamp(vx, 0, 639); vy = clamp(vy, 0, 599)
            id = sizeof(vertices)
            vertices[id] = vx
            vertices[id + 1] = vy
            selected = -1
        endif
    endif
   
    ' Right click: delete nearest vertex or deselect
    if rightDown and not isRight then
        if selected >= 0 then
            deleteVertex(selected)
            selected = -1
        else
            id = findNearestVertex(mx, my, 15)
            if id >= 0 then
                deleteVertex(id)
            endif
        endif
    endif
   
    ' Mouse move: vertex dragging
    if isDrag and selected >= 0 and leftDown then
        nx = mx - dragX ; ny = my - dragY
        nx = snapValue(nx, GRID_SIZE); ny = snapValue(ny, GRID_SIZE)
        vertices[selected*2] = clamp(nx, 0, 639)
        vertices[selected*2 + 1] = clamp(ny, 0, 599)
    endif
   
    ' Release mouse: stop dragging and auto-deselect
    if not leftDown then
        if isDrag then selected = -1 
        isDrag = false
    endif
   
    ' Control Keys
    if keydown(KEY_C, true) then clearCanvas()
    if keydown(KEY_S, true) then
        if showCode then
            showCode = false
        else
            generateCode()
        endif
    endif
   
    isLeft = leftDown
    isRight = rightDown
endfunc

function render()
    ' Clear screen
    set color 0, 0, 0; cls
      
    ' Draw grid
    set color 100, 100, 100
    for gx = 0 to 640 step GRID_SIZE  draw line gx, 0, gx, 600
    for gy = 0 to 600 step GRID_SIZE  draw line 0, gy, 640, gy
   
    ' Draw filled polygon
    vcount = sizeof(vertices)/2
    if vcount >= 3 then
        set color 100, 100, 255, 80
        polyArgs = []
        for i = 0 to vcount - 1
            polyArgs[sizeof(polyArgs)] = vertices[i*2]
            polyArgs[sizeof(polyArgs)] = vertices[i*2 + 1]
        next
        draw poly polyArgs, true
    endif
   
    ' Draw polygon edges
    if vcount >= 2 then
        set color 200, 200, 255
        for i = 0 to vcount - 1
            j = (i + 1) % vcount
            x1 = vertices[i*2]
            y1 = vertices[i*2 + 1]
            x2 = vertices[j*2]
            y2 = vertices[j*2 + 1]
            draw line x1, y1, x2, y2
        next
    endif
   
    ' Draw vertices
    if vcount > 0 then
        for i = 0 to vcount - 1
            vx = vertices[i*2]
            vy = vertices[i*2 + 1]
            if i = selected then
                set color 255, 255, 100
                draw ellipse vx, vy, 10, 10, true
            endif
            set color 255, 100, 100; draw ellipse vx, vy, 6, 6, true
            set color 0, 0, 0 ;      draw ellipse vx, vy, 4, 4, true
        next
    endif
   
    ' Infobox
    set color 50, 50, 50; draw rect 640, 0, 260, 600, true
    set color 255, 255, 255 ; set caret 648, 10
    wln "==================="
    wln "      INFOBOX"
    wln "==================="
    wln
    wln "Mini Polygon Maker"
    wln "One Polygon only"
    wln "Add vertex in sequence"
    wln "Min 3 vertex"
    wln
    wln
    wln "LEFT CLICK:"
    wln "- Add vertex"
    wln "- Drag to move"
    wln
    wln
    wln "RIGHT CLICK:"
    wln "- Delete vertex"
    wln
    wln
    wln "C: Clear canvas"
    wln "S: Show/Hide code"
    wln
    wln "ESC: Exit"
   
    ' Show Code Overlay
    if showCode then
        set color 50, 50, 50;draw rect 30, 50, 750, 500, true
        set color 200, 200, 200;draw rect 30, 50, 750, 500, false
       
        set color 200, 255, 200;set caret 75,95
        for i = 0 to sizeof(codeLines) - 1  wln codeLines[i]
       
        set color 255, 255, 0; set caret 75, 400
        wln "Code generated & copied to clipboard"
        wln "Open your NED, and paste the code from clipboard"
        wln "Press S to close this window"
    endif
endfunc

function findNearestVertex(tx, ty, maxDist)
    if sizeof(vertices) = 0 then return -1
   
    bestid = -1
    bestDistSqr = maxDist * maxDist
    vcount = sizeof(vertices)/2
    for i = 0 to vcount - 1
        dx = vertices[i*2] - tx
        dy = vertices[i*2 + 1] - ty
        dSqr = dx*dx + dy*dy
        if dSqr < bestDistSqr then
            bestDistSqr = dSqr
            bestid = i
        endif
    next
    return bestid
endfunc

function deleteVertex(id)
    newVerts = []
    vcount = sizeof(vertices)/2
    for i = 0 to vcount - 1
        if i <> id then
            nid = sizeof(newVerts)
            newVerts[nid] = vertices[i*2]
            newVerts[nid + 1] = vertices[i*2 + 1]
        endif
    next
    vertices = newVerts
   
    if selected = id then
        selected = -1
    elseif selected > id then
        selected = selected - 1
    endif
endfunc

function clamp(value, minVal, maxVal)
    return max(minVal, min(value, maxVal))
endfunc

function snapValue(value, gridSize)
    return int(value / gridSize + 0.5) * gridSize
endfunc

function clearCanvas()
    vertices = []
    selected = -1
endfunc

function generateCode()
    if sizeof(vertices) < 6 then return
   
    vcount = sizeof(vertices)/2
   
    ' Find bounding box
    minX = vertices[0];  maxX = vertices[0]
    minY = vertices[1];  maxY = vertices[1]
    for i = 0 to vcount - 1
        vx = vertices[i*2]
        vy = vertices[i*2 + 1]
        minX = min(minX, vx)
        maxX = max(maxX, vx)
        minY = min(minY, vy)
        maxY = max(maxY, vy)   
    next
   
    'polygon center
    offX = centerX - (minX + maxX) / 2
    offY = centerY - (minY + maxY) / 2
   
    ' Build vertex array string
    vertStr = ""
    for i = 0 to vcount - 1
        nx = int(vertices[i*2] + offX + 0.5)
        ny = int(vertices[i*2 + 1] + offY + 0.5)
        vertStr = vertStr + nx + "," + ny
        if i < vcount - 1 then vertStr = vertStr + ", "
    next
   
    ' codeLines
    codeLines[0] = "#win32"
    codeLines[1] = "set window "+chr(34)+"Polygon"+chr(34)+",640, 480"
    codeLines[2] = "set redraw off"
    codeLines[3] = ""
    codeLines[4] = "' polygon"
    codeLines[5] = "polyVerts = [" + vertStr + "]"
    codeLines[6] = ""
    codeLines[7] = "while not keydown(KEY_ESCAPE, true)"
    codeLines[8] = "    set color 0, 0, 0"
    codeLines[9] = "    cls"
    codeLines[10] = "    "
    codeLines[11] = "    set color 100, 255, 100"
    codeLines[12] = "    draw poly polyVerts, true"
    codeLines[13] = "    "
    codeLines[14] = "    redraw"
    codeLines[15] = "    fwait 60"
    codeLines[16] = "wend"
   
    ' code string with CRLF
    N = chr(13) + chr(10)
    codeStr = codeLines[0] + N
    for i = 1 to 15  codeStr = codeStr + codeLines[i] + N
    codeStr = codeStr + codeLines[16]
   
    ' copies to clipboard
    set clipboard codeStr
   
    showCode = true
endfunc
Reply
#2
Had a look at this during a break at work Smile  Very nice program, well done! But here's a small fix to make adding points and drawing easier (in my opinion, atleast), I've marked the changes with "Marcus":

Code:
'======================
'
' Mini Polygon Maker
'
'======================

#win32
set window "Mini Polygon Maker", 850, 600
set redraw off

constant GRID_SIZE = 40    

visible vertices = []          ' [x0,y0,x1,y1,...]
visible selected = -1          ' index of selected vertex (-1 = none)
visible isDrag = false,dragX = 0, dragY = 0, isLeft = 0, isRight = 0
visible showCode = false, codeLines = []
visible centerX = 320, centerY = 240 'polygon center on screen


'-----------
' Main Loop
'-----------
while not keydown(KEY_ESCAPE, true)
    interact()
    render()
    redraw
    fwait 60
wend


'-----------
' Functions
'-----------
function interact()
    ' mouse interaction
    mx = mousex(); my = mousey()
    leftDown = mousebutton(0) ; rightDown = mousebutton(1)

    ' Only process clicks inside canvas
    if mx < 0 or mx >= 640 or my < 0 or my >= 600 then return

    ' Left click: add vertex OR select/drag vertex
    if leftDown and not isLeft then
        nearVertex = findNearestVertex(mx, my, 10)
    
        if nearVertex >= 0 then
            ' Drag individual vertex
            selected = nearVertex
            isDrag = true
            dragX = mx - vertices[selected*2]
            dragY = my - vertices[selected*2 + 1]
        else
            ' Add new vertex
            vx = mx ; vy = my
            vx = snapValue(vx, GRID_SIZE) ; vy = snapValue(vy, GRID_SIZE)
            vx = clamp(vx, 0, 639); vy = clamp(vy, 0, 599)
            ' Marcus: if vertex count is greater than three, split the closest edge instead of
            ' adding last.
            count = sizeof(vertices)/2
            if count >= 3
                ' find index where vertex should be added.
                minIndex = unset;  mind = unset
                for i = 0 to count - 1
                    j = (i + 1)%count
                    ' project point on edge between vertex i and j.
                    ax = vertices[i*2];  ay = vertices[i*2 + 1]
                    bx = vertices[j*2];  by = vertices[j*2 + 1]
                    t = ((vx - ax)*(bx - ax) + (vy - ay)*(by - ay))/((bx - ax)^2 + (by - ay)^2)
                    ' clamp.
                    t = min(max(t, 0), 1)
                    ' closest point on edge and distance to it from vx, vy.
                    cx = ax + t*(bx - ax);  cy = ay + t*(by - ay)
                    d = (vx - cx)^2 + (vy - cy)^2
                    ' first or closest?
                    if minIndex = unset or d < mind
                        minIndex = j
                        mind = d
                    endif
                next
                ' insert.
                insert vertices, minIndex*2, vy
                insert vertices, minIndex*2, vx
                selected = -1
            else
                id = sizeof(vertices)
                vertices[id] = vx
                vertices[id + 1] = vy
                selected = -1
            endif
        endif
    endif

    ' Right click: delete nearest vertex or deselect
    if rightDown and not isRight then
        if selected >= 0 then
            deleteVertex(selected)
            selected = -1
        else
            id = findNearestVertex(mx, my, 15)
            if id >= 0 then
                deleteVertex(id)
            endif
        endif
    endif

    ' Mouse move: vertex dragging
    if isDrag and selected >= 0 and leftDown then
        nx = mx - dragX ; ny = my - dragY
        nx = snapValue(nx, GRID_SIZE); ny = snapValue(ny, GRID_SIZE)
        vertices[selected*2] = clamp(nx, 0, 639)
        vertices[selected*2 + 1] = clamp(ny, 0, 599)
    endif

    ' Release mouse: stop dragging and auto-deselect
    if not leftDown then
        if isDrag then selected = -1
        isDrag = false
    endif

    ' Control Keys
    if keydown(KEY_C, true) then clearCanvas()
    if keydown(KEY_S, true) then
        if showCode then
            showCode = false
        else
            generateCode()
        endif
    endif

    isLeft = leftDown
    isRight = rightDown
endfunc

function render()
    ' Clear screen
    set color 0, 0, 0; cls
    
    ' Draw grid
    set color 100, 100, 100
    for gx = 0 to 640 step GRID_SIZE  draw line gx, 0, gx, 600
    for gy = 0 to 600 step GRID_SIZE  draw line 0, gy, 640, gy

    ' Draw filled polygon
    vcount = sizeof(vertices)/2
    if vcount >= 3 then
        set color 100, 100, 255, 80
        polyArgs = []
        for i = 0 to vcount - 1
            polyArgs[sizeof(polyArgs)] = vertices[i*2]
            polyArgs[sizeof(polyArgs)] = vertices[i*2 + 1]
        next
        draw poly polyArgs, true
    endif

    ' Draw polygon edges
    if vcount >= 2 then
        set color 200, 200, 255
        for i = 0 to vcount - 1
            j = (i + 1) % vcount
            x1 = vertices[i*2]
            y1 = vertices[i*2 + 1]
            x2 = vertices[j*2]
            y2 = vertices[j*2 + 1]
            draw line x1, y1, x2, y2
        next
    endif

    ' Draw vertices
    if vcount > 0 then
        for i = 0 to vcount - 1
            vx = vertices[i*2]
            vy = vertices[i*2 + 1]
            if i = selected then
                set color 255, 255, 100
                draw ellipse vx, vy, 10, 10, true
            endif
            set color 255, 100, 100; draw ellipse vx, vy, 6, 6, true
            set color 0, 0, 0 ;      draw ellipse vx, vy, 4, 4, true
        next
    endif

    ' Infobox
    set color 50, 50, 50; draw rect 640, 0, 260, 600, true
    set color 255, 255, 255 ; set caret 648, 10
    wln "==================="
    wln "      INFOBOX"
    wln "==================="
    wln
    wln "Mini Polygon Maker"
    wln "One Polygon only"
    wln "Add vertex in sequence"
    wln "Min 3 vertex"
    wln
    wln
    wln "LEFT CLICK:"
    wln "- Add vertex"
    wln "- Drag to move"
    wln
    wln
    wln "RIGHT CLICK:"
    wln "- Delete vertex"
    wln
    wln
    wln "C: Clear canvas"
    wln "S: Show/Hide code"
    wln
    wln "ESC: Exit"

    ' Show Code Overlay
    if showCode then
        set color 50, 50, 50;draw rect 30, 50, 750, 500, true
        set color 200, 200, 200;draw rect 30, 50, 750, 500, false
    
        set color 200, 255, 200;set caret 75,95
        for i = 0 to sizeof(codeLines) - 1  wln codeLines[i]
    
        set color 255, 255, 0; set caret 75, 400
        wln "Code generated & copied to clipboard"
        wln "Open your NED, and paste the code from clipboard"
        wln "Press S to close this window"
    endif
endfunc

function findNearestVertex(tx, ty, maxDist)
    if sizeof(vertices) = 0 then return -1

    bestid = -1
    bestDistSqr = maxDist * maxDist
    vcount = sizeof(vertices)/2
    for i = 0 to vcount - 1
        dx = vertices[i*2] - tx
        dy = vertices[i*2 + 1] - ty
        dSqr = dx*dx + dy*dy
        if dSqr < bestDistSqr then
            bestDistSqr = dSqr
            bestid = i
        endif
    next
    return bestid
endfunc

function deleteVertex(id)
    newVerts = []
    vcount = sizeof(vertices)/2
    for i = 0 to vcount - 1
        if i <> id then
            nid = sizeof(newVerts)
            newVerts[nid] = vertices[i*2]
            newVerts[nid + 1] = vertices[i*2 + 1]
        endif
    next
    vertices = newVerts

    if selected = id then
        selected = -1
    elseif selected > id then
        selected = selected - 1
    endif
endfunc

function clamp(value, minVal, maxVal)
    return max(minVal, min(value, maxVal))
endfunc

function snapValue(value, gridSize)
    return int(value / gridSize + 0.5) * gridSize
endfunc

function clearCanvas()
    vertices = []
    selected = -1
endfunc

function generateCode()
    if sizeof(vertices) < 6 then return

    vcount = sizeof(vertices)/2

    ' Find bounding box
    minX = vertices[0];  maxX = vertices[0]
    minY = vertices[1];  maxY = vertices[1]
    for i = 0 to vcount - 1
        vx = vertices[i*2]
        vy = vertices[i*2 + 1]
        minX = min(minX, vx)
        maxX = max(maxX, vx)
        minY = min(minY, vy)
        maxY = max(maxY, vy)
    next

    'polygon center
    ' Marcus: better if polygon is centered around 0, 0.
    ' offX = centerX - (minX + maxX) / 2
    ' offY = centerY - (minY + maxY) / 2
    offX = -(minX + maxX) / 2
    offY = -(minY + maxY) / 2
    

    ' Build vertex array string
    vertStr = ""
    for i = 0 to vcount - 1
        nx = int(vertices[i*2] + offX + 0.5)
        ny = int(vertices[i*2 + 1] + offY + 0.5)
        vertStr = vertStr + nx + "," + ny
        if i < vcount - 1 then vertStr = vertStr + ", "
    next

    ' codeLines
    codeLines[0] = "#win32"
    codeLines[1] = "set window "+chr(34)+"Polygon"+chr(34)+",640, 480"
    codeLines[2] = "set redraw off"
    codeLines[3] = ""
    codeLines[4] = "' polygon"
    codeLines[5] = "polyVerts = [" + vertStr + "]"
    codeLines[6] = ""
    codeLines[7] = "while not keydown(KEY_ESCAPE, true)"
    codeLines[8] = "    set color 0, 0, 0"
    codeLines[9] = "    cls"
    codeLines[10] = "    "
    codeLines[11] = "    set color 100, 255, 100"
    ' Marcus: use 'draw poly xform' instead
    ' codeLines[12] = "    draw poly polyVerts, true"
    codeLines[12] = "    draw poly xform polyVerts, 320, 240, 1, 1, 0, 0, 0, true"
    codeLines[13] = "    "
    codeLines[14] = "    redraw"
    codeLines[15] = "    fwait 60"
    codeLines[16] = "wend"

    ' code string with CRLF
    N = chr(13) + chr(10)
    codeStr = codeLines[0] + N
    for i = 1 to 15  codeStr = codeStr + codeLines[i] + N
    codeStr = codeStr + codeLines[16]

    ' copies to clipboard
    set clipboard codeStr

    showCode = true
endfunc
Reply
#3
Very cool... It's even easy for 'me' to use... lol
Logic is the beginning of wisdom.
Reply
#4
Very nice indeed - this will be very useful. Many thanks.
Reply
#5
Creating games in Naalaa is a lot of fun because there are many resources available to facilitate game development.

A. Tools:
- NED: The Naalaa Editor, an IDE for writing Naalaa code.
- Enginea Editor: A sector (room)-based 3D game engine.
- Tilemap Editor: Used to create maps that the tilemap library can load.
- nPixel: A pixel image editor by Johnno and Kevin.
  https://www.naalaa.com/forum/thread-191....ght=nPixel
- Mini Polygon Maker: Used to create simple polygons. Big Grin
  https://www.naalaa.com/forum/thread-398-...ml#pid2722

B. Code Examples:
- 27 basic examples
- 17 demo examples
- 20 game examples
- Over 100 function examples
- Over 50 other examples
- Online forum https://www.naalaa.com/forum/index.php
- Many examples demonstrating how to use various libraries:
  Enginea, Highscore, OHS, Polyline, S3D, SFX, Tilemap, and Wolf3D.

C. Documentation:
- Enginea Tutorial (pdf)
- N7 Reference (pdf)
- S3D (pdf)
- Tilemap (pdf)
- Online Reference: https://naalaa.com/autodoc/index.html
Reply


Forum Jump:


Users browsing this thread: 2 Guest(s)