I have been working with box2d and am having a problem where my body is not being set to the correct y coordinate when I try to position it at the bottom right of the screen.
I am trying to set the y coordinate to 0 so that the body aligns directly with the bottom of the screen. However, the half of the body is hanging off the screen. Even when I print out the body's location, it says the y is at 0.
I have my pixel per meter set at screenHeight / 80 which comes out to be around 25 PPM for the current devise I am using. I am not sure if my scaling is causing something weird to happen.
Code:
public class GameScreen extends ScreenAdapter {
Controller game;
public World world;
public Body ball;
public Body block;
public Box2DDebugRenderer box2DDebugRenderer;
private Matrix4 cameraBox2D;
public MyGestureListener myGestureListener;
//x-axis length for top/bottom bar
private float goalWidth;
//pixels per meter
public float PPM;
//y-axis height for back bar
private float goalHeight;
private float goalPostThickness;
//Screen height and width
private float screenWidth;
private float screenHeight;
//How far down/up posts are from edge of screen
private float goalPostTopOffset;
private float goalPostBottomOffset;
//Center x,y of cannon
private float cannonOriginX; //Variables used for starting poisition of balls
private float cannonOriginY;
//Center x,y of ball
float ballX;
float ballY;
//Velocity of ball
public float velocity = 50;
public int colorCode = 1;
//Tracks users drag y coord
public float panLocation = 0;
//Velocity of block once the user releases
public float flingVelocity;
//Changes to true when the block is released
public boolean isReleased = false;
public GameScreen (Controller game){
this.game = game;
}
#Override
public void show(){
myGestureListener = new MyGestureListener(game, this);
cameraBox2D = new Matrix4(game.cam.combined);
screenWidth = game.getScreenWidth();
screenHeight = game.getScreenHeight();
//PPM = screenHeight / 80f;
PPM = screenHeight / 80f;
goalPostTopOffset = screenHeight/7;
goalPostBottomOffset = goalPostTopOffset * 3;
goalHeight = screenHeight - (goalPostTopOffset + goalPostBottomOffset);
goalWidth = screenWidth / 6;
goalPostThickness = screenWidth / 75;
cannonOriginX = goalWidth / 2; //Variables used for starting position of balls
cannonOriginY = (goalPostThickness*5) / 2;
ballX = 0 + cannonOriginX;
ballY = (goalPostBottomOffset - (goalPostBottomOffset / 4)) + cannonOriginY;
world = new World(new Vector2(0, 0f), true);
box2DDebugRenderer = new Box2DDebugRenderer();
//Creates animated ball
ball = createBall();
//Sets radius, density, etc.
setBallProperties(ball);
//Creates block that stops balls
block = createBlock();
//Sets properties
setBlockProperties(block);
}
#Override
public void render(float delta){
//Logic
world.step(1/60f, 6, 2);
//Draw
game.cam.update();
Gdx.gl.glClearColor(32/255f, 32/255f, 32/255f, 0);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
box2DDebugRenderer.render(world, game.cam.combined.scl(PPM));
game.shape.setProjectionMatrix(game.cam.combined);
Gdx.input.setInputProcessor(new GestureDetector(myGestureListener));
System.out.println(block.getPosition().y);
System.out.println(block.getPosition().x);
drawNonAnimated();
drawAnimated();
//show()
cameraBox2D = game.cam.combined.cpy(); //Copy the main camera
cameraBox2D.scl(PPM); //Scale the camera projection to the ratio you're using for Box2D
//render()
box2DDebugRenderer.render(world, cameraBox2D);
}
#Override
public void hide(){
}
//draws stationary objects such as goal posts
public void drawNonAnimated(){
//Cannon platform
game.shape.setColor(1, 1, 1, 1);
game.shape.begin(ShapeRenderer.ShapeType.Filled);
game.shape.rect(0, (goalPostBottomOffset - (goalPostBottomOffset / 4))/PPM, goalWidth/PPM, (goalPostThickness*2)/PPM);
game.shape.end();
//Cannon
game.shape.setColor(1, 1, 1, 1);
game.shape.begin(ShapeRenderer.ShapeType.Filled);
game.shape.rect(0, (goalPostBottomOffset - (goalPostBottomOffset / 4))/PPM, cannonOriginX/PPM,
cannonOriginY/PPM, goalWidth/PPM, (goalPostThickness*5)/PPM, 1, 1, 45);
game.shape.end();
}
public void drawAnimated(){
//FOR BALL
velocity--;
ball.setLinearVelocity(new Vector2(35,velocity));
Vector2 pos = ball.getPosition();
if (pos.x >= screenWidth/PPM){
ball.setTransform(new Vector2(ballX/PPM, ballY/PPM), 0);
//Changing color of ball each loop
if (colorCode == 3){
colorCode = 1;
}
else{
colorCode++;
}
//max 75 min 50
velocity = randInt(50, 75);
}
attachCircleShape(pos);
blockerMovement();
}
public void blockerMovement(){
//FOR BLOCKER RECTANGLE ANIMATION
Vector2 pos = block.getPosition();
float boundaryLocation = (goalPostBottomOffset - (goalPostBottomOffset / 4))/PPM;
//attachBlockerShape(pos);
panLocation = myGestureListener.getPanLocation();
if (isReleased == true){
//Get the velocity as the block is released
//to determine the speed it will continue to go after release
block.setLinearVelocity(0, flingVelocity);
flingVelocity -= 3;
}
else if (myGestureListener.getCheckRelease()|| panLocation/PPM >= boundaryLocation && !isReleased) {
flingVelocity = myGestureListener.speed;
isReleased = true;
System.out.println("SPEED: " + flingVelocity);
}
else if (myGestureListener.isPaning) {
block.setTransform(new Vector2((screenWidth - goalPostThickness) / PPM, panLocation / PPM), 0);
}
}
//Creates animated ball
public Body createBall(){
Body bBody;
BodyDef def = new BodyDef();
def.type = BodyDef.BodyType.DynamicBody;
def.position.set(ballX/PPM,ballY/PPM);
def.fixedRotation = true;
bBody = world.createBody(def);
return bBody;
}
//Sets radius, density, etc.
public void setBallProperties(Body body){
float gbt = screenWidth / 75; //Goal post thickness
float ballRadius = (gbt * 1.5f) / PPM;
// Create a circle shape and set its radius to 6
CircleShape circle = new CircleShape();
circle.setRadius(ballRadius);
// Create a fixture definition to apply our shape to
FixtureDef fixtureDef = new FixtureDef();
fixtureDef.shape = circle;
fixtureDef.density = 3.5f;
fixtureDef.friction = 0.4f;
fixtureDef.restitution = 0.6f; // Make it bounce a little bit
// Create our fixture and attach it to the body
Fixture fixture = ball.createFixture(fixtureDef);
circle.dispose();
}
public Body createBlock(){
Body bBody;
BodyDef def = new BodyDef();
def.type = BodyDef.BodyType.DynamicBody;
def.position.set((screenWidth - goalPostThickness)/PPM,0);
def.fixedRotation = true;
bBody = world.createBody(def);
return bBody;
}
//Sets radius, density, etc.
public void setBlockProperties(Body body){
float gbt = screenWidth / 75; //Goal post thickness
// Create a circle shape and set its radius to 6
PolygonShape square = new PolygonShape();
square.setAsBox(goalPostThickness/PPM, (goalWidth/2)/PPM);
// Create a fixture definition to apply our shape to
FixtureDef fixtureDef = new FixtureDef();
fixtureDef.shape = square;
fixtureDef.density = 3.5f;
fixtureDef.friction = 0.4f;
fixtureDef.restitution = 0.6f; // Make it bounce a little bit
// Create our fixture and attach it to the body
Fixture fixture = block.createFixture(fixtureDef);
square.dispose();
}
public static int randInt(int min, int max) {
Random rand = new Random();
int randomNum = rand.nextInt((max - min) + 1) + min;
return randomNum;
}
public void attachBlockerShape(Vector2 pos){
game.shape.setColor(1, 1, 1, 1);
game.shape.begin(ShapeRenderer.ShapeType.Filled);
game.shape.rect(pos.x, pos.y, goalPostThickness/PPM, (goalWidth/2)/PPM);
game.shape.end();
}
//Attaching a regular libgdx shape to the position of box2d shape
public void attachCircleShape(Vector2 pos){
//Color of ball changes each loop
if (colorCode == 1){
//Blue
game.circle.setColor(66/255f, 134/255f, 244/255f, 0);
}
else if (colorCode == 2){
//Pink
game.circle.setColor(244/255f, 66/255f, 116/255f, 0);
}
else if (colorCode == 3){
game.circle.setColor(244/255f, 116/255f, 66/255f, 0);
}
game.circle.begin(ShapeRenderer.ShapeType.Filled);
game.circle.circle(pos.x*PPM, pos.y*PPM, goalPostThickness * 1.5f);
game.circle.end();
game.cam.update();
}
#Override public void dispose(){
box2DDebugRenderer.dispose();
world.dispose();
}
}
If you create a Body with Box2d 0,0 is in the center of the Body while libgdx set 0,0 on the bottom left corner.
So if you create a Body with Box2d and you want that 0,0 is in the bottom left corner you must move the Body by half of width on x and half of height on y:
public Body createBody(float x, float y, float width, float height){
BodyDef bodyDef = new BodyDef();
bodyDef.type = BodyDef.BodyType.DynamicBody;
//Move the body so if x and y are 0 the bottom left corner of the body is on position 0,0
bodyDef.position.x = x + width / 2;
bodyDef.position.y = y + height / 2;
PolygonShape polygonShape = new PolygonShape();
polygonShape.setAsBox(width / 2, height / 2);
FixtureDef fixtureDef = new FixtureDef();
fixtureDef.shape = polygonShape;
Body body = world.createBody(bodyDef);
body.createFixture(fixtureDef);
polygonShape.dispose();
return body;
}
Related
I'm trying to see if a touch position collides with a Body and I'm not sure about the best way to implement it.
As of now, I have an Obstacle.java that draws a polygon-shaped body as a rectangle. It works fine to draw in the world, I just need to check for collisions.
Furthermore, I want to add some Sprite/Texture/Image to this body, so maybe it's better to check for collision between the sprite rather than the body, I'm not sure. So any pointers in the right direction would be helpful.
Obstacle.java
public class Obstacle{
public int x,y;
public Vector3 position;
public World world;
private Body body;
private BodyDef bodyDef;
private PolygonShape shape;
private float density = 1f;
private final float width = 360f;
private final float height = 20f;
Random r;
public Obstacle(World world) {
r = new Random();
this.world = world;
//rectangle
bodyDef = new BodyDef();
bodyDef.type = BodyDef.BodyType.DynamicBody;
bodyDef.position.set( new Vector2( x + width / 2, y + height / 2));
float randomValue = (float)(0 + (540 - 0) * r.nextDouble());
shape = new PolygonShape();
shape.setAsBox( width / 2, height / 2 );
body = world.createBody(bodyDef);
body.createFixture(shape, density);
body.setTransform(randomValue,1160,0);
float angularVelocity;
if(r.nextInt(2)==0){
angularVelocity=-3;
}else{
angularVelocity=3;
}
body.setAngularVelocity(angularVelocity);
body.setLinearVelocity(0,-250);
}
public float getX() {
return position.x;
}
public float getY() {
return position.y;
}
public float getWidth() {
return 360 / GdxGame.PPM;
}
public float getHeight() {
return 20 / GdxGame.PPM;
}
public void render(SpriteBatch batch,float delta) {
}
public Boolean collidesWithPlayer(float touchX, float touchY){
return false;
}
}
The last method collidesWithPlayer was an effort from me to implement the detection, and in my Screen.java I have:
for(int i = 0; i < obstacles.size(); i++) {
if(obstacles.get(i).collidesWithPlayer(pointerX, pointerY)) {
hasDied=true;
}else{
isPaused=true;
}
}
I am working in a existing project for an amazfit watchface. Code is based in java. The question is: In original project, for show battery, steps and sport percentage, show three circles. My idea is to draw a rectangle (or a line) instead the original circle. The problem is I am new programming in java and I donĀ“t know for change this without FC app.
this watch has two screens: one active and other in stand-by mode (8colors only)
active mode draws circle, standby mode works with an png image.
This is the code (for circles):
package es.xxxx.xxxx.widget;
private final float startAngleBattery = 30;
private final float arcSizeBattery = 360 - startAngleBattery - startAngleBattery;
#Override
public void init(Service service) {
this.thickness = (int) service.getResources().getDimension(R.dimen.xxxx_circles_thickness);
this.textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
this.textPaint.setTypeface(ResourceManager.getTypeFace(service.getResources(), ResourceManager.Font.BEBAS_NEUE));
this.textPaint.setTextSize(service.getResources().getDimension(R.dimen.xxxx_circles_font_size));
this.textPaint.setColor(service.getResources().getColor(R.color.xxxx_time_colour));
this.textPaint.setTextAlign(Paint.Align.CENTER);
this.ring = new Paint(Paint.ANTI_ALIAS_FLAG);
this.ring.setStrokeCap(Paint.Cap.ROUND);
this.ring.setStyle(Paint.Style.STROKE);
this.ring.setStrokeWidth(this.thickness);
this.circle = new Paint(Paint.ANTI_ALIAS_FLAG);
this.circle.setColor(Color.BLACK);
this.circle.setStrokeWidth(1f);
this.circle.setStyle(Paint.Style.STROKE);
#Override
public void draw(Canvas canvas, float width, float height, float centerX, float centerY) {
int count = canvas.save();
int radius = Math.round(Math.min(width / 2, height / 2)) - this.thickness;
RectF oval = new RectF(centerX - radius, centerY - radius, centerX + radius, centerY + radius);
// rotate from 0 to 270 degrees
canvas.rotate(90, centerX, centerY);
this.ring.setColor(this.backgroundColour);
canvas.drawArc(oval, startAngleBattery, arcSizeBattery, false, ring);
if (batterySweepAngle != null) {
float px = getPointX(oval, centerX, startAngleBattery, batterySweepAngle);
float py = getPointY(oval, centerY, startAngleBattery, batterySweepAngle);
this.ring.setColor(this.batteryColour);
canvas.drawArc(oval, startAngleBattery, batterySweepAngle, false, ring);
canvas.drawCircle(px, py, this.thickness / 3f, circle);
canvas.drawCircle(px, py, this.thickness / 6f, circle);
}
canvas.restoreToCount(count);
if (this.batteryData != null) {
String text = String.format("%02d", this.batteryData.getLevel() * 100 / this.batteryData.getScale());
canvas.drawText(text, batteryTextLeft, batteryTextTop, textPaint);
}
}
#Override
public void onDataUpdate(DataType type, Object value) {
switch (type) {
case BATTERY:
onBatteryData((Battery) value);
break;
}
}
#Override
public List<DataType> getDataTypes() {
return Arrays.asList(DataType.BATTERY);
private void onBatteryData(Battery battery) {
this.batteryData = battery;
if (batteryData == null) {
this.batterySweepAngle = 0f;
} else {
float scale = batteryData.getLevel() / (float) batteryData.getScale();
this.batterySweepAngle = Math.min(arcSizeBattery, arcSizeBattery * scale);
}
}
private RectF nextOval(RectF oval) {
oval.left = oval.left + this.thickness + MARGIN;
oval.top = oval.top + this.thickness + MARGIN;
oval.right = oval.right - this.thickness - MARGIN;
oval.bottom = oval.bottom - this.thickness - MARGIN;
return oval;
}
private float getPointX(RectF oval, float cx, float startAngle, float sweepAngle) {
float width = oval.right - oval.left;
return (float) (cx + (width / 2D) * Math.cos((sweepAngle + startAngle) * Math.PI / 180));
}
private float getPointY(RectF oval, float cy, float startAngle, float sweepAngle) {
float height = oval.bottom - oval.top;
return (float) (cy + (height / 2D) * Math.sin((sweepAngle + startAngle) * Math.PI / 180));
}
#Override
public List<SlptViewComponent> buildSlptViewComponent(Service service) {
Typeface timeTypeFace = ResourceManager.getTypeFace(service.getResources(), ResourceManager.Font.BEBAS_NEUE);
SlptLinearLayout power = new SlptLinearLayout();
power.alignX = 2;
power.alignY = 2;
power.add(new SlptPowerNumView());
power.setTextAttrForAll(
service.getResources().getDimension(R.dimen.xxxx_circles_font_size_slpt),
-1,
timeTypeFace
);
power.setStart(
(int) service.getResources().getDimension(R.dimen.xxxx_battery_text_left_slpt),
(int) service.getResources().getDimension(R.dimen.xxxx_battery_text_top_slpt));
SlptPowerArcAnglePicView powerArcView = new SlptPowerArcAnglePicView();
powerArcView.setImagePicture(Util.assetToBytes(service, "battery_splt.png"));
powerArcView.start_angle = (int) startAngleBattery + 180 - 3;
powerArcView.full_angle = (int) arcSizeBattery + 6;
return Arrays.asList(power, powerArcView);
}
}
Thanks in advance.
For anyone still searching...
You can draw the rectangular in the "draw" function that runs in loop constantly when screen is on, however, screen off (SLPT mode) uses ingenic's libraries to draw (function buildSlptViewComponent) and there is the real problem.
I don't want to get into details because it would be pages, so have a look at GreatFit project.
How to deal with different sizes of frames? If I setBounds(0, 0, 100, 100) in constructor then some frames are smaller but if I update it then frames are moved to left and up. How to make that every frame will be in the same place?
mayby you can see it
http://imgur.com/a/AN8Gc
public class Player extends Sprite{
//floats
private float animationTimer;
//box2d variables
public World world;
public Body body;
//enums
public enum State{STANDING, MOVING, SHOOTING, RELOAD, MALEE_ATTACK}
public State currentState;
public State previousState;
//booleans
boolean shoot;
boolean reload;
boolean maleeAttack;
private TextureRegion region;
public PlayScreen playScreen;
public Player(PlayScreen playScreen){
this.playScreen = playScreen;
this.world = playScreen.getWorld();
definePlayer();
animationTimer = 0;
region = Assets.instance.playerAssets.idleAniamtion.getKeyFrame(animationTimer);
setRegion(region);
setBounds(0, 0, getRegionWidth() / Constants.PPM, getRegionHeight() / Constants.PPM);
setPosition(0, 0);
currentState = State.STANDING;
previousState = State.STANDING;
shoot = false;
reload = false;
maleeAttack = false;
}
public void definePlayer(){
BodyDef bodyDef = new BodyDef();
bodyDef.position.set(100 / Constants.PPM, 100 / Constants.PPM);
bodyDef.type = BodyDef.BodyType.DynamicBody;
body = world.createBody(bodyDef);
FixtureDef fixtureDef = new FixtureDef();
CircleShape shape = new CircleShape();
shape.setRadius(50 / Constants.PPM);
fixtureDef.shape = shape;
body.createFixture(fixtureDef).setUserData(this);
body.setLinearDamping(Constants.LINEAR_DAMPING);
}
public void update(float delta){
region = Assets.instance.playerAssets.idleAniamtion.getKeyFrame(animationTimer);
setRegion(getFrame(delta));
moving();
//rotate();
}
public void moving(){
setPosition(body.getPosition().x - getWidth() / 2, body.getPosition(). y - getHeight() / 2);
//setBounds(0, 0, getRegionWidth() / Constants.PPM, getRegionHeight() / Constants.PPM); update bounds
if (input.isKeyPressed(Input.Keys.W) && body.getLinearVelocity().y < 5){
body.applyLinearImpulse(new Vector2(0, 1), body.getWorldCenter(), true);
}
if (input.isKeyPressed(Input.Keys.S) && body.getLinearVelocity().y > -5){
body.applyLinearImpulse(new Vector2(0, -1), body.getWorldCenter(), true);
}
if (input.isKeyPressed(Input.Keys.D) && body.getLinearVelocity().x < 5){
body.applyLinearImpulse(new Vector2(1, 0), body.getWorldCenter(), true);
}
if (input.isKeyPressed(Input.Keys.A) && body.getLinearVelocity().x > -5){
body.applyLinearImpulse(new Vector2(-1, 0), body.getWorldCenter(), true);
}
if (Gdx.input.isKeyPressed(Input.Keys.R)){
reload = true;
}
if (Gdx.input.isKeyPressed(Input.Keys.F)){
maleeAttack = true;
}
if (Gdx.input.isButtonPressed(Input.Buttons.LEFT)){
shoot = true;
}
}
public TextureRegion getFrame(float delta){
TextureRegion region;
currentState = getState();
switch (currentState){
case MOVING:
region = Assets.instance.playerAssets.moveAnimation.getKeyFrame(animationTimer);
break;
case SHOOTING:
maleeAttack = false;
region = Assets.instance.playerAssets.shootAniamtion.getKeyFrame(animationTimer);
if (Assets.instance.playerAssets.shootAniamtion.isAnimationFinished(animationTimer)){
shoot = false;
}
break;
case RELOAD:
region = Assets.instance.playerAssets.reloadAnimation.getKeyFrame(animationTimer);
if (Assets.instance.playerAssets.reloadAnimation.isAnimationFinished(animationTimer)){
reload = false;
}
break;
case MALEE_ATTACK:
region = Assets.instance.playerAssets.maleeAttackAnimation.getKeyFrame(animationTimer);
if (Assets.instance.playerAssets.maleeAttackAnimation.isAnimationFinished(animationTimer)) {
maleeAttack = false;
}
break;
default:
region = Assets.instance.playerAssets.idleAniamtion.getKeyFrame(animationTimer);
break;
}
animationTimer = currentState == previousState ? animationTimer + delta : 0;
previousState = currentState;
return region;
}
public State getState(){
if ((body.getLinearVelocity().x > 1 || body.getLinearVelocity().x < -1 || body.getLinearVelocity().y > 1 || body.getLinearVelocity().y < - 1) && !reload && !shoot && !maleeAttack){
return State.MOVING;
}
if (shoot && !reload){
return State.SHOOTING;
}
if (reload && !maleeAttack){
return State.RELOAD;
}
if (maleeAttack){
return State.MALEE_ATTACK;
}
else {
return State.STANDING;
}
}
public Vector2 getMousePosition(){
Vector2 mousePosition;
mousePosition = playScreen.getViewport().unproject(new Vector2(Gdx.input.getX(), Gdx.input.getY()));
return mousePosition;
}
public float getMouseAngle(){
float angle = (float) Math.atan2(getMousePosition().y - body.getPosition().y, getMousePosition().x - body.getPosition().x);
return angle;
}
public void rotate(){
setOrigin(getWidth() / 2, getHeight() / 2 );
setRotation((float) (getMouseAngle() * (180/Math.PI)));
body.setTransform(body.getPosition(), getMouseAngle());
}
}
To avoid the resizing of the texture just create a variable size used to set the bounds. The bound needs to set every frame.
public class Player extends Sprite {
private Body body;
private Vector2 size;
public Player(){
this.size = new Vector2( getRegionWidth() / Constants.PPM, getRegionHeight() / Constants.PPM );
}
public void update( float delta ){
Vector2 position = body.getPosition();
setRegion( getFrame( delta ) );
setRotation( MathUtils.radDeg * body.getAngle() );
setBounds( position.x, position.y, size.x, size.y );
setOriginCenter();
}
public void rotate(){
this.body.setTransform( body.getPosition(), getMouseAngle() );
}
}
You need to use the additional data information a TextureAtlas provides as an AtlasRegion.
One complete animation should have the same (width/height) size for each keyframe. Pick a size where the biggest keyfarme fits into. Also be aware of positioning correctly. Have the same pivot point for each keyframe.
To avoid wasting space when packing your TextureAtlas enable "trim" function. Should be supported by any TexturePacker Tool out there.
The texture data file (for libGDX) then has entries like this:
walk_animation
rotate: false
xy: 794, 235
size: 86, 109
orig: 160, 170
offset: 37, 22
index: 5
Use the AtlasRegion to draw things at the correct size and position:
float width = 400; // pick your size here
float height = 300;
float offsetPctX = atlasRegion.offsetX / atlasRegion.originalWidth;
float offsetPctY = atlasRegion.offsetY / atlasRegion.originalHeight;
float scaleWidth = (float) atlasRegion.packedWidth / atlasRegion.originalWidth;
float scaleHeight = (float) atlasRegion.packedHeight / atlasRegion.originalHeight;
float drawWidth = width * scaleWidth;
float drawHeight = height * scaleHeight;
float regionOffsetX = offsetPctX * width;
float regionOffsetY = offsetPctY * height;
float drawScaleX = 1; // adjust to your needs
float drawScaleY = 1;
float drawOriginX = 0; // adjust to tour needs
float drawOriginY = 0;
float drawRotation = false;
float x = 100 + offsetX + regionOffsetX; // adjust to your needs
float y = 100 + offsetY + regionOffsetY;
spriteBatch.draw(atlasRegion, x, y, drawOriginX, drawOriginY, drawWidth, drawHeight, drawScaleX, drawScaleY, drawRotation);
I'm using libgdx in java android studio. i have just started. i'm working on android phone. i not using any cameras. all i want is a sprite bounce of all four sides of the screen without tapping. i tried many codes i thought would work but nope. i hope u guys can help me. I'm expecting an answer soon as possible. Thanks
this is what i have:
SpriteBatch batch;
Texture background;
Sprite backgroundsprite;
Sprite ballsprite;
Texture line;
Texture ballimg;
BitmapFont credits;
BitmapFont input;
BitmapFont play;
float dt;
String string = "";
float ballx;
float bally;
float speedx;
float speedy;
Rectangle screenrect;
Rectangle ballrect;
float screenLeft ;
float screenBottom ;
float screenTop ;
float screenRight ;
#Override
public void create() {
batch = new SpriteBatch();
speedx = 5f * dt;
speedy = 5f * dt;
createsprite();
createbackground();
createtext();
ballx = ballsprite.getX();
bally = ballsprite.getY();
}
#Override
public void render() {
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
dt = Gdx.graphics.getDeltaTime();
ballsprite.setPosition(ballx + speedx,ballsprite.getY());
ballsprite.translateX(speedx);
float left = ballrect.getX();
float bottom = ballrect.getY();
float top = bottom + ballrect.getHeight();
float right = left + ballrect.getWidth();
if(left < screenLeft) {
string = "left";
speedx = 5f*dt;
}
if(right > screenRight)
{
string = "right";
speedx = -5f*dt;
}
if(bottom < screenBottom)
{
string = "bottom";
}
if(top > screenTop)
{
string = "top";
}
batch.begin();
backgroundsprite.draw(batch);
ballsprite.draw(batch);
rendertext();
batch.end();
}
public void createbackground() {
background = new Texture("images/BackgroundGodwin.jpg");
backgroundsprite = new Sprite(background);
backgroundsprite.setSize(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
screenrect = new Rectangle(0,0,Gdx.graphics.getWidth(),Gdx.graphics.getHeight());
screenLeft = screenrect.getX();
screenBottom = screenrect.getY();
screenTop = screenBottom + screenrect.getHeight();
screenRight = screenLeft + screenrect.getWidth();
}
public void createsprite() {
ballimg = new Texture("images/SpriteGodwin.png");
ballsprite = new Sprite(ballimg);
ballsprite.setScale(0.65f);
ballsprite.setPosition(Gdx.graphics.getWidth()/3,Gdx.graphics.getHeight()/2);
ballrect = new Rectangle(ballsprite.getBoundingRectangle());
}
#Override
public void dispose() {
batch.dispose();
ballimg.dispose();
background.dispose();
credits.dispose();
play.dispose();
input.dispose();
line.dispose();
}
public void createtext(){
play = new BitmapFont(Gdx.files.internal("fonts/realfont.fnt"));
play.setColor(com.badlogic.gdx.graphics.Color.GOLD);
credits = new BitmapFont(Gdx.files.internal("fonts/realfont.fnt"));
credits.setColor(com.badlogic.gdx.graphics.Color.GOLD);
input = new BitmapFont(Gdx.files.internal("fonts/realfont.fnt"));
input.setColor(com.badlogic.gdx.graphics.Color.OLIVE);
}
public void rendertext() {
credits.draw(batch, "Maded", Gdx.graphics.getWidth() / 7 - 50, Gdx.graphics.getHeight() / 9);
play.draw(batch, "Touch the Screen to play!!", Gdx.graphics.getWidth() / 2 - 175, Gdx.graphics.getHeight() - 80);
input.draw(batch, string, Gdx.graphics.getWidth() / 2 - 160, Gdx.graphics.getHeight() - 120);
}
}
I made a very simple version of what you want:
public class BouncyGame extends ApplicationAdapter {
SpriteBatch batch;
Texture ball;
float speedX = 3f;
float speedY = 3f;
int x;
int y;
#Override
public void create () {
batch = new SpriteBatch();
ball = new Texture("ball.png");
x = Gdx.graphics.getWidth()/2;
y = Gdx.graphics.getHeight()/2;
}
#Override
public void render () {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
//When the ball's x position is on either side of the screen.
//The width of the sprite is taken into account.
if (x > Gdx.graphics.getWidth() - ball.getWidth()/2 || x < 0 + ball.getWidth()/2) {
//Here we flip the speed, so it bonces the other way.
speedX = -speedX;
}
//Same as above, but with on the y-axis.
if (y > Gdx.graphics.getHeight() - ball.getHeight()/2 || y < 0 + ball.getHeight()/2) {
speedY = -speedY;
}
//Move the ball according to the speed.
x += speedX;
y += speedY;
batch.begin();
//Draw the ball so the center is at x and y. Normally it would be drawn from the lower left corner.
batch.draw(ball, x - ball.getWidth()/2, y - ball.getHeight()/2);
batch.end();
}
}
It will result in the following:
http://gfycat.com/TatteredCarefreeHapuku
There are numerous ways to improve this code, you could for example use vectors, and I wouldn't recommend using it in your final product, but it might help you figure out how to do something like this for your own project.
How to unbind an updating vector to a sprite? I am using Libgdx framework. here is my code
public class VectorSample extends GDX_TEST implements InputProcessor {
Texture ball,bullet,guider;
OrthographicCamera camera;
Vector2 vector = new Vector2();
Vector2 vectoralt = new Vector2();
long lastDropTime;
SpriteBatch batch;
Rectangle rect = new Rectangle();
float angle = 0,anglealt = 0;
private ShapeRenderer renderer;
TextureRegion tr;
Sprite sprite,sprite2;
ShapeRenderer sr;
Ship ship;
BallShit shit;
Vector2 nvec;
protected Vector2 center = new Vector2();
Array<Vector2> bullets;
Array<Rectangle> bulletsRect;
Boolean fire = false;
Rectangle tmpRect = new Rectangle();
#Override
public void create() {
renderer = new ShapeRenderer();
ball = new Texture(Gdx.files.internal("data/player.png"));
bullet = new Texture("data/ball_black.png");
tr = new TextureRegion(ball);
camera = new OrthographicCamera();
camera.setToOrtho(false, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
ship = new Ship(new Vector2(5, 50), 1, 1, 0, 5f);
sr = new ShapeRenderer();
batch = new SpriteBatch();
Gdx.input.setInputProcessor(this);
rect.width = ball.getWidth();
rect.height = ball.getHeight();
vector.add(200,200);
sprite = new Sprite(ball);
vectoralt.add(200 + sprite.getWidth(),200);
shit = new BallShit(new Vector2(10,0),50f,50f);
bullets = new Array<Vector2>();
getCenter();
bulletsRect = new Array<Rectangle>();
fireatwill2();
}
#Override
public void render() {
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
camera.update();
batch.setProjectionMatrix(camera.combined);
batch.begin();
{
batch.draw(sprite,vector.x,vector.y,sprite.getWidth()/2,sprite.getHeight()/2,sprite.getWidth(),sprite.getHeight(),1,1,angle);
if(fire == true){
for(Rectangle raindrop: bulletsRect) {
batch.draw(bullet,raindrop.x,raindrop.y);
}
}
}
batch.end();
if(Gdx.input.isKeyPressed(Input.Keys.D)){
vector.add(1,0);
if(vector.x > Gdx.graphics.getWidth()){
Gdx.app.log("x","x");
}
}
if(Gdx.input.isKeyPressed(Input.Keys.A)){
vector.add(-1,0);
if(vector.x < 0){
Gdx.app.log("x","-x");
}
}
float w = camera.frustum.planePoints[1].x - camera.frustum.planePoints[0].x;
float distance = w - (vector.x + sprite.getWidth());
if(distance <=0){
vector.x = w - sprite.getWidth();
}
Gdx.app.log("camera x" , " " + distance);
if(distance >= Gdx.graphics.getWidth() - sprite.getWidth()) {
vector.x = 0;
}
if(Gdx.input.isButtonPressed(Input.Buttons.LEFT)){
fire = true;
if(TimeUtils.nanoTime() - lastDropTime > 100000000) fireatwill2();
}
Iterator<Rectangle> iter = bulletsRect.iterator();
while(iter.hasNext()) {
Rectangle raindrop = iter.next();
double angletry = getAngle() * MathUtils.degreesToRadians;
float speed = 5;
float scale_x = (float)Math.cos(angletry);
float scale_y = (float)Math.sin(angletry);
float velocity_x = (speed* scale_x);
float velocity_y = (speed* scale_y);
raindrop.x += velocity_x;
raindrop.y += velocity_y;
if(raindrop.y < 0) iter.remove();
if(raindrop.y > Gdx.graphics.getHeight() || raindrop.x > Gdx.graphics.getWidth()) iter.remove();
}
//getting the angle
float angle = findAngle(Gdx.input.getX(),
Gdx.graphics.getHeight() - Gdx.input.getY());
this.angle = angle % 360;
}
private float getAngle(){
float angle = findAngle(Gdx.input.getX(),
Gdx.graphics.getHeight() - Gdx.input.getY());
return angle;
}
private void fireatwill2() {
Rectangle raindrop = new Rectangle();
raindrop.x = vector.x + sprite.getWidth() / 2 - (bullet.getWidth() / 2);
raindrop.y = vector.y + sprite.getHeight() / 2 - (bullet.getHeight() / 2);
bulletsRect.add(raindrop);
lastDropTime = TimeUtils.nanoTime();
}
public Vector2 getCenter() {
center.x = vector.x + sprite.getWidth() / 2;
center.y = vector.y + sprite.getHeight() / 2;
return center.cpy();
}
#Override
public void pause() {
super.pause(); //To change body of overridden methods use File | Settings | File Templates.
}
#Override
public void resume() {
super.resume(); //To change body of overridden methods use File | Settings | File Templates.
}
public float findAngle(float x1, float y1) {
Vector2 center = getCenter();
float x0 = center.x;
float y0 = center.y;
float a = MathUtils.atan2(y1 - y0, x1 - x0);
return a * MathUtils.radiansToDegrees;
}
}
and here is the running demo and source is here
I cant explain it well but if you could run the demo u will get what i am saying.
Im really stuck in here.. Thanks.