Bouncing Ball// source http://jsbin.com/lagahi
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
<html> | |
<head> | |
<title>Bouncing Ball</title> | |
<script data-pace-options='{ "eventLag": false }' src="https://cdnjs.cloudflare.com/ajax/libs/pace/1.0.2/pace.min.js"></script> | |
<style> | |
.pace .pace-progress { height:4px; background:#88f; position:fixed; z-index:9999; top:0; right:100%; width:100%; } | |
.pace-inactive { display:none; } | |
.pace { -webkit-pointer-events:none; pointer-events:none; -webkit-user-select:none; -moz-user-select:none; user-select:none; } | |
</style> | |
</head> | |
<body style=" margin:0; padding:0; border:0; overflow:hidden; background:#000;"> | |
<script id="gamecake_init_lua" type="text/lua" >--<![CDATA[ | |
-- grab some libs | |
local pack=require("wetgenes.pack") -- raw memory packing | |
local wstr=require("wetgenes.string") -- string helpers | |
local tardis=require("wetgenes.tardis") -- matrix/vector math | |
-- a window/screen handler this works in windows/linux/nacl/android/raspi | |
local win=require("wetgenes.win").create({}) | |
-- wrap some extra shader compiler functions around a basic gles2 library | |
local gl=require("glescode").create( assert(require("gles").gles2) ) | |
-- source code for a simple a shader, the name= are just for debuging | |
local prog_color= | |
{ | |
name="prog_color", | |
vshaders= | |
{{ | |
name="vtx_color", | |
source=[[ | |
{shaderprefix} | |
uniform mat4 modelview; | |
uniform mat4 projection; | |
attribute vec3 vertex; | |
uniform vec4 color; | |
varying vec4 v_color; | |
void main() | |
{ | |
gl_Position = projection * modelview * vec4(vertex, 1.0); | |
v_color=color; | |
} | |
]] | |
}}, | |
fshaders= | |
{{ | |
name="frg_color", | |
source=[[ | |
{shaderprefix} | |
varying vec4 v_color; | |
void main(void) | |
{ | |
gl_FragColor=v_color ; | |
} | |
]] | |
}}, | |
} | |
-- an amiga ball | |
local function ball_create() | |
local ball={} | |
local p={} -- tempory table to build points into | |
function pp(...) for i,v in ipairs{...} do p[#p+1]=v end end -- and data push function | |
function xy(x,y) return p[((x+(y*17))*3)+1],p[((x+(y*17))*3)+2],p[((x+(y*17))*3)+3] end | |
for y=0,8 do | |
for x=0,16 do | |
local s=math.cos(math.pi*(y-4)/8) | |
pp( math.sin(2*math.pi*x/16)*s , math.sin(math.pi*(y-4)/8) , math.cos(2*math.pi*x/16)*s ) | |
end | |
end | |
local t={} -- tempory table to build tris into | |
function tp(...) for i,v in ipairs{...} do t[#t+1]=v end end -- and data push function | |
for check=0,1 do -- make chequered pattern order | |
for y=0,7 do | |
for x=0,15 do | |
if ((x+y)%2)==check then | |
tp( xy(x+0,y+0) ) | |
tp( xy(x+1,y+0) ) | |
tp( xy(x+0,y+1) ) | |
tp( xy(x+1,y+0) ) | |
tp( xy(x+1,y+1) ) | |
tp( xy(x+0,y+1) ) | |
end | |
end | |
end | |
end | |
ball.vdat=pack.alloc( #t*4 ) | |
pack.save_array(t,"f32",0,#t,ball.vdat) -- pack data as 32bit floats | |
ball.vbuf=gl.GenBuffer() | |
gl.BindBuffer(gl.ARRAY_BUFFER,ball.vbuf) | |
gl.BufferData(gl.ARRAY_BUFFER,#t*4,ball.vdat,gl.STATIC_DRAW) | |
function ball.draw(siz,color,part) | |
local p=gl.program(prog_color) | |
gl.UseProgram( p[0] ) | |
gl.PushMatrix() | |
gl.Scale(siz,siz,siz) | |
gl.BindBuffer(gl.ARRAY_BUFFER,ball.vbuf) | |
gl.VertexAttribPointer(p:attrib("vertex"), 3 , gl.FLOAT , gl.FALSE , 3*4 , 0*4) | |
gl.EnableVertexAttribArray(p:attrib("vertex")) | |
gl.UniformMatrix4f(p:uniform("modelview"), gl.matrix(gl.MODELVIEW) ) | |
gl.UniformMatrix4f(p:uniform("projection"), gl.matrix(gl.PROJECTION) ) | |
gl.Uniform4f(p:uniform("color"), color[1],color[2],color[3],color[4] ) | |
-- draw odd squares or even squares or both. so we can choose what color ball to draw very simply | |
if part==0 then | |
gl.DrawArrays(gl.TRIANGLES,0,(#t/3)/2) | |
elseif part==1 then | |
gl.DrawArrays(gl.TRIANGLES,(#t/3)/2,(#t/3)/2) | |
elseif part==2 then | |
gl.DrawArrays(gl.TRIANGLES,0,(#t/3)) | |
end | |
gl.PopMatrix() | |
end | |
return ball | |
end | |
-- select a standard gles context | |
win:context({}) | |
--local frame_rate=1/60 | |
local frame_time=0 | |
local ball=ball_create() | |
-- lets bounce | |
local siz=256 | |
local pos={0,0,0} | |
local vec={4,4,0} | |
local rot={0,0,0} | |
local vrt={1,1,1/2} | |
local function pulse() | |
-- frame limit | |
if frame_rate then | |
if frame_time<win:time() then frame_time=win:time() end -- prevent race condition | |
if frame_time>win:time() then return end -- simple frame limit | |
frame_time=frame_time+frame_rate -- step frame forward | |
end | |
repeat -- handle msg queue (so we know the window size on windows) | |
local m=win:msg() | |
until not (m and m[1]) | |
-- velocity | |
rot[1]=rot[1]+vrt[1] | |
rot[2]=rot[2]+vrt[2] | |
rot[3]=rot[3]+vrt[3] | |
pos[1]=pos[1]+vec[1] | |
pos[2]=pos[2]+vec[2] | |
-- gravity | |
vec[2]=vec[2] + (1/8) | |
-- simple collision against sides ofscreen | |
siz=win.height/4 | |
if pos[1] > -siz+win.width/2 then pos[1]=-siz+win.width/2 vec[1]=vec[1]*-1 vrt[1]=vrt[1]*-1 end | |
if pos[1] < siz-win.width/2 then pos[1]= siz-win.width/2 vec[1]=vec[1]*-1 vrt[1]=vrt[1]*-1 end | |
if pos[2] > -siz+win.height/2 then pos[2]=-siz+win.height/2 vec[2]=vec[2]*-1 vrt[2]=vrt[2]*-1 end | |
if pos[2] < siz-win.height/2 then pos[2]= siz-win.height/2 vec[2]=0 vrt[2]=vrt[2]*-1 end | |
-- fake friction at top, prevents runaway fizix | |
-- prepare to draw a frame | |
gl.BlendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA) -- default of premultiplied alpha blending mode | |
gl.Enable(gl.BLEND) | |
gl.Enable(gl.DEPTH_TEST) | |
win:info() -- updates the current width and height | |
gl.Viewport(0,0,win.width,win.height) | |
gl.ClearColor(0,0,1/4,1/4) | |
gl.Clear(gl.COLOR_BUFFER_BIT+gl.DEPTH_BUFFER_BIT) | |
gl.MatrixMode(gl.PROJECTION) | |
gl.LoadMatrix( tardis.m4_project23d(win.width,win.height,win.width,win.height,0.25,win.height*4) ) | |
gl.MatrixMode(gl.MODELVIEW) | |
gl.LoadIdentity() | |
gl.PushMatrix() | |
-- draw the ball | |
gl.Translate(0,0,-win.height*2) | |
gl.Translate(pos[1],pos[2],pos[3]) | |
gl.Rotate(rot[2],1,0,0) | |
gl.Rotate(rot[1],0,0,1) | |
ball.draw(siz,{1,1,1,1},0) -- draw white parts | |
ball.draw(siz,{1,0,0,1},1) -- draw red parts | |
--calling this can stall the pipeline but is good for catching errors | |
--print(gl.GetError()) | |
gl.PopMatrix() | |
win:swap() | |
end | |
-- set a global function that will get called from javascript and keep all the above locals alive | |
gamecake_pulse=pulse | |
--]]></script> | |
<div id="gamecake_container" style=" width:100%; height:100%; position:absolute; "> | |
<canvas id="gamecake_canvas" style=" width:100%; height:100%; position:absolute; " oncontextmenu="event.preventDefault()"></canvas> | |
<script type="text/javascript"> | |
var gamecake_start=function() { | |
//define a callmelater function | |
/* var requestAnimationFrame = (function(){ | |
return function(callback,element){ | |
window.setTimeout(callback, 1000 / 60); | |
}; | |
})(); | |
*/ | |
//initialise lua | |
gamecake_post('cmd=lua\n',document.getElementById("gamecake_init_lua").innerHTML); | |
//gamecake_post('cmd=lua\n','require("wetgenes.win").emcc_start({})'); | |
// create a pulse function and call it every frame | |
var pulse; | |
pulse=function() { | |
requestAnimationFrame(pulse); // we need to always ask to be called again | |
gamecake_post('cmd=lua\n','return gamecake_pulse()'); | |
}; | |
requestAnimationFrame(pulse); // start the updates | |
} | |
var show_progress=function(n) | |
{ | |
window.show_progress_max=window.show_progress_max || 0; | |
if(window.show_progress_max<n) { window.show_progress_max=n; } | |
var pct=Math.floor(100*(1-(n/window.show_progress_max))); | |
console.log("GameCake Loading "+pct+"%"); | |
}; | |
var resize=function(){ | |
var e=document.getElementById("gamecake_container"); | |
var w=parseFloat(window.getComputedStyle(e).width); | |
var h=parseFloat(window.getComputedStyle(e).height); | |
Module.setCanvasSize(w,h); | |
if(gamecake_post) | |
{ | |
gamecake_post('cmd=lua\n','require("wetgenes.win").hardcore.resize(nil,'+w+','+h+')'); | |
} | |
}; | |
window.addEventListener("resize",resize); | |
Module={}; | |
Module.canvas=document.getElementById("gamecake_canvas"); | |
Module.canvas_resize=resize; | |
Module.memoryInitializerPrefixURL="http://play.4lfa.com/gamecake/"; | |
Module['_main'] = function() { | |
gamecake_post = Module.cwrap('main_post', 'int', ['string','string']); | |
gamecake_start(); | |
resize(); | |
}; | |
Module["preInit"] = function() { | |
// FS.createPreloadedFile('/', "gamecake.zip", "/swankypaint.zip", true, false); | |
}; | |
Module["monitorRunDependencies"]=show_progress; | |
</script> | |
<script type="text/javascript" src="http://play.4lfa.com/gamecake/gamecake.js"></script> | |
</div> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment