How do you add movement event to the sprite?
I really do not know how to use input events i have checked out tons of different links on this website and the others and none have really helped. I need someone to explain and help me out with this please.
package com.KDevs.test;
import java.util.Random;
import java.util.Vector;
import org.andengine.engine.camera.Camera;
import org.andengine.engine.options.EngineOptions;
import org.andengine.engine.options.ScreenOrientation;
import org.andengine.engine.options.resolutionpolicy.RatioResolutionPolicy;
import org.andengine.entity.modifier.IEntityModifier;
import org.andengine.entity.scene.IOnSceneTouchListener;
import org.andengine.entity.scene.Scene;
import org.andengine.entity.scene.background.Background;
import org.andengine.entity.sprite.Sprite;
import org.andengine.extension.physics.box2d.PhysicsConnector;
import org.andengine.extension.physics.box2d.PhysicsFactory;
import org.andengine.extension.physics.box2d.PhysicsWorld;
import org.andengine.input.touch.TouchEvent;
import org.andengine.opengl.texture.atlas.bitmap.BitmapTextureAtlas;
import org.andengine.opengl.texture.atlas.bitmap.BitmapTextureAtlasTextureRegionFactory;
import org.andengine.opengl.texture.region.ITextureRegion;
import org.andengine.ui.activity.BaseGameActivity;
import android.hardware.SensorManager;
import android.util.Log;
import android.view.MotionEvent;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.Body;
import com.badlogic.gdx.physics.box2d.BodyDef.BodyType;
import com.badlogic.gdx.physics.box2d.FixtureDef;
public class Main extends BaseGameActivity {
Random rand;
Scene scene;
int x , y;
protected static final int CAMERA_WIDTH = 800;
protected static final int CAMERA_HEIGHT = 480;
BitmapTextureAtlas playerTexture;
ITextureRegion playerTexureRegion;
BitmapTextureAtlas blockTexture;
ITextureRegion blockTexureRegion;
BitmapTextureAtlas ZeusTexture;
ITextureRegion ZeusTexureRegion;
PhysicsWorld physicsWorld;
Sprite sPlayer;
Sprite block;
#Override
public EngineOptions onCreateEngineOptions() {
// TODO Auto-generated method stub
Camera mCamera = new Camera(0, 0, CAMERA_WIDTH, CAMERA_HEIGHT);
EngineOptions options = new EngineOptions(true,
ScreenOrientation.LANDSCAPE_FIXED, new RatioResolutionPolicy(
CAMERA_WIDTH, CAMERA_HEIGHT), mCamera);
return options;
}
#Override
public void onCreateResources(
OnCreateResourcesCallback pOnCreateResourcesCallback)
throws Exception {
// TODO Auto-generated method stub
loadGfx();
// resource
pOnCreateResourcesCallback.onCreateResourcesFinished();
}
private void loadGfx() {
// TODO Auto-generated method stub
BitmapTextureAtlasTextureRegionFactory.setAssetBasePath("gfx/");
ZeusTexture = new BitmapTextureAtlas(getTextureManager(), 64, 64);
ZeusTexureRegion = BitmapTextureAtlasTextureRegionFactory
.createFromAsset(ZeusTexture, this, "zeus.png", 0, 0);
ZeusTexture.load();
// width and height power of 2^x
playerTexture = new BitmapTextureAtlas(getTextureManager(), 64, 64);
playerTexureRegion = BitmapTextureAtlasTextureRegionFactory
.createFromAsset(playerTexture, this, "player.png", 0, 0);
playerTexture.load();
blockTexture = new BitmapTextureAtlas(getTextureManager(), 64, 256);
blockTexureRegion = BitmapTextureAtlasTextureRegionFactory
.createFromAsset(blockTexture, this, "block.png", 0, 0);
blockTexture.load();
}
#Override
public void onCreateScene(OnCreateSceneCallback pOnCreateSceneCallback)
throws Exception {
// TODO Auto-generated method stub
this.scene = new Scene();
this.scene.setBackground(new Background(0, 0, 0));
physicsWorld = new PhysicsWorld(new Vector2(0,SensorManager.GRAVITY_MARS), false);
this.scene.registerUpdateHandler(physicsWorld);
pOnCreateSceneCallback.onCreateSceneFinished(this.scene);
}
#Override
public void onPopulateScene(Scene pScene,
OnPopulateSceneCallback pOnPopulateSceneCallback) throws Exception {
int counter = 0 , timer = 0;
int x2 , y2;
counter++;
x =CAMERA_WIDTH /2;
y = 416;
x2 = 300;
y2= -40;
//if(counter % 100 == 0){
//x++;
//timer++;
//}
rand = new Random();
int area = rand.nextInt(800);
//Player
sPlayer = new Sprite(x, y,
playerTexureRegion, this.mEngine.getVertexBufferObjectManager());
scene.registerTouchArea(sPlayer);
scene.setTouchAreaBindingOnActionDownEnabled(true);
scene.setTouchAreaBindingOnActionMoveEnabled(true);
//Block
block = new Sprite(x2 , y2,
blockTexureRegion, this.mEngine.getVertexBufferObjectManager());
//Zeus Sprite
Sprite zeus = new Sprite(CAMERA_WIDTH/2 , 11,
ZeusTexureRegion, this.mEngine.getVertexBufferObjectManager());
//sPlayer.setRotation(45.0f);
//I knew this shit would be helpful
block.setRotation(90.0f);
FixtureDef PLAYERBlock = PhysicsFactory.createFixtureDef(5.0f, 0.0f, 0.0f);
Body body = PhysicsFactory.createCircleBody(physicsWorld, block, BodyType.DynamicBody, PLAYERBlock);
this.scene.attachChild(sPlayer);
this.scene.attachChild(block);
this.scene.attachChild(zeus);
physicsWorld.registerPhysicsConnector(new PhysicsConnector(block, body,true,false));
pOnPopulateSceneCallback.onPopulateSceneFinished();
}
public boolean onTouchEvent(MotionEvent event) {
if(event.getAction==MotionEvent.ACTION_DOWN){
Log.e("Touching", "Touching the Screen");
}
else if(event.getAction==MotionEvent.ACTION_UP){
Log.e("Touching up", "Touching the Screen up");}
return true;
}
}
First of all I would extend from SimpleBaseGameActivity.
You need to override onAreaTouch method of a sprite object. This way:
Sprite sprite = new Sprite(x, y, texture, this.getVertexBufferObjectManager()) {
public boolean onAreaTouched(org.andengine.input.touch.TouchEvent pSceneTouchEvent, float pTouchAreaLocalX, float pTouchAreaLocalY)
{
//<DO ANYTHING this.setPosition(x,y) method to move the sprite>
this.setPosition(this.getX() + 10 , this.getY() + 10);
return true;
};
};
scene.setTouchAreaBindingOnActionDownEnabled(true);
scene.registerTouchArea(sprite);
Related
I am trying to implement autoparrallexbackgrounf using andengine 2 for sample. But its not working for me. A still screen appears with player sprite still at centre. Here are my two classes.. can anybody help what i am doing wrong?
package com.example.movingbackground;
import org.andengine.engine.camera.Camera;
import org.andengine.engine.options.EngineOptions;
import org.andengine.engine.options.ScreenOrientation;
import org.andengine.engine.options.WakeLockOptions;
import org.andengine.engine.options.resolutionpolicy.FillResolutionPolicy;
import org.andengine.entity.scene.Scene;
import org.andengine.opengl.texture.atlas.bitmap.BitmapTextureAtlasTextureRegionFactory;
import org.andengine.ui.activity.SimpleBaseGameActivity;
public class MainActivity extends SimpleBaseGameActivity
{
public Camera mCamera = null;
private static final int width = 480;
private static final int height = 800;
private GamePlay mScene = null;
public EngineOptions onCreateEngineOptions()
{
mCamera = new Camera(0, 0, width, height);
EngineOptions eo = new EngineOptions(true, ScreenOrientation.PORTRAIT_FIXED, new FillResolutionPolicy(), mCamera);
eo.setWakeLockOptions(WakeLockOptions.SCREEN_ON);
return eo;
}
protected void onCreateResources()
{
BitmapTextureAtlasTextureRegionFactory.setAssetBasePath("gfx/");
loadRes();
}
private void loadRes()
{
mScene = new GamePlay(this);
}
protected Scene onCreateScene()
{
return mScene;
}
}
Scene Class goes like :
package com.example.movingbackground;
import org.andengine.entity.scene.Scene;
import org.andengine.entity.scene.background.AutoParallaxBackground;
import org.andengine.entity.scene.background.ParallaxBackground.ParallaxEntity;
import org.andengine.entity.sprite.Sprite;
import org.andengine.opengl.texture.TextureOptions;
import org.andengine.opengl.texture.atlas.bitmap.BitmapTextureAtlas;
import org.andengine.opengl.texture.atlas.bitmap.BitmapTextureAtlasTextureRegionFactory;
import org.andengine.opengl.texture.region.TextureRegion;
public class GamePlay extends Scene
{
private MainActivity mCxt = null;
private Sprite background_1 = null;
private Sprite background_2 = null;
private Sprite background_3 = null;
private AutoParallaxBackground bg = null;
private Sprite player = null;
public GamePlay(MainActivity mCxt)
{
this.mCxt = mCxt;
bg = new AutoParallaxBackground(0.0f, 0.0f, 0.0f, 1f);
background_1 = new Sprite(0, 0, getSpriteRegion(640, 1136, "bg.png"), this.mCxt.getVertexBufferObjectManager());
background_2 = new Sprite(0, 0, getSpriteRegion(640, 1136, "bg.png"), this.mCxt.getVertexBufferObjectManager());
background_3 = new Sprite(0, 0, getSpriteRegion(640, 1136, "bg.png"), this.mCxt.getVertexBufferObjectManager());
player = new Sprite(100, 100, getSpriteRegion(512, 512, "icon.png"), this.mCxt.getVertexBufferObjectManager())
{
#Override
protected void onManagedUpdate(float pSecondsElapsed)
{
// TODO Auto-generated method stub
super.onManagedUpdate(pSecondsElapsed);
player.setX(player.getX()+10);
}
};
attachChilds();
setBackground(bg);
}
private void attachChilds()
{
bg.attachParallaxEntity(new ParallaxEntity(0.0f, background_1, 640, 1136));
bg.attachParallaxEntity(new ParallaxEntity(0.0f, background_2, 640, 1136));
bg.attachParallaxEntity(new ParallaxEntity(0.0f, background_3, 640, 1136));
attachChild(player);
this.mCxt.mCamera.setChaseEntity(player);
}
#Override
protected void onManagedUpdate(float pSecondsElapsed)
{
// TODO Auto-generated method stub
super.onManagedUpdate(pSecondsElapsed);
this.mCxt.mCamera.updateChaseEntity();
}
private TextureRegion getSpriteRegion(int width, int height, String name)
{
BitmapTextureAtlas atlas = new BitmapTextureAtlas(this.mCxt.getTextureManager(), width, height, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
atlas.load();
return BitmapTextureAtlasTextureRegionFactory.createFromAsset(atlas, this.mCxt.getAssets(), name , 0 , 0);
}
}
I only worked with a Parllax Background in andengine right now, but I think the problem is, that you create all your ParallaxEntitys with 0.0f as parallaxFactor. (The first parameter is the parallaxFactor, isn't it?)
I'm not sure, but I think something like
bg.attachParallaxEntity(new ParallaxEntity(5.0f, background_1, 640, 1136));
bg.attachParallaxEntity(new ParallaxEntity(10.0f, background_2, 640, 1136));
bg.attachParallaxEntity(new ParallaxEntity(15.0f, background_3, 640, 1136));
should work.
I want in my game to draw houses (huis = house) that fall continuesly at the sides of the screen. (On the grass as the 'world' moves downwards.'
But,having this code, and no trouble in the logcat i dont know why it doesnt draw the houses.
The 'main flow' of this code goes as follows: I created an arraylist that holds the house.png. Then through a for loop it adds a house when there is some space between it.
package com.mygdx.Papermadness;
import java.util.ArrayList;
import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.InputAdapter;
import com.badlogic.gdx.audio.Music;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.Texture.TextureWrap;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer.ShapeType;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector2;
public class Papermadness extends InputAdapter implements ApplicationListener {
private SpriteBatch huisBatch;
private Texture huisTexture;
private SpriteBatch batch;
private Sprite sprite;
private SpriteBatch spriteBatch;
private Sprite huisSprite;
private Texture spriteTexture;
private float scrollTimer = 0.0f;
private float huisVelocity = 200f;
private float huisLinksY = 2100;
private float huisLinksX = 0;
private float huisRechtsY = 2100;
private float huisRechtsX = 903;
private Sprite huis;
private ArrayList<Sprite> huisArray = new ArrayList<Sprite>();
Rectangle bounds;
Player player;
Paper paper;
ShapeRenderer sr;
#Override
public void create() {
player = new Player(new Vector2(50, 100), new Vector2(100, 100));
paper = new Paper(new Vector2(Gdx.input.getX(),Gdx.graphics.getHeight()-Gdx.input.getY()), new Vector2(50, 50));
sr = new ShapeRenderer();
spriteBatch = new SpriteBatch();
huisBatch = new SpriteBatch();
huisTexture = new Texture("huis.png");
huisSprite = new Sprite(huisTexture);
spriteTexture = new Texture("b2.png");
spriteTexture.setWrap(TextureWrap.Repeat, TextureWrap.Repeat);
sprite = new Sprite(spriteTexture);
sprite.setSize(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
batch = new SpriteBatch();
}
#Override
public void render() {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
float delta = Gdx.graphics.getDeltaTime();
scrollTimer += Gdx.graphics.getDeltaTime();
if (scrollTimer > 2f)
scrollTimer = 0.0f;
sprite.setV(scrollTimer + 2);
sprite.setV2(scrollTimer);
player.update();
paper.update();
spriteBatch.begin();
sprite.draw(spriteBatch);
for (int i = 0; i < huisArray.size(); i++) {
huisArray.get(i).setY(huisArray.get(i).getY() - huisVelocity * delta);
if (huisArray.get(i).getY() <= 200) {
huisArray.remove(i);
i--;
}
}
if (huisArray.size() > 0 && huisArray.get(0).getY() < 1200) {
addNewHuis();
}
huisBatch.begin();
for (int i = 0; i < huisArray.size(); i++) {
huisBatch.draw(huisArray.get(i), huisArray.get(i).getX(), huisArray.get(i).getY());
}
huisLinksY -= huisVelocity * delta;
huisRechtsY -= huisVelocity * delta;
batch.begin();
player.draw(batch);
paper.draw(batch);
batch.end();
sr.begin(ShapeType.Filled);
sr.setColor(Color.BLUE);
sr.setColor(Color.RED);
sr.setColor(Color.YELLOW);
sr.rect(Gdx.input.getX(), Gdx.graphics.getHeight() - Gdx.input.getY(), paper.getSize().x,
paper.getSize().y);
sr.end();
}
private void addNewHuis() {
huis = new Sprite();
huis.setY(1800);
huisArray.add(0, huis);
}
#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 dispose() {
// TODO Auto-generated method stub
}
}
Any help would be appreciated.
From my point of view, your house array is empty - so it does not have anything to draw. You create huisArray, but you do not add anything to it. So when you render() is called first, huisArray.size() == 0 is true.
for (int i = 0; i < huisArray.size(); i++) { //you do not step into this piece of code.
huisArray.get(i).setY(huisArray.get(i).getY() - huisVelocity * delta);
if (huisArray.get(i).getY() <= 200) {
huisArray.remove(i);
i--;
}
}
Then, you want to add a house if there are some houses there. But it's still empty so you do not add anything.
if (huisArray.size() > 0 && huisArray.get(0).getY() < 1200) {
addNewHuis();
}
And you attempt to draw still empty array:
huisBatch.begin();
for (int i = 0; i < huisArray.size(); i++) { //you do not step into this piece of code either
huisBatch.draw(huisArray.get(i), huisArray.get(i).getX(), huisArray.get(i).getY());
}
Solution: Add one-two huisSprite to huisArray in create().
Hope it helps :)
I use Libgdx and VLCj to play video, but the color is wrong (the left side on the image is ok).
I use DirectMediaPlayer to catch frame data from the memory, create texture and draw on the screen.
My code:
import java.awt.GraphicsEnvironment;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.IntBuffer;
import uk.co.caprica.vlcj.binding.LibVlc;
import uk.co.caprica.vlcj.player.MediaPlayerFactory;
import uk.co.caprica.vlcj.player.direct.BufferFormat;
import uk.co.caprica.vlcj.player.direct.BufferFormatCallback;
import uk.co.caprica.vlcj.player.direct.DirectMediaPlayer;
import uk.co.caprica.vlcj.player.direct.RenderCallbackAdapter;
import uk.co.caprica.vlcj.player.direct.format.RV32BufferFormat;
import uk.co.caprica.vlcj.runtime.RuntimeUtil;
import uk.co.caprica.vlcj.runtime.x.LibXUtil;
import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL10;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.Gdx2DPixmap;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.utils.GdxRuntimeException;
import com.sun.jna.Native;
import com.sun.jna.NativeLibrary;
public class MyGdxGame implements ApplicationListener {
private OrthographicCamera camera;
private Texture texture;
private BitmapFont font;
private SpriteBatch batch;
float w = 800;
float h = 600;
private BufferedImage image;
private MediaPlayerFactory factory;
private DirectMediaPlayer mediaPlayer;
private Pixmap pixmap;
#Override
public void create() {
w = Gdx.graphics.getWidth();
h = Gdx.graphics.getHeight();
camera = new OrthographicCamera();
camera.setToOrtho(false, w, h);
camera.update();
font = new BitmapFont();
batch = new SpriteBatch();
LibXUtil.initialise();
NativeLibrary.addSearchPath(RuntimeUtil.getLibVlcLibraryName(), "C:\\Users\\Dima\\Desktop\\vlc-2.1.0_64\\");
Native.loadLibrary(RuntimeUtil.getLibVlcLibraryName(), LibVlc.class);
image = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration().createCompatibleImage((int) w, (int) h);
image.setAccelerationPriority(1.0f);
String[] args = { "--no-video-title-show", "--verbose=3" };
String media = "C:\\video512.mp4";
factory = new MediaPlayerFactory(args);
mediaPlayer = factory.newDirectMediaPlayer(new TestBufferFormatCallback(), new TestRenderCallback());
mediaPlayer.playMedia(media);
System.out.println(LibVlc.INSTANCE.libvlc_get_version());
}
#Override
public void dispose() {
Gdx.app.exit();
}
#Override
public void render() {
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
batch.begin();
if (pixmap != null) {
texture = new Texture(pixmap);
batch.draw(texture, 0, 0, 800, 600);
}
font.draw(batch, "FPS: " + Gdx.graphics.getFramesPerSecond(), 10, 20);
batch.end();
}
private final class TestRenderCallback extends RenderCallbackAdapter {
public TestRenderCallback() {
super(((DataBufferInt) image.getRaster().getDataBuffer()).getData());
}
#Override
public void onDisplay(DirectMediaPlayer mediaPlayer, int[] data) {
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(data.length * 4).order(ByteOrder.nativeOrder());
IntBuffer intBuffer = byteBuffer.asIntBuffer();
intBuffer.put(data);
try {
long[] nativeData = new long[] { 0, 800, 600, Gdx2DPixmap.GDX2D_FORMAT_RGBA8888 };
Gdx2DPixmap pixmapData = new Gdx2DPixmap(byteBuffer, nativeData);
pixmap = new Pixmap(pixmapData);
} catch (Exception e) {
pixmap = null;
throw new GdxRuntimeException("Couldn't load pixmap from image data", e);
}
}
}
private final class TestBufferFormatCallback implements BufferFormatCallback {
#Override
public BufferFormat getBufferFormat(int sourceWidth, int sourceHeight) {
return new RV32BufferFormat((int) w, (int) h);
}
}
#Override
public void resize(int width, int height) {
}
#Override
public void pause() {
}
#Override
public void resume() {
}
}
If you know others ways to draw video in java, let me know.
Solved!
Method getBufferFormat in TestBufferFormatCallback class was not correct. Right variant:
#Override
public BufferFormat getBufferFormat(int sourceWidth, int sourceHeight) {
sourceWidth = 800;
sourceHeight = 600;
System.out.println("Got VideoFormat: " + sourceWidth + "x" + sourceHeight);
BufferFormat format = new BufferFormat("RGBA", sourceWidth, sourceHeight, new int[] { sourceWidth * 4 }, new int[] { sourceHeight });
return format;
}
I'm getting
Canvas: trying to use a recycled bitmap
android.graphics.Bitmap#4057a3a8
everytime i'm trying to show one image.
Image
When i delete bmp.recycle() everything goes well but i dont use this image in my code so i dont understand where the problem is.
package com.example.photobooth;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import android.os.Bundle;
import android.os.Environment;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Rect;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.ImageView;
public class EditorActivity extends Activity implements OnClickListener{
String path = null;
private int screen_height;
private int screen_width;
private Bitmap setUpImage(Bitmap image) {
int min_side = Math.min(screen_height, screen_width);
float scale_factor = (float) (((float) min_side / image.getWidth()) * 1.5);
float[] scalef = { scale_factor, scale_factor };
Bitmap scaled_image = ImageUtilities.scaleImage(image, scalef);
return scaled_image;
}
private void setUp() {
Bundle b = getIntent().getExtras();
if (b != null) {
path = b.getString("path");
}
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
this.screen_height = metrics.heightPixels;
this.screen_width = metrics.widthPixels;
int min_measure = Math.min(screen_width, screen_height);
// Make ImageView square
ImageView img = (ImageView) findViewById(R.id.photo_holder);
android.view.ViewGroup.LayoutParams lp = img.getLayoutParams();
lp.height = min_measure;
img.setLayoutParams(lp);
Bitmap bmp = BitmapFactory.decodeFile(path);
final Bitmap ready_image = setUpImage(bmp);
bmp.recycle();
ImageView iv = (ImageView) findViewById(R.id.photo_holder);
iv.setImageBitmap(ready_image);
// set up touch event for imageview(photo_holder)
img.setOnTouchListener(new OnTouchListener() {
float touch_x, touch_y, scrolled_x = 0.0f, scrolled_y = 0.0f;
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
touch_x = event.getX();
touch_y = event.getY();
break;
case MotionEvent.ACTION_MOVE:
float cur_x = event.getX();
float cur_y = event.getY();
float scroll_x = -cur_x + touch_x;
float scroll_y = -cur_y + touch_y;
scrolled_x += scroll_x;
scrolled_y += scroll_y;
if (scrolled_x > (ready_image.getWidth() - screen_width)/2
|| scrolled_x < -(ready_image.getWidth() - screen_width)/2){
scrolled_x -= scroll_x;
scroll_x = 0;
}
if (scrolled_y > (ready_image.getHeight() - screen_width)/2
|| scrolled_y < -(ready_image.getHeight() - screen_width)/2){
scrolled_y -= scroll_y;
scroll_y = 0;
}
v.scrollBy((int) (scroll_x),
(int) (scroll_y));
touch_x = cur_x;
touch_y = cur_y;
break;
}
return true;
}
});
//Set up buttons
Button btn = (Button)findViewById(R.id.save);
btn.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
ImageView img = (ImageView)findViewById(R.id.photo_holder);
int scroll_x = img.getScrollX();
int scroll_y = img.getScrollY();
int left = (ready_image.getWidth() - screen_width)/2
+ scroll_x;
int top = (ready_image.getHeight() - screen_width)/2
+ scroll_y;
int right = left + screen_width;
int bottom = top + screen_width;
Rect r = new Rect(left, top, right, bottom);
Bitmap croped_image = ImageUtilities.cropImage(ready_image,
r,
screen_width,
screen_width);
String path_to_folder = Environment.getExternalStorageDirectory()
.getAbsolutePath();
String pic_path = path_to_folder + File.separator + MainActivity.app_name;
File f = new File(pic_path);
File picture = null;
try {
picture = File.createTempFile("photo_", ".jpg", f);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
FileOutputStream fos = new FileOutputStream(picture);
croped_image.compress(Bitmap.CompressFormat.JPEG, 100, fos);
fos.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (requestWindowFeature(Window.FEATURE_NO_TITLE))
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.activity_editor);
setUp();
}
public void onClick(View v) {
// TODO Auto-generated method stub
}
}
bmp is recycled in setUp() method.
ImageUtility is
package com.example.photobooth;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
public class ImageUtilities {
public static Bitmap getRoundedCornerBitmap(Context context, Bitmap input,
int pixels, int w, int h, boolean squareTL, boolean squareTR,
boolean squareBL, boolean squareBR, boolean border) {
Bitmap output = Bitmap.createBitmap(w, h, Config.ARGB_8888);
Canvas canvas = new Canvas(output);
final float densityMultiplier = context.getResources()
.getDisplayMetrics().density;
final int color = 0xff424242;
final Paint paint = new Paint();
final Rect rect = new Rect(0, 0, w, h);
final RectF rectF = new RectF(rect);
// make sure that our rounded corner is scaled appropriately
final float roundPx = pixels * densityMultiplier;
paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(color);
canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
// draw rectangles over the corners we want to be square
if (squareTL) {
canvas.drawRect(0, 0, w / 2, h / 2, paint);
}
if (squareTR) {
canvas.drawRect(w / 2, 0, w, h / 2, paint);
}
if (squareBL) {
canvas.drawRect(0, h / 2, w / 2, h, paint);
}
if (squareBR) {
canvas.drawRect(w / 2, h / 2, w, h, paint);
}
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
canvas.drawBitmap(input, 0, 0, paint);
if (border) {
paint.setStyle(Paint.Style.STROKE);
paint.setColor(Color.WHITE);
paint.setStrokeWidth(3);
canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
}
return output;
}
public static Bitmap cropImage(Bitmap origina_bmp, Rect rec, int w, int h) {
Bitmap target_bitmap = Bitmap.createBitmap(w, h,
Bitmap.Config.ARGB_8888);
target_bitmap.setDensity(origina_bmp.getDensity());
Canvas canvas = new Canvas(target_bitmap);
canvas.drawBitmap(origina_bmp, new Rect(rec.left, rec.top, rec.right,
rec.bottom), new Rect(0, 0, w, h), null);
return target_bitmap;
}
public static Bitmap makeSquareImage(Bitmap original_image, int size){
int min_side = Math.min(original_image.getWidth(),
original_image.getHeight());
int side_size = ImageUtilities.get2del(min_side);
int crop_to;
Bitmap croped_image = null;
if (min_side == original_image.getWidth()){
crop_to = (original_image.getHeight() - side_size) / 2;
croped_image = ImageUtilities.cropImage(original_image, new Rect(
0, crop_to, original_image.getWidth(),
original_image.getHeight() - crop_to), size, size);
}else{
crop_to = (original_image.getWidth() - side_size) / 2;
croped_image = ImageUtilities.cropImage(original_image, new Rect(
crop_to, 0, original_image.getWidth() - crop_to,
original_image.getHeight()), size, size);
}
return croped_image;
}
public static int get2del(int num) {
while (num % 2 != 0)
num++;
return num;
}
public static Bitmap scaleImage(Bitmap originalBMP, float[] scaleFactor) {
Matrix scaleMat = new Matrix();
scaleMat.postScale(scaleFactor[0], scaleFactor[1]);
Bitmap scaledImage = Bitmap.createBitmap(originalBMP, 0, 0,
originalBMP.getWidth(), originalBMP.getHeight(), scaleMat,
false);
return scaledImage;
}
}
so it doesn't.
If i write bmp = null instead of bmp.recycle() everything is ok but i wonder why in the second chance application is crashed.
What is ImageUtilities? Maybe scaleImage may reuse the same image.
Does your program work correctly if you do:
bmp = null;
instead of
bmp.recycle();
?
The official documentation of recycle says:
"This is an advanced call, and normally need not be called, since the normal GC process will free up this memory when there are no more references to this bitmap. "
So using "bmp = null" should be better than "bmp.recycle()".
Im trying to make a Java screensaver of a 3D rotating Lorenz Attractor
Im using java and jogl (OPENGL) to render the graphics...
i have 2 classes one is the main program setup OPENGL etc...
and another that just stores a LinkedList of Point3d's That are the vertex of the line..
Only one new point is added to the List every frame render.....
The problem i am having is render speed is very slow, my question is this...
1. Is there a Better / Easy way of buffering either the screen or the line strip so i only need to draw the last line....
2. Can VBO's be used for LINE_STRIP's and if i have to add one vertex to the buffer every step is this really going to speed things up...?
Its really quite annoying... glBegin()/ glEnd() works fine up to about 100 lines then crashes badly.
Help much needed to speed up render and would be greatly apreaciated.....
Ive added the working code below to get it to work you have to link to JOGL opengl lib's
CODE
LorenzSim.java
import javax.media.opengl.GL;
import javax.media.opengl.GL2;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.GLProfile;
import javax.media.opengl.awt.GLCanvas;
import javax.media.opengl.fixedfunc.GLMatrixFunc;
import javax.media.opengl.glu.GLU;
import java.io.File;
import java.io.IOException;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;
import javax.vecmath.Point3d;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.*;
import com.jogamp.opengl.util.FPSAnimator;
import com.jogamp.opengl.util.gl2.GLUT;
import java.util.*;
import java.awt.event.*;
import sun.misc.*;
public class LorenzSim implements GLEventListener, KeyListener {
private static final int MIN_X = -20;
private static final int MAX_X = 20;
private static final int MIN_Y = -20;
private static final int MAX_Y = 20;
private static final double MIN_Z = 0;
private static final double MAX_Z = 40;
/**
* #param args
*/
// GLOBAL PARTS
boolean started = false;
int index = 0; // ANIMATOR COUNTER
String consoleLine = "";
// GENERAL OPEN GL
GLProfile glp = null;
GLCapabilities caps = null;
GLCanvas canvas = null;
GraphicsEnvironment ge = null;
GraphicsDevice gd = null;
Frame frame = null;
// GL _ CAM
double camX = 30;
double camY = 30;
double camZ = 50;
Lorenz myLorenz = null;
public LorenzSim ()
{
// GENERAL OPEN GL AND AWT SETUP
glp = GLProfile.getDefault();
caps = new GLCapabilities(glp);
canvas = new GLCanvas(caps);
ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
gd = ge.getDefaultScreenDevice();
frame = new Frame("QuadSim");
frame.setSize(600,600);
//frame.setUndecorated(true);
//gd.setFullScreenWindow(frame);
frame.setVisible(true);
canvas.setSize(frame.getWidth(),frame.getHeight());
frame.add(canvas);
// SETUP EVENT LISTENERS
canvas.addGLEventListener(this);
canvas.addKeyListener(this);
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
frame.dispose();
System.exit(0);
}
});
started = true;
FPSAnimator animator = new FPSAnimator(canvas, 60);
animator.add(canvas);
animator.start();
caps.setDoubleBuffered(true);
myLorenz = new Lorenz();
myLorenz.doSteps(0);
}
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println("Welcome to Quad Simulator v0.1 - by Phil Poore");
LorenzSim mySim = new LorenzSim();
}
//############################################
// GL EVENT INTERFACE
//############################################
#Override
public void display(GLAutoDrawable drawable) {
// TODO Auto-generated method stub
if (started)
{
update();
render(drawable);
//System.out.println("Drisplay_index:"+index);
}
}
private void update() {
// TODO Auto-generated method stub
index++;
myLorenz.step();
}
private void render(GLAutoDrawable drawable) {
// TODO Auto-generated method stub
GL2 gl = drawable.getGL().getGL2();
GLU glu = new GLU();
drawable.swapBuffers();
gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
// START OF RENDER CYCLE
setCamera(gl,glu);
drawAxis(gl);
drawBox(gl);
drawLorenz(gl);
drawHUD(gl);
}
private void drawLorenz(GL2 gl) {
// TODO Auto-generated method stub
gl.glBegin(GL.GL_LINE_STRIP);
gl.glColor3f(1.0f, 0.0f, 0.0f);
gl.glLineWidth(0.1f);
for (int i = 0; i < myLorenz.myPoints.size() - 1; i++)
{
//float dx = (float) (myLorenz.myPoints.get(i).x - myLorenz.myPoints.get(i+1).x);
//float dy = (float) (myLorenz.myPoints.get(i).y - myLorenz.myPoints.get(i+1).y);
//float dz = (float) (myLorenz.myPoints.get(i).z - myLorenz.myPoints.get(i+1).z);
//float dc = (Math.abs(dx) + Math.abs(dy) + Math.abs(dz))/3.0f;
//gl.glColor3d(dc,dc,dc);
gl.glVertex3d(
myLorenz.myPoints.get(i).x,
myLorenz.myPoints.get(i).y,
myLorenz.myPoints.get(i).z);
}
gl.glEnd();
}
private void drawBox(GL2 gl) {
// TODO Auto-generated method stub
Point3d a = new Point3d(MIN_X,MIN_Y,MIN_Z);
Point3d b = new Point3d(MAX_X,MIN_Y,MIN_Z);
Point3d c = new Point3d(MAX_X,MAX_Y,MIN_Z);
Point3d d = new Point3d(MIN_X,MAX_Y,MIN_Z);
Point3d aa = new Point3d(MIN_X,MIN_Y,MAX_Z);
Point3d ab = new Point3d(MAX_X,MIN_Y,MAX_Z);
Point3d ac = new Point3d(MAX_X,MAX_Y,MAX_Z);
Point3d ad = new Point3d(MIN_X,MAX_Y,MAX_Z);
gl.glBegin(GL.GL_LINE_STRIP);
gl.glVertex3d(a.x, a.y, a.z);
gl.glVertex3d(b.x, b.y, b.z);
gl.glVertex3d(c.x, c.y, c.z);
gl.glVertex3d(d.x, d.y, d.z);
gl.glVertex3d(a.x, a.y, a.z);
gl.glEnd();
gl.glBegin(GL.GL_LINE_STRIP);
gl.glVertex3d(aa.x, aa.y, aa.z);
gl.glVertex3d(ab.x, ab.y, ab.z);
gl.glVertex3d(ac.x, ac.y, ac.z);
gl.glVertex3d(ad.x, ad.y, ad.z);
gl.glVertex3d(aa.x, aa.y, aa.z);
gl.glEnd();
gl.glBegin(GL.GL_LINES);
gl.glVertex3d(a.x, a.y, a.z);
gl.glVertex3d(aa.x, aa.y, aa.z);
gl.glVertex3d(b.x, b.y, b.z);
gl.glVertex3d(ab.x, ab.y, ab.z);
gl.glVertex3d(c.x, c.y, c.z);
gl.glVertex3d(ac.x, ac.y, ac.z);
gl.glVertex3d(d.x, d.y, d.z);
gl.glVertex3d(ad.x, ad.y, ad.z);
gl.glEnd();
}
private void drawHUD(GL2 gl) {
// TODO Auto-generated method stub
gl.glRasterPos2d(10,10);
gl.glWindowPos2d(10, 10);
gl.glColor3d(0.8, 0.8, 0.8);
GLUT glut = new GLUT();
//DecimalFormat df = new DecimalFormat("#.##");
glut.glutBitmapString(GLUT.BITMAP_8_BY_13,
":");
}
#Override
public void dispose(GLAutoDrawable arg0) {
// TODO Auto-generated method stub
}
#Override
public void init(GLAutoDrawable drawable) {
// TODO Auto-generated method stub
GL2 gl = drawable.getGL().getGL2();
//gl.glOrtho(0,100,-5,25,0,100);
gl.glEnable( GL.GL_LINE_SMOOTH );
gl.glHint( GL.GL_LINE_SMOOTH_HINT, GL.GL_NICEST );
}
#Override
public void reshape(GLAutoDrawable arg0, int arg1, int arg2, int arg3,
int arg4) {
// TODO Auto-generated method stub
}
private void drawAxis(GL2 gl) {
gl.glLineWidth((float) 1.0);
gl.glBegin(GL.GL_LINES);
// X
gl.glColor3f(1, 0, 0);
gl.glVertex3d(0,0,0);
gl.glVertex3d(1,0,0);
// Y
gl.glColor3f(0, 1, 0);
gl.glVertex3d(0,0,0);
gl.glVertex3d(0,1,0);
// Z
gl.glColor3f(0, 0, 1);
gl.glVertex3d(0,0,0);
gl.glVertex3d(0,0,1);
gl.glEnd();
}
private void setCamera(GL2 gl,GLU glu)
{
gl.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
gl.glLoadIdentity();
glu.gluPerspective(120, 1.0, 5, 100);
gl.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
gl.glLoadIdentity();
glu.gluLookAt(camX, camY, camZ,
0.0,0.0 ,0.0 ,
0.0,0.0, 1.0);
gl.glRotated(0.0+index, 0, 0, 1);
// gl.glTranslated(MAX_X-MIN_X, MAX_Y-MIN_Y, MAX_Z-MIN_Z);
}
//############################################
// KEY LISTENER INTERFACE
//############################################
#Override
public void keyPressed(KeyEvent e) {
// TODO Auto-generated method stub
if (e.getKeyCode() == 27)
System.exit(0);
}
#Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
}
#Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
}
Lorenz.java
import javax.vecmath.*;
import java.awt.geom.;
import java.util.;
public class Lorenz {
public static final double rho = 28.0;
public static final double sigma = 10.0;
public static final double beta = 8.0/3.0;
private static final double step = 200.0;
public LinkedList<Point3d> myPoints = null;
public Lorenz ()
{
myPoints = new LinkedList<Point3d>();
Point3d first = new Point3d(0.1,0.1,0.1);
myPoints.add(first);
}
public void step()
{
System.out.println("stepping..."+myPoints.size());
Point3d last = myPoints.get(myPoints.size()-1);
double dx = (sigma * (last.y - last.x))/step;
double dy = ((last.x*(rho-last.z))-last.y)/step;
double dz = ((last.x*last.y - beta*last.z))/step;
Point3d next = new Point3d(last.x+dx,last.y+dy,last.z+dz);
myPoints.add(next);
}
public void doSteps(int count)
{
for (int i = 0; i < count; i++)
{
step();
}
}
public void dump()
{
System.out.println(myPoints.toString());
}
}
Phil
Try creating multiple VBOs for your set of lines. That way you only have to update a smaller number of vertices for each new line and the bulk of your geometry is already (probably) in video memory.
this may sound funny but try to remove the System.out.println() in the step() method. Printing to console is fairly slow/unpredictable in java so don't do this every frame.
to answer your question:
2) VBOs are fast for large(er) datasets and best used with rarely or partly updating data. They can represent any primitive you like, triangles, line strips etc. Adding one vertex every frame is not a good idea since they are allocated statically. You can still use them by predicting the maximum amount of vertices you would like to render and simply allocate this buffer a-priory.
if you decide to use VBOs you will have to make this changes:
- allocate a VBO which will determine the max amount of vertices of the graph
- upload only the new vertices per frame
- stop at max or think about a ringbuffer, but you will probably need an additional buffer used as indexbuffer to implement this
tipp: use JOGL's debug pipeline, it will try to throw an exception as soon as OpenGL sets an error code. This will may help to fix the crash issue you mentioned.
http://michael-bien.com/mbien/entry/jogl_2_composeable_pipline