Placeholder Image

Subtitles section Play video

  • COLTON OGDEN: All right, I think we're alive now.

  • Sorry for the delay.

  • This is CS50 on Twitch.

  • My name is Colton Ogden and today we're going

  • to continue the stream that we did last week on Friday where

  • we started implementing the game Snake from scratch.

  • Recall, we ended up putting something together a little bit like this.

  • So we had a little-- oh, sorry.

  • I forgot to switch to actual machine over there.

  • There we go.

  • We had something that look a little bit like this.

  • So almost like a little Etch A Sketch going but not exactly Snake

  • in the sense that most people I think recognize Snake.

  • But a lot of the pieces are still there.

  • You know, we went from having a cube that moved across the screen

  • to having a cube that sort of moved discreetly across the screen

  • in like a grid sort of way.

  • Talking about how we can actually divide our game space up into

  • a grid, which allows us to then start transitioning

  • into games like Rogue Lights and other games that are more tile based,

  • which we could definitely get into in the future.

  • And then we started talking about a Snake data structure

  • and we talked about some basic drawing routines and Love 2D

  • and all sorts of other stuff.

  • Won't go too much into the details because the VOD will be up

  • and this and the other video will also be going on YouTube.

  • But today, a couple of the problems that we want to solve

  • are one, make sure that when we do eat an apple in our game,

  • rather than our snake kind of just drawing an infinite line,

  • we want to actually get rid of the tail.

  • We want to pop the tail while continuing to draw, you know,

  • the head is just moving in another direction.

  • And another big thing that we want to bite off today

  • is making sure that when we collide with other parts of the snake

  • that we trigger a game over, as I would have just done right there.

  • And those are two sort of big pieces that we're going to bite off

  • and they're actually not terribly difficult.

  • I spent a little bit time over the weekend actually thinking

  • through the problem and I was a little bit tired last time

  • but we should be good today.

  • And then if we do have time, which I think we will--

  • we're going to be on for a three hour stream today.

  • We'll take a look at having an intro screen.

  • Like a-- you know, the word snake, press enter

  • to start because right now you kind of just

  • get right into the action, which is a little bit

  • tricky to jump just right into.

  • And then also a game over screen so that when we do intersect with the snake,

  • the game should stop.

  • Maybe transition us to another screen with some text on it

  • that says, "you've got a game over" and then display your score.

  • [? Sue Leith ?] says hello.

  • Hello, [? Sue Leith. ?] Good to see you.

  • [? Bavick Night ?] says hey, how's it going.

  • [? Bavick Night, ?] good to see you again.

  • And [? Sue Leith ?] asks, will this be re uploaded?

  • Yes.

  • So last week's video and this video will be up--

  • uploaded to YouTube.

  • They should be uploaded today, tonight, if not tomorrow morning.

  • And the VOD from last week is actually-- should

  • be accessible on this Twitch account.

  • The get hub for the actual code itself is on this URL.

  • So, github.com/coltonoscopy/snake50.

  • And you'll be able to see the main.lua file that's in there just by itself.

  • And recall main.lua is the entry point for LOVE 2D,

  • which is the framework that we used last Friday.

  • If unfamiliar, if you're just joining the stream for the first time, LOVE 2D

  • is the framework that we're using to do all of the game programming.

  • All the graphics, all the windowing, all the input, all that stuff.

  • So you can go to love2d.org.

  • By default, it should take you to a page that looks like this

  • and then you can download the version of ProCreate for your operating system.

  • So I'm on a Mac, I'm on Mojave, so you can just download here.

  • If you want to download other versions and older versions,

  • you have an option to do so here.

  • [? Bavick Night ?] says glad to be here.

  • Glad to have you, with us [? Bavick Night. ?] Thanks for joining.

  • All right.

  • So let's dive right in.

  • Briefly I will just summarize the code that we have.

  • So we have a constant table up here.

  • So just a set of constants that just basically say,

  • oh what's the window width and height?

  • What's the tile size?

  • Tile size being of our grid size, so we could think of it that way as well.

  • The number of tiles on the X and Y. And then a few constants

  • to represent particular slots in the grid

  • whether a tile is empty, whether it's a snake head, whether it's a snake body,

  • whether it's an apple.

  • Those are the main sort of game play mechanics at play.

  • And then lastly, a constant for the time in seconds

  • that should elapse before the snake actually moves in an individual grid

  • tile in the game.

  • We have a few other variables here.

  • So a font, a score, which is important, the actual grid for our tiles.

  • This is the data structure that actually holds the zeros,

  • one's, two's and three's that represent what's going on in our game world.

  • The snake X and the snake Y, which is where the snake's head is located,

  • whether our snake-- what direction or snake is moving in.

  • Which, this should just probably be called local snake direction

  • equals right.

  • But we've already called it snake moving, so we'll just keep it that way.

  • And then a snake timer because remember we

  • do have to keep track of how much time has actually

  • elapsed over the course of all the frames

  • before we end up moving our snake.

  • So we basically check snake timer against snake speed.

  • If snake timer is greater than snake speed,

  • then we should move to the next location.

  • And then here, we do need a data structure to represent our snake.

  • So because we need to make sure that we pop our tail off of the snake

  • whenever we move, we need to keep track of all the nodes

  • that we add to the snake as time goes on.

  • [? Sue Leith ?] says, where did you learn all of this?

  • Is there a Love 2D manual?

  • So, yeah.

  • Actually, Love 2D has some excellent documentation.

  • So there's a very basic set of tutorials just on the main page.

  • So here you can see there's some examples of basic application

  • where you draw text, draw on image, play a sound.

  • There are some full games you can take a look at.

  • I believe some of these have source code and some of these

  • are actually commercial Steam projects, which is cool.

  • Which goes to show you that you can actually

  • use this to make a published game on Steam if that's

  • something that's of interest to you.

  • The actual documentation is here.

  • So at the very bottom right, you can just click on any of those modules

  • and that will take you to the page for that.

  • [? CPU Intensive ?] says, tall hair.

  • Yeah, I know.

  • I need a haircut super badly, like really bad.

  • But if you go to love2d.org/wiki/love is where you can actually see

  • the documentation.

  • And there's a bunch of different name spaces here.

  • Love, love.audio, love.data, love.event.

  • We're going to be using pretty much just love.graphics.

  • We use love.window, as well, and then the core functions

  • that you can access in love.

  • So love.load, love.update, love.draw.

  • These are the functions that make up our game loop.

  • If you're familiar, we talked about this last week.

  • Every frame, which is usually 1/60 of a second.

  • Love2D will execute some code in a function

  • called love.update and love.draw each frame, update happening before draw.

  • And at the very start of your program it'll call a function called love.load.

  • Love.load sort of sets up everything, if you

  • have some variables that need to be initialized

  • or some resources that need to be loaded.

  • Optionally, as we did up here, you could just

  • put them at the very top of your script, and they'll all execute

  • in advance in much the same way.

  • But as is sort of tradition, you'll see a lot of these functions

  • like love.window.setTitle, love.graphics.setFont,

  • love.window.setMode, a lot of these functions that sort of set up the game,

  • set up the state machine that is Love2D, in a sense.

  • Those all exist here, as does setting the random number

  • generator, which we did last week.

  • And maybe initializing some data, and such.

  • [? JPguy ?] says hello again.

  • Hello, JP.

  • Good to see you.

  • I wanted to have the Twitch chat enabled in today's stream,

  • but we're having a little bit of difficulties with Streamlabs.

  • So we're going to try again.

  • Next week we should actually have the embedded chat in the final video,

  • so that folks watching online on YouTube or what

  • not after the fact can see what people in the chat saying.

  • So looking forward to--

  • hopefully tomorrow.

  • So tomorrow we're having another stream with Kareem Zidane

  • and if anybody's familiar.

  • He's going to be doing the Git and GitHub stream.

  • Elias says, "Hello, again from Morocco."

  • Hello, Elias.

  • Good to see you, again.

  • Thanks for coming in.

  • Just to cover a little bit more of what we have going on

  • in our love.keypressed function.

  • It takes a key.

  • Remember that we were testing for input.

  • So if we pressed left, right, up, or down,

  • we should set our moving variable to left, right, up, or down accordingly.

  • And then we do a check in our update function.

  • So remember, update executes once every 1/60 of a second,

  • approximately every frame.

  • And if we're moving in any of these given directions,

  • then we should increment or decrement our snakeX and snakeY variables.

  • Which, remember, that's where our head is going to be,

  • and that's sort of where its index is in the grid.

  • Originally, that was our pixel value, so we were measuring our square in pixels.

  • But remember, that was kind of continuous movement.

  • It wasn't actually adhering to a grid.

  • So a little bit trickier to do collision detection that way.

  • So we divided it up into a grid and we make

  • sure to move our snake in increments of 32 pixels, instead of just one pixel.

  • JP says, "How long have you been streaming?

  • I just got home from work."

  • Just for a couple of minutes.

  • So we're just reviewing all of the code that we did last Friday.

  • JP, I know you were there, so this is all old hat to you.

  • But in case anybody is watching who needs a refresher,

  • this sort of is a recap of everything that we did.

  • And then in drawGrid, we're basically just checking

  • each tile in a nested loop in our tile grid table, at yx for 1 to MAX_TILES y,

  • and one to MAX_TILES x on the y and the x-axes.

  • If it's empty, don't try anything.

  • If it's apple, draw red.

  • If it's head, draw a lighter shade of green.

  • So kind of a cyan green, since we have-- remember, love.graphics has that color,

  • takes in four variables--

  • red, green, blue, and alpha.

  • For a cyan-ish value, it needs to be 1 and 0.5.

  • 1 and 1 here.

  • G and B both thing 1 would be completely cyan.

  • But that's all a bit too bright, so we're just going

  • to make it 0.5 on the blue component.

  • And then the body itself we're just making kind of a dark green.

  • So instead of setting G all the way to 1,

  • we're sitting at the 0.5, which just kind of is halfway

  • between black and full green, effectively.

  • And then at our xy, we subtract 1 from the x and the y,

  • multiply that value by 32, because tables are one index by default.

  • But coordinate systems are zero indexed, so we need to decrement our xy,

  • and then multiply the end value by tile size.

  • That will have the effect of drawing that rectangle,

  • that square at the appropriate pixel coordinate in our game.

  • The drawSnake function we ended up actually not using,

  • so I think I'm just going to delete that.

  • I don't think we actually need to draw that.

  • The grid itself is going to handle drawing the snake,

  • so I'm going to take away the drawSnake call.

  • I'm going to take away the bit of code down near the drawSnake function,

  • going to save it.

  • Initializing the grid is fine.

  • And then up in our update function was sort