240 Help - BYU Computer Science Students Homepage Index

Download Report

Transcript 240 Help - BYU Computer Science Students Homepage Index

240 Help
Importer
• There is no “Activity” or Controller you have to
worry about. Just initialize the “dataImporter”
variable in the ImportActivity class with a new
DataImporter instance
Reading from a JSON file
• Create one long string, s, from contents of the JSON
input file opened as a “Reader”
• Use “JSONObject root = new JSONObject(s)” to create
a parse tree (or DOM). The new JSONObject is the root
of the tree.
• The root has one node in it. It is of type JSONObject, it
has the name “asteroidsGame”, and represents all of
the information in the asteroids game
– Use JSONObject asteroidsGame =
root.getJSONObject(“asteroidsGame”)
– To retrieve the child node in root.
Reading from a JSON file
Continued
• The “asteroidsGame” object is a map of game section
names to subtrees representing arrays of section name
instances
• The section names are :
–
–
–
–
–
–
–
–
objects
asteroids
levels
mainBodies
cannons
extraParts
engines
powerCores
Reading from a JSON file
Continued
• Get each of the sections from the asteroidsGame
node using
asteroidsGame.getJSONArray(sectionName);
– Iterate over the each element in the array which is a
subtree in the parse tree.
– Pass the subtree, which is a JSONObject to the
appropriate constructor of a DTO
– Pass the instance of the DTO to the appropriate “add”
method in the DAO to have the information added as
a tuple to the correct table in your database
Reading from a JSON file
Continued
• Most of my DTO classes were also model classes
in my AsteroidsModel
– Thus I usually had two constructors
• One created an instance from a JSONObject
• The other created an instance from its constituent parts
extracted from the database
– This occurred in my DAO
• If you designed your database as I did you will
also have two, many-to-many relations between
– The Levels and LevelAsteroids
• It also includes the position and scale of each levelAsteroid
• Derived from LevelAsteroids information in a JSON level
– The Levels and LevelObjects
• It also includes the number of levelAsteroids for each level
• Derived from the LevelObject information in a JSON level
ShipBuilder
• Check to see if the database has any
information in it. If not, don’t do anything.
– How can you tell?
Interactions
loadContent(ContentManager)
setPartViewImageList(PartSelectionView, int[])
onSlideView(ViewDirection)
animateToView(PartSelectionView, ViewDirection)
onViewLoaded(PartSelectionView)
Ship Builder
Activity
setArrow(PartSelectionView, ViewDirection, boolean, String)
onPartSelected(int)
setStartGameButton(boolean)
onStartGamePressed()
startGame()
Ship Builder
Controller
loadContent(ContentManager)
• loadContent(ContentManager contentManger)
– Populate your model
• Including the star field
– In the ShipBuilderActivity set the partViewImageList
of each spaceship part type to the list of all imageIds
for all images of that spaceship part type
onSlideView(ViewDirection)
• onSlideView(ViewDirection swipeDirection)
– If the model was initialized
• set the state of the controller to the new state determined
by the current state and swipeDirection
– The ship state defines which ship part is being displayed (see
PartSelectionView)
• For the new state (new ship part) tell the
ShipBuildingActivity to “animateToView” or draw the new
screen including the ship (even if partially completed) and
images for all instances of the new ship part (in our game
there are always only two images)
• This direction given the “animateToView” method is the
opposite of the swipeDirection
onViewLoaded(PartSelectionView)
• onViewLoaded(PartSelectionView spaceshipPart)
– If the model was initialized
• Based on the current spaceship part, set each of the 4
arrows on the screen to appropriate values by calling the
setArrow method in the ShipBuildingActivity and passing in
the current state, one of four arrow directions
(ViewDirection), whether the arrow is visible, and the text to
appear above each arrow (if any).
• Use the
setArrow(PartSelectionView, ViewDirection, boolean, String)
in the ShipBuildingActivity instance
onPartSelected(int)
• onPartSelected(int index)
– If the model was initialized
• The Activity is displaying 1 or more options for the current
spaceship part. The index indicates which of the options
was selected by the user. It is an integer between 0 and n-1
where n is the number of options displayed. In our game n
is always 2.
• attach the particular part to the spaceship
• if the spaceship is complete tell the ShipBuildingActivity to
“setStartGameButton(true)”
onStartGamePressed()
• onStartGamePressed()
– tell the activity to start the game
– this can only be called if the start button has been
enabled and that can only happen if the spaceship
is complete which can only happen if the model
had been initialized.
draw()
Called from ShipBuilderShipView
• Get the location where the ship is to drawn
– Usually where the center point of the main body is to
be drawn
• centerX - horizontal center of the screen
– Use DrawingHelper.getGameViewWidth()/2
• yOffset – vertical location, often just above the bottom
arrow
– Use DrawingHelper.getGameViewWidth()/3
– Set the alpha level of the ship to 255 (totally opaque)
– Tell the ship to draw itself at centerX, yOffset
• You might consider including a scale factor so the ship has
the appropriate size on your device
QuickPlay
Interactions
onQuickPlayPressed()
startGame()
Main
Activity
MainMenu
Controller
onQuickPlayPressed()
• Populate you model
– Including your star field object
• Create random starship
• Tell the corresponding mainActivity
“startGame()”
Game Play
Interactions
update()
draw()
Game
View
loadContent()
Game
Delegate
implements
base.
IGameDelegate
unload()
Check TODOs
• To make sure the GameView and
GameDelegate are connected appropriately
• Notice that for the Game vocabulary has
changed
– What was an “Activity” is now “View” and what
was a “Controller” is now a “Delegate”
– Also the game activity is in the “game” package”
but the “IGameDelegate” is in the “base” package.
update
• For each asteroid
– Change its position according to its velocity
– Detect whether it hit the north, south, east or
west sides of the “world”
• If so, ricochet (see GraphicsUtils.ricochetObject(…)
-- Since it does nothing if you are not at the edge
of the world, you can call it every 1/60th of a
second
update Continued
• Update ship
– Change its position
• Change the position of the MainBody, LeftWing, Cannon, and Engine
• Change its orientation by changing the orientation of all its parts
• See subsequent slides for how to rotate parts around the main body
– Detect collision with space ship with asteroids
• Use bounding boxes implemented as RectF for all moving objects
– Use RectF.intersect(float left, float top, float right, float bottom) to detect
collision
– Update bounding boxes every 1/60th of a second
• If there was a collision, subtract “lives” from ship and make the ship
immune from collision for a time
– Change the image of the ship during this time (maybe decrease alpha)
– Use some type of timer to determine how long the ship is immune
» It can be as easy as putting a counter in the spaceship
» When the space ship collides, set the counter to some value.
» Decrement the counter every 1/60th of a second
• While the counter is > 0 no more collisions can take place and the
ship remains partly invisible
» When the counter reaches 0, change the alpha back to 255 and enable
collisions
update Continued
• Update ship continued
• If laser’s fired
– game.InputManager.fingerPoint != null AND
InputManager.fingerPressed
– Laser shots are just another moving object
» Created from “attackImage”, “attackImageWidth”, and
“attackImageHeight” defined in the each Cannon section of
the JSON
» Create laser shot instances and fire them in same direction
as ship
» Also make the laser shot sound
• content.playSound(soundId)
» Be sure to space them out
» Ignore firePressed until all laser shots fired
» Kill them at appropriate time (collision with asteroid, or, they
reach the end of the viewport, or they reach the end of the
world)
update Continued
• Update ship continued
• If we should rotate the ship
– game.InputManager.fingerPoint != null and not
InputManager.fingerPressed
– Compute angle from center of spaceship to fingerPoint
» Get dx and dy from center point to fingerPoint
» The angle in radians is Math.atan(dx/dy)
– Store the new angle in the space ship, it will be used the next
time the draw() method on the space ship is called
update Continued
• Update laser bolt
– Change its position according to velocity
– Detect collision with asteroid
• Use RectF as bounding boxes again, use “intersect”
• If there is a collision with an asteroid, remove laser bolt and
split asteroid appropriately (into 2 or 8 pieces)
– If the asteroid had been previously split
» remove it
– else
» Make the new asteroids (fragments) smaller by adjusting
scale appropriately (1/2 or 1/8)
• How: adjust scale of current asteroid
• Make n-1 copies using copy constructor
• Send each in a random direction (set dx and dy)
• Use Random random = new Random()
• Add each new fragment to set of asteroids for the
current level
draw()
• Use drawing.DrawingHelper.drawImage(imageId,
xPosition, yPosition, rotationDegrees, scaleX,
scaleY, alpha)
• Draw
– Draw the background image (star field)
• Scale or tile to fill background of viewport
– Draw all asteroids
– Draw all laser shots
– Draw the ship
• Draw the MainBody, LeftWing, Cannon, and Engine
– Rotate the ship as needed
Drawing attached parts
• DrawingHelper.drawImage(imageId, x, y,
rotationDegrees, scaleX, scaleY, alpha)
– Origin is top-left of view (y-axis is inverted)
– Center of image is drawn at (x, y)
• x and y are device or viewport coordinates
– Zero degrees is “up”
– Alpha: from 0 (invisible) to 255 (totally opaque)
Drawing attached parts
(0, 0)
partAttach
bodyCenter
(0, 0)
partCenter
bodyPartAttach
We want the bodyPartAttach point and the partAttach to be at the same point
Each attached part has an offset from
the main body’s center
partOffset
partOffset = (bodyAttach – bodyCenter) + (partCenter – partAttach)
The are methods for addition and subtraction of points in GraphicsUtils
partOffset is not a point but a dx, dy pair
When drawing the ship, a part’s location is
calculated relative to ship’s location using the
part offset
(0, 0)
bodyLocation
partOffset
partLocation = bodyLocation + partOffset
partLocation
Drawing a rotated ship
(0, 0)
The orientation of the bodyLocation
and the partLocation are changed by
passing the ship rotation angle to the
drawing helper when these images
are drawn
rotatedPartOffset = GraphicsUtils.rotate(partOffset, angleRadians)
The rotatedPartOffset is the new dx, dy offset from the bodyLocation
partLocation = bodyLocation + rotatedPartOffset
Rotating the Ship
• If you scale the ship and its subparts to make
it look right on the screen, you will have to
scale the rotatedShipOffset(the dx and dy) to
the same amount.
Helps
• Android.graphics.
– PointF
– Rect
• core.GraphicsUtils
–
–
–
–
–
–
–
–
void radiansToDegrees(double angleInRadians)
PointF add(PointF p1, PointF p2)
PointF subtract(PointF p1, PointF p2)
double distance(PointF p1, PointF p2)
PointF scale(PointF p1, PointF p2)
PointF translate(PointF p, float dx, float dy)
PointF rotate(p, double angleInRadians)
MoveObjectResult move(PointF objPosition, RectF objBounds, double
speed, double angleRadians, double elapsedTime)
• Moves the objectPosition by deltaX and deltaY
• Moves the objectBounds left, top, right, and bottom by deltaX and deltaY
– RicochetObjectResult ricochetObject(PointF objPosition, RectF
objBounds, double angleRadians, float worldWidth, float worldHeight)