Android:About AndEngine updateThread and uiThread - java

I recently explore on AndEngine. I write a simple test demo, in which I implement IOnSceneTouchListener and the scene registers a TimerHandler to change one ChangableText.
And I set the engine runOnUpdateThread true.
So the problem is: when I touched the scene a while, the activity paused and crashed. And the Logcat showed the same text as before:"org.anddev.andengine.util.pool.PoolUpdateHandler$1 was exhausted, with 1 item not yet recycled. Allocated 1 more."
If anyone can solve my problem, so thankful I will be!
PS: my code
public class TestActivity extends BaseGameActivity implements IOnSceneTouchListener, IOnMenuItemClickListener {
...
...
private TimerHandler mTimeUpdateHandler = new TimerHandler(1.f, true, new ITimerCallback() {
#Override
public void onTimePassed(TimerHandler arg0) {
runOnUpdateThread(new Runnable() {
#Override
public void run() {
if (mElapsedText != null && mAttempts > 0) {
mElapsedText.setText("Time: "
+ (ParticlyActivity.this.mEngine.getSecondsElapsedTotal() - mCurrentTotalSeconds),
false);
}
}
});
}
});
...
...
// #Override
public Engine onLoadEngine() {
this.mCamera = new BoundCamera(0, 0, CAMERA_WIDTH, CAMERA_HEIGHT);
final EngineOptions engineOptions = new EngineOptions(true, ScreenOrientation.LANDSCAPE,
new RatioResolutionPolicy(CAMERA_WIDTH, CAMERA_HEIGHT), mCamera).setNeedsSound(true);
engineOptions.getTouchOptions().setRunOnUpdateThread(true);
this.mEngine = new Engine(engineOptions);
return this.mEngine;
}
public Scene onLoadScene(){
...
// Text
mElapsedText = new ChangeableText(20, 12, this.mFont, "Time:00.00");
mScene.getFirstChild().attachChild(mElapsedText);
mScene.registerUpdateHandler(mTimeUpdateHandler);
...
}
#Override
public boolean onSceneTouchEvent(final Scene pScene, final TouchEvent pSceneTouchEvent) {
if ((pSceneTouchEvent.isActionMove() || pSceneTouchEvent.isActionDown()) && mAttempts < MaxBullets) {
double angle = 0;
if ((pSceneTouchEvent.getX() - StartX) == 0) {
angle = 90;
} else {
angle = Math
.abs(Math.atan((StartY - pSceneTouchEvent.getY()) / (StartX - pSceneTouchEvent.getX())) / 3.14 * 180);
}
if (angle > 90) {
angle = 90;
} else if (angle < 0) {
angle = 0;
}
mGun.setRotation((float) -angle);
mGun.setStrength(pSceneTouchEvent.getX());
} else if (pSceneTouchEvent.isActionUp() && mAttempts < MaxBullets) {
...
}
}
return true;
}
}
TimerHandler:
private TimerHandler mTimeUpdateHandler = new TimerHandler(1.f, true, new ITimerCallback() {
#Override
public void onTimePassed(TimerHandler arg0) {
runOnUpdateThread(new Runnable() {
#Override
public void run() {
if (mElapsedText != null && mAttempts > 0) {
mElapsedText.setText("Time: " + (ParticlyActivity.this.mEngine.getSecondsElapsedTotal() - mCurrentTotalSeconds), false);
}
}
});
}
});

UIThread is the one responsible for drawing , UpdateThread gets executed every frame
if you need to change Text values , do that on the UpdateThread [just stay away from the UIThread in general]

Related

why applyLinearImpulse is not working, using libgdx?

