Author: matt.burkhart
Date: Tue Dec 23 23:57:21 2008
New Revision: 63
Modified:
trunk/content_package/jump.humanoid.animation
trunk/content_package/run.humanoid.animation
trunk/src/android/com/abb/AlienBloodBathMain.java
trunk/src/android/com/abb/ArticulatedEntity.java
trunk/src/android/com/abb/Avatar.java
trunk/src/android/com/abb/Blood.java
trunk/src/android/com/abb/Content.java
trunk/src/android/com/abb/Enemy.java
trunk/src/android/com/abb/Entity.java
trunk/src/android/com/abb/Fire.java
trunk/src/android/com/abb/Game.java
trunk/src/android/com/abb/GameState.java
trunk/src/android/com/abb/GameView.java
trunk/src/android/com/abb/Graphics.java
trunk/src/android/com/abb/Map.java
trunk/src/android/com/abb/MapSelectActivity.java
trunk/src/android/com/abb/Weapon.java
Log:
• Update avatar animations.
• Code style cleanups including unnecessary package imports.
• Efficiently improvements for increased game frame rate in both the Map
and Avatar rendering methods.
• Automatic hardware detection and created graphics API method:
hasHardwareAcceleration(). This is now used to enable background drawing
only when hardware is available.
• Work on improving the OpenGL state though application hibernations. More
work still needs to be done for this to function properly.
• Added getPartTransfomation(...) method to ArticulatedEntity to support
proper gun positioning.
Modified: trunk/content_package/jump.humanoid.animation
==============================================================================
--- trunk/content_package/jump.humanoid.animation (original)
+++ trunk/content_package/jump.humanoid.animation Tue Dec 23 23:57:21 2008
@@ -1,8 +1,8 @@
root 0.0 0
-root 1.0 360
+root 0.75 360
thigh_r 0.0 -45
-thigh_l 0.0 -45
+thigh_l 0.0 -40
leg_r 0.0 50
leg_l 0.0 50
@@ -13,7 +13,7 @@
shoulder_l 0.0 -110
arm_r 0.0 140
-arm_l 0.0 140
+arm_l 0.0 135
farm_r 0.0 -90
farm_l 0.0 -90
Modified: trunk/content_package/run.humanoid.animation
==============================================================================
--- trunk/content_package/run.humanoid.animation (original)
+++ trunk/content_package/run.humanoid.animation Tue Dec 23 23:57:21 2008
@@ -28,8 +28,13 @@
shoulder_l 1.0 200
shoulder_l 2.0 190
-arm_r 0.0 -110
-arm_l 0.0 140
+arm_r 0.0 -120
+arm_r 1.0 -100
+arm_r 2.0 -120
+
+arm_l 0.0 150
+arm_l 1.0 130
+arm_l 2.0 150
farm_r 0.0 -110
farm_l 0.0 -80
Modified: trunk/src/android/com/abb/AlienBloodBathMain.java
==============================================================================
--- trunk/src/android/com/abb/AlienBloodBathMain.java (original)
+++ trunk/src/android/com/abb/AlienBloodBathMain.java Tue Dec 23 23:57:21
2008
@@ -23,10 +23,6 @@
import android.view.WindowManager;
import android.widget.TextView;
-import android.com.abb.Content;
-import android.com.abb.GameState;
-import android.com.abb.GameView;
-
public class AlienBloodBathMain extends Activity {
@Override
Modified: trunk/src/android/com/abb/ArticulatedEntity.java
==============================================================================
--- trunk/src/android/com/abb/ArticulatedEntity.java (original)
+++ trunk/src/android/com/abb/ArticulatedEntity.java Tue Dec 23 23:57:21
2008
@@ -26,15 +26,11 @@
import java.util.Stack;
import junit.framework.Assert;
-import android.com.abb.Content;
-import android.com.abb.Entity;
-import android.com.abb.Graphics;
-
-/** An ArticulatedEntity is a functional replacement to an Entity. It
represents
- * a single drawable, collideable game unit. The ArticulatedEntity class
- * provides, on top of Entity, the drawing of an articulated model and
joint
- * animations. */
+/** An ArticulatedEntity is a functional replacement to an Entity
instance. It
+ * represents a single drawable, physical game object. The
ArticulatedEntity
+ * class provides, on top of Entity, the drawing of an articulated model
and
+ * joint animations. */
public class ArticulatedEntity extends Entity {
public ArticulatedEntity() {
super();
@@ -124,6 +120,17 @@
mRoot.draw(graphics, mImageHandle, root_transformation, mAnimation);
}
+ /** Return the 3x3 transformation matrix used to draw child parts. In
other
+ * words, the returned matrix transforms points into screen coordinates
with
+ * the origin at the tip / end of the part. For example, multiplying by
the
+ * vector (0, 0, 1)^T will yield (x, y, w) screen coordinates at the tip
of
+ * the part. */
+ public Matrix getPartTransformation(String part_name) {
+ Part part = findPartByName(part_name);
+ Assert.assertNotNull("Unknown part name: " + part_name, part);
+ return part.transformation;
+ }
+
private Part findPartByName(String part_name) {
if (part_name.equals("root")) {
return mRoot;
@@ -132,7 +139,6 @@
}
}
-
/** The Part class structure represents a single element of the
articulated
* entity. */
private class Part {
@@ -182,6 +188,8 @@
}
return null;
}
+
+ private float[] mTransformationData = new float[9];
}
/** The Animation class stores and provides access to a independent, time
@@ -236,6 +244,11 @@
}
public float getPartAngle(String part_name) {
+ ArrayList<KeyFrame> part_keyframes = mKeyFrames.get(part_name);
+ if (part_keyframes == null) {
+ return 0.0f; // No animation track for this part exists.
+ }
+
// We need to find the two nearest key frames and interpolate between
// them. The following assumes the key frames are sorted within each
track
// prior to this call.
@@ -243,11 +256,6 @@
float angle_a = 0.0f;
float time_b = 0.0f;
float angle_b = 0.0f;
-
- ArrayList<KeyFrame> part_keyframes = mKeyFrames.get(part_name);
- if (part_keyframes == null) {
- return 0.0f;
- }
for (int index = 0; index < part_keyframes.size(); ++index) {
KeyFrame keyframe_a = part_keyframes.get(index);
Modified: trunk/src/android/com/abb/Avatar.java
==============================================================================
--- trunk/src/android/com/abb/Avatar.java (original)
+++ trunk/src/android/com/abb/Avatar.java Tue Dec 23 23:57:21 2008
@@ -15,19 +15,18 @@
import android.net.Uri;
import android.view.KeyEvent;
-import android.com.abb.ArticulatedEntity;
-import android.com.abb.GameState;
-import android.com.abb.Weapon;
-
public class Avatar extends ArticulatedEntity {
public Avatar(GameState game_state) {
super();
- game_state_ = game_state;
+ mGameState = game_state;
+ mWeapon = new Weapon(mGameState);
+
setDrawingScale(kDrawingScale);
radius = kRadius;
}
+ @Override
public void step(float time_step) {
super.step(time_step);
mWeapon.x = x;
@@ -36,22 +35,21 @@
// Update the horizontal acceleration acceleration according to the
current
// controls and the contact with the ground.
- if (ddx > 0 && has_ground_contact)
+ if (ddx > 0 && has_ground_contact) {
ddx = +kGroundAcceleration;
- if (ddx > 0 && !has_ground_contact)
+ } else if (ddx > 0 && !has_ground_contact) {
ddx = +kAirAcceleration;
- if (ddx < 0 && has_ground_contact)
+ } else if (ddx < 0 && has_ground_contact) {
ddx = -kGroundAcceleration;
- if (ddx < 0 && !has_ground_contact)
+ } else if (ddx < 0 && !has_ground_contact) {
ddx = -kAirAcceleration;
+ }
// Update the avatar animation frame according the current entity
motion.
if (dx < 0) {
- facing_left_ = true;
- sprite_flipped_horizontal = facing_left_;
+ sprite_flipped_horizontal = true;
} else if (dx > 0) {
- facing_left_ = false;
- sprite_flipped_horizontal = facing_left_;
+ sprite_flipped_horizontal = false;
}
if (has_ground_contact) {
@@ -67,14 +65,15 @@
stepAnimation(time_step);
}
- mWeapon.setSprite(facing_left_);
+ mWeapon.setSprite(sprite_flipped_horizontal);
// Update the shooting mechanism. The choices for shot direction are
// specialized for each animation case: in the air, facing left,
right, and
- // considering the avatar's speed.
- shot_delay_ -= time_step;
- if (shooting_ && shot_delay_ < time_step) {
- shot_delay_ = kShotDelay;
+ // considering the avatar's speed. TODO(barnes): Replace all of this
with
+ // the equivalent in Weapon.java.
+ mShotDelay -= time_step;
+ if (mShooting && mShotDelay < time_step) {
+ mShotDelay = kShotDelay;
float shot_angle;
float shot_distance = kShotDistance;
float shot_velocity = kShotVelocity;
@@ -82,69 +81,64 @@
float y_offset;
if (!has_ground_contact) {
- shot_angle = shot_phase_;
- if (facing_left_)
- shot_angle = -shot_phase_;
- shot_delay_ -= 2.0f * time_step;
- shot_phase_ += 45.0f * (float)Math.PI / 180.0f;
+ shot_angle = mShotPhase;
+ if (sprite_flipped_horizontal) {
+ shot_angle = -mShotPhase;
+ }
+ mShotDelay -= 2.0f * time_step;
+ mShotPhase += 45.0f * (float)Math.PI / 180.0f;
shot_velocity *= 0.6f;
x_offset = kShotDistance * (float)Math.cos(shot_angle);
y_offset = kShotDistance * (float)Math.sin(shot_angle);
- } else if (facing_left_) {
- shot_angle = kShotSpread * (float)Math.sin(shot_phase_) +
(float)Math.PI;
- shot_phase_ += 10.0f;
+ } else if (sprite_flipped_horizontal) {
+ shot_angle = kShotSpread * (float)(Math.sin(mShotPhase) + Math.PI);
+ mShotPhase += 10.0f;
x_offset = -kShotOffsetX;
y_offset = kShotOffsetY;
- if (Math.abs(dx) > kAnimationStopThreshold)
- y_offset += kShotDistance / 2.0f * (float)Math.sin(shot_phase_);
+ if (Math.abs(dx) > kAnimationStopThreshold) {
+ y_offset += kShotDistance / 2.0f * (float)Math.sin(mShotPhase);
+ }
} else {
- shot_angle = kShotSpread * (float)Math.sin(shot_phase_);
- shot_phase_ += 10.0f;
+ shot_angle = kShotSpread * (float)Math.sin(mShotPhase);
+ mShotPhase += 10.0f;
x_offset = kShotOffsetX;
y_offset = kShotOffsetY;
- if (Math.abs(dx) > kAnimationStopThreshold)
- y_offset += kShotDistance / 2.0f * (float)Math.sin(shot_phase_);
+ if (Math.abs(dx) > kAnimationStopThreshold) {
+ y_offset += kShotDistance / 2.0f * (float)Math.sin(mShotPhase);
+ }
}
float dx_offset = shot_velocity * (float)Math.cos(shot_angle);
float dy_offset = shot_velocity * (float)Math.sin(shot_angle);
- game_state_.createFireProjectile(
+ mGameState.createFireProjectile(
x + x_offset, y + y_offset, dx + dx_offset, dy + dy_offset);
}
}
public void setKeyState(int key_code, int state) {
- if (key_code == kKeyLeft)
+ if (key_code == kKeyLeft) {
ddx = -kGroundAcceleration * state;
- if (key_code == kKeyRight)
+ } else if (key_code == kKeyRight) {
ddx = +kGroundAcceleration * state;
- if (key_code == kKeyJump && state == 1 && has_ground_contact)
+ } else if (key_code == kKeyJump && state == 1 && has_ground_contact) {
dy -= kJumpVelocity;
- if (key_code == kKeyShoot)
- shooting_ = (state == 1);
- }
-
- private void setSprite(int index, boolean facing_left) {
- // Set up the sprite drawing parameters within our *parent* Entity
class.
- sprite_rect.top = kSpriteSize * index;
- sprite_rect.bottom = kSpriteSize * index + kSpriteSize;
- sprite_flipped_horizontal = facing_left;
+ } else if (key_code == kKeyShoot) {
+ mShooting = (state == 1);
+ }
}
- private float animation_phase_ = 0.0f;
- private boolean facing_left_;
- private GameState game_state_;
- private boolean shooting_;
- private float shot_delay_;
- private float shot_phase_;
- public Weapon mWeapon = new Weapon(game_state_);
+ private GameState mGameState;
+ private float mShotDelay;
+ private boolean mShooting;
+ private float mShotPhase;
+ public Weapon mWeapon;
private static final float kAirAcceleration = 40.0f;
private static final float kAnimationStopThreshold = 40.0f;
private static final float kDrawingScale = 0.4f;
private static final float kGravity = 200.0f;
private static final float kGroundAcceleration = 700.0f;
- private static final float kGroundAnimationSpeed = 1.0f / 600.0f;
+ private static final float kGroundAnimationSpeed = 1.0f / 500.0f;
private static final float kJumpVelocity = 250.0f;
private static final int kKeyLeft = KeyEvent.KEYCODE_A;
private static final int kKeyRight = KeyEvent.KEYCODE_S;
Modified: trunk/src/android/com/abb/Blood.java
==============================================================================
--- trunk/src/android/com/abb/Blood.java (original)
+++ trunk/src/android/com/abb/Blood.java Tue Dec 23 23:57:21 2008
@@ -15,8 +15,6 @@
import android.view.KeyEvent;
import java.lang.Math;
-import android.com.abb.Entity;
-
public class Blood extends Entity {
public Blood() {
Modified: trunk/src/android/com/abb/Content.java
==============================================================================
--- trunk/src/android/com/abb/Content.java (original)
+++ trunk/src/android/com/abb/Content.java Tue Dec 23 23:57:21 2008
@@ -29,7 +29,8 @@
/** Class to abstract the details of extracting and accessing files from
the ABB
- * content zip file in the same was files on disk are accessed. */
+ * content zip file in the same was files on disk are accessed. TODO: This
class
+ * is not thread-safe. Extracted files are not cached. */
public class Content {
public static void initialize(Resources resources) {
try {
Modified: trunk/src/android/com/abb/Enemy.java
==============================================================================
--- trunk/src/android/com/abb/Enemy.java (original)
+++ trunk/src/android/com/abb/Enemy.java Tue Dec 23 23:57:21 2008
@@ -15,8 +15,6 @@
import android.view.KeyEvent;
import java.lang.Math;
-import android.com.abb.Entity;
-
public class Enemy extends Entity {
public Enemy(Entity target) {
Modified: trunk/src/android/com/abb/Entity.java
==============================================================================
--- trunk/src/android/com/abb/Entity.java (original)
+++ trunk/src/android/com/abb/Entity.java Tue Dec 23 23:57:21 2008
@@ -18,9 +18,9 @@
import java.lang.Math;
import java.util.Random;
-import android.com.abb.Graphics;
-
+/** The Entity class is intended to be lowest level, drawable, physical
+ * in-game object. */
public class Entity {
public boolean alive = true; // Should not be deleted from the game.
public boolean has_ground_contact;
@@ -49,9 +49,9 @@
// The following is a poor hack to simulate "friction" against the
ground
// surface. The problem with this implementation is that it does not
account
- // for the time_step. TODO(burkhart): Fix this implementation.
+ // for the time_step. TODO(burkhart): Fix this friction implementation.
if (has_ground_contact) {
- dx *= (1.0f - kGroundFriction);
+ dx *= (1.0f - kGroundKineticFriction);
}
dx = Math.max(dx, -kMaxVelocity);
@@ -85,6 +85,6 @@
protected static Random mRandom = new Random();
- private static final float kGroundFriction = 0.2f;
+ private static final float kGroundKineticFriction = 0.2f;
private static final float kMaxVelocity = 200.0f;
}
Modified: trunk/src/android/com/abb/Fire.java
==============================================================================
--- trunk/src/android/com/abb/Fire.java (original)
+++ trunk/src/android/com/abb/Fire.java Tue Dec 23 23:57:21 2008
@@ -15,8 +15,6 @@
import android.view.KeyEvent;
import java.lang.Math;
-import android.com.abb.Entity;
-
public class Fire extends Entity {
public Fire() {
Modified: trunk/src/android/com/abb/Game.java
==============================================================================
--- trunk/src/android/com/abb/Game.java (original)
+++ trunk/src/android/com/abb/Game.java Tue Dec 23 23:57:21 2008
@@ -15,8 +15,6 @@
import android.content.res.Resources;
import android.graphics.Canvas;
-import android.com.abb.Graphics;
-
/** Simple interface which hides most of the Android specifics. All method
calls
* are serialized. */
Modified: trunk/src/android/com/abb/GameState.java
==============================================================================
--- trunk/src/android/com/abb/GameState.java (original)
+++ trunk/src/android/com/abb/GameState.java Tue Dec 23 23:57:21 2008
@@ -25,15 +25,6 @@
import java.util.Iterator;
import java.util.Random;
-import android.com.abb.Avatar;
-import android.com.abb.Blood;
-import android.com.abb.Content;
-import android.com.abb.Enemy;
-import android.com.abb.Fire;
-import android.com.abb.Game;
-import android.com.abb.Graphics;
-import android.com.abb.Map;
-import android.com.abb.Weapon;
public class GameState implements Game {
public Avatar avatar = new Avatar(this);
@@ -45,8 +36,8 @@
public ArrayList<Entity> projectiles = new ArrayList<Entity>();
public GameState(Context context) {
- context_ = context;
- vibrator_ =
(Vibrator)context.getSystemService(Context.VIBRATOR_SERVICE);
+ mContext = context;
+ mVibrator =
(Vibrator)context.getSystemService(Context.VIBRATOR_SERVICE);
}
public void initializeGraphics(Graphics graphics) {
@@ -63,8 +54,8 @@
misc_sprites = graphics.loadImageFromBitmap(misc_sprites_bitmap);
}
- /** Initialize the game state structure. Upon returning, game_state_
should be
- * in a state representing a new game life. */
+ /** Initialize the game state structure. Upon returning the game state
should
+ * be in a state representing a new game "life". */
public void reset() {
map.reload();
particles.clear();
@@ -72,11 +63,11 @@
enemies.clear();
avatar.stop();
avatar.alive = true;
- avatar.x = map.starting_x;
- avatar.y = map.starting_y;
- view_x_ = target_view_x_ = avatar.x;
- view_y_ = target_view_y_ = avatar.y;
- death_timer_ = kDeathTimer;
+ avatar.x = map.getStartingX();
+ avatar.y = map.getStartingY();
+ mViewX = mTargetViewX = avatar.x;
+ mViewY = mTargetViewY = avatar.y;
+ mDeathTimer = kDeathTimer;
}
public boolean onKeyDown(int key_code) {
@@ -98,16 +89,17 @@
/** Run the game simulation for the specified amount of seconds. */
protected void stepGame(float time_step) {
// Update the view parameters.
- if (!avatar.has_ground_contact)
- target_zoom_ = kAirZoom;
- else
- target_zoom_ = kGroundZoom;
- target_view_x_ = avatar.x + kViewLead * avatar.dx;
- target_view_y_ = avatar.y + kViewLead * avatar.dy;
-
- zoom_ += (target_zoom_ - zoom_) * kZoomSpeed;
- view_x_ += (target_view_x_ - view_x_) * kViewSpeed;
- view_y_ += (target_view_y_ - view_y_) * kViewSpeed;
+ if (!avatar.has_ground_contact) {
+ mTargetZoom = kAirZoom;
+ } else {
+ mTargetZoom = kGroundZoom;
+ }
+ mTargetViewX = avatar.x + kViewLead * avatar.dx;
+ mTargetViewY = avatar.y + kViewLead * avatar.dy;
+
+ mZoom += (mTargetZoom - mZoom) * kZoomSpeed;
+ mViewX += (mTargetViewX - mViewX) * kViewSpeed;
+ mViewY += (mTargetViewY - mViewY) * kViewSpeed;
// Step the avatar.
if (avatar.alive) {
@@ -119,17 +111,18 @@
reset();
}
} else {
- if (death_timer_ == kDeathTimer) {
+ if (mDeathTimer == kDeathTimer) {
for (int n = 0; n < 2 * kBloodBathSize; n++) {
createBloodParticle(
avatar.x, avatar.y,
- 2.0f * kBloodBathVelocity * (0.5f - random_.nextFloat()) +
avatar.dx,
- 2.0f * kBloodBathVelocity * (0.5f - random_.nextFloat()) +
avatar.dy);
+ 2.0f * kBloodBathVelocity * (0.5f - mRandom.nextFloat()) +
avatar.dx,
+ 2.0f * kBloodBathVelocity * (0.5f - mRandom.nextFloat()) +
avatar.dy);
}
}
- death_timer_ -= time_step;
- if (death_timer_ < 0)
+ mDeathTimer -= time_step;
+ if (mDeathTimer < 0) {
reset();
+ }
}
// Step the enemies.
@@ -142,8 +135,8 @@
for (int n = 0; n < kBloodBathSize; n++) {
createBloodParticle(
enemy.x, enemy.y,
- kBloodBathVelocity * (0.5f - random_.nextFloat()) + enemy.dx,
- kBloodBathVelocity * (0.5f - random_.nextFloat()) +
enemy.dy);
+ kBloodBathVelocity * (0.5f - mRandom.nextFloat()) + enemy.dx,
+ kBloodBathVelocity * (0.5f - mRandom.nextFloat()) +
enemy.dy);
}
it.remove();
}
@@ -153,18 +146,21 @@
for (Iterator it = projectiles.iterator(); it.hasNext();) {
Fire projectile = (Fire)it.next();
projectile.step(time_step);
- for (Iterator enemy_it = enemies.iterator(); enemy_it.hasNext();)
+ for (Iterator enemy_it = enemies.iterator(); enemy_it.hasNext();) {
projectile.collideEntity((Entity)enemy_it.next());
- if (!projectile.alive)
+ }
+ if (!projectile.alive) {
it.remove();
+ }
}
// Step the particles.
for (Iterator it = particles.iterator(); it.hasNext();) {
Entity particle = (Entity)it.next();
particle.step(time_step);
- if (!particle.alive)
+ if (!particle.alive) {
it.remove();
+ }
}
}
@@ -172,26 +168,29 @@
* avatar centered in the screen. */
protected void drawGame(Graphics graphics) {
// Draw the map tiles.
- map.draw(graphics, view_x_, view_y_, zoom_);
+ map.draw(graphics, mViewX, mViewY, mZoom);
// Draw the enemies.
- for (Iterator it = enemies.iterator(); it.hasNext();)
- ((Entity)it.next()).draw(graphics, view_x_, view_y_, zoom_);
+ for (Iterator it = enemies.iterator(); it.hasNext();) {
+ ((Entity)it.next()).draw(graphics, mViewX, mViewY, mZoom);
+ }
// Draw the avatar and weapon.
if (avatar.alive) {
- avatar.draw(graphics, view_x_, view_y_, zoom_);
+ avatar.draw(graphics, mViewX, mViewY, mZoom);
avatar.mWeapon.setImage(graphics);
- avatar.mWeapon.draw(graphics, view_x_, view_y_, zoom_);
+ //avatar.mWeapon.draw(graphics, mViewX, mViewY, mZoom);
}
// Draw the projectiles.
- for (Iterator it = projectiles.iterator(); it.hasNext();)
- ((Entity)it.next()).draw(graphics, view_x_, view_y_, zoom_);
+ for (Iterator it = projectiles.iterator(); it.hasNext();) {
+ ((Entity)it.next()).draw(graphics, mViewX, mViewY, mZoom);
+ }
// Draw the particles.
- for (Iterator it = particles.iterator(); it.hasNext();)
- ((Entity)it.next()).draw(graphics, view_x_, view_y_, zoom_);
+ for (Iterator it = particles.iterator(); it.hasNext();) {
+ ((Entity)it.next()).draw(graphics, mViewX, mViewY, mZoom);
+ }
}
public Entity createEnemy(float x, float y) {
@@ -228,18 +227,18 @@
}
public void vibrate() {
- vibrator_.vibrate(kVibrateLength);
+ mVibrator.vibrate(kVibrateLength);
}
public void loadStateBundle(Bundle saved_instance_state) {
map.loadStateBundle(saved_instance_state.getBundle("map"));
reset();
- target_view_x_ = saved_instance_state.getFloat("target_view_x_");
- target_view_y_ = saved_instance_state.getFloat("target_view_y_");
- view_x_ = saved_instance_state.getFloat("view_x_");
- view_y_ = saved_instance_state.getFloat("view_y_");
- zoom_ = saved_instance_state.getFloat("zoom_");
+ mTargetViewX = saved_instance_state.getFloat("mTargetViewX");
+ mTargetViewY = saved_instance_state.getFloat("mTargetViewY");
+ mViewX = saved_instance_state.getFloat("mViewX");
+ mViewY = saved_instance_state.getFloat("mViewY");
+ mZoom = saved_instance_state.getFloat("mZoom");
avatar.x = saved_instance_state.getFloat("avatar.x");
avatar.y = saved_instance_state.getFloat("avatar.y");
@@ -256,11 +255,11 @@
Bundle saved_instance_state = new Bundle();
saved_instance_state.putBundle("map", map.saveStateBundle());
- saved_instance_state.putFloat("target_view_x_", target_view_x_);
- saved_instance_state.putFloat("target_view_y_", target_view_y_);
- saved_instance_state.putFloat("view_x_", view_x_);
- saved_instance_state.putFloat("view_y_", view_y_);
- saved_instance_state.putFloat("zoom_", zoom_);
+ saved_instance_state.putFloat("mTargetViewX", mTargetViewX);
+ saved_instance_state.putFloat("mTargetViewY", mTargetViewY);
+ saved_instance_state.putFloat("mViewX", mViewX);
+ saved_instance_state.putFloat("mViewY", mViewY);
+ saved_instance_state.putFloat("mZoom", mZoom);
saved_instance_state.putFloat("avatar.x", avatar.x);
saved_instance_state.putFloat("avatar.y", avatar.y);
@@ -272,16 +271,16 @@
return saved_instance_state;
}
- private Context context_;
- private float death_timer_ = kDeathTimer;
- private Random random_ = new Random();
- private float target_view_x_ = 0.0f;
- private float target_view_y_ = 0.0f;
- private float target_zoom_ = kGroundZoom;
- private Vibrator vibrator_;
- private float view_x_ = 0.0f;
- private float view_y_ = 0.0f;
- private float zoom_ = kGroundZoom;
+ private Context mContext;
+ private float mDeathTimer = kDeathTimer;
+ private Random mRandom = new Random();
+ private float mTargetViewX = 0.0f;
+ private float mTargetViewY = 0.0f;
+ private float mTargetZoom = kGroundZoom;
+ private Vibrator mVibrator;
+ private float mViewX = 0.0f;
+ private float mViewY = 0.0f;
+ private float mZoom = kGroundZoom;
private static final float kAirZoom = 0.6f;
private static final int kBloodBathSize = 10; // Number of blood
particles.
Modified: trunk/src/android/com/abb/GameView.java
==============================================================================
--- trunk/src/android/com/abb/GameView.java (original)
+++ trunk/src/android/com/abb/GameView.java Tue Dec 23 23:57:21 2008
@@ -32,9 +32,7 @@
import java.lang.Math;
import java.lang.System;
import java.lang.Thread;
-
-import android.com.abb.Game;
-import android.com.abb.Graphics;
+import junit.framework.Assert;
public class GameView extends SurfaceView implements
SurfaceHolder.Callback {
@@ -53,7 +51,9 @@
}
synchronized (game_) {
- graphics_ = new Graphics();
+ Assert.assertEquals(
+ "GameView thread must only be run once.", graphics_, null);
+ graphics_ = new Graphics();
graphics_.initialize(surface_holder_);
game_.initializeGraphics(graphics_);
}
@@ -64,7 +64,7 @@
// possible. Here we define the maximum framerate which needs to
make the
// trade off between graphics fluidity and power savings.
final float kMaxFrameRate = 15.0f; // Frames / second.
- final float kMinFrameRate = 4.0f; // Frames / second.
+ final float kMinFrameRate = 5.0f; // Frames / second.
final float kMinTimeStep = 1.0f / kMaxFrameRate; // Seconds.
final float kMaxTimeStep = 1.0f / kMinFrameRate; // Seconds.
@@ -99,6 +99,14 @@
// If someone has notified this thread, just forget about it
and
// continue on. It's not worth the cycles to handle.
}
+ } else {
+ // In the case where the thread took too long, let the thread
yield to
+ // other processes. This should usually only happen in the case
+ // something "big" is happening and we don't need / want to
starve the
+ // more important system threads.
+ try {
+ Thread.sleep(0); // Yield.
+ } catch (InterruptedException ex) {}
}
time_step = Math.max(time_step, kMinTimeStep);
time_step = Math.min(time_step, kMaxTimeStep);
@@ -113,6 +121,7 @@
graphics_.endFrame();
}
}
+ graphics_.destroy();
}
public void setGame(Game game) {
Modified: trunk/src/android/com/abb/Graphics.java
==============================================================================
--- trunk/src/android/com/abb/Graphics.java (original)
+++ trunk/src/android/com/abb/Graphics.java Tue Dec 23 23:57:21 2008
@@ -23,7 +23,6 @@
import android.opengl.GLUtils;
import android.util.Log;
import android.view.SurfaceHolder;
-
import java.io.PrintWriter;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
@@ -59,7 +58,7 @@
surfaceChanged(
surface_holder, surface_frame.width(), surface_frame.height());
- switch (backend_type_) {
+ switch (mBackendType) {
case ANDROID2D:
Log.d("Graphics::Initialize", "Initializing Android2D rendering.");
initializeAndroid2D();
@@ -73,23 +72,23 @@
public void surfaceChanged(SurfaceHolder surface_holder,
int width, int height) {
- surface_holder_ = surface_holder;
- surface_width_ = width;
- surface_height_ = height;
- Log.d("Graphics::SurfaceChanged",
- "Size = " + surface_width_ + "x" + surface_height_ + ".");
+ mSurfaceHolder = surface_holder;
+ mSurfaceWidth = width;
+ mSurfaceHeight = height;
+ Log.d("Graphics::surfaceChanged",
+ "Size = " + mSurfaceWidth + "x" + mSurfaceHeight + ".");
- switch (backend_type_) {
+ switch (mBackendType) {
case ANDROID2D:
break; // Don't care.
case OPENGL:
- gl_surface_initialized_ = false;
+ mGlSurfaceInitialized = false;
break;
}
}
public void destroy() {
- switch (backend_type_) {
+ switch (mBackendType) {
case ANDROID2D:
break; // Don't care.
case OPENGL:
@@ -99,7 +98,7 @@
}
public int getWidth() {
- switch (backend_type_) {
+ switch (mBackendType) {
case ANDROID2D:
return getWidthAndroid2D();
case OPENGL:
@@ -109,7 +108,7 @@
}
public int getHeight() {
- switch (backend_type_) {
+ switch (mBackendType) {
case ANDROID2D:
return getHeightAndroid2D();
case OPENGL:
@@ -125,7 +124,7 @@
Assert.assertNotNull(
"Null bitmap specified in LoadImageFromBitmap", bitmap);
- switch (backend_type_) {
+ switch (mBackendType) {
case ANDROID2D:
return loadImageFromBitmapAndroid2D(bitmap);
case OPENGL:
@@ -135,7 +134,7 @@
}
public void freeImage(int image_handle) {
- switch (backend_type_) {
+ switch (mBackendType) {
case ANDROID2D:
freeImageAndroid2D(image_handle);
break;
@@ -149,7 +148,7 @@
boolean flipped_horizontal, boolean
flipped_vertical) {
Assert.assertTrue("Invalid image handle in drawImage", image_handle >=
0);
- switch (backend_type_) {
+ switch (mBackendType) {
case ANDROID2D:
drawImageAndroid2D(image_handle, source_rect, dest_rect,
flipped_horizontal, flipped_vertical);
@@ -165,7 +164,7 @@
boolean flipped_horizontal, boolean
flipped_vertical) {
Assert.assertTrue("Invalid image handle in drawImage", image_handle >=
0);
- switch (backend_type_) {
+ switch (mBackendType) {
case ANDROID2D:
drawImageAndroid2D(image_handle, source_rect, dest_matrix,
flipped_horizontal, flipped_vertical);
@@ -178,7 +177,7 @@
}
public void beginFrame() {
- switch (backend_type_) {
+ switch (mBackendType) {
case ANDROID2D:
beginFrameAndroid2D();
break;
@@ -189,7 +188,7 @@
}
public void endFrame() {
- switch (backend_type_) {
+ switch (mBackendType) {
case ANDROID2D:
endFrameAndroid2D();
break;
@@ -199,57 +198,65 @@
}
}
+ public boolean hasHardwareAcceleration() {
+ return mHasHardwareAcceleration;
+ }
+
/**
* Private shared methods and state.
*/
void determineBackendType() {
- // Determine which rendering backend to use based off of the system
setup,
+ // Determine which rendering back-end to use based off of the system
setup,
// specifically the presence of rendering hardware. OpenGL appears to
be
// faster on both the Emulator and the HTC Dream handset than the
Android2D
- // back end.
- backend_type_ = BackendType.OPENGL;
+ // back end. The software OpenGL rasterizer is faster than the
Android2D
+ // graphics API so it should be preferred in nearly all situations.
However,
+ // when using either software back-end, pixel fill rate has been
+ // experimentally been shown to be bottleneck.
+ mBackendType = BackendType.OPENGL;
}
private enum BackendType { ANDROID2D, OPENGL }
- private BackendType backend_type_;
- private SurfaceHolder surface_holder_;
- private int surface_height_;
- private int surface_width_;
+ private BackendType mBackendType;
+ private SurfaceHolder mSurfaceHolder;
+ private int mSurfaceHeight;
+ private int mSurfaceWidth;
/**
* Private Android 2D backend methods and state.
*/
private void initializeAndroid2D() {
- surface_holder_.setType(SurfaceHolder.SURFACE_TYPE_HARDWARE);
+ mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_HARDWARE);
}
private int loadImageFromBitmapAndroid2D(Bitmap bitmap) {
- images_android2D_.add(bitmap);
- return images_android2D_.size();
+ mImagesAndroid2D.add(bitmap);
+ return mImagesAndroid2D.size();
}
private void freeImageAndroid2D(int image_handle) {
- if (image_handle >= 1)
- images_android2D_.set(image_handle - 1, null);
+ if (image_handle >= 1) {
+ mImagesAndroid2D.set(image_handle - 1, null);
+ }
}
private int getWidthAndroid2D() {
- return surface_width_;
+ return mSurfaceWidth;
}
private int getHeightAndroid2D() {
- return surface_height_;
+ return mSurfaceHeight;
}
private void beginFrameAndroid2D() {
- canvas_android2D_ = surface_holder_.lockCanvas(null);
- canvas_android2D_.drawRGB(0, 0, 0);
+ mCanvasAndroid2D = mSurfaceHolder.lockCanvas(null);
+ mCanvasAndroid2D.drawRGB(0, 0, 0);
}
private void endFrameAndroid2D() {
- surface_holder_.unlockCanvasAndPost(canvas_android2D_);
+ mSurfaceHolder.unlockCanvasAndPost(mCanvasAndroid2D);
}
private void drawImageAndroid2D(int image_handle,
@@ -260,17 +267,17 @@
!flipped_vertical);
if (flipped_horizontal) {
- transformation_android2D_.setScale(-1.0f, 1.0f);
- transformation_android2D_.postTranslate(
+ mTransformationAndroid2D.setScale(-1.0f, 1.0f);
+ mTransformationAndroid2D.postTranslate(
2.0f * dest_rect.left + dest_rect.width(), 0.0f);
} else {
- transformation_android2D_.setScale(1.0f, 1.0f);
+ mTransformationAndroid2D.setScale(1.0f, 1.0f);
}
- Bitmap bitmap = images_android2D_.get(image_handle - 1);
- canvas_android2D_.setMatrix(transformation_android2D_);
- canvas_android2D_.drawBitmap(
- bitmap, source_rect, dest_rect, paint_android2D_);
+ Bitmap bitmap = mImagesAndroid2D.get(image_handle - 1);
+ mCanvasAndroid2D.setMatrix(mTransformationAndroid2D);
+ mCanvasAndroid2D.drawBitmap(
+ bitmap, source_rect, dest_rect, mPaintAndroid2D);
}
private void drawImageAndroid2D(int image_handle,
@@ -280,10 +287,10 @@
Assert.fail("Method not yet implemented.");
}
- private Canvas canvas_android2D_;
- private ArrayList<Bitmap> images_android2D_ = new ArrayList<Bitmap>();
- private Paint paint_android2D_ = new Paint();
- private Matrix transformation_android2D_ = new Matrix();
+ private Canvas mCanvasAndroid2D;
+ private ArrayList<Bitmap> mImagesAndroid2D = new ArrayList<Bitmap>();
+ private Paint mPaintAndroid2D = new Paint();
+ private Matrix mTransformationAndroid2D = new Matrix();
/**
* Private OpenGL backend methods and state.
@@ -294,12 +301,12 @@
//
http://java.sun.com/javame/reference/apis/jsr239/javax/microedition
// /khronos/opengles/GL10.html
- egl_ = (EGL10)EGLContext.getEGL();
- egl_display_ = egl_.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
+ mEgl = (EGL10)EGLContext.getEGL();
+ mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
// We can now initialize EGL for that display.
int[] version = new int[2];
- egl_.eglInitialize(egl_display_, version);
+ mEgl.eglInitialize(mEglDisplay, version);
Log.d("Graphics::initializeOpenGL",
"Found version: " + version[0] + "." + version[1]);
@@ -309,21 +316,21 @@
EGLConfig[] configs = new EGLConfig[1];
int[] num_config = new int[1];
- egl_.eglChooseConfig(egl_display_, attrib_list, configs, 1,
num_config);
- egl_config_ = configs[0];
- egl_context_ = egl_.eglCreateContext(
- egl_display_, egl_config_, EGL10.EGL_NO_CONTEXT, null);
- gl_ = (GL10)egl_context_.getGL();
+ mEgl.eglChooseConfig(mEglDisplay, attrib_list, configs, 1, num_config);
+ mEglConfig = configs[0];
+ mEglContext = mEgl.eglCreateContext(
+ mEglDisplay, mEglConfig, EGL10.EGL_NO_CONTEXT, null);
+ mGl = (GL10)mEglContext.getGL();
final boolean kEnableOpenGLDebugging = false;
if (kEnableOpenGLDebugging) {
int debugging_flags = (GLDebugHelper.CONFIG_LOG_ARGUMENT_NAMES |
GLDebugHelper.CONFIG_CHECK_THREAD |
GLDebugHelper.CONFIG_CHECK_GL_ERROR);
- egl_ = (EGL10)GLDebugHelper.wrap(
- egl_, debugging_flags, new PrintWriter(System.out));
- gl_ = (GL10)GLDebugHelper.wrap(
- gl_, debugging_flags, new PrintWriter(System.out));
+ mEgl = (EGL10)GLDebugHelper.wrap(
+ mEgl, debugging_flags, new PrintWriter(System.out));
+ mGl = (GL10)GLDebugHelper.wrap(
+ mGl, debugging_flags, new PrintWriter(System.out));
}
// Create a place holder surface so we can continue with
initialization.
@@ -335,26 +342,29 @@
/** Create a new rendering surface. This is indented to be called
whenever the
* window size changes, for example. */
private void initializeOpenGLSurface() {
- Log.d("Graphics::initializeOpenGLSurface", "Creating OpenGL surface.");
+ Log.d("Graphics::initializeOpenGLSurface", "Freeing old OpenGL
surface.");
- surface_holder_.setType(SurfaceHolder.SURFACE_TYPE_GPU);
+ mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_GPU);
- if (egl_surface_ != null) {
+ if (mEglSurface != null) {
// Unbind and destroy the old EGL surface, if there is one.
- egl_.eglMakeCurrent(egl_display_,
+ mEgl.eglMakeCurrent(mEglDisplay,
EGL10.EGL_NO_SURFACE,
EGL10.EGL_NO_SURFACE,
EGL10.EGL_NO_CONTEXT);
- egl_.eglDestroySurface(egl_display_, egl_surface_);
+ mEgl.eglDestroySurface(mEglDisplay, mEglSurface);
+ mEglSurface = null;
}
// Create an EGL surface we can render into.
- egl_surface_ = egl_.eglCreateWindowSurface(
- egl_display_, egl_config_, surface_holder_, null);
+ Log.d("Graphics::initializeOpenGLSurface", "Creating new OpenGL
surface.");
+ mEglSurface = mEgl.eglCreateWindowSurface(
+ mEglDisplay, mEglConfig, mSurfaceHolder, null);
// Before we can issue GL commands, we need to make sure the context is
// current and bound to a surface.
- egl_.eglMakeCurrent(egl_display_, egl_surface_, egl_surface_,
egl_context_);
+ Log.d("Graphics::initializeOpenGLSurface", "Updating OpenGL context.");
+ mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
mEglContext);
initializeOpenGLClientState();
}
@@ -362,17 +372,35 @@
private void initializeOpenGLClientState() {
Log.d("Graphics::initializeOpenGLClientState", "Setting up client
state.");
+ String gl_renderer = mGl.glGetString(GL10.GL_RENDERER);
+ Log.d("Graphics::initializeOpenGLClientState",
+ "Found renderer: " + gl_renderer);
+
+ // Default settings for unknown hardware considerations. We choose to
be on
+ // the save side with respect to performance considerations.
+ mHasHardwareAcceleration = false;
+
+ // Dream / G1.
+ if (gl_renderer.indexOf("Q3Dimension") != -1) {
+ mHasHardwareAcceleration = true;
+ }
+
+ // Emulator / Software drivers.
+ if (gl_renderer.indexOf("PixelFlinger") != -1) {
+ mHasHardwareAcceleration = false;
+ }
+
// Initialize the orthographic projection within our surface. This must
// happen whenever the surface size changes.
- gl_.glViewport(0, 0, getWidthOpenGL(), getHeightOpenGL());
- gl_.glMatrixMode(GL10.GL_PROJECTION);
- gl_.glLoadIdentity();
- gl_.glOrthof(0, getWidthOpenGL(), 0, getHeightOpenGL(), -1, 1);
+ mGl.glViewport(0, 0, getWidthOpenGL(), getHeightOpenGL());
+ mGl.glMatrixMode(GL10.GL_PROJECTION);
+ mGl.glLoadIdentity();
+ mGl.glOrthof(0, getWidthOpenGL(), 0, getHeightOpenGL(), -1, 1);
// Since we will only be rendering quads, set up a shared vertex and
texture
// coordinate array. The following is so convoluted I really wonder if
this
// is right of if the Java / OpenGL ES folks need their heads examined.
- float[] corner_array = { 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1 };
+ float[] corner_array = { 0, 0, 1, 0, 1, 1, 0, 1 };
ByteBuffer corner_byte_buffer =
ByteBuffer.allocateDirect(4 * corner_array.length);
corner_byte_buffer.order(ByteOrder.nativeOrder());
@@ -380,44 +408,46 @@
corner_float_buffer.put(corner_array);
corner_float_buffer.position(0);
- gl_.glVertexPointer(2, GL10.GL_FLOAT, 0, corner_float_buffer);
- gl_.glEnableClientState(GL10.GL_VERTEX_ARRAY);
- gl_.glTexCoordPointer(2, GL10.GL_FLOAT, 0, corner_float_buffer);
- gl_.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
+ mGl.glVertexPointer(2, GL10.GL_FLOAT, 0, corner_float_buffer);
+ mGl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
+ mGl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, corner_float_buffer);
+ mGl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
// OpenGL rendering state configuration.
- gl_.glEnable(GL10.GL_TEXTURE_2D);
- gl_.glDisable(GL10.GL_CULL_FACE);
- gl_.glDisable(GL10.GL_DEPTH_TEST);
- gl_.glEnable(GL10.GL_BLEND);
- gl_.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
- gl_.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
- gl_.glDisable(GL10.GL_ALPHA_TEST);
+ mGl.glEnable(GL10.GL_TEXTURE_2D);
+ mGl.glDisable(GL10.GL_CULL_FACE);
+ mGl.glDisable(GL10.GL_DEPTH_TEST);
+ mGl.glEnable(GL10.GL_BLEND);
+ mGl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+ mGl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
+ mGl.glDisable(GL10.GL_ALPHA_TEST);
}
private void destroyOpenGL() {
- if (egl_surface_ != null) {
- egl_.eglMakeCurrent(egl_display_,
+ Log.d("Graphics::destroyOpenGL", "Destroying open gl.");
+
+ if (mEglSurface != null) {
+ mEgl.eglMakeCurrent(mEglDisplay,
EGL10.EGL_NO_SURFACE,
EGL10.EGL_NO_SURFACE,
EGL10.EGL_NO_CONTEXT);
- egl_.eglDestroySurface(egl_display_, egl_surface_);
- egl_surface_ = null;
+ mEgl.eglDestroySurface(mEglDisplay, mEglSurface);
+ mEglSurface = null;
}
- if (egl_context_ != null) {
- egl_.eglDestroyContext(egl_display_, egl_context_);
- egl_context_ = null;
- }
- if (egl_display_ != null) {
- egl_.eglTerminate(egl_display_);
- egl_display_ = null;
+ if (mEglContext != null) {
+ mEgl.eglDestroyContext(mEglDisplay, mEglContext);
+ mEglContext = null;
+ }
+ if (mEglDisplay != null) {
+ mEgl.eglTerminate(mEglDisplay);
+ mEglDisplay = null;
}
}
private int loadImageFromBitmapOpenGL(Bitmap bitmap) {
// Allocate a texture handle within the OpenGL context.
int[] texture_names = new int[1];
- gl_.glGenTextures(1, texture_names, 0);
+ mGl.glGenTextures(1, texture_names, 0);
int texture_name = texture_names[0];
Log.d("Graphics::loadImageFromBitmapOpenGL",
"Allocated texture handle: " + texture_name);
@@ -436,8 +466,8 @@
((0x000000FF & pixel) << 16)); // Blue.
}
IntBuffer bitmap_data_buffer = IntBuffer.wrap(bitmap_data);
- gl_.glBindTexture(GL10.GL_TEXTURE_2D, texture_name);
- gl_.glTexImage2D(GL10.GL_TEXTURE_2D,
+ mGl.glBindTexture(GL10.GL_TEXTURE_2D, texture_name);
+ mGl.glTexImage2D(GL10.GL_TEXTURE_2D,
0, // Mipmap level.
GL10.GL_RGBA, // Internal format.
bitmap.getWidth(),
@@ -446,22 +476,24 @@
GL10.GL_RGBA, // Format.
GL10.GL_UNSIGNED_BYTE,
bitmap_data_buffer);
- gl_.glTexParameterf(GL10.GL_TEXTURE_2D,
- GL10.GL_TEXTURE_MIN_FILTER,
- GL10.GL_NEAREST);
- gl_.glTexParameterf(GL10.GL_TEXTURE_2D,
- GL10.GL_TEXTURE_MAG_FILTER,
- GL10.GL_NEAREST);
+ mGl.glTexParameterf(GL10.GL_TEXTURE_2D,
+ GL10.GL_TEXTURE_MIN_FILTER,
+ GL10.GL_NEAREST);
+ mGl.glTexParameterf(GL10.GL_TEXTURE_2D,
+ GL10.GL_TEXTURE_MAG_FILTER,
+ GL10.GL_NEAREST);
// The size must be manually stored for retrieval during the rendering
// process since the texture coordinate scheme under OpenGL is
normalized
// where as under the Android2D back end, texture coordinates are
absolute.
- if (texture_widths_.size() <= texture_name)
- texture_widths_.setSize(texture_name + 1);
- if (texture_heights_.size() <= texture_name)
- texture_heights_.setSize(texture_name + 1);
- texture_widths_.set(texture_name, bitmap.getWidth());
- texture_heights_.set(texture_name, bitmap.getHeight());
+ if (mTextureWidths.size() <= texture_name) {
+ mTextureWidths.setSize(texture_name + 1);
+ }
+ if (mTextureHeights.size() <= texture_name) {
+ mTextureHeights.setSize(texture_name + 1);
+ }
+ mTextureWidths.set(texture_name, bitmap.getWidth());
+ mTextureHeights.set(texture_name, bitmap.getHeight());
return texture_name;
}
@@ -470,153 +502,155 @@
}
private int getWidthOpenGL() {
- return surface_width_;
+ return mSurfaceWidth;
}
private int getHeightOpenGL() {
- return surface_height_;
+ return mSurfaceHeight;
}
private void drawImageOpenGL(int image_handle,
Rect source_rect, RectF dest_rect,
boolean flipped_horizontal,
boolean flipped_vertical) {
- if (image_handle != current_texture_) {
- current_texture_ = image_handle;
- gl_.glBindTexture(GL10.GL_TEXTURE_2D, image_handle);
+ if (image_handle != mCurrentTexture) {
+ mCurrentTexture = image_handle;
+ mGl.glBindTexture(GL10.GL_TEXTURE_2D, image_handle);
}
// The vertex and texture coordinate arrays have already been
initialized.
// All that is left is to set up the texture and model view
transformation
// matrices and render. Note that the OpenGL API expects matrices with
a
// column-major layout.
- float texture_width = texture_widths_.get(image_handle);
- float texture_height = texture_heights_.get(image_handle);
+ float texture_width = mTextureWidths.get(image_handle);
+ float texture_height = mTextureHeights.get(image_handle);
- matrix4x4_[1] = matrix4x4_[2] = matrix4x4_[4] =
- matrix4x4_[6] = matrix4x4_[8] = matrix4x4_[9] = 0.0f;
+ mMatrix4x4[1] = mMatrix4x4[2] = mMatrix4x4[4] =
+ mMatrix4x4[6] = mMatrix4x4[8] = mMatrix4x4[9] = 0.0f;
if (flipped_vertical) {
- matrix4x4_[5] = (source_rect.top - source_rect.bottom) /
texture_height;
- matrix4x4_[13] = source_rect.bottom / texture_height;
+ mMatrix4x4[5] = (source_rect.top - source_rect.bottom) /
texture_height;
+ mMatrix4x4[13] = source_rect.bottom / texture_height;
} else {
- matrix4x4_[5] = (source_rect.bottom - source_rect.top) /
texture_height;
- matrix4x4_[13] = source_rect.top / texture_height;
+ mMatrix4x4[5] = (source_rect.bottom - source_rect.top) /
texture_height;
+ mMatrix4x4[13] = source_rect.top / texture_height;
}
if (flipped_horizontal) {
- matrix4x4_[0] = (source_rect.left - source_rect.right) /
texture_width;
- matrix4x4_[12] = source_rect.right / texture_width;
+ mMatrix4x4[0] = (source_rect.left - source_rect.right) /
texture_width;
+ mMatrix4x4[12] = source_rect.right / texture_width;
} else {
- matrix4x4_[0] = (source_rect.right - source_rect.left) /
texture_width;
- matrix4x4_[12] = source_rect.left / texture_width;
+ mMatrix4x4[0] = (source_rect.right - source_rect.left) /
texture_width;
+ mMatrix4x4[12] = source_rect.left / texture_width;
}
- gl_.glMatrixMode(GL10.GL_TEXTURE);
- gl_.glLoadMatrixf(matrix4x4_, 0);
+ mGl.glMatrixMode(GL10.GL_TEXTURE);
+ mGl.glLoadMatrixf(mMatrix4x4, 0);
- matrix4x4_[0] = dest_rect.right - dest_rect.left;
- matrix4x4_[5] = dest_rect.top - dest_rect.bottom;
- matrix4x4_[12] = dest_rect.left;
- matrix4x4_[13] = surface_height_ - dest_rect.top;
- gl_.glMatrixMode(GL10.GL_MODELVIEW);
- gl_.glLoadMatrixf(matrix4x4_, 0);
+ mMatrix4x4[0] = dest_rect.right - dest_rect.left;
+ mMatrix4x4[5] = dest_rect.top - dest_rect.bottom;
+ mMatrix4x4[12] = dest_rect.left;
+ mMatrix4x4[13] = mSurfaceHeight - dest_rect.top;
+ mGl.glMatrixMode(GL10.GL_MODELVIEW);
+ mGl.glLoadMatrixf(mMatrix4x4, 0);
- gl_.glDrawArrays(GL10.GL_TRIANGLES, 0, 6);
+ mGl.glDrawArrays(GL10.GL_TRIANGLE_FAN, 0, 4);
}
private void drawImageOpenGL(int image_handle,
Rect source_rect, Matrix dest_matrix,
boolean flipped_horizontal,
boolean flipped_vertical) {
- if (image_handle != current_texture_) {
- current_texture_ = image_handle;
- gl_.glBindTexture(GL10.GL_TEXTURE_2D, image_handle);
+ if (image_handle != mCurrentTexture) {
+ mCurrentTexture = image_handle;
+ mGl.glBindTexture(GL10.GL_TEXTURE_2D, image_handle);
}
// The vertex and texture coordinate arrays have already been
initialized.
// All that is left is to set up the texture and model view
transformation
// matrices and render. Note that the OpenGL API expects matrices with
a
// column-major layout.
- float texture_width = texture_widths_.get(image_handle);
- float texture_height = texture_heights_.get(image_handle);
+ float texture_width = mTextureWidths.get(image_handle);
+ float texture_height = mTextureHeights.get(image_handle);
- matrix4x4_[1] = matrix4x4_[2] = matrix4x4_[4] =
- matrix4x4_[6] = matrix4x4_[8] = matrix4x4_[9] = 0.0f;
+ mMatrix4x4[1] = mMatrix4x4[2] = mMatrix4x4[4] =
+ mMatrix4x4[6] = mMatrix4x4[8] = mMatrix4x4[9] = 0.0f;
if (flipped_vertical) {
- matrix4x4_[5] = (source_rect.top - source_rect.bottom) /
texture_height;
- matrix4x4_[13] = source_rect.bottom / texture_height;
+ mMatrix4x4[5] = (source_rect.top - source_rect.bottom) /
texture_height;
+ mMatrix4x4[13] = source_rect.bottom / texture_height;
} else {
- matrix4x4_[5] = (source_rect.bottom - source_rect.top) /
texture_height;
- matrix4x4_[13] = source_rect.top / texture_height;
+ mMatrix4x4[5] = (source_rect.bottom - source_rect.top) /
texture_height;
+ mMatrix4x4[13] = source_rect.top / texture_height;
}
if (flipped_horizontal) {
- matrix4x4_[0] = (source_rect.left - source_rect.right) /
texture_width;
- matrix4x4_[12] = source_rect.right / texture_width;
+ mMatrix4x4[0] = (source_rect.left - source_rect.right) /
texture_width;
+ mMatrix4x4[12] = source_rect.right / texture_width;
} else {
- matrix4x4_[0] = (source_rect.right - source_rect.left) /
texture_width;
- matrix4x4_[12] = source_rect.left / texture_width;
+ mMatrix4x4[0] = (source_rect.right - source_rect.left) /
texture_width;
+ mMatrix4x4[12] = source_rect.left / texture_width;
}
- gl_.glMatrixMode(GL10.GL_TEXTURE);
- gl_.glLoadMatrixf(matrix4x4_, 0);
+ mGl.glMatrixMode(GL10.GL_TEXTURE);
+ mGl.glLoadMatrixf(mMatrix4x4, 0);
- screen_matrix_ = new Matrix();
- screen_matrix_.preTranslate(0.0f, surface_height_);
- screen_matrix_.preScale(1.0f, -1.0f);
- screen_matrix_.preConcat(dest_matrix);
- screen_matrix_.getValues(matrix3x3_);
- matrix4x4_[0] = matrix3x3_[0];
- matrix4x4_[1] = matrix3x3_[3];
- matrix4x4_[2] = matrix3x3_[6];
- matrix4x4_[4] = matrix3x3_[1];
- matrix4x4_[5] = matrix3x3_[4];
- matrix4x4_[6] = matrix3x3_[6];
- matrix4x4_[12] = matrix3x3_[2];
- matrix4x4_[13] = matrix3x3_[5];
- gl_.glMatrixMode(GL10.GL_MODELVIEW);
- gl_.glLoadMatrixf(matrix4x4_, 0);
+ mScreenMatrix.reset();
+ mScreenMatrix.preTranslate(0.0f, mSurfaceHeight);
+ mScreenMatrix.preScale(1.0f, -1.0f);
+ mScreenMatrix.preConcat(dest_matrix);
+ mScreenMatrix.getValues(mMatrix3x3);
+ mMatrix4x4[0] = mMatrix3x3[0];
+ mMatrix4x4[1] = mMatrix3x3[3];
+ mMatrix4x4[2] = mMatrix3x3[6];
+ mMatrix4x4[4] = mMatrix3x3[1];
+ mMatrix4x4[5] = mMatrix3x3[4];
+ mMatrix4x4[6] = mMatrix3x3[6];
+ mMatrix4x4[12] = mMatrix3x3[2];
+ mMatrix4x4[13] = mMatrix3x3[5];
+ mGl.glMatrixMode(GL10.GL_MODELVIEW);
+ mGl.glLoadMatrixf(mMatrix4x4, 0);
- gl_.glDrawArrays(GL10.GL_TRIANGLES, 0, 6);
+ mGl.glDrawArrays(GL10.GL_TRIANGLE_FAN, 0, 4);
}
private void beginFrameOpenGL() {
- if (!gl_surface_initialized_) {
+ if (!mGlSurfaceInitialized) {
initializeOpenGLSurface();
- gl_surface_initialized_ = true;
+ mGlSurfaceInitialized = true;
}
- if (!gl_state_initialized_) {
+ if (!mGlStateInitialized) {
initializeOpenGLClientState();
- gl_state_initialized_ = true;
+ mGlStateInitialized = true;
}
- gl_.glClear(GL10.GL_COLOR_BUFFER_BIT);
+ mGl.glClear(GL10.GL_COLOR_BUFFER_BIT);
}
private void endFrameOpenGL() {
- egl_.eglSwapBuffers(egl_display_, egl_surface_);
+ mEgl.eglSwapBuffers(mEglDisplay, mEglSurface);
// Always check for EGL_CONTEXT_LOST, which means the context and all
// associated data were lost (For instance because the device went to
// sleep). We need to sleep until we get a new surface.
- if (egl_.eglGetError() == EGL11.EGL_CONTEXT_LOST)
+ if (mEgl.eglGetError() == EGL11.EGL_CONTEXT_LOST) {
Log.d("Graphics::endFrameBufferOpenGL", "Context Lost.");
+ }
}
- private int current_texture_ = -1;
- private Vector<Integer> texture_widths_ = new Vector<Integer>();
- private Vector<Integer> texture_heights_ = new Vector<Integer>();
- private EGL10 egl_;
- private EGLConfig egl_config_;
- private EGLContext egl_context_;
- private EGLDisplay egl_display_;
- private EGLSurface egl_surface_;
- private GL10 gl_;
- private boolean gl_state_initialized_ = false;
- private boolean gl_surface_initialized_ = false;
+ private int mCurrentTexture = -1;
+ private Vector<Integer> mTextureWidths = new Vector<Integer>();
+ private Vector<Integer> mTextureHeights = new Vector<Integer>();
+ private EGL10 mEgl;
+ private EGLConfig mEglConfig;
+ private EGLContext mEglContext;
+ private EGLDisplay mEglDisplay;
+ private EGLSurface mEglSurface;
+ private GL10 mGl;
+ private boolean mGlStateInitialized = false;
+ private boolean mGlSurfaceInitialized = false;
+ private boolean mHasHardwareAcceleration = false;
// The following matrix definitions are used to avoid any allocations
within
// the draw methods.
- private Matrix screen_matrix_ = new Matrix();
- private float[] matrix3x3_ = new float[] {
+ private Matrix mScreenMatrix = new Matrix();
+ private float[] mMatrix3x3 = new float[] {
1, 0, 0, 0, 1, 0, 0, 0, 1 };
- private float[] matrix4x4_ = new float[] {
+ private float[] mMatrix4x4 = new float[] {
1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 };
}
Modified: trunk/src/android/com/abb/Map.java
==============================================================================
--- trunk/src/android/com/abb/Map.java (original)
+++ trunk/src/android/com/abb/Map.java Tue Dec 23 23:57:21 2008
@@ -29,15 +29,8 @@
import java.util.Random;
import junit.framework.Assert;
-import android.com.abb.Content;
-import android.com.abb.Entity;
-import android.com.abb.GameState;
-
public class Map {
- public float starting_x;
- public float starting_y;
-
public Map(GameState game_state) {
mGameState = game_state;
}
@@ -168,8 +161,8 @@
mTiles = tiles;
for (int n = 0; n < kMapWidth * kMapHeight; ++n) {
if (mTiles[n] == kStartingTile) {
- starting_x = (n / kMapWidth) * kTileSize;
- starting_y = (n % kMapWidth) * kTileSize;
+ mStartingX = (n / kMapWidth) * kTileSize;
+ mStartingY = (n % kMapWidth) * kTileSize;
}
}
}
@@ -196,14 +189,18 @@
return mTiles[tile_index];
}
- public static boolean tileIsEnemy(int tile_id) {
- return (tile_id == 12);
- }
-
public static boolean tileIsGoal(int tile_id) {
return (tile_id == kEndingTile);
}
+ public float getStartingX() {
+ return mStartingX;
+ }
+
+ public float getStartingY() {
+ return mStartingY;
+ }
+
public void collideEntity(Entity entity) {
if (entity.radius <= 0) {
return; // Collision disabled for this entity.
@@ -324,13 +321,15 @@
* the tile, eg. (0, 0) is the center of the first tile. */
public void draw(Graphics graphics, float center_x, float center_y,
float zoom) {
- // Load the images if it hasn't been done already.
+ // Load the textures required for rending here, in the primary thread,
since
+ // the OpenGL backend requires that all calls be from the same thread
which
+ // initialized it.
if (mTilesBitmap != null) {
graphics.freeImage(mTilesImage);
mTilesImage = graphics.loadImageFromBitmap(mTilesBitmap);
mTilesBitmap = null;
}
- if (mBackgroundBitmap != null) {
+ if (graphics.hasHardwareAcceleration() && mBackgroundBitmap != null) {
graphics.freeImage(mBackgroundImage);
mBackgroundImage = graphics.loadImageFromBitmap(mBackgroundBitmap);
mBackgroundBitmap = null;
@@ -339,7 +338,7 @@
// Draw background.
int canvas_width = graphics.getWidth();
int canvas_height = graphics.getHeight();
- if (mBackgroundImage != -1) {
+ if (graphics.hasHardwareAcceleration() && mBackgroundImage != -1) {
float scaled_background_size = kBackgroundScale * kBackgroundSize;
Rect background_src = new Rect(0, 0, kBackgroundSize,
kBackgroundSize);
RectF background_dst = new RectF(
@@ -353,6 +352,8 @@
}
// Draw tiles.
+ Rect source_rect = new Rect(0, 0, kTileSize, kTileSize);
+ RectF destination_rect = new RectF();
int half_canvas_width = canvas_width / 2;
int half_canvas_height = canvas_height / 2;
float x_min = center_x - half_canvas_width / zoom;
@@ -365,29 +366,31 @@
int tile_id = tileAt(x, y);
// Spawn enemies if we happen to pass over an enemy tile.
- if (tileIsEnemy(tile_id)) {
+ // TODO(burkhart): Check for more general "triggers" within tiles
+ // instead of hard coding an special enemy tile id.
+ if (tile_id == 12) {
mGameState.createEnemy(x, y);
setTileAt(x, y, (char)0); // Clear the tile.
+ continue;
}
- if (tile_id == 0 || tile_id == 12) {
+ if (tile_id == 0) {
continue; // Not a visual tile.
}
int index_x = (int)(x / kTileSize + 0.5f);
int index_y = (int)(y / kTileSize + 0.5f);
- Rect tile_source = new Rect(
- 0, kTileSize * tile_id,
- kTileSize, kTileSize * tile_id + kTileSize);
- RectF tile_destination = new RectF(
- kTileSize * index_x * zoom, kTileSize * index_y * zoom,
- (kTileSize * index_x + kTileSize) * zoom,
- (kTileSize * index_y + kTileSize) * zoom);
- tile_destination.offset(
+ source_rect.top = kTileSize * tile_id;
+ source_rect.bottom = kTileSize * tile_id + kTileSize;
+ destination_rect.left = kTileSize * index_x * zoom;
+ destination_rect.top = kTileSize * index_y * zoom;
+ destination_rect.right = (kTileSize * index_x + kTileSize) * zoom;
+ destination_rect.bottom = (kTileSize * index_y + kTileSize) * zoom;
+ destination_rect.offset(
-center_x * zoom + half_canvas_width - kTileSize / 2 * zoom,
-center_y * zoom + half_canvas_height - kTileSize / 2 * zoom);
graphics.drawImage(
- mTilesImage, tile_source, tile_destination, false, false);
+ mTilesImage, source_rect, destination_rect, false, false);
}
}
}
@@ -414,6 +417,8 @@
private GameState mGameState;
private int mLevelOffset = 0; // Level within the mBaseUri package.
private Random mRandom = new Random();
+ private float mStartingX;
+ private float mStartingY;
private char[] mTiles;
private Bitmap mTilesBitmap;
private int mTilesImage = -1;
Modified: trunk/src/android/com/abb/MapSelectActivity.java
==============================================================================
--- trunk/src/android/com/abb/MapSelectActivity.java (original)
+++ trunk/src/android/com/abb/MapSelectActivity.java Tue Dec 23 23:57:21
2008
@@ -36,7 +36,7 @@
super.onCreate(savedInstanceState);
loadMaps();
- String[] maps = maps_.toArray(new String[0]);
+ String[] maps = mMaps.toArray(new String[0]);
int item_layout_id = R.layout.mapselect_item;
setListAdapter(new ArrayAdapter<String>(this, item_layout_id, maps));
@@ -46,14 +46,14 @@
@Override
protected void onListItemClick(ListView l, View v, int position, long
id) {
Intent intent = new Intent(Intent.ACTION_VIEW,
- Uri.parse(map_uris_.get(position)),
+ Uri.parse(mMapUris.get(position)),
this, AlienBloodBathMain.class);
setResult(RESULT_OK, intent);
finish();
}
private void unzipMapPackages() {
- for (String root_path : paths_) {
+ for (String root_path : mSearchPaths) {
String[] files = (new File(root_path)).list();
if (files == null) {
continue;
@@ -106,27 +106,28 @@
unzipMapPackages();
// Add maps located within files.
- for (String root_path : paths_) {
+ for (String root_path : mSearchPaths) {
Log.d("MapSelectActivity::LoadMaps", "Listing " + root_path);
String[] map_paths = Content.list(Uri.parse(root_path));
- if (map_paths == null)
+ if (map_paths == null) {
continue;
+ }
for (String map_path : map_paths) {
String full_path = root_path + map_path;
Log.d("MapSelectActivity::LoadMaps",
"Looking for level_0.txt in " + full_path);
if (Content.exists(Uri.parse(full_path + "level_0.txt"))) {
- maps_.add(full_path);
- map_uris_.add(full_path);
+ mMaps.add(full_path);
+ mMapUris.add(full_path);
}
}
}
}
- private ArrayList<String> maps_ = new ArrayList<String>();
- private ArrayList<String> map_uris_ = new ArrayList<String>();
- private String[] paths_ = {
+ private ArrayList<String> mMaps = new ArrayList<String>();
+ private ArrayList<String> mMapUris = new ArrayList<String>();
+ private String[] mSearchPaths = {
"content:///",
"file:///sdcard/abb_maps/",
"file:///sdcard/" };
Modified: trunk/src/android/com/abb/Weapon.java
==============================================================================
--- trunk/src/android/com/abb/Weapon.java (original)
+++ trunk/src/android/com/abb/Weapon.java Tue Dec 23 23:57:21 2008
@@ -23,10 +23,6 @@
import java.util.Random;
import junit.framework.Assert;
-import android.com.abb.Avatar;
-import android.com.abb.Content;
-import android.com.abb.Entity;
-import android.com.abb.GameState;
public class Weapon extends Entity {
public Weapon(GameState game_state) {
@@ -55,7 +51,8 @@
mWeaponString = file_data.toString();
Log.d("Weapon String", mWeaponString);
} catch (IOException ex) {
- Assert.fail("Weapon::loadWeaponFromFile. Cannot find: " +
weapons_path + ".");
+ Assert.fail("Weapon::loadWeaponFromFile. " +
+ "Cannot find: " + weapons_path + ".");
}
}
@@ -70,7 +67,8 @@
Assert.fail("Weapon::loadWeaponImagesFromFile. Invalid argument.");
mWeaponsBitmap = BitmapFactory.decodeFile(weapon_images_path);
if (mWeaponsBitmap == null)
- Assert.fail("Weapon::loadWeaponImagesFromFile. Cannot find: " +
weapon_images_path + ".");
+ Assert.fail("Weapon::loadWeaponImagesFromFile. " +
+ "Cannot find: " + weapon_images_path + ".");
}
public void setImage(Graphics graphics) {
@@ -101,5 +99,4 @@
private float shotSpread = 15.0f * (float)Math.PI / 180.0f;
private float shotVelocity = 60.0f;
private static final int kSpriteSize = 64;
-
}