Project Snake. Project Snake Snake For this project, we’re going to make Snake This includes Making the overall game logic (using a 2D array) Handling.

Slides:



Advertisements
Similar presentations
2D Graphics Drawing Things. Graphics In your GUI, you might want to draw graphics E.g. draw lines, circles, shapes, draw strings etc The Graphics class.
Advertisements

Graphics You draw on a Graphics object The Graphics object cannot directly be created by your code, instead one is generated when the method paintComponent.
1 Drawing C Sc 335 Object-Oriented Programming and Design Rick Mercer.
CMSC 341 Building Java GUIs. 09/26/2007 CMSC 341 GUI 2 Why Java GUI Development? Course is about Data Structures, not GUIs. We are giving you the opportunity.
Cosc 5/4730 Game Design. A short game design primer. A game or animation is built on an animation loop. – Instance variables of “objects” are updated.
Mrs. Chapman. Tabs (Block Categories) Commands Available to use Script Area where you type your code Sprite Stage All sprites in this project.
Cosc 5/4730 Game Design. A short game design primer. A game or animation is built on an animation loop. – Instance variables of “objects” are updated.
IAT 800 Lab 1: Loops, Animation, and Simple User Interaction.
Mr. Wortzman. Tabs (Block Categories) Available Blocks Script Area Sprite Stage All sprites in this project.
Introduction to TouchDevelop
Iteration. Adding CDs to Vic Stack In many of the programs you write, you would like to have a CD on the stack before the program runs. To do this, you.
© The McGraw-Hill Companies, 2006 Chapter 4 Implementing methods.
CSE 219 Computer Science III Images. HW1 Has been posted on Blackboard Making a Game of Life with limited options.
KeyListener and Keyboard Events Just as we can implement listeners to handle mouse events, we can do the same for keyboard events (keypresses) –to implement.
KeyListener and Keyboard Events Another type of listener listens for keyboard entry – the KeyListener which generates KeyEvents –to implement KeyListener,
tiled Map Case Study: Rendering with JPanel © Allan C. Milne v
Addison Wesley is an imprint of © 2010 Pearson Addison-Wesley. All rights reserved. Chapter 7 The Game Loop and Animation Starting Out with Games & Graphics.
Graphics Concepts CS 2302, Fall /3/20142 Drawing Paths.
Graphic User Interface. Graphic User Interface (GUI) Most of us interact with computers using GUIs. GUIs are visual representations of the actions you.
11 Adding Tomato Targets Session Session Overview  We now have a game which lets a player bounce a piece of cheese on a bread bat  Now we have.
CSE 219 Computer Science III Image Manipulation. HW 1 Has been posted on Blackboard Making a Game of Life with limited.
Making Python Pretty!. How to Use This Presentation… Download a copy of this presentation to your ‘Computing’ folder. Follow the code examples, and put.
Interactive Programs Java API. Terminology Event—an action or occurrence, not part of a program, detected by the program. Events can be Event—an action.
1 GUIs, Layout, Drawing Rick Mercer. 2 Event-Driven Programming with Graphical user Interfaces  Most applications have graphical user interfaces (GUIs)
Lesson 3: Arrays and Loops. Arrays Arrays are like collections of variables Picture mailboxes all lined up in a row, or storage holes in a shelf – You.
Lesson 2: Reading a program. Remember: from yesterday We learned about… Precise language is needed to program Actors and Classes Methods – step by step.
CS 5JA Introduction to Java Graphics One of the powerful things about Java is that there is.
KeyListener and Keyboard Events Just as we can implement listeners to handle mouse events, we can do the same for keyboard events (keypresses) –to implement.
GUI Tutorial Day 4. More GUI action  adding a Mouse Listener  SimpleDots  Simple mouse listener  Draw an oval where the mouse is clicked  Box example.
CompSci 4 Java 4 Apr 14, 2009 Prof. Susan Rodger.
Game Maker Tutorials Introduction Clickball IntroductionClickball Where is it? Shooting Where is it?Shooting.
Sprites (Images) and Sounds
Graphical Output Basic Images.
MOM! Phineas and Ferb are … Aims:
Pixels, Colors and Shapes
Scratch for Interactivity
FLOWCHARTS Part 1.
PYGAME.
Eclipse Navigation & Usage.
Java Programming: Guided Learning with Early Objects
Let's Race! Typing on the Home Row
Miscellaneous Topics #6: Polygons GUI Components and Event Handlers
Engineering Innovation Center
PC02 Term 1 Project Basic Messenger. PC02 Term 1 Project Basic Messenger.
Computation as an Expressive Medium
Introduction to Object-Oriented Programming
4.14 GUI and Graphics Case Study: Creating Simple Drawings (Cont.)
Functions BIS1523 – Lecture 17.
Unreal Engine and C++ We’re finally at a point where we can start working in C++ with Unreal Engine To get everything set up for this properly, we’re going.
OOP Paradigms There are four main aspects of Object-Orientated Programming Inheritance Polymorphism Abstraction Encapsulation We’ve seen Encapsulation.
Fundamentals of Programming
PC02 Consolidation %WITTY_QUOTE%. PC02 Consolidation %WITTY_QUOTE%
CSE 8A Lecture 6 Reading for next class:
Coding Concepts (Sub- Programs)
PC01 Term 3 Project Snake. PC01 Term 3 Project Snake.
Coding Concepts (Data Structures)
Go to =>
Topic 1: Problem Solving
We’re moving on to more recap from other programming languages
Coding Concepts (Basics)
Introduction to TouchDevelop
Fundamentals of Data Representation
Game Loop Update & Draw.
Go to =>
Problem Solving Designing Algorithms.
Python programming exercise
Events, Event Handlers, and Threads
Data Structures & Algorithms
Creating a Simple Game in Scratch
Presentation transcript:

Project Snake

Snake For this project, we’re going to make Snake This includes Making the overall game logic (using a 2D array) Handling user input (using a KeyListener) Rendering the game to a window (using an extended JComponent class)

Snake Eventually, we’ll end up with something like this

Snake First, some setup Let’s start with the panel! The game area will be made up of a 2D array of integers Each cell represents a space in the game Each value represents something different 0 – empty space -1 – power-up Anything else – part of the Snake We can render these different parts onto a panel Let’s start with the panel!

SnakePanel Exercise Create a new Java project Give it a package Make a class in this package called SnakePanel Needs to extend JComponent Create five static final Color variables and give them values COLOUR_BACKGROUND (the colour of the background) COLOUR_LINES (the colour of the grid lines) COLOUR_SNAKE (the colour of the Snake) COLOUR_SNAKE_HEAD (the colour of the Snake’s head) COLOUR_POWERUP (the colour of power-ups)

SnakePanel This will be the first ‘game’ we’ve rendered before We looked at drawing shapes in Unit 6 This will work in the same way However, we’re going to use double-buffering Also known as V-Sync This is something that is done in games (especially for graphics)

SnakePanel Frame tearing (A.K.A screen tearing) is what happens when things are drawing directly onto a screen We’ll see some of the drawing process happen before the whole frame is rendered This is stopped via V-Sync (vertical sync) or double-buffering

SnakePanel When double-buffering, we draw onto a different panel Then, when done, we swap it out with the one on the screen That way, the player doesn’t see any direct rendering This, removing screen tears We’ll be doing this on our SnakePanel using a BufferedImage

SnakePanel Exercise After the static final colours, create a private BufferedImage instance variable Called canvas Give SnakePanel a constructor Assigns null to canvas Create a public void function called render Accepts two parameters 2D Integer array called snakeGrid Integer called snakeSize

SnakePanel Exercise At the beginning of render, use this line of code to create a BufferedImage: Then, get a ‘brush’ for this image using this line of code: BufferedImage vCanvas = new BufferedImage( (canvas == null ? getWidth() : canvas.getWidth()), (canvas == null ? getHeight() : canvas.getHeight()), BufferedImage.TYPE_INT_RGB); Graphics g = vCanvas.getGraphics();

SnakePanel What we’ve essentially done is made our ‘canvas’ off the screen I.e. the user will not see this yet The vCanvas.getGraphics() line gets the ‘brush’ for the image we made If you’re interested in the BufferedImage constructor, it accepted three arguments The width of the image The height of the image The image colour type

SnakePanel The width and the height should be the same as the panel That’s what we’re checking with canvas == null ? If the canvas is null (with the canvas being the screen) then get the width of the panel Otherwise get the screen’s width (really, they’re identical) The colour type determines the colour mode We generally use RGB (red, green, blue) That’s what the BufferedImage we just made uses However, there are more (like CMYK – Cyan, Magenta, Yellow, Key) With the side canvas and brush set up, we can get to work ‘rendering’

SnakePanel Exercise Set the ‘brush’ colour to COLOUR_BACKGROUND Fill a rectangle over the whole canvas Then calculate the cellWidth and cellHeight These represent the width and height of the cells in the game Can be calculated by dividing width/height by the lengths of the two dimensions in the 2D array I.e. this tells us how much space each cell in the grid can take up Once calculated, use a loop and a nested loop to go through every cell in the 2D array You’re essentially going through every row in the grid, and every column of every row

