You get a 68% lifetime learning discount!

Ready to level up your career? This week, we're offering new learners a lifetime discount on Educative subscriptions. Popular topics include:

System Design
Generative AI
Interview Prep
ML/Data Science
Home/Blog/Programming/Polish your JavaScript: Create a Breakout game
Home/Blog/Programming/Polish your JavaScript: Create a Breakout game

Polish your JavaScript: Create a Breakout game

27 min read
Jul 02, 2024
content
The starter HTML and CSS template
Displaying all of the blocks
A JavaScript class for the blocks
Displaying a row of blocks
Displaying three rows of blocks
The bat
Bat movement
Ball functionality
Displaying the ball
Get the ball rolling
Maintaining coordinates for each corner of a block
Ball rebounds
Rebound from walls
Rebound from the bat
Collisions with the blocks
Rebound from blocks
Score and finishing touches

When learning to code, practicing by creating applications is extremely important. Early-stage learners often get discouraged by the complexity of it. Creating games is a great way to practice coding for various reasons. First, we’re familiar with the game rules, which removes some of the complexity from the process. Second, games are fun, so we enjoy ourselves coding them. This blog assumes basic knowledge of HTML, CSS, and JavaScript.

In this blog, we’ll create a clone of the classic console game Breakout. The game has a bounding rectangle inside which the game elements reside. There are three rows with six blocks in each. There’s a bat and a ball. The ball bounces off the bat or the wall. When the ball hits a block, it pops and disappears. For each popped block, the player gets 10 points. If the ball hits the lower edge of the bounding rectangle, the game is over. Here’s a live preview of what we are going to build. Click the “Run” button to try it out. Use the right and left arrow keys to move the bat around:

The complete code

Here’s what we need to do:

  • Create a bounding rectangle.

  • Create the blocks and render them inside the container.

  • Maintain the coordinates of each block so that we can check for collision.

  • Create a ball and render it within the bounding rectangle.

  • Set the ball in motion and periodically update its location.

  • Create a bat and render it within the bounding rectangle.

  • Handle keystrokes to update the bat’s position.

  • Implement detection of the collision of the ball with the bat, the walls, or the blocks.

  • Implement block removal and score updates on the collision of the ball with a block.

  • Implement ball rebound on the collision of the ball with the walls or the bat.

The starter HTML and CSS template#

Let’s start with a basic HTML document and CSS styling:

HTML template and CSS

We start off with a container div element with one div element inside it. We give each of these div elements different classes. The block type div element is just to get us started. We’ll render all the blocks programmatically later on.

Coming to the CSS now. During the game, the player will hit the blocks, making them disappear, so we’re not looking for a responsive design. So, instead of using CSS Flexbox or Grid to position the blocks, we’ll use plain-old CSS positioning.

We want blocks that are 100 pixels wide and 20 pixels in height. If we lay out six of these in a row, with 10 pixels of spacing in between and around the blocks, we need the game canvas to be 100×6+7×10=670100 \times 6 + 7 \times 10 = 670pixels. Accordingly, we set the width for the grid element to 670 pixels on line 2. We set its height to 300 pixels on line 3. We assign a black border to it on line 4. We also set the position property to absolute on it (line 5). This value for the position property is chosen to control their positioning. The browser will position them relative to their nearest positioned ancestor element rather than the normal flow of the web page. Otherwise, as one block pops, others after it will shift to fill the vacated space, which isn’t how the game is played.

We want to center the gameplay area horizontally on the screen. For that, first, we set the left property to 50% (line 6), which places the left edge of the div element with a class of grid horizontally at the center of the page. But we want that div element’s horizontal center to be aligned with the horizontal center of the page. For that, we apply a translate transform to shift the div element to the left by half of its width (line 7).

We also style the block class with a width of 100 pixels (line 11), a height of 20 pixels (line 12), and a bluish background color (line 13). We set its position property to absolute, as well (line 14). We then set its left and bottom properties to 10 pixels each (lines 15–16). What’s going on with that?

By setting the position property to absolute for the element with a class of block in line 14, we are taking it out of the normal flow of the element placement. This would have placed the inner div near the left top corner of the outer div. The inner div will now be placed relative to the nearest ancestor with a position other than static. In our case, it is the outer div with a style of grid. The left: 10px directive tells the browser to place the block element 10 pixels from the left edge of the element with the class of grid. Similarly, bottom: 10px tells the browser to place it 10 pixels from the bottom of the grid element. At this point, in the “Output” tab, we see a blue colored block near the bottom of the rectangle with a black border.

Displaying all of the blocks#

We can’t hard-code all the blocks in index.html. We have to create the blocks using JavaScript. So, let’s remove the div element with a class of block from index.html and try inserting it using JavaScript.

Displaying a block using JavaScript

We access the div element with a class of grid using the querySelector() method in line 1. We create a new div element using the createElement() method in line 2. We add the class of block to the new element in line 3 and add it as a child to the grid element in line 4.

At this point, the page should render the same as it did in the previous coding playground, even though we removed the inner div from index.html.

A JavaScript class for the blocks#

All of the blocks share certain characteristics. For example, they are all rectangular. They all have the same width and height. The bat with which the player hits the ball also shares a rectangular shape. We’ll use object orientation to capture these similarities and not rewrite code. In this blog, we use the old-school way of declaring classes in JavaScript.

Modern JavaScript has the class keyword to define classes, but that is just syntactic sugar over the old-school way of doing object orientation in JavaScript using the prototype keyword. It helps to be aware of what lies beneath the surface.

Displaying a block using object-oriented code

We define variables to store the width, height, and coordinates of the blocks (lines 1–4) so that, given the bottom-left position of a block, we can calculate the coordinates of all four of its corners. We define a function named Block (lines 8–13), which we later use as the constructor for the block objects. We pass in the bottom and left positioning values, which we had previously hard-coded in CSS. The function also accepts the width and height of the block. Given these values, we calculate and store the coordinates for all four corners (lines 9–12). Note that in our system, the origin is at the bottom-left corner of the grid element; the x coordinate increases from left to right, whereas the y coordinate increases from bottom to top. For each corner, we create an object with x and y values for the coordinates. The following illustration might help wrap your head around the four coordinate calculations.

canvasAnimation-image
1 / 4

Having declared the constructor, we define an array to hold the blocks (lines 15–17). For now, we create just one, with hard-coded bottom and left parameters. In line 19, we call a function named displayBlocks() to display the blocks. In this function, for each block in the blocks array, we create a div element (line 23), assign it a class of block (line 24), set its left and bottom style values to the x and y values of the bottom-left of the Block object (lines 25–26). Notice that we concatenate the string px to the number stored in the object for these values since CSS expects a unit specification. Finally, since we are setting the left and bottom attributes in the code, we remove those from the block class specification in CSS.

Switching to the “Output” tab in the above coding playground shows a single block inside the grid container near the top left corner of the grid.

Displaying a row of blocks#

Let’s now try to create a row of blocks in JavaScript without hard coding. Let’s start with the first row. With 10 pixels on either side of each block, a block width of 100 pixels, and a block height of 20 pixels, the first row should have bottom left coordinates as shown in the following diagram:

Coordinates of the bottom-left corner of the six blocks in the first row
Coordinates of the bottom-left corner of the six blocks in the first row

The y-coordinate for all blocks is the same since they are aligned in a row. Why is it 270? The grid container is 300 pixels in height, we want to leave 10 pixels from the top, and the block height is 10 pixels, so that takes away a total of pixels from the 300 pixels, leaving us pixels.

For the x-coordinates, the first block is 10 pixels away from the left edge, so that’s 10. How much further do we need to go along the x-axis to get to the left edge of the second block? We have to go across the first block’s width, so that’s 100 pixels, and we also have to leave 10 pixels to the right of the first block, so that’s a total of 110 pixels. Since the first block had an x-coordinate of 10, the second block has 10+110=12010 + 110=120 pixels. Each subsequent block will have its bottom left x-coordinate increment by 110 pixels.

If the block numbers go from 0 to 5, left to right, then a general formula for the x-coordinate of the ith block is: 10 + i * (width + 10). The first 10 is the left margin we left before the first block. Each subsequent block, as we discussed, is offset by 110 pixels or width + 10 pixels, in general. A function to create the first row of blocks is given below:

Displaying a row of blocks

First, rather than hard-code the numbers for the coordinates that we calculated, we declare constants to hold the dimensions (lines 3, 5, and 6). We change the blocks array definition and remove the hard-coded initialization from earlier (line 13). Since this array is to be assigned later in the code, we changed the definition to use let rather than const. We call a function named createRow() on line 15. We define this function in lines 29–34. It uses a for loop that runs six times to create Block objects with the coordinates set according to the formula we discussed above (line 31). We append each object to the blocks array using the Array.push() method on line 32.

