i have multiple objects on my canvas. and after some condition, i want some of my sprite do animate. here my code:
private AnimatedSprite[] sign;
sign = new AnimatedSprite[9];
// some loop code to create 9 sign
..
sign[index] = new AnimatedSprite(x, y, myregion);
..
until this part is ok, all signs is on position. but when i want to animate some sprite, all of that sprite will do animate too. here the code:
while(signIndex<9)
{
if(signIndex==winSlot[0] || signIndex==winSlot[1] || signIndex==winSlot[2])
{
grupSign= null;
grupSign= sign[signIndex];
grupSign.animate(200, true);
}
signIndex++;
}
anyone know and can help me how to make only specific sprites do animate?
As per my suggestion you have to use deepCopy() method while you create your animated sprite object. As per the following
sign[index] = new AnimatedSprite(x, y, myregion.deepCopy());
Advantage of using deepCopy() method is that each time new region will created for your sprite.
Related
i am new to unity and need some help regarding creating a background that will look something like this (A bit jittery because its a gif), i want it to be like fill every screen size and have size 1/8th of the screen (the black box):
You can use the following setup:
First the image should have borders like this one and set its Wrap mode to reapeat in the import settings
Your background should be a ScreenSpace Overlay Canvas (depends on your setup ofcourse)
Within that Canvas have a RawImage object, use your image as Texture and add this component to it
[RequireComponent(typeof(RawImage))]
public class BackgroundController : MonoBehaviour
{
[Header("References")]
[SerializeField] private RectTransform _rectTransform;
[SerializeField] private RectTransform _parentRectTransform;
[SerializeField] private RawImage _image;
[Header("Settings")]
[SerializeField] private Vector2 repeatCount;
[SerializeField] private Vector2 scroll;
[SerializeField] private Vector2 offset;
private void Awake()
{
if (!_image) _image = GetComponent<RawImage>();
_image.uvRect = new Rect(offset, repeatCount);
}
// Start is called before the first frame update
private void Start()
{
if (!_rectTransform) _rectTransform = GetComponent<RectTransform>();
if (!_parentRectTransform) _parentRectTransform = GetComponentInParent<RectTransform>();
SetScale();
}
// Update is called once per frame
private void Update()
{
#if UNITY_EDITOR
// Only done in the Unity editor since later it is unlikely that your screensize changes
SetScale();
#endif
offset += scroll * Time.deltaTime;
_image.uvRect = new Rect(offset, repeatCount);
}
private void SetScale()
{
// get the diagonal size of the screen since the parent is the Canvas with
// ScreenSpace overlay it is always fiting the screensize
var parentCorners = new Vector3[4];
_parentRectTransform.GetLocalCorners(parentCorners);
var diagonal = Vector3.Distance(parentCorners[0], parentCorners[2]);
// set width and height to at least the diagonal
_rectTransform.sizeDelta = new Vector2(diagonal, diagonal);
}
}
This first scales the RawImage to fit the diagonal size of the parent. Since it is already fitting the screen this gets us the screen sizes => always fills the entire screen, no matter what the scales or rotation are (as long as your RawImage is on the center of the screen ofcourse).
Using the repeatCount you define how often the texture should be on the background.
Then using the scroll you can define how fast and in which direction the background should scroll. The script basically simply updates the RawImage.uvRect every frame.
Finally you simply rotate the RawImage so the scroll goes in the final direction you want
So you want some kind of infinity scrolling background?
Here is some simple way to create it.
1) You will need tilable image (that can be connected one side to other seamlessly). You can use one frame from your gif. Add it to your assets (just drag and drop it there).
2) In your Unity scene create new Quad object (GameObject->3d Object->Quad)
3) Drag and drop your image from your assets window right onto your Quad. That will apply texture to it.
4) Create simple script on your Quad object. I called mine RollerScript
using System.Collections;
using UnityEngine;
public class RollerScript : MonoBehaviour
{
public float speed = 2f;
public MeshRenderer renderer;
void Update()
{
Vector2 offset = new Vector2(Time.time * speed, Time.time * speed);
renderer.material.mainTextureOffset = offset;
}
}
5) Go back to Editor and assign renderer field (drag your Quad object from Hierarchy to that field)
6) Hit Play and adjust speed parameter in your script editor window. Your texture will scroll diagonally to right-top (as on your gif). If you want another direction you can change this line:
Vector2 offset = new Vector2(Time.time * speed, Time.time * speed);
Set x or y value of Vector2 to zero if you want NO scrolling horizontaly/vertically. Change x or y value to -x or -y if you want to scroll in opposite direction.
I am using MPAndroidChart and I have a requirement that i have to sync the dragging and zooming of two graphs, like if i zoom out, zoom in or drag one any of one graph then other graph should be zoomed out, zoomed in or dragged to same extent on X-axis.
Example: If i drag the upper graph to 12th point on X-axis then lower graph should also be dragged to 12th point on X-axis automatically.
Guys i need need some idea how to do this, i am enough familiar with mpchartandroid library.
I wrote a function to do this, i am calling this function of Drag and scale listener. Working perfectly.
private void syncCharts(Chart mainChart, LineChart[] otherCharts) {
Matrix mainMatrix;
float[] mainVals = new float[9];
Matrix otherMatrix;
float[] otherVals = new float[9];
mainMatrix = mainChart.getViewPortHandler().getMatrixTouch();
mainMatrix.getValues(mainVals);
for (LineChart tempChart : otherCharts) {
otherMatrix = tempChart.getViewPortHandler().getMatrixTouch();
otherMatrix.getValues(otherVals);
otherVals[Matrix.MSCALE_X] = mainVals[Matrix.MSCALE_X];
otherVals[Matrix.MTRANS_X] = mainVals[Matrix.MTRANS_X];
otherVals[Matrix.MSKEW_X] = mainVals[Matrix.MSKEW_X];
otherMatrix.setValues(otherVals);
tempChart.getViewPortHandler().refresh(otherMatrix, tempChart, true);
}
}
Use the OnChartGestureListener.
https://github.com/PhilJay/MPAndroidChart/wiki/Interaction-with-the-Chart
I am creating an app using AndEngine for the first time. My app is animation-oriented i.e. it has a number of images which on click animate. Most of these animations are frame by frame animations. I am using AndEngine because I require some animations with particle system, gravity and other stuff. Can someone help me with a simple onclick animation code in AndEngine or maybe point me to some good tutorial since all AndEngine tutorials are game tutorials that do not have frame by frame animation. Any help would be appreciated.
Before starting: note that this answer is using the TexturePacker extension for AndEngine.
For my frame by frame animations I am using a program called Texture Packer, which is supported by AndEngine. You actually just drag all your images to there, and it exports 3 files you need to use inside your project. The file are: .xml , .java , .png
By doing that i'm creating a big bitmap (try to stay below or equal to 2048x2048) with all the frames inside of it.
After assuming you have those files created, you need to copy them to your project. the .png and .xml go into the same directory, most likely under assets/gfx/ ... and the .java file should be located in the src directory with the rest of your classes.
Now lets check out some code..
First of all we will need to load all the textures from the files.. we will do that using the following code:
Those are the variables we will use to create our animatable object.
private TexturePack dustTexturePack;
private TexturePackTextureRegionLibrary dustTexturePackLibrary;
public TiledTextureRegion dust;
The following code actually loads the single textures from the bitmap into our variable
try {
dustTexturePack = new TexturePackLoader(activity.getTextureManager(),"gfx/Animations/Dust Animation/").loadFromAsset(activity.getAssets(),"dust_anim.xml");
dustTexturePack.loadTexture();
dustTexturePackLibrary = dustTexturePack.getTexturePackTextureRegionLibrary();
} catch (TexturePackParseException e) {
Debug.e(e);
}
TexturePackerTextureRegion[] obj = new TexturePackerTextureRegion[dustTexturePackLibrary.getIDMapping().size()];
for (int i = 0; i < dustTexturePackLibrary.getIDMapping().size(); i++) {
obj[i] = dustTexturePackLibrary.get(i);
}
dust = new TiledTextureRegion(dustTexturePack.getTexture(), obj);
As you can see, we are using the TiledTextureRegion object. what we've done until now is actually loading the textures, and giving our TiledTextureRegion object all the info needed about the regions of the smaller images located in our big bitmap.
Later on, to use this in any part of our game, we can do the following: (notice that my "dust" variable is located inside a ResourceManager class, and therefore its public - this info is given for the next code)
AnimatedSprite dustAnimTiledSprite = new AnimatedSprite(500, 125, resourcesManager.dust, vbom);
myScene.attachChild(dustAnimTiledSprite);
At last, to animated the object in a specific given time, we just use the simple method animate, just like this :
dustAnimTiledSprite.animate(40, 0);
(In this case, the duration of each frame is 40, and there is 0 loops - will be animated once)
** Not too sure what's the difference between AnimatedSprite to TiledSprite. but this is how I show simple animations in my game.
I hope this is what you were looking for. good luck
This is sprite sheet with 8 frames
Player.sprite.animate(
new long[] { 100, 100 }, 7, 8,
false, new IAnimationListener() {
public void onAnimationStarted(
AnimatedSprite pAnimatedSprite,
int pInitialLoopCount) {
}
public void onAnimationLoopFinished(
AnimatedSprite pAnimatedSprite,
int pRemainingLoopCount,
int pInitialLoopCount) {
}
public void onAnimationFrameChanged(
AnimatedSprite pAnimatedSprite,
int pOldFrameIndex,
int pNewFrameIndex) {
}
public void onAnimationFinished(
AnimatedSprite pAnimatedSprite) {
Player.sprite.animate(
new long[] { 100,
100, 100,
100, 100,
100, 100 },
0, 6, true);
}
});
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 !
I have been trying to use a MouseJoint to move a piece wherever the user touches. But the piece, being affected by the joint, behaves strangely, never reaching the point. This is the code (x and y are already converted to 'physical' units):
MouseJointDef mj_def;
MouseJoint mj = null;
Body mj_gbody;
public void move(float x, float y)
{
if(mj == null)
{
BodyDef mgbd = new BodyDef();
mj_gbody = wrld.createBody(mgbd);
//
mj_def = new MouseJointDef();
mj_def.bodyA = mj_gbody;
mj_def.bodyB = body;
mj_def.collideConnected = true;
mj_def.maxForce = 20.0f * body.getMass();
//mj_def.target.set(x,y);
mj = (MouseJoint)wrld.createJoint(mj_def);
body.setAwake(true);
}
mj.setTarget(new Vector2(x, y));
}
I was looking for some way to establish the anchor point in the BodyB, as the 'strange behaviour' that I mentioned seems to make the body gravitate around the established point (an orbit twice the width of the object), as if the anchor point was outside of the body (hexagon shaped, btw). But I don't see any way of doing so in libgdx.
Does anybody know what I am doing wrong? Thank you in advance!
Well, MouseJoint was working properly, I just misunderstood how MouseJoint works.
As it is clearly seen in the Box2d testbed, MouseJoint is used for dragging after selecting an object. Therefore, the anchor is assigned in the first target.set.
As I wanted to move the center of the object to the place where the mouse was (or the user touched), a mj_def.target.set(body.getPosition().x + 2.0f, body.getPosition().y + 1.0f); (the object is 4.0f by 2.0f) in the initialization solved the problem. Also, it may be not the best Joint for my intentions (to move an specific object to one place in the screen).