I need some help when I try make a game, which is controlled by commands. I need to use textarea and I try to pass the value from textarea to contructer. But my game is not working. I know what mistake is appeared because I call contructer 2 times. I add some code:
public class inputs extends Game implements Disposable {
private Skin skin;
private Viewport viewport;
public Stage stage;
private Table table;
private TextButton button;
public TextArea TF;
private Main game;
public SpriteBatch spriteBatch;
public inputs(final SpriteBatch sb, final Main game){
viewport = new FitViewport(1200, 624, new OrthographicCamera());
stage = new Stage(viewport, sb);
skin = new Skin(Gdx.files.internal("data/uiskin.json"));
button = new TextButton("Send", skin, "default");
TF = new TextArea("", skin);
TF.setWidth(300);
TF.setHeight(570);
TF.setPosition(0,54);
button.setWidth(300);
button.setHeight(54);
button.setPosition(0, 0);
button.addListener(new ClickListener(){
#Override
public void clicked(InputEvent event, float x, float y) {
spriteBatch = new SpriteBatch();
setScreen(new MainCodeProgram(game,TF.getText(),spriteBatch));
TF.setText("");
button.setTouchable(Touchable.disabled);
}
});
stage.addActor(TF);
stage.addActor(button);
Gdx.input.setInputProcessor(stage);
Gdx.input.setInputProcessor(stage);
}
public void setButtonTouchable(){
button.setTouchable(Touchable.enabled);
}
#Override
public void create() {
}
#Override
public void dispose() {
stage.dispose();
}
}
Main.java :
public class Main extends Game {
public SpriteBatch spriteBatch;
public static int Width = 400;
public static int Height = 208;
public static final short objectwhit = 32;
public static final short mariowhit= 2;
public static final short itemwhit = 256;
public static float PPM = 100;
public static final short marioheadwhit = 512;
public static final short blockwhit = 4;
public static final short coinwhit = 8;
public static final short nothing = 0;
public static final short ground = 1;
public static final short destroyedwhit = 16;
public static final short enemywhit = 64;
public static final short enemyheadwhit = 128;
public static inputs inp1;
#Override
public void create () {
spriteBatch = new SpriteBatch();
inp1 = new inputs(spriteBatch,this);
setScreen(new MainCodeProgram(this,null,spriteBatch));
}
#Override
public void dispose() {
super.dispose();
spriteBatch.dispose();
}
}
Pseudocode recognize :
public class MainCodeProgram extends JFrame implements Screen, TextInputListener, Disposable {
static ArrayList<String> firstintkint = new ArrayList<String>();
static ArrayList<Integer> firstintvalue = new ArrayList<Integer>(); //int
private Main game;
private OrthographicCamera orthographicCamera;
private TextureAtlas textureAtlas;
public static int whichlevel=1;
private Mario player;
public Stage stage;
private Hud hud;
private TmxMapLoader maploader;
private TiledMap tilemap;
static int walks = 0;
private OrthogonalTiledMapRenderer renderer;
private Viewport viewport;
private World world;
private Array<Item> items;
private LinkedBlockingQueue<ItemVector> itemstoSpawn;
String text="";
private Box2DDebugRenderer b2dr;
private OtherWorldCreator otherWorldCreator;
public String kodas;
public boolean b =false;
public MainCodeProgram(){
}
public MainCodeProgram(Main game, String text,SpriteBatch spriteBatch) {
if(text == null){
textureAtlas = new TextureAtlas("All.pack");
this.game= game;
orthographicCamera = new OrthographicCamera();
viewport = new FitViewport(Main.Width / Main.PPM, Main.Height / Main.PPM, orthographicCamera);
viewport.apply();
hud = new Hud(game.spriteBatch);
newlevel();
otherWorldCreator = new OtherWorldCreator(this);
player = new Mario( this);
world.setContactListener(new WorldContact());
items = new Array<Item>();
itemstoSpawn = new LinkedBlockingQueue<ItemVector>();
}
if(text != null){
b = true;
textureAtlas = new TextureAtlas("All.pack");
this.game= game;
orthographicCamera = new OrthographicCamera();
viewport = new FitViewport(Main.Width / Main.PPM, Main.Height / Main.PPM, orthographicCamera);
viewport.apply();
hud = new Hud(spriteBatch);
newlevel();
otherWorldCreator = new OtherWorldCreator(this);
player = new Mario( this);
world.setContactListener(new WorldContact());
items = new Array<Item>();
itemstoSpawn = new LinkedBlockingQueue<ItemVector>();
input(text);
}
}
public TextureAtlas getAtlas(){return textureAtlas;}
#Override
public void show() {}
int i = 0, kur = 1;
public void handleInput(float dt) {
if (player.currentstate!= Mario.State.died) {
;
}
}
public void spawnItem(ItemVector idef)
{
itemstoSpawn.add(idef);
}
public void handleSpawningItems(){
if(!itemstoSpawn.isEmpty())
{
ItemVector idef = itemstoSpawn.poll();
if(idef.type == Mushroom.class){items.add(new Mushroom(this, idef.position.x,idef.position.y));}
}
}
public void update(float dt)
{
handleInput(dt);
handleSpawningItems();
world.step(1 / 60f, 6, 2);
player.update(dt);
for (Enemy enemy: otherWorldCreator.getEbemies()) {
enemy.update(dt);
if(enemy.getX() < player.getX() + 224 / Main.PPM){enemy.b2body.setActive(true);}
}
for(Item item : items){item.update(dt);}
hud.refresh(dt);
if(player.currentstate!= Mario.State.died){orthographicCamera.position.x = player.b2body.getPosition().x;}
orthographicCamera.update();
renderer.setView(orthographicCamera);
}
public boolean gameOver()
{
if(player.currentstate== Mario.State.died && palyer.getStateTimer() > 3){return true;}
if(whichlevel== 5){return true;}
else if(player.getY() <0){return true;}
else{return false;}
}
public boolean Youwonn()
{
if(whichlevel==4){return true;}
else{return false;}
}
#Override
public void render(float delta) {
update(delta);
int k = 0;
Gdx.gl.glClearColor(0,0,0,1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
renderer.render();
b2dr.render(world, orthographicCamera.combined);
game.spriteBatch.setProjectionMatrix(orthographicCamera.combined);
game.spriteBatch.begin();
game.draw(game.spriteBatch);
for (Enemy enemy: otherWorldCreator.getEbemies())
enemy.draw(game.spriteBatch);
for(Item item : items)
item.draw(game.spriteBatch);
game.spriteBatch.end();
game.spriteBatch.setProjectionMatrix(hud.stage.getCamera().combined);
hud.stage.draw();
if(gameOver())
{
whichlevel= 1;
game.setScreen(new GameOverWorld(game));
dispose();
}
if ((player.getX() > 15 && whichlevel< 4)) {
whichlevel++;
if(whichlevel!=4){
game.setScreen(new MainCodeProgram(game,"",""));
dispose();
}
}
if (whichlevel==4)
{
game.setScreen(new WinWindow(game));
dispose();
}
Main.inp1.stage.draw();
}
#Override
public void resize(int width, int height) {viewport.update(width,height);}
public World getWorld(){ return world;}
public TiledMap getMap(){return tilemap;}
#Override
public void pause() {}
#Override
public void resume() {}
#Override
public void hide() {}
public void newlevel()
{
maploader = new TmxMapLoader();
if(whichlevel== 1){tilemap = maploader.load("mario1lvl.tmx");
}
if (whichlevel== 2){tilemap = maploader.load("mario2lvl.tmx");}
if (whichlevel== 3){tilemap = maploader.load("mario3lvl.tmx");}
if (whichlevel== 4){
game.setScreen(new WinWindow(game));}
renderer = new OrthogonalTiledMapRenderer(tilemap, 1 / Main.PPM);
orthographicCamera.position.set(viewport.getWorldWidth() / 2, viewport.getWorldHeight() / 2, 0);
world = new World(new Vector2(0, -10 ), true);
b2dr = new Box2DDebugRenderer();
}
#Override
public void dispose() {
tilemap.dispose();
renderer.dispose();
world.dispose();
b2dr.dispose();
hud.dispose();
}
public void input(String text) {
ArrayList<String> pseudocode = new ArrayList<String>();
this.text = text;
i = 0;
String str = text;
String split[] = str.split("/");
for (String spacebar : split) {
pseudocode.add(spacebar);
i = 0;
}
int foras = 0;
for (int i = 0;i < pseudocode.size(); i++) {
if(pseudocode.get(i).equals("jump")||pseudocode.get(i).equals("jump;")){jump();}
if(pseudocode.get(i).startsWith("int")){recognizeint(pseudocode.get(i));}
if(pseudocode.get(i).startsWith("for"))
{
recognizefor(pseudocode.get(i));
foras++;
}
if(pseudocode.get(i).startsWith("while")){ recognizewhile(pseudocode.get(i));}
if(pseudocode.get(i).endsWith("--")||pseudocode.get(i).endsWith("--;"))
{
if(foras == 0){minuminus(pseudocode.get(i));}
else{foras--;}
}
if(pseudocode.get(i).endsWith("++")||pseudocode.get(i).endsWith("++;"))
{
if(foras==0){plusplus(pseudocode.get(i));}
else{foras--;}
}
if(istheend){
walks = 0;
istheend = false;
}
}
}
#Override
public void canceled() {
}
public void jump()
{
if(istheend){
try {Thread.sleep(1*walks);
} catch (InterruptedException e) {e.printStackTrace();}}
else{try {Thread.sleep(50*walks);
} catch (InterruptedException e) {e.printStackTrace();}}
walks = 0;
if(player.b2body.getLinearVelocity().y == 0){
if(b == true) {
player.b2body.applyLinearImpulse(new Vector2(0, 4f), player.b2body.getWorldCenter(), true); //Mistake is here
}
}
else if(player.b2body.getLinearVelocity().y != 0){
try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}
player.b2body.applyLinearImpulse(new Vector2(0, 4f), player.b2body.getWorldCenter(), true);
}
}
}
Mistake is here:
public void jump()
{
if(istheend){
try {Thread.sleep(1*walks);
} catch (InterruptedException e) {e.printStackTrace();}}
else{try {Thread.sleep(50*walks);
} catch (InterruptedException e) {e.printStackTrace();}}
walks = 0;
if(player.b2body.getLinearVelocity().y == 0){
if(b == true) {
player.b2body.applyLinearImpulse(new Vector2(0, 4f), player.b2body.getWorldCenter(), true); //Mistake is here
}
}
else if(player.b2body.getLinearVelocity().y != 0){
try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}
player.b2body.applyLinearImpulse(new Vector2(0, 4f), player.b2body.getWorldCenter(), true);
}
}
Thank you very much for help
I believe your code it is a little confusing, for the ApplyLinearImpulse works in your HandleInput you send a command jump() and inside the Entity you make the jump() method and also to make the animation to join the b2body, with update(dt) method + getState() + getFrame().
Your jump() method should be simple like this
public void jump(){
if(currentState != State.Jumping){
b2body.applyLinearImpulse(new Vector2(0,4f), b2body.getWorldCenter(), true);
currentState=State.JUMPING
}
}
What should be stuck the applyLinearImpulse are the conditions you included. Try to remove it all and leave only the main stuff. Use also LOGS everywhere Gdx.app.log("MESSAGE:", "" + variable); and you can start seeing what is going in and out with your methods and variables, and find your mistake.
Also, if you would like to learn more and don't forget any detail regarding map / viewport / b2bodies, follow this tutorial that I use as my guide for B2Box (Youtube / Github), it is very quick and easy to follow and you are going to love use B2Box for everything :-) and also continue with LibGdx Framework developments.
Click here Youtube Tutorial.
Click here GitHub codes.
I hope it helps you.
Cheers!!

Why is my simple java2d Space Invaders game lagging?

I'm currently making a space invaders-esque game for my software engineering course. I've already got everything working that satisfies the requirements, so this isn't a 'solve my homework' kind of question. My problem is that the game will lag (at what seems like random times & intervals) to the point where it becomes too frustrating to play. Some things I think might be causing this - though I'm not positive - are as follows:
Problem with timer event every 10 ms (I doubt this because of the very limited resources required for this game).
Problem with collision detection (checking for collision with every visible enemy every 10 ms seems like it would take up a large chunk of resources)
Problem with repainting? This seems unlikely to me however...
#SuppressWarnings("serial")
public class SIpanel extends JPanel {
private SIpanel panel;
private Timer timer;
private int score, invaderPace, pulseRate, mysteryCount, distanceToEdge;
private ArrayList<SIthing> cast;
private ArrayList<SIinvader> invaders, dead;
private ArrayList<SImissile> missileBase, missileInvader;
private SIinvader[] bottomRow;
private SIbase base;
private Dimension panelDimension;
private SImystery mysteryShip;
private boolean gameOver, left, right, mysteryDirection, space, waveDirection;
private boolean runningTimer;
private Music sound;
private void pulse() {
pace();
processInputs();
if (gameOver) gameOver();
repaint();
}
private void pace() {
// IF invaders still live
if (!invaders.isEmpty()) {
invaderPace++;
// Switch back manager
if (distanceToEdge <= 10) {
switchBack();
pulseRate = (pulseRate >= 16) ? (int) (pulseRate*(0.8)) : pulseRate;
waveDirection = !waveDirection;
distanceToEdge = calculateDistanceToEdge();
}
// Move invaders left/right
else if (invaderPace >= pulseRate) {
invaderPace = 0;
distanceToEdge = calculateDistanceToEdge();
moveAI();
invadersFire();
if (!dead.isEmpty()) removeDead();
if (mysteryCount < 1) tryInitMysteryShip();
}
// All invaders are kill, create new wave
} else if (missileBase.isEmpty() && missileInvader.isEmpty() && !cast.contains(mysteryShip)) {
// System.out.println("New Wave!");
newWave();
}
// Every pace
if (!missileBase.isEmpty()) moveMissileBase();
// Every two paces
if (invaderPace % 2 == 0) {
if (!missileInvader.isEmpty()) moveMissileInvader();
if (mysteryCount > 0) moveMysteryShip();
}
}
private void processInputs() {
if (left) move(left);
if (right) move(!right);
if (space) fireMissile(base, true);
}
protected void fireMissile(SIship ship, boolean isBase) {
if(isBase && missileBase.isEmpty()) {
base.playSound();
SImissile m = new SImissile(ship.getX()+(ship.getWidth()/2), ship.getY()-(ship.getHeight()/4));
missileBase.add(m);
cast.add(m);
} else if (!isBase && missileInvader.size()<3) {
base.playSound();
SImissile m = new SImissile(ship.getX()+(ship.getWidth()/2), ship.getY()+(ship.getHeight()/4));
missileInvader.add(m);
cast.add(m);
}
}
private void newWave() {
pulseRate = 50;
int defaultY=60, defaultX=120, defaultWidth=30, defaultHeight=24;
for(int i=0; i<5; i++) {
for(int j=0; j<10; j++) {
if (i<1) invaders.add(new SItop((j*defaultWidth)+defaultX, (i*defaultHeight)+defaultY, defaultWidth, defaultHeight));
else if (i<3) invaders.add(new SImiddle((j*defaultWidth)+defaultX, (i*defaultHeight)+defaultY, defaultWidth, defaultHeight));
else if (i<5) invaders.add(new SIbottom((j*defaultWidth)+defaultX, (i*defaultHeight)+defaultY, defaultWidth, defaultHeight));
}
}
for (SIinvader s: invaders) {
cast.add(s);
}
if (!cast.contains(base)) {
cast.add(base);
}
bottomRow = getBottomRow();
}
private void tryInitMysteryShip() {
Random rand = new Random();
int x=rand.nextInt(1000);
if (x<=3) {
mysteryCount = 1;
if (rand.nextBoolean()) {
mysteryDirection = true;
}
if (mysteryDirection) {
mysteryShip = new SImystery(0, 60, 36, 18);
} else {
mysteryShip = new SImystery(480, 60, 36, 18);
}
cast.add(mysteryShip);
}
}
private void moveMysteryShip() {
int distance = 0;
if (mysteryDirection) {
mysteryShip.moveRight(5);
distance = getWidth() - mysteryShip.getX();
} else {
mysteryShip.moveLeft(5);
distance = 30+mysteryShip.getX()-mysteryShip.getWidth();
}
if (distance <= 5) {
dead.add(mysteryShip);
mysteryShip = null;
mysteryCount = 0;
}
}
private void removeDead() {
#SuppressWarnings("unchecked")
ArrayList<SIinvader> temp = (ArrayList<SIinvader>) dead.clone();
dead.clear();
for (SIinvader s : temp) {
invaders.remove(s);
cast.remove(s);
}
bottomRow = getBottomRow();
}
private void invadersFire() {
int[] p = new int[bottomRow.length];
for (int i=0; i<p.length; i++) {
for (int j=0; j<p.length; j++) {
p[j] = j;
}
Random rand = new Random();
int a=rand.nextInt(101);
if (a>=20) {
int b=rand.nextInt(p.length);
fireMissile(bottomRow[b], false);
}
}
}
private int calculateDistanceToEdge() {
int distance = 0;
SIinvader[] outliers = getOutliers();
if (waveDirection) {
distance = getWidth() - outliers[0].getX()-outliers[0].getWidth();
} else {
distance = outliers[1].getX();
}
return distance;
}
private SIinvader[] getOutliers() {
SIinvader leftMost = invaders.get(0), rightMost = invaders.get(0);
for (SIinvader s : invaders) {
if (s.getX() < leftMost.getX()) {
leftMost = s;
}
if (s.getX() > rightMost.getX()) {
rightMost = s;
}
}
return new SIinvader[] { rightMost, leftMost };
}
private SIinvader[] getBottomRow() {
SIinvader[] x = new SIinvader[(invaders.size()>10)?10:invaders.size()];
for (int i=0; i<x.length; i++) {
x[i] = invaders.get(i);
for (SIinvader s:invaders) {
if (s.getX() == x[i].getX()) {
if (s.getY() > x[i].getY()) {
x[i] = s;
}
}
}
}
return x;
}
private void move(boolean b) {
int defaultX = 5;
if (b) base.moveLeft(defaultX);
else base.moveRight(defaultX);
}
private void moveAI() {
for(SIinvader s : invaders) {
s.changeImage();
int defaultX = 5;
if (waveDirection) s.moveRight(defaultX);
else s.moveLeft(defaultX);
}
}
private void moveMissileBase() {
if (invaders.isEmpty()) return;
int movement = -5, bound = 0;
SImissile missile = missileBase.get(0);
missile.moveDown(movement);
SIinvader lowestInvader = getLowestInvader();
if (missile.getY() < (lowestInvader.getY() + lowestInvader.getHeight())) {
for (SIinvader s:bottomRow) {
if (checkCollision(missile, s)) {
s.setHit();
dead.add(s);
cast.remove(missile);
missileBase.clear();
score += s.value;
return;
}
}
if (mysteryCount > 0) {
if (checkCollision(missile, mysteryShip)) {
mysteryShip.setHit();
dead.add(mysteryShip);
cast.remove(missile);
missileBase.clear();
score += mysteryShip.value;
return;
}
}
if (missile.getY() < bound) {
missileBase.remove(missile);
cast.remove(missile);
}
}
}
private SIinvader getLowestInvader() {
SIinvader lowest = bottomRow[0];
for (SIinvader invader : bottomRow) {
if (invader.getY() > lowest.getY()) {
lowest = invader;
}
}
return lowest;
}
private void moveMissileInvader() {
int movement = 5, bound = (int) panelDimension.getHeight();
for (SImissile missile : missileInvader) {
missile.moveDown(movement);
if(missile.getY() >= base.getY()) {
if (checkCollision(missile, base)) {
base.setHit();
gameOver = true;;
missileInvader.remove(missile);
cast.remove(missile);
return;
} else if (missile.getY() >= bound-25) {
missileInvader.remove(missile);
cast.remove(missile);
return;
}
}
}
}
private boolean checkCollision(SIthing missile, SIthing ship) {
Rectangle2D rect1 = new Rectangle2D.Double(
missile.getX(),
missile.getY(),
missile.getWidth(),
missile.getHeight()
);
Rectangle2D rect2 = new Rectangle2D.Double(
ship.getX(),
ship.getY(),
ship.getWidth(),
ship.getHeight()
);
return rect1.intersects(rect2);
}
private void switchBack() {
int defaultY = 12;
for (SIinvader s : invaders) {
if (s.getY() > getHeight()) {
gameOver = true;
return;
}
s.moveDown(defaultY);
}
}
private void gameOver() {
pause(true);
SI.setGameOverLabelVisibile(true);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setColor(Color.GREEN);
Font font = new Font("Arial", 0, 20);
setFont(font);
String score = "Score: "+this.score;
Rectangle2D rect = font.getStringBounds(score, g2.getFontRenderContext());
int screenWidth = 0;
try { screenWidth = (int) panelDimension.getWidth(); }
catch (NullPointerException e) {}
g2.setColor(Color.GREEN);
g2.drawString(score, (int) (screenWidth - (10 + rect.getWidth())), 20);
for(SIthing a:cast) {
a.paint(g);
}
}
public SIpanel() {
super();
setBackground(Color.BLACK);
cast = new ArrayList<SIthing>();
missileBase = new ArrayList<SImissile>();
score = invaderPace = mysteryCount = pulseRate = 0;
sound = new Music("AmbientMusic.wav");
panel = this;
addKeyListener(new KeyAdapter() {
#Override
public void keyPressed(KeyEvent e) {
switch (e.getKeyCode()) {
case KeyEvent.VK_LEFT : left = true; break;
case KeyEvent.VK_RIGHT : right = true; break;
case KeyEvent.VK_SPACE : space = true; break;
}
}
#Override
public void keyReleased(KeyEvent e) {
switch (e.getKeyCode()) {
case KeyEvent.VK_LEFT : left = false; break;
case KeyEvent.VK_RIGHT : right = false; break;
case KeyEvent.VK_SPACE : space = false; break;
}
}
});
setFocusable(true);
timer = new Timer(10, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
pulse();
}
});
}
public void reset() {
SI.setGameOverLabelVisibile(false);
score = invaderPace = mysteryCount = 0;
pulseRate = 50;
cast = new ArrayList<SIthing>();
invaders = new ArrayList<SIinvader>();
dead = new ArrayList<SIinvader>();
missileBase = new ArrayList<SImissile>();
missileInvader = new ArrayList<SImissile>();
base = new SIbase(230, 370, 26, 20);
waveDirection = true;
gameOver = false;
sound.stop();
sound.loop();
panelDimension = SI.getFrameDimensions();
bottomRow = getBottomRow();
newWave();
timer.start();
runningTimer=true;
}
public SIpanel getPanel() {
return this.panel;
}
public void pause(boolean paused) {
if (paused) timer.stop();
else timer.start();
}
}
I believe that collision detection may be the reason for lagging and you should simply investigate it by trying to increase and decrease count of enemies or missiles drastically to see if that makes a difference.
Consider garbage collector your enemy. In your checkCollision method you are instantiating two (very simple) objects. It may not seem like a lot, but consider that your might be creating them for each collision check, and that at 60fps it adds up until it may reach critical mass when GC says "stop the world" and you see noticeable lag.
If that is the case, possible solution to that would be to not instantiate any objects in a method called so frequently. You may create Rectangle2D once, and then update its position, instead of creating a new one each time, so you will avoid unnecessary memory allocation.

JavaFX animation problems

I'm currently working on an application with animation in JavaFX. The application is used by human corrector, who is correcting computer-generated subtitles. In the animation there is a floating text. My problem is that the animation sometimes shutters. You can see the following image for demonstration:
This flaw occurs mainly after resizing. When the animation breaks, it never gets to the fully functioning state again.
I use the JFXpanel which is in inserted in Swing UI. I use it this way because I've created quite a lot of code in Swing and I didn't want to toss it all away. I don't use Swing for animation because I wasn't able to create an animation that is smooth enough.
Here is the animation-related code:
public class AnimationPanel extends JFXPanel {
public MyAnimationTimer animationTimer;
public EditObject editObject;
public Color colorHOST1;
public Color colorHOST2;
public Color colorGUEST1;
public Color colorGUEST2;
public Color colorUSER;
public Color colorSIGNING;
public Color basicColor = Color.WHITE;
public Color currentColor = Color.WHITE;
public AnimationPanel(EditObject editObject) {
super();
this.editObject = editObject;
Group group = new Group();
this.animationTimer = new MyAnimationTimer((List<MyText>)(List<?>)group.getChildren(), this);
final Scene scene = new Scene(group, 800, 600, Color.BLACK);
this.setScene(scene);
this.animationTimer.start();
/* // Update animation when component is resized
this.addComponentListener(new ComponentListener() {
#Override
public void componentResized(ComponentEvent e) {
animationTimer.updateAnimations();
}
#Override
public void componentMoved(ComponentEvent e) {
}
#Override
public void componentShown(ComponentEvent e) {
}
#Override
public void componentHidden(ComponentEvent e) {
}
});*/
}
public void setColors(Gui g) {
this.colorHOST1 = Color.rgb(g.colorHOST1.getRed(), g.colorHOST1.getGreen(), g.colorHOST1.getBlue(), g.colorHOST1.getAlpha()/255.0);
this.colorHOST2 = Color.rgb(g.colorHOST2.getRed(), g.colorHOST2.getGreen(), g.colorHOST2.getBlue(), g.colorHOST2.getAlpha()/255.0);
this.colorGUEST1 = Color.rgb(g.colorGUEST1.getRed(), g.colorGUEST1.getGreen(), g.colorGUEST1.getBlue(), g.colorGUEST1.getAlpha()/255.0);
this.colorGUEST2 = Color.rgb(g.colorGUEST2.getRed(), g.colorGUEST2.getGreen(), g.colorGUEST2.getBlue(), g.colorGUEST2.getAlpha()/255.0);
this.colorUSER = Color.rgb(g.colorUSER.getRed(), g.colorUSER.getGreen(), g.colorUSER.getBlue(), g.colorUSER.getAlpha()/255.0);
this.colorSIGNING = Color.rgb(g.colorSIGNING.getRed(), g.colorSIGNING.getGreen(), g.colorSIGNING.getBlue(), g.colorSIGNING.getAlpha()/255.0);
}
}
public class MyAnimationTimer extends AnimationTimer {
private List<MyText> nodes;
private long subtitle_max_time_in_app;
private AnimationPanel animationPanel;
private boolean stopAtTheEnd = false;
private boolean isAtTheEnd = false;
private int currentPos = 0;
public MyAnimationTimer(List<MyText> nodes, AnimationPanel animationPanel) {
super();
this.nodes = nodes;
this.animationPanel = animationPanel;
}
#Override
public void handle(long now) {
MyText node;
if(this.stopAtTheEnd) {
if(this.isAtTheEnd) {
for (int i = this.currentPos; i < this.nodes.size(); i += 2) {
node = nodes.get(i);
if(this.collides(nodes.get(i-2), node)) {
node.setTranslateXforTextandSubText(nodes.get(i-2).getBoundsInParent().getWidth() + nodes.get(i-2).getTranslateX() + 10);
this.currentPos+=2;
}
node.setTranslateXforTextandSubText(node.getTranslateX() - node.getVelocity());
}
} else {
if(nodes.size()!=0) {
node = nodes.get(0);
if((node.getTranslateX() - node.getVelocity()) < 0) {
node.setTranslateXforTextandSubText(0);
this.isAtTheEnd = true;
this.currentPos = 2;
} else {
for (int i = 0; i < this.nodes.size(); i += 2) {
node = nodes.get(i);
node.setTranslateXforTextandSubText(node.getTranslateX() - node.getVelocity());
}
}
}
}
} else {
for (int i = 0; i < this.nodes.size(); i += 2) {
node = nodes.get(i);
node.setTranslateXforTextandSubText(node.getTranslateX() - node.getVelocity());
}
}
}
private boolean collides(MyText node1, MyText node2) {
return (node1.getBoundsInParent().getWidth() + node1.getTranslateX() - node2.getTranslateX()) + 7 >= 0;
}
public void addNode(final MyText node) {
Platform.runLater(() -> {
node.setTranslateYforTextandSubText(animationPanel.getHeight() / 2);
node.setTranslateXforTextandSubText(animationPanel.getWidth());
node.setVelocity(this.getVelocity());
nodes.add(node);
nodes.add(node.id);
// Check for overlaying
if(nodes.size()>=4) {
int size = nodes.size();
double overlaying = (nodes.get(size-4).getBoundsInParent().getWidth() + nodes.get(size-4).getTranslateX() - nodes.get(size-2).getTranslateX()) + 7;
if(overlaying>0) {
nodes.get(size-2).setTranslateXforTextandSubText(nodes.get(size-2).getTranslateX()+overlaying);
}
}
});
}
public void recalculateGaps() {
Platform.runLater(() -> {
if (nodes.size() >= 4) {
double overlaying;
// System.out.println("Size: " + nodes.size());
for (int i = nodes.size() - 2; i > 0; i -= 2) {
overlaying = (nodes.get(i - 2).getBoundsInParent().getWidth() + nodes.get(i - 2).getTranslateX() - nodes.get(i).getTranslateX()) + 7;
if (overlaying > 0) {
nodes.get(i - 2).setTranslateXforTextandSubText(nodes.get(i - 2).getTranslateX() - overlaying);
}
}
}
});
}
public void removeNodesBehindTheScene() {
Platform.runLater(() -> {
MyText node;
for (int i=0; i<nodes.size(); i+=2) {
node = nodes.get(i);
if(node.getTranslateX() > 0) {
break;
} else {
if(!node.isOverdue()) {
animationPanel.editObject.setMessageToBeSendSoon(node);
}
nodes.remove(i);
nodes.remove(i);
i-=2;
}
}
});
}
/* public void updateAnimations() {
// This method is called when the window is resized.
for (int i=0; i<this.nodes.size(); i+=2) {
nodes.get(i).setTranslateYforTextandSubText(animationPanel.getHeight()/2);
}
this.setVelocity();
}*/
public double getVelocity() {
return (this.animationPanel.getWidth()/4)*3/((double) this.subtitle_max_time_in_app)*1000/60;
}
public void setSubtitle_max_time_in_app(long subtitle_max_time_in_app) {
this.subtitle_max_time_in_app = subtitle_max_time_in_app;
}
public void setStopAtTheEnd(boolean stopAtTheEnd) {
// Remove all overdue
if(stopAtTheEnd) {
Platform.runLater(() -> {
for (int i = 0; i < nodes.size(); i += 2) {
if (nodes.get(i).isOverdue()) {
nodes.remove(i);
// Remove ID number
nodes.remove(i);
i -= 2;
} else {
break;
}
}
});
this.isAtTheEnd = false;
this.currentPos = 0;
}
this.stopAtTheEnd = stopAtTheEnd;
}
public void removeUpToNode(MyText node) {
Platform.runLater(() -> {
if(nodes.contains(node)) {
for (int i = 0; i < nodes.size(); i += 2) {
if (nodes.get(i) == node) {
nodes.remove(i);
nodes.remove(i);
break;
}
else {
nodes.remove(i);
nodes.remove(i);
i-=2;
}
}
}
});
}
public void addNodesAtTheBeginning(List<MyText> nodes_list, double nodeposition) {
Platform.runLater(() -> {
MyText node;
double position;
for (int i = nodes_list.size() - 1; i >= 0; i--) {
node = nodes_list.get(i);
node.setTranslateYforTextandSubText(animationPanel.getHeight() / 2);
if(nodes.size()!=0) {
position = this.nodes.get(0).getTranslateX() - node.getBoundsInParent().getWidth() - 10;
} else {
position = animationPanel.getWidth();
}
if(i==(nodes_list.size() - 1)) {
double exactposition = nodeposition - node.getBoundsInParent().getWidth();
if(exactposition < position) {
node.setTranslateXforTextandSubText(exactposition);
} else {
node.setTranslateXforTextandSubText(position);
}
} else {
node.setTranslateXforTextandSubText(position);
}
node.setVelocity(this.getVelocity());
nodes.add(0, node.id);
nodes.add(0, node);
}
});
}
}
I've tested various versions of JavaFX(including the one packed in JDK9), but with no result. Thanks in advance
Finally I fixed the bug. The problem was that I was setting a property of an existing node from my own thread instead of JavaFX thread. Putting it in Platform.runLater method fixed it. I didn't notice the bug immediately because it didn't throw the illegal thread exception as it does when you try to add node. I should have red the documentation more thoroughly.
Thanks

Android crashed and the crash report doesn't show in the Android Studio console

So I have an Android Tetris game that I'm writing. When I run the app in the emulator and click on the start button and it crashed. There isn't a dialog box that says the app has stopped running (You usually get that when an exception is thrown, right?). And I don't know which line of code throws the exception because I can't see the stack trace! Does anyone know where the crash reports are or how can I see the stack trace? I am a beginner programmer for android and I used to write WinForms apps.
I only showed part of code. If you think the problem is somewhere else please tell me so that I can post it here.
By the way, sorry for my bad English if I made any grammatical mistakes as I am Chinese.
Here are code:
The start button:
<Button
android:layout_width="319dp"
android:layout_height="160dp"
android:text="START"
android:id="#+id/buttonStart"
android:layout_x="8dp"
android:layout_y="116dp"
android:textSize="30pt"
android:onClick="btnStartClick"
android:layout_below="#+id/textView"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"/>
OnClick event handler:
public void btnStartClick (View view) {
startActivity (new Intent (StartPage.this, TetrisActivity.class));
}
TetrisActivity's onCreate method:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate (savedInstanceState);
setContentView (R.layout.activity_tetris);
board = new TetrisBoard (this);//board is a TetrisBoard instance
board.addTetrimino ();
}
TetrisBoard class
public class TetrisBoard implements ITetrisEventListener{
private TetrisActivity activity;
private Random r;
public TetrisBlock[][] tetrisBlockMatrix;
public TetrisBoard (TetrisActivity activity) {
tetrisBlockMatrix = new TetrisBlock[16][22];
r = new Random ();
this.activity = activity;
}
public void addTetrimino () {
Tetrimino tetrimino = null;
int randomNumber = r.nextInt (140);
if (randomNumber < 20) {
tetrimino = new OShapedTetrimino (tetrisBlockMatrix, activity);
} else if (randomNumber < 40) {
tetrimino = new IShapedTetrimino (r.nextInt (2), tetrisBlockMatrix,
activity);
} else if (randomNumber < 60) {
tetrimino = new ZShapedTetrimino (r.nextInt (2), tetrisBlockMatrix,
activity);
} else if (randomNumber < 80) {
tetrimino = new SShapedTetrimino (r.nextInt (2), tetrisBlockMatrix,
activity);
} else if (randomNumber < 100) {
tetrimino = new TShapedTetrimino (r.nextInt (4), tetrisBlockMatrix,
activity);
} else if (randomNumber < 120) {
tetrimino = new JShapedTetrimino (r.nextInt (4), tetrisBlockMatrix,
activity);
} else {
tetrimino = new LShapedTetrimino (r.nextInt (4), tetrisBlockMatrix,
activity);
}
tetrimino.registerLandedListeners (this);
tetrimino.setTimerInterval (activity.timerInterval);
activity.fallingTetrimino = tetrimino;
}
#Override
public void onLanded(Tetrimino sender) {
try {
sender.addTetrisBlocksToMatrix (tetrisBlockMatrix);
activity.checkScore ();
addTetrimino ();
} catch (IllegalArgumentException e) {
TetrisUtility.showMsgDialog ("Game Over", "Tetris", activity);
activity.finish ();
}
}
}
And finally the Tetrimino class:
public abstract class Tetrimino {
public TetrisBlock[] blocks;
protected Timer timer;
protected TetrisBlock[][] tetrisBlockMatrix;
protected ArrayList<ITetrisEventListener> landedEventListeners;
protected TimerTask task = new TimerTask () {
#Override
public void run() {
moveDown ();
}
};
public static final int LEFT = -1;
public static final int RIGHT = 1;
protected abstract TetrisBlock[] getTouchingSides();
protected void landed () {
for (int i = 0 ; i < landedEventListeners.size () ; i++) {
landedEventListeners.get (i).onLanded (this);
}
}
public void registerLandedListeners (ITetrisEventListener listener) {
landedEventListeners.add (listener);
}
public void moveDown () {
if (!checkLanded ()) {
for (TetrisBlock block:blocks) {
block.moveDown ();
}
} else {
timer.cancel ();
landed ();
}
}
protected boolean checkLanded () {
TetrisBlock[] touchingSides = getTouchingSides ();
for (TetrisBlock block:touchingSides) {
if (block.getY () >= 21) {
return true;
}
if (tetrisBlockMatrix[block.getX ()][block.getY () + 1] != null) {
return true;
}
}
return false;
}
public boolean checkPositionValid (int x, int y) {
if (x < 0 || y < 0 ||
x > 15 || y > 21)
return false;
if (tetrisBlockMatrix[x][y] == null)
return true;
return false;
}
public void move (int side) {
if (side == 1 || side == -1) {
for (TetrisBlock block:blocks) {
block.setX (block.getX () + side);
}
for (TetrisBlock block:blocks) {
if (!checkPositionValid (block.getX (), block.getY ())) {
if (side == LEFT)
move (RIGHT);
else
move (LEFT);
}
}
} else {
throw new IllegalArgumentException ();
}
}
public void addTetrisBlocksToMatrix (TetrisBlock[][] matrix) {
for (TetrisBlock block:blocks) {
if (matrix[block.getX ()][block.getY ()] == null) {
matrix[block.getX ()][block.getY ()] = block;
} else {
throw new IllegalArgumentException ();
}
}
}
public void setTimerEnabled (boolean value) {
if (value) {
timer.cancel ();
timer = new Timer ();
timer.scheduleAtFixedRate (task, 0L, 1000L);
} else {
timer.cancel ();
}
}
public void setTimerInterval (int milliseconds) {
timer.cancel ();
timer = new Timer ();
timer.scheduleAtFixedRate (task, 0L, milliseconds);
}
protected Tetrimino (TetrisBlock[][] matrix, TetrisActivity activity) {
this.tetrisBlockMatrix = matrix;
timer = new Timer ();
timer.scheduleAtFixedRate (task, 0L, 1000L);
landedEventListeners = new ArrayList<> ();
blocks = new TetrisBlock[4];
}
}
I fix it by repeatedly looping through the following:
Restart Logcat
Change the filter to No Filters from Show only selected application
Change the log level to Debug and back to verbose
Unplug and plug the device back
Running adb kill-server and adb start-server
Restart Android Studio
Restart Computer

Opening a new JFrame using a JButton

I have two classes (Sampling and Stacker). The Sampling class (my Main class) is extends JFrame and has a JButton with an ActionListener to open the Stacker class.
The problem is when the button is clicked, the Stacker class will open but only a frame without any components. When I switch the main method into the Stacker class, the program works fine. What is the problem?
Here is the code:
The Sampling class:
public class Sampling extends JFrame implements ActionListener
{
private JButton openStacker;
Stacker st;
public Sampling()
{
setSize(300,300);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLayout(new FlowLayout());
setLocationRelativeTo(null);
openStacker = new JButton("Start Stacker!");
add(openStacker);
openStacker.addActionListener(this);
setVisible(true);
}
public void actionPerformed(ActionEvent e)
{
dispose();
st = new Stacker();
}
public static void main (String args[])
{
new Sampling();
}
}
The Stacker game class:
public class Stacker extends JFrame implements KeyListener
{
int iteration = 1;
double time = 200;
int last = 0;
int m = 10;
int n = 20;
JButton b[][];
int length[] = {5,5};
int layer = 19;
int deltax[] = {0,0};
boolean press = false;
boolean forward = true;
boolean start = true;
public Stacker()
{
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setSize(400,580);
this.setUndecorated(false);
this.setLocationRelativeTo(null);
b = new JButton [m][n];
setLayout(new GridLayout(n,m));
for (int y = 0;y<n;y++)
{
for (int x = 0;x<m;x++)
{
b[x][y] = new JButton(" ");
b[x][y].setBackground(Color.DARK_GRAY);
add(b[x][y]);
b[x][y].setEnabled(false);
}//end inner for
}
this.setFocusable(true);
this.pack();
this.addKeyListener(this);
this.setVisible(true);
go();
}
public void go()
{
int tmp = 0;
Component temporaryLostComponent = null;
do{
if (forward == true)
{
forward();
} else {
back();
}
if (deltax[1] == 10-length[1])
{
forward = false;
} else if (deltax[1] == 0)
{
forward = true;
}
draw();
try
{
Thread.sleep((long) time);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}while(press == false);
if (layer>12)
{
time= 150-(iteration*iteration*2-iteration);
} else
{
time = time - 2.2;
}
iteration++;
layer--;
press = false;
tmp = check();
length[0] = length[1];
length[1] = tmp;
if (layer == -1)
{
JOptionPane.showMessageDialog(temporaryLostComponent, "Congratulations! You beat the game!");
repeat();
}
if (length[1] <= 0)
{
JOptionPane.showMessageDialog(temporaryLostComponent, "Game over! You reached line "+(18-layer)+"!");
repeat();
}
last = deltax[1];
start = false;
go();
}
public int check()
{
if (start == true)
{
return length[1];
}
else if (last<deltax[1])
{
if (deltax[1]+length[1]-1 <= last+length[0]-1)
{
return length[1];
}
else
{
return length[1]-Math.abs((deltax[1]+length[1])-(last+length[0]));
}
}
else if (last>deltax[1])
{
return length[1]-Math.abs(deltax[1]-last);
}
else
{
return length[1];
}
}
public void forward()
{
deltax[0] = deltax[1];
deltax[1]++;
}
public void back()
{
deltax[0] = deltax[1];
deltax[1]--;
}
public void draw()
{
for (int x = 0;x<length[1];x++)
{
b[x+deltax[0]][layer].setBackground(Color.DARK_GRAY);
}
for (int x = 0;x<length[1];x++)
{
b[x+deltax[1]][layer].setBackground(Color.CYAN);
}
}
public void repeat()
{
if(JOptionPane.showConfirmDialog(null, "PLAY AGAIN?","WARNING",JOptionPane.YES_NO_OPTION)== JOptionPane.YES_OPTION)
{
dispose();
new Stacker();
}else{
System.exit(0);
}
}
public void keyPressed(KeyEvent e)
{
if (e.getKeyCode() == KeyEvent.VK_SPACE)
{
press = true;
}
}
public void keyReleased(KeyEvent arg0)
{
}
public void keyTyped(KeyEvent arg0)
{
}
}
Just to put all my comments into an answer, and give you somewhere to start with:
Comment 1:
Take out go(); see that happens. I tested it and it will work. If you leave it there, even the frame's close button is jammed. You're blocking the edt with the while->Thread.sleep junk. You'll want to do some refactoring. You're code it hard to follow and I have no idea what you're trying to do, so I didn't even attempt it
Comment 2:
If you're wondering why it works when you just run the main from the Stacker class, it's probably because you are running it outside the EDT,
public static void main(String[] args) { new Stacker(); }. What happens when you click the button, that action is performed within the EDT, and hence your new Stacker() will be run on the EDT. In which case the EDT gets blocked by your while loop. If you try run the program from the Stacker class, but wrap it in a SwingUtilities.invokeLater, you will also notice the program fails to work. Swing programs should be run on the EDT though.
Comment 2: Read the first few sections on Concurrency with Swing
So what you can do is use a Swing Timer (which operates on the EDT) for the game loop. What I did was refactor your code a bit. It doesn't operate the way you want it to yet, only because I didn't really understand the logic of your code. So I couldn't get it to work. What I did though, is put some of the logic into the Timer.
Timer timer = new Timer((int)time, new ActionListener(){
public void actionPerformed(ActionEvent event) {
if (forward == true) {
forward();
} else {
back();
}
if (deltax[1] == 10 - length[1]) {
forward = false;
} else if (deltax[1] == 0) {
forward = true;
}
draw();
}
});
And when the go() method is called, it just starts the timer by calling timer.start(). Basically what you need to know about the timer, is that every tick (the milliseconds you pass it), the actionPerformed will be called. So you can update the game state in that method, just like you did in the while loop each iteration.
Take some time to go over How to Use Swing Timers
To get the game working properly, you still need to make some adjustments, but this should give you a head start.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Sampling extends JFrame implements ActionListener {
private JButton openStacker;
Stacker st;
public Sampling() {
setSize(300, 300);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLayout(new FlowLayout());
setLocationRelativeTo(null);
openStacker = new JButton("Start Stacker!");
add(openStacker);
openStacker.addActionListener(this);
setVisible(true);
}
public void actionPerformed(ActionEvent e) {
dispose();
st = new Stacker();
}
public static void main(String args[]) {
SwingUtilities.invokeLater(new Runnable(){
public void run() {
new Sampling();
}
});
}
}
class Stacker extends JFrame implements KeyListener {
int iteration = 1;
double time = 200;
int last = 0;
int m = 10;
int n = 20;
JButton b[][];
int length[] = {5, 5};
int layer = 19;
int deltax[] = {0, 0};
boolean press = false;
boolean forward = true;
boolean start = true;
Timer timer = new Timer((int)time, new ActionListener(){
public void actionPerformed(ActionEvent event) {
if (forward == true) {
forward();
} else {
back();
}
if (deltax[1] == 10 - length[1]) {
forward = false;
} else if (deltax[1] == 0) {
forward = true;
}
draw();
}
});
public Stacker() {
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setSize(400, 580);
this.setUndecorated(false);
this.setLocationRelativeTo(null);
b = new JButton[m][n];
setLayout(new GridLayout(n, m));
for (int y = 0; y < n; y++) {
for (int x = 0; x < m; x++) {
b[x][y] = new JButton(" ");
b[x][y].setBackground(Color.DARK_GRAY);
add(b[x][y]);
b[x][y].setEnabled(false);
}//end inner for
}
this.setFocusable(true);
this.pack();
JPanel panel = (JPanel)getContentPane();
panel.addKeyListener(this);
this.setVisible(true);
panel.requestFocusInWindow();
go();
}
public void go() {
int tmp = 0;
Component temporaryLostComponent = null;
timer.start();
if (layer > 12) {
time = 150 - (iteration * iteration * 2 - iteration);
} else {
time = time - 2.2;
}
iteration++;
layer--;
press = false;
tmp = check();
length[0] = length[1];
length[1] = tmp;
if (layer == -1) {
JOptionPane.showMessageDialog(temporaryLostComponent, "Congratulations! You beat the game!");
repeat();
}
if (length[1] <= 0) {
JOptionPane.showMessageDialog(temporaryLostComponent, "Game over! You reached line " + (18 - layer) + "!");
repeat();
}
last = deltax[1];
start = false;
//go();
}
public int check() {
if (start == true) {
return length[1];
} else if (last < deltax[1]) {
if (deltax[1] + length[1] - 1 <= last + length[0] - 1) {
return length[1];
} else {
return length[1] - Math.abs((deltax[1] + length[1]) - (last + length[0]));
}
} else if (last > deltax[1]) {
return length[1] - Math.abs(deltax[1] - last);
} else {
return length[1];
}
}
public void forward() {
deltax[0] = deltax[1];
deltax[1]++;
}
public void back() {
deltax[0] = deltax[1];
deltax[1]--;
}
public void draw() {
for (int x = 0; x < length[1]; x++) {
b[x + deltax[0]][layer].setBackground(Color.DARK_GRAY);
}
for (int x = 0; x < length[1]; x++) {
b[x + deltax[1]][layer].setBackground(Color.CYAN);
}
}
public void repeat() {
if (JOptionPane.showConfirmDialog(null, "PLAY AGAIN?", "WARNING", JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) {
dispose();
new Stacker();
} else {
System.exit(0);
}
}
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_SPACE) {
System.out.println("Pressed");
press = true;
}
}
public void keyReleased(KeyEvent arg0) {
}
public void keyTyped(KeyEvent arg0) {
}
}
Notice the SwingUtilities.invokeLater in the main. That's how you can start up the program on the EDT. The link on Concurrency In Swing will give you more information.

Categories