LibGDX animation is flickering when flipped - animation

Hi I have an animation in my LibGDX game that flickers when flipped.
So it switches really fast (like every frame) from flipped and not flipped and i know that the flip variable is not changing. Here's the code:
#Override
public void render(SpriteBatch sb, float a) {
updateDrawVariables(a);
if (isWalking) {
walkStateTime += Gdx.graphics.getDeltaTime();
}
TextureRegion frame = walk.getKeyFrame(walkStateTime, true);
if (flip) {
frame.flip(true, false);
}
sb.draw(frame, drawX, drawY, drawWidth, drawHeight);
if (Main.DEBUG)Resources.font.draw(sb, "HP: " + health, drawX, drawY);
}
Any answers is appreciated!

frame.flip(true, false);
This will always flip the texture region from it's current state. So it will be flipped one frame, not flipped the next and then flipped again.
You want something like
frame.flip(!frame.isFlipX(), frame.isFlipY());

Related

How to keep image original in QgraphicsView in QT

I have load an image in QGraphicsView, but consider of the size of QGraphicsView scene, I need to scale the image first, then add the scaled image to scene.
e.g. The image original size is 1536*1024, the QGraphicsView size is 500*400, firstly I scale the image like this:
image2D = image2D.scaled( h * P , h, Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation);
myScene->setSceneRect((h * P-w)/2, 0, h * P , h);
pixmapItem = new QGraphicsPixmapItem(image2D);
myScene->addItem(pixmapItem);
myView->setScene(myScene);
And now a problem comes to me, when wheelEvent happends and the QGraphicsView zoom in, the scaled image becomes indistinct while I want it to keep as clear as the original one.
I find a way that I can hold an original copy of image, then when wheelEvent happend just scale the original copy and put it to scene.
But I don't know how to write this code, thanks for help~
or are there any simple methods?
class interactiveView : public QGraphicsView
{
protected:
void wheelEvent(QWheelEvent *event) override;
}
void interactiveView::wheelEvent(QWheelEvent *event)
{
int scrollAmount = event->delta();
xPos = event->pos().x();
yPos = event->pos().y();
scrollAmount > 0 ? zoomIn() : zoomOut();
}
Update:
I find a simple way like this:
just use QGraphicsView::fitInView() to make sure that the image scale is equal to QGraphicsView, and do not need to scale image first.
Therefore the image won't be indistinct when zoom in, and I only need to recall the QGraphicsView::fitInView() to reset to original view instead of using QGraphicsView::resetMatrix()
void myImageWindow::loadImag(int w, int h)
{
pixmapItem->setPixmap(image2D);
//if the scale of image changed
if(image2D.height() != imgHeight_pre){
myView->fitInView(pixmapItem, Qt::KeepAspectRatioByExpanding);
imgHeight_pre = image2D.height();
}
//if the scene of QGraphicsView changed
if(h != sceneHeight_pre){
myView->fitInView(pixmapItem, Qt::KeepAspectRatioByExpanding);
sceneHeight_pre = h;
}
}
void myImageWindow::on_rstImgBtn_clicked()
{
myView->fitInView(pixmapItem, Qt::KeepAspectRatioByExpanding);
}
Scaled image:
becomes indistinct when zoom in:
You can use this method resetMatrix() to reset image
For example:
graphicsView->scale(2, 2);
graphicsView->resetMatrix();
graphicsView->scale(1, 1);

Enemies always clumping together in unity 2d

I'm trying to make a top-down shooter game in unity 2d. But the enemies are always clumping together. Does someone knows how to avoid it?
Here's my enemy code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Enemy : MonoBehaviour
{
public float moveSpeed;
public float stoppingDistance;
public Transform player;
private Rigidbody2D rb;
public GameObject effect;
public int health = 3;
public static int enemyCounter;
public SpriteRenderer enemy;
public Color hurtColor;
void Start() {
rb = GetComponent<Rigidbody2D>();
player = GameObject.FindGameObjectWithTag("Player").transform;
}
void Update() {
enemyCounter = EnemySpawner.enemyCounter;
Vector2 direction = transform.position - player.position;
if (Vector2.Distance(transform.position, player.position) > stoppingDistance) {
transform.position = Vector2.MoveTowards(transform.position, player.position,
moveSpeed * Time.deltaTime);
}
else if (Vector2.Distance(transform.position, player.position) > stoppingDistance) {
transform.position = this.transform.position;
}
}
IEnumerator Flash(){
enemy.color = hurtColor;
yield return new WaitForSeconds(0.01f);
enemy.color = Color.red;
}
void OnCollisionEnter2D(Collision2D other) {
if (other.gameObject.tag == "Bullet") {
StartCoroutine(Flash());
health -= 1;
}
if (health <= 0) {
GameObject DestroyEnemy = Instantiate(effect, transform.position, Quaternion.identity);
Destroy(this.gameObject);
Destroy(DestroyEnemy, 2f);
}
}
}
The enemies is moving towards the player, but they clump together when I move the player. I really need help.
If the enemies are moving in straight line to the player they will always clump up. If you want to ensure a minimal distance between enemies you could consider using a second larger collider on another layer but this will might end up looking bad and could make some exploits possible if too big.
The other alternative would be to change the behaviour of the enemies. Making an enemy move depending on the position of the other enemies seems complicated therefore i would simply try to add some randomness to their behaviour. Here are some ideas you could try:
-(would be my first try) switch randomly between two behaviours, 1: move straight to the player (always if very close to player), 2: move in a random direction (sometimes when further away from the player)
-don't give all your enemies the same speed
-make them move towards the player + a small random angle away from the player if far away
-...
To sum it up you will need an improved behaviour and there isn't a single solution.

