Transformation of images in mobile apps - android

I tried to create a simple collage designer for Android. Each image can be moved, rotated, scaled. Use this code:
var os:Sprite = new Sprite();
os.cacheAsBitmap = true;
os.cacheAsBitmapMatrix = new Matrix();
Multitouch.inputMode = MultitouchInputMode.GESTURE;
if (Multitouch.supportsGestureEvents){
os.addEventListener(TransformGestureEvent.GESTURE_ROTATE , onRotate );
os.addEventListener(TransformGestureEvent.GESTURE_ZOOM , onZoom);
os.addEventListener(TransformGestureEvent.GESTURE_PAN , onPan);
}
os.addEventListener(MouseEvent.MOUSE_DOWN, onDown);
os.addEventListener(MouseEvent.MOUSE_UP, onUp);
protected function onRotate(event:TransformGestureEvent):void
{
event.target.rotation += event.rotation;
}
protected function onZoom(event:TransformGestureEvent):void
{
event.target.scaleX *= event.scaleX;
event.target.scaleY *= event.scaleY;
}
protected function onPan(event:TransformGestureEvent):void
{
event.target.x = event.offsetX;
event.target.y = event.offsetY;
}
protected function onDown(e:MouseEvent):void
{
os.startDrag();
e.stopPropagation();
}
protected function onUp(e:MouseEvent):void
{
os.stopDrag();
}
However, scaling images is not smooth, the image suddenly changes size, motion pull. Although I have quite a powerful device for testing. I can not use a standard way using markers, because the images are quite small, and tap your finger into the marker will be difficult.
Prompt code examples how this can be implemented, please.

Are you using "gpu" renderMode to test?
And try use bitmap instead

Related

Drawing 200 textures in LibGdx based Android game

When I draw more around 100-200 textures all in the same screen, the device becomes very slow and the app crashes without any exceptions. Could you please let me know any best way to have 100 textures without compromising the performance.
I am using the TextureRegion from TextureAtlas.
MainGame
public void render(SpriteBatch sb) {
// TODO Auto-generated method stub
// System.out.println("BallPoolGame Screen - render");
batch = sb;
sb.setProjectionMatrix(camera.combined);
sb.begin();
sb.draw(BACKGROUND_BALL_POOL, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
cellManager.draw(sb);
ballManager.draw(sb);
sb.end();
}
private void setGameTextures() {
gameScreenAtlas = new TextureAtlas("data/texturetutorialpack.pack");
RED_BALL = gameScreenAtlas.findRegion("redball");
// RED_BALL.getTexture().setFilter(TextureFilter.Linear, TextureFilter.Linear);
BLUE_BALL = gameScreenAtlas.findRegion("blueball");
// BLUE_BALL.getTexture().setFilter(TextureFilter.Linear, TextureFilter.Linear);
GREEN_BALL = gameScreenAtlas.findRegion("greenball");
// GREEN_BALL.getTexture().setFilter(TextureFilter.Linear, TextureFilter.Linear);
}
CellManager
public void draw(SpriteBatch sb){
batch=sb;
showImageTexture(MODEL1,207,1);
if(showSelectedCell){
if(allPossiblePathSize>0)
setupBoardCellTexture();
showImage(CELL_SELECTED, rowCoordinate[cellRow], colCoordinate[cellCol]);
}
}
private void setupBoardCellTexture(){
for(CellGrid c : masterGrid){
if(cellTextureIndicator[c.getRow()][c.getCol()]==1){
showImage(CELL_ALL_PATH_TEXTURE,c.getRowCoordinate() ,c.getColCoordinate() );
}
}
}
private void showImage(TextureRegion tr, float rowCoordinate, float colCoordinate) {
batch.draw(tr, colCoordinate,rowCoordinate);
}
BallManager
public void draw(SpriteBatch sb) {
batch = sb;
setupBoardBallTexture();
if (moveTheBall) {
updateBallPosition();
showImage(ball.getTextureRegion(), moveRow + 6, moveCol + 6);
}
squeezeBalls.draw(sb);
}
You are missing some essential data about your app to answer than question:
How big is one texture on average (Size: widthxheight)
On which device is this error occuring (some devices might have less fillrate than others)
What texture filter does the TextureAtlas use (LINEAR, NEAREST, ...)
I guess that you are trying to draw many textures event if they are out of sight. If that is the case you have to implement a check if the cell is visible to the camera.
Another guess would be that you are trying to draw too many elements with the LINEAR TextureFilter. When using linear as a texture filter the gpu needs to sample way more points then with nearest (i think it was 4 times the samples; so in theory your gpu draws 400-800 textures; depending on images size that are too much for mobile gpu fillrates)
Try to describe more circumstances then i can give probably more insight in your problem.

How to make a camera panning js script in Unity3d

I am trying to make the following camera panning js script, to work as it should, meaning panning the camera left and right. What I have accomplished till now, is to move camera only left and back to its starting position. I can't get it move left and right on a gui.button being clicked/touched.
Here is the js script:
#pragma strict
var target : GameObject;
var xpositionLeft = 10;
var xpositionRight = -10;
//var smooth : float = 5; // Don't know where should I put this var to make it pan smooth?
private static var isPanning = false;
function Update()
{
if(isPanning == true)
{
transform.position.x = target.transform.position.x;
transform.position.x = xpositionLeft;
}
else
{
transform.position.x = target.transform.position.x; // It only pan the camera left, not right!
transform.position.x = xpositionRight;
}
}
static function doPanning ()
{
isPanning = !isPanning;
}
Can someone give a clue on how to make this script work? I'm new to Unity and programming, so any help is more than welcomed.
Thank you all in advance for your time, and your answers.
There are several problems with your code. First, the lines transform.position.x = target.transform.position.x; don't have any effect, because you're immediately overwriting it in the next line. Your code basically only flips transform.position.x between -10 and 10.
Second, the behavior you expect doesn't match the logic in your code. You have only two states, isPanning true and false, but you need three states: pan left, pan right and do nothing.
// how far the camera should move witch each click
var xPositionOffset = 10;
// -1 = left, 0 = do dothing, 1 = right
var panDirection = 0;
function Update()
{
if (panDirection != 0) // pan left/right
{
transform.position.x = transform.position.x + (panDirection * xPositionOffset);
panDirection = 0;
}
}
Now you only need to set the variable panDirection to -1 or 1 if one your buttons is pressed and the camera will move farther to that side.
If you're having trouble with the vector arithmetic, have a look at the chapter 'Understanding Vector Arithmetic' from the Unity manual.
The above code will move the camera not very smooth, but it's easier to understand the basic concept this way. You can use the function Vector3.MoveTowards to get a smoother movement and the example showed in the linked reference should help you to implement it.

How to make Object follow touch movement on screen

Hey guys so I've been trying to solve this for awhile I have looked on many forums and tried to understand what they were trying to convey with the code using ActionScript 3 but i still get nothing. My main goal is to have a character on stage named "mainPlayer" now i want to set up touch events so that when the user drages his finger up down or side to side i want to the mainPlayer to follow the users path or if the user touches a point on the screen and holds his finger there the mainPlayer will be attracted to the touch and move to the point where the finger is currently at on the screen.
Ive seen lots of stuff with Phase and ID implemented but dont really understand whats going on
so far this is what i have set up:
public class realmEngine extends MovieClip
{
//MultiTouch gestures
Multitouch.inputMode = MultitouchInputMode.TOUCH_POINT;
Multitouch.inputMode = MultitouchInputMode.GESTURE;
public var mainPlayer:mcPlayer;
//PlayerControls
private var speed:Number = 8.0;
public var vx:Number = 0;
public var vy:Number = 0;
private var friction:Number = 0.85;
private var maxSpeed:Number = 15;
public function realmEngine()
{
//Add Player to Stage
mainPlayer = new mcPlayer();
stage.addChild(mainPlayer);
mainPlayer.x = (stage.stageWidth / 2) - 300;
mainPlayer.y = (stage.stageHeight / 2 );
//trace("this works");
//Setup Touch Event listeners
mainPlayer.addEventListener(TouchEvent.TOUCH_BEGIN, onTouchBegin);
stage.addEventListener(TouchEvent.TOUCH_MOVE, onTouchMove);
stage.addEventListener(TouchEvent.TOUCH_END, onTouchEnd);
//Game Loop Event Listener
stage.addEventListener(Event.ENTER_FRAME, gameLoop);
}
private function gameLoop(e:Event):void
{
mainPlayerControls();
}
private function mainPlayerControls():void
{
}
private function onTouchEnd(e:TouchEvent):void
{
}
private function onTouchMove(e:TouchEvent):void
{
}
private function onTouchBegin(e:TouchEvent):void
{
}
}
I'm not sure what to do inside the onTouch Functions in order for the object that i add to stage by Code to follow the users touch on the screen.
Can anyone lead my in the right direction or give me any advice? I woudld really appreciate it thanks guys
Yes I happen to know how to do this, I just wasn't sure if I had grasped fully what you wanted to achieve.
Note that I won't be taking into account the speed and maxSpeed variables for moving the player. It's beyond this scope and beyond the scope of the top of my head. A little bit of internet searching will get you far on that subject however!
First of all, in order to make the object follow a path drawn by the user, we need a way to store the path. For this, I suggest a Vector with Point as its datatype. It's fast and easy to work with when adding and removing elements without having to worry about its length.
We also need a way to tell wether the player sprite should move or not, in other words wether the user is pressing the finger on the screen or not.
private var _pathPoints : Vector.<Point>;
private var _isMoving : Boolean = false;
Easy-cakes. Now for the fun part!
First, we need to change the scope of the onTouchBegin event, from mainPlayer to the stage. If we don't, the user won't be able to touch an abstract point on the stage and get the player sprite to move there. Simply done with a change to
mainPlayer.addEventListener(TouchEvent.TOUCH_BEGIN, onTouchBegin);
Then we take care of when the user moves his or her finger. Nothing fancy going on here.
We're just simply storing the coordinates in our vector and storing the current state of wether the user is pressing the screen or not.
private function onTouchBegin ( e:TouchEvent ) : void
{
_pathPoints.push( new Point( e.stageX, e.stageY ) );
_isMoving = true;
}
private function onTouchMove ( e:TouchEvent ) : void
{
_pathPoints.push( new Point( e.stageX, e.stageY ) );
}
private function onTouchEnd ( e:TouchEvent ) : void
{
// Dirty but quick way of clearing the vector
_pathPoints.splice(0);
_isMoving = false;
}
Finally, for the even funnier part; the main game loop! Or "Where the Magic Happens".
private function mainPlayerControls () : void
{
// Update player position and forces
vx *= friction;
vy *= friction;
mainPlayer.x += vx;
mainPlayer.y += vy;
// Check if the player should be moving to a new point
if( _isMoving )
{
// Get a reference to the current target coordinate
var target : Point = _pathPoints[0];
// Check if the player position has reached the current target point
// We use a bounding box with dimensions equal to max speed to ensure
// that the player doesn't move across the point, move back towards it
// and start jojo-ing back and forth
if(mainPlayer.x >= target.x - maxSpeed && mainPlayer.x <= target.x + maxSpeed &&
mainPlayer.y >= target.y - maxSpeed && mainPlayer.y <= target.y)
{
// The player has reached its target
//so we remove the first element of the vector
_pathPoints.shift();
// and update the target reference
target = _pathPoints[0];
}
// Calculate velocities to the first element of the vector
vx = mainPlayer.x - target.x;
vy = mainPlayer.y - target.y;
}
}

AndEngine: Handling collisions with TMX Objects

I managed to load a tmx map now I would like to create the obstacle that the sprite can not move, I recovered the obstacle like this :
try {
final TMXLoader tmxLoader = new TMXLoader(this, this.mEngine.getTextureManager(), TextureOptions.BILINEAR_PREMULTIPLYALPHA, new ITMXTilePropertiesListener() {
#Override
public void onTMXTileWithPropertiesCreated(final TMXTiledMap pTMXTiledMap, final TMXLayer pTMXLayer, final TMXTile pTMXTile, final TMXProperties<TMXTileProperty> pTMXTileProperties) {
/* We are going to count the tiles that have the property "cactus=true" set. */
if(pTMXTileProperties.containsTMXProperty("obstacle", "true")) {
//TMXTiledMapExample.this.mCactusCount++;
//coffins[coffinPtr++] = pTMXTile.getTileRow() * 15 + pTMXTile.getTileColumn();
}
}
});
How do I handle collisions with obstacles so as to prevent the player from walking through the obstacle (i.e., like a wall)?
I believe what you're asking is how do you implement collision handling. To be clear: Collision detection is the step where you determine that something is colliding(overlapping) with something else. Collision handling is where you, say, move one of those things such that it is no longer overlapping. In this case, I'm assuming we're past the collision detection and on to collision handling because you're in a method called "onTMXTileWithPropertiesCreated," which I'm guessing means the player is on such a tile. So here's the idea, put very simply:
When, due to the movement of the player (or some other sprite) you detect that the sprite is colliding with a sprite that you would like to be impassable -- "real" in your terms, you're going to want to move the sprite back the distance that would prevent it from overlapping.
Doing this with rectangles is very simple. Doing it with other shapes gets a little more complicated. Because you're working with a TMX tile map, rectangles will probably work for now. Here's a basic example with rectangles.
public boolean adjustForObstacle(Rect obstacle) {
if (!obstacle.intersect(this.getCollisionRect())) return false;
// There's an intersection. We need to adjust now.
// Due to the way intersect() works, obstacle now represents the
// intersection rectangle.
if (obstacle.width() < obstacle.height()) {
// The intersection is smaller left/right so we'll push accordingly.
if (this.getCollisionRect().left < obstacle.left) {
// push left until clear.
this.setX(this.getX() - obstacle.width());
} else {
// push right until clear.
this.setX(this.getX() + obstacle.width());
}
} else {
if (this.getCollisionRect().top < obstacle.top) {
// push up until clear.
this.setY(this.getY() - obstacle.height());
} else {
// push down until clear.
this.setY(this.getY() + obstacle.height());
}
}
return true;
}
What this is doing is calculating the overlapping rectangle and moving the sprite along the smallest dimension of overlap by the amount that will make it no longer overlap. Since you're using AndEngine, you can make use of the collidesWith() method in IShape, which detects collisions more elegantly than the above approach.
since I use this
if(pTMXTileProperties.containsTMXProperty("obstacle", "true")) {
//TMXTiledMapExample.this.mCactusCount++;
//coffins[coffinPtr++] = pTMXTile.getTileRow() * 15 + pTMXTile.getTileColumn();
//initRacetrackBorders2();
// This is our "wall" layer. Create the boxes from it
final Rectangle rect = new Rectangle(pTMXTile.getTileX()+10, pTMXTile.getTileY(),14, 14);
final FixtureDef boxFixtureDef = PhysicsFactory.createFixtureDef(0, 0, 1f);
PhysicsFactory.createBoxBody(mPhysicsWorld, rect, BodyType.StaticBody, boxFixtureDef);
rect.setVisible(false);
mScene.attachChild(rect);
}
Have fun !

Drawing multiple times with graphics and storing to the same bitmap

I'm creating a simple drawing prototype to be used on Android where the user can drag his finger across the screen and draw basic lines/shapes etc. I'm having some performance issues when drawing over the same areas and after a while performance drops considerably.
I am wondering if there is any way to, after the line has been drawn (after a touch begin, touch move, and touch end event chain), to store the newly drawn line into a bitmap containing the rest of the drawings.
I've had a look at bitmap.merge() but this would create problems when it came to mixing colors. I simply want any new 'drawings' to be saved on top of everything drawn previously.
// To hold current 'drawing'
var clip:Shape = new Shape();
// To hold past 'drawings'
var drawing:Bitmap = new Bitmap();
public function Main()
{
Multitouch.inputMode = MultitouchInputMode.TOUCH_POINT;
addChild(drawing);
addChild (clip);
addEventListener(TouchEvent.TOUCH_BEGIN, tBegin);
addEventListener(TouchEvent.TOUCH_MOVE, tMove);
addEventListener(TouchEvent.TOUCH_END, tEnd);
}
private function tBegin(e:TouchEvent):void
{
clip.graphics.lineStyle(28,0x000000);
clip.graphics.moveTo(mouseX, mouseY);
}
private function tMove(e:TouchEvent):void
{
clip.graphics.lineTo(mouseX, mouseY);
}
private function tEnd(e:TouchEvent):void
{
// Save new graphics and merge with drawing
}
Just keep drawing in your clip shape, and on tEnd draw clip inside a bitmapData assigned to a bitmap
// To hold current 'drawing'
var bmpData:BitmapData = new BitmapData (800, 800) // put here your desired size
var clip:Shape = new Shape();
// To hold past 'drawings'
var drawing:Bitmap = new Bitmap(bmpData);
public function Main()
{
Multitouch.inputMode = MultitouchInputMode.TOUCH_POINT;
addChild(drawing);
addChild (clip);
addEventListener(TouchEvent.TOUCH_BEGIN, tBegin);
addEventListener(TouchEvent.TOUCH_MOVE, tMove);
addEventListener(TouchEvent.TOUCH_END, tEnd);
}
private function tBegin(e:TouchEvent):void
{
clip.graphics.lineStyle(28,0x000000);
clip.graphics.moveTo(mouseX, mouseY);
}
private function tMove(e:TouchEvent):void
{
clip.graphics.lineTo(mouseX, mouseY);
}
private function tEnd(e:TouchEvent):void
{
// Save new graphics and merge with drawing
bmpData.draw (clip);
clip.graphics.clear();
}

Categories

Resources