Last active
December 21, 2015 03:09
-
-
Save juaxix/6240100 to your computer and use it in GitHub Desktop.
Destructible Terrain and water fluids
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- destructable | |
-- Use this function to perform your initial setup | |
function setup() | |
parameter.boolean("addWater",false) | |
defaultGravity = physics.gravity() | |
parameter.boolean("useGravity",false, function(v) | |
if v then | |
physics.gravity(Gravity) | |
else | |
physics.gravity(defaultGravity) | |
end | |
end) | |
parameter.watch("#balls") | |
txture = readImage("Documents:ExampleCircle",5,5) | |
ter = Terrain(vec2(WIDTH/2,HEIGHT/4),vec2(WIDTH,HEIGHT/2)) | |
circ = physics.body(CIRCLE,15) | |
circ.position = vec2(WIDTH/2,600) | |
holding = nil | |
setupWater() | |
bgImg = readImage("SpaceCute:Background") | |
end | |
function touched(touch) | |
if addWater then | |
WaterTouched(touch) | |
else | |
TerrainTouched(touch) | |
end | |
end | |
function TerrainTouched(t) | |
local tp = vec2(t.x,t.y) | |
local cp = circ.position | |
if t.state == BEGAN and tp:dist(cp) < 30 then | |
holding = tp | |
end | |
if t.state == MOVING and holding ~= nil then | |
holding = tp | |
end | |
if t.state == ENDED and holding ~= nil then | |
holding = nil | |
end | |
if holding == nil then | |
ter:touched(t) | |
end | |
end | |
-- This function gets called once every frame | |
function draw() | |
if useGravity then | |
physics.gravity(Gravity) | |
end | |
--background(127, 127, 127, 255) | |
background(255) | |
sprite(bgImg, WIDTH/2, HEIGHT/2, WIDTH, HEIGHT) | |
-- This sets the line thickness | |
strokeWidth(5) | |
if holding ~= nil then | |
circ:applyForce(holding-circ.position-circ.linearVelocity/4) | |
end | |
-- Do your drawing here | |
ter:draw() | |
waterDraw() | |
sprite("Documents:ExampleCircle",circ.x,circ.y,circ.radius*2.5) | |
end | |
function setupWater() | |
m = {} | |
m.shader = shader(vS, fS) | |
Number_of_Balls = 500 | |
Metaball_Resolution = 211 | |
Metaball_Size = 50 | |
function GENERATE_METABALL() | |
local mr = Metaball_Resolution | |
local ms = Metaball_Size | |
blendMode(NORMAL) | |
ballTex = image(166, 166) | |
local a,d2,ref2 | |
ref2 = ms*ms/15 | |
for i = 1,166 do | |
for j =1,166 do | |
d2 = (i-100)*(i-100) + (j-100)*(j-100) | |
a = math.exp(-d2/ref2)*255 | |
ballTex:set(i,j,color(a,a,a,255)) | |
end | |
end | |
end | |
GENERATE_METABALL() | |
balls = {} | |
img = image(WIDTH, HEIGHT) | |
m = mesh() | |
r = m:addRect(WIDTH / 2, HEIGHT / 2, WIDTH, HEIGHT) | |
m:setRectTex(r, 0, 0, 1, 1) | |
m.texture = img | |
m.shader = shader(vS, fS) | |
--soft = SoftBody() | |
end | |
function createDrop(x,y) | |
local ball = physics.body(CIRCLE, 6) | |
--ball.type = DYNAMIC | |
ball.x = x | |
ball.y = y | |
ball.restitution = .1 | |
ball.linearVelocity = vec2(0,0) | |
ball.friction = 0.05 | |
ball.mass = 0.1 | |
ball.angularVelocity = 0.0 | |
ball.bullet = false | |
ball.linearDamping = 0 | |
return ball | |
end | |
function waterDraw() | |
-- remove invisible balls... here to avoid flickering | |
for k,b in ipairs(balls) do | |
if b.x+Metaball_Size> WIDTH +Metaball_Size *2 or b.x<-Metaball_Size then | |
table.remove(balls, k) | |
b:destroy() | |
end | |
end | |
blendMode(NORMAL) | |
setContext(img) | |
background(0) -- clear buffer | |
--tint(139, 145, 157, 255) | |
blendMode(ADDITIVE) | |
for k,b in ipairs(balls) do | |
sprite(ballTex, b.x, b.y) | |
end | |
--noTint() | |
setContext() | |
m.texture = img | |
blendMode(MULTIPLY) | |
m:draw() | |
end | |
function WaterTouched(touch) | |
if touch.state == BEGAN or touch.state == MOVING then | |
if balls[Number_of_Balls + 1] == nil then | |
local ball = createDrop(touch.x,touch.y) | |
table.insert(balls, ball) | |
else | |
balls[Number_of_Balls + 1].x = touch.x | |
balls[Number_of_Balls + 1].y = touch.y | |
end | |
end | |
end | |
vS = [[ | |
// | |
// A basic vertex shader | |
// | |
//This is the current model * view * projection matrix | |
// Codea sets it automatically | |
uniform mat4 modelViewProjection; | |
//This is the current mesh vertex position, color and tex coord | |
// Set automatically | |
attribute vec4 position; | |
attribute vec4 color; | |
attribute vec2 texCoord; | |
//This is an output variable that will be passed to the fragment shader | |
varying lowp vec4 vColor; | |
varying highp vec2 vTexCoord; | |
void main() | |
{ | |
//Pass the mesh color to the fragment shader | |
vColor = color; | |
vTexCoord = texCoord; | |
//Multiply the vertex position by our combined transform | |
gl_Position = modelViewProjection * position; | |
} | |
]] | |
fS = [[ | |
// | |
// A basic fragment shader | |
// | |
//Default precision qualifier | |
precision highp float; | |
//This represents the current texture on the mesh | |
uniform lowp sampler2D texture; | |
//The interpolated vertex color for this fragment | |
varying lowp vec4 vColor; | |
//The interpolated texture coordinate for this fragment | |
varying highp vec2 vTexCoord; | |
void main() | |
{ | |
//Sample the texture at the interpolated coordinate | |
lowp vec4 col = texture2D( texture, vTexCoord ) * vColor; | |
//Set the output color to the texture color | |
if (max(col.r, max(col.g, col.b)) > 0.75) | |
{ | |
gl_FragColor = vec4(0.0, 0.0, 1.0, 1.0); | |
} | |
else | |
{ | |
gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0); | |
} | |
} | |
]] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Terrain = class() | |
function Terrain:init(pos,size) | |
self.pos = pos | |
self.size = size | |
local verts = {} | |
for x=1,20 do | |
table.insert(verts,vec2(pos.x-size.x/2+(size.x/20)*x,pos.y+size.y/2)) | |
end | |
for y=1,20 do | |
table.insert(verts,vec2(pos.x+size.x/2,pos.y+size.y/2-(size.y/20)*y)) | |
end | |
for x=1,20 do | |
table.insert(verts,vec2(pos.x+size.x/2-(size.x/20)*x,pos.y-size.y/2)) | |
end | |
for y=1,20 do | |
table.insert(verts,vec2(pos.x-size.x/2,pos.y-size.y/2+(size.y/20)*y)) | |
end | |
self.verts = verts | |
self.m = mesh() | |
self.m:setColors(255,255,255,255) | |
self.m.vertices = triangulate(verts) | |
self.floor = physics.body(POLYGON,unpack(verts)) | |
self.floor.type = STATIC | |
self.bound = 30 | |
self.oe = ElapsedTime | |
end | |
function Terrain:draw() | |
if ElapsedTime > self.oe+0.2 then | |
self.oe = ElapsedTime | |
if self.t then | |
self.m.vertices = triangulate(self.verts) | |
self.floor:destroy() | |
self.floor = physics.body(POLYGON,unpack(self.verts)) | |
self.floor.type = STATIC | |
end | |
end | |
self.m:draw() | |
local sv = self.verts | |
for i=1,#sv do | |
sprite(txture,sv[i].x,sv[i].y,5,5) | |
end | |
pushStyle() | |
fill(0,255) | |
text(math.floor(1/DeltaTime).."FPS",100,600) | |
popStyle() | |
end | |
function Terrain:touched(t) | |
self.t = true | |
if t.state == ENDED then | |
self.t = false | |
end | |
local p,s = self.pos,self.size | |
local tp = vec2(t.x,t.y) | |
local sp = #self.verts | |
for i=1,sp do | |
local sv = self.verts[i] | |
local svi | |
if i > 1 then | |
svi = self.verts[i-1] | |
else | |
svi = self.verts[sp] | |
end | |
if not sv then return end | |
local pass = true | |
if sv:dist(tp) < self.bound then | |
local dir = (sv-tp):normalize()*5+vec2(t.deltaX,t.deltaY) | |
for ii=1,sp do | |
if i ~= ii then | |
local tsv = self.verts[ii] | |
if tsv:dist(sv+dir) < self.bound/2 then | |
pass = false | |
end | |
end | |
end | |
--pass = true | |
if pass then | |
self.verts[i] = self.verts[i] + dir | |
end | |
end | |
if sv:dist(svi) > self.bound*2 and pass then | |
local d = (sv+svi)/2 | |
if d.x > p.x-s.x/2 and d.x < p.x+s.x/2 and d.y > p.y-s.y/2 then | |
table.insert(self.verts,i,d) | |
else | |
table.remove(self.verts,i) | |
return | |
end | |
elseif sv:dist(svi) < self.bound/2 then | |
table.remove(self.verts,i) | |
return | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment