如何在android studio项目中为类似于flappy bird的简单2D游戏保存高分?
Posted
技术标签:
【中文标题】如何在android studio项目中为类似于flappy bird的简单2D游戏保存高分?【英文标题】:How to do I save a highscore for simple 2D game similar to flappy bird in android studio project? 【发布时间】:2015-06-21 17:32:57 【问题描述】:我是编程新手,所以我不确定我的代码哪里出错了。我尝试为人们的高分添加保存功能,并尝试在寻求帮助之前自己搜索答案。我知道需要共享首选项并且我已经添加了代码并且没有错误但是它实际上并没有保存高分所以我添加的代码现在非常多余。请有人能指出我正确的方向吗?我在下面添加了我的代码。
编辑-我检查了我的代码并在共享首选项下我输入了 int score(这是我一开始要编码为基本分数但后来我将其更改为 player.getScore。无论如何,当我尝试将 score 修改为 player.getScore 它无法解析 player.getScore,我该如何修复它,一旦完成,我的游戏会保存高分吗?
感谢您的帮助。
package com.curtis.myfirstgame;
import android.content.Context;
import android.content.SharedPreferences;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.preference.PreferenceManager;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import java.util.ArrayList;
import java.util.Random;
public class GamePanel extends SurfaceView implements SurfaceHolder.Callback
public static final int WIDTH = 856;
public static final int HEIGHT = 480;
public static final int MOVESPEED = -5;
private long smokeStartTime;
private long missileStartTime;
private MainThread thread;
private Background bg;
private Player player;
private ArrayList<Smokepuff> smoke;
private ArrayList<Missile> missiles;
private ArrayList<TopBorder> topborder;
private ArrayList<BotBorder> botborder;
private Random rand = new Random();
private int maxBorderHeight;
private int minBorderHeight;
private boolean topDown = true;
private boolean botDown = true;
private boolean newGameCreated;
public static int Score = 0;
public static int HighScore = 0;
public static SharedPreferences prefs;
private String saveScore = "HighScore";
//increase to slow down difficulty progression, decrease to speed up difficulty progression
private int progressDenom = 20;
private Explosion explosion;
private long startReset;
private boolean reset;
private boolean dissapear;
private boolean started;
public GamePanel(Context context)
super(context);
SharedPreferences prefs = context.getSharedPreferences("com.curtis.myfirstgame", Context.MODE_PRIVATE);
int player.getScore = prefs.getInt("highScore", 0);
//above is where my problem is
String spackage = "com.curtis.myfirstgame";
HighScore = prefs.getInt(saveScore, 0);
//add the callback to the surfaceholder to intercept events
getHolder().addCallback(this);
//make gamePanel focusable so it can handle events
setFocusable(true);
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
@Override
public void surfaceDestroyed(SurfaceHolder holder)
boolean retry = true;
int counter = 0;
while (retry && counter < 1000)
counter++;
try
thread.setRunning(false);
thread.join();
retry = false;
thread = null;
catch (InterruptedException e)
e.printStackTrace();
prefs.edit().putInt(saveScore, HighScore).commit();
@Override
public void surfaceCreated(SurfaceHolder holder)
bg = new Background(BitmapFactory.decodeResource(getResources(), R.drawable.grassbg1));
player = new Player(BitmapFactory.decodeResource(getResources(), R.drawable.helicopter), 65, 25, 3);
smoke = new ArrayList<Smokepuff>();
missiles = new ArrayList<Missile>();
topborder = new ArrayList<TopBorder>();
botborder = new ArrayList<BotBorder>();
smokeStartTime = System.nanoTime();
missileStartTime = System.nanoTime();
thread = new MainThread(getHolder(), this);
//we can safely start the game loop
thread.setRunning(true);
thread.start();
@Override
public boolean onTouchEvent(MotionEvent event)
if (event.getAction() == MotionEvent.ACTION_DOWN)
if (!player.getPlaying() && newGameCreated && reset)
player.setPlaying(true);
player.setUp(true);
if (player.getPlaying())
if (!started) started = true;
reset = false;
player.setUp(true);
return true;
if (event.getAction() == MotionEvent.ACTION_UP)
player.setUp(false);
return true;
return super.onTouchEvent(event);
public void update()
if (player.getPlaying())
if (botborder.isEmpty())
player.setPlaying(false);
return;
if (topborder.isEmpty())
player.setPlaying(false);
return;
bg.update();
player.update();
//calculate the threshold of height the border can have based on the score
//max and min border heart are updated, and the border switched direction when either max or
//min is met
maxBorderHeight = 30 + player.getScore() / progressDenom;
//cap max border height so that borders can only take up a total of 1/2 the screen
if (maxBorderHeight > HEIGHT / 4) maxBorderHeight = HEIGHT / 4;
minBorderHeight = 5 + player.getScore() / progressDenom;
//check bottom border collision
for (int i = 0; i < botborder.size(); i++)
if (collision(botborder.get(i), player))
player.setPlaying(false);
//check top border collision
for (int i = 0; i < topborder.size(); i++)
if (collision(topborder.get(i), player))
player.setPlaying(false);
//update top border
this.updateTopBorder();
//udpate bottom border
this.updateBottomBorder();
//add missiles on timer
long missileElapsed = (System.nanoTime() - missileStartTime) / 1000000;
if (missileElapsed > (2000 - player.getScore() / 4))
//first missile always goes down the middle
if (missiles.size() == 0)
missiles.add(new Missile(BitmapFactory.decodeResource(getResources(), R.drawable.
missile), WIDTH + 10, HEIGHT / 2, 45, 15, player.getScore(), 13));
else
missiles.add(new Missile(BitmapFactory.decodeResource(getResources(), R.drawable.missile),
WIDTH + 10, (int) (rand.nextDouble() * (HEIGHT - (maxBorderHeight * 2)) + maxBorderHeight), 45, 15, player.getScore(), 13));
//reset timer
missileStartTime = System.nanoTime();
//loop through every missile and check collision and remove
for (int i = 0; i < missiles.size(); i++)
//update missile
missiles.get(i).update();
if (collision(missiles.get(i), player))
missiles.remove(i);
player.setPlaying(false);
break;
//remove missile if it is way off the screen
if (missiles.get(i).getX() < -100)
missiles.remove(i);
break;
//add smoke puffs on timer
long elapsed = (System.nanoTime() - smokeStartTime) / 1000000;
if (elapsed > 120)
smoke.add(new Smokepuff(player.getX(), player.getY() + 10));
smokeStartTime = System.nanoTime();
for (int i = 0; i < smoke.size(); i++)
smoke.get(i).update();
if (smoke.get(i).getX() < -10)
smoke.remove(i);
else
player.resetDY();
if (!reset)
newGameCreated = false;
startReset = System.nanoTime();
reset = true;
dissapear = true;
explosion = new Explosion(BitmapFactory.decodeResource(getResources(), R.drawable.explosion), player.getX(),
player.getY() - 30, 100, 100, 25);
explosion.update();
long resetElapsed = (System.nanoTime() - startReset) / 1000000;
if (resetElapsed > 2500 && !newGameCreated)
newGame();
public boolean collision(GameObject a, GameObject b)
if (Rect.intersects(a.getRectangle(), b.getRectangle()))
return true;
return false;
@Override
public void draw(Canvas canvas)
final float scaleFactorX = getWidth() / (WIDTH * 1.f);
final float scaleFactorY = getHeight() / (HEIGHT * 1.f);
if (canvas != null)
final int savedState = canvas.save();
canvas.scale(scaleFactorX, scaleFactorY);
bg.draw(canvas);
if (!dissapear)
player.draw(canvas);
//draw smokepuffs
for (Smokepuff sp : smoke)
sp.draw(canvas);
//draw missiles
for (Missile m : missiles)
m.draw(canvas);
//draw topborder
for (TopBorder tb : topborder)
tb.draw(canvas);
//draw botborder
for (BotBorder bb : botborder)
bb.draw(canvas);
//draw explosion
if (started)
explosion.draw(canvas);
drawText(canvas);
canvas.restoreToCount(savedState);
public void updateTopBorder()
//every 50 points, insert randomly placed top blocks that break the pattern
if (player.getScore() % 50 == 0)
topborder.add(new TopBorder(BitmapFactory.decodeResource(getResources(), R.drawable.brick
), topborder.get(topborder.size() - 1).getX() + 20, 0, (int) ((rand.nextDouble() * (maxBorderHeight
)) + 1)));
for (int i = 0; i < topborder.size(); i++)
topborder.get(i).update();
if (topborder.get(i).getX() < -20)
topborder.remove(i);
//remove element of arraylist, replace it by adding a new one
//calculate topdown which determines the direction the border is moving (up or down)
if (topborder.get(topborder.size() - 1).getHeight() >= maxBorderHeight)
topDown = false;
if (topborder.get(topborder.size() - 1).getHeight() <= minBorderHeight)
topDown = true;
//new border added will have larger height
if (topDown)
topborder.add(new TopBorder(BitmapFactory.decodeResource(getResources(),
R.drawable.brick), topborder.get(topborder.size() - 1).getX() + 20,
0, topborder.get(topborder.size() - 1).getHeight() + 1));
//new border added wil have smaller height
else
topborder.add(new TopBorder(BitmapFactory.decodeResource(getResources(),
R.drawable.brick), topborder.get(topborder.size() - 1).getX() + 20,
0, topborder.get(topborder.size() - 1).getHeight() - 1));
public void updateBottomBorder()
//every 40 points, insert randomly placed bottom blocks that break pattern
if (player.getScore() % 40 == 0)
botborder.add(new BotBorder(BitmapFactory.decodeResource(getResources(), R.drawable.brick),
botborder.get(botborder.size() - 1).getX() + 20, (int) ((rand.nextDouble()
* maxBorderHeight) + (HEIGHT - maxBorderHeight))));
//update bottom border
for (int i = 0; i < botborder.size(); i++)
botborder.get(i).update();
//if border is moving off screen, remove it and add a corresponding new one
if (botborder.get(i).getX() < -20)
botborder.remove(i);
//determine if border will be moving up or down
if (botborder.get(botborder.size() - 1).getY() <= HEIGHT - maxBorderHeight)
botDown = true;
if (botborder.get(botborder.size() - 1).getY() >= HEIGHT - minBorderHeight)
botDown = false;
if (botDown)
botborder.add(new BotBorder(BitmapFactory.decodeResource(getResources(), R.drawable.brick
), botborder.get(botborder.size() - 1).getX() + 20, botborder.get(botborder.size() - 1
).getY() + 1));
else
botborder.add(new BotBorder(BitmapFactory.decodeResource(getResources(), R.drawable.brick
), botborder.get(botborder.size() - 1).getX() + 20, botborder.get(botborder.size() - 1
).getY() - 1));
public void newGame()
dissapear = false;
botborder.clear();
topborder.clear();
missiles.clear();
smoke.clear();
minBorderHeight = 5;
maxBorderHeight = 30;
player.resetDY();
player.resetScore();
player.setY(HEIGHT / 2);
//update score only if new score is higher
if (player.getScore() > HighScore)
HighScore = player.getScore();
SharedPreferences.Editor edit = prefs.edit();
edit.putInt("highScore", HighScore);
edit.commit();
//create initial borders
//initial top border
for (int i = 0; i * 20 < WIDTH + 40; i++)
//first top border create
if (i == 0)
topborder.add(new TopBorder(BitmapFactory.decodeResource(getResources(), R.drawable.brick
), i * 20, 0, 10));
else
topborder.add(new TopBorder(BitmapFactory.decodeResource(getResources(), R.drawable.brick
), i * 20, 0, topborder.get(i - 1).getHeight() + 1));
//initial bottom border
for (int i = 0; i * 20 < WIDTH + 40; i++)
//first border ever created
if (i == 0)
botborder.add(new BotBorder(BitmapFactory.decodeResource(getResources(), R.drawable.brick)
, i * 20, HEIGHT - minBorderHeight));
//adding borders until the initial screen is filed
else
botborder.add(new BotBorder(BitmapFactory.decodeResource(getResources(), R.drawable.brick),
i * 20, botborder.get(i - 1).getY() - 1));
newGameCreated = true;
public void drawText(Canvas canvas)
Paint paint = new Paint();
paint.setColor(Color.BLACK);
paint.setTextSize(30);
paint.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD));
canvas.drawText("SCORE: " + (player.getScore() * 3), 10, HEIGHT - 10, paint);
canvas.drawText("HIGHSCORE: " + HighScore, WIDTH - 215, HEIGHT - 10, paint);
if (!player.getPlaying() && newGameCreated && reset)
Paint paint1 = new Paint();
paint1.setTextSize(40);
paint1.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD));
canvas.drawText("PRESS TO START", WIDTH / 2 - 50, HEIGHT / 2, paint1);
paint1.setTextSize(20);
canvas.drawText("PRESS AND HOLD TO GO UP", WIDTH / 2 - 50, HEIGHT / 2 + 20, paint1);
canvas.drawText("RELEASE TO GO DOWN", WIDTH / 2 - 50, HEIGHT / 2 + 40, paint1);
【问题讨论】:
从prefs中获取高分,如果小于当前分数,则将当前分数保存为高分。Database
或sharedPreference
【参考方案1】:
Do following
SharedPreferences prefs = this.getSharedPreferences("myPrefsKey", Context.MODE_PRIVATE);
int oldScore = prefs.getInt("highScore", 0);
//update score only if new score is higher
if(newScore > oldScore )
Editor edit = prefs.edit();
edit.putInt("highScore", newScore);
edit.commit();
【讨论】:
【参考方案2】:使用此代码:
SharedPreferences preference = PreferenceManager.getDefaultSharedPreferences(context);
SharedPreferences.Editor editor = preference.edit();
Integer score = preference.getInt("score",null); //read from pref
if(classFound == null)
editor.putInt("score",100); //write to pref
editor.commit();
使用 Integer 因为 int 不是 nullabe。
您可以通过将 100 替换为变量来保存任何 int 值
如果有帮助请点赞:)
【讨论】:
以上是关于如何在android studio项目中为类似于flappy bird的简单2D游戏保存高分?的主要内容,如果未能解决你的问题,请参考以下文章
如何在一个 android studio 项目中为两种不同类型的用户提供两种不同的导航抽屉活动?
如何在 Visual Studio Code 中为 React Native 设置调试?
在 Android Studio 中为 Dart 启用彩虹括号