I have a bitmap of bird flying from point a straight to point b, and I want to make the movement a bit more natural, with some wiggles and small random movements that are smooth and not jittery, I'm using canvas so I can't use xml, but is there something automatic that can add some natural shakes to the bitmap while it is moving like animator?
Something like that:
My first idea was getting random points around the bitmap and moving it towards them, but that would look very robotic and not smooth, is there some calculation I can do to make the movement between points smoother?
I will also be happy to hear other ideas of creating a wiggle effect, any idea will help because I cant think of anything, nor find anything.
Here is the flying code:
public void fly(float x1,float y1,float scale){
flyTo.x=x1;
flyTo.y=y1;
this.scale=scale;
mCurrentState=BossState.Flying;
}
private void UpdateAll(){
switch (mCurrentState) {
case Flying:
if(flyTo.x==position.x&&flyTo.y==position.y){
mCurrentState=BossState.Normal;
}
else{
if(flyTo.x>position.x){
position.x+=speed;
}
else if(flyTo.x<position.x){
position.x-=speed;
}
if(flyTo.y>position.y){
position.y+=speed;
}
else if(flyTo.y<position.y){
position.y-=speed;
}
}
break;
...
}
Related
I'm using LibGDX and I want to know if it is possible to do a speech system where the text gets drawn letter by letter, or slowly, like a person speaking, instead of just appearing. Is this possible? Do I need to make a function to do it or does LibGDX or java have it built in??
Thanks,
Luke
I would recommend something similar to Sameera's comment, although a wait generally isn't a good idea for a game as it stops everything else, unless you do it in a separate thread.
Instead of waiting, perhaps use your delta times:
private float timeSinceLastLetter = 0f;
private static final float TIME_PER_LETTER = 100f;
public void render(float deltaTime) {
// do your other rendering
if(timeSinceLastLetter > TIME_PER_LETTER) {
timeSinceLastLetter = 0f;
// render your next letter here
} else {
timeSinceLastLetter += deltaTime;
}
}
There's plenty more details that need filling in, but that should give a rough idea
I'm trying to make a simple bit of code that will detect whether a model was clicked on. So far the best method I've seen is to create some sort of rectangle around the mesh and detect with Gdx.input.justTouched() to get the x,y coordinates, and then check if the rectangle contains the coordinates returned by justTouched().
I have no idea if there's a better way to do this, some kind of mesh onClick listener or something that LibGDX has in place that I'm unaware of (I've been scouring Google and the javadocs but I can't seem to find anything). I don't really need to deal with the z-axis coordinate, at least I don't think so. I only have the one PerspectiveCamera and it's not going to be moving around that much (not sure if this matters?)
Anyways, in my render() method I have:
if (Gdx.input.justTouched()) {
//this returns the correct values relative to the screen size
Vector2 pos = new Vector2(Gdx.input.getX(), Gdx.input.getY());
//I'm not sure how to get the correct rectangle to see what the
//width and height are for the model relative to the screen?
Rectangle modelBounds = new Rectangle(<<not sure what to put here>>);
if (modelBounds.contains(pos.x, pos.y) {
System.out.println("Model is being touched at: " + pos.x + ", " + pos.y);
}
}
I'm really not sure if this is the correct way to do this. I can get the position of the model with:
modelInstance.getNode("Node1").globalTransform.getTranslation(new Vector3());
but I'm not sure how to get the width and height as a rectangle relative to the screen size, if it's even possible.
I'm also unsure if this would cause massive lag, as I'm going to have about 7 nodes total that I need to detect if they're clicked on or not.
Is there a better way to do this? If not, is there a way to get the model width & height relative to the screensize (or camera, maybe)?
EDIT: Read about using Bounding Boxes, seems like what I need. Not quite sure how to implement it properly, however. I've changed my code to such:
public ModelInstance modelInstance;
public BoundingBox modelBounds;
#Override
public void create() {
...
//omitted irrelevant bits of code
modelInstance = new ModelInstance(heatExchangerModel);
modelBounds = modelInstance.calculateBoundingBox(new BoundingBox());
}
#Override
public void render() {
...
if (Gdx.input.justTouched()) {
Vector3 pos = new Vector3(Gdx.input.getX(), Gdx.input.getY(), 0);
System.out.println(pos);
if (modelBounds.contains(pos)) {
System.out.println("Touching the model");
}
}
}
I'm not really sure what the output of BoundingBox is supposed to be, or how the numbers it gives me correlates to the position in a 2d space. Hmm..
EDIT2: Think I'm getting closer.. Read about Rays and the .getPickRay method for my PerspectiveCamera. .getPickRay seems to return completely unusable numbers though, like really tiny numbers. I think I need to do something like:
if (Gdx.input.justTouched()) {
Vector3 intersection = new Vector3();
Ray pickRay = perspectiveCamera.getPickRay(Gdx.input.getX(), Gdx.input.getY());
Intersector.intersectRayBounds(pickRay, modelBounds, intersection);
}
and then intersection should give me the point where they overlap. It appears to be not working, however, giving me really small numbers like (4.8066642E-5, 2.9180354E-5, 1.0) .. hmmm..
I have a game that is almost done but I forgot about gravity and impulse, i did not want to implement box2d and i got the gravity to work, but can some body explain how to apply an impulse without box2d?
You can simulate an impulse just by adding a velocity to the objects velocity. Like that:
class GameObject {
private Vector2 velocity = new Vector2();
public void applyImpulse(Vector2 impulse) {
velocity.add(impulse);
}
public void update(float deltaTime) {
float dampingPerSecond = 0.5f;
float dampingFactor = Math.max(0f, 1 - deltaTime*dampingPerSecond);
velocity.scl(dampingFactor);
}
}
Now you might use it like this: object.applyImpulse(new Vector2(3, 2));. In case you update all your GameObjects in every frame, your object will slow down after an impulse was given. Which is what you would expect to happen, if no further impulses hit your object. Doing this in a realistic way though is difficult and might only be achieved by using box2d. You might however tweak that and hope that it will work in your game. Remember to always apply your gravity after that though.
I am trying to make a onTouchEvent to create a missile that will launch from my character sprite and forward.
I have this working using
if (missdraw = true){
canvas.drawBitmap(missile,missilex,missileY,null);
missilex = missilex + 14;
missdraw = false;
}
in my onDraw method, but the problem is it will only create one at a time.
I tried to create a class to deal with this, but this just causes an error and crashes when i try to fire.
here is what i use for the class: (this is in the ondraw in my gameview)
for (Batcher missile : missiles ){
missile.onDraw(canvas);
}
this is in the class
public Batcher(List<Batcher> temps, ScreenActivity newView, float x,
float y, Bitmap missile){
this.x = 1;
this.y = 2;
this.missile = missile;
}
public void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
canvas.drawBitmap(missile, x,y, null);
}
I would appreciate any help, but also if you could explain how it would work, instead of just code, as im quite new to programming, and really need to understand what im doing and why im doing it, rather than just copying peoples code because it works.
Cheers Phil.
Your concepts are pretty good, actually. There are a few things I don't quite understand about the code samples you posted up, I'll try to translate into what I'd do and you can tell me if I'm doing it wrong :)
in your game class you need (and it looks like you have) a list of Missiles:
LinkedList<Batcher> missiles;
In your onTouch(), however a missile is created -
missiles.add(new Batcher(missilex, missiley, missile));
you now have a collection of missiles. Note that I didn't include the list in the constructor of your batcher, because an object should never need to know that it's a part of a collection. All it needs to know is how to draw itself and where. Since I assume that all of your missiles will be added to or removed from the screen frequently, while only having a few on screen at a time, I've used a LinkedList, which is fast for adding and removing, but slow for accessing a specific missile. If you needed to access specific items in the collection and the collection didn't change very much, you would use an ArrayList instead. on to onDraw - as you have it the missile draws itself, which is fine, but I prefer to let the View do the drawing, with the missile telling it where it should be drawn -
for (Batcher missile : missiles ){
missile.setX(missile.getX() + 14); // to make it move
if (missile.getX() > canvas.gedWidth()) { //check if it's left the screen
missiles.remove(missile); // Remove it
}
else { //perform drawing
canvas.drawBitmap(missile.getBitmap(), missile.getX(), missile.getY(), null);
}
}
Hopefully that'll do it for you, but feel free to let me know if there's anything you'd like me to explain more!
Is there a way to make the mouseDragged Event be called more Often ( In my Case, Drawing a Color? I need it for Smooth Drawing, because right now, if you move too fast, it doesn't Draw All my Path. Also, I have an 2D Array Storing the Color of the Pixel, so that's also Problematic if I try to solve by problem by another Way, that's why I thought Increasing the mouseDragged Frequency would be the Best thing to Do
Thanks
If you want smooth drawing, you'd likely have to interpolate the data yourself. If you get an event at (3,3) and another at (10,10) you can figure the slope between the two, and iterate through the logical points that the mouse must have been dragged to get from (3,3) to (10,10)
I don't know of a way to force mouseDragged to update faster, and if, for instance the system was under high load, or someone used a touch screen, you might get huge jumps anyhow.
If you are drawing ovals to as color lines, change to lines:
ArrayList<> colors;
mousepressed(Event e) {
startPoint = e.getPoint();
}
mousedragged(Event e) {
colors.add(new Color(startPoint, e.getPoint);
startPoint = e.getPoint();
}
class Color() {
Color(Point start, Point end) {
// ...
}
paint(Graphics g) {
g.drawLine(start, end);
}
}