Tutorial - Sprite Collision Detection

Sprite Basic has a built-in physic engine, used to move bodies under forces and detect/react to collisions
However, sometimes when you need basic collision detection and don't want to use forces to move objects, you can use the sprite collision detection system.
We will show how to design a simple ball breaker demo using this system.

Setting the scene : adding walls

After setting the screen logical dimensions and getting a renderer, like seen in Web GL Renderer Tutorial, we now make still in OnInit() method some walls on top, right, left of the scene to prevent the ball going off bounds
We will use to do so the renderer.createShapedSprite() function, that computes a shape from a type ('rectangle','roundRectangle','circle' or 'ellipse'), an outline color and linewidth, a fill color, a width, an height and x and y position
An important thing to remember is that position of a sprite or a body is the position of its center
So a sprite going from 0 to width has for x position : width/2, and for x size : width
Because we will later check collisions against those walls, we will push those walls into a list.

object top=renderer.createShapedSprite("rectangle","boundarie",0xff0000,0x000ff,2,width/2,10,width,20) // red outline, blue fill, 2 pixels outline width, position width/2,10 size widthx20 boundaries.push(top) object left=renderer.createShapedSprite("rectangle","boundarie",0xff0000,0x000ff,2,10,20+(height-20)/2,20,height-20) // remember that position of a sprite or a body is its center position boundaries.push(left) object right=renderer.createShapedSprite("rectangle","boundarie",0xff0000,0x000ff,2,width-10,20+(height-20)/2,20,height-20) // so a sprite going from 0 to width has x position width/2, and x size : width boundaries.push(right)

Setting the scene : creating the bricks

We will place bricks on the screen using two for loops
The inner for loop, draw a line of bricks, the outer loop repeat this operation 7 times so we have 7 lines of bricks
You may have noticed that if you upload graphics, x and y dimensions are appended to the end of filename
However, when it comes to slicing a sprite sheet, instead of appending the dimensions, the slicer append an index to the end of filename
This to allow creating sprites or especially animations of a sprite sheet through a for loop instead than filename by filename
Note that because filename must be known at compile time to allow for the build-it loader to cache the sprite upon splash screen showing, the index must be an index of a for loop and only one index is permitted in a filename at the time of writing (we may extends that if a popular request)
This is then how looks the bricks routine :

for i=0 to 7 for j=1 to 9 object brick=renderer.createSprite("brick","ball-breaker/Arkanoid_1_"+i+".png",j*70+50,i*25+70,70,22) // label, texture, x position, y position, width and height (last two optional) bricks.push(brick) next next

Adding a paddle and ball

Ball and paddle are created with the renderer.createSprite() function that takes a texture, x and y coordinates and optional width and height (if omitted texture dimensions will be used)
Like for any object, you can store properties onto the object for later use, instead of keeping the property reference in a global variable
Here we set vx and vy to the ball corresponding to the speed, which will also be used to 'bounce' automatically the ball upon collision
If you get unexpected result after setting a property, change your property name, it could be used already internally (rare but don't set x and y directly for example, position wouldn't adapt correctly to screen size)

ball=renderer.createSprite("ball","ball-breaker/Arkanoid_1_11.png",width/2, height*.75, 20, 20) ball.vx=-2 ball.vy=-2 paddle=renderer.createSprite("paddle","ball-breaker/Arkanoid_1_12.png",width/2, height*.92, 100, 20)

The OnUpdate loop : moving ball and checking collision

As we saw earlier, OnUpdate() is called each frame. This allow to move the ball by adding the speed vx and vy to the current ball position
Then we test the ball against the list of walls. We specify collider types for better accuracy and prevent sprites from overlaping setting the fifth parameter to true, making the ball bounce setting the sixth parameter to true
Because we used vx and vy properties to store speed on ball object, those values will be changed accordingly upon collision, making the bouncing reaction
We do same for each brick, still using the renderer.collideList() function. If a brick sprite is returned upon collision, we remove it from list and from screen
We make paddle follow ball and check ball against paddle collision using renderer.collide() function (single object collision detection). Ball would bounce same way

ball.setPosition(ball.getPositionX()+ball.vx,ball.getPositionY()+ball.vy) // move ball according to speed renderer.collideList(ball,"circle",boundaries,"rectangle",true,true) // check collisions between ball, of type circle, with the walls of type rectangle, prevent from overlaping and making it bounce object brick=renderer.collideList(ball,"circle",bricks,"rectangle",true,true) // same for brick, because 'bounce' is set to true, vxx and/or vy will change automatically upon collision if brick!=null // if ball has collided a brick renderer.remove(brick) // remove brick sprite from screen bricks.pop(brick) // remove brick sprite from list endif paddle.setPosition(ball.getPositionX(),paddle.getPositionY()) // make paddle follow ball renderer.collide(ball,"circle",paddle,"rectangle",true,true) // check paddle/ball collision, preventing from overlaping and making bounce

You can try the code in TUTO-SPRITE-COLLISION project on the Guest Account
You can find reference of the functions used in the Documentation