Initial upload
This commit is contained in:
381
core/src/io/anuke/moment/Control.java
Normal file
381
core/src/io/anuke/moment/Control.java
Normal file
@@ -0,0 +1,381 @@
|
||||
package io.anuke.moment;
|
||||
|
||||
import static io.anuke.moment.world.TileType.tilesize;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.Input.Buttons;
|
||||
import com.badlogic.gdx.Input.Keys;
|
||||
import com.badlogic.gdx.graphics.Color;
|
||||
import com.badlogic.gdx.graphics.GL20;
|
||||
import com.badlogic.gdx.math.MathUtils;
|
||||
import com.badlogic.gdx.math.Rectangle;
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
|
||||
import io.anuke.gif.GifRecorder;
|
||||
import io.anuke.moment.ai.Pathfind;
|
||||
import io.anuke.moment.entities.Enemy;
|
||||
import io.anuke.moment.entities.TileEntity;
|
||||
import io.anuke.moment.resource.ItemStack;
|
||||
import io.anuke.moment.world.Tile;
|
||||
import io.anuke.moment.world.TileType;
|
||||
import io.anuke.ucore.core.*;
|
||||
import io.anuke.ucore.entities.*;
|
||||
import io.anuke.ucore.graphics.Atlas;
|
||||
import io.anuke.ucore.graphics.Hue;
|
||||
import io.anuke.ucore.modules.RendererModule;
|
||||
import io.anuke.ucore.scene.style.Styles;
|
||||
import io.anuke.ucore.scene.utils.Cursors;
|
||||
import io.anuke.ucore.util.Mathf;
|
||||
import io.anuke.ucore.util.Timers;
|
||||
|
||||
public class Control extends RendererModule<Moment>{
|
||||
GifRecorder recorder = new GifRecorder(batch);
|
||||
int rangex = 10, rangey = 10;
|
||||
float breaktime = 0;
|
||||
float breakdur = 50;
|
||||
|
||||
public Control() {
|
||||
atlas = new Atlas("moment.atlas");
|
||||
cameraScale = 4f;
|
||||
setPixelation();
|
||||
buffers.add("shadow", (int) (Gdx.graphics.getWidth() / cameraScale), (int) (Gdx.graphics.getHeight() / cameraScale));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(){
|
||||
DrawContext.font = Styles.styles.font();
|
||||
|
||||
Entities.initPhysics(0, 0, main.pixsize, main.pixsize);
|
||||
|
||||
Effect.addDraw("place", 16, e -> {
|
||||
Draw.thickness(3f - e.ifract() * 2f);
|
||||
Draw.square(e.x, e.y, TileType.tilesize / 2 + e.ifract() * 3f);
|
||||
Draw.clear();
|
||||
});
|
||||
|
||||
Effect.addDraw("spark", 10, e -> {
|
||||
Draw.thickness(1f);
|
||||
Draw.color(Hue.mix(Color.WHITE, Color.GRAY, e.ifract()));
|
||||
Draw.spikes(e.x, e.y, e.ifract() * 5f, 2, 8);
|
||||
Draw.clear();
|
||||
});
|
||||
|
||||
Effect.addDraw("smelt", 10, e -> {
|
||||
Draw.thickness(1f);
|
||||
Draw.color(Hue.mix(Color.YELLOW, Color.RED, e.ifract()));
|
||||
Draw.spikes(e.x, e.y, e.ifract() * 5f, 2, 8);
|
||||
Draw.clear();
|
||||
});
|
||||
|
||||
Effect.addDraw("break", 12, e -> {
|
||||
Draw.thickness(2f);
|
||||
Draw.color(Color.WHITE, Color.GRAY, e.ifract());
|
||||
Draw.spikes(e.x, e.y, e.ifract() * 5f, 2, 5);
|
||||
Draw.clear();
|
||||
});
|
||||
|
||||
Effect.addDraw("hit", 10, e -> {
|
||||
Draw.thickness(1f);
|
||||
Draw.color(Hue.mix(Color.WHITE, Color.ORANGE, e.ifract()));
|
||||
Draw.spikes(e.x, e.y, e.ifract() * 3f, 2, 8);
|
||||
Draw.clear();
|
||||
});
|
||||
|
||||
Effect.addDraw("explosion", 15, e -> {
|
||||
Draw.thickness(2f);
|
||||
Draw.color(Hue.mix(Color.ORANGE, Color.GRAY, e.ifract()));
|
||||
Draw.spikes(e.x, e.y, 2f + e.ifract() * 3f, 4, 6);
|
||||
Draw.circle(e.x, e.y, 3f + e.ifract() * 3f);
|
||||
Draw.clear();
|
||||
});
|
||||
|
||||
Effect.addDraw("ind", 100, e -> {
|
||||
Draw.thickness(3f);
|
||||
Draw.color("royal");
|
||||
Draw.circle(e.x, e.y, 3);
|
||||
Draw.clear();
|
||||
});
|
||||
|
||||
Pathfind.updatePath();
|
||||
}
|
||||
|
||||
public void tryMove(SolidEntity e, float x, float y){
|
||||
e.getBoundingBox(Rectangle.tmp);
|
||||
Rectangle.tmp.setSize(Rectangle.tmp.width * 0.5f);
|
||||
|
||||
if(!overlaps(Rectangle.tmp, e.x + x, e.y)){
|
||||
e.x += x;
|
||||
}
|
||||
|
||||
if(!overlaps(Rectangle.tmp, e.x, e.y + y)){
|
||||
e.y += y;
|
||||
}
|
||||
}
|
||||
|
||||
boolean overlaps(Rectangle rect, float x, float y){
|
||||
int r = 1;
|
||||
rect.setCenter(x, y);
|
||||
int tilex = Mathf.scl2(x, tilesize);
|
||||
int tiley = Mathf.scl2(y, tilesize);
|
||||
|
||||
for(int dx = -r; dx <= r; dx++){
|
||||
for(int dy = -r; dy <= r; dy++){
|
||||
Tile tile = main.tile(tilex + dx, tiley + dy);
|
||||
if(tile != null && tile.block().solid && Rectangle.tmp2.setSize(tilesize).setCenter(tile.worldx(), tile.worldy()).overlaps(rect)){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Rectangle getRect(int x, int y){
|
||||
return Rectangle.tmp2.setSize(tilesize).setCenter(x * tilesize, y * tilesize);
|
||||
}
|
||||
|
||||
void input(){
|
||||
|
||||
if(UInput.keyUp("rotate"))
|
||||
main.rotation++;
|
||||
|
||||
main.rotation %= 4;
|
||||
|
||||
if(main.recipe != null && !main.hasItems(main.recipe.requirements)){
|
||||
main.recipe = null;
|
||||
Cursors.restoreCursor();
|
||||
}
|
||||
|
||||
if(UInput.keyUp(Keys.G))
|
||||
new Enemy(0).set(main.player.x, main.player.y).add();
|
||||
|
||||
if(UInput.buttonUp(Buttons.LEFT) && main.recipe != null && validPlace(tilex(), tiley(), main.recipe.result) && !get(UI.class).hasMouse()){
|
||||
Tile tile = main.tile(tilex(), tiley());
|
||||
if(tile == null)
|
||||
return; //just in ase
|
||||
|
||||
tile.setBlock(main.recipe.result);
|
||||
tile.rotation = main.rotation;
|
||||
|
||||
Pathfind.updatePath();
|
||||
|
||||
Effects.effect("place", roundx(), roundy());
|
||||
Effects.shake(2f, 2f);
|
||||
|
||||
for(ItemStack stack : main.recipe.requirements){
|
||||
main.removeItem(stack);
|
||||
}
|
||||
|
||||
if(!main.hasItems(main.recipe.requirements)){
|
||||
main.recipe = null;
|
||||
Cursors.restoreCursor();
|
||||
}
|
||||
}
|
||||
|
||||
if(main.recipe != null && UInput.buttonUp(Buttons.RIGHT)){
|
||||
main.recipe = null;
|
||||
Cursors.restoreCursor();
|
||||
}
|
||||
|
||||
//block breaking
|
||||
if(UInput.buttonDown(Buttons.RIGHT) && cursorNear() && main.tile(tilex(), tiley()).artifical()
|
||||
&& main.tile(tilex(), tiley()).block() != TileType.core){
|
||||
Tile tile = main.tile(tilex(), tiley());
|
||||
breaktime += delta();
|
||||
if(breaktime >= breakdur){
|
||||
Effects.effect("break", tile.entity);
|
||||
Effects.shake(3f, 1f);
|
||||
tile.setBlock(TileType.air);
|
||||
Pathfind.updatePath();
|
||||
breaktime = 0f;
|
||||
}
|
||||
}else{
|
||||
breaktime = 0f;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
float roundx(){
|
||||
return Mathf.round2(UGraphics.mouseWorldPos().x, TileType.tilesize);
|
||||
}
|
||||
|
||||
float roundy(){
|
||||
return Mathf.round2(UGraphics.mouseWorldPos().y, TileType.tilesize);
|
||||
}
|
||||
|
||||
int tilex(){
|
||||
return Mathf.scl2(UGraphics.mouseWorldPos().x, TileType.tilesize);
|
||||
}
|
||||
|
||||
int tiley(){
|
||||
return Mathf.scl2(UGraphics.mouseWorldPos().y, TileType.tilesize);
|
||||
}
|
||||
|
||||
boolean validPlace(int x, int y, TileType tile){
|
||||
|
||||
if(!cursorNear())
|
||||
return false;
|
||||
|
||||
for(SolidEntity e : Entities.getNearby(x * tilesize, y * tilesize, tilesize * 2f)){
|
||||
Rectangle.tmp.setSize(e.hitsize);
|
||||
Rectangle.tmp.setCenter(e.x, e.y);
|
||||
|
||||
if(getRect(x, y).overlaps(Rectangle.tmp)){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return main.tiles[x][y].block() == TileType.air;
|
||||
}
|
||||
|
||||
boolean cursorNear(){
|
||||
return Vector2.dst(main.player.x, main.player.y, tilex() * tilesize, tiley() * tilesize) <= main.placerange;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(){
|
||||
if(Gdx.input.isKeyJustPressed(Keys.ESCAPE))
|
||||
Gdx.app.exit();
|
||||
|
||||
Entities.update();
|
||||
|
||||
input();
|
||||
camera.position.set(main.player.x, main.player.y, 0f);
|
||||
clampCamera(-tilesize / 2f, -tilesize / 2f, main.pixsize - tilesize / 2f, main.pixsize - tilesize / 2f);
|
||||
|
||||
drawDefault();
|
||||
|
||||
recorder.update();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(){
|
||||
Draw.clear();
|
||||
|
||||
for(int l = 0; l < 4; l++){
|
||||
if(l == 1){
|
||||
batch.end();
|
||||
buffers.end("pixel");
|
||||
|
||||
buffers.begin("shadow");
|
||||
|
||||
batch.begin();
|
||||
Gdx.gl.glClearColor(0, 0, 0, 0);
|
||||
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
|
||||
}
|
||||
for(int x = -rangex; x <= rangex; x++){
|
||||
for(int y = -rangey; y <= rangey; y++){
|
||||
int worldx = Mathf.scl(camera.position.x, tilesize) + x;
|
||||
int worldy = Mathf.scl(camera.position.y, tilesize) + y;
|
||||
|
||||
if(Mathf.inBounds(worldx, worldy, main.tiles)){
|
||||
Tile tile = main.tiles[worldx][worldy];
|
||||
if(l == 1){
|
||||
if(tile.block() != TileType.air)
|
||||
Draw.rect("shadow", worldx * tilesize, worldy * tilesize);
|
||||
}else if(l == 0 || l == 2){
|
||||
(l == 0 ? tile.floor() : tile.block()).draw(tile);
|
||||
}else{
|
||||
tile.block().drawOver(tile);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(l == 1){
|
||||
batch.end();
|
||||
buffers.end("shadow");
|
||||
batch.setColor(0, 0, 0, 0.15f);
|
||||
|
||||
buffers.begin("pixel");
|
||||
|
||||
drawFull("shadow");
|
||||
batch.setColor(Color.WHITE);
|
||||
batch.setProjectionMatrix(camera.combined);
|
||||
|
||||
batch.begin();
|
||||
}
|
||||
}
|
||||
|
||||
Entities.draw();
|
||||
|
||||
if(main.recipe != null && !get(UI.class).hasMouse()){
|
||||
float x = Mathf.round2(UGraphics.mouseWorldPos().x, tilesize);
|
||||
float y = Mathf.round2(UGraphics.mouseWorldPos().y, tilesize);
|
||||
|
||||
boolean valid = validPlace(tilex(), tiley(), main.recipe.result);
|
||||
|
||||
Draw.color(valid ? Color.PURPLE : Color.SCARLET);
|
||||
Draw.thickness(2f);
|
||||
Draw.square(x, y, TileType.tilesize / 2 + MathUtils.sin(Timers.time() / 6f) + 1);
|
||||
|
||||
if(main.recipe.result.rotate){
|
||||
Draw.color("orange");
|
||||
vector.set(7, 0).rotate(main.rotation * 90);
|
||||
Draw.line(x, y, x + vector.x, y + vector.y);
|
||||
}
|
||||
|
||||
if(valid)
|
||||
Cursors.setHand();
|
||||
else
|
||||
Cursors.restoreCursor();
|
||||
}
|
||||
|
||||
//block breaking
|
||||
if(UInput.buttonDown(Buttons.RIGHT) && cursorNear()){
|
||||
Tile tile = main.tile(tilex(), tiley());
|
||||
if(tile.artifical() && tile.block() != TileType.core){
|
||||
Draw.color(Color.YELLOW, Color.SCARLET, breaktime / breakdur);
|
||||
Draw.square(tile.worldx(), tile.worldy(), 4);
|
||||
Draw.clear();
|
||||
}
|
||||
}
|
||||
|
||||
if(main.recipe == null && !get(UI.class).hasMouse()){
|
||||
Tile tile = main.tiles[tilex()][tiley()];
|
||||
|
||||
if(tile.block() != TileType.air){
|
||||
if(tile.block().name().contains("turret")){
|
||||
Draw.color("green");
|
||||
Draw.dashcircle(tile.worldx(), tile.worldy(), tile.block().range);
|
||||
Draw.clear();
|
||||
}
|
||||
if(tile.entity != null)
|
||||
drawHealth(tile.entity);
|
||||
}
|
||||
}
|
||||
|
||||
for(Entity entity : Entities.all()){
|
||||
if(entity instanceof DestructibleEntity && !(entity instanceof TileEntity)){
|
||||
DestructibleEntity dest = ((DestructibleEntity) entity);
|
||||
|
||||
drawHealth(dest);
|
||||
}
|
||||
}
|
||||
|
||||
//Draw.text(Gdx.graphics.getFramesPerSecond() + " FPS", main.player.x, main.player.y);
|
||||
}
|
||||
|
||||
void drawHealth(DestructibleEntity dest){
|
||||
float len = 3;
|
||||
float offset = 7;
|
||||
Draw.thickness(3f);
|
||||
Draw.color(Color.GRAY);
|
||||
Draw.line(dest.x - len + 1, dest.y - offset, dest.x + len + 1, dest.y - offset);
|
||||
Draw.thickness(1f);
|
||||
Draw.color(Color.BLACK);
|
||||
Draw.line(dest.x - len + 1, dest.y - offset, dest.x + len, dest.y - offset);
|
||||
Draw.color(Color.RED);
|
||||
Draw.line(dest.x - len + 1, dest.y - offset, dest.x - len + len * 2 * ((float) dest.health / dest.maxhealth), dest.y - offset);
|
||||
Draw.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resize(int width, int height){
|
||||
super.resize(width, height);
|
||||
|
||||
buffers.remove("shadow");
|
||||
buffers.add("shadow", (int) (Gdx.graphics.getWidth() / cameraScale), (int) (Gdx.graphics.getHeight() / cameraScale));
|
||||
|
||||
rangex = (int) (width / tilesize / cameraScale);
|
||||
rangey = (int) (height / tilesize / cameraScale);
|
||||
}
|
||||
}
|
||||
169
core/src/io/anuke/moment/Moment.java
Normal file
169
core/src/io/anuke/moment/Moment.java
Normal file
@@ -0,0 +1,169 @@
|
||||
package io.anuke.moment;
|
||||
|
||||
import com.badlogic.gdx.Input.Keys;
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
import com.badlogic.gdx.utils.ObjectMap;
|
||||
|
||||
import io.anuke.aabb.Collider;
|
||||
import io.anuke.moment.entities.Enemy;
|
||||
import io.anuke.moment.entities.Player;
|
||||
import io.anuke.moment.resource.Item;
|
||||
import io.anuke.moment.resource.ItemStack;
|
||||
import io.anuke.moment.resource.Recipe;
|
||||
import io.anuke.moment.world.Generator;
|
||||
import io.anuke.moment.world.Tile;
|
||||
import io.anuke.moment.world.TileType;
|
||||
import io.anuke.ucore.core.KeyBinds;
|
||||
import io.anuke.ucore.core.Settings;
|
||||
import io.anuke.ucore.core.UInput;
|
||||
import io.anuke.ucore.modules.ModuleController;
|
||||
import io.anuke.ucore.util.Mathf;
|
||||
import io.anuke.ucore.util.Timers;
|
||||
|
||||
public class Moment extends ModuleController<Moment>{
|
||||
public static Moment i;
|
||||
public Player player;
|
||||
public int size = 128;
|
||||
public int pixsize = size*TileType.tilesize;
|
||||
public Tile[][] tiles = new Tile[size][size];
|
||||
public ObjectMap<Item, Integer> items = new ObjectMap<>();
|
||||
public Recipe recipe;
|
||||
public int rotation;
|
||||
public float placerange = 60;
|
||||
|
||||
public int wave = 1;
|
||||
public float wavespace = 2000/100;
|
||||
public float wavetime = wavespace;
|
||||
public Tile core;
|
||||
public Array<Tile> spawnpoints = new Array<Tile>();
|
||||
|
||||
@Override
|
||||
public void init(){
|
||||
i = this;
|
||||
|
||||
addModule(new Control());
|
||||
addModule(new UI());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setup(){
|
||||
KeyBinds.defaults(
|
||||
"up", Keys.W,
|
||||
"left", Keys.A,
|
||||
"down", Keys.S,
|
||||
"right", Keys.D,
|
||||
"rotate", Keys.R
|
||||
);
|
||||
|
||||
Settings.loadAll("io.anuke.moment");
|
||||
|
||||
for(int x = 0; x < size; x ++){
|
||||
for(int y = 0; y < size; y ++){
|
||||
tiles[x][y] = new Tile(x, y, TileType.grass);
|
||||
}
|
||||
}
|
||||
|
||||
generate();
|
||||
|
||||
items.put(Item.stone, 200);
|
||||
items.put(Item.iron, 200);
|
||||
|
||||
Collider.defaultDrag = 0.2f;
|
||||
|
||||
player = new Player().add();
|
||||
|
||||
player.x = core.worldx();
|
||||
player.y = core.worldy()+10;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(){
|
||||
super.update();
|
||||
|
||||
if(Enemy.amount == 0)
|
||||
wavetime -= delta();
|
||||
|
||||
if(wavetime < 0 || UInput.keyUp(Keys.F)){
|
||||
runWave();
|
||||
}
|
||||
}
|
||||
|
||||
public void coreDestroyed(){
|
||||
//TODO "you lose" message or something
|
||||
}
|
||||
|
||||
void generate(){
|
||||
Generator.generate(tiles, "map");
|
||||
core.setBlock(TileType.core);
|
||||
int x = core.x, y = core.y;
|
||||
|
||||
set(x, y-1, TileType.conveyor, 1);
|
||||
set(x, y-2, TileType.router, 0);
|
||||
set(x, y-3, TileType.conveyor, 1);
|
||||
set(x, y-4, TileType.stonedrill, 0);
|
||||
//just in case
|
||||
tiles[x][y-4].setFloor(TileType.stone);
|
||||
|
||||
set(x+1, y-2, TileType.conveyor, 0);
|
||||
set(x+2, y-2, TileType.conveyor, 1);
|
||||
set(x+2, y-1, TileType.conveyor, 1);
|
||||
set(x+2, y, TileType.turret, 0);
|
||||
|
||||
set(x-1, y-2, TileType.conveyor, 2);
|
||||
set(x-2, y-2, TileType.conveyor, 1);
|
||||
set(x-2, y-1, TileType.conveyor, 1);
|
||||
set(x-2, y, TileType.turret, 0);
|
||||
}
|
||||
|
||||
void set(int x, int y, TileType type, int rot){
|
||||
tiles[x][y].setBlock(type);
|
||||
tiles[x][y].rotation = rot;
|
||||
}
|
||||
|
||||
public void runWave(){
|
||||
int amount = 3*wave;
|
||||
|
||||
for(int i = 0; i < amount; i ++){
|
||||
int point = i%spawnpoints.size;
|
||||
Tile tile = spawnpoints.get(point);
|
||||
|
||||
Timers.run((int)(i/spawnpoints.size)*40f, ()->{
|
||||
new Enemy(point).set(tile.worldx(), tile.worldy()).add();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
wave ++;
|
||||
wavetime = wavespace;
|
||||
}
|
||||
|
||||
public Tile tile(int x, int y){
|
||||
if(!Mathf.inBounds(x, y, tiles)) return null;
|
||||
return tiles[x][y];
|
||||
}
|
||||
|
||||
public Tile spawn(){
|
||||
return tiles[size/2][size-1];
|
||||
}
|
||||
|
||||
public void addItem(Item item, int amount){
|
||||
items.put(item, items.get(item, 0)+amount);
|
||||
get(UI.class).updateItems();
|
||||
}
|
||||
|
||||
public boolean hasItems(ItemStack[] items){
|
||||
for(ItemStack stack : items)
|
||||
if(!hasItem(stack))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean hasItem(ItemStack req){
|
||||
return items.get(req.item, 0) >= req.amount;
|
||||
}
|
||||
|
||||
public void removeItem(ItemStack req){
|
||||
items.put(req.item, items.get(req.item, 0)-req.amount);
|
||||
get(UI.class).updateItems();
|
||||
}
|
||||
}
|
||||
194
core/src/io/anuke/moment/UI.java
Normal file
194
core/src/io/anuke/moment/UI.java
Normal file
@@ -0,0 +1,194 @@
|
||||
package io.anuke.moment;
|
||||
|
||||
import static io.anuke.moment.world.TileType.tilesize;
|
||||
|
||||
import com.badlogic.gdx.graphics.Color;
|
||||
import com.badlogic.gdx.utils.Align;
|
||||
|
||||
import io.anuke.moment.entities.Enemy;
|
||||
import io.anuke.moment.resource.Item;
|
||||
import io.anuke.moment.resource.ItemStack;
|
||||
import io.anuke.moment.resource.Recipe;
|
||||
import io.anuke.moment.world.Tile;
|
||||
import io.anuke.moment.world.TileType;
|
||||
import io.anuke.ucore.core.Draw;
|
||||
import io.anuke.ucore.core.UGraphics;
|
||||
import io.anuke.ucore.modules.SceneModule;
|
||||
import io.anuke.ucore.scene.builders.*;
|
||||
import io.anuke.ucore.scene.style.Styles;
|
||||
import io.anuke.ucore.scene.ui.*;
|
||||
import io.anuke.ucore.scene.ui.layout.Table;
|
||||
import io.anuke.ucore.util.Mathf;
|
||||
|
||||
public class UI extends SceneModule<Moment>{
|
||||
Table itemtable;
|
||||
|
||||
public UI(){
|
||||
Styles.styles.font().setUseIntegerPositions(false);
|
||||
TooltipManager.getInstance().animations = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(){
|
||||
scene.getBatch().setProjectionMatrix(get(Control.class).camera.combined);
|
||||
scene.getBatch().begin();
|
||||
Tile tile = main.tiles[tilex()][tiley()];
|
||||
if(tile.block() != TileType.air){
|
||||
String error = tile.block().error(tile);
|
||||
if(error != null){
|
||||
Draw.tcolor(Color.SCARLET);
|
||||
Draw.tscl(1/8f);
|
||||
Draw.text(error, tile.worldx(), tile.worldy()+tilesize);
|
||||
|
||||
}else if(tile.block().name().contains("turret")){
|
||||
Draw.tscl(1/8f);
|
||||
Draw.tcolor(Color.GREEN);
|
||||
Draw.text("Ammo: " + tile.entity.shots, tile.worldx(), tile.worldy()-tilesize);
|
||||
}
|
||||
|
||||
Draw.tscl(0.5f);
|
||||
Draw.clear();
|
||||
}
|
||||
scene.getBatch().end();
|
||||
|
||||
super.update();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(){
|
||||
|
||||
build.begin(scene);
|
||||
|
||||
new table(){{
|
||||
abottom();
|
||||
aright();
|
||||
|
||||
new table(){{
|
||||
|
||||
get().background("button");
|
||||
|
||||
for(Recipe r : Recipe.values()){
|
||||
Image image = new Image(Draw.region(r.result.name()));
|
||||
|
||||
new button(r.result.name(), ()->{
|
||||
main.recipe = r;
|
||||
}){{
|
||||
get().clearChildren();
|
||||
get().pad(10f);
|
||||
get().add(image).size(42).padRight(4f);
|
||||
Table table = new Table();
|
||||
table.add(get().getLabel()).left();
|
||||
get().add(table);
|
||||
get().left();
|
||||
|
||||
ItemStack[] req = r.requirements;
|
||||
for(ItemStack stack : req){
|
||||
table.row();
|
||||
table.add("[YELLOW]"+stack.amount +"x " +stack.item.name()).left();
|
||||
}
|
||||
get().getLabel().setAlignment(Align.left);
|
||||
|
||||
String description = r.result.description();
|
||||
if(r.result.ammo != null){
|
||||
description += "\n[SALMON]Ammo: " + r.result.ammo.name();
|
||||
}
|
||||
|
||||
Table tiptable = new Table();
|
||||
tiptable.background("button");
|
||||
tiptable.add("[PURPLE]"+r.result.name(), 0.5f).left().padBottom(2f);
|
||||
tiptable.row();
|
||||
tiptable.add("[ORANGE]"+description).left();
|
||||
tiptable.pad(8f);
|
||||
|
||||
Tooltip tip = new Tooltip(tiptable);
|
||||
tip.setInstant(true);
|
||||
|
||||
get().addListener(tip);
|
||||
|
||||
Recipe current = r;
|
||||
get().update(()->{
|
||||
get().setDisabled(!main.hasItems(current.requirements));
|
||||
//get().setTouchable(!main.hasItems(current.requirements) ? Touchable.disabled : Touchable.enabled);
|
||||
});
|
||||
|
||||
}}.width(220f);
|
||||
|
||||
row();
|
||||
}
|
||||
|
||||
get().pad(20f);
|
||||
|
||||
}}.right().bottom();
|
||||
|
||||
}}.end();
|
||||
|
||||
new table(){{
|
||||
atop();
|
||||
aleft();
|
||||
itemtable = new table().top().left().get();
|
||||
itemtable.background("button");
|
||||
}}.end();
|
||||
|
||||
//wave table...
|
||||
new table(){{
|
||||
atop();
|
||||
aright();
|
||||
|
||||
new table(){{
|
||||
get().background("button");
|
||||
|
||||
new label("Wave 1"){{
|
||||
get().setFontScale(1f);
|
||||
get().update(()->{
|
||||
get().setText("[YELLOW]Wave " + Moment.i.wave);
|
||||
});
|
||||
}}.left();
|
||||
|
||||
row();
|
||||
|
||||
new label("Time"){{
|
||||
get().update(()->{
|
||||
get().setText(Enemy.amount > 0 ?
|
||||
Enemy.amount+" Enemies remaining" : "New wave in " + (int)(main.wavetime/60f));
|
||||
});
|
||||
}}.minWidth(150);
|
||||
|
||||
get().pad(8);
|
||||
}};
|
||||
}}.end();
|
||||
|
||||
|
||||
updateItems();
|
||||
|
||||
build.end();
|
||||
}
|
||||
|
||||
public void updateItems(){
|
||||
itemtable.clear();
|
||||
|
||||
for(Item stack : main.items.keys()){
|
||||
Image image = new Image(Draw.region("icon-" + stack.name()));
|
||||
Label label = new Label(""+ main.items.get(stack));
|
||||
label.setFontScale(1f);
|
||||
itemtable.add(image).size(32);
|
||||
itemtable.add(label);
|
||||
itemtable.row();
|
||||
}
|
||||
}
|
||||
|
||||
float roundx(){
|
||||
return Mathf.round2(UGraphics.mouseWorldPos().x, TileType.tilesize);
|
||||
}
|
||||
|
||||
float roundy(){
|
||||
return Mathf.round2(UGraphics.mouseWorldPos().y, TileType.tilesize);
|
||||
}
|
||||
|
||||
int tilex(){
|
||||
return Mathf.scl2(UGraphics.mouseWorldPos().x, TileType.tilesize);
|
||||
}
|
||||
|
||||
int tiley(){
|
||||
return Mathf.scl2(UGraphics.mouseWorldPos().y, TileType.tilesize);
|
||||
}
|
||||
}
|
||||
22
core/src/io/anuke/moment/ai/MHueristic.java
Normal file
22
core/src/io/anuke/moment/ai/MHueristic.java
Normal file
@@ -0,0 +1,22 @@
|
||||
package io.anuke.moment.ai;
|
||||
|
||||
import com.badlogic.gdx.ai.pfa.Heuristic;
|
||||
|
||||
import io.anuke.moment.world.Tile;
|
||||
import io.anuke.moment.world.TileType;
|
||||
|
||||
public class MHueristic implements Heuristic<Tile>{
|
||||
//so this means that the cost of going through solids is 10x going through non solids
|
||||
float multiplier = 10f;
|
||||
|
||||
@Override
|
||||
public float estimate(Tile node, Tile other){
|
||||
float cost = Math.abs(node.worldx() - other.worldx()) + Math.abs(node.worldy() - other.worldy());
|
||||
|
||||
//TODO balance multiplier
|
||||
if(node.artifical() && node.block().solid) cost += TileType.tilesize*multiplier;
|
||||
if(other.artifical() && other.block().solid) cost += TileType.tilesize*multiplier;
|
||||
return cost;
|
||||
}
|
||||
|
||||
}
|
||||
38
core/src/io/anuke/moment/ai/PassTileGraph.java
Normal file
38
core/src/io/anuke/moment/ai/PassTileGraph.java
Normal file
@@ -0,0 +1,38 @@
|
||||
package io.anuke.moment.ai;
|
||||
|
||||
import com.badlogic.gdx.ai.pfa.Connection;
|
||||
import com.badlogic.gdx.ai.pfa.indexed.IndexedGraph;
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
|
||||
import io.anuke.moment.Moment;
|
||||
import io.anuke.moment.world.Tile;
|
||||
|
||||
/**Tilegraph that ignores player-made tiles.*/
|
||||
public class PassTileGraph implements IndexedGraph<Tile>{
|
||||
private Array<Connection<Tile>> tempConnections = new Array<Connection<Tile>>();
|
||||
|
||||
@Override
|
||||
public Array<Connection<Tile>> getConnections(Tile fromNode){
|
||||
tempConnections.clear();
|
||||
|
||||
if(fromNode.block().solid && !fromNode.block().update)
|
||||
return tempConnections;
|
||||
|
||||
for(Tile tile : fromNode.getNearby()){
|
||||
if(tile != null && (!tile.block().solid || tile.block().update))
|
||||
tempConnections.add(new TileConnection(fromNode, tile));
|
||||
}
|
||||
|
||||
return tempConnections;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIndex(Tile node){
|
||||
return node.x+node.y*Moment.i.size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNodeCount(){
|
||||
return Moment.i.size*Moment.i.size;
|
||||
}
|
||||
}
|
||||
96
core/src/io/anuke/moment/ai/Pathfind.java
Normal file
96
core/src/io/anuke/moment/ai/Pathfind.java
Normal file
@@ -0,0 +1,96 @@
|
||||
package io.anuke.moment.ai;
|
||||
|
||||
import com.badlogic.gdx.ai.pfa.DefaultGraphPath;
|
||||
import com.badlogic.gdx.ai.pfa.indexed.IndexedAStarPathFinder;
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
|
||||
import io.anuke.moment.Moment;
|
||||
import io.anuke.moment.entities.Enemy;
|
||||
import io.anuke.moment.world.Tile;
|
||||
import io.anuke.ucore.entities.Entities;
|
||||
import io.anuke.ucore.entities.Entity;
|
||||
|
||||
public class Pathfind{
|
||||
static MHueristic heuristic = new MHueristic();
|
||||
static TileGraph graph = new TileGraph();
|
||||
static PassTileGraph passgraph = new PassTileGraph();
|
||||
static IndexedAStarPathFinder<Tile> pathfinder = new IndexedAStarPathFinder<Tile>(graph);
|
||||
static IndexedAStarPathFinder<Tile> passpathfinder = new IndexedAStarPathFinder<Tile>(passgraph);
|
||||
static Array<DefaultGraphPath<Tile>> paths = new Array<>();
|
||||
static Vector2 vector = new Vector2();
|
||||
|
||||
static public Vector2 find(Enemy enemy){
|
||||
if(enemy.node == -1){
|
||||
findNode(enemy);
|
||||
}
|
||||
|
||||
//-1 is only possible here if both pathfindings failed, which should NOT happen
|
||||
//check graph code
|
||||
|
||||
DefaultGraphPath<Tile> path = paths.get(enemy.spawn);
|
||||
|
||||
Tile target = path.get(enemy.node);
|
||||
|
||||
float dst = Vector2.dst(enemy.x, enemy.y, target.worldx(), target.worldy());
|
||||
|
||||
if(dst < 2){
|
||||
if(enemy.node <= path.getCount()-2)
|
||||
enemy.node ++;
|
||||
|
||||
target = path.get(enemy.node);
|
||||
}
|
||||
|
||||
|
||||
return vector.set(target.worldx(), target.worldy());
|
||||
|
||||
}
|
||||
|
||||
static public void updatePath(){
|
||||
if(paths.size == 0){
|
||||
for(int i = 0; i < Moment.i.spawnpoints.size; i ++){
|
||||
DefaultGraphPath<Tile> path = new DefaultGraphPath<>();
|
||||
paths.add(path);
|
||||
}
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
for(DefaultGraphPath<Tile> path : paths){
|
||||
path.clear();
|
||||
passpathfinder.searchNodePath(
|
||||
Moment.i.spawnpoints.get(i),
|
||||
Moment.i.core, heuristic, path);
|
||||
|
||||
//for(Tile tile : path){
|
||||
// Effects.effect("ind", tile.worldx(), tile.worldy());
|
||||
///}
|
||||
i++;
|
||||
}
|
||||
|
||||
for(Entity e : Entities.all()){
|
||||
if(e instanceof Enemy){
|
||||
findNode((Enemy)e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void findNode(Enemy enemy){
|
||||
DefaultGraphPath<Tile> path = paths.get(enemy.spawn);
|
||||
|
||||
Tile closest = null;
|
||||
float ldst = 0f;
|
||||
int cindex = -1;
|
||||
|
||||
for(int i = 0; i < path.getCount(); i ++){
|
||||
Tile tile = path.get(i);
|
||||
float dst = Vector2.dst(tile.worldx(), tile.worldy(), enemy.x, enemy.y);
|
||||
|
||||
if(closest == null || dst < ldst){
|
||||
ldst = dst;
|
||||
closest = tile;
|
||||
cindex = i;
|
||||
}
|
||||
}
|
||||
enemy.node = cindex;
|
||||
}
|
||||
}
|
||||
30
core/src/io/anuke/moment/ai/TileConnection.java
Normal file
30
core/src/io/anuke/moment/ai/TileConnection.java
Normal file
@@ -0,0 +1,30 @@
|
||||
package io.anuke.moment.ai;
|
||||
|
||||
import com.badlogic.gdx.ai.pfa.Connection;
|
||||
|
||||
import io.anuke.moment.world.Tile;
|
||||
|
||||
public class TileConnection implements Connection{
|
||||
Tile a, b;
|
||||
|
||||
public TileConnection(Tile a, Tile b){
|
||||
this.a = a;
|
||||
this.b = b;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getCost(){
|
||||
return Math.abs(a.worldx() - b.worldx()) + Math.abs(a.worldy() - b.worldy());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getFromNode(){
|
||||
return a;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getToNode(){
|
||||
return b;
|
||||
}
|
||||
|
||||
}
|
||||
36
core/src/io/anuke/moment/ai/TileGraph.java
Normal file
36
core/src/io/anuke/moment/ai/TileGraph.java
Normal file
@@ -0,0 +1,36 @@
|
||||
package io.anuke.moment.ai;
|
||||
|
||||
import com.badlogic.gdx.ai.pfa.Connection;
|
||||
import com.badlogic.gdx.ai.pfa.indexed.IndexedGraph;
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
|
||||
import io.anuke.moment.Moment;
|
||||
import io.anuke.moment.world.Tile;
|
||||
|
||||
public class TileGraph implements IndexedGraph<Tile>{
|
||||
private Array<Connection<Tile>> tempConnections = new Array<Connection<Tile>>();
|
||||
|
||||
@Override
|
||||
public Array<Connection<Tile>> getConnections(Tile fromNode){
|
||||
tempConnections.clear();
|
||||
|
||||
if(fromNode.block().solid && fromNode != Moment.i.core)
|
||||
return tempConnections;
|
||||
|
||||
for(Tile tile : fromNode.getNearby()){
|
||||
if(tile != null && (!tile.block().solid || tile == Moment.i.core))
|
||||
tempConnections.add(new TileConnection(fromNode, tile));
|
||||
}
|
||||
return tempConnections;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIndex(Tile node){
|
||||
return node.x+node.y*Moment.i.size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNodeCount(){
|
||||
return Moment.i.size*Moment.i.size;
|
||||
}
|
||||
}
|
||||
32
core/src/io/anuke/moment/entities/Bullet.java
Normal file
32
core/src/io/anuke/moment/entities/Bullet.java
Normal file
@@ -0,0 +1,32 @@
|
||||
package io.anuke.moment.entities;
|
||||
|
||||
import io.anuke.ucore.entities.BulletEntity;
|
||||
import io.anuke.ucore.entities.Entity;
|
||||
import io.anuke.ucore.entities.SolidEntity;
|
||||
|
||||
public class Bullet extends BulletEntity{
|
||||
BulletType type;
|
||||
|
||||
public Bullet(BulletType type, Entity owner, float x, float y, float angle){
|
||||
super(owner, type.speed, angle);
|
||||
set(x, y);
|
||||
this.lifetime = type.lifetime;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public void draw(){
|
||||
type.draw(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void collision(SolidEntity other){
|
||||
super.collision(other);
|
||||
type.collide(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDamage(){
|
||||
return type.damage;
|
||||
}
|
||||
|
||||
}
|
||||
51
core/src/io/anuke/moment/entities/BulletType.java
Normal file
51
core/src/io/anuke/moment/entities/BulletType.java
Normal file
@@ -0,0 +1,51 @@
|
||||
package io.anuke.moment.entities;
|
||||
|
||||
import com.badlogic.gdx.graphics.Color;
|
||||
|
||||
import io.anuke.ucore.core.Draw;
|
||||
import io.anuke.ucore.entities.Effects;
|
||||
|
||||
public enum BulletType{
|
||||
stone(1.5f, 2){
|
||||
public void draw(Bullet b){
|
||||
Draw.color("gray");
|
||||
Draw.square(b.x, b.y, 1f);
|
||||
Draw.clear();
|
||||
}
|
||||
},
|
||||
iron(1.7f, 2){
|
||||
public void draw(Bullet b){
|
||||
Draw.color("gray");
|
||||
Draw.rect("bullet", b.x, b.y, b.angle());
|
||||
Draw.clear();
|
||||
}
|
||||
},
|
||||
small(1.5f, 1){
|
||||
public void draw(Bullet b){
|
||||
Draw.color("orange");
|
||||
Draw.rect("bullet", b.x, b.y, b.angle());
|
||||
Draw.clear();
|
||||
}
|
||||
},
|
||||
shot(2.4f, 2){
|
||||
{lifetime=40;}
|
||||
public void draw(Bullet b){
|
||||
Draw.color(Color.GOLD);
|
||||
Draw.rect("bullet", b.x, b.y, b.angle());
|
||||
Draw.clear();
|
||||
}
|
||||
};;
|
||||
public float speed;
|
||||
public int damage;
|
||||
public float lifetime = 60;
|
||||
|
||||
private BulletType(float speed, int damage){
|
||||
this.speed = speed;
|
||||
this.damage = damage;
|
||||
}
|
||||
|
||||
public void collide(Bullet b){
|
||||
Effects.effect("hit", b);
|
||||
}
|
||||
public void draw(Bullet b){}
|
||||
}
|
||||
89
core/src/io/anuke/moment/entities/Enemy.java
Normal file
89
core/src/io/anuke/moment/entities/Enemy.java
Normal file
@@ -0,0 +1,89 @@
|
||||
package io.anuke.moment.entities;
|
||||
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
|
||||
import io.anuke.moment.Control;
|
||||
import io.anuke.moment.Moment;
|
||||
import io.anuke.moment.ai.Pathfind;
|
||||
import io.anuke.ucore.core.Draw;
|
||||
import io.anuke.ucore.entities.*;
|
||||
import io.anuke.ucore.util.Timers;
|
||||
|
||||
public class Enemy extends DestructibleEntity{
|
||||
public static int amount = 0;
|
||||
|
||||
public Vector2 direction = new Vector2();
|
||||
public float xvelocity, yvelocity;
|
||||
public float speed = 0.3f;
|
||||
public int node = -1;
|
||||
public Entity target;
|
||||
public int spawn;
|
||||
public float reload = 40;
|
||||
|
||||
public Enemy(int spawn){
|
||||
this.spawn = spawn;
|
||||
|
||||
hitsize = 5;
|
||||
|
||||
maxhealth = 30;
|
||||
heal();
|
||||
|
||||
amount ++;
|
||||
}
|
||||
|
||||
void move(){
|
||||
Vector2 vec = Pathfind.find(this);
|
||||
vec.sub(x, y).setLength(speed);
|
||||
|
||||
Moment.module(Control.class).tryMove(this, vec.x*delta, vec.y*delta);
|
||||
|
||||
target = Entities.getClosest(x, y, 60, e->{
|
||||
return (e instanceof TileEntity || e instanceof Player);
|
||||
});
|
||||
|
||||
if(target != null){
|
||||
if(Timers.get(this, reload))
|
||||
new Bullet(BulletType.small, this, x, y, direction.angle()).add();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean collides(SolidEntity other){
|
||||
return (other instanceof Bullet) && !(((Bullet)other).owner instanceof Enemy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeath(){
|
||||
Effects.effect("explosion", this);
|
||||
Effects.shake(3f, 4f);
|
||||
remove();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removed(){
|
||||
amount --;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(){
|
||||
float lastx = x, lasty = y;
|
||||
|
||||
move();
|
||||
|
||||
xvelocity = x - lastx;
|
||||
yvelocity = y-lasty;
|
||||
|
||||
if(target == null){
|
||||
direction.add(xvelocity, yvelocity);
|
||||
direction.limit(speed*8);
|
||||
}else{
|
||||
float angle = angleTo(target);
|
||||
direction.lerp(vector.set(0, 1).setAngle(angle), 0.25f);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(){
|
||||
Draw.rect("mech1", x, y, direction.angle()-90);
|
||||
}
|
||||
}
|
||||
74
core/src/io/anuke/moment/entities/Player.java
Normal file
74
core/src/io/anuke/moment/entities/Player.java
Normal file
@@ -0,0 +1,74 @@
|
||||
package io.anuke.moment.entities;
|
||||
|
||||
import com.badlogic.gdx.Input.Buttons;
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
|
||||
import io.anuke.moment.Control;
|
||||
import io.anuke.moment.Moment;
|
||||
import io.anuke.moment.UI;
|
||||
import io.anuke.ucore.core.Draw;
|
||||
import io.anuke.ucore.core.UInput;
|
||||
import io.anuke.ucore.entities.DestructibleEntity;
|
||||
import io.anuke.ucore.util.Angles;
|
||||
|
||||
public class Player extends DestructibleEntity{
|
||||
Vector2 direction = new Vector2();
|
||||
float speed = 2f;
|
||||
float rotation;
|
||||
float reload;
|
||||
Weapon weapon = Weapon.blaster;
|
||||
|
||||
public Player(){
|
||||
hitsize = 5;
|
||||
|
||||
maxhealth = 100;
|
||||
heal();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removed(){
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(){
|
||||
Draw.rect("player", x, y, direction.angle()-90);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(){
|
||||
vector.set(0, 0);
|
||||
|
||||
if(UInput.keyDown("up"))
|
||||
vector.y += speed;
|
||||
if(UInput.keyDown("down"))
|
||||
vector.y -= speed;
|
||||
if(UInput.keyDown("left"))
|
||||
vector.x -= speed;
|
||||
if(UInput.keyDown("right"))
|
||||
vector.x += speed;
|
||||
|
||||
reload -= delta;
|
||||
|
||||
boolean shooting = UInput.buttonDown(Buttons.LEFT) && Moment.i.recipe == null && !Moment.module(UI.class).hasMouse();
|
||||
|
||||
if(shooting && reload <= 0){
|
||||
weapon.shoot(this);
|
||||
reload = weapon.reload;
|
||||
}
|
||||
|
||||
vector.limit(speed);
|
||||
|
||||
//x += vector.x*delta;
|
||||
//y += vector.y*delta;
|
||||
|
||||
Moment.module(Control.class).tryMove(this, vector.x*delta, vector.y*delta);
|
||||
|
||||
if(!shooting){
|
||||
direction.add(vector.scl(delta));
|
||||
direction.limit(speed*6);
|
||||
}else{
|
||||
float angle = Angles.mouseAngle(x, y);
|
||||
direction.lerp(vector.set(0, 1).setAngle(angle), 0.26f);
|
||||
}
|
||||
}
|
||||
}
|
||||
96
core/src/io/anuke/moment/entities/TileEntity.java
Normal file
96
core/src/io/anuke/moment/entities/TileEntity.java
Normal file
@@ -0,0 +1,96 @@
|
||||
package io.anuke.moment.entities;
|
||||
|
||||
import com.badlogic.gdx.utils.DelayedRemovalArray;
|
||||
import com.badlogic.gdx.utils.ObjectMap;
|
||||
|
||||
import io.anuke.moment.Moment;
|
||||
import io.anuke.moment.ai.Pathfind;
|
||||
import io.anuke.moment.resource.Item;
|
||||
import io.anuke.moment.world.Tile;
|
||||
import io.anuke.moment.world.TileType;
|
||||
import io.anuke.ucore.entities.DestructibleEntity;
|
||||
import io.anuke.ucore.entities.Effects;
|
||||
import io.anuke.ucore.entities.SolidEntity;
|
||||
|
||||
public class TileEntity extends DestructibleEntity{
|
||||
public final Tile tile;
|
||||
public DelayedRemovalArray<ItemPos> convey = new DelayedRemovalArray<>();
|
||||
public ObjectMap<Item, Integer> items = new ObjectMap<>();
|
||||
public int shots;
|
||||
public TileEntity link;
|
||||
public float rotation;
|
||||
|
||||
public TileEntity(Tile tile){
|
||||
this.tile = tile;
|
||||
x = tile.worldx();
|
||||
y = tile.worldy();
|
||||
hitsize = TileType.tilesize;
|
||||
|
||||
maxhealth = tile.block().health;
|
||||
heal();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean collides(SolidEntity other){
|
||||
return (other instanceof Bullet) && ((Bullet)other).owner instanceof Enemy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeath(){
|
||||
if(tile.block() == TileType.core){
|
||||
Moment.i.coreDestroyed();
|
||||
}
|
||||
tile.setBlock(TileType.air);
|
||||
Pathfind.updatePath();
|
||||
Effects.shake(4f, 4f);
|
||||
Effects.effect("explosion", this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(){
|
||||
tile.block().update(tile);
|
||||
}
|
||||
|
||||
public int totalItems(){
|
||||
int sum = 0;
|
||||
for(Item item : Item.values()){
|
||||
sum += items.get(item, 0);
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
public boolean hasItem(Item item){
|
||||
return items.get(item, 0) > 0;
|
||||
}
|
||||
|
||||
public void addItem(Item item, int amount){
|
||||
items.put(item, items.get(item, 0) + amount);
|
||||
}
|
||||
|
||||
public void removeItem(Item item, int amount){
|
||||
items.put(item, items.get(item, 0) - amount);
|
||||
}
|
||||
|
||||
public void addConvey(Item item){
|
||||
addConvey(item, 0);
|
||||
}
|
||||
|
||||
public void addConvey(Item item, float pos){
|
||||
ItemPos posa = new ItemPos(item);
|
||||
posa.pos = pos;
|
||||
convey.add(posa);
|
||||
}
|
||||
|
||||
public void removeConvey(ItemPos pos){
|
||||
convey.removeValue(pos, true);
|
||||
}
|
||||
|
||||
static public class ItemPos{
|
||||
public Item item;
|
||||
public float pos;
|
||||
|
||||
public ItemPos(Item item){
|
||||
this.item = item;
|
||||
}
|
||||
}
|
||||
}
|
||||
28
core/src/io/anuke/moment/entities/Weapon.java
Normal file
28
core/src/io/anuke/moment/entities/Weapon.java
Normal file
@@ -0,0 +1,28 @@
|
||||
package io.anuke.moment.entities;
|
||||
|
||||
import io.anuke.ucore.entities.Entity;
|
||||
import io.anuke.ucore.util.Angles;
|
||||
|
||||
public enum Weapon{
|
||||
blaster(15, BulletType.shot){
|
||||
{
|
||||
unlocked = true;
|
||||
}
|
||||
};
|
||||
public float reload;
|
||||
public BulletType type;
|
||||
public boolean unlocked;
|
||||
|
||||
private Weapon(float reload, BulletType type){
|
||||
this.reload = reload;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public void shoot(Player p){
|
||||
bullet(p, p.x, p.y);
|
||||
}
|
||||
|
||||
void bullet(Entity owner, float x, float y){
|
||||
new Bullet(type, owner, x, y, Angles.mouseAngle(owner.x, owner.y)).add();
|
||||
}
|
||||
}
|
||||
5
core/src/io/anuke/moment/resource/Item.java
Normal file
5
core/src/io/anuke/moment/resource/Item.java
Normal file
@@ -0,0 +1,5 @@
|
||||
package io.anuke.moment.resource;
|
||||
|
||||
public enum Item{
|
||||
stone, iron, coal, steel;
|
||||
}
|
||||
12
core/src/io/anuke/moment/resource/ItemStack.java
Normal file
12
core/src/io/anuke/moment/resource/ItemStack.java
Normal file
@@ -0,0 +1,12 @@
|
||||
package io.anuke.moment.resource;
|
||||
|
||||
public class ItemStack{
|
||||
public Item item;
|
||||
public int amount;
|
||||
public float pos;
|
||||
|
||||
public ItemStack(Item item, int amount){
|
||||
this.item = item;
|
||||
this.amount = amount;
|
||||
}
|
||||
}
|
||||
30
core/src/io/anuke/moment/resource/Recipe.java
Normal file
30
core/src/io/anuke/moment/resource/Recipe.java
Normal file
@@ -0,0 +1,30 @@
|
||||
package io.anuke.moment.resource;
|
||||
|
||||
import io.anuke.moment.world.TileType;
|
||||
|
||||
public enum Recipe{
|
||||
stonewall(TileType.stonewall, stack(Item.stone, 4)),
|
||||
ironwall(TileType.ironwall, stack(Item.iron, 4)),
|
||||
drill(TileType.stonedrill, stack(Item.stone, 5)),
|
||||
irondrill(TileType.irondrill, stack(Item.stone, 30)),
|
||||
coaldrill(TileType.coaldrill, stack(Item.stone, 30), stack(Item.iron, 30)),
|
||||
conveyor(TileType.conveyor, stack(Item.stone, 1)),
|
||||
router(TileType.router, stack(Item.stone, 3)),
|
||||
smelter(TileType.smelter, stack(Item.stone, 40), stack(Item.iron, 40)),
|
||||
healturret(TileType.healturret, stack(Item.iron, 20)),
|
||||
turret(TileType.turret, stack(Item.stone, 4)),
|
||||
dturret(TileType.doubleturret, stack(Item.stone, 6)),
|
||||
machineturret(TileType.machineturret, stack(Item.iron, 8), stack(Item.stone, 6));
|
||||
|
||||
public TileType result;
|
||||
public ItemStack[] requirements;
|
||||
|
||||
private Recipe(TileType result, ItemStack... requirements){
|
||||
this.result = result;
|
||||
this.requirements = requirements;
|
||||
}
|
||||
|
||||
private static ItemStack stack(Item item, int amount){
|
||||
return new ItemStack(item, amount);
|
||||
}
|
||||
}
|
||||
52
core/src/io/anuke/moment/world/Generator.java
Normal file
52
core/src/io/anuke/moment/world/Generator.java
Normal file
@@ -0,0 +1,52 @@
|
||||
package io.anuke.moment.world;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.graphics.Color;
|
||||
import com.badlogic.gdx.graphics.Pixmap;
|
||||
import com.badlogic.gdx.math.MathUtils;
|
||||
|
||||
import io.anuke.moment.Moment;
|
||||
import io.anuke.ucore.noise.Noise;
|
||||
|
||||
public class Generator{
|
||||
static final int black = Color.rgba8888(Color.BLACK);
|
||||
static final int white = Color.rgba8888(Color.WHITE);
|
||||
static final int red = Color.rgba8888(Color.RED);
|
||||
static final int blue = Color.rgba8888(Color.BLUE);
|
||||
|
||||
public static void generate(Tile[][] tiles, String mapname){
|
||||
Pixmap pix = new Pixmap(Gdx.files.internal("maps/"+mapname+".png"));
|
||||
Noise.setSeed(MathUtils.random(0, 99999));
|
||||
for(int x = 0; x < tiles.length; x ++){
|
||||
for(int y = 0; y < tiles.length; y ++){
|
||||
TileType floor = TileType.stone;
|
||||
TileType block = TileType.air;
|
||||
|
||||
int color = pix.getPixel(x, pix.getHeight()-1-y);
|
||||
|
||||
if(Noise.nnoise(x, y, 8, 1) > 0.22){
|
||||
floor = TileType.iron;
|
||||
}
|
||||
|
||||
if(Noise.nnoise(x, y, 6, 1) > 0.245){
|
||||
floor = TileType.coal;
|
||||
}
|
||||
|
||||
if(color == white){
|
||||
block = TileType.dirtblock;
|
||||
|
||||
|
||||
}else if(color == blue){
|
||||
Moment.i.core = tiles[x][y];
|
||||
}else if(color == red){
|
||||
Moment.i.spawnpoints.add(tiles[x][y]);
|
||||
}
|
||||
|
||||
tiles[x][y].setBlock(block);
|
||||
tiles[x][y].setFloor(floor);
|
||||
}
|
||||
}
|
||||
|
||||
pix.dispose();
|
||||
}
|
||||
}
|
||||
74
core/src/io/anuke/moment/world/Tile.java
Normal file
74
core/src/io/anuke/moment/world/Tile.java
Normal file
@@ -0,0 +1,74 @@
|
||||
package io.anuke.moment.world;
|
||||
|
||||
import io.anuke.moment.Moment;
|
||||
import io.anuke.moment.entities.TileEntity;
|
||||
|
||||
public class Tile{
|
||||
private static Tile[] tiles = new Tile[4];
|
||||
private TileType floor = TileType.air;
|
||||
private TileType block = TileType.air;
|
||||
public TileEntity entity;
|
||||
public int x, y, rotation;
|
||||
|
||||
public Tile(int x, int y){
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
public Tile(int x, int y, TileType floor){
|
||||
this(x, y);
|
||||
this.floor = floor;
|
||||
}
|
||||
|
||||
public int id(){
|
||||
return x + y * Moment.i.size;
|
||||
}
|
||||
|
||||
public float worldx(){
|
||||
return x * TileType.tilesize;
|
||||
}
|
||||
|
||||
public float worldy(){
|
||||
return y * TileType.tilesize;
|
||||
}
|
||||
|
||||
public TileType floor(){
|
||||
return floor;
|
||||
}
|
||||
|
||||
public TileType block(){
|
||||
return block;
|
||||
}
|
||||
|
||||
public void setBlock(TileType type){
|
||||
this.block = type;
|
||||
changed();
|
||||
}
|
||||
|
||||
public void setFloor(TileType type){
|
||||
this.floor = type;
|
||||
}
|
||||
|
||||
public boolean artifical(){
|
||||
return block.update;
|
||||
}
|
||||
|
||||
public Tile[] getNearby(){
|
||||
tiles[0] = Moment.i.tile(x+1, y);
|
||||
tiles[1] = Moment.i.tile(x, y+1);
|
||||
tiles[2] = Moment.i.tile(x-1, y);
|
||||
tiles[3] = Moment.i.tile(x, y-1);
|
||||
|
||||
return tiles;
|
||||
}
|
||||
|
||||
|
||||
public void changed(){
|
||||
//TODO where do the items go?
|
||||
if(entity != null)
|
||||
entity.remove();
|
||||
|
||||
if(block.update)
|
||||
entity = new TileEntity(this).add();
|
||||
}
|
||||
}
|
||||
571
core/src/io/anuke/moment/world/TileType.java
Normal file
571
core/src/io/anuke/moment/world/TileType.java
Normal file
@@ -0,0 +1,571 @@
|
||||
package io.anuke.moment.world;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.math.MathUtils;
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
|
||||
import io.anuke.moment.Moment;
|
||||
import io.anuke.moment.entities.*;
|
||||
import io.anuke.moment.entities.TileEntity.ItemPos;
|
||||
import io.anuke.moment.resource.Item;
|
||||
import io.anuke.ucore.core.Draw;
|
||||
import io.anuke.ucore.entities.*;
|
||||
import io.anuke.ucore.graphics.Hue;
|
||||
import io.anuke.ucore.util.Angles;
|
||||
import io.anuke.ucore.util.Mathf;
|
||||
import io.anuke.ucore.util.Timers;
|
||||
|
||||
public enum TileType{
|
||||
air{
|
||||
//nothing gets drawn
|
||||
public void draw(Tile tile){
|
||||
}
|
||||
},
|
||||
grass, stone, dirt, iron, coal, dirtblock(true), stoneblock(true), stonewall(true, true){
|
||||
{
|
||||
health = 50;
|
||||
}
|
||||
},
|
||||
ironwall(true, true){
|
||||
{
|
||||
health = 80;
|
||||
}
|
||||
},
|
||||
stonedrill(true, true){
|
||||
public void update(Tile tile){
|
||||
|
||||
if(tile.floor() == TileType.stone && Timers.get(tile, 60 * 6)){
|
||||
offloadNear(tile, Item.stone);
|
||||
Effects.effect("spark", tile.x * tilesize, tile.y * tilesize);
|
||||
}
|
||||
|
||||
if(Timers.get(tile.hashCode() + "dump", 30)){
|
||||
tryDump(tile);
|
||||
}
|
||||
}
|
||||
|
||||
public String description(){
|
||||
return "Mines 1 stone every 6 seconds.";
|
||||
}
|
||||
|
||||
public String error(Tile tile){
|
||||
if(tile.floor() != TileType.stone)
|
||||
return "Not on stone block!";
|
||||
return null;
|
||||
}
|
||||
},
|
||||
irondrill(true, true){
|
||||
public void update(Tile tile){
|
||||
|
||||
if(tile.floor() == TileType.iron && Timers.get(tile, 60 * 6)){
|
||||
offloadNear(tile, Item.iron);
|
||||
Effects.effect("spark", tile.x * tilesize, tile.y * tilesize);
|
||||
}
|
||||
|
||||
if(Timers.get(tile.hashCode() + "dump", 30)){
|
||||
tryDump(tile);
|
||||
}
|
||||
}
|
||||
|
||||
public String description(){
|
||||
return "Mines 1 iron every 6 seconds.";
|
||||
}
|
||||
|
||||
public String error(Tile tile){
|
||||
if(tile.floor() != TileType.iron)
|
||||
return "Not on iron ore block!";
|
||||
return null;
|
||||
}
|
||||
},
|
||||
coaldrill(true, true){
|
||||
public void update(Tile tile){
|
||||
|
||||
if(tile.floor() == TileType.coal && Timers.get(tile, 60 * 6)){
|
||||
offloadNear(tile, Item.coal);
|
||||
Effects.effect("spark", tile.x * tilesize, tile.y * tilesize);
|
||||
}
|
||||
|
||||
if(Timers.get(tile.hashCode() + "dump", 30)){
|
||||
tryDump(tile);
|
||||
}
|
||||
}
|
||||
|
||||
public String description(){
|
||||
return "Mines 1 coal every 6 seconds.";
|
||||
}
|
||||
|
||||
public String error(Tile tile){
|
||||
if(tile.floor() != TileType.coal)
|
||||
return "Not on coal block!";
|
||||
return null;
|
||||
}
|
||||
},
|
||||
conveyor(false, true, true){
|
||||
float speed = 0.02f;
|
||||
|
||||
public void draw(Tile tile){
|
||||
Draw.rect(name() + (Timers.time() % ((20 / 100f) / speed) < (10 / 100f) / speed ? "" : "move"), tile.worldx(), tile.worldy(), tile.rotation * 90);
|
||||
|
||||
vector.set(tilesize, 0).rotate(tile.rotation * 90);
|
||||
vector2.set(-tilesize / 2, 0).rotate(tile.rotation * 90);
|
||||
|
||||
for(ItemPos pos : tile.entity.convey){
|
||||
Draw.rect("icon-" + pos.item.name(), tile.x * tilesize + vector.x * pos.pos + vector2.x, tile.y * tilesize + vector.y * pos.pos + vector2.y, 4, 4);
|
||||
}
|
||||
}
|
||||
|
||||
public void update(Tile tile){
|
||||
tile.entity.convey.begin();
|
||||
|
||||
for(ItemPos pos : tile.entity.convey){
|
||||
pos.pos += speed * Gdx.graphics.getDeltaTime() * 60f;
|
||||
if(pos.pos >= 1f && offloadDir(tile, pos.item)){
|
||||
tile.entity.removeConvey(pos);
|
||||
continue;
|
||||
}
|
||||
pos.pos = Mathf.clamp(pos.pos);
|
||||
}
|
||||
|
||||
tile.entity.convey.end();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accepts(Item item){
|
||||
return true;
|
||||
}
|
||||
|
||||
public String description(){
|
||||
return "Moves Items";
|
||||
}
|
||||
|
||||
@Override
|
||||
void handleItem(Tile tile, Item item, float f){
|
||||
tile.entity.addConvey(item, f);
|
||||
}
|
||||
},
|
||||
steelconveyor(false, true, true){
|
||||
float speed = 0.03f;
|
||||
|
||||
public void draw(Tile tile){
|
||||
Draw.rect(name() + (Timers.time() % ((20 / 100f) / speed) < (10 / 100f) / speed ? "" : "move"), tile.worldx(), tile.worldy(), tile.rotation * 90);
|
||||
|
||||
vector.set(tilesize, 0).rotate(tile.rotation * 90);
|
||||
vector2.set(-tilesize / 2, 0).rotate(tile.rotation * 90);
|
||||
|
||||
for(ItemPos pos : tile.entity.convey){
|
||||
Draw.rect("icon-" + pos.item.name(), tile.x * tilesize + vector.x * pos.pos + vector2.x, tile.y * tilesize + vector.y * pos.pos + vector2.y, 4, 4);
|
||||
}
|
||||
}
|
||||
|
||||
public void update(Tile tile){
|
||||
tile.entity.convey.begin();
|
||||
|
||||
for(ItemPos pos : tile.entity.convey){
|
||||
pos.pos += speed * Gdx.graphics.getDeltaTime() * 60f;
|
||||
if(pos.pos >= 1f && offloadDir(tile, pos.item)){
|
||||
tile.entity.removeConvey(pos);
|
||||
continue;
|
||||
}
|
||||
pos.pos = Mathf.clamp(pos.pos);
|
||||
}
|
||||
|
||||
tile.entity.convey.end();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accepts(Item item){
|
||||
return true;
|
||||
}
|
||||
|
||||
public String description(){
|
||||
return "Moves Items (faster than a normal conveyor!)";
|
||||
}
|
||||
|
||||
@Override
|
||||
void handleItem(Tile tile, Item item, float f){
|
||||
tile.entity.addConvey(item, f);
|
||||
}
|
||||
},
|
||||
router(true, true, false){
|
||||
|
||||
public void update(Tile tile){
|
||||
if(Timers.get(tile, 20) && tile.entity.totalItems() > 0){
|
||||
tryDump(tile, tile.rotation++);
|
||||
tile.rotation %= 4;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accepts(Item item){
|
||||
return true;
|
||||
}
|
||||
|
||||
public String description(){
|
||||
return "Splits conveyor belt input";
|
||||
}
|
||||
},
|
||||
smelter(true, true, false){
|
||||
{health=70;}
|
||||
|
||||
public void update(Tile tile){
|
||||
|
||||
if(tile.entity.hasItem(Item.coal) && tile.entity.hasItem(Item.iron)){
|
||||
tile.entity.removeItem(Item.coal, 1);
|
||||
tile.entity.removeItem(Item.iron, 1);
|
||||
offloadNear(tile, Item.steel);
|
||||
Effects.effect("smelt", tile.entity);
|
||||
}
|
||||
|
||||
if(Timers.get(tile, 20) && tile.entity.hasItem(Item.steel)){
|
||||
tryDump(tile);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accepts(Item item){
|
||||
return item == Item.iron || item == Item.coal;
|
||||
}
|
||||
|
||||
public String description(){
|
||||
return "Smelts iron and coal into steel";
|
||||
}
|
||||
},
|
||||
core(true, true, false){
|
||||
{
|
||||
health = 300;
|
||||
}
|
||||
|
||||
@Override
|
||||
void handleItem(Tile tile, Item item, float f){
|
||||
Moment.i.addItem(item, 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accepts(Item item){
|
||||
return true;
|
||||
}
|
||||
},
|
||||
turret(true, true, false){
|
||||
{
|
||||
range = 40;
|
||||
reload = 10f;
|
||||
bullet = BulletType.stone;
|
||||
ammo = Item.stone;
|
||||
}
|
||||
|
||||
public void update(Tile tile){
|
||||
updateTurret(tile);
|
||||
}
|
||||
|
||||
public void draw(Tile tile){
|
||||
Draw.rect("block", tile.worldx(), tile.worldy());
|
||||
}
|
||||
|
||||
public void drawOver(Tile tile){
|
||||
Draw.rect(name(), tile.worldx(), tile.worldy(), tile.entity.rotation - 90);
|
||||
}
|
||||
|
||||
public String description(){
|
||||
return "Shoots things.";
|
||||
}
|
||||
},
|
||||
doubleturret(true, true, false){
|
||||
{
|
||||
range = 40;
|
||||
reload = 10f;
|
||||
bullet = BulletType.stone;
|
||||
ammo = Item.stone;
|
||||
health = 50;
|
||||
}
|
||||
|
||||
public void update(Tile tile){
|
||||
updateTurret(tile);
|
||||
}
|
||||
|
||||
public void draw(Tile tile){
|
||||
Draw.rect("block", tile.worldx(), tile.worldy());
|
||||
}
|
||||
|
||||
public void drawOver(Tile tile){
|
||||
Draw.rect(name(), tile.worldx(), tile.worldy(), tile.entity.rotation - 90);
|
||||
}
|
||||
|
||||
public String description(){
|
||||
return "Shoots things.";
|
||||
}
|
||||
},
|
||||
machineturret(true, true, false){
|
||||
{
|
||||
range = 65;
|
||||
reload = 5f;
|
||||
bullet = BulletType.iron;
|
||||
ammo = Item.iron;
|
||||
health = 65;
|
||||
}
|
||||
|
||||
public void update(Tile tile){
|
||||
updateTurret(tile);
|
||||
}
|
||||
|
||||
public void draw(Tile tile){
|
||||
Draw.rect("block", tile.worldx(), tile.worldy());
|
||||
}
|
||||
|
||||
public void drawOver(Tile tile){
|
||||
Draw.rect(name(), tile.worldx(), tile.worldy(), tile.entity.rotation - 90);
|
||||
}
|
||||
|
||||
public String description(){
|
||||
return "Shoots things.";
|
||||
}
|
||||
},
|
||||
healturret(true, true, false){
|
||||
{
|
||||
range = 30;
|
||||
reload = 30f;
|
||||
health = 50;
|
||||
}
|
||||
|
||||
public void update(Tile tile){
|
||||
/*
|
||||
* if(tile.entity.hasItem(ammo)){ tile.entity.shots += 20;
|
||||
* tile.entity.removeItem(ammo, 1); }
|
||||
*/
|
||||
//if(tile.entity.shots > 0){
|
||||
tile.entity.link = findTileTarget(tile, range);
|
||||
|
||||
if(tile.entity.link != null){
|
||||
tile.entity.rotation = tile.entity.angleTo(tile.entity.link);
|
||||
|
||||
if(Timers.get(tile, reload)){
|
||||
tile.entity.link.health++;
|
||||
}
|
||||
}
|
||||
//}
|
||||
}
|
||||
|
||||
public void draw(Tile tile){
|
||||
Draw.rect("block", tile.worldx(), tile.worldy());
|
||||
}
|
||||
|
||||
public void drawOver(Tile tile){
|
||||
if(tile.entity.link != null){
|
||||
float x = tile.worldx(), y = tile.worldy();
|
||||
float x2 = tile.entity.link.x, y2 = tile.entity.link.y;
|
||||
|
||||
Draw.color(Hue.rgb(138, 244, 138, (MathUtils.sin(Timers.time() / 2f) + 1f) / 15f));
|
||||
Draw.alpha(0.3f);
|
||||
Draw.thickness(4f);
|
||||
Draw.line(x, y, x2, y2);
|
||||
Draw.thickness(2f);
|
||||
Draw.circle(x2, y2, 2f);
|
||||
Draw.alpha(1f);
|
||||
Draw.thickness(2f);
|
||||
Draw.line(x, y, x2, y2);
|
||||
Draw.thickness(1f);
|
||||
Draw.circle(x2, y2, 1f);
|
||||
Draw.clear();
|
||||
}
|
||||
Draw.rect(name(), tile.worldx(), tile.worldy(), tile.entity.rotation - 90);
|
||||
}
|
||||
|
||||
public String description(){
|
||||
return "Heals nearby tiles.";
|
||||
}
|
||||
};
|
||||
static Vector2 vector = new Vector2();
|
||||
static Vector2 vector2 = new Vector2();
|
||||
|
||||
public boolean solid, update, rotate;
|
||||
public static final int tilesize = 8;
|
||||
public int health = 40;
|
||||
|
||||
//turrets
|
||||
public float range = 50f;
|
||||
public float reload = 10f;
|
||||
public BulletType bullet;
|
||||
public Item ammo;
|
||||
|
||||
private TileType() {
|
||||
solid = false;
|
||||
}
|
||||
|
||||
private TileType(boolean solid) {
|
||||
this.solid = solid;
|
||||
}
|
||||
|
||||
private TileType(boolean solid, boolean update) {
|
||||
this.solid = solid;
|
||||
this.update = update;
|
||||
}
|
||||
|
||||
private TileType(boolean solid, boolean update, boolean rotate) {
|
||||
this.solid = solid;
|
||||
this.update = update;
|
||||
this.rotate = rotate;
|
||||
}
|
||||
|
||||
public void init(TileEntity entity){
|
||||
|
||||
}
|
||||
|
||||
void updateTurret(Tile tile){
|
||||
if(tile.entity.hasItem(ammo)){
|
||||
tile.entity.shots += 20;
|
||||
tile.entity.removeItem(ammo, 1);
|
||||
}
|
||||
|
||||
if(tile.entity.shots > 0){
|
||||
Enemy enemy = findTarget(tile, range);
|
||||
if(enemy != null){
|
||||
tile.entity.rotation = MathUtils.lerpAngleDeg(tile.entity.rotation, Angles.predictAngle(tile.worldx(), tile.worldy(), enemy.x, enemy.y, enemy.xvelocity, enemy.yvelocity, bullet.speed - 0.1f), 0.2f);
|
||||
if(Timers.get(tile, reload)){
|
||||
new Bullet(bullet, tile.entity, tile.worldx(), tile.worldy(), tile.entity.rotation).add();
|
||||
tile.entity.shots--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Enemy findTarget(Tile tile, float range){
|
||||
Entity closest = null;
|
||||
float dst = 0;
|
||||
|
||||
Array<SolidEntity> array = Entities.getNearby(tile.worldx(), tile.worldy(), 100);
|
||||
|
||||
for(Entity e : array){
|
||||
|
||||
if(e instanceof Enemy){
|
||||
float ndst = Vector2.dst(tile.worldx(), tile.worldy(), e.x, e.y);
|
||||
if(ndst < range && (closest == null || ndst < dst)){
|
||||
dst = ndst;
|
||||
closest = e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (Enemy) closest;
|
||||
}
|
||||
|
||||
TileEntity findTileTarget(Tile tile, float range){
|
||||
Entity closest = null;
|
||||
float dst = 0;
|
||||
|
||||
Array<SolidEntity> array = Entities.getNearby(tile.worldx(), tile.worldy(), 100);
|
||||
|
||||
for(Entity e : array){
|
||||
|
||||
if(e instanceof TileEntity && ((TileEntity) e).health < ((TileEntity) e).tile.block().health){
|
||||
float ndst = Vector2.dst(tile.worldx(), tile.worldy(), e.x, e.y);
|
||||
if(ndst < range && (closest == null || ndst < dst)){
|
||||
dst = ndst;
|
||||
closest = e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (TileEntity) closest;
|
||||
}
|
||||
|
||||
void handleItem(Tile tile, Item item, float f){
|
||||
tile.entity.addItem(item, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to put this item into a nearby container, if there are no available
|
||||
* containers, it gets added to the block's inventory.
|
||||
*/
|
||||
void offloadNear(Tile tile, Item item){
|
||||
int i = 0;
|
||||
for(Tile other : tile.getNearby()){
|
||||
if(other != null && other.block().accepts(item)
|
||||
//don't output to things facing this thing
|
||||
&& !(other.block().rotate && (other.rotation + 2) % 4 == i)){
|
||||
|
||||
other.block().handleItem(other, item, 0);
|
||||
return;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
handleItem(tile, item, 0);
|
||||
}
|
||||
|
||||
/** Try dumping any item near the tile. */
|
||||
boolean tryDump(Tile tile){
|
||||
return tryDump(tile, -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Try dumping any item near the tile. -1 = any direction
|
||||
*/
|
||||
boolean tryDump(Tile tile, int direction){
|
||||
int i = 0;
|
||||
|
||||
for(Tile other : tile.getNearby()){
|
||||
if(i == direction || direction == -1)
|
||||
for(Item item : Item.values()){
|
||||
|
||||
if(tile.entity.hasItem(item) && other != null && other.block().accepts(item) &&
|
||||
//don't output to things facing this thing
|
||||
!(other.block().rotate && (other.rotation + 2) % 4 == i)){
|
||||
other.block().handleItem(other, item, 0);
|
||||
tile.entity.removeItem(item, 1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Try offloading an item to a nearby container. Returns true if success.
|
||||
*/
|
||||
boolean offloadDir(Tile tile, Item item){
|
||||
Tile other = tile.getNearby()[tile.rotation];
|
||||
if(other != null && other.block().accepts(item)){
|
||||
int ch = Math.abs(other.rotation - tile.rotation);
|
||||
other.block().handleItem(other, item, ch == 1 ? 0.5f : ch == 2 ? 1f : 0f);
|
||||
//other.entity.addCovey(item, ch == 1 ? 0.5f : ch ==2 ? 1f : 0f);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean accepts(Item item){
|
||||
return item == ammo;
|
||||
}
|
||||
|
||||
public String description(){
|
||||
return "[no description]";
|
||||
}
|
||||
|
||||
public void draw(Tile tile){
|
||||
if(tile.floor() == this){
|
||||
MathUtils.random.setSeed(tile.id());
|
||||
Draw.rect(name() + MathUtils.random(1, 3), tile.worldx(), tile.worldy(), rotate ? tile.rotation * 90 : 0);
|
||||
}else{
|
||||
Draw.rect(name(), tile.worldx(), tile.worldy(), rotate ? tile.rotation * 90 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
public String error(Tile tile){
|
||||
if(ammo != null && !tile.entity.hasItem(ammo) && tile.entity.shots <= 0)
|
||||
return "No ammo!";
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void drawOver(Tile tile){
|
||||
/*
|
||||
* String error = error(tile); if(error != null){ Draw.color("scarlet");
|
||||
* Draw.square(tile.worldx(), tile.worldy(), 6); Draw.clear(); }
|
||||
*/
|
||||
}
|
||||
|
||||
public void update(Tile tile){
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user