[LIVE] Code-It-Yourself! Sliding Block Puzzle Games

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
right and we'll see what are we live we'll see i think we're live yes looks like we're good uh so firstly hello to all of the people that i've just been chatting to it's been very nice having sort of a pre-show chat that's good and uh hello to all of the people that i missed in the last five minutes uh thank you very much for dropping by uh somebody shout out make sure you can hear me yes you can good we're live good excellent right so i'm going to be sort of casting an eye over the youtube chat as well as getting on with the video and the reason i'm doing this live is i have been very very busy in real life for those that follow the channel you'll have noticed maybe way back when 100k subscriber special i said there'll be a period of this year where i'm not going to have any time at all and i'm right in the middle of it with a real life project very exciting project i build robots for a living and we've got a big customer and it's just taking up all of my time so i thought what we'll do is a simple video on this block sliding puzzle and i'll do it live so we're going to have lots of bugs and errors and all sorts of things going wrong so periodically i'm just going to have a glance at the chat up here just to make sure i'm not missing anything but it looks like we're all good and everything's set up and hopefully the volume is fine and we can just start so i'm going to be using the pixel game engine as normal now i know some of you join live specials like to follow along and uh to start with all i do is i've created a blank c plus file and in the pixel game engine header file you'll see some text of a blank skeleton program and i recommend that you copy and paste all of that into a blank c plus file and strip out the bits we don't need there will be a section during this where there's going to be a little bit of a q a i think so uh i'll try and answer some of the questions as we go but i don't want this stream to go on for hours and hours and hours and hours um so i'm going to just push on with it right so the type of game that we're thinking about here are along the lines of soccer band right the thumbnail should have given that away the idea is you control a player and the player can push blocks around and you have to get blocks over goals and some of the blocks have certain restrictions on what direction they can move there's a whole bunch of different mechanics and what i thought would be interesting was to create a video on how simply we can implement these mechanics and how we can build a framework upon which we can extend and add new and interesting stuff so we won't actually really get around to designing any puzzles today just really the framework right so let's where should we get started and this is the beauty of doing things live um full disclosure i have got a little bit of a prototype obviously you saw the thumbnail that wasn't just a mock-up but i will be sort of coding it all as we go along and i think what we'll do is start with we'll start with something that renders a basic level and i'm going to keep this very very simple indeed so you'll have to excuse now the real typing and the typos as we go along so i'm going to represent a basic level as a string that's how i usually like to do things in prototype form and i've already set my console game engine screen to be low resolution 256 by 240. now we're working with blocks so how many blocks can we sensibly fit into that resolution and it well it works out that 16 by 16 pixels is a nice size for a block and uh we can therefore fit 16 by 15 blocks entirely on that resolution so i want to create some sort of basic level template and i'm going to represent it as a string and i'm going to use the symbols hash now if you've watched the first person shooter videos you'll see this before i have to count these out for uh one two three four one two three four one two three four okay that's good and i'm going to want 15 of these now you'll notice i'm not putting a comma at the end of things hang on lost count already 6 7 8 9 10 11 12 13 14 15. so that's my full level the c compiler will automatically concatenate all of those into a single string so i'm going to use the hash symbol or pound symbol or whatever it is from wherever you're from to represent solid blocks so we'll start there and i'm going to represent uh dots to show well there's no block there so nothing at all and we'll notice later on that there are some limitations with this approach but just to keep the video simple i'm going to be using characters to define the levels and i'm sure it's not a big leap for you guys to see well hang on we could have different strings representing different levels later on so let's just get some basic framework to start some rendering up there i'm going to need a few other bits and pieces of information for example how big is the level because i've got this string but it doesn't tell me anything about the dimensions of it so i'll create a vector oh i'm programming in the wrong language here vf2d that's the floating point type vector and i'm going to call that v level size and i'll just initialize that to 16 by 15. yes good excellent have a quick glance at the chat it's where i have to go quiet whilst i'm reading it because the chat moves a lot quicker than i used to no i'm not going to be using command line graphics for this one i'm going to be using uh pixel game engine now we know that each block or tile or whatever you want to call it in my level is going to be um 16 by 16. so i'm going to just cache that here it's useful to have it as well just a convenience variable it also means we can we can change the size of things later on so as i mentioned at the start this is really going to be a video about creating some customizable framework for us to later on develop more and more things into so we've got level size and we've got the block size uh so let's go down to uh on user create and just before that i'm going to create a function called load level we might have different levels and things later on we might want to choose them do you know if i'll give that a parameter i you know i'm not going to call it i i'll call it n because i use i as indices and things and the whole purpose of load level is going to be to turn our string into something that represents the level and we'll get back to that in a little while so i think next what we'll add is something to render the level maybe or should we start thinking about the blocks let's think about blocks let's create a basic block structure struct block what is it to be a block in this level well i'm going to try and use object-oriented programming for this when i did the shoot-em-up i used a very procedural programming for that and we we gave the different entities in the game different behaviors and different rendering styles by uh sort of using function pointers it was very strange way of doing it but it worked very well we just wanted a small minor change in this instance i'm going to use sort of polymorphism very very simple stuff in order to construct the world and we'll look at how we can move the blocks around and the mechanics sort of next but for now let's just get it rendering something uh very simple and my block is going to be a base class for a block those that are following along hopefully you don't miss too much but i will put the source code up at the end of the end of the video as i always do and it will be the source code warts and all in this case right i'm going to give our block a basic constructor now a stroked in a class just saves me having to type out public all the time i'm not too interested in the security of object-oriented programming for this but i am interested in allowing the blocks to be able to draw themselves so i'm going to put in a base class called draw self and we'll flesh this out a little bit as we'd start developing the application but whenever you have an object in pixel game engine or whatever platform you're using that's drawing itself somehow it has to have access to the drawing tools so i'm going to allow it to pass in a pointer to the pixel game engine you also get to see me sort of picking my nose and all sorts of things when i'm doing these things live the block is going to exist somewhere in space now i don't want to create an array of blocks as such where they all know their own location this block is more a description of what does the block look like and what is its behavior so i need to pass in some information to say where this block actually is in the world where's it going to be drawn on the screen so i'm going to pass in a two-dimensional vector for this pause and i'm also going to pass in the same again for the size now these are integer vector types because everything's going to be nice round even pixel numbers there we go draw self oh we need a return type on that don't we put a void there very good let's have a look at the quick chat good not seen anything going terribly wrong excellent where's the caffeine unfortunately no there's no caffeine here today right so my load level is going to construct blocks so i need to store these blocks in something and i'm just going to store them in a vector standard not a standard uh olc vector just a standard vector in this instance but i want to use polymorphism so if i'm going to store all of these blocks in a vector i can't just store them as blocks i need to store them as pointers and i'm going to do something unusual oh oh thank you very much tom have you ever used pascal or delphi what do you think the place for other languages in a space dominated by python c i have used both pascal and delphi in fact when i was a teenager that was what they were teaching at the time was pascal at least and then i moved on to delphi a little bit later on what do you think the place for other languages is in a space dominated by python c it's very tricky i think there's a lot of languages which are not getting as much support now particularly things like pascal and delphi are they still that relevant well the purists will say yes and some of the computer scientists will say yes um but i think i mean i'm biased i like c plus plus because i can i can use it without having to think about it too much it's very second nature to me so to to suddenly say well i'd prefer to write this application in pascal it's just not really a decision i would ever sensibly make i've also noticed now that you're right so things like python and lua and c-plus plus and now things like rust and go are gaining great popularity um i'm not too familiar with rust or go but hey so do does pascal and delphi have a place in the world today undecided i think as enthusiasts yes they do but as production level development packages probably not simply because there's little guarantee that they're going to be around in 10 years time and if you're working for a company who's producing software and you have to support it for its lifetime is it going to be around is the talent pool going to be there don't know this is live yes right so what we're going to do is store we're going to use some smart pointers now that's a rare thing for this channel but it does make life a little bit easier for us later on so we're going to use unique pointers and we're going to use unique pointers to block the type we've got now all of this will be a little bit cryptic to start with but we have to just get going somewhere have to have some sort of basic framework and once we start rendering the framework you'll start to see oh yeah that makes complete sense and so i'm just asking you to to run with me a little bit on this and i'm just going to consult my notes what did i call this vector because i'll start typing it out and then i'll have to start changing absolutely everything and so i do need a bit of a backup plan oh hang on whoa whoa whoa i'm getting all sorts of pings and things going on suik hello thank you very much hello yes suec that's an interesting name and zleepingbird hello 50 wow that's a that's a big donation it's good to see you sleeping there i know you do pop up on the server periodically and we just always seem to be like we have a phrase called ships in the night we always seem to miss each other when we're when we're chatting um yes i hope your studies are going well anyway and i hope things are working out for you and hurry up and finish that paper because it's a really interesting thing and i want to i want to show it in a video right that's a bit of a mess when you have a vector of smart pointers yes it can be a bit of a mess that's the only downside with the standard library and smart pointers and things like that is it can get a bit wordy regardless let's press on i'm going to call that v level now i know people who's using hungarian notation yes i use just get used to it i prefix things with the types a little mental hint for me i quite like it now where were we so in on user create the first thing i'm going to do is just call my load level function one way or another suic thanks for all the videos they've helped a lot although you're struggling with the 3d stuff oh well yeah the 3d stuff it's not that simple it is complicated you need to you need to understand a little bit of the mathematics now i've tried to approach it in such a way that you don't have to have seen all of the maths before but certainly if you've not covered it in school yet or you've never had any formal training in trigonometry and geometry they can be quite tricky i started out because i i was dabbling with 3d graphics well before i started playing with trigonometry and things in anger at school certainly matrices never even looked at those and i just used to take the parts as black boxes and just simply say well i know that whatever that thing is there it rotates my geometry and i kind of understood how it did it and certainly by using them as black box components it helped me understand them and i think later on when i did go to learn these things at maths in school and university i found them much simpler simply because i programmed them so it kind of helped me learn these things to run with but yes 3d stuff if if it's new to you it is it is a bit tricky and some people spend their entire lives working on nothing but 3d programming um i think there's something to be said for good old 2d programming particularly when it comes to some of the geometry because a lot of the stuff that you can do in 2d you can easily extend into 3d what's the clever thing about using a unique point i'm just picking a question at random here what's the clever thing about using a unique pointer the clever thing about using this unique pointer is when i clear the level it will free the memory up but we'll also see why am i using a pointer in the first place why am i not just storing the blocks and that's because i'm going to exploit polymorphism and i need things to be pointers in order to exploit polymorphism so yes somebody asked me this question the other day experto did you work on war of the monsters no i'm sorry it wasn't me right i'm going to push on for five minutes and answer some questions a little later on if i do miss your questions i've sort of scheduled in this later on we're going to be drawing some of the blocks that's probably a good time to do a bit of a q a right so completely lost where i'm up to load level what are we going to do so we need to load our string and convert these into our block type so let's do that now we'll have two nested for loops uh into y well i got shouted at once for doing x and then y you should actually do y and then x it can be a little bit more cash efficient though you know hey so what a few extra clock cycles between friends what's the problem and we created this vector size thing before to give us the dimensions of our array so i'm just going to grab the height of it out of there respect for your work from from a australia i'm looking forward to teaching others in code myself in the future very good i think it's important that once you have got a little bit of programming knowledge pass it on right lots of people don't have it and it's one of those things that's really useful to do it's easy enough to pick up to a usable degree okay it's difficult to master i won't argue with that but um getting getting it working for you one that when you're starting out programming one of the first things you'll you'll realize is hang on everything seems like hard work but after a while it sort of clicks and you go hang on this is actually making my life much easier and you start developing tools that help you and that's definitely so once you've hit that point you know it's for you it's going to be what you need to do for the rest of your life right so yeah so so far we've created earth nested for loop i keep getting distracted i should start looking and now one of the nice things about having things in a string array like this is we can easily access that array so i'm just going to call switch and to that i'm going to take our string variable and we can pass in a coordinate now we all know this and if everybody's not shouting this out at once we know that it's going to be y or lowercase y times the width of our level plus x so we're going to convert those 2d coordinates into 1d i y why before x well traditionally if you're storing things in an array uh usually your x's are closer to each other in the array contiguously rather than the y's so basically as i'm as i'm iterating through this array now the change from one array element to the next is minimal it's a single x it's a single one each time so i'm going to get better cache performance iterating through my array that way but don't worry about it i mean that that's the reason why but it's not that important unless you're doing really critical sort of image processing code or really hammering arrays a lot because if i did it x and then y the inner loop being y means i've got a huge jump potentially between elements and they may not be in the cache so it's that's all it's really about right so i'm going to switch based on the character i'm reading so i've converted my 2d into 1d and that will give me a location somewhere in here and now i can put in some case statements so if we are a solid block we're going to do something and if we are a full stop you know i'm not even going to bother with the full stop because i'm just going to leave that as default stops playing noita to watch david get distracted yes is it any good that game i've seen it and it looks reasonably interesting but i don't know i don't know if it's for me or not right so we know we're going to have two types of block we've got one which is solid and something that doesn't exist at all but right now all we've got is this basic prototype of a block so i'm going to copy all of that and i'm going to duplicate it down here and call this one as block solid so these are going to be blocks that cannot move i don't even need the constructor for this and just you know we'll do it properly we'll get rid of the virtual and we'll put an override at the end it keeps the parents happy he says optimistically well we got a thing override does not override a base class member yes it does oh we know it doesn't because we need to inherit from our basic block there we go come on fingers wake up there we go i told you i'm terrible at typing this is the advantage of doing a video is i get to edit all this stuff out now if it's going to be a solid block we're just going to draw it as a filled in rectangle so i'll take the pointer that we've passed in for the pixel game engine and i'm going to call fill rect i'm going to give it the position times the size so the position is going to be in sort of tile space so up here is 0 0 and down here is 16 by 15. but when we're drawing it to the screen we need to know the size of the blocks and that's why the position is multiplied by the size the size of the block is of course just the size and i'm going to color those in blue there we go so all we've done now is created a subtype called block solid and it just draws itself blue whereas a regular block doesn't do anything at all so now i can push into my vector at the correct location well in place black and this is where things are going to get a little bit modern now with lots of wordy stuff we're going to make the unique pointer we'll call this one block solid so this will handle the polymorphism for us we're basically now creating a pointer so that's handled just fine and there is no constructor to pass in so it's just that's it that's all we need to do now that's when we encountered the hash symbol we're going to put a solid block in but what are we going to do for all of the other blocks in this case they're all period symbols and we're just not going to put anything at all but i don't want to do that because right now my vector will consist of only the things that are there and i'm going to exploit the fact that we can have hit my microphone going to exploit the fact that we can have empty blocks and for an empty block i'm not going to create a special type or anything i'm just going to use null pointer so in the situation that we get a block that we don't understand or in this case the period symbol i'm simply going to push null pointer to my vector right i'm just gonna have a mouthful a go i suppose there's some caffeine in that i know that was a that was a question was it right so now we want to draw our array and we're almost halfway done with the actual framework here because you'll see pushing the blocks around isn't actually very have a complicated look at the uh the chats here yes i think on the whole console game engine is is not um not something i use very much anymore uh it's unfortunately windows kept doing updates and things to the terminal i guess they wanted to push the new powershell and the new terminal products out there so the original command prompt is no longer as flexible as it once was and it now suffers from a bit of a performance hit things still do work but use the pixel game engine instead right so we're going to draw stuff that's what we're going to do first so the first thing i'm going to do is clear the screen to black and that will mean we're starting from a blank canvas each time and now i want to iterate through my vector so this vector will now contain the same number of elements as our map contains and they'll be in the same place if we index them in the same way so there's a correlation between that and the types of blocks that we put there so i'm going to create a little uh variable here called tile oh dear v i 2d in this case we'll call that tile this is going to be what we're using to count through the tiles as we're drawing them so i'll initialize that to zero zero no no real need to initialize it though it's just a force of habit i guess now so uh tell you what i will call that v tile pulse so it's very explicit that we know that that represents the tile's position in tile space tilepass.x and we're going to begin at zero oh we've just had a debate about this haven't we let's do it in y first let's be consistent uh tile pass dot y is less than v level size dot y so we're just literally going to iterate through absolutely everything i'll pass dot y there we go and inside there we need another book for x x x x and x excellent now the reason i've not just used x and y in this case is a lot of the drawing functions and things can take in this integer 2d vector type so it's just convenient so now i've got an index to a particular tile in my array i want to be able to sort of access it frequently i'm going to create a small lambda function to help me out here because i'm going to be frequently turning these x and y uh positions into 1d positions for my vector indices kind of like what we did here but i'm going to wrap it up in a nice little lambda function i'll call that id so c plus plus lambda functions well they're one of those things that are a bit curious and unique to c plus other languages do have them so if you're following along in a different language just create a normal function that returns a single integer in this case i'm going to call it id and i'm going to just capture everything which i know you shouldn't do and i'm going to pass into that let me just consult my notes before i get carried away here doing something incorrect all right yes i'm going to pass into that my vi 2d just a reference to it pause and all this lambda function is going to do is do what we said before this y times the width plus the x so pause dot y well i need to put a return in don't i that always helps pause dot y at times everything is going to be relative to level size dot x plus pass dot x and that's our little lambda function so that's just a utility function it's just going to save me having to type this out over and over and over again just convenient now i want to get the type of the tile from our vector i'm going to use auto to do this because i could be getting back all sorts of different things fundamentally it's going to be a unique pointer to block but i want to be able to treat it as different types so what did i call this video i think i just called this variable b i did call it b there we go that's convenient wasn't it b for block so now i can access my vector of blocks i can call my little id function and i can pass in my tile path vector and that's going to give me the pointer to the block at that particular location so all of this so far has just been about making the syntax easy to follow they say if you've not got c plus you can implement this in many ways in well just a function that takes in an x and a y and returns an index very simple stuff now it could be that b is no pointer so that's something that we want to check for because null pointer means there's no block here don't do anything so i'm just having a quick glance at the chat here uh what would you move out of this cpp file into a header file uh yes so i tend to do everything in one file because it's convenient for the video rather than me flicking around but ultimately you could create your uh well anything that's got a body doesn't need to be in the header file that's as simple as that now the beauty of this approach here is now i can just simply call the draw self function and all i need to pass in is a pointer to the pixel game engine the tile position and the tile size do i not have a tile size what did i call it did i call it what did i call it something else i called it block size of course why not is it block size should be block pulse then i guess wouldn't it but hey ho block size right i'm just going to zoom out a tad so we can just see a little bit more code if it gets a bit too small on the screen i apologize do shout out so here we've got our rendering framework and so far that is all we're going to need because the blocks are going to be capable of drawing themselves let's have a quick test compile and see if it's got any lots of syntax errors and things that we need to work out and let's run it oh oh it's not looking very healthy i think we've got an error somewhere ah well that's not going to help is it we've got no increment on the end of our loops there have i forgotten those elsewhere there we go let's try that ta-da so yes we've drawn a black rectangle it would seem no what we've done here is draw for the individual tiles uh we've now got them on the screen now if we want to prove that that's the case let's just go and bang in a couple more things here just some simple obstacles if we run it now excellent so we've got our square tiles and we've got a convenient way of rendering them so let's take the example a little bit further we're going to need a starting position npc unit keep up the great work your videos are useful take care of yourself thank you very much emp that's very kind of you um yes and i think that's a good message to absolutely everybody during these uh these really frustrating times i wouldn't everybody says unprecedented and doom and gloom there's just more frustrating than anything else um and i think it's important that people do take the warnings reasonably seriously i'm sorry if that doesn't align with your political beliefs but it it's just common sense that we shouldn't all be spitting and gobbing on each other in the streets so uh do do take uh responsibility for your surroundings that's my only political message i'm ever going to say on this channel but i feel i'm getting tired of the whole thing and i want it to go away as quickly as possible right so what we're going to do now is create another block another block type and we'll have this one as the player and wherever the player starts is going to be the letter p so i will take i'll just copy and paste the implementation of our block solid and i'll call it block player the player i'm going to draw as a white rectangle and here we'll start to see the the real powerful nature of polymorphic programming why it's useful why it's one of those things that yes people will moan about but it's worth learning nonetheless so we've got our block player if i want to add a new type i know it's wherever the letter p exists let's just go and change this to block player and i don't need to change anything else don't need to tell it that anything else exists we've got a new thing in our game that's separate and controllable but we don't need to change our rendering framework so that's quite a nice thing to have yes notice the lack of increments well thank you everybody for shouting that one out that's god i miss editing now i think it's time to start talking about how we're going to move the blocks around we can see that we can easily have different types in fact why not let's just add another one just to prove the point we'll have a another simple block so simple block is going to be a block that can be moved in any direction and we'll talk about the movement just after this but let's color it in simple blocks are going to be red for now we're starting off with very simple graphics don't start off by drawing the graphics first just start off with simple placeholders and so we'll have a simple blocks we will have plus as the symbol which means they can be moved in any direction so i'm just going to scatter a few around the world here and later on when we start moving them around we might want to see how they behave in different orientations and that sort of thing so simple pluses and we will add into our level loader the plus symbol and call that block simple double check that that's worked very nice okay we will update these graphics towards the end you see i don't do live very often on youtube but i do do twitch occasionally and i'm live fairly frequently on discord um and if you've not joined the discord server i recommend that you do come and have a chat with us on the discord server and i've got another actual thing i wanted to to mention uh the olc code jam 2020 is going to start as a bit of a time-off but in one month's time that's where it's going to start so if you're interested uh check it out it's itch dot io slash jam slash olc code jam 2020. uh in fact you know what i will paste a link in the chat there there we go right we want to talk about how we're going to shuffle the blocks about so let me just pull up one note because we like one note on the channel here's my 2d array and i'm going to draw into this some simple blocks simple blocks we decided we're going to be red so let's say i've got a block here and a block here and i'm also going to have my player now do not i'll do the player in black the reason being is i might want to use blue for a solid wall simple blocks are capable of moving in all directions so i'll use the plus symbol to indicate what directions they can move in and the idea is that the player is going to exert a force in a particular direction and don't worry we're not going to get all physics and collision detection in this video it's really not necessary we're going to exert a force in that direction and what we're going to do is propagate that force along so the first thing we'll check in that direction we'll see well tell you what let's just back up a little bit there i've got to delete this now without deleting the whole background that's the downside of onenote we know we're going to start where the player is and so the first thing i'm going to interrogate is can the player move well players can always move we're going to set that up as a role as a rule can it move in that direction well it needs to find out so it's then going to go and look at its neighbor in the direction it's pushing and say can you move are you allowed to move and this block will go well yes i can move in any direction but i just need to double check with my neighbor and so it does that can you move and this one goes well yes yes i can move let me double check with my neighbor oh hang on i've not got a neighbor i'm now in null pointer land there's a very boring place and when we propagate like this and we reach this null pointer we know that there is empty space so it is possible in that one cycle to push all of these blocks along once let's just leave null point to land for the moment what if there wasn't what if there was a solid block this solid block will have responded well hang on i can't move anywhere at which point this red block simple block in the middle that can't move anywhere the first red block can't move anywhere and the block representing the player can't move anywhere so if we end up in a situation where the blocks can't move and we've not hit a null pointer for that cell well then nothing else can move but let's now go back into the very exciting null pointer land i knew that would happen this is the downside to one note and deleting things it is a pain once we've realized there is empty space here we can then systematically work backwards and swap the empty space with the blocks so we can swap u with this block which will of course move this red block over to this null pointer i can't draw that out very easily without deleting all the screen and then we can swap again and we'll keep swapping until we get back to the starting position and that will have the effect of moving all of the blocks along once so in this instance the player can push multiple blocks along providing that the blocks allow them to be pushed and there is space to push them into this is where we're differing from soccer band where i think you can only push one thing at a time but we could implement a restriction to allow us to just move one block at a time but i'm not going to do that i think it's more interesting to have sort of collections of blocks passing around because you can then start to think of more interesting puzzle dynamics but where do we factor in how can a block move how is it going to tell us that it can be pushed in a particular direction so i think we need to implement that next let's have a quick glance at the chat what about pulling blocks well we can talk about pulling blocks a little later on but for right now this is a simple video it's a simple algorithm because i'm doing it live i'm going to do pushing blocks excuse me and i'm going to need some directions now you don't you're not allowed to use hash define anymore so you need to use const expression and you need to spell it right as well there we go let me just zoom in a little bit more so we can see and i'm going to have the first one as north i'm going to give that the value zero and we're going to go around in clockwise order so east south west now it's important that you get the order correct because there's a trick you can do with the order and we'll be seeing that trick in in a moment now on my base blocks just you know just a tab i need to have a function that tells me is this block pushable from a particular direction so let's put that in as a base function and it's going to return a bool why can't you use hash defy no that was me being a little facetious you'll get basically all of the c-plus plus pedants coming out of the woodwork and shouting at you now because well it's it's not the nice way to do things hashtag is basically cut and paste doing things with const expressions uh allows some degree of control over what's going on from the compiler you could use uh an enum class or something else but the the downside with enum classes i find is you're always casting between them because there's a lot of value to being able to use an enum uh both in name and numeric position within the enum however that's a debate for a different time so i'm going to add a function here called push and this isn't going to move the block we can see already the block doesn't have any knowledge of where it is in space but what it's going to tell us is what is its behavior when we want to push it and so we need to provide it with what direction are you being pushed from and for our base block we're going to assume that all blocks can be pushed in all directions note that it's not checking its neighbors it doesn't know anything all it knows is that if i am pushed i can be moved very good conversely for our solid blocks we know that they can't be moved they can't be moved in any circumstance it doesn't matter what direction so i'm just going to set that to false the player block so far can be moved because the player we want to be able to walk around the level and what we'll see is we add more blocks such as blocks that can only move horizontally and only move vertically then we'll need to change the calculation performed in this push function to give us those different behaviors but we'll get there in a bit ah we've also got our simple block haven't we a simple block is very similar to player except it renders red yes there we go it's a simple block is one that can be pushed in all directions why both snake and camel case why not where am i up to we're up to movement okay good good good sorry i'm catching up with some of the chats oh it's from oh man yes sir man yes thank you for posting your video right we need to handle some user inputs that's how we're going to start this algorithm and even though what we've just looked like seems like a brilliant candidate for recursion i'm not going to use recursion either it's so simple we don't need to there's really literally no code to this but you'll see that the end result is very pleasing to push things around so what i'm going to check for is the w a s and d keys being pressed and in the pixel game engine you just simply choose the key and if it's being pressed uh that's gives you a true on the frame that the key has been pressed on so that you know it won't repeat anymore you just sort of get that one hit and i'm going to need that for all four directions w s a and d of course if your keyboard layout isn't wasd you could use the arrow keys just as happily and what i want to convert is this key press into the action of pushing so i'm going to create a boolean variable spell it right pushing which by default is false we're not pressing we're not pushing anything unless we're pressing one of these keys but i also need to store the direction we'll call that push and uh you know i'll just store that as zero for now but we're going to set that to one of our const expressions in the event of pushing being true so let's just see what i mean by that so if we're pressing the w key then the direction we're pushing is northwards so we can use that constant we created earlier and i'll set the b pushing variable to true and this will be true for just this one frame very similar for south and here we've got a which is pushed towards the west and here we're going to have d push towards the east hi brian and this up hello sorry if i've missed loads and loads of chat i do apologize but i do want to get through it and there will be a little room for some chat later on we got off to a bit of a slow start so i'm just trying to catch up right so now we've established that we're pushing and we know which direction we're going to be pushing in so what do we do about it well first thing let's be responsive to if we're pushing because if we're not then we don't want to do anything at all so i just go back quickly to the onenote one of the things that we need to know is where do we start doing this search so i'm going to have a player coordinate vector value pair x and y tell me where the player exists in the world and from there we will then in the direction of the push start interrogating the neighbor cells so let's throw in a variable up here it's an olc vf2d type we'll call that v player now we need to set that to something and we know that we specify where the player is going to be in the level because we've got a b for the character player so when we load that particular block it will also set the position of the player which is simple enough right so i'm not going to move the player around so much but what i'm going to do is maintain a cursor as we jump across the blocks because i don't want to sort of lose where the player is positioning so if we are pushing the first thing i'm going to do is create this cursor location i'll tell you something i've just called the player a vf 2d haven't i my brain's running slower than my mouth where did i put that block block block block should be a v i 2d everything's in integer space keeping everything very simple we go so you don't get all of this scrolling when i'm doing the normal videos that's the i see it would be easy to get disoriented so we'll call this cursor v block that's going i'm going to set that to v player so that's going to be the first location that we're going to start looking for things and we need to scroll across these blocks so i'm going to have to sit in a loop checking blocks in a particular direction and i want to stay in that loop until i hit this null pointer scenario which means there's some empty space at the end and therefore we can allow the push to occur or i want to abort going through the loop because i can't push anything any further the movement is not allowed so i'll create some flags to tell me if we're allowed to do the push i'll default that to false for now because that's what we're testing for in this loop and i'm going to sit in a loop until my testing scenario comes to some form of stop and we'll see when i start typing that out what that means but for now we do want to sit in a loop which sits based on b test so while b test is true we're going to check to see if a block can be moved well firstly we need to check does the block even exist now i created this little lambda function down here do you know what i'm going to move that up here because i'm going to reuse it a little bit there we go so it's now defined so i can use it within this testing loop so the first thing i will check for is firstly is the block we're testing is it null pointer because if it's null pointer there's nothing to test we can't actually interact with it so we want to be dead safe there so v level uh id the block now if that is uh not do you know i'm going to be really explicit here so it's clear in our minds what's going on here so we're testing that there is actually a block in that location you don't need the uh not equals null points a bit but it's just it sort of reminds you that it's there you that's what you're testing for and now the push functions that we've just added to our block types we're going to check those to see can you be pushed from that direction so let's call that function for the block so if v level type that out again v level id v block push now what direction do we choose we've got our direction of push but the block rather confusingly is sensitive to which direction are we being pushed from it wants the opposite direction so if we're pushing something in the northern direction the block is being pushed from the south so we want to convert that north to a south well one of the convenient ways of doing that is because we've stored these as zero one two and three in clockwise order you can see that north and south are two apart and east and west are two apart so opposites are always going to be two apart so we can take our direction and add two to it mod four so we wrap around because it's a compass and that will give us the opposite direction so let's just do all of that uh we've got we want to our direction of push plus two oh that's a start sir push you know that sounds pretty cool isn't it der push mod 4 there we go and so that's now flipped our direction for us a nice little convenient mathematical trick there i'm going to make sure i've got the right number of brackets going on here if yeah that looks that looks legit okay if our block allows pushing from that direction that we're pushing in block allows to be pushed if that block allows us to push in that direction so i've got to try and verbalize this then we want to move our cursor along in that direction so switch to push and we've got to go through all four of them there's no real way around this uh so if we're going in the northern direction north is up the screen so our y value gets less this is our cursor's location for the next block that we're going to test if we're pushing in a southerly direction then we want to increase our y value and we've got something very similar for east and west too so if we're going in the x if it's east we're increasing that's going towards the right on the screen and for the west we're decreasing so this is moving our cursor on if the block has allowed us to move the cursor on the blocker said yes i can be pushed in that direction keep going mate if the block says no i'm i'm not moving no sir not for me you've got to stop then we may as well stop testing because the push isn't going to be allowed the block has to stop it can't be moved so we'll stop testing and not bother doing anything else later on however we made this check that if our cursor ends up in null pointer land then we do allow the move to occur so we can set our allow push value to true and because we're only ever moving one block at a time we can also terminate our test zoom out a little bit and just have a bit of a recap what's going on here so we're setting up a cursor that's going to systematically test all of the blocks in the direction that we're pushing i've got a flag here to say well do all of the blocks along that direction are they all going to allow me to push them because if they are then we're going to move them all so i sit in a loop and i test the blocks i start at the player block because we're treating the player as a block can the player move yes it can then it goes and tests the neighbor so let's say we're pushing towards the east so it takes the eastern neighbor moves the cursor a long one can you move in an easterly direction yes i can so we move the cursor along one and we keep doing that until either we get a block that says i can't move mate you're going to have to stop or we get an empty space we end up with no block which means of course we can move all of these blocks because there's nothing there to stop the last block in the chain being moved let me just have a quick catch up with the chat and a mouth full of coke so over your head meant to be a simple one this but i get the feel the the downside is because i can't sort of edit the one notes very well i can't draw them um sort of conveniently so we're doing everything in code but we're almost done and and that's the nice thing this you'll see how simple and then then we'll start to see how really powerful this technique is so we've only got the second half of the algorithm to do now and that is we've now tested can the blocks be moved and depending on whether they can or not we've got our b allow push value has been set so we can now do something if we're allowed to push the blocks then we need to move the blocks zoom in a tad there now at the moment our block cursor is at the end of the block chain and i don't mean blockchain like the discussion we were having before the start um so this this cursor is technically in the free block at the end of the chain here in this uh null point to land here where this zero is our cursor is now there so we're going to work backwards until the cursor is at the original player location that's a nice way we know how far we've got to go we don't need to do any additional testing for things we just work backwards now towards the starting location which is our player so while our cursor spell it right would help wouldn't it while our v block is not equal to our v player then we're going to systematically walk backwards and swap the cell that we're on with the cell next door so we need to know where that cell is next door so i'm just going to create a temporary little vector vi2 then we'll call it v source because this is going to be the we're going to now use the swap function we need two values one is going to be the cursor and one is going to be the neighbor of the cursor in a particular direction so how do we calculate that source value well we're going to use another little switch block like we did before so you know what i'm going to copy that and paste it in but we have to be a little bit careful now for starters we're operating on the source and now we're also working backwards so we're going to flip these we're going in the opposite direction to how we were going before so that will give me a block and a neighbor in the appropriate direction so let's assume i'm now in this null space here let me get a pen where's my pen pen there we go so let's assume now our cursor is here we've just calculated this cell here that's our source because we took the direction that we were pushed in and we went the opposite way and what we're going to do now is swap these around with each other and we can do this very very simply because of the way we've stored the blocks we're just going to use the standard swap function v level id v source doesn't matter what order you call these in because they're just getting swapped and v level id v block and that will do it that will swap things for us it'll do it in a reasonably efficient way it doesn't matter that the contents of our vector our unique pointers or anything like that swap will take care of it all for us nothing's going to get lost or deleted or confused or duplicated or anything like that it's just going to handle it for us and once we've done the swap we now need to update our cursor position well our update is simply now where the source was we're just going to move our cursor backwards towards the start so that's the second half done if a push was allowed then we work backwards from wherever the cursor was and move all of the blocks into the neighboring space one last thing to do we need to update our player's coordinate and that's very simple because i'm going to take this little switch block again i want to make sure i'm in in the right set of brackets here if we're pushing and yes if we allow the push depending on the direction of the push we're now setting our player coordinate legitimately this time no no sort of flipping around no moving around so if everything's happened if we've moved all the blocks then the player is allowed to move into the cell it was next to and that's going to be facilitated by this little switch case here so take the direction of the push if it's north we move the player up the screen south down the screen east and west so so right will any of that work this is where we've got to have some fingers crossed to time it compiles that's a good start so let's run it so the white square is the player and as i tap the keys doesn't matter if i hold them down you'll see the player moves around and i can't move into the blue cells hissing stone thank you very much hi vsauce javid here so what you might notice straight away is well hang on all of that that we've just done we've never explicitly sort of made the player move except for that very last bit at the end so it must in order to have allowed the player to move it must have allowed the push even though we're not pushing against any blocks so the same algorithm is also really implementing this player movement and the collision detection and you can see it works in all directions i'll tap really loudly so you can hear when i'm pressing the keys now let's take a single block here so these blocks can be pushed in all directions and i can push that until i can't push it any further i can push it down here and it's uh it's stuck now i can't i can't pull it so i can't make it move let's try pushing this one into some red you know i'm going to go up here so we don't make this prematurely end i can push all of these red blocks in one go which i think is very nice so you know very simple algorithm very simple framework and we've got different behaviors going on because the solid blocks can't move the player block can move and the red blocks can move in all directions so we're starting to build up the very fundamentals that we need for a sliding puzzle game yes it probably does need some sound effects right let's add in some different block types just to prove a point so let's uh add in i think we'll add in horizontal and vertical blocks so these are blocks that can only be moved in horizontal or vertical directions so the first one we'll have is block horizontal and horizontal blocks will draw in green why not now we know that these can only be pushed if it can only move horizontally it can only be pushed from the east or from the west so if from is equal to east or from is equal to west in that situation it's uh it's true we can we can move the block what i'm hoping to demonstrate here is by spending the time laying down the sort of framework it now becomes very trivial to add sort of new and interesting behaviors so for yellow so vertical blocks we'll have yellow tiles let's go with yellow and they of course can only be moved from the north or south there we go so let's add some into our map just some test ones to get us going we'll use minus signs for horizontal let's have three of them there and always put one in isolation somewhere just so you can try it from other directions and we'll use the vertical bar sign that one for vertical tiles we'll have one in isolation down there let's go and add these to our loader so if it's the minus sign that was a horizontal block if it's a vertical bar that's a vertical block and let's see what happens now i've already forgotten the colors but i think green was blocks that could only be pushed horizontally so i'm pressing down here and i can't move i can press up and move the red ones out the way um but the green ones don't move but if i take them on from the side they can only move horizontally can't move them vertically let's try the single one and hopefully the yellow one should have the opposite behavior so yes i can move that one vertically but i can't move it horizontally yes very nice let's have a quick catch up with some of the chat give my voice a chance to recover i see now push them all together you see you can push them all together all right so what's the next phase the next phase is i think a more interesting block type now this one's i don't know if they exist in in soccer ban but i thought it'd be quite useful to have blocks that you can only push a certain number of times so i'm going to create another block type and we'll call these countdown blocks and i'm going to actually have a constructor in here to pass in how many times it's allowed to move i'll create a little variable somewhere inside here int and moves equals well it to zero oh let's spell that right hadn't i and we'll set that value in the constructor right when it draws itself we should pick a color let's pick cyan for that and we're also going to draw the number of moves that it's got available so i'm going to use the draw string function now to draw this the single digit number of moves we'll assume it's going to be single digits and i know my blocks are 16 by 16. i know a single character in the pixel game engine is eight by eight so if i want the character to be in the middle of the block i need to offset it by four by four so pause time size plus four by four i just want to make sure i've done my sums right it'll be embarrassing if the digits are all over the place yes i have and we want to convert the number of moves to a string type and i will color that in black since we've got a cyan tile and i'm going to draw the character in black there there we go and we'll have these uh we'll not have any restrictions on the directions they can be moved so they can be pushed from all directions but we need to add this into our level loader now now i'm not going to do this for all possible numbers but let's assume that excuse me let's assume that we've got the number five to place a block that we can move five times let's go to our loader copy one of those so when we see the number five i'm going to load in our type block countdown and pass into its constructor five we could do some clever tricks like detecting was the character a number and using that but i'm just going to keep it very simple so we can quickly get through all of this video let's have a look let's play so here we've got a block with the number five on it and as i push it well it's not counting down that's because we don't really have a way yet of interacting with the block when it moves so we need to add that in somehow it's probably quite a useful thing so a block can update its state when it moves this means we need to go right back to our base block and add in another base method and we'll call this one a virtual void move so upon moving it does something what it does who knows now all of these don't care very much but this countdown block does actually care so we need to override it and all it's going to do is decrement its move counter simple stuff but we don't want it to be pushed anymore if the move counter is at zero so we're only going to allow it to move if our moves counter is greater than zero now let's try it oh well hang on no point in trying yet because we don't call our move function would where's the best place to call our move function well it's here because the block physically only moves if it's going to get swapped so i'm going to check before we move the block does the block actually exist save me typing this out let's copy that so if the block exists i.e it's not equal to null point again being dead explicit there then call the move function on that block so we literally it doesn't matter if you bump into it or try to move it it's not going to count down only on the physical move when we call swap do we actually want to call that move function so now for three in two different directions two one zero and it's stop dead we cannot move it and other blocks can't move it either one of the things we didn't actually test were these horizontal yes they were horizontal so we can we actually combine different block types yes we can you see very nice but we can't push down there yes good oh hey tarius didn't see you there man good to see you is this c minus very possibly the way i'm coding it today right so one thing to add in now is some sort of win condition when when do we know that we've uh satisfied uh some a criteria of winning and this is where well my approach in this video is going to do it in a really quick hacky way if you're going to take this on properly you'd probably want to do things a bit differently usually the objective of these games is to cover a certain tile with a block doesn't necessarily matter which block or whatever so let's put in a winning tile condition and i'm going to put that in as an at symbol so in this case in order to win we need to have tiles or blocks on top of all of those at symbols there's an argument made here so there is an argument to be made here that you should store the floor as a separate map to your level the reason being is at the moment i can't specify a tile to already exist on top of that winning condition now that does sort of stifle some of the problems that you can create it means always the goals have to be covered you might want your puzzle to be more sophisticated and that you've got to take tiles off the uh the winning tiles to actually solve the puzzle there's something in that so there's there's an argument that your floor should be separate and for other reasons too what if you wanted regions of floor that could only be pushed in certain directions or you wanted regions of floor that act like uh teleporters you could have an orange and a blue tile for example to move things around so the floor may well you might want that to be a completely separate structure you can still interrogate it and set it up the same way so i'm just doing things for convenience in the same map here but you know it's no big stretch and i'm sure the people watching this will be able to work out yep you could have another layer as the floor and we could draw it separately you could have all sorts of different things depends on what you want to do for the puzzle i'm just keeping it simple and i'm going to have my goals uh as discrete entities in the level but i don't want them to be blocks because i don't want them to ever interfere with something moving on top of them and this adds a unique thing that i need to know i need to know where my goals are in this level so i'm going to create another vector a standard vector in this case and i'm going to store in that vector integer 2d types i'm going to call it goals and all i'm going to store in this vector is the physical coordinates of these at symbols and we'll calculate those on load so i should also have done this at the start shouldn't i uh when we're loading a level uh we want to clear whatever the existing level is and we'll want to do the same for our goals just clear those out just to be super safe and secure so now when i encounter an at symbol when i'm loading in again not wanting to repeat everything i've just said you could load this in from a separate map to detect what the floor conditions are then i'm going to add to my goals the coordinate of that symbol i need some curly brackets there we go curly brackets found them but i also do need to add something to my level i can't allow it to have nothing uh there oh dear where's they come from let's get rid of those so i also need to push back a null pointer as well because we even we're sort of storing things in two separate structures now physically the location is stored in this v level which is what we're interrogating for drawing things and and to keep everything in check if we didn't add something here then everything would become out of sequence and we're also storing the goals as a set of coordinates and this will allow us now to easily check does something occupy a particular tile where there is a goal so we can go and implement this i'm just using coloured rectangles for the moment but we will go into writing so we will we will create some sprites for this don't worry all right so testing for goals how do we do testing for goals how many goals have we covered up with tiles well that's pretty easy let's just create a variable that counts number of goals and we'll set that to zero and then i'm going to iterate through my vector of goals need a bracket there g v goals now this g is of course a vector integer 2d and a goal is satisfied if there is a block on top of it so if in my level at that location i'll say id at that location if it's null pointer nothing exists that's one of the nice things but if it's not null pointer i.e there is an object there then increment our goal count and that's it that tests for our winning condition this has one side effect and what we'll see is that the player actually counts as a block so we could put in a specific test for that or you could use it as part of your puzzle dynamic it's up to you this again it's just a very simple block pushing framework but i was i was having quite a bit of fun with it when i was uh prototyping this so we want to draw the goals to give the player an indication of where they might be and i'm going to not draw them as part of the tile so i could check in every single iteration of these nested loops do does a goal exist at this location i'm not going to do that the first thing i'm going to do is just iterate through them again i guess i could have done this up here in the same loop but hey ho and i'm just going to draw a circle to say i'm a goal keeping it dead simple and the location of that is going to be right so g is the physical coordinate in tile space we need to scale that by the size of our blocks to put it into pixel space but we want to draw this circle in the middle of a block so i want to take the block size and divide it by two so that gives us our position the block size is going to be equivalent to the radius now if we were working with rectangular blocks we'd have all sorts of fun and games here but fortunately i know that they're square so i'm just going to take the width of a block and divide that by two and that will give us a full block circle that's probably too big so i'm just going to shrink that down a little bit so it's not doesn't occupy the entire square it's just a nice circle within the square and we'll color that at yellow i'm a goal and i think it's useful to inform the player how they're getting on because when we covered up the goals you won't be able to see them again graphical decisions you can make and display in different ways i'm just going to display boring text at the top of the screen so i'm going to call drawstring and we'll start at four by four which will be in the middle of the top left tile and i'll call that goals and do a bit of string mangling here standard two string that's not going to work that'll be better so how many goals have we got so far well we know that that's our goal count variable and i want to do that out off there we go uh standard two string how do we know how many goals we've got well conveniently we stored them in a vector so let's just look at the size of the vector and we'll color that white uh anything i've missed let's have a think we'll find out so those are three goals the three circles there and is it possible for me to actually put any blocks on them let's have a look there we go so we've covered up one and our goals has increased now the player still counts as a block don't forget so you can see that goes up and down as i move along perfect and at that point once we know we've got three out of three goals we could move on to the next level it's one thing to do often is the case that you mess things up when you're doing these games so we need a reset function to be able to reset the level how you score these things it could be that you count the number of moves that the player is is doing or you can count the time there's various different ways again this video is just about the mechanics of multiple blocks pushing around and also briefly mention about not pushing multiple blocks if you want it to just be one block at a time but for now we want to reset don't we so let's make the r key reset so i'll be sensitive to the r key being pressed and you might think well resetting is actually quite a bit of effort well it isn't because we used unique pointers as i can just load level load whatever level you could say i'm just passing in zero and it doesn't even do anything but you could pass in the particular level count that you're on the first thing the load level does is clear the two vectors and reconstructs everything and by clearing the level vector we're automatically erasing all of these uh objects that we've created so very nice not going to leak so as i move things around let's make a mess push these here and let's move our counter block there we go i press r everything gets reset we've not not jumped up a huge amount of memory so that's good everything's in a nice place so i think there's one thing left to talk about and then we'll actually change it to sprites and make it look pretty how long have we been going anyway not too bad we have run over a little bit and we always do when it's live it's just the number of questions i get asked um right one thing to talk about so what if we did want it so you could only move one block at a time well the easiest way and i've not done it and i'm not going to hack it live totally live is you could just keep a count of how many times you've iterated through this pushing loop and i was thinking about how you could augment this even further you could have each block has a mass so let's say you could push up to a total number of five units whatever it is and each of the different block types have different weights how do you make that dynamic well you just add in another base function which returns the mass and as you're going along as you're moving the cursor along you accumulate these masses and as soon as you hit the threshold where you can't push any further you return the test is false it can't move you don't allow the push so that's also an another dynamic we could add into this game i think quite a a useful one as well it's in a way it's similar to the number of limited number of moves you could push a block around for but it works in from a slightly different dimension as it were so lots of different things so you'll see if i just zoom out here including the level all we've done is define different block types these are those really small bits here i've designed different blocks there's basically no code at all right it's it's uh it's how do we interpret the level and create the objects and of course that could all be streamlined if white space is one of those things you don't like and all we've got really is this very simple loop where we check the blocks being pushed outwards if the push is allowed we allow them to move and we move them all one block to the right and that's it even drawing it we did the drawing routine at the start we've never had to touch it again but let's make it a little bit more interesting oh gareth hey i didn't see you there gareth time regeneration of pushes and in-app purchases yeah i think that we will make the peg x the pixel game engine extension for in-app purchases that will be coming very soon um what was i going to do completely distracted gareth totally knocked me off the rails there lip your neck uh where am i up to i was up to going to start doing some graphics i think because i think what we do is we know our blocks are 16 by 16 pixels but let's make them a little bit more interesting i have here i call this asperite but i think it's a sprite is how it should be pronounced and i think this would be an opportunity for um well now it's probably a good time to ask some questions whilst i'm drawing this because the the video is almost finished from a code perspective so if anybody has got any interesting questions um then shout them out but i'm going to get these in a particular order so i want a solid block this is where i know there's a couple of guys in the chat that use this software backwards and they'll be looking at me going oh how how come it's so slow what are you doing and for blue i'm going to put in a little bit of highlighting on these things let's put a shadow at the bottom so this is the stuff you don't normally see in videos when i'm making it but i want it to be complete this time round let's highlight those like that and click click the corners away can make those alpha there we go have you done any videos on smart pointers yes yeah i did actually my video on what are pointers actually covers smart pointers as well as regular raw pointers uh can you show us your elbow there you go don't say i don't do anything for this community can you limit yourself to palette i knew somebody would ask that no i can't i'm not going to uh because i'm doing these things far too live to do that so i'm going to have a so my blue block is going to be solid let's let's put in a red one i did ask yesterday there's a guy rui here is one of the moderators may or may not be here at the moment uh we know him as tutus on the discord uh he can use this software like nobody else he's absolutely brilliant at using it and i was asking what are all the key codes to uh do things a bit faster for the video now because this is going to be my simple block i want some sort of indicator on it that i can move it around i think if i hold down alt there we go i want i'm going to use the plus on it that sort of indicates i can move this in any direction there we go let's move on to the next one i will have horizontal and vertical blocks and we'll color those the same we'll just put in oh dear that was a mistake wasn't i can't see where the thing lines up let's doing art live never do art live lesson note to self this is horrible i think we need a bit brighter for that one there we go let's get rid of the corners again and we'll just cut and paste that why would i use this uh why would i use this well one it was bought for me by a member of the community which i'm very grateful for but also it's actually very good at doing this it's very good at pixel artwork and given that i work predominantly with the pixel game engine it makes some sense in my mind that it's the right tool to use so we want one of these to represent vertical movement and we'll have one that represents horizontal only movement uh oh i've got an errant green pixel i don't know what that's about let's get rid of you what type of block have we not covered we've got movers we've got the countdown block we've not covered you yet have we countdown block let's go for green let's pick a darker green lighter green so i was hoping that there was going to be some sort of automatic shading tool built into this but no there isn't well at least though i've not found one and these are going to be countdown so we're actually going to draw the number on there right mr block type out solid blocks we've got the player that's going to stay as a rectangle got the move everywhere horizontal vertical countdown style by mr block goal so i'm going to keep the goals as little circles will this tutorial be available after the stream ends yes it'll just be a regular video um i'm not going to it'll just be this stream let me save those so save as although the sprites from um oh when was that that was the 100k wasn't it uh so uh blocks dot png okay we'll run with that and see how well we go so last bit of code is just to add in the graphics now and make it look a little bit more presentable and to do this we're going to use a new type so those of you that are dead familiar with the pixel game engine might not have seen this it snuck in without very much fanfare we're going to use a type called a renderable and i'm going to create another unique point actually i'm getting into the habit of using smart pointers for things on the whole some of you will like that some of you won't but you know we'll see how it goes so what i'm going to create is a renderable uh for my graphics now renderable simultaneously loads a sprite and creates a decal which is certainly a pge2 thing we've not used decals today and i've no intention of using it just yet and we'll call that tile so that's going to load up that image that we've just created and i'll go down to my on user create function and actually load that's a gfx tiles dot load and i know that the function is gfx slash what did we just call that png blocks dot png i hope i've got that right so we then load our graphics and now we want to be able to pass the graphics into all of these objects now there's lots of inelegant ways using static pointers and that sort of thing i'm just going to simply pass it in by modifying all of the draw cell functions to take in a reference excuse me a reference to this particular renderable const olc renderable and we'll call it skin and the idea being is that you can create your own tile sheet and you can just load that tile sheet once and reuse it everywhere and if you wanted to have a completely different look and feel on a different level you don't have to necessarily change the underlying graphics it's all tapping into you just pass in that particular single sheet of graphics now of course that's going to upset all of my subsequent overrides fortunately visual studio tells me where they are and so it's just a cut and paste job to sort them all out there we go and when we actually render the tiles down here in the draw south i need to pass in my gfx tiles that's what i call gfx tiles now the objects themselves aren't just going to miraculously start drawing the sprite now we need to change these fill rects into the equivalent draw whatever for that particular tile this is where i'm going to get everything backwards and upside down let's start with solid block so we're no longer just going to fill the rect we're going to call pg draw partial sprite which takes out what that allows us to do is we're going to specify the source location within this larger sprite and it'll chop that out and draw that for us so draw a partial sprite and the well the arguments are pretty similar actually pause time size the actual sprite is going to be our skin and we're going to take the sprite component of the renderable so as i've just mentioned a renderable combines decals and sprites and it is going to be sort of the recommended way now to access sort of image data going forward in the pixel game engine there's a variety of reasons why that's the case but if you prefer the old way that's totally acceptable too and i'm going to do something odd because i know that my solid block my solid block is this first one along so its coordinates is 0 0 but just to make these things a little bit easier to change later on if i need to i'm going to create a null vector there times size that's giving us our top left position zero zero times size and we also need to pass in the size of the bitmap or png that we want to chop out which again is just psi so it's all very simple stuff and i can copy and paste that line for the different block types so block player i'm just going to leave as a white rectangle block simple and get rid of the coloring in bit but let's go and have a look where did we say so that's now one over that's our first block lippy neck don't look at my desktop it's a terrible mess isn't it so now we're going to look at yes block simple which is one over and now we will go over to horizontal which is horizontal is 0 1 2 3 over 3 over oh that's hey look you know i'm a busy guy right desktop's a busy place uh and so vertical was i've already lost count now vertical was zero one two two over we'll put that there to a two countdown block we still want to do the draw string bit but we're going to use a different color that was our loss count zero one two three four that's four over four and i don't think there's any more block types left so providing i got the file name correct which chances are i'm not having much luck today am i ah ta-da there we go we've now got graphics very simple graphics and we can now make sense of what the blocks are telling us so this one can be pushed in all directions these can be pushed but they get stopped by those blocks there that can only move horizontally i'm going to be careful here so i won't be able to move those blocks vertically there we go we can move those vertically they can be moved and our countdown block five four three two one zero can't move anymore blocks can be stacked like this that's quite nice actually i like the block stacking let's try just mixing those up a bit so yeah it's quite happy with that job done i think the very basic mechanics of a sliding block puzzle game now should i no i don't think i will i think we've gone on long enough since this has to be uh an uploaded video [Laughter] oh well thank you there and excite us thank you very much so that's not too bad right in an hour and a half you know we've sort of thrown together the very basics we've not created actually any levels um and i'm going to leave that as a bit of a challenge for you guys so a bit later on today i'll upload the source code it'll be interesting to see what people can do with this and if you if you're on the discord server do actually sort of post screenshots or post the levels one of the things we could do is establish a common language for what these level formats are and start exchanging them as puzzles for people uh to uh to solve and pass around i'll bring that back on the screen so we can stir it oh press r and everything resets so yes a puzzle game video without actually creating any puzzles there now i've got one last thing to mention i did mention at the start uh i don't know how many viewers we've got because i cover those numbers up but the code jam is uh officially going to start in a month right i know that seems like ages away which to give people enough time i know a lot of people want to actually book a little bit of time off work or something like that to spend a couple of days on it certainly that's what i'm going to do it starts in a month's time it's a code jam i'm not going to reveal what the theme is of course until the uh the start and uh it's uh because it's a coach doesn't have to be games it can be applications can be all sorts of interesting things it's usually a very popular jam each year it's a lot of fun it's only one week long um but it starts in about a month if you're interested do join up the only thing to win is internet points but uh usually most of the the sensible entries get featured in a video later on too so there is that particularly the winning uh winning video so that is all from me i think there we go we've got a very simple puzzle game uh which leads me to say the usual stuff what do i normally say at the end of a video um ah if you've enjoyed this video please think of oh no i've said it wrong now i'm gonna start again starting if you've enjoyed this video please give me a big thumbs up have a think about subscribing come and have a chat on the discord server and i'll see you next time take care
Info
Channel: javidx9
Views: 38,656
Rating: undefined out of 5
Keywords:
Id: l7YEaa2otVE
Channel Id: undefined
Length: 96min 50sec (5810 seconds)
Published: Sun Jul 26 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.