How to achieve the following effect with libGDX? - libgdx

I'm developping a game with libGDX. I have a question: Know the initial coordinates and target coordinates, as the picture shows, how to achieve the parabolic effect of the bullet ? to achieve the operation of shells . Who can teach me ? or tell me some tutorial. Tks
picture

You need to add some physics to your app (ex. Box2d). Then you 'throw' canon ball with some velocity and some direction/angle.
Physics engine do rest for you.
Here you have tutorial for box2d: https://www.youtube.com/watch?v=vXovY2KTing
Very very basic example for throw something without box2d. For your example you need to calculate right 'power' for target position.
public class SampleApp extends ApplicationAdapter
{
Sprite sprite;
Vector2 velocity = new Vector2(0, 0);
Vector2 terminateVelocity = new Vector2(2000, 2000);
Vector2 friction = new Vector2(200, 300);
Vector2 position = new Vector2(0, 0);
Vector2 launchPower = new Vector2(0, 0);
boolean shotNow;
#Override
public void render()
{
update(Gdx.graphics.getDeltaTime());
// ...
// here render your stuff
}
public void shot(float power)
{
// Calculate x launch power
launchPower.x = ((power - sprite.getX() + sprite.getWidth()*0.5f) / 2f) + velocity.x;
// We want to end our fly at ground
launchPower.y = ((0 - sprite.getY()) / 2f) + velocity.y;
// Setup start position
position.x = sprite.getX();
position.y = sprite.getY();
// Add some acc to velocity
velocity.add(launchPower);
shotNow = true;
}
public void update(float dt)
{
if (Gdx.input.justTouched()) {
shot(900);
}
// Very basic sprite movement.
// For best results you should implement more physics (acceleration etc.)
if (shotNow && position.y > 0) {
// Friction/gravity
velocity.x = MathUtils.clamp(velocity.x - friction.x * dt, -terminateVelocity.x, terminateVelocity.x);
velocity.y = MathUtils.clamp(velocity.y - friction.y * dt, -terminateVelocity.y, terminateVelocity.y);
position.add(velocity.x * dt, velocity.y * dt);
sprite.setPosition(position.x, position.y);
}
}
}

Related

libgdx: How do i get the result of an orthographic camera through another orthographic camera?

