I am trying to simulate tap and joystick movement on screen using AccessibilityService.
In addition i'm getting my input from gamepad controller device. doing tap is ok and done. my problem is simulating joystick movement on screen.
I don't know how can i do continuous touch with GestureDescription, because of time duration that this function requires.
i have used this code for tap:
public void virtual_touch(int posX, int posY)
{
Path path = new Path();
path.moveTo(posX, posY);
GestureDescription.Builder gestureBuilder = new GestureDescription.Builder();
gestureBuilder.addStroke(new GestureDescription.StrokeDescription(path, 10, 10));
//gestureBuilder.build();
boolean isDispatched = dispatchGesture(gestureBuilder.build(), new AccessibilityService.GestureResultCallback()
{
#Override
public void onCompleted(GestureDescription gestureDescription)
{
super.onCompleted(gestureDescription);
MyUtils.Log("onCompleted");
}
#Override
public void onCancelled(GestureDescription gestureDescription)
{
super.onCancelled(gestureDescription);
MyUtils.Log("onCancelled");
}
}, null);
MyUtils.Log("virtual_touch isDispatched : " + isDispatched);
}
For Continue Stroke Use this method may be this will help to you.
willContinue --
continueStroke
public GestureDescription.StrokeDescription continueStroke (Path path,
long startTime,
long duration,
boolean willContinue)
boolean: true if this stroke will be continued by one in the next gesture false otherwise. Continued strokes keep their pointers down when the gesture completes.
I'm working on modifying the Attraction2D example from the Toxiclibs library to be controlled by gestures from a Leap Motion sensor, as opposed to the mouse in the example.
I'm doing all my gesture recognition in an Open Frameworks app, and sending that over OSC.
When a Gesture 0 event occurs, I call the method below to remove the gestureAttractor from the physics object:
void resetAttraction() {
if (gestureAttractor != null){
physics.removeBehavior(gestureAttractor);
println("ATTRACTOR NULL");
} else {
println("not null");
}
}
If a Gesture 1 event occurs, I call this method to create a new gestureAttractor, and add it back to the physics object:
void addAttraction(){
if (gestureAttractor == null) {
println("ATTRACTOR NULL");
position1.set(340, 191);
gestureAttractor = new AttractionBehavior2D(position1, 250, 0.9f);
physics.addBehavior(gestureAttractor);
} else {
println("not null");
}
}
What seems to happen consistently is whenever the gesture state changes, I'll get a ConcurrentModificationException crash at physics.update(); in the draw method.
I'm sure it has something to do with the way the lifecycle of these objects are handled, but I haven't been able to determine anything yet - anyone have any ideas?
Below is the entirety of the sketch:
import toxi.geom.*;
import toxi.physics2d.*;
import toxi.physics2d.behaviors.*;
import oscP5.*;
import netP5.*;
OscP5 oscP5;
int NUM_PARTICLES = 750;
VerletPhysics2D physics;
//AttractionBehavior2D mouseAttractor;
AttractionBehavior2D gestureAttractor;
//Vec2D mousePos;
Vec2D position1;
boolean isGestureAttractorAdded;
void setup() {
size(680, 382,P3D);
// setup physics with 10% drag
physics = new VerletPhysics2D();
physics.setDrag(0.05f);
physics.setWorldBounds(new Rect(0, 0, width, height));
// the NEW way to add gravity to the simulation, using behaviors
physics.addBehavior(new GravityBehavior2D(new Vec2D(0, 0.15f)));
// start oscP5, listening for incoming messages at port 12000
oscP5 = new OscP5(this, 6000);
position1 = new Vec2D(340, 191);
addAttraction();
//gestureAttractor = new AttractionBehavior2D(position1, 250, 0.9f);
//physics.addBehavior(gestureAttractor);
}
void addParticle() {
VerletParticle2D p = new VerletParticle2D(Vec2D.randomVector().scale(5).addSelf(width / 2, 0));
physics.addParticle(p);
// add a negative attraction force field around the new particle
physics.addBehavior(new AttractionBehavior2D(p, 20, -1.2f, 0.01f));
}
void draw() {
background(255,0,0);
noStroke();
fill(255);
if (physics.particles.size() < NUM_PARTICLES) {
addParticle();
}
physics.update();
for (VerletParticle2D p : physics.particles) {
ellipse(p.x, p.y, 5, 5);
}
}
void mousePressed() {
//position1 = new Vec2D(mouseX, mouseY);
//create a new positive attraction force field around the mouse position (radius=250px)
//gestureAttractor = new AttractionBehavior2D(position1, 250, 0.9f);
//physics.addBehavior(gestureAttractor);
//println(physics.behaviors);
}
void mouseDragged() {
// update mouse attraction focal point
//position1.set(mouseX, mouseY);
}
void mouseReleased() {
// remove the mouse attraction when button has been released
//physics.removeBehavior(gestureAttractor);
}
///// OSC RECEIVING
void oscEvent(OscMessage theOscMessage) {
/* check if theOscMessage has the address pattern we are looking for. */
if (theOscMessage.checkAddrPattern("/gesture_classification") == true) {
/* check if the typetag is the right one. */
if(theOscMessage.checkTypetag("i")) {
/* parse theOscMessage and extract the values from the osc message arguments. */
int gestureClassLabel = theOscMessage.get(0).intValue();
println(" Gesture is: ", gestureClassLabel);
if (gestureClassLabel == 0){
resetAttraction();
} else if (gestureClassLabel == 1) {
addAttraction();
} else if (gestureClassLabel == 2) {
//physics.removeBehavior(gestureAttractor);
}
}
}
}
//////METHODS FOR SETTING POSITION / REMOVAL OF ATTRACTORS...
void resetAttraction() {
if (gestureAttractor != null){
physics.removeBehavior(gestureAttractor);
println("ATTRACTOR NULL");
} else {
println("not null");
}
}
void addAttraction(){
if (gestureAttractor == null) {
println("ATTRACTOR NULL");
position1.set(340, 191);
gestureAttractor = new AttractionBehavior2D(position1, 250, 0.9f);
physics.addBehavior(gestureAttractor);
} else {
println("not null");
}
}
tl;dr: You shouldn't modify a data structure with one thread while you're iterating over it from another thread.
The draw() function is happening on one thread, and it's accessing and modifying data structures inside the physics library.
The oscEvent() function is happening on another thread, and it's also accessing and modifying those same data structures. That's what's causing your error. And please note that wrapping it in a try block is not fixing anything. It's just printing out more information when the error does happen.
To really fix the problem, you need to read up on synchornizing data access between threads. For example, you could use synchronized blocks to prevent different threads from accessing the same data structure. You'll find a ton of results if you google your error.
I am writing an game in java with Libgdx and have a question about how to have multiple instances of the same object in an ArrayList without abusing the garbage collector.
this is the code of my main game state. I am still really new, so I assume my coding habits are downright awful:
package com.frog.game;
import java.util.ArrayList;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.freetype.FreeTypeFontGenerator;
import com.badlogic.gdx.math.MathUtils;
import com.frog.entities.Frog;
import com.frog.entities.Grass;
import com.frog.entities.LilyPad;
import com.frog.gamestates.GameState;
import com.frog.managers.GameStateManager;
import com.frog.managers.Jukebox;
import com.frog.managers.Save;
import com.frog.managers.SimpleDirectionGestureDetector;
import com.frog.managers.SpeedManager;
import com.frog.game.Game;
public class PlayState extends GameState {
private SpriteBatch sb;
private Frog frog;
private BitmapFont font;
private ArrayList<LilyPad> lilypads;
private Grass grass;
private float hopY;
public boolean tmp;
private SpeedManager speedManager;
private float speed;
private float[] placement;
public PlayState(GameStateManager gsm) {
super(gsm);
}
#SuppressWarnings("deprecation")
public void init() {
speedManager = new SpeedManager();
lilypads = new ArrayList<LilyPad>();
sb = new SpriteBatch();
frog = new Frog();
frog.init();
grass = new Grass();
grass.init();
hopY = Game.SIZE * 0.8f;
placement = new float[] {
0,
Game.SIZE,
Game.SIZE * 2
};
addPad();
FreeTypeFontGenerator gen = new FreeTypeFontGenerator(
Gdx.files.internal("PressStart2P-Regular.ttf")
);
font = gen.generateFont((Game.WIDTH / 10));
gen.dispose();
Gdx.input.setInputProcessor(new SimpleDirectionGestureDetector(new SimpleDirectionGestureDetector.DirectionListener() {
#Override
public void onUp() {
// TODO Auto-generated method stub
}
#Override
public void onRight() {
frog.moveRight();
}
#Override
public void onLeft() {
frog.moveLeft();
}
#Override
public void onDown() {
}
}));
}
This is the method I use to add another lilypad at the top of the screen. I make it appear in one of three places randomly. Since the main function of these lilypads is to scroll down the screen, instances of the lilypad are being added and removed from the array non stop. I know this kills because each time I add a new lilypad, I have to run init() for it, otherwise I will get a nullpointerexception. init() instantiates a bunch of objects in order to make that lilypad render, such as textures, the default Y value etc. Is there any way I could run the init() method once for the entire arraylist, even though I am constantly adding & removing them? I have considered wrapping the same lilypads around the screen when they hit the bottom, so I would only need like 7, and then I wouldn't have to add or remove anymore, but would have to rework a big chunk of code for that, and consider it a last resort. The game already runs smooth, it just has a few barely noticeable stutters here and there that I would like to avoid.
private void addPad() {
lilypads.add(new LilyPad(placement[MathUtils.random(0, 2)], 300, false));
lilypads.get(lilypads.size() - 1).init();
}
public void update(float dt) {
speed = speedManager.speed(dt);
speedManager.update(dt);
// update grass
if(!grass.shouldStop()) {
grass.update(dt, speed);
frog.introPlay(speed);
}
// update lily pads
for(int i = 0; i < lilypads.size(); i++) {
lilypads.get(i).update(dt, speed);
This is where I call the addPad() method. It basically says if the last added pad is fully visible on screen, add the next.
if(lilypads.get(i).getY() < (Game.HEIGHT - Game.SIZE) && lilypads.get(i).past()) {
addPad();
}
// hop frog
if(lilypads.get(i).getY() < hopY && lilypads.get(i).past2()) {
// play hop
if(lilypads.get(i).getX() > frog.getX() - Game.SIZE / 2 && lilypads.get(i).getX() < frog.getX() + Game.SIZE / 2){
frog.incrementScore();
Jukebox.play("hop");
lilypads.get(i).splash();
frog.play(speed);
} else {
Jukebox.stopAll();
Save.gd.setTempScore(frog.getScore());
gsm.setState(GameStateManager.GAMEOVER);
return;
}
return;
}
if(lilypads.get(i).getY() < (-Game.SIZE)){
lilypads.remove(i);
}
}
}
public void draw() {
// draw grass
if(!grass.shouldStop()) {
grass.draw(sb);
}
// draw pads
for(int i = 0; i < lilypads.size(); i++){
lilypads.get(i).draw(sb, true);
}
// draw frog
frog.draw(sb, speed, true);
sb.setColor(1, 1, 1, 1);
sb.begin();
font.draw(sb, Long.toString(frog.getScore()),
Game.WIDTH * 0.92f -font.getBounds(Long.toString(frog.getScore())).width, Game.HEIGHT * 0.958f);
sb.end();
}
public void handleInput() {
}
public void dispose() {
sb.dispose();
Jukebox.stopAll();
}
Thanks for the support.
Use libGDX's custom collections for that. You can find all of them here.
In your case you want to use an Array. They are optimized to not cause the garbage collector to kick in, for example by re-using the iterators.
With a standard ArrayList the following piece of code in your render method would create a new Iterator in every frame.
for(LilyPad lilyPad : lilipads){
lilypad.draw(sb, true);
}
In general try to avoid using new whenever you can. This wiki article might help you with it and it explains how pooling works.
Another common trick to avoid GC especially when working with Vector2 or Vector3 is keeping a private final Vector2 tmp = new Vector2() and always only using tmp.set(x, y) to change it. This principle could also be applied to any other custom class that you are creating yourself to hold some data.
I am making the game Asteroids. Everything functionally works properly, but originally I set the background color to black and had the objects represented by shapes that moved around on a Canvas. I've since changed the background to an Image and am working on changing the objects to be represented by images.
However, regardless of the background, I am having trouble repainting the image in a new location. You can see the path of each object after its been moved to each new location. I've been mostly focusing on the shot fired and I noticed if I fire shots all around the screen, the background is refreshed, but it almost seems to be completely at random. If anyone could help guide me in the right direction, that would be great! I've read several documents, textbooks, and watched several videos to try to understand.
package comets;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import javax.sound.sampled.*;
import javax.swing.*;
import java.util.*;
import java.io.*;
import java.net.URL;
// This class is primarily responsible for organizing the game of Comets
public class CometsMain extends JPanel implements KeyListener
{
// GUI Data
private JFrame frame; // The window itself
private JPanel playArea; // The area where the game takes place
private final int playWidth = 500; // The width of the play area (in pixels)
private final int playHeight = 500; // The height of the play area (in pixels)
// Game Data
private SpaceObject spaceObject;
private Ship ship; // The ship in play
private Shot s = new Shot(0, 0, 0, 0);
private LargeComet large = new LargeComet(0, 0, 0, 0);
private MediumComet medium = new MediumComet(0, 0, 0, 0);
private SmallComet small = new SmallComet(0, 0, 0, 0);
private Vector<Shot> shots; // The shots fired by the player
private Vector<Comet> comets; // The comets floating around
private boolean shipDead; // Whether or not the ship has been blown up
private long shipTimeOfDeath; // The time at which the ship blew up
// Keyboard data
// Indicates whether the player is currently holding the accelerate, turn
// left, or turn right buttons, respectively
private boolean accelerateHeld = false;
private boolean turnLeftHeld = false;
private boolean turnRightHeld = false;
private boolean slowDownHeld = false;
// Indicates whether the player struck the fire key
private boolean firing = false;
// Create Images
private Image background; // background image
private BufferedImage spaceShip = null;
private BufferedImage largeComet = null;
private BufferedImage mediumComet = null;
private BufferedImage smallComet = null;
private BufferedImage bullet = null;
private int type = AlphaComposite.SRC_OVER;
private float alpha = 0;
// Set up the game and play!
public CometsMain()
{
// Get everything set up
configureGUI();
configureGameData();
// Display the window so play can begin
frame.setVisible(true);
//Use double buffering
frame.createBufferStrategy(2);
//play music
playMusic();
// Start the gameplay
playGame();
}
private void playMusic(){
try {
URL url = this.getClass().getClassLoader().getResource("BackgroundMusic.wav");
AudioInputStream audioIn = AudioSystem.getAudioInputStream(url);
Clip clip = AudioSystem.getClip();
clip.open(audioIn);
clip.start();
clip.loop(5);
} catch (Exception e) {
e.printStackTrace();
}
}
// Set up the initial positions of all space objects
private void configureGameData()
{
// Configure the play area size
SpaceObject.playfieldWidth = playWidth;
SpaceObject.playfieldHeight = playHeight;
// Create the ship
ship = new Ship(playWidth/2, playHeight/2, 0, 0);
// Create the shot vector (initially, there shouldn't be any shots on the screen)
shots = new Vector<Shot>();
// Read the comets from comets.cfg
comets = new Vector<Comet>();
try
{
Scanner fin = new Scanner(new File("comets.cfg"));
// Loop through each line of the file to read a comet
while(fin.hasNext())
{
String cometType = fin.next();
double xpos = fin.nextDouble();
double ypos = fin.nextDouble();
double xvel = fin.nextDouble();
double yvel = fin.nextDouble();
if(cometType.equals("Large"))
comets.add(new LargeComet(xpos, ypos, xvel, yvel));
else if(cometType.equals("Medium")){
comets.add(new MediumComet(xpos, ypos, xvel, yvel));
}
else
comets.add(new SmallComet(xpos, ypos, xvel, yvel));
}
}
// If the file could not be read correctly for whatever reason, abort
// the program
catch(FileNotFoundException e)
{
System.err.println("Unable to locate comets.cfg");
System.exit(0);
}
catch(Exception e)
{
System.err.println("comets.cfg is not in a proper format");
System.exit(0);
}
}
// Set up the game window
private void configureGUI()
{
// Load Images & Icons
// Background Image
try {
background = ImageIO.read(this.getClass().getClassLoader().getResource("galaxy.jpg"));
} catch (IOException e) {
}
// Space Ship Image
try {
spaceShip = ImageIO.read(this.getClass().getClassLoader().getResource("ship.png"));
} catch (IOException e) {
}
// Large Comet Image
try {
largeComet = ImageIO.read(this.getClass().getClassLoader().getResource("largecomet.png"));
} catch (IOException e) {
}
// Medium Comet Image
try {
mediumComet = ImageIO.read(this.getClass().getClassLoader().getResource("mediumcomet.png"));
} catch (IOException e) {
}
// Medium Comet Image
try {
smallComet = ImageIO.read(this.getClass().getClassLoader().getResource("smallcomet.png"));
} catch (IOException e) {
}
// bullet Image
try {
bullet = ImageIO.read(this.getClass().getClassLoader().getResource("bullet.png"));
} catch (IOException e) {
}
// Create the window object
frame = new JFrame("Comets");
frame.setSize(playWidth+20, playHeight+35);
frame.setResizable(false);
// The program should end when the window is closed
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(playWidth, playHeight);
// Set the window's layout manager
frame.setLayout(new FlowLayout());
// Create background
JLabel bgLabel = new JLabel( new ImageIcon(background.getScaledInstance(playWidth, playHeight, 0) ) );
bgLabel.setSize(playWidth, playHeight);
frame.setContentPane(bgLabel);
frame.pack();
// Create the play area
playArea = new JPanel();
playArea.setSize(playWidth, playHeight);
playArea.setFocusable(false);
playArea.setOpaque(false);
frame.add(playArea);
// Make the frame listen to keystrokes
frame.addKeyListener(this);
}
// The main game loop. This method coordinates everything that happens in
// the game
private void playGame()
{
while(true)
{
// Measure the current time in an effort to keep up a consistent
// frame rate
long time = System.currentTimeMillis();
// If the ship has been dead for more than 3 seconds, revive it
if(shipDead && shipTimeOfDeath + 3000 < time)
{
shipDead = false;
ship = new Ship(playWidth/2, playHeight/2, 0, 0);
}
// Process game events, move all the objects floating around,
// and update the display
if(!shipDead)
handleKeyEntries();
handleCollisions();
moveSpaceObjects();
// Sleep until it's time to draw the next frame
// (i.e. 32 ms after this frame started processing)
try
{
long delay = Math.max(0, 32-(System.currentTimeMillis()-time));
Thread.sleep(delay);
}
catch(InterruptedException e)
{
}
}
}
// Deal with objects hitting each other
private void handleCollisions()
{
// Anything that is destroyed should be erased, so get ready
// to erase stuff
Graphics g = playArea.getGraphics();
Graphics2D g2d = (Graphics2D) g;
g2d.setComposite(AlphaComposite.getInstance(type, alpha));
// Deal with shots blowing up comets
for(int i = 0; i < shots.size(); i++)
{
Shot s = shots.elementAt(i);
for(int j = 0; j < comets.size(); j++)
{
Comet c = comets.elementAt(j);
// If a shot has hit a comet, destroy both the shot and comet
if(s.overlapping(c))
{
// Erase the bullet
shots.remove(i);
i--;
repaint((int)shots.elementAt(i).getXPosition(), (int)shots.elementAt(i).getYPosition(), (int)(2*shots.elementAt(i).getRadius()), (int)(2*shots.elementAt(i).getRadius()));
// If the comet was actually destroyed, replace the comet
// with the new comets it spawned (if any)
Vector<Comet> newComets = c.explode();
if(newComets != null)
{
paintComponent(g);
comets.remove(j);
j--;
comets.addAll(newComets);
}
break;
}
}
}
// Deal with comets blowing up the ship
if(!shipDead)
{
for(Comet c : comets)
{
// If the ship hit a comet, kill the ship and mark down the time
if(c.overlapping(ship))
{
shipTimeOfDeath = System.currentTimeMillis();
shipDead = true;
spaceObject=ship;
paintComponent(g);
}
}
}
}
// Check which keys have been pressed and respond accordingly
private void handleKeyEntries()
{
// Ship movement keys
if(accelerateHeld)
ship.accelerate();
if(slowDownHeld)
ship.slowDown();
// Shooting the cannon
if(firing)
{
firing = false;
shots.add(ship.fire());
}
}
// Deal with moving all the objects that are floating around
private void moveSpaceObjects()
{
Graphics g = playArea.getGraphics();
// Handle the movements of all objects in the field
if(!shipDead)
updateShip(g);
updateShots(g);
updateComets(g);
}
// Move all comets and draw them to the screen
private void updateComets(Graphics g)
{
for(Comet c : comets)
{
spaceObject=c;
paintComponent(g);
// Move the comet to its new position
c.move();
paintComponent(g);
}
}
// Move all shots and draw them to the screen
private void updateShots(Graphics g)
{
for(int i = 0; i < shots.size(); i++)
{
Shot s = shots.elementAt(i);
// Erase the shot at its old position
paintComponent(g);
// Move the shot to its new position
s.move();
// Remove the shot if it's too old
if(s.getAge() > 180)
{
shots.remove(i);
i--;
}
// Otherwise, draw it at its new position
else
{
moveImage(g, s, (int)s.getXPosition(), (int)s.getYPosition());
paintComponent(g);
}
}
}
// Moves the ship and draws it at its new position
private void updateShip(Graphics g)
{
// Erase the ship at its old position
paintComponent(g);
// Ship rotation must be handled between erasing the ship at its old position
// and drawing it at its new position so that artifacts aren't left on the screen
if(turnLeftHeld)
ship.rotateLeft();
if(turnRightHeld)
ship.rotateRight();
ship.move();
// Draw the ship at its new position
moveImage(g, ship, (int)ship.getXPosition(), (int)ship.getYPosition());
paintComponent(g);
}
// Draws this ship s to the specified graphics context
private void drawShip(Graphics g, Ship s)
{
Graphics2D ship = (Graphics2D) spaceShip.getGraphics();
double x = Math.sin(s.getAngle());
double y = Math.cos(s.getAngle());
AffineTransform transformsave = AffineTransform.getRotateInstance(x, y, spaceShip.getWidth()/2, spaceShip.getHeight()/2);
AffineTransformOp transform = new AffineTransformOp( transformsave, AffineTransformOp.TYPE_BILINEAR );
// Figure out where the ship should be drawn
int xCenter = (int)s.getXPosition();
int yCenter = (int)s.getYPosition();
// Draw the ship body
g.drawImage(transform.filter(spaceShip, null), xCenter-10, yCenter-20, null);
ship.setTransform(transformsave);
}
public void setSpaceObject(SpaceObject s){
spaceObject=s;
}
public SpaceObject getSpaceObject(){
return spaceObject;
}
#Override
protected void paintComponent( Graphics g ){
super.paintComponent(g);
spaceObject=getSpaceObject();
int radius = (int)s.getRadius();
int xCenter = (int)s.getXPosition();
int yCenter = (int)s.getYPosition();
// Draw the object
if(spaceObject==s)
g.drawImage( bullet, xCenter-radius, yCenter-radius, this );
else if(spaceObject==large)
g.drawImage( largeComet, xCenter-radius, yCenter-radius, this );
else if(spaceObject==medium)
g.drawImage( mediumComet, xCenter-radius, yCenter-radius, this );
else if(spaceObject==small)
g.drawImage( smallComet, xCenter-radius, yCenter-radius, this );
else if(spaceObject==ship)
drawShip(g, ship);
}
public void moveImage(Graphics g, SpaceObject s, int x, int y){
int radius = (int)s.getRadius();
int xCenter=0, yCenter=0;
if(xCenter!=x || yCenter!=y){
xCenter= (int)s.getXPosition();
yCenter = (int)s.getYPosition();
repaint(xCenter, yCenter, radius*2, radius*2);
}
}
// Deals with keyboard keys being pressed
public void keyPressed(KeyEvent key)
{
// Mark down which important keys have been pressed
if(key.getKeyCode() == KeyEvent.VK_UP)
this.accelerateHeld = true;
if(key.getKeyCode() == KeyEvent.VK_LEFT)
this.turnLeftHeld = true;
if(key.getKeyCode() == KeyEvent.VK_RIGHT)
this.turnRightHeld = true;
if(key.getKeyCode() == KeyEvent.VK_SPACE)
this.firing = true;
//ADD DOWN TO SLOW DOWN SHIP!!!
if(key.getKeyCode() == KeyEvent.VK_DOWN)
this.slowDownHeld = true;
}
// Deals with keyboard keys being released
public void keyReleased(KeyEvent key)
{
// Mark down which important keys are no longer being pressed
if(key.getKeyCode() == KeyEvent.VK_UP)
this.accelerateHeld = false;
if(key.getKeyCode() == KeyEvent.VK_LEFT)
this.turnLeftHeld = false;
if(key.getKeyCode() == KeyEvent.VK_RIGHT)
this.turnRightHeld = false;
//ADD DOWN TO SLOW DOWN SHIP!!!
if(key.getKeyCode() == KeyEvent.VK_DOWN)
this.slowDownHeld = false;
}
// This method is not actually used, but is required by the KeyListener interface
public void keyTyped(KeyEvent arg0)
{
}
public static void main(String[] args)
{
// A GUI program begins by creating an instance of the GUI
// object. The program is event driven from that point on.
new CometsMain();
}
}
Don't use getGraphics. The problem with this, is it's simply a snap shot of what was last painted.
This is like taking a sheet of paper and repeatedly drawing on top of it, it makes a real mess real quick.
getGraphics can also return null.
In Swing painting is controlled by the RepaintManager which makes decisions about what and when things should be painted.
The basic concept you should be trying to follow is to...
Update the state of the game model
Update the view of the game model
Render the view to the screen
This can be achieved in a few different ways, but to start with, if you want to make updates to the UI, you should override the paintComponent method of a component that extends from something like JComponent.
When called, call super.paintComponent which will automatically prepare the Graphics context for painting.
To update the view...
You Could...
In a background thread, update the game model and request that the view be repainted
In the view's paintComponent method, re-draw the model
This is a relatively simple approach, but can, if not controlled well, can get the view and the model out of sync. You also need to ensure that the model is not changed while the view is been updated...
Or, You Could...
Create two (or more) BufferedImages
In a background thread, update the game model
In the background thread, update the "offscreen" buffer to represent the current game model state
Switch the buffered images (moving the "offscreen" buffer to the "active screen" and the "active screen" to the "offscreen")
Request that the view be updated
In the view's paintComponent method, simply draw the "active screen"
This is a more complex process, which will require you to ensure that the buffer's are the same size as the view, but means that the model can be updated independently of the view repaints. There is still the danger that you could change the "off" and "active" screen buffers while the view is been painted.
You could elevate this process slightly by using some kind of queue, where you place BufferedImages that can be used for rendering to (by popping them off the queue) and having the "view" push them back again once it has rendered it...
Or some combination of these, where you lock the switching of the "active" and "off" screen buffers to ensure that that "active" buffer isn't being painted.
Take a look at Performing Custom Painting and Painting in AWT and Swing for more details
For example...
Java Bouncing Ball
the images are not loading
Swing animation running extremely slow
Modern graphics applications use following approach:
For every frame repeat these steps
erase screen
draw background
draw your objects in proper order
do anything else
With this approach you don't need to track previous locations of your objects that can be very tricky because object may overlap.
Of course this will cause flickering, due to lack of performance. Various algorithms to prevent this are exists, take a look on this Documentation and this Question
you can just use getContentPane().repaint() every time you use repaint().
First, I apologize for my poor english.
i am creating a game where i have to throw balls. After a timer i want the ball disapear. So i try to detach it and dispose it. The ball become invisible but is still in my scene because the player is blocked when he's walking on it.
Have you an idea about why the ball is not completly destroy?
private void fire() {
ballon = new Sprite(this.player.getX() + 15, this.player.getY() -5, resourcesManager.ballon_region,vbom);
ballon.setScale(2f);
BallonBody = PhysicsFactory.createCircleBody(this.physicsWorld, ballon, BodyType.DynamicBody, mFixtureDef);
this.physicsWorld.registerPhysicsConnector(new PhysicsConnector(ballon, BallonBody, true, true));
final Vector2 speed = Vector2Pool.obtain(20, 0);
BallonBody.setLinearVelocity(speed);
Vector2Pool.recycle(speed);
attachChild(ballon);
engine.registerUpdateHandler(new TimerHandler(1.6f, new ITimerCallback()
{
public void onTimePassed(final TimerHandler pTimerHandler)
{
//ballon.dispose();
ballon.detachSelf();
ballon=null;
}
}));
}
Edit : Ok , I've found the problem. I just have to destroy the body too.