118
Code Explanation
</body> Close body element
</html> Close html element
You certainly can make improvements to this application, but it probably makes more sense to first make sure you understand it as is and then move on to the next.
119
Function Invoked By / Called By Calls
moveball Invoked by call of the moveit method for the one Ball object
Picture Invoked directly by code in var statements drawAnImage Invoked by call of the draw method for a Picture
object
Table 4-4 shows the complete code for the second application, but only the changed lines have comments.
Table 4-4. The Second Cannonball Application
Code Explanation
<html>
<head>
<title>Cannonball</title>
<style>
form { width:330px;
margin:20px;
background-color:brown;
padding:20px;
}
</style>
<script type="text/javascript">
var cwidth = 600;
120
Code Explanation
var cheight = 400;
var ctx;
var everything = [];
var tid;
var horvelocity;
var verticalvel1;
var verticalvel2;
var gravity = 2;
var cannonx = 10; x location of cannon var cannony = 280; y location of cannon var cannonlength = 200; Cannon length (i.e., width)
var cannonht = 20; Cannon height
var ballrad = 10;
var targetx = 500; x position of target var targety = 50; y position of target
var targetw = 85; Target width
var targeth = 280; Target height
var htargetx = 450; x position of the hit target var htargety = 220; y position of the hit target var htargetw = 355; Hit target width
var htargeth = 96; Hit target height
121
Code Explanation
function Ball(sx,sy,rad,stylestring) { this.sx = sx;
this.sy = sy;
this.rad = rad;
this.draw = drawball;
this.moveit = moveball;
this.fillstyle = stylestring;
}
function drawball() {
ctx.fillStyle=this.fillstyle;
ctx.beginPath();
//ctx.fillStyle= rgb(0,0,0);
ctx.arc(this.sx,this.sy,this.rad, 0,Math.PI*2,true);
ctx.fill();
}
function moveball(dx,dy) { this.sx +=dx;
this.sy +=dy;
}
var cball = new Ball(cannonx+cannonlength, cannony+cannonht*.5,ballrad,"rgb(250,0,0)");
122
Code Explanation
function Myrectangle(sx,sy,swidth,sheight, stylestring) {
this.sx = sx;
this.sy = sy;
this.swidth = swidth;
this.sheight = sheight;
this.fillstyle = stylestring;
this.draw = drawrects;
this.moveit = moveball;
}
function drawrects() {
ctx.fillStyle = this.fillstyle;
ctx.fillRect(this.sx,this.sy, this.swidth,this.sheight);
}
function Picture (sx,sy,swidth, sheight,filen) {
Header for function to set up Picture object
var imga = new Image(); Create an Image object
imga.src=filen; Set the file name
this.sx = sx; Set the sx property
this.sy = sy; … sy
this.img = imga; Set the img property to imga this.swidth = swidth; … swidth
123 Code Explanation
this.sheight = sheight; … sheight
this.draw = drawAnImage; … draw. This will be the draw method for objects of this type.
this.moveit = moveball; … This will be the moveit method. Not used.
} Close Picture function
function drawAnImage() { Header for drawAnImage function ctx.drawImage(this.img,this.sx,
this.sy,this.swidth,this.sheight);
Draw image using properties of this object
} Closes function
var target = new Picture(targetx,targety, targetw,targeth,"hill.jpg");
Construct new Picture object and assign to target variable
var htarget = new Picture(htargetx,
htargety, htargetw, htargeth, "plateau.jpg");
Construct new Picture object and assign to htarget variable
var ground = new Myrectangle(0,300, 600,30,"rgb(10,250,0)");
Construct new Myrectangle object and assign to ground
var cannon = new Myrectangle(cannonx,
cannony,cannonlength,cannonht,"rgb(40,40,0)");
Construct new Myrectangle object and assign to cannon
var targetindex = everything.length; Save what will be the index for target everything.push([target,false]); Add target to everything
everything.push([ground,false]); Add ground to everything
var ballindex = everything.length; Save what will be the index for cball everything.push([cball,false]); Add cball to everything
var cannonindex = everything.length; Save what will be the index for cannon everything.push([cannon,true,0,
cannonx,cannony+cannonht*.5]);
Add cannon to everything; reserve space for rotation
124
Code Explanation
function init(){
ctx = document.getElementById ('canvas').getContext('2d');
drawall();
}
function fire() {
var angle = Number(document.f .ang.value);
Extract angle from form, convert to number
var outofcannon = Number (document.f.vo.value);
Extract velocity out of cannon from form, convert to number
var angleradians = angle*Math .PI/180;
Convert to radians
horvelocity = outofcannon*Math .cos(angleradians);
Compute horizontal velocity
verticalvel1 = - outofcannon*Math .sin(angleradians);
Compute initial vertical velocity
everything[cannonindex][2]=
- angleradians;
Set information to rotate cannon
cball.sx = cannonx +
cannonlength*Math.cos(angleradians);
Set x for cball at mouth of what will be rotated cannon
cball.sy = cannony+cannonht*.5 - cannonlength*Math.sin(angleradians);
Set y for cball at mouth of what will be rotated cannon
drawall();
tid = setInterval(change,100);
return false;
125
Code Explanation
}
function drawall() {
ctx.clearRect(0,0,cwidth,cheight);
var i;
for (i=0;i<everything.length;i++) {
var ob = everything[i]; Extract array for object if (ob[1]) { Need to translate and rotate?
ctx.save(); Save original axes
ctx.translate(ob[3],ob[4]); Do indicated translation ctx.rotate(ob[2]); Do indicated rotation ctx.translate(-ob[3],-ob[4]); Translate back
ob[0].draw(); Draw object
ctx.restore(); } Restore axes
else { Else (no rotation)
ob[0].draw();} Do drawing
} Close for loop
} Close function
function change() {
var dx = horvelocity;
verticalvel2 =verticalvel1 + gravity;
var dy=(verticalvel1 + verticalvel2)*.5;
126
Code Explanation
verticalvel1 = verticalvel2;
cball.moveit(dx,dy);
var bx = cball.sx;
var by = cball.sy;
if ((bx>=target.sx)&&(bx<=(target .sx+target.swidth))&&
(by>=target.sy)&&(by<=(target .sy+target.sheight))) {
clearInterval(tid);
everything.splice (targetindex,1,[htarget,false]);
Remove target and insert htarget
everything.splice (ballindex,1);
Remove the ball
drawall();
}
if (by>=ground.sy) {
clearInterval(tid);
}
drawall();
}
</script>
</head>
<body onLoad="init();">
127
Code Explanation
<canvas id="canvas" width="600"
height="400">
Your browser doesn't support the HTML5 element canvas.
</canvas>
<br/>
<form name="f" id="f" onSubmit=
"return fire();">
Set velocity, angle and fire cannonball. <br/>
Velocity out of cannon <input name=
"vo" id="vo" value="10" type=
"number" min="-100" max="100" />
Label indicating that this is the velocity out of mouth of cannon
<br>
Angle <input name="ang" id="ang"
value="0" type="number" min=
"0" max="80"/>
Label indicating that this is the angle of the cannon
<input type="submit" value="FIRE"/>
</form>
</body>
</html>
This application provides many possibilities for you to make it your own. You can change the cannon, the ball, the ground, and the target. If you don't want to use images, you can use drawings for the target and the hit target. You can draw other things on the canvas. You just need to make sure that the cannonball (or whatever you set your projectile to be) is on top or wherever you want it to be. You could, for example, make the ground cover up the ball. You can use an animated gif for any Image object, including the htarget. You could also use images for the cannon and the ball. One possibility is to use an animated gif file to represent a spinning cannonball. Remember that all image files referenced in the code must be in the same folder as the uploaded HTML file. If they are in a different place on the Web, make sure the reference is correct.
128
The support for audio and video in HTML5 varies across the browsers. You can look ahead to the presentation of video as a reward for completing the quiz in Chapter 6, and to the audio presented as part of the rock-paper-scissors game in Chapter 8. If you want to tackle this subject, it would be great to have a sound when the cannonball hits the target and a video clip showing the target exploding.
Moving away from the look of the game, you can invent a scoring system, perhaps keeping track of attempts versus hits.