SnakePanel Exercise In each cell of the 2D array, check the for the following possibilities (using else-if chain) Current cell equals -1 Set the brush colour to COLOUR_POWERUP Fill a rectangle for the cell Current cell equals snakeSize Set the brush colour to COLOUR_SNAKE_HEAD Current cell greater than 0 Set the brush colour to SNAKE_COLOUR To fill a rectangle, you need the X, Y, width, and height X: multiply column index by cell width Y: multiply row index by cell height Width: cell width Height: cell height

SnakePanel Exercise After the loops, set the colour of the brush to COLOUR_LINES Then draw vertical/horizontal lines (using g.drawLine()) to separate each cell in the grid Best way to do this is go through every row and column separately Then draw lines from beginning to end of screen for each row/column Finally Use g.dispose() to remove the brush Use canvas = vCanvas to ‘swap’ the frame Use repaint() to update what the panel shows

SnakePanel Exercise Note that this doesn’t do anything yet We need to override paintComponent to show the right thing Override paintComponent(Graphics g) Inside, run super.paintComponent(g) Ensures everything still works when component put in something else, like a JScrollPane

SnakePanel Exercise Then check if the canvas is null If it is, show only a dark grey rectangle Otherwise use g.drawImage(canvas, 0, 0, null) to draw the swapped frame The parameters (in order) are The image to draw (our swapped frame, in this case) The X position to start the image at (of the top-left corner) The Y position to start the image at (of the top-left corner) The image observer (which is always null)

SnakeProgram That’s the SnakePanel setup We need to test it now We’ll make another class called SnakeProgram We will make a JFrame and a new SnakePanel We’ll then add the SnakePanel to the JFrame Finally, we’ll test the render function

SnakeProgram Exercise Create a new class called SnakeProgram Give it a constructor In the constructor Create a new JFrame and make it close the program on exit Create a new SnakePanel and give it a preferred size (something like 800x600) Create a 2D Integer array (6 rows and 8 columns) Put 1 in the top-left corner Put -1 in the bottom-right corner Add the SnakePanel to the JFrame, pack the JFrame, and make it visible Run the SnakePanel’s render function (pass in the 2D array and 1 as the arguments)

SnakeProgram Exercise Make the main method in SnakeProgram In the main Create a new SnakeProgram Run your program You should see something like this example image

Game Loop We know need to set up a major component of our game The game loop This loop does three things Maintains a constant frame-rate/update time Updates the game (i.e. moving the Snake and handling user input) Renders the game (using the SnakePanel that we made) To get started on this, we need to make a few instance variables in SnakeProgram

Game Loop Exercise Make the following instance variables Random number generator rng 2D integer array grid SnakePanel snakePanel Integer direction Integer currentRow Integer currentCol Integer size Assign them values in the constructor The grid should have 6 rows and 8 columns All the integers should be 0 (except size, which should be 1) The SnakePanel is already in the constructor Make sure its using the global variable, and not the local one

Game Loop Exercise You can also remove the render call As we don’t need it here Also, don’t add 1 and -1 to the grid any more That will be handled somewhere else

Game Loop With all that set up, let’s make a new function Called play This function will Set up the basic variables Start the game loop The variable setup includes Adding the snake to the current row and column Adding a power-up somewhere else

Game Loop Exercise Create a new function Called play It doesn’t need any parameters At the start of this function Set the current position of the grid to size

Adding Power Ups Something the game will be doing a lot in the game This should be done randomly What it needs to do is Generate random coordinates (row and column) If there’s nothing already there (i.e. the cell is 0) Add -1 to that position and stop Otherwise generate more random coordinates We can then use this function to add a power-up at the start of the game

Adding Power Ups Exercise Create a new function Called addPowerUp It doesn’t need any parameters This function should, using a loop Continuously generate random coordinates Within the limit of the grid If the randomly chosen cell is empty (i.e. the value is 0) Put -1 in its position Otherwise Make more random coordinate and try again

Adding Power Ups Exercise In your play function After setting the current position to size Run the addPowerUp function Then add an infinite loop Inside this loop, render the snakePanel Use the grid and size as the arguments In the main function Add .play() after creating a new SnakeProgram()

Game Loop When we run our program The Snake will be in the same place But the power-up will move about That means the addPowerUp function is working All we need to do is get our Snake moving

Game Loop This is what the grid looks like after running the game a few different times

Updates We need to ‘update’ the Snake’s position So we’ll make a separate function Called update Will handle Moving the Snake Colliding with power-ups/Snake body

Updates Exercise Create a new function Called update In this function, look at the value in direction If its 0, subtract 1 from the current row If its 1, add 1 to the current column Repeat this (but flip the logic) for 2 and 3 If current row or column go off the grid Wrap them back around E.g. if the current row goes to -1, wrap it back to the bottom of the grid

Updates Exercise Once new positions have been calculated Loop through every cell in grid If the cell is greater than 0 Subtract 1 from it Finally, once done Set the current position in the grid to size Run the update function after rendering the SnakePanel in play’s loop

