FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

Added TicTacToe to canvas (#174) · sofmonk/aima-python@68a6600 · GitHub

Repository navigation

Commit 68a6600

Browse files
authored andcommitted
Added TicTacToe to canvas (aimacode#174)
* added kernel test notebook * modified kernel.ipynb * Added canvas support * Added mouseclick to canvas * add TicTacToe to canvas * removed import statement in games.py * corrected HTML tags * Added comments and doctring * Added methods for drawing with normalized units * Added text support * Fixed int type during normalization
1 parent ed41795 commit 68a6600

4 files changed

Lines changed: 641 additions & 53 deletions

File tree

‎canvas.js‎

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
/*
2+
JavaScript functions that are executed by running the corresponding methods of a Canvas object
3+
Donot use these functions by making a js file. Instead use the python Canvas class.
4+
See canvas.py for help on how to use the Canvas class to draw on the HTML Canvas
5+
*/
6+
7+
//Manages the output of code executed in IPython kernel
8+
function output_callback(out, block){
9+
console.log(out);
10+
script = out.content.data['text/html'];
11+
console.log(script);
12+
script = script.substr(8, script.length - 17);
13+
console.log(script);
14+
eval(script)
15+
}
16+
17+
//Handles mouse click by calling mouse_click of Canvas object with the co-ordinates as arguments
18+
function click_callback(element, event, varname){
19+
var rect = element.getBoundingClientRect();
20+
var x = event.clientX - rect.left;
21+
var y = event.clientY - rect.top;
22+
var kernel = IPython.notebook.kernel;
23+
var exec_str = varname + ".mouse_click(" + String(x) + ", " + String(y) + ")";
24+
console.log(exec_str);
25+
kernel.execute(exec_str,{'iopub': {'output': output_callback}}, {silent: false});
26+
}
27+
28+
function rgbToHex(r,g,b){
29+
var hexValue=(r<<16) + (g<<8) + (b<<0);
30+
var hexString=hexValue.toString(16);
31+
hexString ='#' + Array(7-hexString.length).join('0') + hexString; //Add 0 padding
32+
return hexString;
33+
}
34+
35+
function toRad(x){
36+
return x*Math.PI/180;
37+
}
38+
39+
//Canvas class to store variables
40+
function Canvas(id){
41+
this.canvas = document.getElementById(id);
42+
this.ctx = this.canvas.getContext("2d");
43+
this.WIDTH = this.canvas.width;
44+
this.HEIGHT = this.canvas.height;
45+
this.MOUSE = {x:0,y:0};
46+
}
47+
48+
//Sets the fill color with which shapes are filled
49+
Canvas.prototype.fill = function(r, g, b){
50+
this.ctx.fillStyle = rgbToHex(r,g,b);
51+
}
52+
53+
//Set the stroke color
54+
Canvas.prototype.stroke = function(r, g, b){
55+
this.ctx.strokeStyle = rgbToHex(r,g,b);
56+
}
57+
58+
//Set width of the lines/strokes
59+
Canvas.prototype.strokeWidth = function(w){
60+
this.ctx.lineWidth = w;
61+
}
62+
63+
//Draw a rectangle with top left at (x,y) with 'w' width and 'h' height
64+
Canvas.prototype.rect = function(x, y, w, h){
65+
this.ctx.fillRect(x,y,w,h);
66+
}
67+
68+
//Draw a line with (x1, y1) and (x2, y2) as end points
69+
Canvas.prototype.line = function(x1, y1, x2, y2){
70+
this.ctx.beginPath();
71+
this.ctx.moveTo(x1, y1);
72+
this.ctx.lineTo(x2, y2);
73+
this.ctx.stroke();
74+
}
75+
76+
//Draw an arc with (x, y) as centre, 'r' as radius from angles start to stop
77+
Canvas.prototype.arc = function(x, y, r, start, stop){
78+
this.ctx.beginPath();
79+
this.ctx.arc(x, y, r, toRad(start), toRad(stop));
80+
this.ctx.stroke();
81+
}
82+
83+
//Clear the HTML canvas
84+
Canvas.prototype.clear = function(){
85+
this.ctx.clearRect(0, 0, this.WIDTH, this.HEIGHT);
86+
}
87+
88+
//Change font, size and style
89+
Canvas.prototype.font = function(font_str){
90+
this.ctx.font = font_str;
91+
}
92+
93+
//Draws "filled" text on the canvas
94+
Canvas.prototype.fill_text = function(text, x, y){
95+
this.ctx.fillText(text, x, y);
96+
}
97+
98+
//Write text on the canvas
99+
Canvas.prototype.stroke_text = function(text, x, y){
100+
this.ctx.strokeText(text, x, y);
101+
}
102+
103+
104+
//Test if the canvas functions are working
105+
Canvas.prototype.test_run = function(){
106+
var dbg = false;
107+
if(dbg)
108+
alert("1");
109+
this.clear();
110+
if(dbg)
111+
alert("2");
112+
this.fill(0, 200, 0);
113+
if(dbg)
114+
alert("3");
115+
this.rect(this.MOUSE.x, this.MOUSE.y, 100, 200);
116+
if(dbg)
117+
alert("4");
118+
this.stroke(0, 0, 50);
119+
if(dbg)
120+
alert("5");
121+
this.line(0, 0, 100, 100);
122+
if(dbg)
123+
alert("6");
124+
this.stroke(200, 200, 200);
125+
if(dbg)
126+
alert("7");
127+
this.arc(200, 100, 50, 0, 360);
128+
if(dbg)
129+
alert("8");
130+
}

‎canvas.py‎

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
from IPython.display import HTML, display, clear_output
2+
3+
_canvas = """
4+
<script type="text/javascript" src="./canvas.js"></script>
5+
<div>
6+
<canvas id="{0}" width="{1}" height="{2}" style="background:rgba(158, 167, 184, 0.2);" onclick='click_callback(this, event, "{3}")'></canvas>
7+
</div>
8+
9+
<script> var {0}_canvas_object = new Canvas("{0}");</script>
10+
"""
11+
12+
class Canvas:
13+
"""Inherit from this class to manage the HTML canvas element in jupyter notebooks.
14+
To create an object of this class any_name_xyz = Canvas("any_name_xyz")
15+
The first argument given must be the name of the object being create
16+
IPython must be able to refernce the variable name that is being passed
17+
"""
18+
19+
def __init__(self, varname, id=None, width=800, height=600):
20+
""""""
21+
self.name = varname
22+
self.id = id or varname
23+
self.width = width
24+
self.height = height
25+
self.html = _canvas.format(self.id, self.width, self.height, self.name)
26+
self.exec_list = []
27+
display(HTML(self.html))
28+
29+
def mouse_click(self, x, y):
30+
"Override this method to handle mouse click at position (x, y)"
31+
raise NotImplementedError
32+
33+
def mouse_move(self, x, y):
34+
raise NotImplementedError
35+
36+
def exec(self, exec_str):
37+
"Stores the command to be exectued to a list which is used later during update()"
38+
if not isinstance(exec_str, str):
39+
print("Invalid execution argument:",exec_str)
40+
self.alert("Recieved invalid execution command format")
41+
prefix = "{0}_canvas_object.".format(self.id)
42+
self.exec_list.append(prefix + exec_str + ';')
43+
44+
def fill(self, r, g, b):
45+
"Changes the fill color to a color in rgb format"
46+
self.exec("fill({0}, {1}, {2})".format(r, g, b))
47+
48+
def stroke(self, r, g, b):
49+
"Changes the colors of line/strokes to rgb"
50+
self.exec("stroke({0}, {1}, {2})".format(r, g, b))
51+
52+
def strokeWidth(self, w):
53+
"Changes the width of lines/strokes to 'w' pixels"
54+
self.exec("strokeWidth({0})".format(w))
55+
56+
def rect(self, x, y, w, h):
57+
"Draw a rectangle with 'w' width, 'h' height and (x, y) as the top-left corner"
58+
self.exec("rect({0}, {1}, {2}, {3})".format(x, y, w, h))
59+
60+
def rect_n(self, xn, yn, wn, hn):
61+
"Similar to rect(), but the dimensions are normalized to fall between 0 and 1"
62+
x = round(xn * self.width)
63+
y = round(yn * self.height)
64+
w = round(wn * self.width)
65+
h = round(hn * self.height)
66+
self.rect(x, y, w, h)
67+
68+
def line(self, x1, y1, x2, y2):
69+
"Draw a line from (x1, y1) to (x, y2)"
70+
self.exec("line({0}, {1}, {2}, {3})".format(x1, y1, x2, y2))
71+
72+
def line_n(self, x1n, y1n, x2n, y2n):
73+
"Similar to line(), but the dimensions are normalized to fall between 0 and 1"
74+
x1 = round(x1n * self.width)
75+
y1 = round(y1n * self.height)
76+
x2 = round(x2n * self.width)
77+
y2 = round(y2n * self.height)
78+
self.line(x1, y1, x2, y2)
79+
80+
def arc(self, x, y, r, start, stop):
81+
"Draw an arc with (x, y) as centre, 'r' as radius from angles 'start' to 'stop'"
82+
self.exec("arc({0}, {1}, {2}, {3}, {4})".format(x, y, r, start, stop))
83+
84+
def arc_n(self, xn ,yn, rn, start, stop):
85+
"""Similar to arc(), but the dimensions are normalized to fall between 0 and 1
86+
The normalizing factor for radius is selected between width and height by seeing which is smaller
87+
"""
88+
x = round(xn * self.width)
89+
y = round(yn * self.height)
90+
r = round(rn * min(self.width, self.height))
91+
self.arc(x, y, r, start, stop)
92+
93+
def clear(self):
94+
"Clear the HTML canvas"
95+
self.exec("clear()")
96+
97+
def font(self, font):
98+
"Changes the font of text"
99+
self.exec('font("{0}")'.format(font))
100+
101+
def text(self, txt, x, y, fill = True):
102+
"Display a text at (x, y)"
103+
if fill:
104+
self.exec('fill_text("{0}", {1}, {2})'.format(txt, x, y))
105+
else:
106+
self.exec('stroke_text("{0}", {1}, {2})'.format(txt, x, y))
107+
108+
def text_n(self, txt, xn, yn, fill = True):
109+
"Similar to text(), but with normalized coordinates"
110+
x = round(xn * self.width)
111+
y = round(yn * self.height)
112+
self.text(text, x, y, fill)
113+
114+
def alert(self, message):
115+
"Immediately display an alert"
116+
display(HTML('<script>alert("{0}")</script>'.format(message)))
117+
118+
def update(self):
119+
"Execute the JS code to execute the commands queued by exec()"
120+
exec_code = "<script>\n"+'\n'.join(self.exec_list)+"\n</script>"
121+
self.exec_list = []
122+
display(HTML(exec_code))

0 commit comments

Comments
 (0)

Back | FazBrowse Home | New Git URL