When Flappy bird gone viral on Play Store, there‘s many people jump in
to game development industry, like gold rush. We will make it in simple way by
canvas.
Prepare a small icon size 30x30, it look like a bird, you can make it by
using Word, insert Shape.
Icon green bar width 30, height 125dp.
Create folder drawable below res, copy icons in to it. Create a folder
name raw, put a mp3 sound file length one minute, the sound when bird hit the
bar.
In file Androidmanifest.xml of class Main, add two lines.
android:screenOrientation="landscape"
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
We set game to lanscape and full screen.
When you set screen lanscape, x index will be the horizon length, y will
be vertical height.
The origin co-ordinate 0,0 at top left screen corner.
Create a class name gameview below class Main.
Copy these lines to above last bracket.
public
class gameview extends
View {
public
gameview(Context context) {
super(context);
}
@SuppressLint({ "NewApi", "DrawAllocation" })
@Override
protected void onDraw(final Canvas canvas) {
// TODO
Auto-generated method stub
super.onDraw(canvas);
invalidate();
}
}
Copy to below class Main open bracket.
String record = "";
private
gameview game;
Comment the line setContentView, copy to below that comment.
game = new gameview(this);
game.setBackgroundColor(Color.WHITE);
setContentView(game);
Run to see blank screen white.
Copy to below public
class gameview extends
View {
private Paint paint;
private Bitmap bird, bar, bar2;
int y;
int xbar, xbar2, ybar,xcount;
int count;
Boolean hit = false;
Boolean finger = false;
Boolean run = true;
int soky = 0;
private SoundPool soundPool;
int soundId;
int bump = -1;
int r,
c;
Import libraries.
Copy to below super(context);
paint = new Paint();
paint.setColor(Color.parseColor("#FF00FF"));
paint.setTextAlign(Align.CENTER);
paint.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD));
DisplayMetrics metrics =
getResources().getDisplayMetrics();
r = metrics.widthPixels;
c = metrics.heightPixels;
bird =
BitmapFactory.decodeResource(getResources(), R.drawable.ki);
bar =
BitmapFactory.decodeResource(getResources(), R.drawable.kb);
bar2 =
BitmapFactory.decodeResource(getResources(), R.drawable.kb);
xbar = r ;
xbar2 = r;
xcount=xthanh-200+thanh.getWidth()+chim.getWidth();;
y = c / 2;
soundPool = new SoundPool(10,
AudioManager.STREAM_MUSIC, 0);
bump = soundPool.load(context,
R.raw.bump, 1);
Import libraries, make sure icons, mp3 file name the same as you name
them.
To make it simple, we first make only two bars.
Copy these lines to above last bracket.
public void read() {
try {
String
FILE_NAME = "record.txt";
FileInputStream
fIS =
openFileInput(FILE_NAME);
byte[] arrayData = new byte[fIS.available()];
if ((fIS.read(arrayData)) != -1) {
String
fileContent = new String(arrayData);
record = fileContent;
}
fIS.close();
}
catch (Exception e) {
//
Log.e("Error", e.toString());
}
}
public void write(String d) {
try {
FileOutputStream
fos =
openFileOutput("record.txt",
Context.MODE_APPEND);
OutputStreamWriter
osw = new
OutputStreamWriter(fos);
osw.append(d);
osw.flush();
osw.close();
}
catch
(FileNotFoundException e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
}
This is methods to write and read the score, number times the bird fly
through the bars.
Copy to below super.onDraw(canvas);
Paint paint2 = new Paint();
paint2.setColor(Color.BLACK);
paint2.setTextAlign(Align.CENTER);
paint2.setTextSize(25);
paint2.setTextAlign(Align.CENTER);
canvas.drawBitmap(bar, xbar, 0, null);
canvas.drawBitmap(bar2, xbar2, 340, null);
Rect touch=new Rect(200, y,200 + bird.getWidth(),y+bird.getHeight());
Rect touch1 = new Rect(xbar, 0, xbar + bar.getWidth(), bar.getHeight());
Rect touch2
= new Rect(xbar2,
340, xbar2 + bar.getWidth(),
340+bar.getHeight());
if (run == true) {
read();
if (record.length() >
0) {
soky = Integer.parseInt(record);
}
xbar = xcount - 7;
xbar2 = xbar2 - 7;
xcount = xcount-7;
canvas.drawText("Record:
" + soky + " - " + "Score: " + count,
r / 2, 20,
paint2);
if (finger == true) {
y=y-5;
float rotation =
-10.0f;
Matrix
matrix = new Matrix();
float px = 200;
float py = y;
matrix.postRotate(rotation);
matrix.postTranslate(px,
py);
canvas.drawBitmap(bird, matrix, null);
}
else {
y=y+5;
float rotation =
10.0f;
Matrix
matrix = new Matrix();
float px = 200;
float py = y;
matrix.postRotate(rotation);
matrix.postTranslate(px,
py);
canvas.drawBitmap(bird, matrix, null);
}
if (Rect.intersects(touch,
touch1)) {
hit=true;
soundPool.play(bump, 0.9f, 0.1f, 1,
0, 0.7f);
}
if (Rect.intersects(touch,
touch2)) {
hit=true;
soundPool.play(bump, 0.9f, 0.1f, 1,
0, 0.7f);
}
}
Run to see the bird and two bars, but bird fall down because we can’t
control now.
Let take time to look at code.
We declare paint2 to draw String Record and Score on top screen.
The line canvas.drawBitmap(bar,
xbar, 0, null);draw
the first bar, on super(context); we set
xbar = r
; to draw it at top right edge screen.
canvas.drawBitmap(bar2,
xbar2, 340, null);
We draw second bar with y = 340 to make a gap so the bird can fly
through.
Rect touch draw rectangulars to surround the bird, the bars.
In command if, run == true mean game is running, not Over.
xthanh = xthanh - 7;
xthanh2 = xthanh2
- 7;
This make the bars move to the left screen.
if
(finger == true)
{ mean the user touch their finger on screen.
y=y-5;make
the bird fly up when touch.
In command else we set
y=y+5;
mean when finger off screen, the bird fall down.
To make the bird lift up his’s head when fly up, we use.
float rotation =
-10.0f;
Matrix matrix = new Matrix();
float px = 200;
float py = y;
matrix.postRotate(rotation);
matrix.postTranslate(px, py);
canvas.drawBitmap(chim,
matrix, null);
To make the bird lower his head when fall down, in else we change float
rotation = -10.0f; to float
rotation = 10.0f;
if (Rect.intersects(touch,
touch1)) {
In this command, we set what happen when bird hit bars. We
set hit=true;
To make sure our rectangulars draw at true position, add
these lines to below rect touch.
canvas.drawRect(200, y,200 + bird.getWidth(),y+bird.getHeight(),paint);
canvas.drawRect(xbar, 0,xbar + bar.getWidth(),bar.getHeight(),
paint);
canvas.drawRect(xbar2, 340, xbar2 + bar.getWidth(),
340+bar.getHeight(),paint);
Run to see the bars, the bird were surround by pink rectangulars.
Now make them become comments, we just need them to check
positions.
Copy to below invalidate() one close bracket }
@SuppressLint("ClickableViewAccessibility")
@Override
public boolean
onTouchEvent(MotionEvent event) {
switch (event.getAction()
& MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_UP:
finger = false;
break;
case MotionEvent.ACTION_DOWN:
finger=true;
if (run == false) {
run = true;
hit=false;
y=c/2;
count = 0;
xbar = r - bar.getWidth();
xbar2 = r - bar.getWidth();
xcount=xcount-200+bar.getWidth()+bird.getWidth();
}
break;
}
return true;
}
These line allow us control the bird by touch screen phone.
When user touch screen, that is case
MotionEvent.ACTION_DOWN:
We set finger=true;,on the code above,
we set if finger=true;make the bird fly
up.
if
(run == false)
{ that mean Game Over we make everything to be initial position.
When user lift their finger off screen, that is case
MotionEvent.ACTION_UP:
we set finger = false;
In code above, command else make the bird fall down.
Run to see we can control the
bird, but the bar run over just one time.
To make the bars return, add these
lines above invalidate()
if (xbar < -bar.getWidth()) {
xbar = r;
xbar2 = r;
xcount=xbar-200+bar.getWidth()+bird.getWidth();;
}
if (y >c) {
run=false;
}
if (y <0) {
y=0;
}
if(xcount<0){
xcount=r;
count=count+1;
}
if (hit == true) {
finger = false;
run=false;
y = y + 10;
float rotation =
30.0f;
Matrix matrix = new Matrix();
float px = 200;
float py = y;
matrix.postRotate(rotation);
matrix.postTranslate(px, py);
canvas.drawBitmap(bird, matrix, null);
}
if (run == false) {
if (count > soky) {
deleteFile("record.txt");
write(String.valueOf(count));
paint.setTextAlign(Align.CENTER);
paint.setTextSize(30);
canvas.drawText("New
record: " + count + " ", r / 2, 30,
paint);
}
paint.setTextSize(60);
canvas.drawText("Game
Over", r / 2, 100, paint);
canvas.drawText("Tap to
replay!", r / 2, c / 2 + 70, paint);
paint.setTextSize(35);
canvas.drawText("Score:
" + dem, r / 2, 160, paint);
}
First if mean when the bar go in to left
edge, we move it to right edge.
if (y >c) { mean when bird fall down over bottom edge, game over.
if (y <0) { to keep the bird can’t move over top edge screen.
if (hit == true) { we set every values to false, make game over, increase
falling bird by line y = y + 10;
We
also make the bird lower his head when falling down.
if (run == false) { when game over, we
check the times bird fly through the bars, if it’s bigger than last time, we
call method write() to write it and show inform new record.
To know last record, when game open, in command if (run == true){ we call
method read(); and change value received to interger.
if (record.length() > 0) {
soky = Integer.parseInt(record);
}
The first time run game, soky =0.
The line paint.setTextSize(60); to set big font to draw String Game Over, Tap to replay and
number score.
One last problem is how to count the time the bird fly through
bars.
We use two variables xcount and count.
When initial, xcount=xbar-200+bar.getWidth()+bird.getWidth(); this make the xcount go to left edge when
the bar pass over the bird. To make sure the bird has fly over bars, we plus
the widths of both bar and bird.
After that we use
if(xcount<0){
xcount=r;
count=count+1;
}
To
make xcount run parallel with x index of bars,
we set xcount = xcount-7;
When bars return, we also set xcount to initial value.
xcount=xbar-200+bar.getWidth()+bird.getWidth();
When
Game over, we set xcount with same value, and set count=0 to count again.
Below is the entire code game flappy bird.
public class MainActivity extends Activity {
String
record = "";
private gameview game;
@Override
protected void onCreate(Bundle
savedInstanceState) {
super.onCreate(savedInstanceState);
//
setContentView(R.layout.activity_main);
game = new gameview(this);
game.setBackgroundColor(Color.WHITE);
setContentView(game);
}
public class gameview extends View {
private Paint paint;
private Bitmap bird, bar, bar2;
int y;
int xbar, xbar2, xcount;
int count;
Boolean
hit = false;
Boolean
finger = false;
Boolean
run = true;
int soky = 0;
private SoundPool soundPool;
int soundId;
int bump = -1;
int r, c;
public
gameview(Context context) {
super(context);
paint = new Paint();
paint.setColor(Color.parseColor("#FF00FF"));
paint.setTextAlign(Align.CENTER);
paint.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD));
DisplayMetrics
metrics = getResources().getDisplayMetrics();
r = metrics.widthPixels;
c = metrics.heightPixels;
bird =
BitmapFactory.decodeResource(getResources(), R.drawable.ki);
bar =
BitmapFactory.decodeResource(getResources(), R.drawable.kb);
bar2 =
BitmapFactory.decodeResource(getResources(), R.drawable.kb);
xbar = r;
xbar2 = r;
xcount = xbar - 200 + bar.getWidth() + bird.getWidth();
y = c / 2;
soundPool = new SoundPool(10,
AudioManager.STREAM_MUSIC, 0);
bump = soundPool.load(context,
R.raw.bump, 1);
}
@SuppressLint({ "NewApi", "DrawAllocation" })
@Override
protected void onDraw(final Canvas canvas)
{
// TODO
Auto-generated method stub
super.onDraw(canvas);
Paint
paint2 = new Paint();
paint2.setColor(Color.BLACK);
paint2.setTextAlign(Align.CENTER);
paint2.setTextSize(25);
paint2.setTextAlign(Align.CENTER);
canvas.drawBitmap(bar, xbar, 0, null);
canvas.drawBitmap(bar2, xbar2, 340, null);
Rect
touch = new Rect(200, y, 200 + bird.getWidth(), y
+
bird.getHeight());
Rect
touch1 = new Rect(xbar, 0, xbar + bar.getWidth(),
bar.getHeight());
Rect
touch2 = new Rect(xbar2, 340, xbar2 + bar.getWidth(),
340
+ bar.getHeight());
//
canvas.drawRect(200, y,200 +
//
bird.getWidth(),y+bird.getHeight(),paint);
// canvas.drawRect(xbar,
0,xbar +
// bar.getWidth(),bar.getHeight(),
// paint);
//
canvas.drawRect(xbar2, 340, xbar2 + bar.getWidth(),
// 340+bar.getHeight(),
// paint);
if (run == true) {
read();
if (record.length() >
0) {
soky = Integer.parseInt(record);
}
xbar = xbar - 7;
xbar2 = xbar2 - 7;
xcount = xcount - 7;
canvas.drawText("Record:
" + soky + " - " + "Score: " + count,
r / 2, 20,
paint2);
if (finger == true) {
y = y - 5;
float rotation =
-10.0f;
Matrix
matrix = new Matrix();
float px = 200;
float py = y;
matrix.postRotate(rotation);
matrix.postTranslate(px,
py);
canvas.drawBitmap(bird, matrix, null);
}
else {
y = y + 5;
float rotation =
10.0f;
Matrix
matrix = new Matrix();
float px = 200;
float py = y;
matrix.postRotate(rotation);
matrix.postTranslate(px,
py);
canvas.drawBitmap(bird, matrix, null);
}
if (Rect.intersects(touch,
touch1)) {
hit = true;
soundPool.play(bump, 0.9f, 0.1f, 1,
0, 0.7f);
}
if (Rect.intersects(touch,
touch2)) {
hit = true;
soundPool.play(bump, 0.9f, 0.1f, 1,
0, 0.7f);
}
}
if (xbar < -bar.getWidth()) {
xbar = r;
xbar2 = r;
xcount = xbar - 200 + bar.getWidth() + bird.getWidth();
}
if (y > c) {
run = false;
}
if (y < 0) {
y = 0;
}
if (xcount < 0) {
xcount = r;
count = count + 1;
}
if (hit == true) {
finger = false;
run = false;
y = y + 10;
float rotation =
30.0f;
Matrix
matrix = new Matrix();
float px = 200;
float py = y;
matrix.postRotate(rotation);
matrix.postTranslate(px,
py);
canvas.drawBitmap(run, matrix, null);
}
if (run == false) {
if (count > soky) {
deleteFile("record.txt");
write(String.valueOf(count));
paint.setTextAlign(Align.CENTER);
paint.setTextSize(30);
canvas.drawText("New
record: " + count + " ", r / 2, 30,
paint);
}
paint.setTextSize(60);
canvas.drawText("Game
Over", r / 2, 100, paint);
canvas.drawText("Tap to
replay!", r / 2, c / 2 + 70, paint);
paint.setTextSize(35);
canvas.drawText("Score:
" + count, r / 2, 160, paint);
}
invalidate();
}
@SuppressLint("ClickableViewAccessibility")
@Override
public boolean
onTouchEvent(MotionEvent event) {
switch
(event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_UP:
finger = false;
break;
case MotionEvent.ACTION_DOWN:
finger = true;
if (run == false) {
run = true;
hit = false;
y = c / 2;
count = 0;
xbar = r - bar.getWidth();
xbar2 = r - bar.getWidth();
xcount = xbar - 200 + bar.getWidth() + bird.getWidth();
}
break;
}
return true;
}
}
public void read() {
try {
String
FILE_NAME = "record.txt";
FileInputStream
fIS = openFileInput(FILE_NAME);
byte[] arrayData = new byte[fIS.available()];
if
((fIS.read(arrayData)) != -1) {
String
fileContent = new String(arrayData);
record = fileContent;
}
fIS.close();
}
catch (Exception e) {
//
Log.e("Error", e.toString());
}
}
public void write(String d)
{
try {
FileOutputStream
fos = openFileOutput("record.txt",
Context.MODE_APPEND);
OutputStreamWriter
osw = new OutputStreamWriter(fos);
osw.append(d);
osw.flush();
osw.close();
}
catch
(FileNotFoundException e) {
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
No comments:
Post a Comment