I would like to have a TV screen on my stage. I have a master scene containing the TV screen and some other things (some sprites) and the scene corresponding to what I want to render in the TV.
So I would like to render the TV scene through an OrthographicCamera and then put the result in something like a sprite which can then be rendered through the master orthographic camera, how to do that?
I know that one can use multiple camera in multiple viewports but these are directly rendered on the pixels of my computer screen.
Any advice would be much appreciated
This can be achieved by rendering the scene from the perspective of a screen camera to a FrameBuffer and then taking the TextureRegion from the FrameBuffer and rendering that to screen and then render the scene again.
For example:
In the above example the cyan rect shows what the in-scene camera sees, and this is rendered to the grey box, it is possible to move both the scene camera and the main camera independentely.
By creating and grabbing the TextureRegion from a FrameBuffer
screenFrameBuffer = new FrameBuffer(Pixmap.Format.RGBA8888, Gdx.graphics.getWidth(), Gdx.graphics.getHeight(),true);
screenTexture = new TextureRegion(screenFrameBuffer.getColorBufferTexture());
screenTexture.flip(false, true);
all render calls can be made to affect only the screenFrameBuffer by calling screenFrameBuffer.begin(), after screenFrameBuffer.end() is called the next draw call will again affect the actual screen/window.
So in in the render method you can first draw your scene to the FrameBuffer
screenFrameBuffer.begin();
renderScene(screenCamera, Color.DARK_GRAY);
screenFrameBuffer.end();
And then draw it again, followed by the "screen" as a sprite:
renderScene(sceneCamera, Color.BLACK);
batch.setProjectionMatrix(sceneCamera.combined);
batch.begin();
batch.draw(screenTexture, -sceneCamera.viewportWidth / 2.0f,-sceneCamera.viewportHeight / 2.0f,0,0,screenCamera.viewportWidth,screenCamera.viewportHeight,1.0f, 1.0f, 0.0f);
batch.end();
Complete source code for the gif above is:
package com.bornander.sandbox;
import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.graphics.*;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.graphics.glutils.FrameBuffer;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import com.badlogic.gdx.math.RandomXS128;
import com.badlogic.gdx.math.Vector2;
public class MyGdxGame implements ApplicationListener {
public static class Ball {
public Vector2 position = new Vector2();
public Vector2 velocity = new Vector2();
public float size = 1.0f;
public Color color = new Color();
public void render(ShapeRenderer shapeRenderer) {
shapeRenderer.setColor(color);
shapeRenderer.circle(position.x, position.y, size, 16);
}
public void update() {
position.x += velocity.x * Gdx.graphics.getDeltaTime();
position.y += velocity.y * Gdx.graphics.getDeltaTime();
}
}
static RandomXS128 rnd = new RandomXS128();
OrthographicCamera sceneCamera;
OrthographicCamera screenCamera;
ShapeRenderer shapeRenderer;
SpriteBatch batch;
FrameBuffer screenFrameBuffer;
TextureRegion screenTexture;
Ball[] balls;
private static float rnd(float min, float max) {
return min + rnd.nextFloat() * (max - min);
}
#Override
public void create() {
float aspectRatio = (float) Gdx.graphics.getWidth() / (float)Gdx.graphics.getHeight();
sceneCamera = new OrthographicCamera(100.0f, 100.0f / aspectRatio);
screenCamera = new OrthographicCamera(32.0f, 32.0f / aspectRatio);
batch = new SpriteBatch();
screenFrameBuffer = new FrameBuffer(Pixmap.Format.RGBA8888, Gdx.graphics.getWidth(), Gdx.graphics.getHeight(),true);
screenTexture = new TextureRegion(screenFrameBuffer.getColorBufferTexture());
screenTexture.flip(false, true);
shapeRenderer = new ShapeRenderer();
balls = new Ball[128];
for(int i = 0; i < balls.length; ++i) {
balls[i] = new Ball();
balls[i].position.set(0, 0);
balls[i].velocity.set(rnd(-4, 4), rnd(-4, 4));
balls[i].size = rnd(1, 1);
balls[i].color.set(rnd(0.5f, 1.0f), rnd(0.5f, 1.0f), rnd(0.5f, 1.0f), 1.0f);
}
}
private void renderScene(Camera camera, Color background) {
camera.update();
Gdx.gl.glViewport(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
Gdx.gl.glClearColor(background.r, background.g, background.b, background.a);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
shapeRenderer.setProjectionMatrix(camera.combined);
shapeRenderer.begin(ShapeRenderer.ShapeType.Filled);
for(int i = 0; i < balls.length; ++i) {
balls[i].render(shapeRenderer);
}
shapeRenderer.end();
}
#Override
public void render() {
float cs = 8.0f;
for(int i = 0; i < balls.length; ++i)
balls[i].update();
if (Gdx.input.isKeyPressed(Input.Keys.LEFT))
sceneCamera.position.x -= cs * Gdx.graphics.getDeltaTime();
if (Gdx.input.isKeyPressed(Input.Keys.RIGHT))
sceneCamera.position.x += cs * Gdx.graphics.getDeltaTime();
if (Gdx.input.isKeyPressed(Input.Keys.UP))
sceneCamera.position.y -= cs * Gdx.graphics.getDeltaTime();
if (Gdx.input.isKeyPressed(Input.Keys.DOWN))
sceneCamera.position.y += cs * Gdx.graphics.getDeltaTime();
if (Gdx.input.isKeyPressed(Input.Keys.A))
screenCamera.position.x -= cs * Gdx.graphics.getDeltaTime();
if (Gdx.input.isKeyPressed(Input.Keys.D))
screenCamera.position.x += cs * Gdx.graphics.getDeltaTime();
if (Gdx.input.isKeyPressed(Input.Keys.W))
screenCamera.position.y -= cs * Gdx.graphics.getDeltaTime();
if (Gdx.input.isKeyPressed(Input.Keys.S))
screenCamera.position.y += cs * Gdx.graphics.getDeltaTime();
// Render to framebuffer, clear the background to DARK_GRAY
screenFrameBuffer.begin();
renderScene(screenCamera, Color.DARK_GRAY);
screenFrameBuffer.end();
// Render to window/screen, clear backgroun to BLACK
renderScene(sceneCamera, Color.BLACK);
// Draw the framebuffer's texture as a sprite using a normal SpriteBatch
batch.setProjectionMatrix(sceneCamera.combined);
batch.begin();
batch.draw(screenTexture, -sceneCamera.viewportWidth / 2.0f,-sceneCamera.viewportHeight / 2.0f,0,0,screenCamera.viewportWidth,screenCamera.viewportHeight,1.0f, 1.0f, 0.0f);
batch.end();
// This just draws the outline of what the screen camera looks at
shapeRenderer.setProjectionMatrix(sceneCamera.combined);
shapeRenderer.begin(ShapeRenderer.ShapeType.Line);
shapeRenderer.setColor(Color.CYAN);
shapeRenderer.rect(
screenCamera.position.x - screenCamera.viewportWidth / 2.0f,
screenCamera.position.y - screenCamera.viewportHeight / 2.0f,
screenCamera.viewportWidth,
screenCamera.viewportHeight
);
shapeRenderer.end();
}
#Override
public void dispose() {
}
#Override
public void resize(int width, int height) {
}
#Override
public void pause() {
}
#Override
public void resume() {
}
}

Collision detection for an arc of a circle

So how do i implement the collision detection for an arc of a circle? Will i have to use the Box 2d collision or can i do it some other way using Rectangle or stuff like that?
BTW I hate box2d because i dont understand most of the things in it, so if there is a solution that excludes the box2d, it will be very much appreciated.
The yellow arc keeps on rotating over the black circle. How do i implement collision detection in here?
Please help ! Thanks!
To avoid using Box2D you could define the shape as a polygon and use the polygon.contains(x,y) method or use the Intersector
Below is an example using both:
import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.InputProcessor;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import com.badlogic.gdx.math.Circle;
import com.badlogic.gdx.math.Intersector;
import com.badlogic.gdx.math.Polygon;
public class Test extends ApplicationAdapter implements InputProcessor{
private ShapeRenderer sr;
private Polygon polya;
private boolean isColliding = false;
private Circle mp;
#Override
public void create () {
//define arc as polygon
// the more points used to define the shape will
// increase both required computation and collision precision
polya = new Polygon();
// create vertices
float section = 15f;
float[] newVerts = new float[200];
for(int i = 0; i < 50; i++){
newVerts[i*2] = (float)Math.sin(i/section); //x 0 to 98 even
newVerts[i*2+1] = (float)Math.cos(i/section); //y 1 to 99 odd
newVerts[199-i*2] = (float)Math.cos(i/section); //x 100 to 108
newVerts[198-i*2] = (float)Math.sin(i/section) + 0.2f; //y 101 to 199
}
polya.setVertices(newVerts);
polya.scale(50);
polya.setOrigin(1, 1);
polya.rotate(60);
//define circle to act as point for checking intersections
mp = new Circle(Gdx.graphics.getWidth()/2,Gdx.graphics.getHeight()/2,4);
// setup batchers
sr = new ShapeRenderer();
sr.setAutoShapeType(true);
Gdx.input.setInputProcessor(this);
}
#Override
public void render () {
Gdx.gl.glClearColor(0f, 0f, 0f, 0f);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
// check collision with polygon
isColliding = polya.contains(mp.x,mp.y);
//check collision using Intersector
isColliding = Intersector.isPointInPolygon(polya.getTransformedVertices(),0,polya.getVertices().length,mp.x,mp.y);
sr.begin();
sr.setColor(Color.WHITE);
if(isColliding){
sr.setColor(Color.RED);
}
sr.polygon(polya.getTransformedVertices());
sr.circle(mp.x,mp.y,mp.radius);
sr.end();
}
#Override
public void dispose () {
}
#Override
public boolean mouseMoved(int screenX, int screenY) {
int newy = Gdx.graphics.getHeight() - screenY;
polya.setPosition(screenX, newy);
return false;
}
(... removed unused input processor methods for clarity ...)
}
In my case, the arc was in motion and I needed to calculate its collision, so I updated the polygon along with the rendering. Essentially, I got the vertices in the same way that LibGDX renders an arc.
On the left you can see what the arcs I'm drawing look like. On the right you can see what the polygons would look like calculated from the shape of their corresponding arcs if I had to draw them.
Ignore the different colors and count of sections, they are randomly generated.
To achieve this result, I wrote this method:
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.math.Polygon;
import com.badlogic.gdx.math.Vector2;
import java.util.ArrayList;
// ...
public void fillPolygonWithArc(Polygon polygon, float x, float y, float radius, float start, float degrees, int segments) {
float theta = (2 * MathUtils.PI * (degrees / 360.0f)) / segments;
float cos = MathUtils.cos(theta);
float sin = MathUtils.sin(theta);
float cx = radius * MathUtils.cos(start * MathUtils.degreesToRadians);
float cy = radius * MathUtils.sin(start * MathUtils.degreesToRadians);
ArrayList<Vector2> vertices = new ArrayList<>();
vertices.add(new Vector2(x, y));
vertices.add(new Vector2(x + cx, y + cy));
for (int i = 0; i < segments; i++) {
vertices.add(new Vector2(x + cx, y + cy));
float temp = cx;
cx = cos * cx - sin * cy;
cy = sin * temp + cos * cy;
vertices.add(new Vector2(x + cx, y + cy));
}
vertices.add(new Vector2(x + cx, y + cy));
cx = 0;
cy = 0;
vertices.add(new Vector2(x + cx, y + cy));
polygon.setVertices(new float[vertices.size() * 2 + 4]);
for (int i = 0; i < vertices.size(); i++) {
polygon.setVertex(i, vertices.get(i).x, vertices.get(i).y);
}
}
// ...
How does he work?
It takes as parameters a polygon in which to write the vertices of the
arch and the parameters needed to get the shape of the arch, these are
the same parameters that you pass to the method that draws the arc (shapeRenderer.arc).
And then it calculates the vertices of the arch in the same way as
LibGDX does and fills the polygon with them.
I just looked at the LibGDX source.
Use case:
fillPolygonWithArc(polygon, getPosition().x, getPosition().y, getRadius(), start, finalStep, getSegments());
shapeRenderer.setColor(color);
shapeRenderer.begin(ShapeRenderer.ShapeType.Filled);
shapeRenderer.arc(getPosition().x, getPosition().y, getRadius(), start, finalStep, getSegments());
shapeRenderer.end();
Also, if you want, you can draw a polygon:
fillPolygonWithArc(polygon, getPosition().x, getPosition().y, getRadius(), start, finalStep, getSegments());
shapeRenderer.setColor(color);
shapeRenderer.begin(ShapeRenderer.ShapeType.Line);
shapeRenderer.polygon(polygon.getVertices());
shapeRenderer.end();
Ultimately, you can check if some point is inside the polygon you need:
polygon.contains(new Vector2(4, 20));

Actionsciprt 3 How to Accelerometer

I am about to create a 2D car racing game using accelerometer, The problem is the car position on the screen, that when the game starts, the car appears at the left side while expected to be at the center.
How can I solve it?
private var accelerometer: Accelerometer;
var accelX: Number;
public function game() {
if (Accelerometer.isSupported) {
car.addEventListener(Event.ENTER_FRAME, moveCar);
accelerometer = new Accelerometer();
accelerometer.addEventListener(AccelerometerEvent.UPDATE, AccelerometerUpdateHandler);
}
}
function AccelerometerUpdateHandler(event: AccelerometerEvent): void {
accelX = event.accelerationX;
}
function moveCar(evt: Event) {
car.x -= accelX * 30;
if (car.x > 299) {
car.x = 299;
} else if (car.x < 110) {
car.x = 110;
}
}
To centre a MovieClip to the stage at the start of app you need to get the stage width, divide this by 2 and then take away had of the car's width (unless the car is cent erred inside its MovieClip?)
car.x = (stage.stageWidth /2) - (car.width /2)

move body to specific point in world coordinates at a constant speed

I have a kinematic body with gravity 0 which I want to move from a specific point to a specific point in my world coordinates. I've tried to adjust the code from here
to the one below. But the body stays still and doesn't move?
#Override
public void act(float delta) {
super.act(delta);
//Target position in world coordinates
Vector2 targetPosition = new Vector2(4.5142856f, -4.228572f);
//target speed
float targetSpeed = 1f;
//direction
Vector2 direction = targetPosition.sub(body.getPosition());
//distance
float distanceToTravel = direction.nor().len2();
// For most of the movement, the target speed is ok
float speedToUse = targetSpeed;
float distancePerTimestep = speedToUse / 60.0f;
if ( distancePerTimestep > distanceToTravel )
speedToUse *= ( distanceToTravel / distancePerTimestep );
Vector2 desiredVelocity = direction.scl(speedToUse);
Vector2 changeInVelocity = desiredVelocity.sub(body.getLinearVelocity());
Vector2 force = new Vector2(changeInVelocity.scl(body.getMass() * 60.0f));
System.out.println(force);
body.applyForce(force, body.getWorldCenter(), true);
}
Ok I figured it out. The method below will return the correct velocity so that the body can reach the target point.
public Vector2 calculateVelocity(Vector2 target) {
Vector2 direction = new Vector2(target.x - body.getPosition().x, target.y - body.getPosition().y ).nor();
float speed = Constants.enemySpeed;
return new Vector2( speed * direction.x, speed * direction.y );
}

Dealing with twip precision limit placed on DisplayObject positioning

I'm working on a project to render xps content in flash, and am running into the twip (1/20 of a unit) precision limit in flash. The twip limit is mentioned in the swf file format, but in the flash as3 documentation it's only mentioned in PrintJob.addPage method. However, when setting the DisplayObject x and y properties, any precision less than 0.05 is rounded. Regardless of any scaling. The code below demonstrates this issue.
package
{
import flash.display.DisplayObject;
import flash.display.Graphics;
import flash.display.GraphicsPathCommand;
import flash.display.Shape;
import flash.display.Sprite;
import flash.display.StageScaleMode;
public class TWIPTest extends Sprite
{
// can change behaviour by switching between createPoint and drawPoint
public function TWIPTest()
{
this.stage.scaleMode = StageScaleMode.NO_SCALE;
// scale our unit square so we can see what is happening
scaleX = 400; scaleY = 400;
// draw grid
var grid : Sprite = new Sprite();
addChild(grid);
grid.graphics.lineStyle(TWIP, 0x888888);
drawGrid(1 / TWIP, 1 / TWIP, TWIP, TWIP, grid);
// center of unit square
var cx : Number = 0.5;
var cy : Number = 0.5;
var shape : Shape;
// GREEN in middle of unit square
this.addChild(createPoint(cx, cy, 0x00FF00));
//drawPoint(cx, cy, 0x00FF00, this.graphics);
// BLUE one TWIP away from GREEN
this.addChild(createPoint(cx + TWIP, cy + TWIP, 0x0000FF));
//drawPoint(cx + TWIP, cy + TWIP, 0x0000FF, this.graphics);
// RED half a TWIP away from GREEN (this does not work....)
this.addChild(createPoint(cx + (TWIP / 2), cy + (TWIP / 2), 0xFF0000, 0.5));
//drawPoint(cx + (TWIP / 2), cy + (TWIP / 2), 0xFF0000, this.graphics, 0.5);
// now insert new container to work around limit encontered with RED point
var container : Sprite = new Sprite();
this.addChild(container);
container.scaleX = 0.5; container.scaleY = 0.5;
container.addChild(createPoint(2 * cx + TWIP, 2 * cy + TWIP, 0xFF00FF, 1.0, 2 * TWIP));
//drawPoint(cx + (TWIP / 2), cy + (TWIP / 2), 0xFF00FF, container.graphics);
}
static private function createPoint(x:Number, y:Number,color:uint,alpha:Number=1.0,radius:Number=0.05):Shape
{
var shape : Shape = new Shape();
shape.x = x; shape.y = y;
shape.graphics.beginFill(color,alpha);
shape.graphics.drawCircle(0, 0, radius);
shape.graphics.endFill();
return shape;
}
static private function drawPoint(x:Number, y:Number,color:uint,target:Graphics,alpha:Number=1.0,radius:Number=0.05):void
{
target.beginFill(color,alpha);
target.drawCircle(x, y, radius);
target.endFill();
}
// drawGrid from #Feltope
private function drawGrid(numColumns:Number, numRows:Number, cellHeight:Number, cellWidth:Number, grid:Sprite):void
{
for (var col:Number = 0; col &lt numColumns + 1; col++)
{
for (var row:Number = 0; row &lt numRows + 1; row++)
{
grid.graphics.moveTo(col * cellWidth, 0);
grid.graphics.lineTo(col * cellWidth, cellHeight * numRows);
grid.graphics.moveTo(0, row * cellHeight);
grid.graphics.lineTo(cellWidth * numColumns, row * cellHeight);
}
}
}
static private const TWIP : Number = 0.05;
}
}
This posting also mentions this issue.
The problem is that in parsing xps files this can happen anytime, and many times, for example
&ltCanvas RenderTransform="96.201126,0,0,-95.787476,713.62598,207.05859"&gt
&ltPath Data="..." RenderTransform="0.010394889,0,0,-0.010439778,-7.4180626,2.1616458"&gt
Notice the dx in the Path element, which seems trivial, but the parent Canvas (and other parents above this) scale it up so the rounding of dx to 0 or 0.05 is very noticeable.
I could add Sprite containers whenever this happens, as in the code above, but that's going to bloat memory and slow down rendering.
My question (finally), has anyone dealt with this issue? Any ideas on a better way of handling this limit? Workarounds? Any help appreciated. cheers
what is the biggest problem here? How it looks on screen or that after parsing the precision is lost? You can't do with rendering but you could do modified DisplayObject that will store for example position then reading it will contain the precision kept. or am I missing the point?:)
Edit:
Following is an example of custom display objects (Shape and Sprite)
import flash.display.Shape;
import flash.display.Sprite;
internal class MySprite extends Sprite
{
protected var m_nX:Number;
protected var m_nY:Number;
override public function get x():Number
{
return m_nX;
}
override public function set x(value:Number):void
{
m_nX = value;
super.x = m_nX;
}
override public function get y():Number
{
return m_nY;
}
override public function set y(value:Number):void
{
m_nY = value;
super.y = m_nY;
}
}
internal class MyShape extends Shape
{
protected var m_nX:Number;
protected var m_nY:Number;
override public function get x():Number
{
return m_nX;
}
override public function set x(value:Number):void
{
m_nX = value;
super.x = m_nX;
}
override public function get y():Number
{
return m_nY;
}
override public function set y(value:Number):void
{
m_nY = value;
super.y = m_nY;
}
}
Add this to your example and replace any instantiation of Shape and use MyShape, same for Sprite, replace it by MySprite. There will be no visual difference but the x and y of them will return precise values.
This is a sample test for precision keeping:
addChild(createPoint(0.51000005, 0.510000049, 0x800000, 1, TWIP));
var disp :DisplayObject = getChildAt(numChildren - 1);
trace(disp.x, disp.y);
will trace 0.51000005, 0.510000049 but above test added to your example without MySprite and MyShape custom DisplayObjects will return 0.5 0.5.