practical 2 jim finnis ([email protected]) · 2016. 11. 15. · possible models 8x8 array of...

36
CS12020 for CGVG Practical 2 Jim Finnis ([email protected])

Upload: others

Post on 09-Sep-2020

0 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Practical 2 Jim Finnis (jcf1@aber.ac.uk) · 2016. 11. 15. · Possible models 8x8 array of characters, each encoding a piece (e.g. “p” for pawn and “q” for queen, using upper

CS12020 for CGVG

Practical 2

Jim Finnis ([email protected])

Page 2: Practical 2 Jim Finnis (jcf1@aber.ac.uk) · 2016. 11. 15. · Possible models 8x8 array of characters, each encoding a piece (e.g. “p” for pawn and “q” for queen, using upper

This week

● Solution to last week and discussion● Global variables and the model● The Main Loop pattern● States and the State Machine pattern● Random numbers● “Debounced” user input

Page 3: Practical 2 Jim Finnis (jcf1@aber.ac.uk) · 2016. 11. 15. · Possible models 8x8 array of characters, each encoding a piece (e.g. “p” for pawn and “q” for queen, using upper

The previous worksheet

● A common solution:

Go left using for.. loop

Go right using for.. loop

loop()

Page 4: Practical 2 Jim Finnis (jcf1@aber.ac.uk) · 2016. 11. 15. · Possible models 8x8 array of characters, each encoding a piece (e.g. “p” for pawn and “q” for queen, using upper

A good first solution, but...

● Difficult to modify● Each inner loop has to have its own copy of

some of the code– Clear-draw-swap

– In more complex programs this gets really nasty

● When adding new stuff it's easy to forget to add some of that framework code.

Page 5: Practical 2 Jim Finnis (jcf1@aber.ac.uk) · 2016. 11. 15. · Possible models 8x8 array of characters, each encoding a piece (e.g. “p” for pawn and “q” for queen, using upper

Don't repeat yourself

● If you write code that does something, don't just copy and paste it to do that thing again.

● Make the thing into a function.● If you want to do a slightly different thing, make

that function take arguments to change its behaviour.

● This makes your code much easier to modify and extend.

Page 6: Practical 2 Jim Finnis (jcf1@aber.ac.uk) · 2016. 11. 15. · Possible models 8x8 array of characters, each encoding a piece (e.g. “p” for pawn and “q” for queen, using upper

Use variables

● Instead of writing code that just does one thing (move left eight steps, for example),

● write one piece of code that does one thing several different ways using variables.

● Be lazy – don't write it five times, each slightly different. Write it just once, a bit more cleverly.

Page 7: Practical 2 Jim Finnis (jcf1@aber.ac.uk) · 2016. 11. 15. · Possible models 8x8 array of characters, each encoding a piece (e.g. “p” for pawn and “q” for queen, using upper

The Simplest Thing

● But don't be too clever – always think “What's the simplest thing that can possibly work?”

● And one piece of code is always simpler than five.

Page 8: Practical 2 Jim Finnis (jcf1@aber.ac.uk) · 2016. 11. 15. · Possible models 8x8 array of characters, each encoding a piece (e.g. “p” for pawn and “q” for queen, using upper

void setup(){    AberLED.begin();}

void loop(){    int x;    for(int x=0;x<8;x++){        AberLED.clear();        AberLED.set(x,4,RED);        AberLED.swap();        delay(300);    }    for(int x=7;x>=0;x­­){        AberLED.clear();        AberLED.set(x,4,RED);        AberLED.swap();        delay(300);    }}

void setup(){    AberLED.begin();}

int x=0;int dx=1;

void loop(){    AberLED.clear();    AberLED.set(x,4,RED);    AberLED.swap();        x = x+dx;    if(x==0 || x==7){        dx = ­dx;    }    delay(300);}

Page 9: Practical 2 Jim Finnis (jcf1@aber.ac.uk) · 2016. 11. 15. · Possible models 8x8 array of characters, each encoding a piece (e.g. “p” for pawn and “q” for queen, using upper

Global variables

● Are bad.● Unless you're storing data which is genuinely

global – which the whole program needs access to

● Such as the “game state” - the data about the game's “world” - also called the model.

● Object-oriented languages like C++ and Java have helpful ways of dealing with global data.

Page 10: Practical 2 Jim Finnis (jcf1@aber.ac.uk) · 2016. 11. 15. · Possible models 8x8 array of characters, each encoding a piece (e.g. “p” for pawn and “q” for queen, using upper

The Model

● Your game models (makes an abstract “picture” of) a virtual world – this is true of all games.

● This world might be very complex, with hundreds of entities made up of moving parts, as in a modern AAA title

● Or it might be very simple, like noughts and crosses.

● But there's always a model – the game's representation of the world as data.

Page 11: Practical 2 Jim Finnis (jcf1@aber.ac.uk) · 2016. 11. 15. · Possible models 8x8 array of characters, each encoding a piece (e.g. “p” for pawn and “q” for queen, using upper

The Model

● First-person shooters– The environment, consisting of 3D shapes, some of

which may be free to move

– Enemies and other creatures, which have a position and some internal state (pose data, weaponry, ammo, alert status, velocity)

– Objects in the environment, such as ammo packs, quest items etc.

– You and equipment you're carrying/wielding

Page 12: Practical 2 Jim Finnis (jcf1@aber.ac.uk) · 2016. 11. 15. · Possible models 8x8 array of characters, each encoding a piece (e.g. “p” for pawn and “q” for queen, using upper

Simpler models

● Chess– An 8x8 grid

– A set of pieces

● Noughts and crosses (Tic-Tac-Toe)– A 3x3 grid

– Each part of which can be marked X, O or empty

Page 13: Practical 2 Jim Finnis (jcf1@aber.ac.uk) · 2016. 11. 15. · Possible models 8x8 array of characters, each encoding a piece (e.g. “p” for pawn and “q” for queen, using upper

Step 1 in game development:define the model

● What is your environment (the unchanging parts of the world, the “game board”)?

● What are your entities (things in the world)?● How should you represent them as data?

– Variables, arrays, structures...

Page 14: Practical 2 Jim Finnis (jcf1@aber.ac.uk) · 2016. 11. 15. · Possible models 8x8 array of characters, each encoding a piece (e.g. “p” for pawn and “q” for queen, using upper

An example

● Chess is a fairly simple game, model-wise● How would you represent the state of the

game inside the computer?

Page 15: Practical 2 Jim Finnis (jcf1@aber.ac.uk) · 2016. 11. 15. · Possible models 8x8 array of characters, each encoding a piece (e.g. “p” for pawn and “q” for queen, using upper

Possible models

● 8x8 array of characters, each encoding a piece (e.g. “p” for pawn and “q” for queen, using upper and lower case for black and white)

● Two arrays of “piece” structures, one for each player, each containing– Whether the piece has been taken

– X,Y position if not taken

– The index of the piece in the array determines its type, e.g. whitePieces[0] is the white king, and so on.

Page 16: Practical 2 Jim Finnis (jcf1@aber.ac.uk) · 2016. 11. 15. · Possible models 8x8 array of characters, each encoding a piece (e.g. “p” for pawn and “q” for queen, using upper

Which is best?

● It's a good idea to design your model so that invalid states are impossible to represent. This really helps prevent bugs.– The second example is more complex, but does this quite well.

● On the other hand, it should be easy to perform the operations on the model which the game requires – moving pieces, etc.

● On the third hand, it should be easy to display the model to the user – to render it.

● For those who know chess: what is the problem with the second model?

● It's all about compromises.

Page 17: Practical 2 Jim Finnis (jcf1@aber.ac.uk) · 2016. 11. 15. · Possible models 8x8 array of characters, each encoding a piece (e.g. “p” for pawn and “q” for queen, using upper

Making it move: the Main Loop

● Pretty much every game has one of these, even if it's hidden inside the engine

● It's an example of a design pattern – a particular way of solving a problem, more general than an algorithm.– You'll see more design patterns in your second year.

● This pattern is very specific to real-time graphics (games etc.)

● (many engines hide the main loop from you)

Page 18: Practical 2 Jim Finnis (jcf1@aber.ac.uk) · 2016. 11. 15. · Possible models 8x8 array of characters, each encoding a piece (e.g. “p” for pawn and “q” for queen, using upper

The Main Loop

Read input and update model accordingly

Update model for time step

Render model

e.g. player presses FIRE, so create new missile heading in the

player's direction

e.g. for all entities, add the velocity to the position, and

do collision checks

e.g.● Clear buffer● Draw environment● Scan through entities

and draw them● Draw HUD● Flip buffers

Page 19: Practical 2 Jim Finnis (jcf1@aber.ac.uk) · 2016. 11. 15. · Possible models 8x8 array of characters, each encoding a piece (e.g. “p” for pawn and “q” for queen, using upper

Main Loop: handling user input

● Read switches and other inputs.● Process these inputs by modifying the model.● Must not block – that is, it must not wait for

anything (e.g. user input). It runs as fast as it can.– delays are blocking. We'll talk about these later.

– As an aside, all console games will fail product testing if the screen freezes for more than a fraction of a second.

Page 20: Practical 2 Jim Finnis (jcf1@aber.ac.uk) · 2016. 11. 15. · Possible models 8x8 array of characters, each encoding a piece (e.g. “p” for pawn and “q” for queen, using upper

Main loop: updating

● Change the game model (i.e. the game data variables) in other ways than user input changes.

● Typically these are changes due to time or game AI.

● Examples:– Moving objects (player, enemy, bullets..) through the

world by adding their velocity to their position

– See if any of the enemies have noticed the player and change their behaviour if so

Page 21: Practical 2 Jim Finnis (jcf1@aber.ac.uk) · 2016. 11. 15. · Possible models 8x8 array of characters, each encoding a piece (e.g. “p” for pawn and “q” for queen, using upper

Main loop: rendering

● Drawing things to the screen representing the model.

● Doesn't change the model

Page 22: Practical 2 Jim Finnis (jcf1@aber.ac.uk) · 2016. 11. 15. · Possible models 8x8 array of characters, each encoding a piece (e.g. “p” for pawn and “q” for queen, using upper

Keep everything separate

● The update and user input code shouldn't do any rendering

● The rendering code shouldn't do any updating● This helps keep your code easy to maintain

– You know where the code which draws stuff will be

– You know where the code which changes stuff will be

Page 23: Practical 2 Jim Finnis (jcf1@aber.ac.uk) · 2016. 11. 15. · Possible models 8x8 array of characters, each encoding a piece (e.g. “p” for pawn and “q” for queen, using upper

● An example framework for a Main Loop application.

● You need to add:

– Model data

– Set-up code

– Input, update and rendering code

void setup(){    AberLED.begin();    ... // set up initial state}

void handleInput(){    ...}

void update(){    ...}

void render(){    AberLED.clear();    ...    AberLED.swap();}

// do not modify below here

void loop(){    handleInput();    update();    render();}

Page 24: Practical 2 Jim Finnis (jcf1@aber.ac.uk) · 2016. 11. 15. · Possible models 8x8 array of characters, each encoding a piece (e.g. “p” for pawn and “q” for queen, using upper

Timers

● You shouldn't ever use delay() - why not?● The millis() function will return the number of

milliseconds since the program started.● You can use this to find the number of

milliseconds since something happened.

Page 25: Practical 2 Jim Finnis (jcf1@aber.ac.uk) · 2016. 11. 15. · Possible models 8x8 array of characters, each encoding a piece (e.g. “p” for pawn and “q” for queen, using upper

Timers

● Here's some code that will make something happens 2 seconds after something else:

as a global (part of your model):

unsigned long eventTime=0L;

starting the timer:

eventTime = millis()+2000;

somewhere else:

if((0L != eventTime) && (millis() > eventTime)){eventTime=0L; // reset the timer… do something

}

Page 26: Practical 2 Jim Finnis (jcf1@aber.ac.uk) · 2016. 11. 15. · Possible models 8x8 array of characters, each encoding a piece (e.g. “p” for pawn and “q” for queen, using upper

States

● Your game will probably have several different phases:– menu, gameplay, winning/losing screen, high score

table, etc...

● In each of these, render(), update() and handleInput() need to do something completely different.

● The code for this can get very messy.

Page 27: Practical 2 Jim Finnis (jcf1@aber.ac.uk) · 2016. 11. 15. · Possible models 8x8 array of characters, each encoding a piece (e.g. “p” for pawn and “q” for queen, using upper

State Machines

● We use the idea of a state machine to deal with this.

● Each different phase of the program is called a state

● The state machine can be in one of states, and can move to other states.

Page 28: Practical 2 Jim Finnis (jcf1@aber.ac.uk) · 2016. 11. 15. · Possible models 8x8 array of characters, each encoding a piece (e.g. “p” for pawn and “q” for queen, using upper

State Machines

● Have a variable (usually an int) with the current state

● Code in the main loop can then look at the state variable (using if or switch) to decide what to do

● The main loop update can change the state under well-defined conditions

● Like Main Loop, it's another design pattern

Page 29: Practical 2 Jim Finnis (jcf1@aber.ac.uk) · 2016. 11. 15. · Possible models 8x8 array of characters, each encoding a piece (e.g. “p” for pawn and “q” for queen, using upper

Shows only the game

Shows only the menu

State Diagrams

MENU

FADE UP

FADEDOWN

GAMESTARTShow both menu and

game

On “OK” pressed On fade up complete

On game exitOn fade down

complete

Show the states, and how states move to other states

Page 30: Practical 2 Jim Finnis (jcf1@aber.ac.uk) · 2016. 11. 15. · Possible models 8x8 array of characters, each encoding a piece (e.g. “p” for pawn and “q” for queen, using upper

State machine code

● A #define for each state● Global state variable initially invalid (-1)● gotoState(int s) goes to state s (by setting the state

variable to s), and stores the current time● GetStateTime() returns the current time minus the time

of the last call to gotoState()● You add switches and conditional code to update() etc.

which uses the state variable to decide what to do● This code is provided on the worksheet.

Work through an example

Page 31: Practical 2 Jim Finnis (jcf1@aber.ac.uk) · 2016. 11. 15. · Possible models 8x8 array of characters, each encoding a piece (e.g. “p” for pawn and “q” for queen, using upper

Random Numbers

● Are very important in games!● random(max) returns a random number from 0

to max-1● So random(10) returns 0,1,2,3,4,5,6,7,8 or 9

– Note that you get numbers up to max-1, not max!

– What would you use to simulate a six-sided dice?

Page 32: Practical 2 Jim Finnis (jcf1@aber.ac.uk) · 2016. 11. 15. · Possible models 8x8 array of characters, each encoding a piece (e.g. “p” for pawn and “q” for queen, using upper

Random Numbers

● Performing an event sometimes, but not always:

● random(10) will return 0 one time in ten● So if(0==random(10)) { … } will run the code in

the brackets one time in ten● This is useful for doing things at random

intervals in your update● You'll find this handy for the assignment

Page 33: Practical 2 Jim Finnis (jcf1@aber.ac.uk) · 2016. 11. 15. · Possible models 8x8 array of characters, each encoding a piece (e.g. “p” for pawn and “q” for queen, using upper

A Bit More User Input

● Finding out when a button has been pressed● You need to compare the previous state of the

button with the current state● But buttons are bouncy!

Page 34: Practical 2 Jim Finnis (jcf1@aber.ac.uk) · 2016. 11. 15. · Possible models 8x8 array of characters, each encoding a piece (e.g. “p” for pawn and “q” for queen, using upper

Debouncing

Button on

Button off

We want to ignore all these

Button has been down for long enough for it to count

Page 35: Practical 2 Jim Finnis (jcf1@aber.ac.uk) · 2016. 11. 15. · Possible models 8x8 array of characters, each encoding a piece (e.g. “p” for pawn and “q” for queen, using upper

getButtonDown(int n)

● Luckily I've written code which does this for you!

● Call getButtonDown(int b) to find out whether a button has gone down since the last interrupt, and has been down for at least 20 consecutive interrupts.

Page 36: Practical 2 Jim Finnis (jcf1@aber.ac.uk) · 2016. 11. 15. · Possible models 8x8 array of characters, each encoding a piece (e.g. “p” for pawn and “q” for queen, using upper

The assignment

● You should now know everything you need to do the assignment

● Design your model● Structure the main loop as described: handleInput(),

update() and render() functions all called from loop()● Use a state machine and switch statements inside

your main loop functions● Don't use a delay – use getStateTime() or millis()

(see this week's worksheet)