Boxes are cooler when they explode. Quite reasonably, boxes should explode when clicked on, so I need to reassign the creation of boxes to a function that happens to be not the click handler. The initialization function strikes me as a good place to put all that!
... init = function(){ // This function will start things time = new Date().getTime(); setInterval("draw();",20); for(i=0;i<20;i++){ makeBox(5,5); } } ...
Now, that makes a whole lot of boxes, so let's make some way to explode the damn things:
... explodeBox = function(n){ box = boxes[n]; boxes.splice(n,1); if(box.size == 90) for(i=0;i<3;i++){ var y = (box.y-30)+30*i; for(j=0;j<3;j++){ var x = (box.x-30)+30*j; var dvx = (Math.random()-1.0)/9; var dvy = (Math.random()-1.0)/9; boxes.push(new Box(x,y,box.vx+dvx,box.vy+dvy,30,box.color)); } } } ...This function accepts the index of the box I want to explode in the
boxes
array as its input and starts by removing that box from the array. After that, the function pushes nine new, smaller boxes into the array, each having the same color as the original and randomly varied velocity.
All that's left is to make some way to tell the javascript that I want some box to explode, and which box it is. I do this by modifying the click handler:
... clicker = function(event){ var x = 0; var y = 0; if(event){ x = event.pageX - newCanvas.offsetLeft; y = event.pageY - newCanvas.offsetTop; } for(i=0;i<boxes.length;i++){ box = boxes[i]; if(Math.abs(x-box.x)<45 && Math.abs(y-box.y)<45 && box.size==90){ explodeBox(i); } } } ...
The result is quite interesting, visually, but isn't a game yet. Sure, you can click on boxes to make more boxes, but there is no score and no end, so it's just a toy. A good step in the direction of a game is some sort of situation in which the player know he's done, so I'm going to make the smaller boxes explode as well, but this time, the remains won't stay on the screen until the end of time. This way, a "player" can clear the screen and feel good about himself.
So, to destroy boxes altogether, I need to declare an array to hold the elements the boxes break up into. Sticks are my shape of choice, since that's what squares are made up of.
... var sticks = new Array(); ... Stick = function(x,y,theta,vx,vy,length,omega,color){ this.x = x; this.y = y; this.theta = theta; this.vx = vx; this.vy = vy; this.length = length; this.omega = omega; this.color = color; } ...Unlike boxes, sticks can rotate, so the sticks have an extra coordinate, theta, and an extra velocity term, omega. Like boxes, sticks have a color and a size.
Next, I want to modify the function that explodes boxes to be able to handle the smaller boxes:
... explodeBox = function(n)... ... if(box.size == 30){ var dvx = (Math.random()-1.0)/11; var dvy = (Math.random()-1.0)/11; var omega = (Math.random()-1.0)/90; sticks.push(new Stick(box.x,box.y+15,0, box.vx+dvx,box.vy+dvy, 30,omega,box.color)); dvx = (Math.random()-1.0)/11; dvy = (Math.random()-1.0)/11; omega = (Math.random()-1.0)/90; sticks.push(new Stick(box.x,box.y-15,0, box.vx+dvx,box.vy+dvy, 30,omega,box.color)); dvx = (Math.random()-1.0)/11; dvy = (Math.random()-1.0)/11; omega = (Math.random()-1.0)/90; sticks.push(new Stick(box.x+15,box.y,Math.PI/2, box.vx+dvx,box.vy+dvy, 30,omega,box.color)); dvx = (Math.random()-1.0)/11; dvy = (Math.random()-1.0)/11; omega = (Math.random()-1.0)/90; sticks.push(new Stick(box.x-15,box.y,Math.PI/2, box.vx+dvx,box.vy+dvy, 30,omega,box.color)); } } ...
My next step is to modify the click handler so that it calls the box exploding code for the smaller boxes, as well as the large ones:
... clicker = function(event){ ... for(i=0;i<boxes.length;i++){ box = boxes[i]; if(Math.abs(x-box.x)<box.size/2 && Math.abs(y-box.y)<box.size/2){ explodeBox(i); } } ...As well as the drawing function, so it actually draws the sticks:
... draw = function(){... ... for(i=0;i<sticks.length;i++){ var stick = sticks[i]; var x1 = stick.x + (stick.length/2)*Math.cos(stick.theta); var y1 = stick.y + (stick.length/2)*Math.sin(stick.theta); var x2 = stick.x - (stick.length/2)*Math.cos(stick.theta); var y2 = stick.y - (stick.length/2)*Math.sin(stick.theta); stickPhysics(stick,i); newContext.lineWidth = 3; newContext.beginPath(); newContext.moveTo(x1,y1); newContext.lineTo(x2,y2); newContext.strokeStyle = stick.color; newContext.stroke(); } ...A keen eye will spot in there a call to the function
stickPhysics
, so I should probably make that function so I don't run into errors.
... stickPhysics = function(stick,n){ var newTime = new Date().getTime(); var dt = newTime - time; var newx = stick.x + dt*stick.vx; if(newx > 320){ stick.vx = -Math.abs(stick.vx); newx = stick.x + dt*stick.vx; } if(newx < 0){ stick.vx = Math.abs(stick.vx); newx = stick.x + dt*stick.vx; } stick.x = newx; stick.theta = stick.theta+dt*stick.omega; if(stick.theta > 2*Math.PI){ stick.theta = stick.theta - 2*Math.PI; } if(stick.theta < 0){ stick.theta = stick.theta + 2*Math.PI; } stick.vy = stick.vy + dt*0.0001; var newy = stick.y + dt*stick.vy; stick.y = newy; } ...
The result of all this is below
Next time, I work to make this more into a game and less of a toy.
No comments:
Post a Comment