Coding Challenge #46.1: Asteroids with p5.js - Part 1

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
you'll be bleep you okay hi everyone I just did a coding challenge where I programmed this game from scratch using the p5.js library in JavaScript and in a moment I'm going to travel back into time and you're gonna watch that coding challenge this is the end result I'm doing this after I actually did it this is recording this part the reason why I'm doing that is I want to mention something to you I want to tell you about Suraj's channel Suraj geology suraj makes video tutorials about machine learning and now that I've done this coding challenge I'm going to pass this game off to Suraj and Suraj is going to train a bot to play it and get a high score now the game doesn't actually have the score features yet I'm going to add that in later so check this video's description for a link to Suraj this video where the bot plays asteroids and hopefully plays it much better than I ever could so now I'm gonna do dinner to go back at the time and starts this coding challenge which will happen in two parts the first part will just be programming the asteroids and the ship and the second part will be the lasers your view nobody likes that upset Gibbs your puke in the chat they're really upset which is only making you do it more which is kind of a problem enjoy the video enjoy the coding challenge see you at the end or in the next one bye alright here we are I'm gonna start programming asteroids from scratch I'm not entirely from scratch because I mean there's a framework called p5.js that has a lot of hooks in it for drawing and animation but the actual game mechanics I'm going to just sort of figure out on the fly I haven't done this before and we'll see what happens if you want to know how long this takes just look at the how long this video is and then you'll know but I don't know because I can't time travel into the future although it would be if someone to figure that out for me I'll be very helpful for a lot of things I need okay let's going this is the game asteroids and here we go so the first thing that I need to do is I think I should program the spaceship the thing that's in the center of the screen that you can kind of like turn and then push around so what I'm going to do to do that is I'm going to create a ship object and the framework that I'm using is called p5.js which has a lot of things will allow me to draw the triangle pretty easily but it also has a vector a vector object built into it so something that I want this ship to have is a position and I'm going to have that position start at the center of the screen which is with / - and height divided by two and then I'm going to write a function called render where I draw the ship as a triangle so how do I draw a triangle there's a function in p5 called triangle and all I need are all I need are three XY coordinates so what I could do is draw a triangle like this if I think of this as like a zero zero then this could be like five comma five this could be like negative five comma five and this could be like negative five comma zero so that would give me three coordinates of the triangle but maybe these shouldn't be five that should be a variable that has to do with the size of it so I'm going to come back over here and I am going to now add this dot R equals ten and I'm going to say a triangle is three points what I looking over there negative this dot R negative this dot R this dot R a lot of this dots this dot R this R and then zero negative this dot R so what I want now is to create a variable this is just to get the ship called ship and then I'm going to say ship equals new ship this is calls this constructor function and creates an object that has a position on R value and a function called render so I can now say ship dot render and I can run this code and we'll see what we've got look there's a nice little triangle but it's up there in the top left corner because I didn't actually use the position so something I can do in p5 is I can take translate the translate function translates the coordinate system by an X and a y-value vectors have an x and a y value so I can say translate by x and a y which essentially will position the ship now where it actually is so I now have that triangle there I could make it a little bit bigger I could also say I could also say no fill and Stroke 255 this says don't fill the interior of the triangle and give the stroke a white stroke and now I have a nice little triangle right there in the center excellent so now what do I need to do I need to be able to figure out a way that when I press the right arrow key and the left arrow key the triangle rotates so let's figure that out the ship rotates so one thing I should probably add here is of a variable called I could call it angle I'm going to call it heading so I'm going to say it's heading is 0 and before I draw the triangle after I translate I'm always going to rotate by this dot heading so we can see now that's that now what if I change the heading to 90 degrees will be pointed to the right hmm that's not exactly right let's not point it to the right because p5i most computer graphics environment think in terms of radians which is a different unit of measurement according then degrees so to the right 90 degrees is PI divided by 2 radians so I can actually say pi divided by 2 and you can see now there it is it's pointing to the right so that's the heading now what I want I mean the heading is something arbitrary I can start it at 0 for right now so what I want to do is I need to be able to rotate it so I need another function and I'll call it this dot turn now one thing about these functions javascript is a funny place with object-oriented programming and objects have this thing called a prototype so this isn't the best way and I've gotten comments about this to just put these functions in the constructor function itself some people like to put them but just for a sort of ease of use and readability right now I'm just putting the functions in here this dot turn equals function so I can say ah maybe this needs a an angle value that it turns by and I say heading plus equals angle so anytime I call this function this dot turn any of I call this function ship turn it'll turn the ship so for example if in the draw loop draws it p5 has a draw loop that animates over and over again if I were just to say ship turn 0.1 we can see ah okay heading is not defined uh always forget this time so I think where did I forget that this dot heading plus equals angle there we go now I have my ship spinning yes okay but I don't want it to just spin randomly I want to spin if I am pressing the right arrow key so now I need to go back to my code and I need to add a key pressed function now p5 allows you to have these kind of global event handlers one of them is function key pressed so anytime I press a key this function will happen and what I want to do here is just check if the key code is a right arrow ship dot turn by 0.1 else if the key code is left arrow ship turn negative zero point one okay that's pretty good right so now I'm going to turn off this turning that's happening in draw I'm hit refresh and now when I press the right key it turns when I press the left key to turn this is kind of terrible I can't hold down the key to turn it I have to press it one at a time so we're going to have to change how this works and actually there's a sort of a funny way I could do this I'm going to I'm going to make a global variable I could probably packages in the object a bit better and actually I'm going to I'm going to make a variable in the object called this dot rotation and set it equal to zero and this dot turn actually just always turns it by that rotation amount and then I'm going to say this dot set rotation is a function that receives an angle and then this taut rotation equals that angle so now what I want to do is when I press the key I want to set the rotation when I release the key I want to unset it because I want to be able to just I want to handle the key pressed and released it differently so now I can say here set rotation point one set rotation negative one and if I add an event for key released now I can say ship dot set rotation zero so now this should what didn't work so what did I miss I've got a bug here was a nice idea right oh you know what I forgot to do I forgot to call ship turn so I always have to turn it I might be turning it by zero sometimes but the function turn is always calling it's always happening in the draw loop uh sketch eleven shiz which is ship okay so now there we go so now as I hold the key down it turns okay there we go it's turning as I hold it down now the next thing I need to do is I need to be able to move it so when I press the up arrow I want to apply a force in the direction that it's pointing let's think about how I'm going to do this so in other words here's my ship let's say it's pointing in this particular direction so I have this particular angle as this variable heading so what I need to do is I want it to have a velocity that's moving in that direction so I need to add two concepts to the ship I need to add the concept of a velocity which changes its position but I also need to add this concept of an acceleration I don't actually the accelerations the thing that changes the velocity so when I press up which is like a boost thrust or boost onto the ship it's like a force that pushes it and it starts to move so let's see how we can add that both of those things will also be vectors so if I go back to the code boy asteroids is much more complicated than I imagined still only on the ship this dot velocity equals create vector zero zero I want to add a function called update which is always updates whatever this object is doing and I'm going to say this dot position add this dot velocity so if I were to run this you can see oh wait first of all I've got I always make this always forget this I've got to actually call now shift update okay now if I hit refresh it's not doing anything but what if I give it a velocity create vector a 1 comma zero so it's velocity is a vector pointing to the right 1 comma zero now if a it refresh there it is it's moving now it's not pointing in the direction then it's moving so many problems here but we're going to fix all of those things the idea here is that the velocity just starts at zero but instead of assigning it a value I'm going to push it so I need some sort of function that's like this dot boost and when I boost it what do I do I add something to the velocity so I need a vector that points in the direction that it's pointing and I know the direction based on an angle so I need to get a vector an X and a y based on that angle fortunately for us p5 as a framework has a function to create a vector from an angle I could do it manually using sine cosine and trigonometry and I have other videos that show that but if I just come over here I can say var force equals P five dot vector dot from angle heading so this will give me a vector that points in the direction of that heading and I can now say this dot velocity ad force so now I need to add else if keycode equals up arrow that'll be my key for boosting it ship dot boost so let's see how this goes now if I press the up key uh heading is not defined I forgot that this ever have to like I should have to put a quarter in a jar every time I forget this been working an object in JavaScript and then I would be I would be wealthy except for the fact that those would be my own quarter so it wouldn't really work but whatever I just said wealthy in this very like fancy way like I don't know anyway so now if I hit the up arrow uh heading is not defined sketch that just live 41 I die not hit save I must not have hit save there we go now you notice it's working but it's not pointing in the right direction so this is a silly problem because I drew a triangle kind of like pointing up but a rotation of zero is pointing to the right so I kind of just need to like adjust everything I probably could have been could have drawn the rectangle oriented to the right but I can just fix this in my code with a one little line that just says rotate heading plus pi divided by two that should rotate it always offset by 90 degrees and if I do this you can see I am now pushing it around like asteroids now you can't see what keys I'm pressing but left left left right right up up so one thing I want to add is a little bit of dampening or friction just to like make it a little easier for me to play right now and also it's an interesting thing to see in the update function what I'm gonna do is always say this dot velocity dot multiplied by zero point nine five so I just want to reduce the velocity the magnitude of that vector by five percent every frame and you'll see what that does so as I accelerate it kind of slows down and stops now I'm doing it too much the other thing is I can't hold down the up key so I have to do the same exact thing that I did with turning I need to handle that in ship so what I'm going to do is say ship dot boosting true I'm going to change this I'm going to say ship boosting false and I'm going to create a variable called this dot this dot is boosting equals false and then I'm going to write the function this dot boosting which gets a boolean value as an argument and I'm going to say this dot is boosting equals B so I can and then in update I think I can just do this in update I'm just going to say always say this dot boost so it's always oh no no no if it's boosting if this is boosting then updates already always being called so I basically want to turn boosting on and off boost is totally the wrong word I think the word is thrust but whatever it doesn't matter you get the idea um okay so I think this is exciting I think this is gonna work let's see oh my god so now I can hold oh whoa okay it went really fast so now I need to deal with the fact that because I can hold it down that force is much too strong so I'm going to say force dot multiply by 0.5 so I'm going to reduce its magnitude by half I haven't reduced it by 90% just to sort of see so you can see I can now hold the mouse down and it's still it has that and turn it around so it's essentially like drive it around the screen the friction is too much though I just wanted to have a little bit of dampening so I'm just a x 0.99 there we go so I've got asteroids here pretty much I've got the core mechanic now down of driving this triangle around the screen this is totally fun okay ah now what do I need to do boy there's a lot left to do I need to add actual asteroids I also need to deal with the fact that this should wrap around that's kind of an easy problem let's let's add that real quick so I should add a function called this edges equals function oh this is going to be so tedious and I want to say if this dot pause dot X is greater than a width plus minus this dot R so I just want to kind of like if it's nope plus R if it's like all the way off the screen then have it have its position equal negative R else if this dot paws X is less than negative this dot R then have its position get reset to the other side of the screen right so this should do it for X whoops let's drive off this side oh I'm not I do this every time when you write a function you need to actually call it for anything to ever happen so in draw in draw I now also want to say ship edges let's see if that works now whoops and drive off the screen and I got an error I forgot this dot where did I forget this dot in my edges function this dot R and this dot our I don't need this dot with right because with a refers to the width in this sort of global sense of the canvas but our is part of this ship object so now I can drive off the edge and here I come back so asteroids kind of like we would see it in both places and fancier ways and stuff now I just need to implement this for the top and the bottom height and Y and Y and Y and height so now I should have I can drive off the top the side and I can like turn around and slow myself down so I can drive around this is fun I did not get distracted to keep playing the game okay it's time let's add some asteroids now one thing I don't love here is that my code is getting to be a little bit unwieldy so I want to take this whole ship constructor function and I'm going to add a new file and I'm going to call it a ship KS and I'm going to put the whole ship constructor function there I'm going to make a new file called asteroid j s because I want all the code for Astrid the asteroids things that are flying around I want to put there and then what I need to do is in my index.html file I need to make sure that I am also referencing ship j s and asteroid j s so I haven't done anything that should change the way this program works I just moved reorganized my code a little bit I feel good about that how do you feel about that are you still watching maybe I feel like I've been doing this for hours so probably hasn't been that long okay so now asteroid so the first thing I need to deal with is the fact that unlike the ship where there's just one of them I'm going to need many asteroids flying around the screen so I need to save our asteroids equals bracket bracket because I want it to be an array an array being a list of things as opposed to one thing then what I want to do just to get started I want to say asteroids dot push new asteroid push being a function that adds something to an array and I forgot to parentheses there so we need to add an asteroid to that list and then in the draw loop I is less than I want to loop now one of the other comments I get constantly on my channel is why don't you use for each loop and maybe someday I will but I'm just kind of like old and not very good at this that I'm sort of used to these kind of loops with iterating over an index so someday I'll add a for each loop in JavaScript to some of these but right now I'm just going to do this I'm going to do a astroids index I render so notice this is a technique that I often employ I haven't actually written any of the code for the asteroid I'm just imagining what I need I need an array I need to make a new one and then I need to loop through all them and add and call render so now this gives me kind of a template for what I need to write in this asteroid is fun it a JavaScript file I need to write a constructor function called asteroid I also want the asteroid to have a position create vector and you know the position for right now we'll just be a random spot random with random being a p5.js function that gives me a random number between zero and some value like width or height and then I need a render function which is something that I'll draw now what I'm going to do right now just for the I'm what I'm going to do right now is I'm going to call this I'm going to say a translate this dot pause X this dot pause dot Y and I'm just going to write I'm just going to draw a circle zero zero and you know we need an R as well this dot R equals 50 and then I'm going to say this dot R times two because the the ellipse function wants and the lips function wants a diameter so to draw a circle so the radius times choose the diameter so let's see how this goes where's my asteroid there it is here's one asteroid and it's a circle I can hit refresh and it should I must have something wrong with my random cuz right look it seems to be off the screen let's take a look at that random with random height hm oh I know what the problem is I meant to talk about this but I forgot so here's the thing these translates build on each other so the ship is translating and rotating the triangle the asteroid is now translating the ellipse so that asteroid is actually being drawn relative - the ship's location and strand anise but I can show you what I mean like this I got to get to appear look as I move now that's kind of interesting but it's not what we want so one thing I need to add is are these functions that are in p5 that are push the functions push and pop so push is going to save the current translation and rotation state and pop is going to restore it so if I put push and pop around it it makes all this translate rotate for the triangle not affect the other thing and you can see now and also actually if the styles so that you can see now the the asteroids being positioned you know randomly now let me go back to here the asteroid and I also need to add that to here because there's going to be a lot of asteroids and I want them to be independent from each other and I'm also going to say stroke 255 no fill okay so now what I want to do even though I could just keep going it I think it would be really good for us to sort of procedurally generate random asteroids that have that jaggedy look from the original asteroids game I could make this game just with the circles but that act in some ways that defeats the point of what I want to do so I know the whiteboards not the greatest today but I'm going to come over here and just briefly explain how I'm going to do this so I'm drawing a circle with the function ellipse another way I could draw a circle is by setting all the points of a circle as vertices and then connecting them as one polygon and you can see this is like a bit less of a high-resolution circle but if I move these points around a little bit then I can also make something that appears more in jaggedy so how do I get these points I need to do something called polar to Cartesian coordinate transformation and I have another video I think that goes through that in detail or if I don't I better make one and link to it from here but really what I just need to do is think of each one of these spots as an angle from the center and/or distance from the center radius and then I need to convert that to an X Y with a little bit of trigonometry so time to review your trigonometry pause this video and go read about trigonometry if you're watching it okay so what I'm going to do here is I'm going to take out this ellipse and I'm going to write a for loop yet again I'm gonna say a equals zero actually I want to say I equals zero I'm gonna use I equals zero I is less than I don't know let's just use ten points i plus plus I can use the p5 map function to get an angle so I want to take I which goes from zero to ten and I want to get a an angle that's between zero and two pi to pi being the equivalent of 360 degrees then I want to say VAR x equals this R times cosine of that angle this will give this is the polar to Cartesian coordinate the polar coordinate is R comma angle the Cartesian coordinate is X comma Y name for Rene Descartes the mathematician VAR y equals sine of the angle and then what I can do is I can set a vertex at that x and y position okay and now in addition to that what I'm going to do is say begin shape so I want to create an arbitrary shape out of vertices this list of vertices all with their XY and shape and we're going to see what this gives me so you can see it there it is it's kind of like a circle but it's a little more jagged E and notice how it's not connected at the end so an easy way for it for me to do that in p5 is just to add this closed function which will tell the shape to close itself at the end the other thing that I think would be interesting to do is have this BA be flexible so each time I do it I have a different number I have a sort of a different resolution so I'm going to do a variable called total which is a random number between let's say it could be between 5 and 15 points so this is going to say this total and this would now be this total so sometimes it will have a few vertices sometimes we'll have a lot so you can see I'm getting different ones and now you know what would be much better is if I stopped if I right now in the sketch what I should just do here is add a bunch of them so let's add ten of them at the beginning and now so I don't know if we can see there's a whole bunch of them all with the different amount of verses and the other thing I should do is make the size of them variable so I'm also going to say this dot R equals a random number I don't know between five and twenty five that didn't work this dot R oh that's in the ship I changed the ship size which is to be fixed and I want the asteroid itself to have a random value between 15 and 70/50 was it looks like a good sort of maximum size so now you can see and this is too many I want to start it with fewer so let's just start it with five okay so we can see here is now a bunch of asteroids now here's the thing these don't look like the asteroids in asteroids so how do I going to make them jaggedy and more interesting looking what I believe I can do is I can actually let's see how am I going to do this in the asteroid what I can do is offset our each time by some random value hmm but I need it to be the same random values each time so there's a bunch of ways I could do this but I'm going to make this uh I'm going to make this a an array and I need how many I need however many points I have I need that many offsets so this dot offset equals a random amount so when I create the object I make an array of offsets for each one of those vertices and let's say it's between like negative five and five I might want to make it bigger and then now the X and y is plus this dot offset index I and and you know let me let me make this a little simpler to read I'm going to just make another variable the R is actually this dot R plus the offset for each one and now here's the polar to Cartesian coordinate transformation okay I hope this works oh boy I'm gonna be excited if it does if it looks like asteroids ah total is not defined this dot total where's total not defined this total oh I don't see any asteroids this dot offset index I I see in the chat somebody is a yes I need an index I here I need to set each spot in the array whoops there we go that's looking kind of better so you can see these look kind of more like asteroids we can make the offset much more extreme yeah this is better so now I've got something that looks much more like those procedurally generated asteroids so now these asteroids by the way I can still drive around right the whole point is to drive around and not hit the asteroids they're a little bit big I don't know if I'm making this game too hard to play but the asteroids should move right I need the asteroids now to move around the screen so they need an update function and the same thing I could just say this stop position dot add this dot velocity only they don't have a velocity so let me give them a velocity this velocity equals and p5 has a function to create a random vector so a vector of length one pointing in a random direction so I can just say random 2d to give me a random vector if I go to sketch a s I can say did it that asteroids index I update and here we go there we go now the asteroids are moving around oh the asteroids also need to to when they leave to come back so one thing I can probably do is just reuse this edges function you know I could do some kind of fancy object-oriented inherent inheritance thing but I'm just going to take this exact function and yeah I could I could use the same function and assign it to both but I'm just going to copy paste it right now then I'm going to go to sketch J s and say asteroids Edge's okay there we go now I've got the asteroids moving around and now all I need to do boy am I not finished yet oh yeah I have no collision detection so I'm not I'm definitely not going to add collision detection to this today because you know whatever asteroids they're they're in different Z space and they pass through each other and it's room a djegal sense and what happened to my ship there it is but I should add a feature where I can now fire little lasers at the asteroids and break them apart [Music]
Info
Channel: The Coding Train
Views: 89,656
Rating: undefined out of 5
Keywords: JavaScript (Programming Language), live, programming, daniel shiffman, creative coding, p5.js, coding challenge, p5.js tutorial, p5js, javascript (programming language), tutorial, javascript, algorithms, asteroids, atari asteroids, asteroids p5js, asteroids javascript, asteroids game js, asteroids game javascript, asteroids game atari js, coding, challenges, games done quick, html5 canvas game, game javascript, asteroids game bot, asteroids machine learning
Id: hacZU523FyM
Channel Id: undefined
Length: 31min 55sec (1915 seconds)
Published: Thu Dec 15 2016
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.