Guten Abend zusammen.
Ich versuche mich momentan an meinem ersten Android-Game, was bisher auch relativ gut klappt. Dennoch stehe ich nun vor einem Problem für welches ich eure Hilfe brauche.
Vorerst allerdings, ein kurzer Überblick der Umsetzung, um nachgehende Verwirrung zu vermeiden :).
Der Grundriss meines Spiels stellt eine Activity(A_SPGame) dar. Das Layout der Activity beinhaltet eigentlich nur ein ImageView, das den kompletten Bildschirm ausfüllt. Dieses ImageView dient mir dazu, die Bitmap, auf der ich alle Elemente des Spiels zeichne(also das fertige Frame), anzuzeigen.
Die Acitvity selber verarbeitet alle Events wie z.B.: Scrollen, Touch usw. Zudem beinhaltet sie als Membervariable eine Instanz meiner GameKlasse(C_SPGame), welches das eigentliche Spiel darstellt.
Meine Frage ist nun, wo ich am besten die GameLoop unterbringe? Intuitiv wäre onCreate() der Activity meine Wahl gewesen, doch dies scheint nicht wirklich zu funktionieren, denn wenn ich die GameLoop dort unterbringe, verarbeitet meine Activity plötzlich keine Events mehr (kein aufruf von onKeyDown, Scroll usw.). Zudem wird dann auch kein Frame angezeigt(vorher getestet ohne GameLoop, also ohne while-schleife, nur mit aufruf game.update() und game.present()).
Activity(A_SPGame):
public class A_SPGame extends Activity implements OnGestureListener {
// ******** INTERFACE ELEMEMENTS ******** //
// ------ ImageViews ------ //
//the ImageView which contains(displays) the final bitmap(frontbuffer)
private ImageView imageview_frontbuffer;
// ******** RESOURCES ******** //
// ------ Values ------ //
private int int_ScreenWidth, int_ScreenHeight; //Width and height of the screen
private C_SPGame game; //the game!!!
// ------ Bitmaps ------ //
//the Bitmap where the specific part(depends on the view of the user) of the Backbuffer will be drawed to
private Bitmap bitmap_frontbuffer;
// ------ Others ------ //
private GestureDetector gesturedetector;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_spgame);
// ******** INTERFACE ELEMENTS ******** //
// ------ ImageViews ------ //
imageview_frontbuffer = (ImageView)findViewById(R.id.A_SPGame_frontbuffer); //imageview for frontbuffer
// ******** RESOURCES ******** //
// ------ Values ------ //
int_ScreenHeight = getResources().getDisplayMetrics().heightPixels; //height of the screen
int_ScreenWidth = getResources().getDisplayMetrics().widthPixels; //width of the screen
// ------ Bitmaps ------ //
bitmap_frontbuffer = Bitmap.createBitmap(int_ScreenWidth, int_ScreenHeight, Bitmap.Config.ARGB_8888); //frontbuffer
// ******** PREPARING ******** //
imageview_frontbuffer.setImageBitmap(bitmap_frontbuffer); //the imageview displays the frontbuffer
gesturedetector = new GestureDetector(this, this); //gesturedetector for detecting motionEvents like scroll or ondown
game = new C_SPGame(bitmap_frontbuffer, imageview_frontbuffer, getApplicationContext()); //this is the game!!!
// ########################################### //
// ################ GAME LOOP ################ //
// ########################################### //
while(!game.isQuit) {
game.update();
game.present();
}
game.close();
}
// ******** OnGestureListener ******** //
@Override
public boolean onTouchEvent(MotionEvent e) {
return gesturedetector.onTouchEvent(e);
}
@Override
public boolean onDown(MotionEvent e) {
return false;
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
return false;
}
@Override
public void onLongPress(MotionEvent e) {
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
float distanceY) {
game.scroll(distanceX, distanceY);
return false;
}
@Override
public void onShowPress(MotionEvent e) {
// TODO Auto-generated method stub
}
@Override
public boolean onSingleTapUp(MotionEvent e) {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
Log.d("Press", "BACK");
if (keyCode == KeyEvent.KEYCODE_BACK) {
Log.d("Game", "QUIT");
game.isQuit = true;
return true;
}
return super.onKeyDown(keyCode, event);
}
}
Alles anzeigen
Game(C_SPGame):
public class C_SPGame {
// ******** INTERFACE ELEMENTS ******** //
ImageView imageview_frontbuffer;
// ******** RESOURCES ******** //
// ------ Values ------ //
protected boolean isQuit; //indicates if the player quited or not
private Context context; //the Context of the app -> needed for loading bitmaps etc.
private int int_screenWidth, int_screenHeight; //Width and height of the screen
private long long_currentTime; //the current systemTime in milliseconds (for frame-independend gamespeed)
// ------ Graphics ------ //
BitmapFactory.Options bitmapOpt_bitmapoptions; //needet to draw the bitmap without scaling
Bitmap bitmap_frontbuffer; //the frontbuffer we are displaying (displaying part of the backbuffer)
Bitmap bitmap_backbuffer; //the entire frame (whole size of map + elements such as towers shots creeps etc.)
Bitmap bitmap_map; //the map(level)
Canvas canvas_frontbuffer; //the canvas drawing to the frontbuffer (frontbuffer -> specified part/area(screensize) of backbuffer)
Canvas canvas_backbuffer; //the canvas drawing to the backbuffer (backbuffer -> the entire frame, not only the part that were displayed to the screen)
/* ! */ Bitmap bitmap_creep1;
// ------ Others ------ //
private Rect rect_src, rect_dst; //rects for displaying a part of a bitmap
private final Rect rect_backbuffersrc, rect_backbufferdst; //rects to draw the map to the backbuffer (ALWAYS draw the whole map -> final)
// ******** GAME VALUES ******** //
private List<C_Coordinate> list_path; //Path (few C_Corrdinates) on which the creeps are walking
private List<C_BasicGraphicObject> list_gameobjects; //all object from the game are in this list (creeps, tower, shots etc.)
public C_SPGame(Bitmap frontbuffer, ImageView imageview_frontbuffer, Context context) {
// ******** INTERFACE ELEMENTS ******** //
this.imageview_frontbuffer = imageview_frontbuffer;
// ******** RESOURCES ******** //
// ------ Values ------ //
this.isQuit = false; //set to false -> player hasnt quited so far
this.context = context; //set passed context to a member -> needed to load bitmaps etc.
this.int_screenWidth = context.getResources().getDisplayMetrics().widthPixels; //width of the screen
this.int_screenHeight = context.getResources().getDisplayMetrics().heightPixels; //height of the screen
// ------ Graphics ------ //
this.bitmapOpt_bitmapoptions = new BitmapFactory.Options(); //needed to draw bitmaps without scaling
this.bitmapOpt_bitmapoptions.inScaled = false; //set false to load bitmap without scaling
this.bitmap_frontbuffer = frontbuffer; //set the passed frontbuffer to the member frontbuffer
this.bitmap_map = BitmapFactory.decodeResource(context.getResources(), //
R.drawable.map_c1l1, //load the correct map(level-background)
this.bitmapOpt_bitmapoptions); //
this.canvas_frontbuffer = new Canvas(bitmap_frontbuffer); //create new Canvas and set the frontbuffer to the bitmap we want to draw on
this.bitmap_backbuffer = Bitmap.createBitmap(this.bitmap_map.getWidth(), //
this.bitmap_map.getHeight(), //the entire frame(whole mapsize) + creeps, shots etc.
Bitmap.Config.ARGB_8888); //
this.canvas_backbuffer = new Canvas(bitmap_backbuffer); //create new Canvas and set the backbuffer to the bitmap we want to draw on
/* ! */ this.bitmap_creep1 = BitmapFactory.decodeResource(context.getResources(), //
/* ! */ R.drawable.creep1, //load the bitmap of creep1
/* ! */ this.bitmapOpt_bitmapoptions); //
// ------ Others ------ //
this.rect_dst = new Rect(0, 0, this.int_screenWidth, this.int_screenHeight); //rect for drawing to a specific location (destination Rect)
this.rect_src = new Rect(0, 0, this.int_screenWidth, this.int_screenHeight); //rect for getting a specific part from a bitmap (source Rect)
this.rect_backbuffersrc = new Rect(0, //
0, //the rect to get the whole map(level) (always need the entire map -> final variable)
this.bitmap_map.getWidth(), //
this.bitmap_map.getHeight()); //
this.rect_backbufferdst = new Rect(0, //
0, //the rect draw the whole map(level) (always draw the whole map -> final variable)
this.bitmap_backbuffer.getWidth(), //
this.bitmap_backbuffer.getHeight()); //
// ******** GAME VALUES ******** //
list_path = new ArrayList<C_Coordinate>();
/* ! */ list_path.add(new C_Coordinate(50f, 745f));
/* ! */ list_path.add(new C_Coordinate(340f, 745f));
/* ! */ list_path.add(new C_Coordinate(340f, 125f));
/* ! */ list_path.add(new C_Coordinate(795f, 125f));
/* ! */ list_path.add(new C_Coordinate(795f, 650f));
/* ! */ list_path.add(new C_Coordinate(1245f, 650f));
list_gameobjects = new ArrayList<C_BasicGraphicObject>();
/* ! */ list_gameobjects.add(new C_Creep1(bitmap_backbuffer, bitmap_creep1, list_path));
this.long_currentTime = System.currentTimeMillis();
}
protected boolean update() {
Log.d("Call", "Update!");
for(int counter = 0; counter < list_gameobjects.size(); counter++) {
list_gameobjects.get(counter).update((float)(System.currentTimeMillis() - this.long_currentTime));
}
this.long_currentTime = System.currentTimeMillis();
return true;
}
protected boolean present() {
this.canvas_backbuffer.drawBitmap(this.bitmap_map, this.rect_backbuffersrc, this.rect_backbufferdst, null);
for(int counter = 0; counter < list_gameobjects.size(); counter++) {
list_gameobjects.get(counter).render();
}
this.canvas_frontbuffer.drawBitmap(bitmap_backbuffer, rect_src, rect_dst, null);
this.imageview_frontbuffer.setImageBitmap(bitmap_frontbuffer); //finally set the frontbufferBitmap again to update the imageview and display the new frame
return true;
}
protected boolean close() {
return true;
}
protected boolean scroll(float distanceX, float distanceY) {
this.bitmap_frontbuffer.eraseColor(android.graphics.Color.BLACK);
this.rect_src.top = this.rect_src.top + Math.round(distanceY);
this.rect_src.bottom = this.rect_src.top + this.int_screenHeight;
this.rect_src.left = this.rect_src.left + Math.round(distanceX);
this.rect_src.right = this.rect_src.left + this.int_screenWidth;
this.canvas_frontbuffer.drawBitmap(bitmap_backbuffer, rect_src, rect_dst, null);
this.imageview_frontbuffer.setImageBitmap(bitmap_frontbuffer);
return true;
}
}
Alles anzeigen
Bedanke mich schon mal im Voraus!
MfG XoR