/* * The MIT License (MIT) * * FXGL - JavaFX Game Library * * Copyright (c) 2015-2017 AlmasB (almaslvl@gmail.com) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ package com.almasb.fxglgames.geowars.control; import com.almasb.fxgl.app.FXGL; import com.almasb.fxgl.core.math.FXGLMath; import com.almasb.fxgl.core.math.Vec2; import com.almasb.fxgl.ecs.AbstractControl; import com.almasb.fxgl.ecs.Entity; import com.almasb.fxgl.entity.Entities; import com.almasb.fxgl.entity.GameEntity; import com.almasb.fxgl.entity.SpawnData; import com.almasb.fxgl.entity.control.OffscreenCleanControl; import com.almasb.fxgl.time.LocalTimer; import com.almasb.fxglgames.geowars.WeaponType; import javafx.geometry.Point2D; import javafx.scene.paint.Color; /** * @author Almas Baimagambetov (almaslvl@gmail.com) */ public class PlayerControl extends AbstractControl { private GameEntity player; private long spawnTime = System.currentTimeMillis(); private LocalTimer weaponTimer = FXGL.newLocalTimer(); @Override public void onAdded(Entity entity) { player = (GameEntity) entity; } @Override public void onUpdate(Entity entity, double tpf) { } public void shoot(Point2D shootPoint) { WeaponType type = FXGL.getApp().getGameState().getObject("weaponType"); if (weaponTimer.elapsed(type.delay)) { Point2D position = player.getCenter().subtract(14, 4.5); Point2D vectorToMouse = shootPoint.subtract(position); GameEntity bullet = spawnBullet(position, vectorToMouse); switch (type) { case RICOCHET: bullet.removeControl(OffscreenCleanControl.class); bullet.addControl(new RicochetControl()); break; case BEAM: Point2D toMouse = vectorToMouse.normalize().multiply(10); Point2D pos = position; for (int i = 0; i < 7; i++) { spawnBullet(pos.add(toMouse), toMouse); pos = pos.add(toMouse); } break; case WAVE: double baseAngle = new Vec2(vectorToMouse.getX(), vectorToMouse.getY()).angle() + 45; for (int i = 0; i < 7; i++) { Vec2 vec = Vec2.fromAngle(baseAngle); spawnBullet(position, new Point2D(vec.x, vec.y)); baseAngle += 45; } break; case NORMAL: default: break; } weaponTimer.capture(); } } private GameEntity spawnBullet(Point2D position, Point2D direction) { return (GameEntity) FXGL.getApp().getGameWorld().spawn("Bullet", new SpawnData(position.getX(), position.getY()) .put("direction", direction) ); } public void left() { player.translateX(-5); makeExhaustFire(); } public void right() { player.translateX(5); makeExhaustFire(); } public void up() { player.translateY(-5); makeExhaustFire(); } public void down() { player.translateY(5); makeExhaustFire(); } private void makeExhaustFire() { Vec2 position = new Vec2(player.getCenter().getX(), player.getCenter().getY()); double rotation = player.getRotation(); Color midColor = Color.BLUE; Color sideColor = Color.MEDIUMVIOLETRED.brighter(); Vec2 direction = Vec2.fromAngle(rotation); float t = (System.currentTimeMillis() - spawnTime) / 1000f; Vec2 baseVel = direction.mul(-45f); Vec2 perpVel = new Vec2(baseVel.y, -baseVel.x).mulLocal(2f * FXGLMath.sin(t * 10f)); // subtract half extent x, y of Glow.png mul half extent player Vec2 pos = position.sub(new Vec2(17.5, 10)).addLocal(direction.negate().normalizeLocal().mulLocal(20)); // middle stream Vec2 randVec = Vec2.fromAngle(FXGLMath.radiansToDegrees * FXGLMath.random() * FXGLMath.PI2); Vec2 velMid = baseVel.add(randVec.mul(7.5f)); Entities.builder() .at(pos.x, pos.y) .with(new ExhaustParticleControl(velMid, 800, midColor)) .buildAndAttach(FXGL.getApp().getGameWorld()); // side streams Vec2 randVec1 = Vec2.fromAngle(FXGLMath.radiansToDegrees * FXGLMath.random() * FXGLMath.PI2); Vec2 randVec2 = Vec2.fromAngle(FXGLMath.radiansToDegrees * FXGLMath.random() * FXGLMath.PI2); Vec2 velSide1 = baseVel.add(randVec1.mulLocal(2.4f)).addLocal(perpVel); Vec2 velSide2 = baseVel.add(randVec2.mulLocal(2.4f)).subLocal(perpVel); Entities.builder() .at(pos.x, pos.y) .with(new ExhaustParticleControl(velSide1, 800, sideColor)) .buildAndAttach(FXGL.getApp().getGameWorld()); Entities.builder() .at(pos.x, pos.y) .with(new ExhaustParticleControl(velSide2, 800, sideColor)) .buildAndAttach(FXGL.getApp().getGameWorld()); // Pools.free(direction); // Pools.free(position); // Pools.free(baseVel); // Pools.free(perpVel); // Pools.free(pos); // Pools.free(randVec); // Pools.free(velMid); // Pools.free(randVec1); // Pools.free(randVec2); // Pools.free(velSide1); // Pools.free(velSide2); } }