NPM : 54412439
Kelas : 3IA24
BREAKOUT GAME
1. TAHAP KEBUTUHAN
1.1.Eclipse
Eclipse adalah sebuah IDE (Integrated Development Environment) untuk
mengembangkan perangkat lunak dan dapat dijalankan di semua platform
(platform-independent).
(Sumber : http://id.wikipedia.org/wiki/Eclipse_(perangkat_lunak) )
1.2.JRE dan JDK, dan pengertiannya disini
Seperti namanya, JDK adalah semacam kotak peralatan (kit) yang digunakan
untuk development. JDK ini berguna saat Anda menulis code program. Seperti
halnya JRE, JDK juga memiliki JVM di dalamnya.
JRE adalah sesuatu yang memungkinkan sebuah program Java dapat berjalan di
mesin Anda. JRE ini mengeksekusi binary-binary dari class-class dan mengirimnya
ke JVM untuk diproses lagi ke prosesor. Setiap JRE pasti memiliki sebuah JVM di
dalamnya untuk melakukan pemrosesan selanjutnya.
(Sumber : https://webanggasurya.wordpress.com/2012/10/16/perbedan-jdk-dan-jre-pada-java/
)
1.3.Android SDK
Android-SDK merupakan tools bagi para programmer yang ingin mengembangkan
aplikasi berbasis google android. Android SDK mencakup seperangkat alat
pengembangan yang komprehensif. Android SDK terdiri dari debugger, libraries,
handset emulator,dokumentasi, contoh kode, dan tutorial.
(Sumber : https://haidibarasa.wordpress.com/2013/07/06/pengertian-android-sdk-software-development-kit/
)
1.4.Smart Phone berbasis Android
Android adalah sistem operasi berbasis Linux yang dirancang untuk perangkat
seluler layar sentuh seperti telepon pintar dan komputer tablet. Android
awalnya dikembangkan oleh Android, Inc., dengan dukungan finansial dari Google,
yang kemudian membelinya pada tahun 2005. Sistem operasi ini dirilis secara
resmi pada tahun 2007, bersamaan dengan didirikannya Open Handset Alliance,
konsorsium dari perusahaan-perusahaan perangkat keras, perangkat lunak, dan
telekomunikasi yang bertujuan untuk memajukan standar terbuka perangkat
seluler. Ponsel Android pertama mulai dijual pada bulan Oktober 2008.
(Sumber : http://id.wikipedia.org/wiki/Android_(sistem_operasi) )
2. TAHAP DOWNLOAD
2.1.Download Eclipse
Anda dapat mendownload Eclipse disini.
2.2.Download JRE dan JDK disini
Anda dapat mendownload JRE dan JDK disini.
2.3.Download Android SDK disini
Anda dapat mendownload Android SDK disini.
3. TAHAP PENGINSTALAN
3.1.JRE dan JDK
JRE dan JDK dapat anda dilihat tahapan penginstalan disini.
3.2.Android SDK.
Android SDK dapat anda dilihat tahapan penginstalan disini.
3.3.Eclipse
Eclipse tidak perlu diinstal hanya perlu di ekstrak file nya.
4. TAHAP KODING
4.1.Source Code
a. MainActivity.java
package com.kaisar.breakoutgame;
import com.kaisar.breakoutgame.R;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.TextView;
public class MainActivity extends Activity implements BreakoutBoardCallback
{
private static final String TAG =
"MainActivity";
private BreakoutBoardView board;
private TextView lives;
@Override
protected void onCreate(Bundle
savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lives = (TextView)
findViewById(R.id.lives);
board = (BreakoutBoardView)
findViewById(R.id.gameboard);
board.setCallback(this);
}
@Override
public boolean
onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main,
menu);
return true;
}
@Override
public boolean
onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_reset:
Log.d(TAG,
"Resetting game");
board.getThread().reset();
break;
}
return false;
}
@Override
public void onGameChanged(final
int nbrOfLivesLeft) {
// Make sure we run on UI
thread
runOnUiThread(new Runnable()
{
@Override
public void run() {
String label =
String.format(getResources().getString(R.string.lives), nbrOfLivesLeft);
lives.setText(label);
}
});
}
@Override
public void onGameFinished() {
// do nothing (for now)
}
}
b. BreakoutBoardCallback.java
package com.kaisar.breakoutgame;
public interface
BreakoutBoardCallback {
public
void onGameChanged(int nbrOfLivesLeft);
public
void onGameFinished();
}
c. BreakoutBoardView.java
package com.kaisar.breakoutgame;
import java.util.Iterator;
import java.util.List;
import com.kaisar.breakoutgame.model.Background;
import
com.kaisar.breakoutgame.model.Block;
import
com.kaisar.breakoutgame.model.Dot;
import
com.kaisar.breakoutgame.model.Entity;
import
com.kaisar.breakoutgame.model.Paddle;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import
android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnTouchListener;
public class BreakoutBoardView
extends SurfaceView implements SurfaceHolder.Callback, OnTouchListener {
private static final String TAG =
"BreakoutBoardView";
// Render thread
private BreakoutBoardThread thread;
// Touch event position for the paddle
private double lastKnownPaddlePosition;
private BreakoutBoardCallback callback;
public BreakoutBoardView(Context context,
AttributeSet attrs) {
super(context, attrs);
SurfaceHolder holder = getHolder();
holder.addCallback(this);
// SurfaceView must have focus to get
touch events
setFocusable(true);
setOnTouchListener(this);
}
public void
setCallback(BreakoutBoardCallback callback) {
this.callback = callback;
}
@Override
public void surfaceCreated(SurfaceHolder
holder) {
Log.d(TAG, "Surface created,
starting new thread...");
thread = new
BreakoutBoardThread(holder);
thread.setRunning(true);
thread.start();
}
@Override
public void surfaceChanged(SurfaceHolder
holder, int format, int width, int height) {
Log.d(TAG, "Surface changed,
resetting game...");
thread.setSurfaceSize(width, height);
}
@Override
public void surfaceDestroyed(SurfaceHolder
holder) {
Log.d(TAG, "Surface destroyed,
trying to shut down thread...");
boolean retry = true;
thread.setRunning(false);
while (retry) {
try {
thread.join();
retry = false;
} catch (InterruptedException e) {
// Do nothing
}
}
Log.d(TAG, "Thread's dead, baby.
Thread's dead.");
}
@Override
public boolean onTouch(View v, MotionEvent
event) {
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE:
lastKnownPaddlePosition =
event.getX();
}
return true;
}
public BreakoutBoardThread getThread() {
return thread;
}
class BreakoutBoardThread extends Thread {
// Debug
private static final String TAG =
"BreakoutBoardThread";
// Game constants
private static final int NBR_OF_BLOCKS
= 6;
private static final double DOT_SPEED =
400.0;
private static final int NBR_OF_LIVES =
3;
// Game variables
private int nbrOfTriesLeft;
private long lastTime;
// Draw stuff
private SurfaceHolder surfaceHolder;
private boolean running;
private int canvasWidth;
private int canvasHeight;
private Background background;
// Entities
private List
gameEntities;
private ArrayList blocks;
private ArrayList
destroyedBlocks;
private Paddle paddle;
private Dot dot;
public
BreakoutBoardThread(SurfaceHolder surfaceHolder) {
this.surfaceHolder = surfaceHolder;
restart();
}
public void setRunning(boolean running)
{
this.running = running;
}
private void dead() {
Log.d(TAG, "Bang! You're dead.
Resetting...");
reset();
BreakoutBoardView.this.callback.onGameChanged(--nbrOfTriesLeft);
if (nbrOfTriesLeft <= 0) {
setRunning(false);
BreakoutBoardView.this.callback.onGameFinished();
}
}
public void restart() {
reset();
nbrOfTriesLeft = NBR_OF_LIVES;
BreakoutBoardView.this.callback.onGameChanged(nbrOfTriesLeft);
}
public void reset() {
synchronized (surfaceHolder) {
resetEntities(canvasWidth,
canvasHeight);
}
}
@Override
public void run() {
while (running) {
Canvas c = null;
try {
c =
surfaceHolder.lockCanvas(null);
synchronized
(surfaceHolder) {
updatePhysics();
// NOTE: In newer
versions of Android (4+), it seems SurfaceHolder.lockCanvas() may return null
whenever
// SurfaceHolder.Callback.surfaceDestroyed()
has been invoked. In earlier versions, a canvas was always
// returned until
SurfaceHolder.Callback.surfaceDestroyed() was FINISHED. See bug report:
//
https://code.google.com/p/android/issues/detail?id=38658
if (c != null) {
doDraw(c);
}
}
} finally {
// do this in a finally so
that if an exception is thrown
// during the above, we
don't leave the Surface in an
// inconsistent state
if (c != null) {
surfaceHolder.unlockCanvasAndPost(c);
}
}
}
}
public void setSurfaceSize(int width,
int height) {
synchronized (surfaceHolder) {
canvasWidth = width;
canvasHeight = height;
restart();
}
}
private void resetEntities(int width,
int height) {
background = new Background(width,
height);
gameEntities = new
ArrayList();
blocks = new
ArrayList();
destroyedBlocks = new
ArrayList();
double blockWidth = width / (1.1 *
NBR_OF_BLOCKS + 0.1);
double blockHeight = 0.1 *
blockWidth;
for (int i = 0; i <
NBR_OF_BLOCKS; i++) {
double blockX = i * (blockWidth
+ blockHeight) + blockHeight;
double blockY = 2 *
blockHeight;
Block b = new Block((int)
blockX, (int) blockY, (int) blockWidth, (int) blockHeight);
blocks.add(b);
gameEntities.add(b);
}
double paddleWidth = blockWidth *
2;
double paddleHeight = blockHeight *
2;
double paddleX = (width -
paddleWidth) / 2;
double paddleY = height -
paddleHeight;
paddle = new Paddle((int) paddleX,
(int) paddleY, (int) paddleWidth, (int) paddleHeight);
// TODO: Thread should not meddle
with properties of the view. Refactor...
lastKnownPaddlePosition =
paddle.getX();
gameEntities.add(paddle);
double dotSide = blockHeight;
double dotX = paddleX +
(paddleWidth - dotSide) / 2;
double dotY = paddleY - dotSide;
double startAngle = Math.PI *
Math.random() * 0.25; // Starting angle should be somewhat upwards
Log.d(TAG, "seed:" +
startAngle);
double vx = DOT_SPEED *
Math.sin(startAngle);
double vy = -DOT_SPEED * Math.cos(startAngle);
Log.d(TAG, "x:" + dotX +
", y:" + dotY + ", side:" + dotSide);
Log.d(TAG, "vx:" + vx +
", vy:" + vy);
dot = new Dot((int) dotX, (int)
dotY, (int) dotSide, (int) dotSide, vx, vy);
gameEntities.add(dot);
}
// Update game entities for next
iteration
private void updatePhysics() {
long now =
System.currentTimeMillis();
// Make sure we don't update
physics unnecessary often
if (lastTime > now)
return;
double elapsed = (now - lastTime) /
1000.0;
// Update paddle position
paddle.move(lastKnownPaddlePosition);
// Update dot position
double dx = dot.getVx() * elapsed;
double dy = dot.getVy() * elapsed;
dot.move(dx, dy, dot.getVx(),
dot.getVy());
// Check if dot collides with
paddle
if (dot.isColliding(paddle)) {
// New direction depends on
where the dot hits the paddle
int vx =
dot.getCollidingAngle(paddle);
dot.move(-dx, -dy, vx,
-dot.getVy());
}
// Check if dot hits block
Iterator iter =
blocks.iterator();
while (iter.hasNext()) {
Block b = iter.next();
if (dot.isColliding(b)) {
iter.remove();
gameEntities.remove(b);
destroyedBlocks.add(b);
dot.move(-dx, -dy,
dot.getVx(), -dot.getVy());
}
}
// Check if dot hits walls
if (dot.getX() < 0 || dot.getX()
> canvasWidth) {
dot.move(-dx, -dy, -dot.getVx(),
dot.getVy());
}
if (dot.getY() < 0) {
dot.move(-dx, -dy, dot.getVx(),
-dot.getVy());
}
// Check if game over
if (dot.getY() > canvasHeight) {
dead();
}
lastTime = now;
}
// Draws game entities on canvas. Must
be run in
private void doDraw(Canvas c) {
renderBackground(c);
renderEntities(c);
}
// Render the board background.
private void renderBackground(Canvas c)
{
c.drawRect(background.getRect(),
background.getPaint());
}
private void renderEntities(Canvas c) {
for (Entity e : gameEntities) {
c.drawRect(e.getRect(),
e.getPaint());
if (e instanceof Dot) {
Log.d(TAG, "drawing
dot: " + dot.getRect().centerX() + ", " + dot.getRect().centerY());
}
}
Iterator iter =
destroyedBlocks.iterator();
while (iter.hasNext()) {
Block b = iter.next();
Paint p = b.getPaint();
p.setAlpha(p.getAlpha() - 5);
c.drawRect(b.getRect(), p);
if (p.getAlpha() == 0) {
iter.remove();
}
}
}
}
}
d.Background.java
package com.kaisar.breakoutgame.model;
import android.graphics.Color;
public class
Background extends Entity {
public
Background(int width, int
height) {
super(0,0,
width, height,
Color.BLACK);
}
}
e. Block.java
package com.kaisar.breakoutgame.model;
import android.graphics.Color;
public class
Block extends Entity {
public
Block(int posX,
int posY,
int width,
int height)
{
super(posX, posY, width, height, Color.RED);
}
}
f. Dot.java
package com.kaisar.breakoutgame.model;
import android.graphics.Color;
public class
Dot extends MovableEntity {
private
double vx;
private
double vy;
public
Dot(int posX,
int posY,
int width,
int height,
double vx, double
vy) {
super(posX, posY, width, height, Color.WHITE);
this.vx = vx;
this.vy = vy;
}
public
void move(double dx,
double dy, double
vx, double
vy) {
super.move(dx, dy);
this.vx = vx;
this.vy = vy;
}
public
double getVx() {
return
vx;
}
public
double getVy() {
return
vy;
}
}
g. Entity.java
package com.kaisar.breakoutgame.model;
import android.graphics.Paint;
import android.graphics.Rect;
public class Entity {
private
static final int ANGLE_MOD = 5;
private
Rect rect;
private
Paint paint;
public
Entity(int posX, int posY, int width, int height, int color) {
rect
= new Rect(posX, posY, posX + width, posY + height);
paint = new Paint();
paint.setColor(color);
}
public
Rect getRect() {
return rect;
}
public
Paint getPaint() {
return paint;
}
public
boolean isColliding(Entity entity) {
Rect
other = entity.getRect();
return rect.intersects(other.left, other.top, other.right,
other.bottom);
}
public
int getCollidingAngle(Entity entity) {
Rect
other = entity.getRect();
return ANGLE_MOD * (rect.centerX() - other.centerX());
}
}
h. MovebleEntity
package com.kaisar.breakoutgame.model;
public class
MovableEntity extends Entity {
private
double centerX;
private
double centerY;
public
MovableEntity(int posX, int
posY, int
width, int
height, int
color) {
super(posX, posY, width, height, color);
centerX
= getRect().centerX();
centerY
= getRect().centerY();
}
public
double getX() {
return
centerX;
}
public
double getY() {
return
centerY;
}
public
void move(double dx,
double dy) {
centerX
+= dx;
centerY
+= dy;
// Correctly round the
position of the entity
int
moveX = (int) (centerX
- getRect().centerX());
int
moveY = (int) (centerY
- getRect().centerY());
getRect().offset(moveX, moveY);
}
}
i. Paddle
package
com.kaisar.breakoutgame.model;
import android.graphics.Color;
public class
Paddle extends MovableEntity {
public
Paddle(int posX,
int posY,
int width,
int height)
{
super(posX, posY, width, height, Color.BLUE);
}
public
void move(double position)
{
double
dx = position
- getX();
super.move(dx, 0);
}
}
j. Activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity"
>
<TextView
android:id="@+id/lives"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="@string/lives"
android:layout_alignParentTop="true"
android:layout_alignParentRight="true"
android:layout_marginBottom="@dimen/activity_vertical_margin"/>
<com.kaisar.breakoutgame.BreakoutBoardView
android:id="@+id/gameboard"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerHorizontal="true"
android:layout_below="@+id/lives"/>
</RelativeLayout>
5. TAHAP IMPLEMENTASI
5.1.Instalasi APK
6.2.Contoh Permainan
Sumber : http://billmill.org/static/canvastutorial/index.html




Tidak ada komentar:
Posting Komentar