Narrative screens in Dave Dangerous

I have been asked how I created the Narrative screens in Dave Dangerous. So, if you're interested, please read on.

If you have been following my blog, you would know that a few months back I created my first Android game, and my first Java project.  This would not have been possible without the great tutorials over on KiloBolt.com.  I would strongly recommend you have a look.

advedangerous_narrative.png

Before the first level, I wanted to create a storyline.  This was done by creating a new class file, I called StoryScreen.  From the main menu screen, this screen would open, instead of the existing GameScreen.  

For this class to work, I also created a new method in the AndroidGraphics framework class.  This method would render text on screen and return the y coordinate of the bottom of the text block.  This is important, as when y < 0 the text has run off the sceen,  so then open the GameScreen.

Method in AndroidGraphics below.  Don't forget to also add the empty method to the Graphics interface class. 

@Override
public int drawMultiLineString(String text, int x, int y, Paint paint){
   for (String line : text.split("
")) {
      canvas.drawText(line, x, y, paint);
      y += Math.round(paint.getTextSize()); //increase y for multiple lines
   }
   return y;
} 

Full code for this new StoryScreen class is below.  It's fairly straight forward as two methods do most of the work.  

The update method decreases y. Once y is off the screen (<0) it will end, and open the GameScreen.  

The paint method renders the text to the screen at the y position.  If you have any questions, just add a comment at the bottom.

import android.graphics.Color;
import android.graphics.Paint;
import com.nellyfish.framework.Game;
import com.nellyfish.framework.Graphics;
import com.nellyfish.framework.Screen;
import com.nellyfish.framework.Input;
import java.util.List;

public class StoryScreen extends Screen {
// Enum to specify different states
enum StoryState {
World1, World2, World3, World4, World5, TheEnd, Credits
}
// Fields
private StoryState state;
private Paint paint;
private int textY, lastY;
private boolean creditSpeedup;
// Constructor
public StoryScreen(Game game, StoryState s) {
super(game);
//setup startup state
state = s;
textY = 0; // used to scroll credits
lastY = 0; // used to track last line in credits
creditSpeedup = false;
// Defining a paint object
paint = new Paint();
paint.setTextSize(35);
paint.setTextAlign(Paint.Align.CENTER);
paint.setAntiAlias(true);
paint.setColor(Color.WHITE);
}
//Update method that's run every deltaTime
@Override
public void update(float deltaTime) {
//Graphics g = game.getGraphics();
List touchEvents = game.getInput().getTouchEvents();
List keyEvents = game.getInput().getKeyEvents();
//scroll text
if(creditSpeedup)textY -= deltaTime * 5;
else textY -= deltaTime * 0.8;
//has wrapped round so move on to main game screen
if(lastY < 0) {
if(state == StoryState.TheEnd) {
Settings.currentLevel = 1;
game.setScreen(new MainMenuScreen(game));
}
else
game.setScreen(new GameScreen(game));
}
//logic to speed up text
int len = touchEvents.size();
for (int i = 0; i < len; i++) {
Input.TouchEvent event = touchEvents.get(i);
if (event.type == Input.TouchEvent.TOUCH_DOWN){
creditSpeedup = true;
}
if (event.type == Input.TouchEvent.TOUCH_UP){
creditSpeedup = false;
}
}
len = keyEvents.size();
for (int i = 0; i < len; i++) {
Input.KeyEvent event = keyEvents.get(i);
if (event.type == Input.KeyEvent.KEY_DOWN){
creditSpeedup = true;
}
if (event.type == Input.KeyEvent.KEY_UP){
creditSpeedup = false;
}
}
}
@Override
public void paint(float deltaTime) {
Graphics g = game.getGraphics();
g.clearScreen(Color.BLACK);
//display story
lastY = g.drawMultiLineString(getStory(state), 400, 550 + textY, paint);
}
public static String getStory(StoryState s) {
switch (s) {
case World1:
return
"Nobody should ever mess with Dave Dangerous, " +
"the meanest baddest cowboy in the whole " +
"wild west. " +
" " +
"One sunny day he went to see his girlfriend " +
"for a game of tiddlywinks, but she was gone! " +
" " +
"All that was left was a note. " +
" " +
""HA HA! I've got Daphne. " +
"She's ALL MINE ! So there. " +
"Love from " +
"Evil Steve " +
"X X X" " +
" " +
"Evil Steve? Not the villain from the other " +
"side of Deadman's Desert? " +
" " +
"Our hero heads off through the desert and " +
"nothing is going to stand in his way!";
case World2:
return
"another story";
case World3:
return
"another story";
case World4:
return
"another story";
case TheEnd:
return
"another story";
case Credits:
return
"Some credits";
default:
return "No story for " + s + "!";
}
}
@Override
public void pause() { }
@Override
public void resume() { }
@Override
public void dispose() { }
@Override
public void backButton() {
game.setScreen(new MainMenuScreen(game));
}
}

I am currently porting Dave Dangerous over to the libGDX framework.  The new version will benefit from hardware rendering,  and should be on iOS soon.  So stay tuned, I may also create some more levels, lets see :)

#android #coding #gaming

 

Comments

Back to blog