-
Notifications
You must be signed in to change notification settings - Fork 0
2. Creating Sprites
The introduction got us going nicely but in reality you wouldn’t want to do things like that. If we did the code could end up getting very complicated very quickly. The whole reason we use an object-oriented (OO) programming style is to keep things separate and clean. So lets do our first real bit of OO Programming.
The first thing you should learn is that the CVSprite class wasn’t designed to be used directly. It was designed with inheritance in mind. So if you want to create a new type of sprite, create a new class for it and make it inherit from (Extend) CVSprite like this:
var MyBall = new Class({ Extends: CVSprite, });
Put this code at the top of your script underneath this comment: // create your Sprite classes here
Now if you alter this line of code:
var mySprite = new CVSprite({ image: myImage });
to say this:
var mySprite = new MyBall({ image: myImage });
you will find that your code will run exactly the same as before.
You may be wondering what the point in doing this is. Well I like to think of it this way: CVSprite is a badass at what he does. He was built for a purpose and he does that one thing very well. But if you try and teach him anything new he’s gonna throw a fit and have a nervous breakdown. So what we do is clone CVSprite and in the process add some new skills. A sort of CVSprite2.0. If we then later find that we like the new one the way it is but would like to add some new skills again then we can clone our CVSprite2.0, add the skills we need and get a CVSprite3.0. The Class being cloned is known as the ‘Parent’ class and the clone in known as the - you guessed it - child class. So with that in mind lets teach our MyBall()
class some new skills.
Re-write MyBall to read this:
var MyBall = new Class({ Extends: CVSprite, update: function(){ var pos = this.getPos(); this.setPos(pos.x+1, pos.y+1); }, });
We have now cloned the CVSprite class and taught it how to update itself. Awesome! You will probably have noticed that the code here is very similar to what we put in our loop function. The only difference if that we are now referring to this
rather than mySprite
. This is because it is referring to itself and then telling itself what to do. With this in mind we can now remove these two lines of code from our loop function:
var pos = mySprite.getPos(); mySprite.setPos(pos.x+1, pos.y+1);
and replace them with this:
mySprite.update();
We are now calling update()
on our mySprite
object which then tells itself what it needs to do. Again, if you now run the script you will see that nothing has changed and the game runs just the same as before. Let’s change that.
Before we get into doing anything new with our sprite let’s clean it up a little bit more. First lets add some new attributes to our new class. we’ll call them dx and dy, standing for ‘difference in x’ and y. Alter your class so it now looks like this:
var MyBall = new Class({ Extends: CVSprite, initialize: function(args){ this.parent(args); this.dx = 2; this.dy = 2; }, update: function(){ var pos = this.getPos(); this.setPos(pos.x+1, pos.y+1); }, });
The first thing we have is the initialize()
method. This is a method that you will never call explicitly and is used for setting up the initial attributes of the object being created. CVSprite already has an initialize()
method and that is why we need to pass it the arguments with this.parent(args)
This is basically the same as calling initialize(args)
on CVSprite. Next we add the attributes this.dx
and this.dy
to MyBall
Again, the this
keyword makes the attributes belong to the object being created.
Next lets create a new method to calculate the position of the sprite and move some things round again:
var MyBall = new Class({ Extends: CVSprite, initialize: function(args){ this.parent(args); this.dx = 2; this.dy = 2; }, update: function(){ this.calcPostion(); }, calcPosition: function(){ var pos = this.getPos(); this.setPos(pos.x + this.dx, pos.y + this.dy); } });
So now our object has a way to calculate its position and move itself. Lets put that to use now. Add the following method below calcPosition()
:
checkBounds: function(){ if(this.rect.left() < 0 || this.rect.right() > CVCanvas.width){ this.dx *= -1; } if(this.rect.top() < 0 || this.rect.bottom() > CVCanvas.height){ this.dy *= -1; } },
and alter update()
so that it now calls the method:
update: function(){ this.checkBounds(); this.calcPosition(); },
If you now reload the page you will see the results of our script. Our ball now bounces around happily inside our canvas.
The rect
attribute is one that all CVSprite objects have. It represents an invisible box around the sprite which is usually the size of the image being used. It is of course adjustable but we won’t go in to that now. This code in checkBounds()
checks if the edges of the rect
come into contact with the CVCanvas
boundary and reverses the relevant direction. CVCanvas
is a CanVerse2D object that represents the canvas supplied in CVSetCanvas();
Here’s the entire script all together:
var MyBall = new Class({ Extends: CVSprite, initialize: function(args){ this.parent(args); this.dx = 2; this.dy = 2; }, update: function(){ this.checkBounds(); this.calcPosition(); }, calcPosition: function(){ var pos = this.getPos(); this.setPos(pos.x + this.dx, pos.y + this.dy); }, checkBounds: function(){ if(this.rect.left() < 0 || this.rect.right() > CVCanvas.width){ this.dx *= -1; } if(this.rect.top() < 0 || this.rect.bottom() > CVCanvas.height){ this.dy *= -1; } }, }) window.onload = function(){ CVSetCanvas(document.getElementById('canvas1')); var myImage = new CVSurface({width: 80, height:80}); myImage.circle(); var mySprite = new MyBall({ image: myImage }); CVSetLoopFunction(function(){ CVClearCanvas(); mySprite.update(); mySprite.draw(); }); CVInit(); CVMainloop(); }
Now would be a good time to have a play around to get a feeling for CanVerse2D. Check the next tutorial when you’re ready.