Hi Sami, yes I agree, I'm trying to make the projects visual and memorable and I'm adding a new technique each time to improve our skills step by step, hope it helps.
Thanks Frank! Great tutorial! I was coding with you (although with loads of pauses at my end :) and now i need to watch it again to fully understand what is really going on here. keep up the good work mate!!!
You finally did it!!!! Game class and inheritance and polymorphism!!!! You know, you can build Game class only for static properties, so you don't need to instantiate Game for only one canvas and call at the same time all the algorithms you need for update and draw! It can serve the app even million times faster on that way (speaking of microseconds time scale), as no instantiated Game object exists in RAM. On that way, Game class works as a controller ( == a mechanism) for all created objects during runtime. Just a suggestion 😉 Epic work Frank!!!!! Awesome 🆒
Hi, thank you for suggesting improvements, if you have an example of how you would structure the code let me know. Since you say game would handle static properties only, I guess we would need another handle function for drawing and updating the game. In the current code structure you can pass as many different canvases as arguments, I can have enemy canvas, player canvas etc and update them only when necessary. I'm still learning about some of these optimisation techniques so I appreciate your comment, thank you
Hi Franks, really you are my hero, I wrote with you line by line, really you taught me a lot. I have small comments may be I am wrong 1-document.addEventListener('load') doesn't work it should be window not document. 2-I think it will be good not to use game class, then instantiate an object from it, and use an object directly, I tried it and it worked just like you class game={ deltaTime : 0, constructor:function(ctx,width,height){ this.ctx = ctx; this.width=width; this.height = height; this.enemies = []; this.enemyInterval = 500; this.enemyTimer = 0; this.enemyTypes = ['worm','ghost','spider']; }, update:function(){ if(this.enemyTimer> this.enemyInterval){ this.addNewEnemy(); this.enemyTimer = 0; this.enemies = this.enemies.filter(object => !object.markedForDeletion); }else{ this.enemyTimer += this.deltaTime; } this.enemies.forEach(object => object.update()); }, draw:function(){ this.enemies.forEach(object => object.draw()); }, addNewEnemy:function(){ const randomEnemy = this.enemyTypes[Math.floor(Math.random() * this.enemyTypes.length)]; if (randomEnemy == 'worm') this.enemies.push(new Worm(this)); else if (randomEnemy == 'ghost') this.enemies.push(new Ghost(this)); else if (randomEnemy == 'spider') this.enemies.push(new Spider(this)); /*this.enemies.sort(function(a,b){ return a.y-b.y; })*/ } } thank you very much for your experience and time
Hi Alex, you are right load event should be on window object. Creating class vs creating object is just a creative choice I guess, both will work the same, I usually create class even for objects that will have one instance (player object) just so that my code is uniform. Declaring object directly will save you 1 line of code, feel free to choose whatever you prefer.
@@Frankslaboratory thank you for your prompt reply, so I mean that it good to use object just in the game, but sure we have to use classes after that with worm 🐛 and spider 🕷️ as you mentioned in the video. Again all best wishes
Really funny intro 😃 And a nice application of inheritance. It was fun to watch. One comment though... Sorting the enemies like that, from top to down, only really makes sense if the game gives a sense of perspective. Yours does not because all enemies are the same size. I get where you're going with this, though.
I learn that sort trick from you :D yes you are right, ideally enemies that are behind should be smaller, if you play 2d games like plants vs zombies, they do layering like this but everything is the same size, it 's a very flat looking '3D' effect ha. Next time I will tweak the size.
@@Frankslaboratory Yes, but then sorting in the opposite order is also fine. Sorting in the opposite order is also fine with 3D perspective if your worms walk on the ceiling, for example. I think you can play around with that in the future (floor creatures sorted / sized one way, and ceiling creatures in the opposite way).
Hi, good tutorial! I want mention that we can simplify the creation of different enemies by prefilling the array with references to the corresponding classes. It will looks like this: class Game { constructor(...) { ... *this.enemyClasses = [Ghost, Worm, Spider];* this._addNewEnemy(); } ... _addNewEnemy() { const randomEnemyIndex = Math.random() * this.enemyClasses.length | 0; *const RandomEnemyClass = this.enemyClasses[randomEnemyIndex];* this.enemies.push(new RandomEnemyClass(this)); } }
Really enjoying your videos lately! I notice you do everything with vanilla -- is that the way you like it? Or are frameworks like Phaser worth considering after you understand the fundamentals?
at 6:48 window.addEventListener('load', function (){} does work, but not the document.addEventListener version. Because then you are waiting in a loop. Thus waiting for the eventlistener to load too. The cleanest version I know is "onload = () => {}"
Frank The scary part of this video is, I’m starting to really understand JS. I’ve employed a screenshot tool to capture snapshots of the code and print it off. With your explanations still in my mind I can pencil in some comments for further review. Plus messing with some codepen snippets . Works for me. I always read the comments in instructional videos for those little eureka comments like Mike’s regarding the global nature of ID’s. Like you I was taken by surprise when he added his comment. I thought the way you acknowledged his tip and incorporated into your code was awesome. as well as the other suggestion on the ghost transparency. Being a microcontroller guy, memory is a precious resource so if hosting a webpage on a small controller you are acutely aware of how fat JS and associated code really are. The ability to assume association of an id without making a 25byte call is a big deal! Thanks for pointing out the purpose and use of super, ! and #. Of course the overall thank-you for creating your polished video format ,sharing your knowledge and expertise is implied!
Hi Carl, I used to have a notepad with stickers and I was writing important code blocks in it just to remember them better, glad you found a good way to organise the things you learn. I try to make people feel like their comments have impact so if I remember useful tip while recording, I will use it and credit the person. I hope it will encourage people sharing their tips with me, as I'm a student as well. Thank you for your kind feedback Carl, it sounds like you are a very motivated and goal driven person, I wish you a lot of success.
I started coding games to learn about classes and canvas in depth and your videos saved me thanks a lot. I want to ask could I use Map instead of Array in this tutorial? I also wanted to kindly ask you to do tutorials where you use non array objects which hold values as well. thanks again
@@Frankslaboratory THANK YOU! I'll be waiting for it . I am trying to set up a Javascript course for kids in a community center and your videos inspired me a lot. they offer very simple but efficient ways through game to teach programming to children . Thanks again
Hello I have one question, You have left the DOMContentLoaded eventListener in your code and mentioned for us to remove it and switch it to only load.(6:52) If I do that I fail to receive the console.log(); message in the console. I though something was screwy after I replaced the cut code back in. I have double checked it and even added a console.log(canvas.width) directly below the animate() call. My console has nothing, BUT as soon as I add BACK the DOMContentLoaded. I now see the error message lastTime is not defined, and adding it to the code. I see the canvas.width value flash and the deltaTime loop starts. It make life confusing for those of use who are still green to this. Great de-bug lesson but I can see it frustrating some others down the road. I heard your explanations why to use load, but using it here I get no console message or deltaTime loop? See how it can confuse a beginner to JavaScript??
I've been loving all of your videos, thank you! What do you do when you're done designing a game? Is there a way to get them on to the play store or are they strictly best for web playing? I'm most comfortable with js and it would be cool if there was a way to make them apps. Unless it's just best to learn another one of the gaming languages.
Hi, JavaScript games like this can be played in a web browser or you can use React Native to convert them into a native Android and iOS apps. I haven't learned React Native yet so I don't have much experience to share on that topic. Also my games are just a collection of common programming principles, every language has functions and for loops so it would be easy to convert them to a different programming language that supports native apps.
Thank you for the great video!! Can I just follow the "Game Development with Vanilla JavaScript" playlist in order? I'm the very beginner of game programming
Hi, I just restructured my Game Development playlist based on difficulty. Each video is a standalone project so it's possible to jump around, but now it's sorted from easiest to more complex projects. If you still find these videos too advanced you should consider doing a well structured complete beginner JavaScript course and then come back to project tutorials, it will make your learning process faster from my experience. have fun :)
Hi, excellent videos and tutorials! One question, the document.addEventListener('load', function is not working for me, it's like the event never happens. Using DOMContentLoad works fine. I found online that I could also use window.addEventListener and with window it works fine. Any idea why this happens? Thanks!
This is great tutorial. Im following along. i was wondering. the z index. is it possible to set the Z index to Y value in canvas? since each element is in certain x,y position. all we need to do is set Z index to Y once we instantiate enemy object.. this way we should get more or less the correct look and cheaper then sorting array when creating object.. I'm new to this so not sure. :)
Hi Adrian, this is a 2D plane, z index in CSS is just a helper property, behind the scenes CSS has to sort draw order for you as well, there is no Z axis. With canvas we often have to do manually what CSS does for you automatically behind the scenes. In CSS, a lot of these calculations and algorithms have been extracted into simple keywords and properties, but the same work has to be done behind the scenes, if you know what I mean.
Can you make a Video about Javascript Canvas Game development and how to make your game responsive so that you can play it on any device(mobile, tablet, desktop)
Another great one.. lots of concepts implemented so well for teaching purposes. Plus my daughter is going to enjoy the Halloween theme. Any suggestions for smoothing out deltaTime on my raspberry pi, which mostly returns 16ms, but randomly throws in 33ms?
Hi Matt. Halloween is my favourite time of year haha. I dont think there's an issue with irregular delta time. It will still reach target interval in specified amount of milliseconds. Do you see any performance lags? Shouldn't be caused by deltatime unless your system is really struggling with the code
@@Frankslaboratory same! Big October and Halloween fan. Yeah there were some quirks with the spider movements when using deltaTime - they'd get stuck at the bottom, whereas a hard-coded 16ms was fine, but I'm not too worried, understanding the pi can be quirky with that stuff. I at least understood the main concepts which is my goal. Also the graphic illustrations you sometimes use are super helpful.. like showing how you index the animation frames
@@mattmovesmountains1443 Oh, I see, looks like you discovered bug in my code. I can see it now. Irregular delta time should be handled on the line where I revert spider speed to a negative number. If delta time is high enough and it moves more than one step further, the reset check will lock it in endless loop. Thanks for bringing it to my attention. will fix for the final game tutorial. Glad to hear the visuals help. I try to do more of them these days, need to learn Adobe after effects when I have time so I can do them properly :D
hello francks,I understood the idea of requestAnimation... but there is one thing he doesn't like: let lastTime = 1; function animate(timeStamp){ ctx.clearRect(0, 0, canvas.width, canvas.height); const deltaTime = timeStamp - lastTime; lastTime = timeStamp; console.log(deltaTime); requestAnimationFrame(animate); }; animate(); }); the console.log(returns absolutely nothing, I don't even have an error message) I'm having a hard time seeing the error in the code, it all seems logical in its construction If you have an idea of research axis ! Thanks
Hi Phillippe, just do the usual console log routine to see where the problem is, console log other things from inside animate, just to check if it's running at all, even just a text that says 'aaa'. If it doesn't run then problem is outside, I can see too many brackets, I assume that's from load event listener. Just put console log in each level and you will find the problem. Debugging is important skill to have, takes a while to learn how to do it fast.
Request animation frame can be called many times independently. If you have two separate loops you are calling request animation frame more often. I'm not exactly sure what you mean though. Why do you call animate two times?
Hi Sonia, addEventListener can be added to a html element, spiders are canvas drawings, to make spiders clickable is relatively easy, you would do it by creating a class method that checks collision between mouse and each spider.
10:00, deltaTime shouldn't be a let variable, since it is changing or var? For some reason none of the times console log for me, if I use 'load' instead of "DOMContentLoaded"! I am using VScode live server. 35:00 It is so bizarre, when I use the deltaTime in the formula this.x, to make worms move to the left, worms are created, i see in console, but they do not show on the screen; if i leave the old formula they appear on the canvas. It doesn't seems to make a difference what I put in this.vx = Math.random() * 0.1 + 0.1;, big/small numbers, nothing appears on the screen. Is anyone else having this problem with random speed? I did other projects using random movements and never had this; well I will just decrement x by one (leave it as before random speed), for now! I hope to find the issue! OK! FOUND THE PROBLEM, my deltaTime is UNDEFINED, the one from ENEMY class! Makes sense now!
Hi Emanuel, deltaTime can be const, because let and const are block scoped, it means they only exist within the nearest set of curly brackets. You think i'm reasigning the same const variable but what is really happening is i'm creating new delta time variables, and I can do that since each loop is different block, different scope, they don't see each other. Scopes are complex, I need to explain it better next time. Also glad you fixed the bug, debugging can be frustrating but it gets easier
@@Frankslaboratory it would be better for begginners like me to learn data structures through visualization in canvas i hope i soon see sorting visualizer in your play list
Hi Mila, that's interesting. Probably it's down to implementation some of the canvas API methods we are using in particular browser. Never noticed this before but in theory differences like this are possible.
@@Frankslaboratory Ah, thanks for the answer! I just retested it and now - I did some updates to my computer and browsers meanwhile - firefox is still at 16 and chrome changed to 13. well … :)
mh quick question: If each enemy class has acces to the game variable and the game variable holds all enemies, does this not lead to an infinite dependency loop? I could inspect the Game object > Enemies > Enemy0 > Game > Enemies > Enemy0 and so on. Is this something to worry about or does it not matter?
Hi Artur, nice to meet you, this is a good question, I didn't think of that. This questions goes a bit deep and maybe someone else could answer better, but as far as I understand it this is not something to be concerned about, since it looks like we are creating infinite layers of objects, but it actually points to one slot in memory. If I learn more about this I will update this comment
@@Frankslaboratory thanks for the response, let me know if you find more about this in the future, I am really curious, because I encountered this as well in one of my projects, and I was concerned that doing it this way is a bad practice. The idea with the same slot in memory makes sense though - but confirmation would be great. thanks for your videos btw!
@@arturneufeld1516 It's good to raise questions like this, I will research it, well done on noticing this btw, you have great attention to detail, prime quality for programmers
It doesn't matter. Yes, if you wrote a loop to inspect Game object > Enemies > Enemy0 > Game > Enemies > Enemy0 and so on then you would of course loop infinitely but that situation should not arise unless you deliberately choose to do it; why would you?! lol Resource-wise it's not an issue. The array of enemies in Game will simply contain a memory reference to each Enemy instance and each enemy instance would have a property with the memory location reference back to the (single/same) Game instance. There's no recursion because they're of course not copies; Game isn't copied within each Enemy, only a reference to the Game instance. Think of it like your mobile phone and a friend's mobile phone. You have their number (not their actual phone 😂) stored in your phone and they have your number (not your actual phone 😂) stored in their phone. No problem. They can call you. You can call them. Same situation with Game referencing an Enemy instance and that Enemy instance referencing the Game instance.
the best way to understand oop is with developing projects .
keep adding those useful videos
Hi Sami, yes I agree, I'm trying to make the projects visual and memorable and I'm adding a new technique each time to improve our skills step by step, hope it helps.
Thanks Frank! Great tutorial! I was coding with you (although with loads of pauses at my end :) and now i need to watch it again to fully understand what is really going on here. keep up the good work mate!!!
Hi Irek! Nice to meet you. Congratulations on completing the course!
I'm lovin this man, nice upgrades on your code setup :)
Thanks Johnathan, I try to do something new in every video, always learning :)
You finally did it!!!! Game class and inheritance and polymorphism!!!!
You know, you can build Game class only for static properties, so you don't need to instantiate Game for only one canvas and call at the same time all the algorithms you need for update and draw! It can serve the app even million times faster on that way (speaking of microseconds time scale), as no instantiated Game object exists in RAM. On that way, Game class works as a controller ( == a mechanism) for all created objects during runtime.
Just a suggestion 😉
Epic work Frank!!!!! Awesome 🆒
Do you have tutorials to better understand what you mean?
Hi, thank you for suggesting improvements, if you have an example of how you would structure the code let me know. Since you say game would handle static properties only, I guess we would need another handle function for drawing and updating the game. In the current code structure you can pass as many different canvases as arguments, I can have enemy canvas, player canvas etc and update them only when necessary. I'm still learning about some of these optimisation techniques so I appreciate your comment, thank you
This is so awesome!! Great tutorial video!
Hi, your art made it much better, thank you :)
This is pure gold. Thanks so much. Appreciate your contribution
Hi Augustin, I'm here to help, will be using techniques from this video for the next upcoming full game projec
Hi Franks,
really you are my hero, I wrote with you line by line, really you taught me a lot. I have small comments may be I am wrong
1-document.addEventListener('load') doesn't work it should be window not document.
2-I think it will be good not to use game class, then instantiate an object from it,
and use an object directly, I tried it and it worked just like you class
game={
deltaTime : 0,
constructor:function(ctx,width,height){
this.ctx = ctx;
this.width=width;
this.height = height;
this.enemies = [];
this.enemyInterval = 500;
this.enemyTimer = 0;
this.enemyTypes = ['worm','ghost','spider'];
},
update:function(){
if(this.enemyTimer> this.enemyInterval){
this.addNewEnemy();
this.enemyTimer = 0;
this.enemies = this.enemies.filter(object => !object.markedForDeletion);
}else{
this.enemyTimer += this.deltaTime;
}
this.enemies.forEach(object => object.update());
},
draw:function(){
this.enemies.forEach(object => object.draw());
},
addNewEnemy:function(){
const randomEnemy = this.enemyTypes[Math.floor(Math.random() * this.enemyTypes.length)];
if (randomEnemy == 'worm') this.enemies.push(new Worm(this));
else if (randomEnemy == 'ghost') this.enemies.push(new Ghost(this));
else if (randomEnemy == 'spider') this.enemies.push(new Spider(this));
/*this.enemies.sort(function(a,b){
return a.y-b.y;
})*/
}
}
thank you very much for your experience and time
Hi Alex, you are right load event should be on window object. Creating class vs creating object is just a creative choice I guess, both will work the same, I usually create class even for objects that will have one instance (player object) just so that my code is uniform. Declaring object directly will save you 1 line of code, feel free to choose whatever you prefer.
@@Frankslaboratory thank you for your prompt reply, so I mean that it good to use object just in the game, but sure we have to use classes after that with worm 🐛 and spider 🕷️ as you mentioned in the video. Again all best wishes
Really funny intro 😃
And a nice application of inheritance. It was fun to watch.
One comment though... Sorting the enemies like that, from top to down, only really makes sense if the game gives a sense of perspective. Yours does not because all enemies are the same size. I get where you're going with this, though.
I learn that sort trick from you :D yes you are right, ideally enemies that are behind should be smaller, if you play 2d games like plants vs zombies, they do layering like this but everything is the same size, it 's a very flat looking '3D' effect ha. Next time I will tweak the size.
@@Frankslaboratory Yes, but then sorting in the opposite order is also fine. Sorting in the opposite order is also fine with 3D perspective if your worms walk on the ceiling, for example. I think you can play around with that in the future (floor creatures sorted / sized one way, and ceiling creatures in the opposite way).
@@Radu Now you are giving me ideas for future videos, I will do it :D
@@Frankslaboratory Can't wait to see it :-)
Thanks for the feedback, I will review each part. Anyway, thanks for sharing. See you soon.
Happy to help Philippe
Hi, good tutorial!
I want mention that we can simplify the creation of different enemies by prefilling the array with references to the corresponding classes. It will looks like this:
class Game {
constructor(...) {
...
*this.enemyClasses = [Ghost, Worm, Spider];*
this._addNewEnemy();
}
...
_addNewEnemy() {
const randomEnemyIndex = Math.random() * this.enemyClasses.length | 0;
*const RandomEnemyClass = this.enemyClasses[randomEnemyIndex];*
this.enemies.push(new RandomEnemyClass(this));
}
}
Really enjoying your videos lately! I notice you do everything with vanilla -- is that the way you like it? Or are frameworks like Phaser worth considering after you understand the fundamentals?
Another great one! These videos are great!
Thanks Karl
at 6:48 window.addEventListener('load', function (){} does work, but not the document.addEventListener version. Because then you are waiting in a loop. Thus waiting for the eventlistener to load too. The cleanest version I know is "onload = () => {}"
Frank The scary part of this video is, I’m starting to really understand JS. I’ve employed a screenshot tool to capture snapshots of the code and print it off. With your explanations still in my mind I can pencil in some comments for further review. Plus messing with some codepen snippets . Works for me. I always read the comments in instructional videos for those little eureka comments like Mike’s regarding the global nature of ID’s. Like you I was taken by surprise when he added his comment. I thought the way you acknowledged his tip and incorporated into your code was awesome. as well as the other suggestion on the ghost transparency. Being a microcontroller guy, memory is a precious resource so if hosting a webpage on a small controller you are acutely aware of how fat JS and associated code really are. The ability to assume association of an id without making a 25byte call is a big deal! Thanks for pointing out the purpose and use of super, ! and #. Of course the overall thank-you for creating your polished video format ,sharing your knowledge and expertise is implied!
Hi Carl, I used to have a notepad with stickers and I was writing important code blocks in it just to remember them better, glad you found a good way to organise the things you learn. I try to make people feel like their comments have impact so if I remember useful tip while recording, I will use it and credit the person. I hope it will encourage people sharing their tips with me, as I'm a student as well. Thank you for your kind feedback Carl, it sounds like you are a very motivated and goal driven person, I wish you a lot of success.
Lovely monsters😱😱 I will check
Halloween is coming, best time to talk about monsters haha
Супер !
I started coding games to learn about classes and canvas in depth and your videos saved me thanks a lot. I want to ask could I use Map instead of Array in this tutorial? I also wanted to kindly ask you to do tutorials where you use non array objects which hold values as well. thanks again
Awesome tutorial as always. You are an amazing teacher, thanks for sharing your vast knowledge!
Hi Alberto, glad you found it useful, I'm here to help :)
I'm from Brazil, I love your content
Hi Iraci. Thank you. Greetings to Brazil
Thank you very much for clarifying the inheritance concept!
Hi Tshitolo. The same technique can also be used for particle systems. Will make a video on that soon
@@Frankslaboratory THANK YOU! I'll be waiting for it . I am trying to set up a Javascript course for kids in a community center and your videos inspired me a lot. they offer very simple but efficient ways through game to teach programming to children . Thanks again
@@AK243RDC Nice, good luck with your project Tshitolo, I can see how kids could find visual/game coding projects interesting. Let me know how it goes
Maan,amazing work! Thank you so much!
Glad you like it Ken !
I love your videos, they are great!
thanks to you!
Great video! Learned a lot of new things
Hi Luctor, thank you, glad you found the course useful, keep learning
This video is awesome, it's very useful to me, thank you!
Glad you found some value Hank
That was great, super easy (parent easy)
very attracting opening to bring 'extends' and 'super' to live
I try to make coding more fun :)
Hello I have one question, You have left the DOMContentLoaded eventListener in your code and mentioned for us to remove it and switch it to only load.(6:52)
If I do that I fail to receive the console.log(); message in the console. I though something was screwy after I replaced the cut code back in. I have double checked it and even added a console.log(canvas.width) directly below the animate() call.
My console has nothing, BUT as soon as I add BACK the DOMContentLoaded. I now see the error message lastTime is not defined, and adding it to the code.
I see the canvas.width value flash and the deltaTime loop starts. It make life confusing for those of use who are still green to this.
Great de-bug lesson but I can see it frustrating some others down the road. I heard your explanations why to use load, but using it here I get no console message or deltaTime loop? See how it can confuse a beginner to JavaScript??
Hi Will, I can see you messaged me on Twitter as well, I will respond there
@@Frankslaboratory I have the same problem
same problem
@@nicorithner786 Attempt with window.addEventListener('load') instead, due to document apparently being unreliable.
I've been loving all of your videos, thank you! What do you do when you're done designing a game? Is there a way to get them on to the play store or are they strictly best for web playing? I'm most comfortable with js and it would be cool if there was a way to make them apps. Unless it's just best to learn another one of the gaming languages.
Hi, JavaScript games like this can be played in a web browser or you can use React Native to convert them into a native Android and iOS apps. I haven't learned React Native yet so I don't have much experience to share on that topic. Also my games are just a collection of common programming principles, every language has functions and for loops so it would be easy to convert them to a different programming language that supports native apps.
Hey there Frank, thanks for another fantastic tutorial
Pierson! Thank you ❤
So thanks for the video
Happy to help, hope you find some value
Nice
🙏
Another great one
Thank you Sagar ❤
Thank you so much for tip 😍🤩😘🥰
I'm here to help :)
Thank you for the great video!! Can I just follow the "Game Development with Vanilla JavaScript" playlist in order? I'm the very beginner of game programming
Hi, I just restructured my Game Development playlist based on difficulty. Each video is a standalone project so it's possible to jump around, but now it's sorted from easiest to more complex projects. If you still find these videos too advanced you should consider doing a well structured complete beginner JavaScript course and then come back to project tutorials, it will make your learning process faster from my experience. have fun :)
I always wait for your videos
Thanks for waiting :)
Hi, excellent videos and tutorials! One question, the document.addEventListener('load', function is not working for me, it's like the event never happens. Using DOMContentLoad works fine. I found online that I could also use window.addEventListener and with window it works fine. Any idea why this happens? Thanks!
Super cool video ! :)
Thank you
This is great tutorial. Im following along.
i was wondering. the z index. is it possible to set the Z index to Y value in canvas? since each element is in certain x,y position. all we need to do is set Z index to Y once we instantiate enemy object.. this way we should get more or less the correct look and cheaper then sorting array when creating object.. I'm new to this so not sure. :)
Hi Adrian, this is a 2D plane, z index in CSS is just a helper property, behind the scenes CSS has to sort draw order for you as well, there is no Z axis. With canvas we often have to do manually what CSS does for you automatically behind the scenes. In CSS, a lot of these calculations and algorithms have been extracted into simple keywords and properties, but the same work has to be done behind the scenes, if you know what I mean.
Can you make a Video about Javascript Canvas Game development and how to make your game responsive so that you can play it on any device(mobile, tablet, desktop)
Hi, I am working on some mobile specific game tutorials yes
How you protect you browser based js games ? People can see and copy js very easily
I love your content 💖
Thanks Soussou ❤💪
Another great one.. lots of concepts implemented so well for teaching purposes. Plus my daughter is going to enjoy the Halloween theme.
Any suggestions for smoothing out deltaTime on my raspberry pi, which mostly returns 16ms, but randomly throws in 33ms?
Hi Matt. Halloween is my favourite time of year haha. I dont think there's an issue with irregular delta time. It will still reach target interval in specified amount of milliseconds. Do you see any performance lags? Shouldn't be caused by deltatime unless your system is really struggling with the code
@@Frankslaboratory same! Big October and Halloween fan. Yeah there were some quirks with the spider movements when using deltaTime - they'd get stuck at the bottom, whereas a hard-coded 16ms was fine, but I'm not too worried, understanding the pi can be quirky with that stuff. I at least understood the main concepts which is my goal.
Also the graphic illustrations you sometimes use are super helpful.. like showing how you index the animation frames
@@mattmovesmountains1443 Oh, I see, looks like you discovered bug in my code. I can see it now. Irregular delta time should be handled on the line where I revert spider speed to a negative number. If delta time is high enough and it moves more than one step further, the reset check will lock it in endless loop. Thanks for bringing it to my attention. will fix for the final game tutorial. Glad to hear the visuals help. I try to do more of them these days, need to learn Adobe after effects when I have time so I can do them properly :D
@@Frankslaboratory fitting, I suppose, that the spider caught the bug in the code
@@mattmovesmountains1443 ahahaha, well said Matt :D
hello francks,I understood the idea of requestAnimation... but there is one thing he doesn't like:
let lastTime = 1;
function animate(timeStamp){
ctx.clearRect(0, 0, canvas.width, canvas.height);
const deltaTime = timeStamp - lastTime;
lastTime = timeStamp;
console.log(deltaTime);
requestAnimationFrame(animate);
};
animate();
});
the console.log(returns absolutely nothing, I don't even have an error message)
I'm having a hard time seeing the error in the code, it all seems logical in its construction
If you have an idea of research axis !
Thanks
Hi Phillippe, just do the usual console log routine to see where the problem is, console log other things from inside animate, just to check if it's running at all, even just a text that says 'aaa'. If it doesn't run then problem is outside, I can see too many brackets, I assume that's from load event listener. Just put console log in each level and you will find the problem. Debugging is important skill to have, takes a while to learn how to do it fast.
Thanks for the video sir ❤️
Hi Mohammad, I'm here to help 😅❤
when i am calling animate() 2 times,why request animation frame serving frame faster than before?
Request animation frame can be called many times independently. If you have two separate loops you are calling request animation frame more often. I'm not exactly sure what you mean though. Why do you call animate two times?
Welcome back after a month 😅
It's been a while :D I had to return to the office, no more working from home so need to come up with a new routine to make videos
👍👍👍👍👍
❤💪
Hi Frank
I'm new to programmation and I wonder if I can put addeventlistener in the constructor if I want my spider to be clickable ?
Hi Sonia, addEventListener can be added to a html element, spiders are canvas drawings, to make spiders clickable is relatively easy, you would do it by creating a class method that checks collision between mouse and each spider.
💚💚💚
Hi Maruf
Hi @@Frankslaboratory. I was waiting for this tutorial from i have created the walk,running...Dog from your spritesheet.
@@Frankslaboratory thanks
10:00, deltaTime shouldn't be a let variable, since it is changing or var? For some reason none of the times console log for me, if I use 'load' instead of "DOMContentLoaded"! I am using VScode live server. 35:00 It is so bizarre, when I use the deltaTime in the formula this.x, to make worms move to the left, worms are created, i see in console, but they do not show on the screen; if i leave the old formula they appear on the canvas. It doesn't seems to make a difference what I put in this.vx = Math.random() * 0.1 + 0.1;, big/small numbers, nothing appears on the screen. Is anyone else having this problem with random speed? I did other projects using random movements and never had this; well I will just decrement x by one (leave it as before random speed), for now! I hope to find the issue! OK! FOUND THE PROBLEM, my deltaTime is UNDEFINED, the one from ENEMY class! Makes sense now!
Hi Emanuel, deltaTime can be const, because let and const are block scoped, it means they only exist within the nearest set of curly brackets. You think i'm reasigning the same const variable but what is really happening is i'm creating new delta time variables, and I can do that since each loop is different block, different scope, they don't see each other. Scopes are complex, I need to explain it better next time.
Also glad you fixed the bug, debugging can be frustrating but it gets easier
Frank can you make a video on sorting visualizer just like your canvas projects
Hi, sorting visualizer? Hmm, interesting, yes that could be a fun project, I will add it on my list, thank you for another great suggestion
@@Frankslaboratory it would be better for begginners like me to learn data structures through visualization in canvas i hope i soon see sorting visualizer in your play list
can anyone explain why deltatime for me is 16 in firefox and 33 in chrome (both vanilla).
Hi Mila, that's interesting. Probably it's down to implementation some of the canvas API methods we are using in particular browser. Never noticed this before but in theory differences like this are possible.
@@Frankslaboratory Ah, thanks for the answer! I just retested it and now - I did some updates to my computer and browsers meanwhile - firefox is still at 16 and chrome changed to 13. well … :)
mh quick question: If each enemy class has acces to the game variable and the game variable holds all enemies, does this not lead to an infinite dependency loop? I could inspect the Game object > Enemies > Enemy0 > Game > Enemies > Enemy0 and so on. Is this something to worry about or does it not matter?
Hi Artur, nice to meet you, this is a good question, I didn't think of that. This questions goes a bit deep and maybe someone else could answer better, but as far as I understand it this is not something to be concerned about, since it looks like we are creating infinite layers of objects, but it actually points to one slot in memory. If I learn more about this I will update this comment
@@Frankslaboratory thanks for the response, let me know if you find more about this in the future, I am really curious, because I encountered this as well in one of my projects, and I was concerned that doing it this way is a bad practice. The idea with the same slot in memory makes sense though - but confirmation would be great. thanks for your videos btw!
@@arturneufeld1516 It's good to raise questions like this, I will research it, well done on noticing this btw, you have great attention to detail, prime quality for programmers
It doesn't matter. Yes, if you wrote a loop to inspect Game object > Enemies > Enemy0 > Game > Enemies > Enemy0 and so on then you would of course loop infinitely but that situation should not arise unless you deliberately choose to do it; why would you?! lol
Resource-wise it's not an issue. The array of enemies in Game will simply contain a memory reference to each Enemy instance and each enemy instance would have a property with the memory location reference back to the (single/same) Game instance. There's no recursion because they're of course not copies; Game isn't copied within each Enemy, only a reference to the Game instance.
Think of it like your mobile phone and a friend's mobile phone. You have their number (not their actual phone 😂) stored in your phone and they have your number (not your actual phone 😂) stored in their phone. No problem. They can call you. You can call them. Same situation with Game referencing an Enemy instance and that Enemy instance referencing the Game instance.
Sorry if you're scared of spiders but... Happy Halloween :D :D
hey please bit me i want to be franks spiderman :D
great work !!!
@@mra2604 Thank you
@@mra2604 Hahaha, LOL
lol
Bro bagaimana caranya agar codingan game dijadikan aplikasi?
What IDE do you use?
Hi Ангелина, I use VS code editor, with Live server plugin
:} 👍
Bro bagaimana caranya agar codingan game dijadikan aplikasi?