In the “Output” tab in the above coding playground, we see the first row of six blocks nicely set out on the screen.

Displaying three rows of blocks#

After creating and displaying one row programmatically, let’s generalize to more than one row. The six blocks in all rows are set apart exactly alike, as far as the x coordinate is concerned. The only difference is the y coordinate.

What’s the y-coordinate for the bottom-left corner of the first row? It is 300(10+20)=270300 - (10+ 20) = 270 pixels. What’s the y-coordinate for the bottom-left corner of the second row? Well, you come down 10 pixels since you’re leaving 10 pixels between rows. Then, you come down 20 pixels, which is the block height in the second row. So, you have 270(10+20)270 - (10 + 20) pixels. So, for each subsequent row, we take away 30 from the y-coordinate. If the row numbers go from 1 to 3, the y-coordinate of the bottom-left corner of the jth row is 300j×30300 - j \times 30 pixels.

We can modify our createRow() function to accept the row number as an argument and call it repeatedly in a loop from another function named createRows().

Displaying three rows of blocks

The outer loop iterates over the rows, and the inner loop iterates over the blocks in a specific row. The x-coordinate calculation is exactly as before. The y-coordinate calculation is as we just described. If you switch to the “Output” tab, you’ll see three rows of six blocks on the screen.

The bat#

Let’s display the bat that the player can move around. We’ll create it with a div that has the same dimensions as a block. We’ll use a different color. We’ll then position it in the middle of the canvas near the bottom.

Let’s draw out where the bat should be positioned so that we can calculate its left and bottom offsets. As shown in the following diagram, there are two and a half blocks and a total of three inter-block spaces to the bat’s left. In case you’re having difficulty understanding why there are three inter-block spacing, here’s how. First, there are the 10 pixels to the left of the leftmost block, then there are the 10 pixels between the first and the second block, and finally, the 10 pixels between the second and the third blocks.

canvasAnimation-image
1 / 3

Since each block is 100 pixels wide, that gives us a total of 250+30=280250 + 30 = 280 pixels as the left offset/margin. We’ll keep a bottom offset of 10 pixels. Now, onto rendering the bat.

We can reuse the Block class, since the bat appears similar to the blocks except for its color. So, we can do a const bat = new Block(280, 10, blockWidth, blockHeight). Let’s now display it on the page. When you start writing const bat = document.createElement(‘div’), followed by bat.classList.add('bat'), you should have a “wait a minute!” moment. Haven’t you written that code somewhere already? Sure enough, it resides inside the displayBlocks() function.

Can we call that function to display the bat? A better idea is to refactor the code to create a displayBlock() function that you can call for any block, whether it’s the bat or a block. Here’s the refactored code for displayBlocks().

Displaying the bat and blocks with refactored code

We modify the implementation of the displayBlock() function on lines 35–41. Rather than adding a hard-coded CSS style to the Block object, we pass the Block object to displayBlock() as well as the style. From the forEach in displayBlocks() (line 32), we call this function. We declare constants to hold the bat’s coordinates (lines 13–14), create the bat object on line 15, and pass it in a call to displayBlock() in line 16.

For that bat, we need to define a distinctive CSS style. Since the bat shares the dimensions and positioning properties with the other blocks, we go ahead and share the style definition between the two classes (line 10). The only distinguishing characteristic of the bat, as opposed to the other blocks, is the color. To achieve that, we add a style definition for the bat class on lines 17–19. Note that all the properties defined for the bat on lines 11–14 are effective, except for the background color, which we override on line 18 because, as per CSS specification rules, all other things being equal, the last assigned value to a property takes effect.

Bat movement#

Now, let’s try to implement the bat movement with the arrow keys. Here’s what we need to do:

  • Register an event handler for key presses.

  • In the above event handler:

    • Check if the pressed key is a left or right arrow key.

    • Move the bat left or right depending on the key pressed.

Let’s start by implementing the left movement.

Note: To see the bat movement in response to keystrokes, you need to click the game in the “Output” tab to set focus correctly.

Adding code for left arrow movement

On line 18, we add an event listener to the document object for key-down events. In the event listener function defined on lines 61–70, we obtain the key pressed in the variable key on line 62. Then, we have a switch-case statement to handle the arrow keys. At the moment, we are only handling the left arrow key. We have access to the bat thanks to the bat variable, but how do we update its left position?

We add a method named setX() (lines 27–29) to the Block class that updates the block position and calls it to decrement the x coordinate of the bottom-left corner by 10 pixels (line 28). For correctness, the coordinates of the other corners should also be updated, but we’ll do that later.

In the key press event handler, we call setX() to update the bat’s left position. Note that this doesn’t visually update the bat on the screen. We only update a data structure that we used to store the intended position of the bat. To update it on the screen, we query the DOM element with the class of bat (line 66) and update its position on the screen (line 67).

Don’t forget the break at the end of a case statement. It is usually necessary.

Now, the bat moves left across the screen. The bug is that it doesn’t stop at the left edge. Let’s fix that.

Limiting the left movement to the edge of the screen

We define a variable named stepSize (line 4) to hold the number of pixels that the bat should move on one key press. Now, thanks to the if statement on line 65, we only update the bat position if it isn’t already at the left edge.

Next, let’s add the code for the right movements. We’ll need to limit the bat movement to the right edge. When the bat reaches the rightmost point, what is the bottom left x coordinate? The total grid size is 670, a 10 pixel margin to the right of the bat, plus 100 pixels for the bat width, which leaves us 67010010=560670 – 100 – 10 = 560pixels as the answer.

Implementing the bat’s right movement

The code block on lines 59–65 implements the bat’s right movement. When you switch to the “Output” tab, we’ll be able to move the bat left as well as right.

Ball functionality#

Now, let’s add the ball to the mix. We start with displaying the ball.

Displaying the ball#

The Block JavaScript class is generic enough to be used for the ball. However, for a distinctive look, we need to define a new CSS class.

Displaying the ball

We define variables to hold the dimensions of the ball on lines 4–5. We define a Block object named ball to represent the ball in the game in line 14 and display it using the displayBlock() function on line 15. We pass ball as the name of the class to this function. This class is defined in CSS on lines 21–26. Now, you’ll see a static green-colored ball slightly above the bat on the screen in the “Output” tab.

Get the ball rolling#

Let’s get the ball to move diagonally toward the top right. Here’s the updated JavaScript code:

Animating the ball

We declare variables for the interval at which the ball’s position should be updated (line 23), initialized to 25. We declare constants for the ball’s velocity along the x and y axes (lines 24–25). We initialize these to 1. In other words, the ball will move upward and toward the right (northeast) on every step by one pixel. We define a function named moveBall() (lines 97–103) that increments the ball’s x and y coordinates by the ball’s velocity along the respective axis each time it is called. We call setInterval() in line 105 to have this function called every 50 milliseconds. To support this function, we add a setY() method to the Block class on lines 93–95. When we switch to the “Output” tab, we see the ball travel toward the top right and ultimately disappear.

Maintaining coordinates for each corner of a block#

At the moment, we are updating only the coordinates of the bottom-left corner in the setX() and setY() methods of the Block class. It is a good idea to maintain the coordinates for all four corners instead. We should also store the block width and height as attributes of the Block class in the constructor.

Updating coordinates of each corner of a block

We store the width and height of a block as attributes in the Block class on lines 37–38. When updating the x and y coordinates of a Block object, we now update the coordinates of all four corners of the block (lines 43–45 and 50–52).

Ball rebounds#

Let’s implement the ball rebounds on collision with the side walls, top walls, or the bat, and game over on collision with the floor.

Rebound from walls #

Let’s now detect collisions between the ball and a wall, which should result in a rebound, or in case of collision with the bottom wall (or floor), game over.

The ball collides with the left wall if its left bottom (or top) corner’s x-coordinate is equal to the wall’s x-coordinate. After the collision, it changes its direction. The following illustration shows two ways the ball may collide with the left wall and the corresponding reactions. Similar cases exist for the other two walls.

canvasAnimation-image
1 / 2

From slide 1 above, we can see that if the ball’s y-coordinate decreases before the collision, it continues to decrease. From slide 2, we can see that if the ball’s y-coordinate increases before the collision, it continues to increase. The x-coordinate, on the other hand, changes direction in both cases. If the x-coordinate initially increases (when the ball is moving upwards toward the right), it starts to decrease after the collision, and vice versa.

In the moveBall() function, we hard-coded the increments in the x and y-coordinates: ball.setX(ball.bottomLeft.x + 1) and ball.setY(ball.bottomLeft.y + 1). Rather than hard-coding an increase by 1, we can use a variable that is either +1 or -1. For example, we could change the x-coordinate with ball.setX(ball.bottomLeft.x + xDirection). By changing the value of the variable xDirection, we can achieve rightward or leftward motion.

Here’s the code for the collision with the top and the left wall, along with the code for moveBall:

Handling collisions of the ball with a wall

We declare a function checkCollisions() (lines 116–123). We check if the ball’s bottom-right edge reaches the left wall. If so, we reverse the x direction. Similarly, if the ball’s top right edge reaches the top wall, we reverse the y direction. We make a call to this function from within moveBall() on line 106.

Click the “Run” button in the coding playground above, and you’ll see the ball go upward to the right, hit the ceiling, rebound, hit the right wall, and then disappear below the floor.

Rebound from the bat#

With the above code, the ball doesn’t bounce off the bat. The collision detection with the bat is similar to collision detection with the blocks. However, the rebound is slightly different. The ball changes its direction after colliding with the bat differently depending on whether it hit the bat on the left half or the right half. After a collision with a block, we just want the ball to reverse its x direction.

Handling collisions of the ball with the bat

In line 117, we check the ball’s collision with the bat as a logical AND of the following three conditions:

  • The ball’s bottom-right x-coordinate is at or to the right of the bat’s top-left x-coordinate.

  • The ball’s bottom-left x-coordinate is at or to the right of the bat’s top-right x-coordinate.

  • The ball’s bottom-right y-coordinate equals the bat’s top-right y-coordinate.

The AND of the first two conditions collectively ensures that the ball’s projection on the x-axis intersects that of the bat. The last one ensures that the ball has reached the same height as the bat. Now, we should see the ball rebound off the walls and the bat.

Collisions with the blocks#

Now, onto detecting collisions with a block. After updating the ball’s position, we’ll iterate over the blocks to see if it has touched any of the blocks.

The ball may hit any of the four edges of a block for a hit to occur. Let’s start by checking if we hit the block from below:

Console
Checking collision with a block

We use Array.findIndex() (line 134) to find an element from the blocks array with which we had a collision, if at all. We’ll either have a collision with one block or with none at all. Why didn’t we use Array.find()? Because it returns the element if found, not its index. We need the index of the matching element because we want to remove the block from the array, which requires using the Array.splice() function with the element’s index.

We pass the custom comparison function checkBounds to the findIndex() call. The findIndex() method calls this comparison function on every element of the blocks array. The blkIndex variable is set to the index of the first element for which this comparison function returns true. If this function doesn’t return true for any element, then blkIndex is set to -1.

In checkBounds(), we project the position where the ball will be after the next animation. We check if this next position lies within the block. The first two conditions in the if statement (lines 143–144) check if some part of the ball will be in the blue-shaded region in the following illustration. The other two conditions (lines 145–146) check if some part of the ball will be in the red-shaded region in the following illustration. If both of these conditions are true, then the ball has collided with the block. So, we return true (line 147). Otherwise, we return false (line 148).

A collision with a block occurs if the ball is within the intersection of the blue and red regions
A collision with a block occurs if the ball is within the intersection of the blue and red regions

With the above code, you should see a bunch of messages in the JavaScript console whenever the ball hits the bottom edge of a block. When you click the “Run” button in the above playground, you’ll notice that not only the ball’s upward but downward motion triggers the console.log(). The latter one is spurious. We’ll fix this once we start rebounding the ball after a collision.

Great! Now, you should see the console messages when the ball hits any edge of a block. What do we do when that happens? We’ll go ahead and remove that div element from the DOM and the blocks array. The former removes the element from the page, while the latter helps future processing focus only on the remaining blocks. Here’s the code with those changes:

Making blocks disappear when hit

In line 137, we get a collection of all DOM elements that represent the blocks on the screen. We then use the blkIndex variable to remove the block that was hit from the DOM on line 138. Finally, in line 139, we remove the block from blocks array as well so that we no longer check for collisions with this block on later calls to blocks.findIndex(). Now, you should see several blocks disappear from the screen. But the ball isn’t rebounding after hitting the block.

Rebound from blocks#

