I get 630 frames compared to 1950 when now drawing the polygon at all, but this method is at least interesting. For the time being I adapted an algorithm that can draw any polygon (convex or concave).
This is it on its own. s[] is an array of sprites that represent the edge points. (note that your virtual resolution has to match your actual one)
drawSoftBody:
//calculate bounds
minID = 0
for i = 0 to pNm-1
if getSpriteY(s[i]) < getSpriteY(s[minID]) then minID = i
next i
maxID = 0
for i = 0 to pNm-1
if getSpriteY(s[i]) > getSpriteY(s[maxID]) then maxID = i
next i
minY = getSpriteY(s[minID])
maxY = getSpriteY(s[maxID])
minID = 0
for i = 0 to pNm-1
if getSpriteX(s[i]) < getSpriteX(s[minID]) then minID = i
next i
maxID = 0
for i = 0 to pNm-1
if getSpriteX(s[i]) > getSpriteX(s[maxID]) then maxID = i
next i
minX = getSpriteX(s[minID])
maxX = getSpriteX(s[maxID])
dim nodeX[pNm]
for pixelY = minY to maxY-1
nodes = 0
j = pNm-1 //build nodes
for i = 0 to pNm-1
if getSpriteY(s[i]) < pixelY and getSpriteY(s[j]) >= pixelY or getSpriteY(s[j]) < pixelY and getSpriteY(s[i]) >= pixelY
nodeX[nodes] = getSpriteX(s[i])+(pixelY+0.0-getSpriteY(s[i]))/(getSpriteY(s[j])-getSpriteY(s[i]))*(getSpriteX(s[j])-getSpriteX(s[i]))
nodes = nodes+1
endif
j = i
next i
i = 0 //sort nodes
while i < nodes-1
if nodeX[i] > nodeX[i+1]
swp = nodeX[i]
nodeX[i] = nodeX[i+1]
nodeX[i+1] = swp
if i <> 0 then i = i-1
else
i = i+1
endif
endwhile
stop = 0 //draw nodes (if in range)
for i = 0 to nodes-1 step 2
if nodeX[i] > maxX then stop = 1
if stop <> 1 //break if following nodes will exceed range
if nodeX[i+1] > minX
if nodeX[i] < minX then nodeX[i] = minX
if nodeX[i+1] > maxX then nodeX[i+1] = maxX
drawLine(nodeX[i], pixelY, nodeX[i+1], pixelY, 255, 255, 255) //nodeX[i+1]-1 ?
endif
endif
next i
next pixelY
return
and now here's the code as a whole. I can't seem to make the soft body any bigger or AppGameKit crashes... even if I change the physics scale :s
setSyncRate(0, 0)
setVirtualResolution(480, 480)
setPhysicsGravity(0, 0)
//setPhysicsDebugOn()
pNm = 64
pDis# = 15
type joint_UDT
pris
dis
endtype
dim s[pNm]
dim j[pNm] as joint_UDT
s = buildSoftBody(pNm, pDis#)
//obstacles
numOb = 30
for n = 0 to numOb-1
t = createSprite(0)
setSpriteSize(t, 25, 25)
setSpritePhysicsOn(t, 2)
setSpritePosition(t, random(0, 480-25), random(0, 480-25))
while sqrt((getSpriteX(t)-getVirtualWidth()/2.0)^2+(getSpriteY(t)-getVirtualHeight()/2.0)^2) < pDis#+25/2.0
setSpritePosition(t, random(0, 480-25), random(0, 480-25))
endwhile
next n
do
updateCharacter(s)
/*
for i = 1 to pNm-1
drawLine(getSpriteX(s[i])+getSpriteWidth(s[i])/2.0, getSpriteY(s[i])+getSpriteHeight(s[i])/2.0, getSpriteX(s[i-1])+getSpriteWidth(s[i-1])/2.0, getSpriteY(s[i-1])+getSpriteHeight(s[i-1])/2.0, 255, 255, 255)
next i
drawLine(getSpriteX(s[0])+getSpriteWidth(s[0])/2.0, getSpriteY(s[0])+getSpriteHeight(s[0])/2.0, getSpriteX(s[pNm-1])+getSpriteWidth(s[pNm-1])/2.0, getSpriteY(s[pNm-1])+getSpriteHeight(s[pNm-1])/2.0, 255, 255, 255)
*/
//gosub drawSoftBody
if getPointerPressed()
pDis# = pDIs#+1
resizeSoftBody(s, pNm, pDis#)
endif
print(screenFPS())
sync()
loop
/////////////////////////////
function buildSoftBody(particleNumber, particleDistance#)
s = createSprite(0)
setSpriteOffset(s, getSpriteWidth(s)/2.0, getSpriteHeight(s)/2.0)
setSpriteShape(s, 1) //circle
setSpriteSize(s, 4, 4)
setSpritePhysicsOn(s, 2)
setSpritePosition(s, getVirtualWidth()/2.0, getVirtualHeight()/2.0)
setSpriteVisible(s, 0)
for i = 0 to particleNumber-1
angle# =(2*3.14159265)/particleNumber*i;
posX# = getSpriteX(s)+particleDistance#*cos(toRad(angle#))+0.5
posY# = getSpriteY(s)+particleDistance#*sin(toRad(angle#))+0.5
s[i] = createSprite(0)
setSpriteOffset(s[i], getSpriteWidth(s[i])/2.0, getSpriteHeight(s[i])/2.0)
setSpriteShape(s[i], 1) //circle
setSpriteSize(s[i], 2, 2)
setSpritePhysicsOn(s[i], 2)
setSpritePosition(s[i], posX#, posY#)
setSpriteVisible(s[i], 0)
j[i].pris = createPrismaticJoint(s, s[i], getSpriteX(s)+getSpriteWidth(s)/2.0, getSpriteY(s)+getSpriteHeight(s)/2.0, cos(toRad(angle#))/5.0, sin(toRad(angle#))/5.0, 0)
setJointLimitOn(j[i].pris, particleDistance#-1, particleDistance#)
if i > 0
j[i].dis = createDistanceJoint(s[i], s[i-1], getSpriteX(s[i])+getSpriteWidth(s[i])/2.0, getSpriteY(s[i])+getSpriteHeight(s[i])/2.0, getSpriteX(s[i-1])+getSpriteWidth(s[i-1])/2.0, getSpriteY(s[i-1])+getSpriteHeight(s[i-1])/2.0, 0)
endif
if i = particleNumber-1
j[i].dis = createDistanceJoint(s[i], s[0], getSpriteX(s[i])+getSpriteWidth(s[i])/2.0, getSpriteY(s[i])+getSpriteHeight(s[i])/2.0, getSpriteX(s[0])+getSpriteWidth(s[i-1])/2.0, getSpriteY(s[0])+getSpriteHeight(s[i-1])/2.0, 0)
endif
next i
endfunction s
function resizeSoftBody(s, particleNumber, particleDistance#)
for i = 0 to particleNumber-1
angle# =(2*3.14159265)/particleNumber*i;
posX# = getSpriteX(s)+particleDistance#*cos(toRad(angle#))+0.5
posY# = getSpriteY(s)+particleDistance#*sin(toRad(angle#))+0.5
oldX# = getSpriteX(s[i])
oldY# = getSpriteY(s[i])
oldVX# = getSpritePhysicsVelocityX(s[i])
oldVY# = getSpritePhysicsVelocityY(s[i])
setSpritePosition(s[i], posX#, posY#)
deleteJoint(j[i].pris)
j[i].pris = createPrismaticJoint(s, s[i], getSpriteX(s)+getSpriteWidth(s)/2.0, getSpriteY(s)+getSpriteHeight(s)/2.0, cos(toRad(angle#))/5.0, sin(toRad(angle#))/5.0, 0)
setJointLimitOn(j[i].pris, particleDistance#-1, particleDistance#)
if i > 0
deleteJoint(j[i].dis)
j[i].dis = createDistanceJoint(s[i], s[i-1], getSpriteX(s[i])+getSpriteWidth(s[i])/2.0, getSpriteY(s[i])+getSpriteHeight(s[i])/2.0, getSpriteX(s[i-1])+getSpriteWidth(s[i-1])/2.0, getSpriteY(s[i-1])+getSpriteHeight(s[i-1])/2.0, 0)
endif
if i = particleNumber-1
deleteJoint(j[i].dis)
j[i].dis = createDistanceJoint(s[i], s[0], getSpriteX(s[i])+getSpriteWidth(s[i])/2.0, getSpriteY(s[i])+getSpriteHeight(s[i])/2.0, getSpriteX(s[0])+getSpriteWidth(s[i-1])/2.0, getSpriteY(s[0])+getSpriteHeight(s[i-1])/2.0, 0)
endif
//setSpritePosition(s[i], oldX#, oldY#)
setSpritePhysicsVelocity(s[i], oldVX#, oldVY#)
next i
endfunction
function updateCharacter(s)
modX# = 0
modY# = 0
ang# = 90-atanfull(-getPointerX()+getVirtualWidth()/2.0, -getPointerY()+getVirtualHeight()/2.0)
dis# = ((getPointerX()-getVirtualWidth()/2.0)^2+(getPointerY()-getVirtualHeight()/2.0)^2)^0.5
if dis# < 10 then dis# = 0
if dis# > 30 then dis# = 30
dis# = dis#/30.0
if ang# < 0 then ang# = ang#+360
modX# = cos(-ang#)*dis#
modY# = sin(-ang#)*dis#
setSpritePhysicsVelocity(s, getSpritePhysicsVelocityX(s)-modX#*60*getFrameTime()*60, getSpritePhysicsVelocityY(s)-modY#*60*getFrameTime()*60)
endfunction
drawSoftBody:
//calculate bounds
minID = 0
for i = 0 to pNm-1
if getSpriteY(s[i]) < getSpriteY(s[minID]) then minID = i
next i
maxID = 0
for i = 0 to pNm-1
if getSpriteY(s[i]) > getSpriteY(s[maxID]) then maxID = i
next i
minY = getSpriteY(s[minID])
maxY = getSpriteY(s[maxID])
minID = 0
for i = 0 to pNm-1
if getSpriteX(s[i]) < getSpriteX(s[minID]) then minID = i
next i
maxID = 0
for i = 0 to pNm-1
if getSpriteX(s[i]) > getSpriteX(s[maxID]) then maxID = i
next i
minX = getSpriteX(s[minID])
maxX = getSpriteX(s[maxID])
dim nodeX[pNm]
for pixelY = minY to maxY-1
nodes = 0
j = pNm-1 //build nodes
for i = 0 to pNm-1
if getSpriteY(s[i]) < pixelY and getSpriteY(s[j]) >= pixelY or getSpriteY(s[j]) < pixelY and getSpriteY(s[i]) >= pixelY
nodeX[nodes] = getSpriteX(s[i])+(pixelY+0.0-getSpriteY(s[i]))/(getSpriteY(s[j])-getSpriteY(s[i]))*(getSpriteX(s[j])-getSpriteX(s[i]))
nodes = nodes+1
endif
j = i
next i
i = 0 //sort nodes
while i < nodes-1
if nodeX[i] > nodeX[i+1]
swp = nodeX[i]
nodeX[i] = nodeX[i+1]
nodeX[i+1] = swp
if i <> 0 then i = i-1
else
i = i+1
endif
endwhile
stop = 0 //draw nodes (if in range)
for i = 0 to nodes-1 step 2
if nodeX[i] > maxX then stop = 1
if stop <> 1 //break if following nodes will exceed range
if nodeX[i+1] > minX
if nodeX[i] < minX then nodeX[i] = minX
if nodeX[i+1] > maxX then nodeX[i+1] = maxX
drawLine(nodeX[i], pixelY, nodeX[i+1], pixelY, 255, 255, 255) //nodeX[i+1]-1 ?
endif
endif
next i
next pixelY
return
function toRad(num#)
out# = num#/3.1415926589*180
endfunction out#
I'll have to give that sprite technique a try too