Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save nukadelic/388ac4a3e2376b13fee27bcfeddc6c37 to your computer and use it in GitHub Desktop.
Save nukadelic/388ac4a3e2376b13fee27bcfeddc6c37 to your computer and use it in GitHub Desktop.
Canvas JS game to Python image with matplotlib inside notebook
{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"collapsed": true
},
"source": [
"###### . \n",
" \n",
"--- \n",
" \n",
" # Table Of Contents\n",
"\n",
"1. [The basics](#The-basics)\n",
"1. [Execute with a callback](#Execute-with-a-callback)\n",
"1. [Drawing canvas with matplotlib](#Drawing-canvas-with-matplotlib)\n",
"1. [HTML Game to Python](#HTML-Game-to-Python)\n",
"\n",
"$ $\n",
"\n",
"---"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# The basics"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Create a python `sharedVariable` with a string value of \"sample\" in JS"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"data": {
"application/javascript": [
"\n",
"console.log( IPython.notebook.kernel );\n",
"\n",
"IPython.notebook.kernel.execute(\" sharedVariable = 'sample' \")"
],
"text/plain": [
"<IPython.core.display.Javascript object>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"%%javascript \n",
"\n",
"console.log( IPython.notebook.kernel );\n",
"\n",
"IPython.notebook.kernel.execute(\" sharedVariable = 'sample' \")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Preview result in notebook"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"scrolled": true
},
"outputs": [
{
"data": {
"text/plain": [
"'sample'"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"sharedVariable"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Change the variable"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"sharedVariable = sharedVariable + '-edit'"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"##### Declare JS execution function"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"from IPython.display import HTML\n",
"execute = lambda code: HTML('<script>' + code + '</script>' )"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now move this variable from python back to JS & display it with HTML ( note the extra spaces )"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<script> \n",
"\n",
" window.sharedVariable = \"sample-edit\"; \n",
" console.log( 'Shared variable value', window.sharedVariable );\n",
"\n",
"</script>"
],
"text/plain": [
"<IPython.core.display.HTML object>"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"execute(\"\"\" \n",
"\n",
" window.sharedVariable = \"{0}\"; \n",
" console.log( 'Shared variable value', window.sharedVariable );\n",
"\n",
"\"\"\".format( \n",
"# {0}\n",
" str( sharedVariable ) \n",
" \n",
"))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Display HTML tag as output using the sharedVariable"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"<style> \n",
" #id1 { border: 2px solid green; }\n",
"</style>\n",
"\n",
"<h2 id='id1'>\n",
"placeholder\n",
"</h2>\n",
"\n",
"<script> \n",
" document.getElementById('id1').innerHTML = window.sharedVariable; \n",
"</script>"
],
"text/plain": [
"<IPython.core.display.HTML object>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"%%HTML\n",
"\n",
"<style> \n",
" #id1 { border: 2px solid green; }\n",
"</style>\n",
"\n",
"<h2 id='id1'>\n",
"placeholder\n",
"</h2>\n",
"\n",
"<script> \n",
" document.getElementById('id1').innerHTML = window.sharedVariable; \n",
"</script>"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---\n",
"\n",
"▲ [Back to top](#.)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Execute with a callback"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"code_folding": [],
"hide_input": false
},
"outputs": [
{
"data": {
"application/javascript": [
"\n",
"window.execute = ( code, callback )=> {\n",
" window.execute.callback = callback;\n",
" IPython.notebook.kernel.execute( code, \n",
" { 'iopub' : {'output' : window.execute.output} } , \n",
" { silent:false } );\n",
"};\n",
"window.execute.callback = null;\n",
"window.execute.output = result => {\n",
" var content = result.content;\n",
" if( ! content.data ) {\n",
" var trace = result.content.traceback;\n",
" console.warn( trace[ trace.length-1 ].split(':')[1] ); \n",
" return;\n",
" }\n",
" var data = [];\n",
" for( var key in content.data ) {\n",
" console.log( 'execute output: ', key, content.data[ key ] );\n",
" data.push( content.data[ key ] );\n",
" }\n",
" if( window.execute.callback ) \n",
" window.execute.callback( data );\n",
"};\n",
"\n",
"element.append( $('<small/>').text('window.execute - READY'));"
],
"text/plain": [
"<IPython.core.display.Javascript object>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"%%javascript\n",
"\n",
"window.execute = ( code, callback )=> {\n",
" window.execute.callback = callback;\n",
" IPython.notebook.kernel.execute( code, \n",
" { 'iopub' : {'output' : window.execute.output} } , \n",
" { silent:false } );\n",
"};\n",
"window.execute.callback = null;\n",
"window.execute.output = result => {\n",
" var content = result.content;\n",
" if( ! content.data ) {\n",
" var trace = result.content.traceback;\n",
" console.warn( trace[ trace.length-1 ].split(':')[1] ); \n",
" return;\n",
" }\n",
" var data = [];\n",
" for( var key in content.data ) {\n",
" console.log( 'execute output: ', key, content.data[ key ] );\n",
" data.push( content.data[ key ] );\n",
" }\n",
" if( window.execute.callback ) \n",
" window.execute.callback( data );\n",
"};\n",
"\n",
"element.append( $('<small/>').text('window.execute - READY'));"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([9, 3, 9, 9, 6, 2, 9, 7, 0, 5])"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"import numpy as np\n",
"np.random.randint(0,10,10)"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {
"hide_input": false
},
"outputs": [
{
"data": {
"text/html": [
"\n",
"<h2 id='output_2' style='border: 2px solid green;'></h2>\n",
"\n",
"<script>\n",
"\n",
"var pyCode = 'np.random.randint(0,10,10)';\n",
"\n",
"window.execute( pyCode , function( output ) \n",
"{\n",
" if( ! output ) output = 'undefined';\n",
" if( output.length > 1 ) {\n",
" output = output.join( ', ' );\n",
" }\n",
" \n",
" $('#output_2').text( output );\n",
"} );\n",
"\n",
"</script>"
],
"text/plain": [
"<IPython.core.display.HTML object>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"%%HTML\n",
"\n",
"<h2 id='output_2' style='border: 2px solid green;'></h2>\n",
"\n",
"<script>\n",
"\n",
"var pyCode = 'np.random.randint(0,10,10)';\n",
"\n",
"window.execute( pyCode , function( output ) \n",
"{\n",
" if( ! output ) output = 'undefined';\n",
" if( output.length > 1 ) {\n",
" output = output.join( ', ' );\n",
" }\n",
" \n",
" $('#output_2').text( output );\n",
"} );\n",
"\n",
"</script>"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---\n",
"\n",
"▲ [Back to top](#.)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Drawing canvas with matplotlib"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {
"hide_input": false
},
"outputs": [
{
"data": {
"application/javascript": [
"// Create canvas\n",
"var canvas = document.createElement('canvas');\n",
"canvas.id = \"Cnv1\";\n",
"// append to notebook cell element \n",
"element.append( canvas )\n",
"// Canvas style and size\n",
"canvas.style.border = '1px solid black';\n",
"canvas.width = 50; canvas.height = 50;\n",
"// Draw\n",
"var ctx = canvas.getContext('2d');\n",
"var x = 25, y = 35, radius = 15, color = 'red';\n",
"ctx.fillStyle = color;\n",
"ctx.beginPath();\n",
"ctx.moveTo(x, y);\n",
"ctx.arc(x, y, radius, 0, Math.PI * 2, false);\n",
"ctx.fill();"
],
"text/plain": [
"<IPython.core.display.Javascript object>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"%%javascript\n",
"// Create canvas\n",
"var canvas = document.createElement('canvas');\n",
"canvas.id = \"Cnv1\";\n",
"// append to notebook cell element \n",
"element.append( canvas )\n",
"// Canvas style and size\n",
"canvas.style.border = '1px solid black';\n",
"canvas.width = 50; canvas.height = 50;\n",
"// Draw\n",
"var ctx = canvas.getContext('2d');\n",
"var x = 25, y = 35, radius = 15, color = 'red';\n",
"ctx.fillStyle = color;\n",
"ctx.beginPath();\n",
"ctx.moveTo(x, y);\n",
"ctx.arc(x, y, radius, 0, Math.PI * 2, false);\n",
"ctx.fill();"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Get canvas base64"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [
{
"data": {
"application/javascript": [
"\n",
"var canvas = document.getElementById(\"Cnv1\");\n",
"window.imageBase64 = canvas.toDataURL(\"image/png\");\n",
"IPython.notebook.kernel.execute('imageBase64 = \"' + window.imageBase64 + '\"' )"
],
"text/plain": [
"<IPython.core.display.Javascript object>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"%%javascript\n",
"\n",
"var canvas = document.getElementById(\"Cnv1\");\n",
"window.imageBase64 = canvas.toDataURL(\"image/png\");\n",
"IPython.notebook.kernel.execute('imageBase64 = \"' + window.imageBase64 + '\"' )"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Preview output"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {
"scrolled": false
},
"outputs": [
{
"data": {
"text/plain": [
"'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAooAAAD6CAYAAAAmyWZkAAAOUklEQVR4Xu3YoRHAQAwEsXz/TacBg+WnYBPLD3byPh8BAgQIECBAgACBQ+BRIUCAAAECBAgQIHAJCEXv...'"
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"imageBase64[:150] + '...'"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Remove data type"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'iVBORw0KGgoAAAANSUhEUgAAAooAAAD6CAYAAAAmyWZkAAAOUklEQVR4Xu3YoRHAQAwEsXz/TacBg+WnYBPLD3byPh8BAgQIECBAgACBQ+BRIUCAAAECBAgQIHAJCEXvggABAgQIECBA4BQQih4GAQ...'"
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"base64_image_string = imageBase64.split(',')[ 1 ]\n",
"\n",
"base64_image_string[:150] + '...'"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Convert to image"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"import base64\n",
"from io import BytesIO\n",
"from PIL import Image\n",
"import numpy as np\n",
"\n",
"\n",
"image = Image.open( BytesIO( base64.b64decode( base64_image_string )))\n",
"img = np.array(image)"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": true
},
"source": [
"Finally draw with matplotlib"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {
"scrolled": false
},
"outputs": [
{
"data": {
"image/png": "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\n",
"text/plain": [
"<matplotlib.figure.Figure at 0x7f37f9017748>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"import matplotlib.pyplot as plt\n",
"\n",
"# plt.imshow( Image.open( BytesIO( base64.b64decode( imageBase64.split(',')[ 1 ] ))) )\n",
"\n",
"plt.imshow(img)\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---\n",
"\n",
"▲ [Back to top](#.)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# HTML Game to Python"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"To prevent bugs & memory overflow keep only 1 instance of animation frame running at the same time. The generated interface will control everything that was attached to animator."
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {
"code_folding": [],
"hide_input": false,
"scrolled": false
},
"outputs": [
{
"data": {
"application/javascript": [
"\n",
"// Cross browser support \n",
"var requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;\n",
"var cancelAnimationFrame = window.cancelAnimationFrame || window.mozCancelAnimationFrame;\n",
"\n",
"// Override \n",
"if( window.animator ) window.animator.stop();\n",
"\n",
"// Create \n",
"window.animator = {\n",
" // Public vars & methods \n",
" update:_=>{}, terminate: false,paused: false, \n",
" updates:[],\n",
" lastTimeStamp: 0, elapsed: 0, frames: 0, frame: 0, fps: 0,\n",
" stop:_=>{\n",
" var a = window.animator;\n",
" a.terminate = true;\n",
" cancelAnimationFrame( a._request );\n",
" a.update =_=> {}; // sunnies\n",
" }, \n",
" // Private vars & methods \n",
" _request : 0,\n",
" _status: c=> {$('#windowAnimatorStatus').text( window.animator.paused ? 'Paused' : (!!c?`(x${c})`:'') + window.animator.fps.toFixed(2) + ' FPS' );},\n",
" _init: _ => { window.animator._request = requestAnimationFrame( window.animator._onFrame ) },\n",
" _onFrame: timestamp => {\n",
" var a = window.animator;\n",
" if( a.terminate ) { a.stop(); return; }\n",
" a._request = requestAnimationFrame( a._onFrame );\n",
" if( a.lastTimeStamp == 0 ) a.lastTimeStamp = timestamp;\n",
" var delta = timestamp - a.lastTimeStamp;\n",
" a.frames++;;if( ++a.frame < 60 ) a.elapsed += delta;\n",
" else { a.fps = a.elapsed/16.666;a.frame = 0; a.elapsed = 0;a._status();} \n",
" var anim_requests = a.updates.concat( [a.update] );\n",
" if( a.paused && $('#windowAnimatorStatus').text()!='Paused' ) a._status(anim_requests.length);\n",
" if( a.paused ) return;\n",
" anim_requests.forEach( U => !!U?(U.length==2?U(timestamp, delta):(U.length==1?U(timestamp):U())):null );\n",
" a.lastTimeStamp = timestamp;\n",
" }\n",
"};window.animator._init();\n",
"//////////////////////////\\\n",
"\n",
"// when < Hide Input > nb-extension is enbaled, call it\n",
"// $('#btn-hide-input').click();\n",
"\n",
"// Create user interface\n",
"var makeButton = ( text, callback ) => container.append( $('<button/>').click(callback).text( text ).css('padding','4px 12px') );\n",
"var makeSpace = space => container.append( $('<span/>').css( 'width', space + 'px' ).css('display','inline-block') );\n",
"$('<h3/>').html( 'Window Animator' ).appendTo( element );\n",
"$('<br/>').appendTo( element );\n",
"element.css('padding','20px 0');\n",
"var container = $('<div/>').appendTo( element );\n",
"makeButton( 'Pause / Resume', e=> {window.animator.paused = !window.animator.paused;window.animator._status(null);} );\n",
"makeSpace( 10 );makeButton( 'Kill', e=> { window.animator.stop(); container.hide();/*$('#btn-hide-input').click();*/ } );\n",
"makeSpace( 20 );container.append( $('<span id=\"windowAnimatorStatus\" />').html( 'Run cell to start' ) );"
],
"text/plain": [
"<IPython.core.display.Javascript object>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"%%javascript \n",
"\n",
"// Cross browser support \n",
"var requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;\n",
"var cancelAnimationFrame = window.cancelAnimationFrame || window.mozCancelAnimationFrame;\n",
"\n",
"// Override \n",
"if( window.animator ) window.animator.stop();\n",
"\n",
"// Create \n",
"window.animator = {\n",
" // Public vars & methods \n",
" update:_=>{}, terminate: false,paused: false, \n",
" updates:[],\n",
" lastTimeStamp: 0, elapsed: 0, frames: 0, frame: 0, fps: 0,\n",
" stop:_=>{\n",
" var a = window.animator;\n",
" a.terminate = true;\n",
" cancelAnimationFrame( a._request );\n",
" a.update =_=> {}; // sunnies\n",
" }, \n",
" // Private vars & methods \n",
" _request : 0,\n",
" _status: c=> {$('#windowAnimatorStatus').text( window.animator.paused ? 'Paused' : (!!c?`(x${c})`:'') + window.animator.fps.toFixed(2) + ' FPS' );},\n",
" _init: _ => { window.animator._request = requestAnimationFrame( window.animator._onFrame ) },\n",
" _onFrame: timestamp => {\n",
" var a = window.animator;\n",
" if( a.terminate ) { a.stop(); return; }\n",
" a._request = requestAnimationFrame( a._onFrame );\n",
" if( a.lastTimeStamp == 0 ) a.lastTimeStamp = timestamp;\n",
" var delta = timestamp - a.lastTimeStamp;\n",
" a.frames++;;if( ++a.frame < 60 ) a.elapsed += delta;\n",
" else { a.fps = a.elapsed/16.666;a.frame = 0; a.elapsed = 0;a._status();} \n",
" var anim_requests = a.updates.concat( [a.update] );\n",
" if( a.paused && $('#windowAnimatorStatus').text()!='Paused' ) a._status(anim_requests.length);\n",
" if( a.paused ) return;\n",
" anim_requests.forEach( U => !!U?(U.length==2?U(timestamp, delta):(U.length==1?U(timestamp):U())):null );\n",
" a.lastTimeStamp = timestamp;\n",
" }\n",
"};window.animator._init();\n",
"//////////////////////////\\\n",
"\n",
"// when < Hide Input > nb-extension is enbaled, call it\n",
"// $('#btn-hide-input').click();\n",
"\n",
"// Create user interface\n",
"var makeButton = ( text, callback ) => container.append( $('<button/>').click(callback).text( text ).css('padding','4px 12px') );\n",
"var makeSpace = space => container.append( $('<span/>').css( 'width', space + 'px' ).css('display','inline-block') );\n",
"$('<h3/>').html( 'Window Animator' ).appendTo( element );\n",
"$('<br/>').appendTo( element );\n",
"element.css('padding','20px 0');\n",
"var container = $('<div/>').appendTo( element );\n",
"makeButton( 'Pause / Resume', e=> {window.animator.paused = !window.animator.paused;window.animator._status(null);} );\n",
"makeSpace( 10 );makeButton( 'Kill', e=> { window.animator.stop(); container.hide();/*$('#btn-hide-input').click();*/ } );\n",
"makeSpace( 20 );container.append( $('<span id=\"windowAnimatorStatus\" />').html( 'Run cell to start' ) );"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"##### Pong Canvas"
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {
"code_folding": [],
"scrolled": true
},
"outputs": [
{
"data": {
"text/html": [
"<canvas id=\"pongCanvas\" width='650' height='250' \n",
"style='border:1px solid black; margin: 0 auto'></canvas>\n",
"\n",
"<script>\n",
"var canvas = $('#pongCanvas');\n",
"canvas.parent().css('text-align','center');\n",
"</script>"
],
"text/plain": [
"<IPython.core.display.HTML object>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"%%HTML\n",
"<canvas id=\"pongCanvas\" width='650' height='250' \n",
"style='border:1px solid black; margin: 0 auto'></canvas>\n",
"\n",
"<script>\n",
"var canvas = $('#pongCanvas');\n",
"canvas.parent().css('text-align','center');\n",
"</script>"
]
},
{
"cell_type": "markdown",
"metadata": {
"hide_input": true
},
"source": [
"##### Create image scanner"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Some more hacks ( busy the kernel with some work )"
]
},
{
"cell_type": "code",
"execution_count": 29,
"metadata": {
"hide_input": false
},
"outputs": [
{
"data": {
"text/html": [
"<p id='b64_txt'></p>\n",
"<script>\n",
"\n",
"window.animator.updates = [\n",
" function( timelapse ) {\n",
" if( window.animator.frame % 30 != 0 ) return; \n",
" //document.getElementById( \"b64_txt\" ).innerHTML = '' + (window.animator.frame);\n",
" var B64 = document.getElementById( \"pongCanvas\" ).toDataURL(\"image/png\");\n",
" document.getElementById( \"b64_txt\" ).innerHTML = 'Base64: ' + B64.substr(-20);\n",
" IPython.notebook.kernel.execute('imageBase64 = \"' + B64 + '\"' );\n",
" }\n",
"];\n",
"\n",
"</script>"
],
"text/plain": [
"<IPython.core.display.HTML object>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"%%HTML\n",
"<p id='b64_txt'></p>\n",
"<script>\n",
"\n",
"window.animator.updates = [\n",
" function( timelapse ) {\n",
" if( window.animator.frame % 30 != 0 ) return; \n",
" //document.getElementById( \"b64_txt\" ).innerHTML = '' + (window.animator.frame);\n",
" var B64 = document.getElementById( \"pongCanvas\" ).toDataURL(\"image/png\");\n",
" document.getElementById( \"b64_txt\" ).innerHTML = 'Base64: ' + B64.substr(-20);\n",
" IPython.notebook.kernel.execute('imageBase64 = \"' + B64 + '\"' );\n",
" }\n",
"];\n",
"\n",
"</script>"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Pong JS game, to see source code with documentation visit: https://codepen.io/_wad1m/pen/dRZVvZ"
]
},
{
"cell_type": "code",
"execution_count": 30,
"metadata": {
"code_folding": []
},
"outputs": [
{
"data": {
"application/javascript": [
"function start_game() {\n",
" max_level_diff = 6;\n",
" canvasElement = document.getElementById('pongCanvas');\n",
" ctx = canvasElement.getContext('2d');\n",
" canvasElement.addEventListener('mousemove', onMouseMove);\n",
" init_game(); newGame();\n",
" // CONNECT GAME TO WINDOW ANIMATOR \n",
" window.animator.update = update;\n",
" // you can craete global JS variables from score1 & score2 and pass to python\n",
"}\n",
"var max_level_diff, canvasElement, ctx, screenW, screenH, isplayScale,game_frame_rate = 60,mouse_x = 0, \n",
" mouse_y = 0, mouse_moved = false,score1, score2,enemy_velocity = 0,pedal_1_y, pedal_2_y, pedal_1_x, \n",
" pedal_2_x, pedal_thikness, pedal_height, ball_radius, ball_speed, ball_speed_angle, ball_velocity_x, \n",
" ball_velocity_y, ball_x, ball_y, minScreenSize, author = \"Pong!\", displayScale;\n",
"function init_game() {\n",
" screenW = canvasElement.width;\n",
" screenH = canvasElement.height;\n",
" minScreenSize = Math.min( screenW, screenH );\n",
" if( minScreenSize <= 400 ) displayScale = 1;\n",
" else if( minScreenSize <= 600 ) displayScale = 2;\n",
" else if( minScreenSize <= 1000 ) displayScale = 2.5;\n",
" else displayScale = 3;\n",
" pedal_thikness = 10 * displayScale;\n",
" pedal_height = screenH / 6.5;\n",
" pedal_1_x = 30;\n",
" pedal_2_x = screenW - pedal_thikness - 30;\n",
" ball_radius = pedal_thikness / 2;\n",
" ball_speed = displayScale * 240 / game_frame_rate;\n",
" enemy_velocity = displayScale * 80 / game_frame_rate;\n",
"}function update(){updateOnFrame();drawOnFrame();}\n",
"function onMouseMove( event ){\n",
" var rect = canvasElement.getBoundingClientRect();mouse_moved = true;\n",
" mouse_x = ( event.clientX - rect.left )/( rect.right - rect.left) * canvasElement.width;\n",
" mouse_y = ( event.clientY - rect.top )/( rect.bottom - rect.top) * canvasElement.height;\n",
"}function newGame(){\n",
" score1 = score2 = 0;ball_speed_angle = 0;\n",
" pedal_1_y = pedal_2_y = screenH / 2 - pedal_height / 2;\n",
" resetBall( Math.random() > 0.5 ? 1 : -1 );\n",
"}function updateOnFrame(){\n",
" var level_difficulty = Math.min( 1 + score1 / 4, 1+max_level_diff/4 );\n",
" calcBallVelocity( ball_speed_angle, ball_speed * level_difficulty );\n",
" ball_x += ball_velocity_x;ball_y += ball_velocity_y;\n",
" if( ( ball_y < 0 && ball_velocity_y < 0 ) || ( ball_y > screenH && ball_velocity_y > 0 ) )\n",
" ball_speed_angle = Math.atan2( -ball_velocity_y, ball_velocity_x );\n",
" var enemy_speed = enemy_velocity * level_difficulty;\n",
" if( pedal_2_y + pedal_height / 2 < ball_y ) pedal_2_y += enemy_speed;\n",
" if( pedal_2_y + pedal_height / 2 > ball_y ) pedal_2_y -= enemy_speed;\n",
" if( mouse_moved ) pedal_1_y = mouse_y - 0.5 * pedal_height;\n",
" if( ball_x - ball_radius < pedal_1_x + pedal_thikness )\n",
" if( ball_y > pedal_1_y && ball_y < pedal_1_y + pedal_height ){\n",
" var hit = ( ball_y - pedal_1_y ) / pedal_height - 0.5;\n",
" ball_speed_angle = ( Math.PI / 2 ) * hit;\n",
" }if( ball_x + ball_radius > pedal_2_x )\n",
" if( ball_y > pedal_2_y && ball_y < pedal_2_y + pedal_height ){\n",
" var hit = ( ball_y - pedal_2_y ) / pedal_height - 0.5;\n",
" ball_speed_angle = Math.PI + ( Math.PI / 2 ) * -hit;\n",
" }if( ball_x < 0 ){score2++;resetBall(-1);}\n",
" if( ball_x > screenW ){score1++;resetBall(1);}\n",
"}function resetBall( direction ){\n",
" ball_x = screenW / 2;ball_y = screenH / 2;\n",
" ball_speed_angle = ( Math.random() - 0.5 ) * Math.PI / 2;\n",
" if( direction < 0 ) ball_speed_angle += Math.PI;\n",
"}function drawOnFrame() {\n",
" ctx.fillStyle='white';ctx.fillRect(0,0,screenW,screenH);\n",
" ctx.font= getFont(16);ctx.fillStyle='black';ctx.textAlign = 'center'; ctx.textBaseline = 'middle'; \n",
" ctx.fillText(author,screenW/2,screenH-15);\n",
" ctx.font= getFont(18);var textPedding = 10 * displayScale;\n",
" ctx.fillRect(screenW/2-2,0,4,30 + textPedding);ctx.fillText(score1,screenW/2 - 15 - textPedding,12 + textPedding);\n",
" ctx.fillText(score2,screenW/2 + 15 + textPedding,12 + textPedding);\n",
" ctx.fillStyle = 'red';ctx.fillRect(pedal_1_x, pedal_1_y, pedal_thikness, pedal_height );\n",
" ctx.fillRect(pedal_2_x, pedal_2_y, pedal_thikness, pedal_height );\n",
" ctx.beginPath();ctx.arc(ball_x, ball_y, ball_radius, 0, Math.PI * 2, true);ctx.fill();\n",
"}function getFont( size ){return (size * displayScale) + 'px Arial';}\n",
"function calcBallVelocity( angle, speed )\n",
"{ball_velocity_x = Math.cos( angle ) * speed;ball_velocity_y = Math.sin( angle ) * speed;}\n",
"\n",
"start_game();"
],
"text/plain": [
"<IPython.core.display.Javascript object>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"%%javascript \n",
"function start_game() {\n",
" max_level_diff = 6;\n",
" canvasElement = document.getElementById('pongCanvas');\n",
" ctx = canvasElement.getContext('2d');\n",
" canvasElement.addEventListener('mousemove', onMouseMove);\n",
" init_game(); newGame();\n",
" // CONNECT GAME TO WINDOW ANIMATOR \n",
" window.animator.update = update;\n",
" // you can craete global JS variables from score1 & score2 and pass to python\n",
"}\n",
"var max_level_diff, canvasElement, ctx, screenW, screenH, isplayScale,game_frame_rate = 60,mouse_x = 0, \n",
" mouse_y = 0, mouse_moved = false,score1, score2,enemy_velocity = 0,pedal_1_y, pedal_2_y, pedal_1_x, \n",
" pedal_2_x, pedal_thikness, pedal_height, ball_radius, ball_speed, ball_speed_angle, ball_velocity_x, \n",
" ball_velocity_y, ball_x, ball_y, minScreenSize, author = \"Pong!\", displayScale;\n",
"function init_game() {\n",
" screenW = canvasElement.width;\n",
" screenH = canvasElement.height;\n",
" minScreenSize = Math.min( screenW, screenH );\n",
" if( minScreenSize <= 400 ) displayScale = 1;\n",
" else if( minScreenSize <= 600 ) displayScale = 2;\n",
" else if( minScreenSize <= 1000 ) displayScale = 2.5;\n",
" else displayScale = 3;\n",
" pedal_thikness = 10 * displayScale;\n",
" pedal_height = screenH / 6.5;\n",
" pedal_1_x = 30;\n",
" pedal_2_x = screenW - pedal_thikness - 30;\n",
" ball_radius = pedal_thikness / 2;\n",
" ball_speed = displayScale * 240 / game_frame_rate;\n",
" enemy_velocity = displayScale * 80 / game_frame_rate;\n",
"}function update(){updateOnFrame();drawOnFrame();}\n",
"function onMouseMove( event ){\n",
" var rect = canvasElement.getBoundingClientRect();mouse_moved = true;\n",
" mouse_x = ( event.clientX - rect.left )/( rect.right - rect.left) * canvasElement.width;\n",
" mouse_y = ( event.clientY - rect.top )/( rect.bottom - rect.top) * canvasElement.height;\n",
"}function newGame(){\n",
" score1 = score2 = 0;ball_speed_angle = 0;\n",
" pedal_1_y = pedal_2_y = screenH / 2 - pedal_height / 2;\n",
" resetBall( Math.random() > 0.5 ? 1 : -1 );\n",
"}function updateOnFrame(){\n",
" var level_difficulty = Math.min( 1 + score1 / 4, 1+max_level_diff/4 );\n",
" calcBallVelocity( ball_speed_angle, ball_speed * level_difficulty );\n",
" ball_x += ball_velocity_x;ball_y += ball_velocity_y;\n",
" if( ( ball_y < 0 && ball_velocity_y < 0 ) || ( ball_y > screenH && ball_velocity_y > 0 ) )\n",
" ball_speed_angle = Math.atan2( -ball_velocity_y, ball_velocity_x );\n",
" var enemy_speed = enemy_velocity * level_difficulty;\n",
" if( pedal_2_y + pedal_height / 2 < ball_y ) pedal_2_y += enemy_speed;\n",
" if( pedal_2_y + pedal_height / 2 > ball_y ) pedal_2_y -= enemy_speed;\n",
" if( mouse_moved ) pedal_1_y = mouse_y - 0.5 * pedal_height;\n",
" if( ball_x - ball_radius < pedal_1_x + pedal_thikness )\n",
" if( ball_y > pedal_1_y && ball_y < pedal_1_y + pedal_height ){\n",
" var hit = ( ball_y - pedal_1_y ) / pedal_height - 0.5;\n",
" ball_speed_angle = ( Math.PI / 2 ) * hit;\n",
" }if( ball_x + ball_radius > pedal_2_x )\n",
" if( ball_y > pedal_2_y && ball_y < pedal_2_y + pedal_height ){\n",
" var hit = ( ball_y - pedal_2_y ) / pedal_height - 0.5;\n",
" ball_speed_angle = Math.PI + ( Math.PI / 2 ) * -hit;\n",
" }if( ball_x < 0 ){score2++;resetBall(-1);}\n",
" if( ball_x > screenW ){score1++;resetBall(1);}\n",
"}function resetBall( direction ){\n",
" ball_x = screenW / 2;ball_y = screenH / 2;\n",
" ball_speed_angle = ( Math.random() - 0.5 ) * Math.PI / 2;\n",
" if( direction < 0 ) ball_speed_angle += Math.PI;\n",
"}function drawOnFrame() {\n",
" ctx.fillStyle='white';ctx.fillRect(0,0,screenW,screenH);\n",
" ctx.font= getFont(16);ctx.fillStyle='black';ctx.textAlign = 'center'; ctx.textBaseline = 'middle'; \n",
" ctx.fillText(author,screenW/2,screenH-15);\n",
" ctx.font= getFont(18);var textPedding = 10 * displayScale;\n",
" ctx.fillRect(screenW/2-2,0,4,30 + textPedding);ctx.fillText(score1,screenW/2 - 15 - textPedding,12 + textPedding);\n",
" ctx.fillText(score2,screenW/2 + 15 + textPedding,12 + textPedding);\n",
" ctx.fillStyle = 'red';ctx.fillRect(pedal_1_x, pedal_1_y, pedal_thikness, pedal_height );\n",
" ctx.fillRect(pedal_2_x, pedal_2_y, pedal_thikness, pedal_height );\n",
" ctx.beginPath();ctx.arc(ball_x, ball_y, ball_radius, 0, Math.PI * 2, true);ctx.fill();\n",
"}function getFont( size ){return (size * displayScale) + 'px Arial';}\n",
"function calcBallVelocity( angle, speed )\n",
"{ball_velocity_x = Math.cos( angle ) * speed;ball_velocity_y = Math.sin( angle ) * speed;}\n",
"\n",
"start_game();"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---\n",
"Execute this cell many times to see output change"
]
},
{
"cell_type": "code",
"execution_count": 49,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"0HAZAAAAAElFTkSuQmCC\n"
]
},
{
"data": {
"image/png": "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\nnHPQm5nl3P8D02hNCfzFoEQAAAAASUVORK5CYII=\n",
"text/plain": [
"<matplotlib.figure.Figure at 0x7f37f8f0cb70>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"print( imageBase64[-20:] )\n",
"plt.imshow( Image.open( BytesIO( base64.b64decode( imageBase64.split(',')[ 1 ] ))) )\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Multiple images per single figure ( [source](https://gist.github.com/soply/f3eec2e79c165e39c9d540e916142ae1) )"
]
},
{
"cell_type": "code",
"execution_count": 37,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"def show_images(images, cols = 1, titles = None):\n",
" \"\"\"Display a list of images in a single figure with matplotlib.\n",
" Parameters\n",
" ---------\n",
" images: List of np.arrays compatible with plt.imshow.\n",
" cols (Default = 1): Number of columns in figure (number of rows is \n",
" set to np.ceil(n_images/float(cols))).\n",
" titles: List of titles corresponding to each image. Must have\n",
" the same length as titles.\n",
" \"\"\"\n",
" assert((titles is None)or (len(images) == len(titles)))\n",
" n_images = len(images)\n",
" if titles is None: titles = ['Image (%d)' % i for i in range(1,n_images + 1)]\n",
" fig = plt.figure()\n",
" for n, (image, title) in enumerate(zip(images, titles)):\n",
" a = fig.add_subplot(cols, np.ceil(n_images/float(cols)), n + 1)\n",
" if image.ndim == 2:\n",
" plt.gray()\n",
" plt.imshow(image)\n",
" a.set_title(title)\n",
" fig.set_size_inches(np.array(fig.get_size_inches()) * n_images)\n",
" plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Capture game image, using the following:\n",
"- [execute function](#Declare-JS-execution-function)\n",
"- Image scanner [Create image scanner](#Create-image-scanner)\n",
"- [Pong Canvas](#Pong-Canvas)\n",
"- [Window animator](#HTML-Game-to-Python) - used in pong game start_game() method "
]
},
{
"cell_type": "code",
"execution_count": 50,
"metadata": {},
"outputs": [],
"source": [
"# import base64\n",
"# from io import BytesIO\n",
"# from PIL import Image\n",
"# import numpy as np\n",
"# import matplotlib.pyplot as plt\n",
"# import time\n",
"\n",
"# images = []\n",
"\n",
"# for i in range(2):\n",
"# time.sleep(1)\n",
"# # execute('window.canvasToBase64(\"pongCanvas\")')\n",
"# get_ipython().kernel.do_one_iteration()\n",
"# print( i, imageBase64.split(',')[ 1 ][:50] )\n",
"# image = Image.open( BytesIO( base64.b64decode( imageBase64.split(',')[ 1 ] )))\n",
"# images.append( np.array(image) )\n",
" \n",
"# show_images( images )"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Hmmmm... still no luck"
]
},
{
"cell_type": "code",
"execution_count": 52,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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\nFJd0f1AAAAAASUVORK5CYII=\n",
"text/plain": [
"<matplotlib.figure.Figure at 0x7f37f8c977b8>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"image/png": "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\nFJd0f1AAAAAASUVORK5CYII=\n",
"text/plain": [
"<matplotlib.figure.Figure at 0x7f37f8f835c0>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"plt.imshow( Image.open( BytesIO( base64.b64decode( imageBase64.split(',')[ 1 ] ))) )\n",
"plt.show()\n",
"time.sleep(1)\n",
"plt.imshow( Image.open( BytesIO( base64.b64decode( imageBase64.split(',')[ 1 ] ))) )\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"To remove game from animator, execute this cell:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"%%javascript\n",
"window.animator.update = null;"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Additional reading: \n",
"https://jakevdp.github.io/blog/2013/06/01/ipython-notebook-javascript-python-communication/ \n",
"https://github.com/jupyter/notebook/issues/3187"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": true
},
"source": [
"Notebook: 13/April/18"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.3"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment