I am a newbie in libgdx. I am working on a game which has a player body and I have given controls but I want to create enemies at specific time in my game. I have tried creating it but only the player body is been created and but not enemy body.
This is my code
public class Player
implements Screen, InputProcessor {
private Body polybody;
private Player player;
private World world;
private Body enemybody;
private Sprite polysprite;
public final float width, height;
private Vector2 movement = new Vector2();
private float speed = 580;
public Player(World world, float x, float y, float width) {
this.width = width; //IMP
height = width * 2;
BodyDef polygon = new BodyDef();
polygon.type = BodyType.DynamicBody;
polygon.position.set(x, y); //
PolygonShape poly = new PolygonShape();
poly.setAsBox(width / 2, height / 2); //
//fixture defn
FixtureDef polyfixture = new FixtureDef();
polyfixture.shape = poly;
polyfixture.friction = 0.8f; //
polyfixture.restitution = 0.1f; //
polyfixture.density = 3; //
//creating actual body
polybody = world.createBody(polygon);
polybody.createFixture(polyfixture);
// polybody.applyAngularImpulse(52, true);
polysprite = new Sprite(new Texture("img/car.jpg"));
polysprite.setSize(0.5f, 1); //size of mario
polysprite.setOrigin(polysprite.getWidth() / 2, polysprite.getHeight() / 2);
polybody.setUserData(polysprite);
poly.dispose();
}
public void update() {
polybody.applyForceToCenter(movement, true);
}
public Body getBody() {
return polybody;
}
#Override
public void show() {
// TODO Auto-generated method stub
}
final float step = 0.1f;
float timeElapsed = 0f;
#Override
public void render(float delta) {
timeElapsed += delta;
while (timeElapsed > step) {
timeElapsed -= step;
Enemy();
}
}
public void Enemy() {
BodyDef enemy = new BodyDef();
enemy.type = BodyType.DynamicBody;
enemy.position.set(6, 3);
PolygonShape enemypoly = new PolygonShape();
enemypoly.setAsBox(2, 2);
FixtureDef enemyfixture = new FixtureDef();
enemyfixture.shape = enemypoly;
enemyfixture.friction = 0.75f;
enemyfixture.restitution = 0.1f;
enemyfixture.density = 5;
enemybody = world.createBody(enemy);
enemybody.createFixture(enemyfixture);
enemypoly.dispose();
}
#Override
public void resize(int width, int height) {
// TODO Auto-generated method stub
}
#Override
public void pause() {
// TODO Auto-generated method stub
}
#Override
public void resume() {
// TODO Auto-generated method stub
}
#Override
public void hide() {
// TODO Auto-generated method stub
}
#Override
public void dispose() {
// TODO Auto-generated method stub
}
#Override
public boolean keyDown(int keycode) {
// TODO Auto-generated method stub
switch (keycode) {
case Keys.W:
movement.y = speed;
break;
case Keys.S:
movement.y = -speed;
break;
case Keys.D:
movement.x = speed;
break;
case Keys.A:
movement.x = -speed;
}
return true;
}
#Override
public boolean keyUp(int keycode) {
// TODO Auto-generated method stub
switch (keycode) {
case Keys.W:
movement.y = 0;
break;
case Keys.S:
movement.y = 0;
break;
case Keys.D:
movement.x = 0;
break;
case Keys.A:
movement.x = 0;
}
return true;
}
#Override
public boolean keyTyped(char character) {
// TODO Auto-generated method stub
return false;
}
#Override
public boolean touchDown(int screenX, int screenY, int pointer, int button) {
// TODO Auto-generated method stub
movement.x = speed;
Gdx.app.log("Example", "touch done ");
return true;
}
}
This is the player class that gets called first and after this on render method the enemy method gets called. The player body is working fine but I couldn't see any enemy body. Please help .Thanks in advance !!
Apparently, your Player class is responsible for:
Handling inputs for controlling the game
the construction of enemy objects
rendering the entire world (handling time) and displaying the world and all objects
creating Textures (that is supposed to be created only once, not every time you make a Sprite!)
Aaaand you don't have any other class.
I think you should fix this problem.
Also, I'm a bit weary of that you're calling dispose() each time after you create an object.
By the way, the render() method only gets called if you set the active screen for the Game, so
public class MyGame extends Game {
...
MyScreen myScreen = new MyScreen();
...
public void goToMyScreen() {
this.setScreen(myScreen);
}
}
Something like that is necessary for render() to work.
And please check How to track time in Libgdx(android) on how to handle elapsed time.
I suggest a refactoring of your application. That class Player doesn't look like the right place for creating enemies (which you seem to do in every step). Instead you should create the Enemy in the same place where you create your Player and give your Enemy an own class.
Furthermore you could write debug messages to the console or use your IDE's debugger to check what your code is actually doing.
Related
I need to calculate a 2 ovals collision in a java swing mini game.
I have a JPanel which draws my ArrayList of balls Thread's and my player ball. In the run() method of my non player balls i check for a collision between the player ball and the balls Thread ArrayList.
The problem is my collision method is never executed. It's not even getting to my collision if statement. Just never calls the method.
Ball.java:
public class Ball extends Thread
{
int x;
int y;
int velocity = 1;
public int radius = 20;
public boolean directionX = true; // True - right, false - left
public boolean directionY = false; // True - up, false - down
public static final int Y_STARTING_POSITION = 0;
public static final int X_STARTING_POSITION = 0;
public Ball()
{
switch (this.getStartingSide())
{
case 0: // Left
{
this.directionX = true;
this.directionY = true;
this.x = this.getRandomHeight();
this.y = this.getRandomWidth();
break;
}
case 1: // Right
{
this.directionX = false;
this.directionY = false;
this.x = this.getRandomHeight();
this.y = this.getRandomWidth();
break;
}
case 2: // Top
{
this.directionX = true;
this.directionY = false;
this.x = this.getRandomWidth();
this.y = this.getRandomHeight();
break;
}
case 3: // Bottom
{
this.directionX = false;
this.directionY = true;
this.x = this.getRandomWidth();
this.y = this.getRandomHeight();
break;
}
}
}
public int getX()
{
return this.x;
}
public void setX(int x)
{
this.x = x;
}
public int getY()
{
return this.y;
}
public void setY(int y)
{
this.y = y;
}
public void move()
{
if (this.directionX) // Right
{
this.x += this.velocity;
}
else // Left
{
this.x -= this.velocity;
}
if (this.directionY) // Up
{
this.y -= this.velocity;
}
else // Down
{
this.y += this.velocity;
}
}
#Override
public void run()
{
try
{
this.isCollision(); // Never called
Thread.sleep(20);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
/**
* Get a random number varies from 0 to the screen width.
*
* #return The random number.
*
*/
public int getRandomWidth()
{
Random random = new Random();
return random.nextInt((Program.getPanelWidth() - 0) + 1) + 0; // Minimum = 0,maximum = Program.panelWidth
}
/**
* Get a random number varies from 0 to the screen height.
*
* #return The random number.
*
*/
public int getRandomHeight()
{
Random random = new Random();
return random.nextInt((Program.getPanelHeight() - 0) + 1) + 0; // Minimum = 0,maximum = Program.panelHeight
}
/**
* Get the starting side of a ball.
*
* Left - 0.
* Right - 1.
* Top - 2.
* Bottom - 3.
*
* #return
*
*/
public int getStartingSide()
{
Random random = new Random();
return random.nextInt((4 - 0) + 1) + 0; // Minimum = 0,maximum = 3
}
public void isCollision()
{
System.out.println("SSSSSSSSSSSSSSSS");
if (Math.sqrt(Math.pow(MyPanel.playerX + MyPanel.playerRadius - this.getX() + this.radius,2)
+ Math.pow(MyPanel.playerY + MyPanel.playerRadius - this.getY() + this.radius,2))
<= MyPanel.playerRadius + this.radius) // A collision
{
System.exit(0);
}
}
} // End of Ball class
MyPanel.java:
public class MyPanel extends JPanel implements KeyListener
{
private static final long serialVersionUID = 1L;
private static final Color BACKGROUND_COLOR = Color.WHITE;
private static final Color NPC_BALLS_COLOR = Color.RED;
// The player is an oval
public static int playerRadius = 35;
public static int playerX;
public static int playerY;
// True - first player position, false - otherwise
private boolean playerPosition = true;
// Array of all the balls threads
public static ArrayList<Ball> balls = new ArrayList<Ball>();
public MyPanel()
{
this.setBackground(MyPanel.BACKGROUND_COLOR);
this.setFocusable(true);
this.addKeyListener(this);
new Timer(10,new UpdateUI());
}
// Drawing
#Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
final double PANEL_WIDTH = this.getWidth();
final double PANEL_HEIGHT = this.getHeight();
if (this.playerPosition)
{
MyPanel.playerX = (int)(PANEL_WIDTH / 2 - MyPanel.playerRadius);
MyPanel.playerY = (int)(PANEL_HEIGHT / 2 - MyPanel.playerRadius);
this.playerPosition = false;
}
// Drawing the player
g.setColor(Color.BLACK);
g.fillOval(playerX,playerY, MyPanel.playerRadius * 2, MyPanel.playerRadius * 2);
// Drawing npc's balls
g.setColor(MyPanel.NPC_BALLS_COLOR);
for (Ball ball: MyPanel.balls) // ConcurrentModificationException
{
if (ball.isAlive())
{
ball.start();
}
ball.move();
repaint();
g.fillOval(ball.getX(), ball.getY(),
ball.radius * 2, ball.radius * 2);
}
}
// Keyboard listeners
#Override
public void keyPressed(KeyEvent e)
{
switch (e.getKeyCode())
{
case KeyEvent.VK_W: // Up
{
MyPanel.playerY -= 10;
repaint();
break;
}
case KeyEvent.VK_S: // Down
{
MyPanel.playerY += 10;
repaint();
break;
}
case KeyEvent.VK_D: // Right
{
MyPanel.playerX += 10;
repaint();
break;
}
case KeyEvent.VK_A: // Left
{
MyPanel.playerX -= 10;
repaint();
break;
}
}
}
#Override
public void keyReleased(KeyEvent e)
{
}
#Override
public void keyTyped(KeyEvent e)
{
}
public class UpdateUI implements ActionListener
{
#Override
public void actionPerformed(ActionEvent e)
{
repaint();
}
}
} // End of MyPanel class
Program.java:
public class Program
{
private static int panelWidth;
private static int panelHeight;
public static void main(String[] args)
{
MyFrame frame = new MyFrame();
Program.panelWidth = frame.getWidth();
Program.panelHeight = frame.getHeight();
// Generate a ball each 2 seconds
while (true)
{
try
{
MyPanel.balls.add(new Ball());
Thread.sleep(500);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
} // End of main method
public static int getPanelWidth()
{
return Program.panelWidth;
}
public static int getPanelHeight()
{
return Program.panelHeight;
}
}
The JFrame is nothing special and just adds the JPanel to it and so.
So my isCollision() method is never called even if It's on my run() method of my Thread. How come?
You never started the Thread implemented by your Ball class.
The ConcurrentModificationException is due to the fact that you are adding balls to an ArrayList which is by nature a thread-unsafe datastructure if you don't synchronize it externally. Here you are adding in a thread while iterating the list in the EDT (Event Dispatch Thread). Either you synchronize on the list, or you use a thread-safe data structure (for iteration you still may need to lock the full list).
Have a look at Collections.synchronizedList or CopyOnWriteArrayList (the latter doesn't need synchronizing for iteration).
However, synchronization on each insertion and each iteration seems very inefficient to me, especially because you are aiming for a game which requires fast rendering and background processing. It may be sufficient for a basic game though.
As a sidenote: a better technique for a game would be to use double buffering: render the game graphics in a background thread e.g. on a BufferedImage, and when done, switch the two buffers so that the one you just drew is now displayed on screen, and the other one can be used again for drawing the next frame. You might need a synchronization checkpoint between frames. But this is slightly more advanced, so if you are just starting in Java, I wouldn't spend too much time on it and keep things simple.
You need to call the repaint method in your while loop in the main method so run() can be called. You can do it with this:
panel.repaint():
Also, You must call the run method. You can do it in ball or in the panel.
ball.isAlive() always return false bucause your thread has not been started. If you want to start your threads in paintComponent() method you shouldn't use this method.
public class MyPanel extends JPanel implements KeyListener
{
private static final long serialVersionUID = 1L;
private static final Color BACKGROUND_COLOR = Color.WHITE;
private static final Color NPC_BALLS_COLOR = Color.RED;
// The player is an oval
public static int playerRadius = 35;
public static int playerX;
public static int playerY;
// True - first player position, false - otherwise
private boolean playerPosition = true;
private boolean ballsStarted;
// Array of all the balls threads
public static ArrayList<Ball> balls = new ArrayList<Ball>();
public MyPanel()
{
this.setBackground(MyPanel.BACKGROUND_COLOR);
this.setFocusable(true);
this.addKeyListener(this);
new Timer(10,new UpdateUI());
}
// Drawing
#Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
final double PANEL_WIDTH = this.getWidth();
final double PANEL_HEIGHT = this.getHeight();
if (this.playerPosition)
{
MyPanel.playerX = (int)(PANEL_WIDTH / 2 - MyPanel.playerRadius);
MyPanel.playerY = (int)(PANEL_HEIGHT / 2 - MyPanel.playerRadius);
this.playerPosition = false;
}
// Drawing the player
g.setColor(Color.BLACK);
g.fillOval(playerX,playerY, MyPanel.playerRadius * 2, MyPanel.playerRadius * 2);
// Drawing npc's balls
g.setColor(MyPanel.NPC_BALLS_COLOR);
for (Ball ball: MyPanel.balls) // ConcurrentModificationException
{
if (!ballsStarted)
{
ball.start();
}
ball.move();
repaint();
g.fillOval(ball.getX(), ball.getY(),
ball.radius * 2, ball.radius * 2);
}
ballsStarted = true;
}
// Keyboard listeners
#Override
public void keyPressed(KeyEvent e)
{
switch (e.getKeyCode())
{
case KeyEvent.VK_W: // Up
{
MyPanel.playerY -= 10;
repaint();
break;
}
case KeyEvent.VK_S: // Down
{
MyPanel.playerY += 10;
repaint();
break;
}
case KeyEvent.VK_D: // Right
{
MyPanel.playerX += 10;
repaint();
break;
}
case KeyEvent.VK_A: // Left
{
MyPanel.playerX -= 10;
repaint();
break;
}
}
}
#Override
public void keyReleased(KeyEvent e)
{
}
#Override
public void keyTyped(KeyEvent e)
{
}
public class UpdateUI implements ActionListener
{
#Override
public void actionPerformed(ActionEvent e)
{
repaint();
}
}
}
So I made a painting class which has got an ontouchevent method where i set the xpos of my rectangle to the xpos of the touch event but the rectangle isnt moving! how can I correct that?
rectangle class:
public class myRectangle{
public int xpos;
public int ypos;
public int size;
private Paint paint;
public myRectangle(){
size = 40;
paint = new Paint();
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.BLUE);
}
public void drawRectangle(Canvas c,int x, int y){
c.drawRect(x, y, size, size, paint);
}
}
and my paint view:
public class Painting extends View {
myRectangle player;
float x;
float y;
public Painting(Context context) {
super(context);
player = new myRectangle();
// TODO Auto-generated constructor stub
}
#Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
x = event.getX();
y = event.getY();
String s = Float.toString(event.getX());
String c = Float.toString(event.getX());
Log.d(c, s);
return super.onTouchEvent(event);
}
#Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
player.drawRectangle(canvas, (int)x, (int)y);
}
}
I can also post the main activity if needed
the only thing missing is the invalidate() call in your onTouchEvent. invalidate() schedule a draw
I am using a ContactListener to listen for any contact, and if collision is detected between the ball and ground, the ball should get an impulse in the upward direction, which is provided in the void endContact() function of the ContactListener class. But this impulse is having no effect at all, for any impulse value. The ball just bounces off the same distance for any impulse value. What am I doing wrong. Here's the full code:
public class Game implements ApplicationListener {
World world ;
Box2DDebugRenderer debugRenderer;
OrthographicCamera camera;
static final float BOX_STEP=1/60f;
static final int BOX_VELOCITY_ITERATIONS=8;
static final int BOX_POSITION_ITERATIONS=3;
static final float WORLD_TO_BOX=0.01f;
static final float BOX_WORLD_TO=100f;
Rectangle ball;
Body body;
#Override
public void create() {
world = new World(new Vector2(0, -100), true);
camera = new OrthographicCamera();
camera.viewportHeight = 480;
camera.viewportWidth = 800;
camera.position.set(camera.viewportWidth * .5f, camera.viewportHeight * .5f, 0f);
camera.update();
//Ground body
BodyDef groundBodyDef =new BodyDef();
groundBodyDef.position.set(new Vector2(0, 10));
Body groundBody = world.createBody(groundBodyDef);
PolygonShape groundBox = new PolygonShape();
groundBox.setAsBox((camera.viewportWidth) * 2, 10.0f);
groundBody.createFixture(groundBox, 0.0f);
//Dynamic Body
BodyDef bodyDef = new BodyDef();
bodyDef.type = BodyType.DynamicBody;
bodyDef.position.set(camera.viewportWidth / 8, camera.viewportHeight / 2);
body = world.createBody(bodyDef);
// create a Rectangle to logically represent the ball
CircleShape dynamicCircle = new CircleShape();
dynamicCircle.setRadius(40f);
FixtureDef fixtureDef = new FixtureDef();
fixtureDef.shape = dynamicCircle;
fixtureDef.density = 1.0f;
fixtureDef.friction = 0.0f;
fixtureDef.restitution =1f;
body.createFixture(fixtureDef);
debugRenderer = new Box2DDebugRenderer();
listener listener1=new listener();
world.setContactListener(listener1);
}
#Override
public void render() {
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
debugRenderer.render(world, camera.combined);
world.step(BOX_STEP, BOX_VELOCITY_ITERATIONS, BOX_POSITION_ITERATIONS);
}
class listener implements ContactListener
{
#Override
public void beginContact(Contact contact) {
// TODO Auto-generated method stub
}
#Override
public void endContact(Contact contact) {
// TODO Auto-generated method stub
body.applyLinearImpulse(0, 500000f, body.getWorldCenter().x, body.getWorldCenter().y, true);
//body.setLinearVelocity(0,50000000);
System.out.println("Collision detected");
}
#Override
public void preSolve(Contact contact, Manifold oldManifold) {
// TODO Auto-generated method stub
}
#Override
public void postSolve(Contact contact, ContactImpulse impulse) {
// TODO Auto-generated method stub
}
};
#Override
public void resize(int width, int height) {
}
#Override
public void pause() {
}
#Override
public void resume() {
}
#Override
public void dispose() {
}
}
In the original C++ version, EndContact is called inside the Step function, which is a time when you cannot alter anything in the world because the engine is still using it. I would think that the Java version is the same. You will probably need to make a note of the fact that the ball has bounced, and apply the impulse after the Step has finished.
The reason that there is no impact on of impulse is you are try to apply impulse in the endcontact method.
In box2d ContactListener methods you cannot change the property or position of body.
You can do like this
boolean b;
#Override
public void endContact(Contact contact) {
// TODO Auto-generated method stub
//body.applyLinearImpulse(0, 500000f, body.getWorldCenter().x, body.getWorldCenter().y, true);
//body.setLinearVelocity(0,50000000);
b = true;
System.out.println("Collision detected");
}
In you update method.....
if(b)
{
body.applyLinearImpulse(0, 500000f, body.getWorldCenter().x, body.getWorldCenter().y, true);
}
I'm a beginner in Android programming, and I'm working on a small bubble shooter game. However, I face a weird problem which I cannot figure out. I have a piece of code which handles the launcher of the app, if I program the whole code in class, the app runs smooth. However, if I 'cut' the code into different classes there a noticeable lag in the movement of the launcher.
My main question is: what can cause this lag, and what is the best approach to avoid this (now and in the future).
Thanks in advance,
Kind regards,
This is my code when I program everything in one class.
package com.example.bubbleshootergame;
// imports are delete to shorten the post
public class GameThree extends Activity implements OnTouchListener {
OurView v;
Bitmap launcher;
float x, y, rotationAngle;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
v = new OurView(this);
v.setOnTouchListener(this);
launcher = BitmapFactory.decodeResource(getResources(),
R.drawable.launcher);
setContentView(v);
}
#Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
v.pause();
}
#Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
v.resume();
}
public class OurView extends SurfaceView implements Runnable {
Thread t = null;
SurfaceHolder holder;
boolean bool = false;
public OurView(Context context) {
super(context);
// TODO Auto-generated constructor stub
holder = getHolder();
}
#Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
View content = getWindow().findViewById(Window.ID_ANDROID_CONTENT);
// x & y are the width and height of the usable screen size
x = content.getWidth();
y = content.getHeight();
}
#Override
public void run() {
// TODO Auto-generated method stub
while (bool == true) {
if (!holder.getSurface().isValid()) {
continue;
}
Canvas c = holder.lockCanvas();
Paint Blackline = new Paint();
Blackline.setColor(Color.rgb(0, 0, 0));
Blackline.setStrokeWidth(10);
// background color of canvas
c.drawARGB(255, 255, 255, 255);
c.drawRect(0, (float) 0.85*y, x, (float) 0.84*y, Blackline);
// rotate by angle 'rotationAngle' around point x/2 and y
// this corresponds the middle of the launcher
c.rotate(rotationAngle, x / 2, y - (launcher.getHeight() / 2));
// draw the bitmap (this case the launcher) around the center of
// the width of the launcher and bottom of the launcher
c.drawBitmap(launcher, x / 2 - (launcher.getWidth() / 2), y
- (launcher.getHeight()), null);
holder.unlockCanvasAndPost(c);
}
}
public void pause() {
// TODO Auto-generated method stub
bool = false;
while (true) {
try {
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
break;
}
t = null;
}
public void resume() {
// TODO Auto-generated method stub
bool = true;
t = new Thread(this);
t.start();
}
}
#Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
float currentX = event.getX();
float currentY = event.getY();
if (currentY >= 0.85*y ){
}
else
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE: {
double rotationAngleRadians = Math.atan2(currentX - x / 2, y
- currentY);
rotationAngle = (int) Math.toDegrees(rotationAngleRadians);
return true;
}
}
return true;
}
}
Here are the code block when uses different classes:
MainActivity
package com.gabrudar.conquestappgame;
public class MainActivity extends Activity implements OnTouchListener {
GameView view;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
view = new GameView(this);
view.setOnTouchListener(this);
setContentView(view);
}
#Override
protected void onPause() {
super.onPause();
view.pause();
}
#Override
protected void onResume() {
super.onResume();
view.resume();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
try {
Thread.sleep(50);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
view.processTouch(event);
return true;
}
}
GameView:
package com.gabrudar.conquestappgame;
public class GameView extends SurfaceView implements Runnable {
Thread gameThread = null;
SurfaceHolder holder;
boolean continueRunning = false;
Bitmap blob;
Bitmap background;
Sprite sprite;
Rect screenRect;
Bitmap Launcher;
LauncherC launcher;
long startTime;
float deltaTime;
public GameView(Context context) {
super(context);
holder = getHolder();
screenRect = new Rect();
background = BitmapFactory.decodeResource(getResources(), R.drawable.androidbg);
blob = BitmapFactory.decodeResource(getResources(), R.drawable.spritesheet);
Launcher = BitmapFactory.decodeResource(getResources(),
R.drawable.launcher);
launcher = new LauncherC(Launcher);
}
#Override
public void run() {
startTime = System.nanoTime();
while (continueRunning == true){
if (!holder.getSurface().isValid()){
continue;
}
deltaTime = (System.nanoTime() - startTime)/1000000;
startTime = System.nanoTime();
Canvas c = holder.lockCanvas();
onDraw(c);
holder.unlockCanvasAndPost(c);
}
}
public void pause() {
continueRunning = false;
while(true){
try{
gameThread.join();
}catch(InterruptedException e){
e.printStackTrace();
}
break;
}
gameThread = null;
}
public void resume() {
continueRunning = true;
gameThread = new Thread(this);
gameThread.start();
}
protected void update(float dt) {
}
protected void onDraw(Canvas canvas) {
this.getDrawingRect(screenRect);
canvas.drawBitmap(background, null, screenRect, null);
launcher.onDraw(canvas);
}
public void processTouch(MotionEvent me) {
launcher.Toucher(me);
}
}
Launcher:
package com.gabrudar.conquestappgame;
public class LauncherC {
float rotationAngle,x1,y1;
Bitmap L1;
public LauncherC(Bitmap Launcher){
L1 = Launcher;
}
public void onDraw(Canvas c) {
// TODO Auto-generated method stub
Paint Blackline = new Paint();
Blackline.setColor(Color.rgb(0, 0, 0));
Blackline.setStrokeWidth(10);
x1 = c.getWidth();
y1 = c.getHeight();
c.drawRect(0, (float) 0.85 * y1, x1, (float) 0.84 * y1, Blackline);
c.rotate(rotationAngle, x1 / 2, y1 - (L1.getHeight() / 2));
c.drawBitmap(L1, x1 / 2 - (L1.getWidth() / 2), y1
- (L1.getHeight()), null);
}
public void Toucher(MotionEvent event){
// TODO Auto-generated method stub
float currentX = event.getX();
float currentY = event.getY();
if (currentY >= 0.85 * y1) {
} else
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE: {
double rotationAngleRadians = Math.atan2(currentX - x1 / 2, y1
- currentY);
rotationAngle = (int) Math.toDegrees(rotationAngleRadians);
break;
}
}
}
}
Well one glaring difference I see is this in your "separated" code. I don't see it in the original code, and it will definitely induce a lag, since you're sleeping 50ms every time you receive a touch event. That can happen many times per second with a drag-type movement.
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
try {
Thread.sleep(50);
....
So I have this method that when i touch the screen my sprite will jump. Now the problem is when I continuously touch the screen the sprite will jump again and again. What I want to do is if it jumps, the jump method cannot be called unless my sprite hits the ground.
Here is the code.
public class PhyiscsActivity extends BaseGameActivity implements IAccelerometerListener, IOnSceneTouchListener{
private static final int CAMERA_WIDTH = 720;
private static final int CAMERA_HEIGHT = 480;
private Camera mCamera;
private BitmapTextureAtlas mBitmapTextureAtlas;
private TiledTextureRegion mTextureRegion;
private Scene mScene;
private FixtureDef mFixtureDef = PhysicsFactory.createFixtureDef(1,-10f, 0.5f);
private PhysicsWorld mPhysicsWorld;
private Body body;
private AnimatedSprite facebox;
private FixtureDef wallfixture = PhysicsFactory.createFixtureDef(-1,0.5f, 0.5f);
#Override
public Engine onLoadEngine() {
// TODO Auto-generated method stub
this.mCamera = new Camera(0,0,CAMERA_WIDTH, CAMERA_HEIGHT);
final EngineOptions mEngineOptions = new EngineOptions(true, ScreenOrientation.LANDSCAPE, new RatioResolutionPolicy(CAMERA_WIDTH, CAMERA_HEIGHT),this.mCamera);
mEngineOptions.getTouchOptions().setRunOnUpdateThread(true);
return new Engine(mEngineOptions);
}
#Override
public void onLoadResources() {
// TODO Auto-generated method stub
this.mBitmapTextureAtlas = new BitmapTextureAtlas(128,128, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
this.mTextureRegion = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(mBitmapTextureAtlas, this, "gfx/face_box_tiled.png", 0, 0, 2, 1);
this.mEngine.getTextureManager().loadTexture(this.mBitmapTextureAtlas);
}
#Override
public Scene onLoadScene() {
// TODO Auto-generated method stub
this.mEngine.registerUpdateHandler(new FPSLogger());
this.mScene = new Scene();
this.mScene.setBackground(new ColorBackground(1,1,1));
this.mPhysicsWorld = new PhysicsWorld(new Vector2(0,SensorManager.GRAVITY_EARTH),false);
// This is the walls
final Shape roof = new Rectangle(0, 0, CAMERA_WIDTH, 2);
final Shape ground = new Rectangle(0,CAMERA_HEIGHT - 2,CAMERA_WIDTH,2);
final Shape left = new Rectangle(0,0,2,CAMERA_HEIGHT);
final Shape right = new Rectangle(CAMERA_WIDTH -2, 0,2,CAMERA_HEIGHT);
PhysicsFactory.createBoxBody(this.mPhysicsWorld, ground, BodyType.StaticBody, wallfixture);
PhysicsFactory.createBoxBody(this.mPhysicsWorld, roof, BodyType.StaticBody, wallfixture);
PhysicsFactory.createBoxBody(this.mPhysicsWorld, left, BodyType.StaticBody, wallfixture);
PhysicsFactory.createBoxBody(this.mPhysicsWorld, right, BodyType.StaticBody, wallfixture);
// This is the Sprite
facebox = new AnimatedSprite(30,(CAMERA_HEIGHT - 2) - this.mTextureRegion.getHeight() ,this.mTextureRegion);
body = PhysicsFactory.createBoxBody(this.mPhysicsWorld, facebox, BodyType.DynamicBody, mFixtureDef);
this.mScene.attachChild(facebox);
this.mScene.registerUpdateHandler(this.mPhysicsWorld);
this.mPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(facebox,body,true,true));
this.mScene.setOnSceneTouchListener(this);
return this.mScene;
}
#Override
public void onLoadComplete() {
// TODO Auto-generated method stub
}
//Accelerometer
#Override
public void onAccelerometerChanged(AccelerometerData pAccelerometerData) {
// TODO Auto-generated method stub
final Vector2 gravity = Vector2Pool.obtain(pAccelerometerData.getX()* 3, 10);
this.mPhysicsWorld.setGravity(gravity);
Vector2Pool.recycle(gravity);
}
#Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
this.enableAccelerometerSensor(this);
}
#Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
this.disableAccelerometerSensor();
}
//This is where i make the sprite jump
#Override
public boolean onSceneTouchEvent(Scene pScene, TouchEvent pSceneTouchEvent) {
pSceneTouchEvent.isActionDown();{
this.jump(facebox);
}
return false;
}
public void jump(AnimatedSprite sprite){
boolean jumping = false;
if(!jumping ){
body.setLinearVelocity(new Vector2(body.getLinearVelocity().x,-8f));
}
}
public void jump(AnimatedSprite sprite){
if(!jumping){
body.setLinearVelocity(new Vector2(body.getLinearVelocity().x,-10));
jumping = true;
}
}
#Override
public void beginContact(Contact contact) {
// TODO Auto-generated method stub
jumping = true;
}
#Override
public void endContact(Contact contact) {
// TODO Auto-generated method stub
jumping = false;
}
I don't know why the beginContact and endContact isn't initialzing. are there things that i should do to initialize this? example like updating a handler? contactlistener?
You need to have a method wich tell you if your player is jumping or not.
public void jump(AnimatedSprite sprite){
if( isJumping(sprite)){
body.setLinearVelocity(new Vector2(body.getLinearVelocity().x,-8f));
}
In this method you should put the way to compute if the player is jumping. Like if he is touching a wall (if player's body (x,y) is in a wall (rectangle))
Ok you are using box2d to make physics =)
You have to create a ContactListener, you have to implement this class and the function ou want to add.
http://code.google.com/p/andenginephysicsbox2dextension/source/browse/src/com/badlogic/gdx/physics/box2d/ContactListener.java?r=1605f6e82f710ef9ebbe07632d6b055239d3b520
public void beginContact (Contact contact);
public void endContact (Contact contact);
The contact object will countain your objects (Fixture) that are touching. You just have to check and set jumping to false when the body is touching and true when you call jump and you can jump, set jumping to true;
Ok?
#Override
public void beginContact(Contact contact) {
// TODO Auto-generated method stub
jumping = true;
}
#Override
public void endContact(Contact contact) {
// TODO Auto-generated method stub
jumping = false;
}
This is false.. I would think of it like that only:
#Override
public void beginContact(Contact contact) {
jumping = false; //you touched ground so you aren't jumping anymore
}
#Override
public void endContact(Contact contact) {
jumping = true; //you leave ground so you're jumping
}
and one jump method (not two):
public void jump(AnimatedSprite sprite){
if(!jumping ){
jumping = true;
body.setLinearVelocity(new Vector2(body.getLinearVelocity().x,-8f));
}
}
You see?;