OOexample
“Dungeon” example --- as seen in CSCI121?
OO example
• Run through process of developing an OO program– identifying plausible classes– identifying relationships among classes (class
hierarchy)– scenario analysis (sorting out details of object interactions)– preliminary class designs– ...
OO example
• Language specifics– how to define the class hierarchy
• extends• abstract class and function• ...
• Details– how to handle graphics using standard Java library
classes– using Java collection classes
Dungeon Example
Dungeon Example
• Specification: The "dungeon" game program is to:
– Read game details from a text file• map layout,• collectable items, • the monsters, and • the player.
– Provide a display • main map window
– Run the game
Dungeon Example
• Specification (contd):– Operate a "run cycle": every 1 second
• if user has entered a command, execute it• all other active items get a chance to run.
– The player object acquires a collectable item by moving over the point where the item is located. A collectable item will change one or more of the player's "health", "wealth", ... attributes.
– Handle attacks by monster objects on the player. • attacks by adjacent monsters• attacks using projectiles
Dungeon Example• Specification (contd):
– Handle attacks by the player on a monster object.– Handle movements
• restrictions on motion etc
– Behaviours for monster objects.• Attack adjacent player• "look" for the player and, if they can "see" the player, they may advance toward
it or launch a projectile.• perform its "normal movement" function. This might involve random
movement, no movement, or some more purposive behaviour.• do not attempt to acquire collectable items.• do not interact with other monster objects.
Design preliminaries
• Overall program organization
• Some ideas on files containing “dungeon definition data”
• Initial ideas for objects and classes
Design preliminariesOverall organization
• Create the principal object, tell it to “Run”!public class Dungeon {
static public void main(String args[]){if(args.length < 1) { System.out.println("Must provide data file"); System.exit(1); }Dungeon d = new Dungeon();d.initialize(args[0]);d.Run();}
Design preliminariesinput file
• Make it a text file that can be created by a word processor.• Need:
– details of map, • size• location of walls etc
– details of items in dungeon• prefer not to have a count, so use some input scheme with a “sentinel”
data record at end• prefer items in any order (makes it simpler for someone to edit a new dungeon
file)• need some kind of item identifier followed by list of parameters
Design preliminariesinput file
width and height (e.g 50 20)several (20) lines of (50) characters, e.g.##################### … … ############ # # … … # ## ######## # # … … ####### #dungeon itemsPlayer11...
• exactly one human, at least one collectable, all objects located within bounds, …
Object type & parameters
Preliminary Design
• What are the objects (and their classes)?
• As it is a kind of simulation, finding objects will be fairly simple. Most, if not all, will be obvious from the specification.– Dungeon– Player– Monster (? probably with subclasses)– any lists etc needed to keep collections of monsters– “window” classes needed for the display– …
Preliminary Design• Consider in turn each of the “obvious” classes
– what do instances own?– what do instances do?
• How do you do it?– “brainstorming”– analogy to previous similar programs– if a group project, “play act”
• Aim? – establishing an understanding of overall problem,– creating a context for more later more detailed analysis using
techniques like scenarios
Preliminary DesignClass Dungeon
• Does:– load details from file– run– ?
• Owns:– everything really, lists of monsters, lists of collectable
items, map, …– probably owns some “window” objects
Preliminary DesignClass Dungeon
• Sketch pseudo-code for some of major functions:Dungeon: initialize (file)
Open file with name givenLoad map
create a map, tell it to load its data
Load other data read type of next item create an item of that type tell it to load its data
…
Preliminary DesignClass Dungeon
Dungeon: load other data…
• This function is going to have to create “player” object, “collectable items”, and “monster” objects.
• Needs to know about each of these classes – implies strong linkages to other components.
• How do “collectable items” and “monsters” get stored? Leave decision open till later more detailed design stage (but note it as something to be resolved).
Preliminary DesignClass Dungeon
• Main “Run()” function:
Dungeon: Run() Draw initial stateforever ...
wait 1 second Player runs (if command entered, process it)
all monsters get a turn to run update display to reflect changes
if(player no longer “alive”) break; if(all treasures collected) break;
Preliminary DesignClass Dungeon
• Dungeon object “owns” map.• Player and Monster objects will need to know
positions of walls etc when making their moves.
• Hence:– Player and Monster objects will need link (pointer) to
Dungeon so that they can ask it for information– Dungeon class will have to provide some kind of access
function that allows map to be accessed by other objects
Preliminary Designclass Player
• Player object's main responsibility:– getting and interpreting a command entered by
the user.• Movement commands
– Single characters– normal number pad conventions, 7 = "north west", 8 =
"north", 9 = "north east",
Preliminary Designclass Player
• Player: Run()Player: Run()
if keyboard data available read characters if first is digit, perform movement command
Player: perform movement command() based on digit direction, work out new point where player would be check for and take any collectable at that location, check for monster at that location, hit any try movement (not through walls etc)
Preliminary Designclass Player
• Some auxiliary functions needed class Player
• Lots of interactions with other objects – Dungeon, collectable items, monsters
Preliminary Designclass Collectable
• Collectable owns– value(s), display symbol, position, …
• does– draws itself, reports value, ?
• Pretty limited, collectable objects mainly manipulated by others, probably never ask any other object to do anything. (If a project group exercise, you would give class collectable to your weakest group member.)
Preliminary Designclass Monster
• Monster owns:– position, display symbol– some forms of “health” , “strength”, ... ratings– link to Dungeon– …
• Monster does:– probably draws itself when asked by dungeon– gets asked its position (dungeon and/or player)– gets hit by player (taking damage)– “runs”– …
Preliminary Designclass Monster
• Behaviour of Monster epitomised by its Run() function:
Monster: Run()if(CanAttack())
Attack();elseif(CanDetect())
Advance();elseNormalMove();
Preliminary Designclass Monster
• Class Monster can define implementation of some functions– Run(), …
• Class Monster can define a default implementation of other functions– CanAttack(), Attack(), NormalMove(), …
• Class Monster may have some abstract (“pure virtual”) functions that have to be defined by subclasses– ?
Preliminary Designclass Monster
• Subclasses:– differ mainly in how they implement things like “normal
movement”• sit where they are• move randomly• move in constant direction, when blocked pick new direction at random• follow route• …
– this is main area for cusomisation and extension, can invent any number of Monster subclasses with slightly changed behaviours.
Preliminary Designadditional minor classes
• As you work through a design, you often find minor classes not necessarily obvious in the specification.
• Here, need to check positions of Monsters, Player, Collectable objects.
• Position defined by (x, y) coordinate pair; need to do operations like check equality, check adjacency.
• Worth introducing
class Pt { … } also Images, Input, ...
(Pt rather than Point, to avoid conflict with class from Java awt library)
Preliminary DesignWindows
• For this program, can get by with almost standard windows from Java libraries– Frame framewindow (communicates with your
workstation’s window manager,...)– MyCanvas standard Java Canvas (drawing area)
class extended so as to have a link to a structure that can actually draw the data
Preliminary designWindows
• How to create a picture for screen?
• Map is a simple grid of uniformly sized cells - that makes it easy:– use images, create as gifs, (any reasonable size, display code will scale to
specified size)• Map object might as well handle the display
– base layer (walls etc)– overlay layer (entries for moveable items, they will have to
notify map whenever they move)
Preliminary designWindows
• Will have to consider “flicker” on screen if will be drawing lots of images – “off screen images”
• essentially build a copy of overall picture in own memory
• copy completed picture to screen memory buffer
Refining the designDungeon item hierarchy
• First, lets get some distinct subclasses of class Monster
• Ghosts – just hang around until Player gets close, then advance (through walls if necessary) to attack.
• Wanderer – keep moving around, if they see Player they advance.
• Patrol –follow predefined route that they never leave; if they see Player, they fire projectile.
Refining the designSubclasses of Monster
• Ghost: need simply redefine CanDetect() and Advance() functions.
• Wanderer: bit more elaborate, needs data members to record direction in which it is currently travelling, and possibly additional data or function for sorting out line of sight and path for advance.
• Patrol: more elaborate, needs extra data members for route, needs auxiliary member functions to sort out route following behaviour and projectile path.
Refining the designSubclasses of class Monster
Monster
Ghost Wanderer Patrol
class hierarchy diagrams form part of required design documentation
Subclasses of Monster.
Why no subclases of Collectable?
Subclassing
• Subclassing is to cater for real differences in behaviour.• Different Monsters have different ways of detecting and
attacking Player.
• Collectables differ only in value of attributes - their icon, their value(s).
• Don’t subclass if can represent differences by changes in attributes.
Refining the designExtending that hierarchy
• Can go further with the hierarchy by exploiting other relations between classes
• Monster and Player classes– Pt coordinate, a health attribute, a strength attribute– read initial data from file, – get hit, get asked if alive, ...– move.
• Commonalities make it worth defining a new abstraction, "ActiveItem", that subsumes both the Player and the Monsters.
Refining the designExtending that hierarchy
• Collectable and ActiveItem– Pt coordinates, – draw and erase behaviours; – query on location
• Common behaviours can be defined in a base class: DungeonItem.
DungeonItem
Collectable ActiveItem
Player Monster
Ghost Wanderer Patrol
owns link to Dungeon, point coord, display symbol does draws itself, erases itself, reads data from file, reports where it is
owns 3 integer value fields does reads extra data, reports values
owns health & strength attributes does reads extra data "runs" (define in subclass) gets hit reports if still "alive" moves
owns (nothing extra) does "runs" using "Can Attack", "Attack", "Can Detect", "Advance", "NormalMove"
owns "manna", wealth attributes, movecount, links to windows used to display status does reads extra data gets user command, takes collectables, attacks monsters, interprets movement & magic commands
Subclasses of Monster own unique data (patrol "route", wanderer record of last move) does substitute specialized NormalMove(), Advance(), functions; read any extra data params.
Refining the designObject interactions
• Next:– scenario analysis, map out the interactions
among objects
• Aims:– identify all the objects that interact (a “client” object has to be given a
pointer to its “server” object, when and how are these pointer links set)– what requests? (may find additional member functions for servers)– pattern of interactions (provides basis for more detailed pseudo-code
outline for member function)
Scenario analysis• Pick “major events” in program
– could be• user command• arrival of network message• timer event• ...
• Determine what processing is triggered by the arrival of the event– what objects are involved, what do they do
Scenario analysis
• Dungeon– initial start up, how are the objects created and
how do they get to read data from the file– one second timer
• what happens when “Player” object gets to run• what happens when a typical Monster gets to run
– display• how does picture get drawn
Refining the designObject interaction diagrams
• Player: Run()
• extra functions of Dungeon returning position of details of Monster at given point etc
Player object
Dungeon object
System.in object
loop
Run()
Monster object
available()
…PerformMovement…MonsterAt()
GetHit()
Alive()
Attack()
RemoveM()
read()
Object interaction diagrams
• Show principal objects– Player Run() may also involve String objects, Pt
objects etc; can suppress minor detail (these objects will mainly be locals in member functions)
– each principal object shown by “lifeline”• starts at top if object in existence before scenario started • ends at bottom if object still in existence at end• otherwise object being created or destroyed as part of
scenario
Object interaction diagrams• Vertical axis represents time dimension (usually
not to scale)• Interactions among objects marked by call
linesPlayer object Dungeon
“monster at ...”
Object interaction diagrams
• Why draw the diagrams?– When developing program
• lets you work out the processing in a very high level form of pseudo code
• helps you determine what each type of object does (if scenario shows one object asking another for information, then there better be an appropriate member function in class’s public interface)
– When documenting working program• helps you illustrate dynamic relations
Scenario analysis
• Scenario analysis should result in following design documents– object interaction diagrams of major events– finalized lists of all classes– for each class, a “design diagram” listing
• member functions (methods) along with access status and some indication of signature
• data members– for class hierarchies, a hierarchy diagram
Dungeon classes
• Dungeon• Map• Display• MyCanvas• Pt• Input (“static class”)• Images (“static class”)
• DungeonItem hierarchy – DungeonItem
• Collectable• ActiveItem
– Player– Monster
• Ghost• Wanderer• Patrol
class Input: provides some functions for file inputclass Images: “global data” (array of images) and associated function that loads images
class Pt
class Design diagram
int fX, fYconstructors Pt(), Pt(Pt other), Pt(x,y)Read(BufferedInput)access functions X(), Y()
equals(Pt other)adjacent(Pt other)distance(Pt other)SetPt(newx, newy)
class Map
class Design diagram
content and overlayarray, dimensions
constructors Map(width, height)Read(BufferedInput)
acessible(coords)validPt(coords)...paint(Graphics)
class DungeonItem
int ImageNo• Pt position• Link to Dungeon
DungeonItem(imageno, dlink)Read(BufferedInput)Position()Show()Vanish()
Hierarchy requires indication of protected statu
class Collectableextends DungeonItem
int values (cash value, health, etc)
Collectable(imageno, dlink)Read(BufferedInput)
access functions for Health() etc
abstract class ActiveItemextends DungeonItem
int values (health, strength etc)
ActiveItem(imageno, dlink)Read(BufferedInput)abstract Run()Alive?(),GetHit(int)
• Move()• Step()...
Player & Monster subclasses define Run(), nothing in common in their implementations
Detailed design stage• Next step:
– for each class• finalize decision on data type and accessibility of
each data member• develop actual prototypes for member functions
(return type, type of all arguments)• write outline of each member function
– pseudo code– one or two sentence description
Example of detailed design choice in Dungeon program
• Earlier noted that Dungeon would need– collections of Monsters and Collectable items,– would need to iterate through these collections
• for each monster in collection do monster.run
• How to represent such a collection?• How to handle iteration?
Java utility library
• Programming effectively in Java requires extensive knowledge of Java class libraries!
• Utilities library:– class Vector
• essentially a dynamic array– class Enumeration
• standard “iterator”
class Vector
• Vector– addElement(), removeElement(), size(), contains(),
capacity(), elements(), ...
– create a vector (with default or specified capacity)– add elements as required (Vector will grow if initial
capacity inadequate)– search for object, retrieve object at particular position, ...– get an Enumeration (iterator)
class Vector
• Dungeon can use Vector objects for its collections:private Vector fProps;private Vector fInhabitants;
public Dungeon(){fProps = new Vector();fInhabitants = new Vector();
// alternative declare members with new ...}
Dungeon’s use of class Vector
if(s.equals("Ghost")) {Ghost g = new Ghost(this);g.Read(input);fInhabitants.addElement(g);}
private Vector fInhabitants;
Iterators
• Concept of “Iterator” should have been introduced in previous subject, but you probably have not written any code using them.
• So, first a reminder
Iterators
Iterators
• You often need to work through a collection:
for each item in list do print details of item
for each item in binarytree do write details of item to file
{ go to start of list find first item that satisfies user request}
{ find next item that satisfies request}
Simple cases
Slightly more sophisticated ...
From 100-level, C++ material
Iterators
• You may have seen examples where a collection offered some built in traversal function – e.g. a BinaryTree that has print function that involves in-
order traversal
• Increasingly, program designers are trying to generalize, they are trying to find mechanisms that apply to many different problems.
• General approaches have been proposed for working through collections.
Iteratorsclass Iterator {public:
Iterator(…);void First(void);void Next(void);int IsDone(void);void *CurrentItem(void);
private:…
};
From 100-level, C++ material
Iterators
• The idea is that you can create an iterator object associated with a dynamic array, list or tree collection.
• Later you can tell that iterator object to arrange to be looking at the "first" element in the collection.
• Then you can loop examining the items in the collection, using Next() to move on to the next item, and using the IsDone() function to check for completion:
IteratorsCollection c1;…Iteratori1(c1);i1.Start();while(!i1.IsDone()) {
Thing* t = (Thing*) i1.CurrentItem();t->DoSomething();…;i1.Next();}
• This code would work whether the collection were a DynamicArray, a List, or a BinaryTree.
From 100-level, C++ material
Type cast needed, iterator can’t know class of items in collection
Enumeration
• Java collection classes typically have associated “Enumeration” classes.
• Enumeration is simply an interface (a pure abstract class)– each collection class has to provide a
specialized subclass (because each collection class has a different way of storing data)
Enumeration
• Functionality for Enumeration is a bit more limited than example “Iterator” (which reflects common C++ styles).
• Enumeration– boolean hasMoreElements()– Object nextElement() (also does advance
through collection)– (no reset to start of collection etc)
Vector & Enumeration
• A Vector object can be asked to return an Enumeration object.
• This Enumeration object can then step through collection:
Vector & EnumerationMonster MonsterAt(Pt p) {
Enumeration e = fInhabitants.elements();while(e.hasMoreElements()) {try { Monster m = (Monster) e.nextElement(); if(m.IsAt(p)) return m; }catch (NoSuchElementException nosuch) { }}return null;
}
Note, again need type cast
Example of detailed design choice in Dungeon program
• class Input is for functionality that doesn’t really belong in any of the problem specific classes– read an integer– open a file
– design choice: factor these operatons out into separate “static” class
“static” Input class ...class Input {
static public int GetInt(BufferedReader input){...}
static public BufferedReader Openfile( String filename)
{...}
}
“static” Input class ...
• Can then use GetInt() in all the classes that need to read integers – Dungeon (get map dimensions), Pt, Collectable, ...
class Pt { ...
public void Read(BufferedReader in){fX = Input.GetInt(in);fY = Input.GetInt(in);}
Example of detailed design choice in Dungeon program
• class Images illustrates handling of “global data” (responsibility for these data could have been allocated to Map, or maybe MyCanvas, or Dungeon --- but none seemed right!)– Images has publically accessible array of Image
objects
img= Images.theImages[fContent[row][col]];
class Images {static int kBLANK = 0;static int kWALL = 1;...static int kPATROL= 8;
static public Image[] theImages;static String[] thefiles = { ..."images/patrol.GIF" };
static public void LoadImages(Toolkit t) { int nImages = thefiles.length; theImages = new Image[nImages]; for(int i=1; i < nImages; i++) { theImages[i] = t.getImage(thefiles[i]); } }} What is a ‘Toolkit’ and what is
it really doing here?
Example of detailed design choice in Dungeon program
• Double buffering for flicker free display.• Map handles actual drawingclear existing displayfor each row do for each column do image is null if(something in overlay plane) image is image corresponding to item else if (something in backround plane) image is image corresponding to item if(image not null) draw image in box determined by row,col
Display code
• That code would result in a flickery display
• “Standard” code fragment available– add to “update()” of actual display object
(MyCanvas)– arranges to draw to memory image map, then
copy cleanly to screen
How do you know about “flicker free” graphics, and useful code fragments? Yeah, part of the “frameworks” problem!
class MyCanvas extends Canvas { ...
public void update(Graphics g) { Graphics gr;
if (offScreenBuffer==null || (! (offScreenBuffer.getWidth(this) == this.getSize().width && offScreenBuffer.getHeight(this) ==
this.getSize().height))) { offScreenBuffer =
this.createImage(getSize().width, getSize().height); }
gr = offScreenBuffer.getGraphics(); paint(gr);
g.drawImage(offScreenBuffer, 0, 0, this); }
private Image offScreenBuffer;}
Creates new off screen buffer when necessary
Detailed design stage:function prototypes
• Your earlier design diagrams listed member functions with some rough indication of arguments. Finalize them:
Dungeon static public void main(String args[]) public Dungeon() void initialize(String filename) Map Map() Player Human()
void loadItems(BufferedReader input) void RemoveMonster(Monster m)
...
Detailed design stage:function definitions
• Each function should get either a pseudo code outline or a statement in English. Statements:
Map Dungeon.Map() Accessor for Map data member.
void Map.RemoveMonster(Monster m)Gets monster m to remove itself from map, thentells fInhabitants collection to discard its reference to m.
Collectable Map.CollectableAt(Pt p)Using an Enumeration, iterate through fProps collection,asking each collectable if located at specified Pt p. Returnreference to first found, or null if none at Pt p.
Detailed design stage:function definitions
• Statement style descriptions are OK if they admit only one possible implementation.
• Following not OK (because it doesn’t define implementation)
Collectable Map.CollectableAt(Pt p)Find collectable or null at p.
Detailed design stage:function definitions
• Pseudo code styleboolean Pt.adjacent(Pt other)
if this.equals other return false; deltax = difference in X coords deltay = difference in Y coords if both deltax and deltay less than or equal to 1 return true return false
Code, but without the syntactic fussies; easy to implement in Java, or in C++, (or Delphi, or ...)
Detailed design stage
• Only complex functions in program are those for determining “clear line of sight” between two points.
• Algorithm used is a standard one from computer graphics – take pseudo code from graphics book– adapt
Implementation• Module structure• Code:
– Use of enumerators, creation of objects, heterogeneous collection and polymorphism, graphics, ...
– Defining and using class hierarchies• Constructors when have hierarchy• Abstract classes and functions• Default implementations• Overriding default implementations• Using parent class partial implementation
Implementation:module structure
• A C++ version of this program should involve multiple modules.• In Java, it is on the borderline; is just within size
range where still reasonable to construct as a single module containing definitions of all classes.
• Dungeon.java will need to import– awt.* for Frame, Canvas, Graphics– Math.* for Double.sqrt() etc– util.* for Vector, Enumeration,
import java.awt.*;...class Images { ... }class Input {... }class Pt {... }class Map { ... } class MyCanvas extends Canvas {... } class Display {... } class DungeonItem {... } class Collectable extends DungeonItem {... } abstract class ActiveItem extends DungeonItem {... } class Player extends ActiveItem {... } abstract class Monster extends ActiveItem {... } class Ghost extends Monster {... } class Wanderer extends Monster {... } class Patrol extends Monster {... } public class Dungeon { }
class Dungeon• Constructorpublic Dungeon()
{fProps = new Vector();fInhabitants = new Vector();}
• ? Probably better Java style to do allocation of vectors where variables declared
private Vector fInhabitants = new Vector();
• Use of Enumeration as previously illustrated:Monster MonsterAt(Pt p) { Enumeration e = fInhabitants.elements();
while(e.hasMoreElements()) {try { Monster m = (Monster) e.nextElement(); if(m.IsAt(p)) return m;
}catch (NoSuchElementException nosuch) { }}return null;
}
class Dungeon
• Reading a simple text file and creating required objects void loadItems(BufferedReader input) {for(;;) { String s = null;
try { s = input.readLine(); }catch (IOException e) { return; }s = s.trim();if(s.equals("END")) break;if(s.equals("Gold")) {Collectable c =
new Collectable(Images.kGOLD, this);c.Read(input);fProps.addElement(c);}
Typical style for input of objects from text file, identify class, create instance (we will see a smarter way later), tell object to read itself.Note passing of “this” as argument, new object wants link back to Dungeon object
• Main Run() routine controlled by timer is a little unusual; you will see related constructs (in a slightly more sophisticated form) when we get to “threads”:
void Run() {ShowAll();for(;;) {try { Thread.sleep(1000); }catch (InterruptedException e) { }fPlayer.Run();MoveInhabitants();ShowAll();if(!fPlayer.Alive()) break;if(fProps.size() == 0) break;}Finish(fPlayer.Alive());
}
Ignoring exceptions
• In some places there really isn’t anything you want to do about an exception:
try { Thread.sleep(1000); }catch (InterruptedException e) { }
try {Monster m = (Monster) e.nextElement();if(m.IsAt(p)) return m;
}catch (NoSuchElementException nosuch) { }
• still, considered rather poor form to ingore them like this!
• Polymorphism and dynamic dispatchvoid MoveInhabitants() {
Enumeration e = fInhabitants.elements();while(e.hasMoreElements()) {try {Monster m = (Monster) e.nextElement();m.Run();}catch (NoSuchElementException nosuch) { }}
}
• each monster “runs in its own way”.
class Dungeon
fInhabitants is a heterogeneous collection, m is a polymorphic reference
Actually, same Run(); but functions called from Run() vary
class Displayclass Display {
public Display(String name, Map m) { ... }
public void Redraw() {fCanvas.repaint();
}public void ShowResult(String s) { ... }
private MyCanvas fCanvas;private Frame fFrame;
}
public Display(String name, Map m) {fFrame = new Frame("Dungeon " + name);fCanvas = new MyCanvas(m);Images.LoadImages(fFrame.getToolkit());
fFrame.add(fCanvas);fFrame.pack();fFrame.show();
}public void ShowResult(String s) {
fCanvas.setVisible(false);fFrame.remove(fCanvas);Label l = new Label(s);fFrame.add(l);fFrame.pack();
}
class DungeonItemclass DungeonItem {
public DungeonItem(int imageNo, Dungeon d) {fImageNo = imageNo; fDungeon = d;}public void Vanish() { ... }public boolean IsAt(Pt p) { return fPos.equals(p); }public void Show() { ... }public void Read(BufferedReader in) { ...}public Pt Position() { return fPos; }protected Pt fPos;private int fImageNo;protected Dungeon fDungeon;
}
class DungeonItem
• Defines things that are common to all DungeonItems (“base class” of hierarchy).
• All kinds of DungeonItem– own a Pt position, an integer identifying icon, a
link by to Dungeon– initialize icon# an link in similar fashion in
constructor, report their position, draw and hide using similar code to interact with Map
class DungeonItem
• Code common to all:public DungeonItem(int imageNo, Dungeon d) {
fImageNo = imageNo; fDungeon = d;}public void Vanish() {
Map m= fDungeon.Map();m.Clear(fPos.X(), fPos.Y());
}public void Show(){
Map m= fDungeon.Map();m.Set(fPos.X(), fPos.Y(), fImageNo);
}
class DungeonItem
• Partial implementation of common behaviour.• All DungeonItem’s have an initial point
coordinate that must be read from file. Factor out this common code and put it in base class:
public void Read(BufferedReader in){fPos = new Pt();fPos.Read(in);
}
class DungeonItem
• Member functions all called from code of other classes --- so public.
• Data members:– integer for icon only used within DungeonItem
(so private)– others (link to Dungeon and Pt location) needed
in subclasses (so protected)
class DungeonItem
• Conceptually, DungeonItem is “abstract” --- but its definition makes it a concrete class – no abstract functions
• Illustrates an important difference between Java and C++ styles– this is a difference that is going to cause you lots of
bugs in both Java and C++ while you work with both but haven’t much experience!
class DungeonItem
• Remember:– Java : all variables declared of class types are
object reference variables (pointers)– C++ : a class can declare other objects contained
within it.class DungeonItem {
...protected Pt fPos;protected Dungeon fDungeon;
}
Meanings different when have these same declarations in C++ and Java
• Equivalent declarations• Javaclass DungeonItem {
...protected Pt fPos;protected Dungeon fDungeon;
}
• C++class DungeonItem {
...protected Pt *fPos;protected Dungeon *fDungeon;
}
class DungeonItem
• What do we really want here?• We really want a point data member and
link to a collaborating Dungeon object.• In C++ could specify it:class DungeonItem {
...protected Pt fPos;protected Dungeon *fDungeon;
}
class DungeonItem• Since can’t say that in Java where both must be object reference
variables (pointers), we must remember to create the Pt objectpublic void Read(BufferedReader in){
fPos = new Pt();fPos.Read(in);
}
• or declare it with new specified (probably better choice)class DungeonItem {
...protected Pt fPos = new Pt();protected Dungeon fDungeon;
}
class Collectable• A Collectable is a DungeonItem.
class Collectable extends DungeonItem {...
...}
• A Collectable simply has a few extra data members and member functions
class Collectable extends DungeonItem {public Collectable(int ImageNo, Dungeon d) {super(ImageNo, d);}public void Read(BufferedReader in) {super.Read(in);fHealth = Input.GetInt(in);fWealth = Input.GetInt(in);fManna = Input.GetInt(in);}public int Health() { return fHealth; }public int Wealth() { return fWealth; }public int Manna() { return fManna; }private int fHealth;private int fWealth;private int fManna;
}
class Collectable
• Collectable’s constructor simply passes arguments back to constructor of parent class (DungeonItem)
public Collectable(int ImageNo, Dungeon d) {
super(ImageNo, d);}
class Collectable
• The file entry for a Collectable, like that of all DungeonItems, starts with point coordinates, then has integers for value fields.
• Invoke DungeonItem.Read() as part of processing:
public void Read(BufferedReader in) {super.Read(in);fHealth = Input.GetInt(in);fWealth = Input.GetInt(in);fManna = Input.GetInt(in);
}
class ActiveItem• An ActiveItem is
– just an abstraction (while there is a Player and maybe several Monsters, there are no ActiveItems)
– a kind of DungeonItem, but one with extra data members and extra behaviours
abstract class ActiveItem extends DungeonItem {
abstract class ActiveItem extends DungeonItem {public ActiveItem(int ImageNo, Dungeon d)
{ super(ImageNo, d); }abstract void Run();
public void GetHit(int damage) { fHealth -= damage; }public boolean Alive() { return fHealth > 0; }protected void Move(int newx, int newy) { ... }public void Read(BufferedReader in){ ... }protected Pt Step(int dir){ ... }protected int fHealth;protected int fStrength;
}
class ActiveItem
• Adds behaviours common to Players and Monsters– both own health and strength data members– both can get hit, can report whether still
alive, ... (Step() function used only in Monster class in Java program, used also in additional Player code in the original more elaborate C++ program)
class ActiveItem
• Constructor is similar to that of Collectable, simply passes arguments to base class’s constructor.
• Read function is again like that of Collectable; invoke Dungeon.Read() to get Pt location, then read own data.
public void Read(BufferedReader in) {super.Read(in);fHealth = Input.GetInt(in);fStrength = Input.GetInt(in);
}
class Player• A Player is a kind of ActiveItem.• class Player is a concrete class (doesn’t
leave Run() as abstract)• A Player adds lots of new functionality -
like reading commands entered by user
class Player extends ActiveItem { public Player(Dungeon d) { super(Images.kPLAYER, d);}
public void Run() { ...}public void GetHit(int damage) {...}private void TryMove(int x, int y){...}private void PerformMovementCommand(int act){ ... }private void PerformMagicCommand(int act) {... }private void performAction(int act) { ... }private int fWealth;private int fManna;
}
class Player
• void Run() had to be defined (as abstract in ActiveItem)
• No new Read() function; Player doesn’t have any data to read other than that read by ActiveItem; so ActiveItem.Read() will suffice.
• Slight extension to ActiveItem.GetHit():public void GetHit(int damage) {
super.GetHit(damage);System.out.println("You've been hit");
}
Again note C++/Java differences
• class Player could simply override the public ActiveItem.GetHit() function.
• In Java, public and protected functions can be overridden if not specified as final; private functions can never be overridden.
• In C++, any function originally specified as virtual can be overridden.
class Monster• A Monster is a kind of ActiveItem.• class Monster is an abstract class (defines
Run() but introduces new abstract functions like CanDetect())
abstract class Monster extends ActiveItem {public Monster(int ImageNo, Dungeon d) { super(ImageNo, d); }public void Run() {
if(CanAttack()) Attack();elseif(CanDetect()) Advance();else NormalMove();
}protected boolean CanAttack() { ... }protected abstract boolean CanDetect();protected void Attack() {...}protected void Advance() { }protected void NormalMove() { }
} Note empty functions, sometimes appropriate to define a “default behaviour” as ‘do nothing’!
class Ghost• A Ghost is a kind of Monster
– it can sense Player within distance of 5 on grid– it can advance directly toward Player (going through
walls if necessary).class Ghost extends Monster {
public Ghost(Dungeon d) {super(Images.kGHOST, d);}protected void Advance() { ... }protected boolean CanDetect() {...}
}
Dungeon Example
Dungeon Example
• Read through code – focus on declaration of class hierarchy
• use of inherited functions• invoking base class constructor an member function
– check the Enumeration style iterators– look for uses of polymorphism– skim things like ‘clear line of sight
Dungeon Example
• Try adding new subclass of Monster:– Blob
• can detect line of sight, range 2• advance walk through clear areas• normal move sit, but once in a while teleport
to some random location– Klepto
• like Wanderer, but will pick up (and later drop) Collectable items that it encounters
Top Related