Now, let’s add the functionality to make the ball rebound after hitting a block. If the ball hits the block on its left or right side, it will continue in the same vertical direction but change its x direction. On the other hand, if the ball hits either the top or bottom edge of a block, it will continue along the same x direction but will reverse its vertical direction. The following illustration shows this.

The direction of rebound after collisions with different edges of the block
The direction of rebound after collisions with different edges of the block

Having determined how to react to collision with the top/bottom or side edges of a block, let’s determine how to detect if the ball collides with the side of a block or not. If the ball’s bottom-left (or right) corner is above the top edge or its top-left (or right) corner is above the bottom edge of the block, then the collision is with either the top edge or the bottom edge of the block. These conditions are shown in the following diagram with the dotted lines.

Condition for the left-side collision with a block
Condition for the left-side collision with a block

As the above diagram illustrates, the ball has collided with the top edge of a block if the ball’s bottom-right (or left) y-coordinate is greater than that of the block’s top-left (or right) corner. Similarly, the ball has collided with the bottom edge of a block if the ball’s top-right (or left) y-coordinate is greater than that of the block’s bottom-left (or right) corner.

Here’s the implementation:

Ball rebound after hitting a block

In checkCollision(), we already detected a possible collision with a block in line 136. So, inside that if statement, we insert another if statement to check if the ball hit the block from the right or left in line 137. We write a function named hitSide() for this (lines 157–165). In line 158, we check whether the ball hit the top edge of a block. In line 159, we check whether the ball hit the bottom edge of the block. In line 161, we take the logical OR of these two conditions and return false if it evaluates to true. Otherwise, we return false (line 152). Why do we have the variable ballvy involved in lines 158–159? To understand this, let’s examine line 158. The ball has already collided with the block, so if it hit the block from the top, at this point ball.bottomLeft.y will be exactly equal to b.topLeft.y. However, in this case, in the previous animation cycle, the ball would be slightly above the block’s top edge. By taking away ballvy from ball.bottomLeft.y, we calculate the ball’s previous location and arrive at the correct conclusion.

In hitSide(), we are only checking y coordinates to detect side collisions. Why aren’t we checking the x-coordinates for the collision? The reason is that the x-coordinate checks are done in the checkBounds() function, which was invoked in line 132. Our call to hitSide() was conditional to the value returned by checkCollision(). That’s why we don’t have to re-check the x-coordinates of the ball against that of the block in hitSide().

Notice that we put the bat collision code right at the top. Why is that? If we don’t do it that way, and the ball comes to hit the wall and the bat at the same time, as shown in the following illustration, it will appear to slide over the bat and it’s game over.

A scenario where the ball hits the wall and the bat at the same time
A scenario where the ball hits the wall and the bat at the same time

Score and finishing touches#

Finally, let’s put the finishing touches on showing the score as we play the game and displaying a message when the game is over. Note the additional span element in the HTML file and the highlighted changes in the JavaScript in the following coding playground.

The complete code

At this point, the checkCollision() function is a bit on the longer side. It is time to refactor it. What part of it would you extract into a separate function?

We hope you liked the tutorial. Enjoy the game. Practice your skills by adding features to it. How would you increase the ball’s speed? How would you make the game progressively harder by increasing the ball’s speed after every 50 points? How would you store the highest score statistics? Hint: local storage.

Cover
Building Web-Based Games and Utility Projects Using JavaScript

JavaScript is one of the most popular programming languages for creating interactive web pages, apps, and games. Knowing JavaScript can give you a huge edge in the job market. This course is for you if you want to learn JavaScript by creating hands-on projects instead of learning from theory. It will first introduce you to the basics of JavaScript, such as classes, objects, variables, and DOM manipulation. Then, it will help you create several web-based games and projects using different data structures, such as arrays, linked lists, LRU cache, and graphs. You’ll get clear step-by-step instructions for developing each project, while multiple assessments will help monitor your progress. By the end of this course, you’ll have a solid understanding of JavaScript and how to utilize its different data structures to create actual projects, giving you a good foundation to grow your career in web development, game programming, and interactive media.

18hrs
Intermediate
64 Playgrounds
10 Quizzes

Written By:
Saqib Ilyas
New on Educative
Learn any Language for FREE all September 🎉,
For the entire month of September, get unlimited access to our entire catalog of beginner coding resources.
🎁 G i v e a w a y
30 Days of Code
Complete Educative’s daily coding challenge every day in September, and win exciting Prizes.

Free Resources