Stop rotating for a click right on the game object

I have a unity game and in it, a rotating game object, which increases its speed when it is clicked.
My problem is that the game does not work as I want it to. Right now, if I click any part of the screen, it increases the game object's speed of rotation. On the other hand, if I keep my finger on the screen, the game object starts to slow down and then starts rotating in the opposite direction.
I want the rotation of the object to increase when I click on it, not just if I click on any part of the screen. Furthermore, I don't know why holding down reverses the direction of rotation.
var speed = 1;
var click = 0;
Screen.orientation = ScreenOrientation.LandscapeLeft;
function Update (){
{
transform.Rotate(0,0,speed);
}
if(Input.GetMouseButton(0))
{
if(speed != 0)
{
speed = 0;
} else {
click++;
speed = click;
}
You must use Input.GetMouseButtonUp or Input.GetMouseButtonDown, NOT A Input.GetMouseButton, this method used for clamping.
Try use this code:
var speed = 1;
var click = 0;
Screen.orientation = ScreenOrientation.LandscapeLeft;
function Update (){
{
transform.Rotate(0,0,speed);
}
if(Input.GetMouseButtonDown(0))
{
if(speed != 0)
{
speed = 0;
} else {
click++;
speed = click;
}
A few issues here:
Firstly:
To increase speed upon clicking on the object only, use raycasting from camera, and check if it hits your object. Your object needs need a collider component on it for this to work.
RaycastHit hit;
Ray ray = camera.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out hit))
{
Transform objectHit = hit.transform;
objectHit.Rotate(0,0,speed);
}
Refer to https://docs.unity3d.com/Manual/CameraRays.html -> Raycasting section, for more information.
Secondly:
Input.GetMouseButtonDown(..) // returns true at the instance your mouse button transits from up to down
Input.GetMouseButton(..) // returns true as long as your mouse button is held down
Use Input.GetMouseButtonDown(..) in your Update() method if you want to to do something when you click on it.

How to duplicate one frame of an animation?

I have a punch animation with, let's assume, 5 frames;
the second frame is the punch collision itself. I wanna be able to duplicate this keyframe and move the following frames forward.
I wanna be able to do this when there is a collision. Making the animation slower doesn't work because it would delay the whole frames.
any tips
Maybe you could pause the animation, wait for a few frames, and then resume it. Animation can be paused by setting Animator.speed to 0. Something like this:
public class PunchAnimation : MonoBehaviour {
public Animator animator;
public float delay;
IEnumerator WaitAndResume(Animator animator, float delay) {
animator.speed = 0;
yield return new WaitForSeconds(delay);
animator.speed = 1;
}
void OnCollisionEnter(Collision c) {
StartCoroutine(WaitAndResume(animator, delay));
}
}

Having FPS lags when drawing tiles in XNA

I am developing my own tile-based game in xna 4.0, and i suffer big fps lags while drawing the tiles on the screen.
I've read a lot about increasing performance and i've got to this:
I store my tiles in a simple dictionary
private Dictionary<Vector2, IBlock> WorldBlocks;
private Vector2 ExactBlockPosition;
private IBlock ExistingBlock;
public void Draw(SpriteBatch SpriteBatch, Vector2 ScreenStart, Vector2 ScreenEnd)
{
// Run over all the blocks in the screen
for (this.ExactBlockPosition.X = this.GetCurrentBlockXPosition(ScreenStart.X);
this.ExactBlockPosition.X < ScreenEnd.X;
this.ExactBlockPosition.X += Global.BLOCK_WIDTH)
{
for (this.ExactBlockPosition.Y = this.GetCurrentBlockYPosition(ScreenStart.Y);
this.ExactBlockPosition.Y < ScreenEnd.Y;
this.ExactBlockPosition.Y += Global.BLOCK_HEIGHT)
{
// Check if there is a block in the exact block location
if (this.WorldBlocks.TryGetValue(this.ExactBlockPosition, out this.ExistingBlock))
{
// Draw the block on the screen
this.ExistingBlock.Draw(SpriteBatch);
}
}
}
}
private int GetCurrentBlockXPosition(float X)
{
return (int)(X - X % Global.BLOCK_WIDTH);
}
private int GetCurrentBlockYPosition(float Y)
{
return (int)(Y - Y % Global.BLOCK_WIDTH);
}
In short, this code is drawing the blocks that are on the screen only.
But still my fps falls to 31 when there is a lot of tiles on the screen.
The tile width and heigh is 20 pixels.
Any suggestions why my fps falls?

Resources