Java tutorial
/* * Copyright 2017 TheNightForum * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.tnf.ptm.entities.asteroid; import com.badlogic.gdx.graphics.g2d.TextureAtlas; import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.physics.box2d.Body; import com.badlogic.gdx.physics.box2d.ContactImpulse; import com.tnf.ptm.common.*; import com.tnf.ptm.handler.dra.Dra; import com.tnf.ptm.entities.item.Loot; import com.tnf.ptm.entities.item.PtmItem; import com.tnf.ptm.entities.planet.Planet; import com.tnf.ptm.entities.item.MoneyItem; import com.tnf.ptm.gfx.particle.ParticleSrc; import com.tnf.ptm.entities.planet.TileObject; import java.util.ArrayList; import java.util.List; public class Asteroid implements PtmObject { public static final float MIN_SPLIT_SZ = .25f; public static final float MIN_BURN_SZ = .3f; public static final float SZ_TO_LIFE = 20f; public static final float SPD_TO_ATM_DMG = SZ_TO_LIFE * .11f; public static final float MAX_SPLIT_SPD = 1f; private static final float DUR = .5f; private final Body myBody; private final Vector2 myPos; private final Vector2 mySpd; private final ArrayList<Dra> myDras; private final TextureAtlas.AtlasRegion myTex; private final RemoveController myRemoveController; private final ParticleSrc mySmokeSrc; private final ParticleSrc myFireSrc; private final float myMass; private float myAngle; private float myLife; private float mySize; public Asteroid(PtmGame game, TextureAtlas.AtlasRegion tex, Body body, float size, RemoveController removeController, ArrayList<Dra> dras) { myTex = tex; myRemoveController = removeController; myDras = dras; myBody = body; mySize = size; myLife = SZ_TO_LIFE * mySize; myPos = new Vector2(); mySpd = new Vector2(); myMass = myBody.getMass(); setParamsFromBody(); List<ParticleSrc> effs = game.getSpecialEffects().buildBodyEffs(size / 2, game, myPos, mySpd); mySmokeSrc = effs.get(0); myFireSrc = effs.get(1); myDras.add(mySmokeSrc); myDras.add(myFireSrc); } @Override public Vector2 getPosition() { return myPos; } @Override public FarObj toFarObj() { float rotSpd = myBody.getAngularVelocity(); return new FarAsteroid(myTex, myPos, myAngle, myRemoveController, mySize, mySpd, rotSpd); } @Override public List<Dra> getDras() { return myDras; } @Override public float getAngle() { return myAngle; } @Override public Vector2 getSpd() { return mySpd; } @Override public void handleContact(PtmObject other, ContactImpulse impulse, boolean isA, float absImpulse, PtmGame game, Vector2 collPos) { float dmg; if (other instanceof TileObject && MIN_BURN_SZ < mySize) { dmg = myLife; } else { dmg = absImpulse / myMass / DUR; } receiveDmg(dmg, game, collPos, DmgType.CRASH); } @Override public String toDebugString() { return null; } @Override public Boolean isMetal() { return false; } @Override public boolean hasBody() { return true; } @Override public void update(PtmGame game) { boolean burning = updateInAtm(game); mySmokeSrc.setWorking(burning); myFireSrc.setWorking(burning); setParamsFromBody(); } private boolean updateInAtm(PtmGame game) { Planet np = game.getPlanetMan().getNearestPlanet(); float dst = np.getPos().dst(myPos); if (np.getFullHeight() < dst) { return false; } if (MIN_BURN_SZ >= mySize) { return false; } float dmg = myBody.getLinearVelocity().len() * SPD_TO_ATM_DMG * game.getTimeStep(); receiveDmg(dmg, game, null, DmgType.FIRE); return true; } private void setParamsFromBody() { myPos.set(myBody.getPosition()); mySpd.set(myBody.getLinearVelocity()); myAngle = myBody.getAngle() * PtmMath.radDeg; } @Override public boolean shouldBeRemoved(PtmGame game) { return myLife <= 0 || myRemoveController != null && myRemoveController.shouldRemove(myPos); } @Override public void onRemove(PtmGame game) { game.getPartMan().finish(game, mySmokeSrc, myPos); game.getPartMan().finish(game, myFireSrc, myPos); myBody.getWorld().destroyBody(myBody); if (myLife <= 0) { game.getSpecialEffects().asteroidDust(game, myPos, mySpd, mySize); float vol = PtmMath.clamp(mySize / .5f); game.getSoundManager().play(game, game.getSpecialSounds().asteroidCrack, null, this, vol); maybeSplit(game); } } private void maybeSplit(PtmGame game) { if (MIN_SPLIT_SZ > mySize) { return; } float sclSum = 0; while (sclSum < .7f * mySize * mySize) { float spdAngle = PtmMath.rnd(180); Vector2 spd = new Vector2(); PtmMath.fromAl(spd, spdAngle, PtmMath.rnd(0, .5f) * MAX_SPLIT_SPD); spd.add(mySpd); Vector2 newPos = new Vector2(); PtmMath.fromAl(newPos, spdAngle, PtmMath.rnd(0, mySize / 2)); newPos.add(myPos); float sz = mySize * PtmMath.rnd(.25f, .5f); Asteroid a = game.getAsteroidBuilder().buildNew(game, newPos, spd, sz, myRemoveController); game.getObjMan().addObjDelayed(a); sclSum += a.mySize * a.mySize; } float thrMoney = mySize * 40f * PtmMath.rnd(.3f, 1); List<MoneyItem> moneyItems = game.getItemMan().moneyToItems(thrMoney); for (MoneyItem mi : moneyItems) { throwLoot(game, mi); } } private void throwLoot(PtmGame game, PtmItem item) { float spdAngle = PtmMath.rnd(180); Vector2 lootSpd = new Vector2(); PtmMath.fromAl(lootSpd, spdAngle, PtmMath.rnd(0, Loot.MAX_SPD)); lootSpd.add(mySpd); Vector2 pos = new Vector2(); PtmMath.fromAl(pos, spdAngle, PtmMath.rnd(0, mySize / 2)); pos.add(myPos); Loot l = game.getLootBuilder().build(game, pos, item, lootSpd, Loot.MAX_LIFE, PtmMath.rnd(Loot.MAX_ROT_SPD), null); game.getObjMan().addObjDelayed(l); } @Override public void receiveDmg(float dmg, PtmGame game, Vector2 pos, DmgType dmgType) { myLife -= dmg; game.getSpecialSounds().playHit(game, this, pos, dmgType); } @Override public boolean receivesGravity() { return true; } @Override public void receiveForce(Vector2 force, PtmGame game, boolean acc) { if (acc) { force.scl(myMass); } myBody.applyForceToCenter(force, true); } public float getLife() { return myLife; } }