Testing If you run your program, you should notice something The snake should be moving erratically That’s because it’s moving as fast as it can We’ve not put a limit on updates yet Easiest way of doing this is by adding a ‘speed’ for the Snake It will then update at the correct rate

Snake Speed Exercise Create an integer instance variable Called millisecondsPerUpdate Start it off with a value of 500 That’s half a second Assign it this value in the constructor At the start of play, create a long variable Called currentTime Assign it the value of System.currentTimeMillis() This gets the current system time

Snake Speed Exercise Then, inside the loop After rendering, but before updating Check if System.currentTimeMillis() – currentTime > millisecondsPerUpdate If so Update the game (using update) Set currentTime to System.currentTimeMillis() again

Testing If you run your program, the Snake should move at an acceptable pace now However, we can’t change its direction yet We need to add some controls That’s where a key listener will come in They are things we can attach to Swing components Like our SnakePanel

Key Listeners There’s an interface called KeyListener that we can implement We’ll implement it in our SnakeProgram class This will add a few functions keyTyped keyPressed keyReleased We’ll focus on keyPressed

Key Listeners Exercise Make your class implement KeyListener Add the functions required for this interface keyTyped keyPressed keyReleased

Key Listeners Inside keyPressed, we’ll use the KeyEvent parameter to work out which key was pressed This parameter has a function we can use called getKeyCode() We can use the returned value of this (an integer) and match it against static variables of the KeyEvent class for the different keys A quick way of doing this is by using a switch-statement

Key Listeners Here’s an example The different VK variables are the keyboard keys The UP, DOWN etc. keys are the arrow keys We could then change the direction based off which key we pressed switch(e.getKeyCode()) { case KeyEvent.VK_UP: break; case KeyEvent.VK_RIGHT: break; case KeyEvent.VK_DOWN: break; case KeyEvent.VK_LEFT: break; }

Key Listeners Exercise Inside the keyPressed function Use a switch-statement to check values against the parameter’s geyKeyCode() value Add cases for the different arrow keys (e.g. KeyEvent.VK_UP) If using up, set direction to 0 If using right, set direction to 1 And so on

Key Listeners Adding this function isn’t enough We need to then register this listener with the panel We need to do three things (all in SnakePanel’s constructor) Set the snakePanel to focusable Focus on the snakePanel Register a KeyListener on the snakePanel snakePanel.setFocusable(true); snakePanel.requestFocusInWindow(); snakePanel.addKeyListener(this);

Key Listeners Exercise Add these three lines of code to your SnakePanel class’s constructor Then play your game You should be able to move the Snake using the arrow keys snakePanel.setFocusable(true); snakePanel.requestFocusInWindow(); snakePanel.addKeyListener(this);

Testing When we play the game, we’ll be able to move the Snake using the arrow keys! Of course, we can’t pickup any power-ups yet We kind of ‘override’ them However, that will be the next thing to handle

Collisions Let’s get started on picking up those power-ups This, in essence, is detecting ‘collisions’ This will also be needed for when the snake runs into itself Just before setting the current position to size, we should see what cell the snake is moving onto If it’s a power-up, then we increase size Also add another power-up Using addPowerUp() function we made

Collisions Exercise Go into your update() function Go just before setting size to the current position Check if the current position in the grid equals -1 If it does, increase size by 1 Then assign size to current position in grid Then also run addPowerUp() Otherwise Add size to current position in grid

Collisions When we run this now, we’ll be able to pick up power-ups Our snake will also increase in size However, it can still go through itself The game doesn’t end When the snake runs into itself That’s something we need to add

Collisions However, our game loop is infinite Even if we lose, it will keep going We need a boolean flag (we’ll call it playing) Start this at true when game starts Can then use this as the condition in the game loop’s while part

Collisions Exercise Create a boolean instance variable: playing At the start of play(), set it to true Replace the while(true) with while(playing)

Collisions With this flag in place, we can change it When the snake runs into itself This is simple to do Simply change playing to false The game loop will then stop As the condition of the while loop will return false We could even output a message box saying the player has lost

Collisions Exercise In your update() function Add an else-if statement After the if statement for checking if it’s a power-up Add an else-if statement Checks if the current position in the grid is greater than 0 If it is, set playing to false OPTIONAL: Output a message box saying “You lose!”

Testing The game should now be ‘complete’! We can play the game Pick up power-ups Increase snake’s size Make snake crash into itself End the game

Optional Exercise The rest of these are optional (and should only be attempted once the rest is finished) Display the snake’s size on the window (either drawn on the panel or shown using a JLabel on the window somewhere) Let the user choose the number of rows/columns the game will use Add a way for resetting the game Make the snake move faster as it picks up power-ups