Test Commit

This commit is contained in:
Pan 2018-08-30 23:07:37 +12:00
commit 7c83ed1267
162 changed files with 38764 additions and 0 deletions

6
.classpath Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="src" path=""/>
<classpathentry kind="output" path=""/>
</classpath>

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/main.class

17
.project Normal file
View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>Java_RTS</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

20
core/.gitignore vendored Normal file
View File

@ -0,0 +1,20 @@
/AssetManager.class
/DaemonThread.class
/PathFinder.class
/Rect.class
/Ticker.class
/Turn2DTo3DFactory.class
/baseInfo.class
/camera.class
/gameData.class
/geometry.class
/grid.class
/mainThread.class
/polygon3D.class
/postProcessingThread.class
/rasterizer.class
/sunLight.class
/terrain.class
/textRenderer.class
/texture.class
/vector.class

820
core/AssetManager.java Normal file
View File

@ -0,0 +1,820 @@
package core;
import enemyAI.*;
import entity.*;
import gui.*;
import particles.*;
//This class stores and maintains all the entities created in the game
public class AssetManager {
public int polygonCount;
public int visibleUnitCount;
public solidObject[] visibleUnit;
public int[][] selectedUnitsInfo;
public int[][] selectedUnitsInfo2;
public float[][] visionPolygonInfo;
public float[][] visionPolygonInfo2;
public int visionPolygonCount;
public int[][] unitsForMiniMap;
public int[][] unitsForMiniMap2;
public int unitsForMiniMapCount;
public boolean[] minimapBitmap;
public boolean[] minimapBitmap2;
public float[][] smokeEmmiterList;
public float[][] smokeEmmiterList2;
public int smokeEmmiterCount;
public float[][] explosionInfo;
public float[][] explosionInfo2;
public int explosionCount;;
public float[][] helixInfo;
public float[][] helixInfo2;
public int helixCount;
public double[] confirmationIconInfo;
public double[] confirmationIconInfo2;
public lightTank[] lightTanks;
public heavyTank[] heavyTanks;
public palmTree[] trees;
public int plamTreeCount;
public powerPlant[] powerPlants;
public refinery[] refineries;
public rocketTank[] rocketTanks;
public harvester[] harvesters;
public goldMine[] goldMines;
public constructionVehicle[] constructionVehicles;
public constructionYard[] constructionYards;
public factory[] factories;
public drone[] drones;
public communicationCenter[] communicationCenters;
public techCenter[] techCenters;
public stealthTank[] stealthTanks;
public gunTurret[] gunTurrets;
public missileTurret[] missileTurrets;
public terrain Terrain;
public bullet[] bullets;
public rocket[] rockets;
public polygon3D[] visionPolygon;
public void init(){
selectedUnitsInfo = new int[100][6];
selectedUnitsInfo2 = new int[100][6];
visionPolygonInfo = new float[400][5];
visionPolygonInfo2 = new float[400][5];
unitsForMiniMap = new int[1000][5];
unitsForMiniMap2 = new int[1000][5];
smokeEmmiterList = new float[100][8];
smokeEmmiterList2 = new float[100][8];
minimapBitmap = new boolean[128 * 128];
minimapBitmap2 = new boolean[128 * 128];
explosionInfo = new float[100][8];
explosionInfo2 = new float[100][8];
helixInfo = new float[128][4];
helixInfo2 = new float[128][4];
confirmationIconInfo = new double[5];
confirmationIconInfo2 = new double[5];
bullets = new bullet[200];
for(int i = 0; i < 200; i ++){
bullets[i] = new bullet();
}
rockets = new rocket[200];
for(int i = 0; i < 200; i ++){
rockets[i] = new rocket();
}
visibleUnit = new solidObject[400];
//polygons which represent the area of sight for player
double angle = Math.PI/24;
visionPolygon = new polygon3D[4];
vector[] v = new vector[48];
for(int i = 0; i < 48; i++){
v[i] = new vector((float)Math.sin(i*angle)*1.6f, 1f, (float)Math.cos(i*angle)*1.6f);
}
visionPolygon[0] = new polygon3D(v, v[0], v[1], v[3], null, 1,1, 2);
// vision created by an attacking enemy unit
v = new vector[48];
for(int i = 0; i < 48; i++){
v[i] = new vector((float)Math.sin(i*angle)*0.5f, -1.5f, (float)Math.cos(i*angle)*0.5f);
}
visionPolygon[1] = new polygon3D(v, v[0], v[1], v[3], null, 1,1, 2);
//vision created by building
v = new vector[48];
for(int i = 0; i < 48; i++){
v[i] = new vector((float)Math.sin(i*angle)*2.1f, 1f, (float)Math.cos(i*angle)*2.1f);
}
visionPolygon[2] = new polygon3D(v, v[0], v[1], v[3], null, 1,1, 2);
//vision created by communication center
v = new vector[48];
for(int i = 0; i < 48; i++){
v[i] = new vector((float)Math.sin(i*angle)*3.1f, 1f, (float)Math.cos(i*angle)*3.1f);
}
visionPolygon[3] = new polygon3D(v, v[0], v[1], v[3], null, 1,1, 2);
lightTanks = new lightTank[768];
heavyTanks = new heavyTank[256];
trees = new palmTree[2048];
powerPlants = new powerPlant[256];
refineries = new refinery[128];
rocketTanks = new rocketTank[512];
harvesters = new harvester[128];
constructionVehicles = new constructionVehicle[64];
goldMines = new goldMine[16];
constructionYards = new constructionYard[64];
factories = new factory[128];
drones = new drone[384];
communicationCenters = new communicationCenter[128];
techCenters = new techCenter[64];
stealthTanks = new stealthTank[384];
gunTurrets = new gunTurret[512];
missileTurrets = new missileTurret[256];
Terrain = new terrain();
//unit costs/hit point/power consumption/exp on kill
//lightTank 300/120/0/10
//rocketTank 450/70/0/15
//harvester 800/260/0/25
//stealth tank 600/80/0/20
//heavyTank 1100/320/0/50
//constructionVehicle 1700/300/0/30
//
//power plant 500/400/+500/25
//refinery 1200/750/-150/35
//communication center 1000/550/-250/35
//factory 1400/850/-200/40
//tech center 1500/s/-450/50
//gun turret 400/250/-100/20
//missile turret 750/250/(-200/-400)/35
//construction yard 1700/1000/0/50
//
//harvester speed research 1200
//missile turret overcharge research 1500
//light tank range upgrade 1500
//Missile tank dmg upgrade 2500
//stealth tank split lasor 2500
//Heavy tank regen 3000
goldMines[0] = new goldMine(2f,-0.515f, 1.25f, 30000);
goldMines[1] = new goldMine(9.5f,-0.515f, 5.5f, 30000);
goldMines[2] = new goldMine(2f,-0.515f, 28.25f, 40000);
goldMines[3] = new goldMine(26f,-0.515f, 3.5f, 40000);
goldMines[4] = new goldMine(29.75f,-0.515f, 30f, 30000);
goldMines[5] = new goldMine(22.5f,-0.515f, 25.5f, 30000);
goldMines[6] = new goldMine(15.5f,-0.515f, 17.75f, 45000);
goldMines[7] = new goldMine(16.5f,-0.515f, 12.5f, 45000);
//create trees from bitmap
short[] treeBitmap = mainThread.textures[56].pixelData;
for(int i = 0; i < 114; i++){
for(int j = 0; j < 114; j++){
if((treeBitmap[j + i * 128]<<10) <128 && plamTreeCount < trees.length){
trees[plamTreeCount] = new palmTree(j*0.28f, -0.3f, (113 -i)*0.28f);
plamTreeCount++;
}
}
}
mainThread.pc = new playerCommander();
mainThread.pc.init();
mainThread.ec = new enemyCommander();
mainThread.ec.init();
}
public void prepareAssetForNewGame(){
addConstructionVehicle(new constructionVehicle(new vector(3.125f,-0.3f, 2.125f), 90, 0));
addConstructionVehicle(new constructionVehicle(new vector(29.625f,-0.3f, 28.875f), 90, 1));
constructionVehicles[1].expand();
for(int i = 0; i < 6; i ++){
for(int j = 0; j < 10; j++){
//if(i == 0) {
//rocketTank l = new rocketTank(new vector(j*0.25f+ 1.125f,-0.3f, 22.125f - i*0.25f), 90, 1);
//l.damageMultiplier =2;
//addRocketTank(l);
//techCenter.rocketTankResearched_enemy = true;
//}else {
//heavyTank l = new heavyTank(new vector(j*0.25f+ 1.125f,-0.3f, 22.125f - i*0.25f), 90, 1);
//addHeavyTank(l);
//}
}
}
for(int i = 0; i < 10; i ++){
for(int j = 0; j < 6; j++){
//heavyTank l = new heavyTank(new vector(i*0.25f+ 1.125f,-0.3f, 17.375f - 0.25f*j), 90, 0);
//addHeavyTank(l);
//l.hasMultiShotUpgrade = true;
//lightTank l = new lightTank(new vector(i*0.25f + 1.125f,-0.3f, 0.5f + 18.625f + j*0.25f), 90, 0);
//l.attackRange = 1.99f;
//lightTank.tileCheckList_player = lightTank.generateTileCheckList(6);
//addLightTank(l);
//addMissileTurret(new missileTurret(i*0.25f -0.125f + 1, -0.65f, 0.25f + 16.125f + j*0.25f, 0));
}
}
}
public void addContructionYard(constructionYard o){
for(int i = 0; i < constructionYards.length; i++){
if(constructionYards[i] == null){
constructionYards[i] = o;
break;
}
}
}
public void addPowerPlant(powerPlant o){
for(int i = 0; i < powerPlants.length; i++){
if(powerPlants[i] == null){
powerPlants[i] = o;
break;
}
}
}
public void addRefinery(refinery o){
for(int i = 0; i < refineries.length; i++){
if(refineries[i] == null){
refineries[i] = o;
break;
}
}
}
public void addFactory(factory o){
for(int i = 0; i < factories.length; i++){
if(factories[i] == null){
factories[i] = o;
break;
}
}
}
public void addDrone(drone o){
for(int i = 0; i < drones.length; i++){
if(drones[i] == null){
drones[i] = o;
break;
}
}
}
public void addCommunicationCenter(communicationCenter o){
for(int i = 0; i < communicationCenters.length; i++){
if(communicationCenters[i] == null){
communicationCenters[i] = o;
break;
}
}
}
public void addTechCenter(techCenter o){
for(int i = 0; i < techCenters.length; i++){
if(techCenters[i] == null){
techCenters[i] = o;
break;
}
}
}
public void addHarvester(harvester o){
for(int i = 0; i < harvesters.length; i++){
if(harvesters[i] == null){
harvesters[i] = o;
break;
}
}
}
public void addLightTank(lightTank o){
for(int i = 0; i < lightTanks.length; i++){
if(lightTanks[i] == null){
lightTanks[i] = o;
break;
}
}
}
public void addHeavyTank(heavyTank o){
for(int i = 0; i < heavyTanks.length; i++){
if(heavyTanks[i] == null){
heavyTanks[i] = o;
break;
}
}
}
public void addStealthTank(stealthTank o){
for(int i = 0; i < stealthTanks.length; i++){
if(stealthTanks[i] == null){
stealthTanks[i] = o;
break;
}
}
}
public void addRocketTank(rocketTank o){
for(int i = 0; i < rocketTanks.length; i++){
if(rocketTanks[i] == null){
rocketTanks[i] = o;
break;
}
}
}
public void addConstructionVehicle(constructionVehicle o){
for(int i = 0; i < constructionVehicles.length; i++){
if(constructionVehicles[i] == null){
constructionVehicles[i] = o;
break;
}
}
}
public void addGunTurret(gunTurret o){
for(int i = 0; i < gunTurrets.length; i++){
if(gunTurrets[i] == null){
gunTurrets[i] = o;
break;
}
}
}
public void addMissileTurret(missileTurret o){
for(int i = 0; i < missileTurrets.length; i++){
if(missileTurrets[i] == null){
missileTurrets[i] = o;
break;
}
}
}
public void updateAndDraw(){
polygonCount = 0;
visibleUnitCount = 0;
visionPolygonCount = 0;
unitsForMiniMapCount = 0;
explosionCount = 0;
smokeEmmiterCount = 0;
helixCount = 0;
Terrain.update();
for(int i = 0; i < lightTanks.length; i++){
if(lightTanks[i] != null)
lightTanks[i].update();
}
for(int i = 0; i < heavyTanks.length; i++){
if(heavyTanks[i] != null)
heavyTanks[i].update();
}
for(int i = 0; i < stealthTanks.length; i++){
if(stealthTanks[i] != null)
stealthTanks[i].update();
}
for(int i = 0; i < plamTreeCount; i++)
trees[i].update();
for(int i = 0; i < constructionYards.length; i++){
if(constructionYards[i] != null)
constructionYards[i].update();
}
for(int i = 0; i < powerPlants.length; i++){
if(powerPlants[i] != null)
powerPlants[i].update();
}
for(int i = 0; i < techCenters.length; i++){
if(techCenters[i] != null)
techCenters[i].update();
}
for(int i = 0; i < gunTurrets.length; i++){
if(gunTurrets[i] != null)
gunTurrets[i].update();
}
for(int i = 0; i < missileTurrets.length; i++){
if(missileTurrets[i] != null)
missileTurrets[i].update();
}
for(int i = 0; i < communicationCenters.length; i++){
if(communicationCenters[i] != null)
communicationCenters[i].update();
}
for(int i = 0; i < refineries.length; i++){
if(refineries[i] != null)
refineries[i].update();
}
for(int i = 0; i < factories.length; i++){
if(factories[i] != null)
factories[i].update();
}
for(int i = 0; i < drones.length; i++){
if(drones[i] != null)
drones[i].update();
}
for(int i = 0; i < rocketTanks.length; i++){
if(rocketTanks[i] != null)
rocketTanks[i].update();
}
for(int i = 0; i < harvesters.length; i++){
if(harvesters[i] != null)
harvesters[i].update();
}
for(int i = 0; i < constructionVehicles.length; i++){
if(constructionVehicles[i] != null)
constructionVehicles[i].update();
}
for(int i = 0; i < 10; i++){
if(goldMines[i] != null)
goldMines[i].update();
}
//start drawing
//maximize the zbuffer value in the area that are occupied by UI, so the drawing process will not waste time filling the pixels which would eventually get overdrawn
int start = 381 * 768 + 3;
int start2 = 381 * 768 + 635;
for(int y = 0; y < 131; y++){
for(int x = 0; x < 128; x ++){
mainThread.zBuffer[start + x + y*768] = Integer.MAX_VALUE;
mainThread.zBuffer[start2 + x + y*768] = Integer.MAX_VALUE;
}
}
for(int i = 0; i < 200; i ++)
bullets[i].updateAndDraw();
for(int i = 0; i < 200; i ++)
rockets[i].update();
for(int i = 0; i < lightTanks.length; i++){
if(lightTanks[i] != null)
lightTanks[i].draw();
}
for(int i = 0; i < heavyTanks.length; i++){
if(heavyTanks[i] != null)
heavyTanks[i].draw();
}
for(int i = 0; i < stealthTanks.length; i++){
if(stealthTanks[i] != null)
stealthTanks[i].draw();
}
for(int i = 0; i < plamTreeCount; i++)
trees[i].draw();
for(int i = 0; i < powerPlants.length; i++){
if(powerPlants[i] != null)
powerPlants[i].draw();
}
for(int i = 0; i < gunTurrets.length; i++){
if(gunTurrets[i] != null)
gunTurrets[i].draw();
}
for(int i = 0; i < missileTurrets.length; i++){
if(missileTurrets[i] != null)
missileTurrets[i].draw();
}
for(int i = 0; i < communicationCenters.length; i++){
if(communicationCenters[i] != null)
communicationCenters[i].draw();
}
for(int i = 0; i < techCenters.length; i++){
if(techCenters[i] != null)
techCenters[i].draw();
}
for(int i = 0; i < refineries.length; i++){
if(refineries[i] != null)
refineries[i].draw();
}
for(int i = 0; i < rocketTanks.length; i++){
if(rocketTanks[i] != null)
rocketTanks[i].draw();
}
for(int i = 0; i < harvesters.length; i++){
if(harvesters[i] != null)
harvesters[i].draw();
}
for(int i = 0; i < constructionVehicles.length; i++){
if(constructionVehicles[i] != null)
constructionVehicles[i].draw();
}
for(int i = 0; i < constructionYards.length; i++){
if(constructionYards[i] != null)
constructionYards[i].draw();
}
for(int i = 0; i < goldMines.length; i++){
if(goldMines[i] != null)
goldMines[i].draw();
}
for(int i = 0; i < 200; i ++)
rockets[i].draw();
for(int i = 0; i < drones.length; i++){
if(drones[i] != null)
drones[i].draw();
}
for(int i = 0; i < factories.length; i++){
if(factories[i] != null)
factories[i].draw();
}
Terrain.draw();
if(mainThread.pc.selectedConstructionYard != null){
mainThread.pc.selectedConstructionYard.drawDeploymentGrid();
}
for(int i = 0; i < factories.length; i++){
if(factories[i] != null)
factories[i].drawRallyPointLine();
}
//prepare selected unit list
for(int i = 0; i < 99; i++){
if(mainThread.pc.selectedUnits[i] != null && mainThread.pc.selectedUnits[i].isSelectable){
selectedUnitsInfo[i][0] = mainThread.pc.selectedUnits[i].level << 16 | mainThread.pc.selectedUnits[i].groupNo << 8 | mainThread.pc.selectedUnits[i].type;
selectedUnitsInfo[i][1] = (int)mainThread.pc.selectedUnits[i].tempCentre.screenX;
selectedUnitsInfo[i][2] = (int)mainThread.pc.selectedUnits[i].tempCentre.screenY;
if(mainThread.pc.selectedUnits[i].type == 199){
selectedUnitsInfo[i][1] = (int)mainThread.pc.selectedUnits[i].screenX_gui;
selectedUnitsInfo[i][2] = (int)mainThread.pc.selectedUnits[i].screenY_gui;
}
selectedUnitsInfo[i][3] = (int)mainThread.pc.selectedUnits[i].type;
selectedUnitsInfo[i][4] = mainThread.pc.selectedUnits[i].currentHP;
selectedUnitsInfo[i][5] = mainThread.pc.selectedUnits[i].progressStatus;
}else{
selectedUnitsInfo[i][0] = -1;
}
}
}
//swap the resources that are held by the main thread and the post processing thread
public void swapResources(){
int[][] list;
list = selectedUnitsInfo;
selectedUnitsInfo = selectedUnitsInfo2;
selectedUnitsInfo2 = list;
float[][] floatList;
floatList = visionPolygonInfo;
visionPolygonInfo = visionPolygonInfo2;
visionPolygonInfo2 = floatList;
int[][] unitList;
unitList = unitsForMiniMap;
unitsForMiniMap = unitsForMiniMap2;
unitsForMiniMap2 = unitList;
boolean[] bitmap;
bitmap = minimapBitmap;
minimapBitmap = minimapBitmap2;
minimapBitmap2 = bitmap;
float[][] emmiterList;
emmiterList = smokeEmmiterList;
smokeEmmiterList = smokeEmmiterList2;
smokeEmmiterList2 = emmiterList;
float[][] explosionList;
explosionList = explosionInfo;
explosionInfo = explosionInfo2;
explosionInfo2 = explosionList;
double[] iconInfo;
iconInfo = confirmationIconInfo;
confirmationIconInfo = confirmationIconInfo2;
confirmationIconInfo2 = iconInfo;
}
//spawn a bullet
public void spawnBullet(int angle, int damage, solidObject target, vector centre, solidObject attacker){
for(int i = 0; i < 200; i ++)
if(!bullets[i].isInAction){
bullets[i].setActive(angle, damage, target, centre, attacker);
break;
}
}
//spawn a rocket
public void spawnRocket(int angle, int damage, solidObject target, vector centre, solidObject attacker){
for(int i = 0; i < 200; i ++)
if(!rockets[i].isInAction){
rockets[i].setActive(angle, damage, target, centre, attacker);
break;
}
}
//remove object that ceased to exist (e.g get destroyed)
public void removeObject(solidObject o){
mainThread.pc.removeDestoryedObjectFromSelection(o);
for(int i = 0; i < lightTanks.length; i++){
if(lightTanks[i] == o){
lightTanks[i] = null;
return;
}
}
for(int i = 0; i < stealthTanks.length; i++){
if(stealthTanks[i] == o){
stealthTanks[i] = null;
return;
}
}
for(int i = 0; i < powerPlants.length; i++){
if(powerPlants[i] == o){
powerPlants[i] = null;
return;
}
}
for(int i = 0; i < techCenters.length; i++){
if(techCenters[i] == o){
techCenters[i] = null;
return;
}
}
for(int i = 0; i < gunTurrets.length; i++){
if(gunTurrets[i] == o){
gunTurrets[i] = null;
return;
}
}
for(int i = 0; i < missileTurrets.length; i++){
if(missileTurrets[i] == o){
missileTurrets[i] = null;
return;
}
}
for(int i = 0; i < communicationCenters.length; i++){
if(communicationCenters[i] == o){
communicationCenters[i] = null;
return;
}
}
for(int i = 0; i < refineries.length; i++){
if(refineries[i] == o){
refineries[i] = null;
return;
}
}
for(int i = 0; i < factories.length; i++){
if(factories[i] == o){
factories[i] = null;
return;
}
}
for(int i = 0; i < drones.length; i++){
if(drones[i] == o){
drones[i] = null;
return;
}
}
for(int i = 0; i < rocketTanks.length; i++){
if(rocketTanks[i] == o){
rocketTanks[i] = null;
return;
}
}
for(int i = 0; i < heavyTanks.length; i++){
if(heavyTanks[i] == o){
heavyTanks[i] = null;
return;
}
}
for(int i = 0; i < harvesters.length; i++){
if(harvesters[i] == o){
harvesters[i] = null;
return;
}
}
for(int i = 0; i < constructionVehicles.length; i++){
if(constructionVehicles[i] == o){
constructionVehicles[i] = null;
return;
}
}
for(int i = 0; i < constructionYards.length; i++){
if(constructionYards[i] == o){
constructionYards[i] = null;
return;
}
}
}
}

10
core/DaemonThread.java Normal file
View File

@ -0,0 +1,10 @@
package core;
public class DaemonThread implements Runnable {
public void run(){
try{
Thread.sleep(Long.MAX_VALUE);
}
catch(Exception e){}
}
}

148
core/PathFinder.java Normal file
View File

@ -0,0 +1,148 @@
package core;
/*
1. You start the search from the destination-point (Step 0) and not the start-point.
2. You mark the 4 squares over/under and left/right of the current square with "1" (step value) (if its not a wall) as in "one step from the destination", then you add these squares to a node-list.
3. Go through the current node-list and repeat point 2 on each entry, mark the appropriate squares "2" (n+1) and add these to a swap node-list.Squares already marked with a step-value are IGNORED (like a wall).
4. Repeat point 2 & 3 while incresing the step-value for every cycle/point until you have reached the start-point. (or continue and scan the whole maze if desired).
5. Now you have the shortest way to the target, by simply moving to the adjacent square with the lowest number - until you have reached the destination!
*/
public class PathFinder{
public static int[] nodes = new int[128*128];
public static boolean createHeuristicMap(byte[] heuristicMap, int occupiedTile0, int occupiedTile1, int occupiedTile2, int occupiedTile3, int destX, int destY){
if(destX == 0)
destX = 1;
if(destX == 127)
destX = 126;
if(destY == 0)
destY = 1;
if(destY == 127)
destY = 126;
int l = 128 * 128;
for(int i = 0; i < l ; i++)
heuristicMap[i] = 127;
boolean[] obstacleMap = mainThread.gridMap.previousObstacleMap;
int destTile = destX + destY*128;
//mark destination tile with heuristic value 0
if(destTile < 0)
destTile = 0;
if(destTile >= 16384)
destTile = 16383;
heuristicMap[destTile] = 0;
int topTile = destTile- 128;
int botTile = destTile+ 128;
int leftTile = destTile- 1;
int rightTile = destTile+ 1;
//check if path is the starting tiles is reached
if(topTile == occupiedTile0 || topTile == occupiedTile1 || topTile == occupiedTile2 || topTile == occupiedTile3 ||
botTile == occupiedTile0 || botTile == occupiedTile1 || botTile == occupiedTile2 || botTile == occupiedTile3 ||
leftTile == occupiedTile0 || leftTile == occupiedTile1 || leftTile == occupiedTile2 || leftTile == occupiedTile3 ||
rightTile == occupiedTile0 || rightTile == occupiedTile1 || rightTile == occupiedTile2 || rightTile == occupiedTile3){
return true;
}
int nodeCount = 0;
if(obstacleMap[topTile]){
nodes[nodeCount] = topTile;
heuristicMap[topTile] = 1;
nodeCount++;
}
if(obstacleMap[botTile]){
nodes[nodeCount] = botTile;
heuristicMap[botTile] = 1;
nodeCount++;
}
if(obstacleMap[leftTile]){
nodes[nodeCount] = leftTile;
heuristicMap[leftTile] = 1;
nodeCount++;
}
if(obstacleMap[rightTile]){
nodes[nodeCount] = rightTile;
heuristicMap[rightTile] = 1;
nodeCount++;
}
int startIndex = 0;
int endIndex = startIndex + nodeCount;
for(byte i = 0, distance = 2; i < 126; i++, distance++){ // max depth = 126
nodeCount = 0;
for(int j = startIndex; j < endIndex; j++){
destTile = nodes[j];
topTile = destTile- 128;
botTile = destTile+ 128;
leftTile = destTile- 1;
rightTile = destTile+ 1;
//check if path is the starting tiles is reached
if(topTile == occupiedTile0 || topTile == occupiedTile1 || topTile == occupiedTile2 || topTile == occupiedTile3 ||
botTile == occupiedTile0 || botTile == occupiedTile1 || botTile == occupiedTile2 || botTile == occupiedTile3 ||
leftTile == occupiedTile0 || leftTile == occupiedTile1 || leftTile == occupiedTile2 || leftTile == occupiedTile3 ||
rightTile == occupiedTile0 || rightTile == occupiedTile1 || rightTile == occupiedTile2 || rightTile == occupiedTile3){
return true;
}
if(heuristicMap[topTile] == 127 && obstacleMap[topTile]){
nodes[endIndex + nodeCount] = topTile;
heuristicMap[topTile] = distance;
nodeCount++;
}
if(heuristicMap[botTile] == 127 && obstacleMap[botTile]){
nodes[endIndex + nodeCount] = botTile;
heuristicMap[botTile] = distance;
nodeCount++;
}
if(heuristicMap[leftTile] == 127 && obstacleMap[leftTile]){
nodes[endIndex + nodeCount] = leftTile;
heuristicMap[leftTile] = distance;
nodeCount++;
}
if(heuristicMap[rightTile] == 127 && obstacleMap[rightTile]){
nodes[endIndex + nodeCount] = rightTile;
heuristicMap[rightTile] = distance;
nodeCount++;
}
}
startIndex = endIndex;
endIndex+=nodeCount;
}
return false;
}
}

58
core/Rect.java Normal file
View File

@ -0,0 +1,58 @@
package core;
import entity.solidObject;
//this clase define a rectangle in Cartesian coordinate
public class Rect {
public int x1,x2,y1,y2,width,height;
public solidObject owner;
public Rect(int x1, int y1, int width, int height){
this.x1 = x1;
this.y1 = y1;
this.width = width;
this.height = height;
x2 = x1 + width - 1;
y2 = y1 - height + 1;
}
public void setOrigin(int x1, int y1){
this.x1 = x1;
this.y1 = y1;
x2 = x1 + width - 1;
y2 = y1 - height + 1;
}
public boolean intersect(Rect r){
return !(x1 > r.x2 || r.x1 > x2 || y2 > r.y1 || r.y2 > y1);
}
public boolean contains(int x, int y){
return x >= x1 && x <=x2 && y <= y1 && y >= y2;
}
public void expand(int r){
x1-=r;
x2+=r;
y1+=r;
y2-=r;
width+=2*r;
height+=2*r;
}
public void shrink(int r){
x1+=r;
x2-=r;
y1-=r;
y2+=r;
width-=2*r;
height-=2*r;
}
public String toString(){
return x1 + " " + y1 + " " + width + " " + height;
}
}

78
core/Ticker.java Normal file
View File

@ -0,0 +1,78 @@
package core;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Ticker implements Runnable{
ActionListener al;
private boolean isTicking;
Thread t;
int delay;
public Ticker(int i, ActionListener actionlistener){
al = actionlistener;
delay = i;
t = new Thread(this);
t.start();
isTicking = false;
}
public Ticker(int i){
delay = i;
t = new Thread(this);
t.start();
isTicking = false;
}
public void addActionListener(ActionListener actionlistener){
if(al == null)
al = actionlistener;
else
System.out.println("WARNING: ActionListener already added to Ticker.");
}
public boolean isRunning(){
return isTicking;
}
public void start(){
isTicking = true;
}
public void stop() {
isTicking = false;
}
public void setDelay(int i){
delay = i;
}
public int getDelay(){
return delay;
}
private void fireActionPerformed(){
if(al == null || !isTicking){
return;
} else{
ActionEvent actionevent = new ActionEvent(this, 0, null);
al.actionPerformed(actionevent);
return;
}
}
public void run(){
do{
fireActionPerformed();
try{
Thread.sleep(delay);
}
catch(InterruptedException interruptedexception){
System.out.println("WARNING: Ticker thread interrupted.");
}
} while(true);
}
}

View File

@ -0,0 +1,75 @@
package core;
//takes a pixel position from a rasterized polygon and find its 3D location in world space
public class Turn2DTo3DFactory {
public vector O, U, V, W, A, B, C;
public vector location3D;
public float X, Y;
public void init(){
O = new vector(0,0,0);
U = new vector(0,0,0);
V = new vector(0,0,0);
W = new vector(0,0,0);
A = new vector(0,0,0);
B = new vector(0,0,0);
C = new vector(0,0,0);
location3D = new vector(0,0,0);
}
public vector get3DLocation(polygon3D poly, int x, int y){
O.set(poly.origin);
O.subtract(camera.position);
O.rotate_XZ(camera.XZ_angle);
O.rotate_YZ(camera.YZ_angle);
U.set(poly.rightEnd);
U.subtract(camera.position);
U.rotate_XZ(camera.XZ_angle);
U.rotate_YZ(camera.YZ_angle);
V.set(poly.bottomEnd);
V.subtract(camera.position);
V.rotate_XZ(camera.XZ_angle);
V.rotate_YZ(camera.YZ_angle);
U.subtract(O);
U.unit();
V.subtract(O);
V.unit();
A.cross(V,O);
B.cross(O,U);
C.cross(U,V);
W.set(x-384, -y + 256, 650);
X = A.dot(W)/C.dot(W);
Y = B.dot(W)/C.dot(W);
O.set(poly.origin);
U.set(poly.rightEnd);
V.set(poly.bottomEnd);
U.subtract(O);
V.subtract(O);
X/=(U.getLength());
Y/=(V.getLength());
location3D.set(O);
location3D.add(U, X);
location3D.add(V, Y);
return location3D;
}
}

93
core/baseInfo.java Normal file
View File

@ -0,0 +1,93 @@
package core;
//store all the information about a base, eg current credit, number of structures , current power level, tech trees and etc...
public class baseInfo {
public int numberOfPowerPlant;
public int numberOfConstructionYard;
public int numberOfRefinery;
public int numberOfFactory;
public int numberOfCommunicationCenter;
public int numberOfTechCenter;
public int numberOfGunTurret;
public int numberOfMissileTurret, numberOfOverChargedMissileTurret;
public boolean canBuildPowerPlant, canBuildRefinery, canBuildFactory, canBuildCommunicationCenter, canBuildTechCenter, canBuildGunTurret, canBuildMissileTurret;
public boolean canBuildLightTank, canBuildRocketTank, canBuildDrone, canBuildStealthTank, canBuildHeavyTank, canBuildMCV, canBuildHarvester;
public int currentCredit;
public int currentPowerLevel;
public int currentPowerConsumption;
public int powerStatus;
public boolean lowPower;
public baseInfo(){
currentCredit = 5000;
}
public void update(){
//update tech tree
canBuildPowerPlant = true;
canBuildRefinery = false;
canBuildFactory = false;
canBuildCommunicationCenter= false;
canBuildTechCenter = false;
canBuildGunTurret = false;
canBuildMissileTurret= false;
canBuildLightTank = true;
canBuildRocketTank = true;
canBuildDrone = true;
canBuildHarvester = false;
canBuildMCV = false;
canBuildHeavyTank = false;
canBuildStealthTank = false;
if(numberOfPowerPlant > 0){
canBuildRefinery = true;
}
if(numberOfRefinery > 0){
canBuildFactory = true;
canBuildHarvester = true;
}
if(numberOfFactory > 0){
canBuildCommunicationCenter = true;
canBuildGunTurret = true;
}
if(numberOfCommunicationCenter > 0){
canBuildMissileTurret = true;
canBuildTechCenter = true;
canBuildStealthTank = true;
canBuildMCV = true;
}
if(numberOfTechCenter > 0){
canBuildHeavyTank = true;
}
currentPowerLevel = numberOfPowerPlant*500 + numberOfConstructionYard*100;
currentPowerConsumption = numberOfRefinery*150 + numberOfFactory*200 + numberOfCommunicationCenter*250 + numberOfGunTurret*100 + numberOfMissileTurret*200 + numberOfOverChargedMissileTurret*150 + numberOfTechCenter*400;
//calculate power level and power consumption
if(currentPowerLevel == 0){
powerStatus = -1;
}else{
powerStatus = currentPowerConsumption * 100 / currentPowerLevel;
}
if(powerStatus == -1 || powerStatus > 100)
lowPower = true;
else
lowPower = false;
if(powerStatus != -1){
powerStatus = currentPowerConsumption << 16 | currentPowerLevel;
}
}
}

134
core/camera.java Normal file
View File

@ -0,0 +1,134 @@
package core;
import java.awt.*;
public class camera{
public static vector position;
public static vector view_Direction;
public static vector left, right, left_, right_;
public static boolean MOVE_LEFT, MOVE_RIGHT, MOVE_UP, MOVE_DOWN, TURN_LEFT, TURN_RIGHT;
public static int XZ_angle, YZ_angle;
public static float sinXZ_angle, cosXZ_angle, sinYZ_angle, cosYZ_angle;
public static final vector viewDirection = new vector(0, 0, 1);
//a rectangle that represents the screen area
public static final Rectangle screen = new Rectangle(0,0,768, 512);
public camera(vector p, int XZ, int YZ){
view_Direction = new vector(0, 0, 1);
position = p;
XZ_angle = XZ;
YZ_angle = YZ;
left = new vector(0,0,0);
right = new vector(0,0,0);
left_ = new vector(0, -1, 0);
right_ = new vector(0, 1, 0);
}
public void update(){
position.add(view_Direction.x*3, 0 , view_Direction.z*3);
if(TURN_RIGHT){
XZ_angle+=1;
}
if(TURN_LEFT){
XZ_angle-=1;
}
float x = position.x;
float z = position.z;
if(MOVE_LEFT){
left.cross(view_Direction, left_);
left.unit();
position.add(left, -0.1f);
}
if(MOVE_RIGHT){
right.cross(view_Direction, right_);
right.unit();
position.add(right, -0.1f);
}
if(MOVE_UP){
vector up = new vector(view_Direction.x, 0, view_Direction.z);
up.unit();
position.add(up, 0.1f);
}
if(MOVE_DOWN){
vector down = new vector(view_Direction.x, 0, view_Direction.z);
down.unit();
position.add(down, -0.1f);
}
//make sure the camera never leaves the map
if(position.x < 0.5){
position.x = 0.5f;
}
if(position.z < 0.5){
position.z = 0.5f;
}
if(position.x > 31.5){
position.x = 31.5f;
}
if(position.z > 31.5){
position.z = 31.5f;
}
XZ_angle = (XZ_angle + 360) % 360;
YZ_angle = (YZ_angle + 360) % 360;
sinXZ_angle = gameData.sin[XZ_angle];
cosXZ_angle = gameData.cos[XZ_angle];
sinYZ_angle = gameData.sin[YZ_angle];
cosYZ_angle = gameData.cos[YZ_angle];
view_Direction.set(viewDirection);
view_Direction.rotate_YZ(YZ_angle);
view_Direction.rotate_XZ(XZ_angle);
view_Direction.y*=-1;
view_Direction.x*=-1;
view_Direction.unit();
position.add(-view_Direction.x*3, 0 , -view_Direction.z*3);
MOVE_LEFT = false;
MOVE_RIGHT = false;
MOVE_UP = false;
MOVE_DOWN = false;
TURN_LEFT = false;
TURN_RIGHT = false;
}
}

196
core/gameData.java Normal file
View File

@ -0,0 +1,196 @@
package core;
import java.awt.Image;
import java.awt.image.PixelGrabber;
import javax.imageio.ImageIO;
//Store useful arithmetic data for the game engine such as
//Cos/Sin look up table, color palette, etc...
public class gameData {
public static int[] random;
public static int randomIndex;
public static float[] sin;
public static float[] cos;
public static int[][] colorTable, colorTableTemp;
public static float[] intensityTable;
public static int[][] size;
public static byte[][] cloakTextures;
public static String imageFolder = "../images/";
public static void makeData(){
//Make random number table
random = new int[1024];
for(int i = 0; i < 1024; i ++){
random[i] = (int)(Math.random()*1024);
}
//Make sin and cos look up tables
sin = new float[361];
cos = new float[361];
for(int i = 0; i < 361; i ++){
sin[i] = (float)Math.sin(Math.PI*i/180);
cos[i] = (float)Math.cos(Math.PI*i/180);
}
//make color palette.
//The main color palette has 32768 (15bits) different colors with 128 different intensity levels,
//the default intensity is at level 31 .
if(colorTable == null)
colorTable = new int[128][32768];
if(colorTableTemp == null)
colorTableTemp = new int[32768][128];
intensityTable = new float[128];
double r, g, b, dr, dg, db;
int r_, g_, b_;
for(int i = 0; i < 32768; i++){
r = (double)((i & 31744) >> 10)*8;
g = (double)((i & 992) >> 5)*8;
b = (double)((i & 31))*8;
dr = r*0.75/64;
dg = g*0.75/64;
db = b*0.75/64;
//calculated the intensity from lvl 0 ~ 63
for(int j = 0; j < 64; j++){
r_ = (int)(r-dr*j);
g_ = (int)(g-dg*j);
b_ = (int)(b-db*j);
colorTableTemp[i][63 - j] = b_ + (g_<<8)+ (r_<<16);
intensityTable[63 - j] = 1 - (0.75f/64)*j;
}
dr = r*0.75/64;
dg = g*0.75/64;
db = b*0.75/64;
double d = (dr + dg + db)/3;
//calculated the intensity from lvl 64 ~ 127
for(int j = 1; j <= 64; j++){
r_ = (int)(r+d*j);
g_ = (int)(g+d*j);
b_ = (int)(b+d*j);
if(r_ > 255)
r_ = 255;
if(g_ > 255)
g_ = 255;
if(b_ > 255)
b_ = 255;
colorTableTemp[i][63 + j] = b_ + (g_<<8)+ (r_<<16);
intensityTable[63 + j] = 1 + (0.75f/64)*j;
}
}
for(int i = 0; i < 128; i++){
for(int j = 0; j <32768; j++ )
colorTable[i][j] = colorTableTemp[j][i];
}
//free memory used for creating color table
colorTableTemp = null;
//create particle bitmap
size = new int[9][];
size[0] = new int[]{0,-1, -768};
size[1] = new int[]{-769,0,-1, -768};
size[2] = new int[]{1, 0,-1, -768,768};
size[3] = new int[]{-769,-767,1, 0,-1, -768,768};
size[4] = new int[]{-769,-767,1, 0,-1, -768,768, 767, 769};
size[5] = new int[]{-1536, -1537, -770,-769,-768, -767, -2, -1, 0, 1, 767, 768};
size[6] = new int[]{-1537, -1535, -770,-766,766, 770,1535, 1537,-1536,-769,-2,-767,1, 2, 0,-1, -768,768, 767, 769, 1536};
size[7] = new int[]{-1534, -1538, 1538, 1534, -2304, 2304, -3, 3, -1537, -1535, -770,-766,766, 770,1535, 1537,-1536,-769,-2,-767,1, 2, 0,-1, -768,768, 767, 769, 1536};
size[8] = new int[]{0};
//create cloack textures
cloakTextures= new byte[120][64*64];
int[] buffer = new int[64*64];
loadTexture("69.jpg", buffer, cloakTextures[0], 64, 64);
loadTexture("70.jpg", buffer, cloakTextures[40], 64, 64);
loadTexture("71.jpg", buffer, cloakTextures[80], 64, 64);
for(int i = 1; i < 40; i++){
for(int j = 0; j < 64*64; j++){
cloakTextures[i][j] = (byte)(cloakTextures[0][j] + (cloakTextures[40][j] - cloakTextures[0][j])* i / 40);
cloakTextures[40 + i][j] = (byte)(cloakTextures[40][j] + (cloakTextures[80][j] - cloakTextures[40][j])* i / 40);
cloakTextures[80 + i][j] = (byte)(cloakTextures[80][j] + (cloakTextures[0][j] - cloakTextures[80][j])* i / 40);
}
}
System.gc();
}
//get a random number
public static int getRandom(){
randomIndex++;
if(randomIndex >= 1024)
randomIndex=0;
return random[randomIndex];
}
//It frees the data stored when the applet is finished
public static void destory(){
random = null;
sin = null;
cos = null;
colorTable = null;
}
public static void loadTexture(String imgName, int[] buffer, byte[] dest, int width, int height){
Image img = null;
try{
img = ImageIO.read(gameData.class.getResource(imageFolder + imgName));
}catch(Exception e){
e.printStackTrace();
}
PixelGrabber pg = new PixelGrabber(img, 0, 0, width, height, buffer, 0, width);
try {
pg.grabPixels();
}catch(Exception e){
e.printStackTrace();
}
for(int i = 0; i < buffer.length; i++){
dest[i] = (byte)((buffer[i]&255)/2);
}
}
}

205
core/geometry.java Normal file
View File

@ -0,0 +1,205 @@
package core;
//determine the drawing orders for polygons and models
public class geometry {
public static vector temp = new vector(0,0,0);
public static vector temp1 = new vector(0,0,0);
public static vector temp2 = new vector(0,0,0);
//solutions for liner equation
// a1 * X + b1 * Y = c1
// a2 * X + b2 * Y = c2
public static float X, Y;
//solve liner equation with 2 variables
public static void solveLinerEquation2D(float a1, float a2, float b1, float b2, float c1, float c2){
if(a1 != 0){
Y = (c2 - a2*c1/a1)/(b2 - a2*b1/a1);
X = (c1 - b1*Y)/a1;
}else{
float a, b, c;
a = a1;
a1 = a2;
a2 = a;
b = b1;
b1 = b2;
b2 = b;
c = c1;
c1 = c2;
c2 = c;
Y = (c2 - a2*c1/a1)/(b2 - a2*b1/a1);
X = (c1 - b1*Y)/a1;
}
}
//find angle between 2 point with respect to the positive y axis
public static int findAngle(float x0, float y0, float x1, float y1){
return (int)(Math.atan2(-(x1 - x0), -(y1 - y0))/Math.PI * 180) + 180;
}
//find the direction of rotation between 2 angles
public static int findAngleDelta(int start, int finish,int maxTurnRate){
int difference = finish - start;
if(difference < 0){
if(difference < -180){
if(difference < -360 + maxTurnRate)
return 360 + difference;
else
return maxTurnRate;
}else{
if(difference > -maxTurnRate)
return difference;
else
return -maxTurnRate;
}
}else{
if(difference > 180){
if(difference > 360 - maxTurnRate)
return difference - 360;
else
return -maxTurnRate;
}else{
if(difference < maxTurnRate)
return difference;
else
return maxTurnRate;
}
}
}
//draw dot line
public static void drawLine(vector startPoint, vector endPoint, int color, byte shadowBit){
int[] screen = mainThread.screen;
temp1.set(startPoint);
temp1.y = -0.5f;
temp1.x -= 0.07f;
temp1.subtract(camera.position);
temp1.rotate_XZ(camera.XZ_angle);
temp1.rotate_YZ(camera.YZ_angle);
temp2.set(endPoint);
temp2.y = -0.5f;
temp2.subtract(camera.position);
temp2.rotate_XZ(camera.XZ_angle);
temp2.rotate_YZ(camera.YZ_angle);
if(temp1.z < 1f && temp2.z < 1f)
return;
if(temp1.z < 1f){
float f = (temp2.z - 1)/(temp2.z - temp1.z);
temp.set(temp1);
temp.subtract(temp2);
temp.scale(f);
temp1.set(temp2);
temp1.add(temp);
}
temp1.updateLocation();
if(temp2.z < 1f){
float f = (temp1.z - 1)/(temp1.z - temp2.z);
temp.set(temp2);
temp.subtract(temp1);
temp.scale(f);
temp2.set(temp1);
temp2.add(temp);
}
temp2.updateLocation();
int xPos1 = (int)temp1.screenX;
int yPos1 = (int)temp1.screenY;
int xPos2 = (int)temp2.screenX;
int yPos2 = (int)temp2.screenY;
int start = 0;
int x, y;
int xDirection, yDirection;
if(xPos1 < xPos2)
xDirection = 1;
else
xDirection = -1;
if(yPos1 < yPos2)
yDirection = 1;
else
yDirection = -1;
if(Math.abs(xPos2 - xPos1) > Math.abs(yPos2 - yPos1)){
float slope = (float)(yPos2 - yPos1)/(xPos2 - xPos1);
for(int i = 0; i <= Math.abs(xPos2 - xPos1); i ++){
x = xPos1 + i*xDirection;
y = (int)(yPos1 + slope*i*xDirection);
if(x <0 || x > 767 || y < 0 || y > 511)
continue;
screen[start + x + y*768] = color;
mainThread.shadowBitmap[start + x + y*768] = shadowBit;
}
}else{
float slope = (float)(xPos2 - xPos1)/(yPos2 - yPos1);
for(int i = 0; i <= Math.abs(yPos2 - yPos1); i ++){
y = yPos1 + i*yDirection;
x = (int)(xPos1 + slope*i*yDirection);
if(x <0 || x > 767 || y < 0 || y > 511)
continue;
screen[start + x + y*768] = color;
mainThread.shadowBitmap[start + x + y*768] = shadowBit;
}
}
int index;
for(int j = 0; j < 5; j++){
for(int k = 0; k < 5; k++){
int xPos = xPos2 - 2 + k;
int yPos = yPos2 - 2 + j;
if(xPos < 0 || xPos > 767 || yPos < 0 || yPos > 511)
continue;
index = xPos + yPos*768;
if(index >= 0 && index < 512*768){
screen[index] = color;
mainThread.shadowBitmap[index] = shadowBit;
}
}
}
}
}

60
core/grid.java Normal file
View File

@ -0,0 +1,60 @@
package core;
import entity.*;
public class grid {
public int size;
public solidObject[][] tiles; //a list of colliable objects, used by local path finding
public boolean[] previousObstacleMap, currentObstacleMap; //a boolean representation of the collideble objects, used by A star
public grid(int size){
this.size = size;
tiles = new solidObject[size * size][5];
previousObstacleMap = new boolean[size * size];
currentObstacleMap = new boolean[size * size];
for(int i = 0; i < size * size; i++){
previousObstacleMap[i] = true;
currentObstacleMap[i] = true;
}
}
public void update(){
int l = size * size;
for(int i = 0; i < l; i++){
previousObstacleMap[i] = currentObstacleMap[i];
currentObstacleMap[i] = true;
}
for(int i = 0; i < size; i++){
currentObstacleMap[i] = false;
currentObstacleMap[l - 1 - i] = false;
currentObstacleMap[i * 128] = false;
currentObstacleMap[(i+1) * 128 - 1] = false;
}
}
public void draw(){
int pos = 2 + 20 * 768;
boolean tile;
int[] screen = mainThread.screen2;
for(int i = 0; i < 128; i++){
for(int j = 0; j < 128; j++){
tile = previousObstacleMap[j + i*128];
if(!tile)
screen[pos + j + i*768] = 0;
}
}
}
}

526
core/mainThread.java Normal file
View File

@ -0,0 +1,526 @@
package core;
//Java real time strategy
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import enemyAI.*;
import gui.*;
public class mainThread extends JFrame implements KeyListener, ActionListener, MouseMotionListener, MouseListener, FocusListener{
public static int[] screen;
public static int[] screen2;
public static int[] zBuffer;
public static int[] zBuffer2;
public static BufferedImage doubleBuffer;
public static BufferedImage doubleBuffer2;
public static BufferedImage bf;
public static Ticker t;
public static int frameInterval;
public static int frameIndex;
public static long lastDraw;
public static int sleepTime;
public static int framePerSecond, cpuUsage;
public static double thisTime, lastTime;
public static boolean JavaRTSLoaded;
public static boolean inGame;
public static texture[] textures;
public static byte[][] lightMapTextures;
public static int[][] lightMapTexturesInfo;
public static camera Camera;
public static playerCommander pc;
public static enemyCommander ec;
public static AssetManager theAssetManager;
public static grid gridMap;
public static postProcessingThread PPT;
public static Object PPT_Lock;
public static JPanel panel;
public static Turn2DTo3DFactory my2Dto3DFactory;
public static byte[] shadowBitmap;
public static byte[] shadowBitmap2;
public static short[] displacementBuffer;
public static short[] displacementBuffer2;
public mainThread(){
setTitle("JAVA RTS");
panel= (JPanel) this.getContentPane();
panel.setPreferredSize(new Dimension(768, 512));
panel.setMinimumSize(new Dimension(768,512));
panel.setLayout(null);
setResizable(false);
pack();
setVisible(true);
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
setLocation(dim.width/2-this.getSize().width/2, dim.height/2-this.getSize().height/2);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//load resource if the applet is loaded for the first time. (i.e refresh browser will not cause the applet to load resources again)
if(JavaRTSLoaded == false){
//create screen buffer
doubleBuffer = new BufferedImage(768, 512, BufferedImage.TYPE_INT_RGB);
DataBuffer dest = doubleBuffer.getRaster().getDataBuffer();
screen = ((DataBufferInt)dest).getData();
doubleBuffer2 = new BufferedImage(768, 512, BufferedImage.TYPE_INT_RGB);
DataBuffer dest2 = doubleBuffer2.getRaster().getDataBuffer();
screen2 = ((DataBufferInt)dest2).getData();
//create depth buffer
zBuffer = new int[393216];
zBuffer2 = new int[393216];
//create shadoow bitmap
shadowBitmap = new byte[393216];
shadowBitmap2 = new byte[393216];
for(int i = 0; i < 393216; i++){
shadowBitmap[i] = 127;
shadowBitmap2[i] = 127;
}
//create displacement buffer
displacementBuffer = new short[393216];
displacementBuffer2 = new short[393216];
for(int i = 0; i < 393216; i++){
displacementBuffer[i] = 12345;
}
//create camera
Camera = new camera(new vector(3,2f,-1.25f), 0, 300);
//Create look up tables
gameData.makeData();
//init grid
gridMap = new grid(128);
//init light source
sunLight.init();
//init rasterizer
rasterizer.init();
//init 2d to 3d factory
my2Dto3DFactory = new Turn2DTo3DFactory();
my2Dto3DFactory.init();
loadTexture();
//init post processing thread
postProcessingThread.init();
theAssetManager = new AssetManager();
theAssetManager.init();
frameIndex = 0;
frameInterval = 33;
lastDraw = 0;
JavaRTSLoaded = true;
//test only
inGame = true;
}
//Add key handler
panel.addKeyListener(this);
panel.addMouseMotionListener(this);
panel.addMouseListener(this);
panel.addFocusListener(this);
panel.requestFocus();
//create main thread
t = new Ticker(0);
t.addActionListener(this);
//create a daemon thread which will sleep for the duration of the game
Thread dt = new Thread(new DaemonThread() );
dt.setDaemon(true);
//create another thread to create post processing effects
PPT_Lock = new Object();
PPT = new postProcessingThread();
Thread theTread = new Thread(PPT);
//start threads
t.start();
dt.start();
theTread.start();
}
//This method is called every time the ticker ticks. To take advantage of modern multicore cpu,
//The graphic engine does polygon rasterization on the main thread and post processing stuff (explosion,
//smokes, user interface etc...) on a second thread. One draw back is that the post processing
//thread is always lag the main thread by 1 frame. However it is barely noticeable.
public void actionPerformed(ActionEvent e){
frameIndex++;
inputHandler.processInput();
//handle user's interaction with game GUI
if(frameIndex == 1){
theAssetManager.prepareAssetForNewGame();
}
gridMap.update();
//Clears the z-buffer. All depth values are set to 0.
clearDepthBuffer();
//update camera
Camera.update();
//update light source
sunLight.update();
//update and draw 3D mashes from game objects
theAssetManager.updateAndDraw();
pc.update();
ec.update();
//gridMap.draw();
if(this.getGraphics() != null && PPT!= null){
//wait for the Post processing Thread if it is still working
waitForPostProcessingThread();
//prepare resources for the post processing thread
postProcessingThread.prepareResources();
//Signal post processing thread that it can proceed
synchronized(PPT) {
PPT.notify();
}
if(frameIndex %2 == 0 && frameIndex > 3){
bf = doubleBuffer;
paintComponent(panel.getGraphics());
}else if(frameIndex != 1 && frameIndex > 3){
bf = doubleBuffer2;
paintComponent(panel.getGraphics());
}
swapResources();
//maintain a constant frame rate
regulateFramerate();
}else{
System.exit(-1);
}
}
public void paintComponent(Graphics g){
//copy the pixel information to the video memory
Graphics2D g2 =(Graphics2D)bf.getGraphics(); //(Graphics2D)g;
//display polygon count and frame rate
g2.setColor(Color.WHITE);
g2.drawString("FPS: " + framePerSecond + " " + "Polygons: " + theAssetManager.polygonCount + " " + "Thread1 Sleep: " + sleepTime + "ms " + "Thread2 Sleep: " + postProcessingThread.sleepTime + "ms " , 5, 15);
//copy the screen buffer to video memory
g.drawImage(bf, 0, 0, this);
}
public void clearDepthBuffer(){
zBuffer[0] = 0;
for(int i = 1; i < 393216; i+=i)
System.arraycopy(zBuffer, 0, zBuffer, i, 393216 - i >= i ? i : 393216 - i);
}
//read keyboard inputs
public void keyPressed(KeyEvent e){
if(e.getKeyCode() == KeyEvent.VK_LEFT)
inputHandler.leftKeyPressed = true;
else if(e.getKeyCode() == KeyEvent.VK_RIGHT)
inputHandler.rightKeyPressed = true;
else if(e.getKeyCode() == KeyEvent.VK_CONTROL)
inputHandler.controlKeyPressed = true;
inputHandler.readCharacter(e.getKeyChar());
}
public void keyReleased(KeyEvent e){
if(e.getKeyCode() == KeyEvent.VK_LEFT)
inputHandler.leftKeyPressed = false;
else if(e.getKeyCode() == KeyEvent.VK_RIGHT)
inputHandler.rightKeyPressed = false;
else if(e.getKeyCode() == KeyEvent.VK_CONTROL)
inputHandler.controlKeyPressed = false;
inputHandler.handleKeyRelease(e.getKeyChar());
}
public void keyTyped(KeyEvent e) {
}
public void mouseDragged(MouseEvent e) {
inputHandler.mouse_x = e.getX();
inputHandler.mouse_y = e.getY();
}
public void mouseMoved(MouseEvent e) {
inputHandler.mouse_x = e.getX();
inputHandler.mouse_y = e.getY();
}
@Override
public void mouseClicked(MouseEvent arg0) {}
@Override
public void mouseEntered(MouseEvent arg0) {
inputHandler.mouseIsInsideScreen = true;
}
@Override
public void mouseExited(MouseEvent arg0) {
inputHandler.mouseIsInsideScreen = false;
}
@Override
public void mousePressed(MouseEvent e) {
if(e.getButton() == 1){
inputHandler.leftMouseButtonPressed = true;
}
if(e.getButton() == 3){
inputHandler.rightMouseButtonPressed = true;
}
}
@Override
public void mouseReleased(MouseEvent e) {
if(e.getButton() == 1){
inputHandler.leftMouseButtonReleased = true;
}
if(e.getButton() == 3){
inputHandler.rightMouseButtonReleased = true;
}
}
public void loadTexture(){
textures = new texture[73];
String imageFolder = "../images/";
try{
textures[0] = new texture("basic", ImageIO.read(getClass().getResource(imageFolder + "1.jpg")), 9, 9);
textures[1] = new texture("explosion aura", ImageIO.read(getClass().getResource(imageFolder + "2.jpg")), 7, 7);
textures[2] = new texture("basic", ImageIO.read(getClass().getResource(imageFolder + "3.jpg")), 6, 6);
textures[3] = new texture("basic", ImageIO.read(getClass().getResource(imageFolder + "4.jpg")), 8, 6);
textures[4] = new texture("basic", ImageIO.read(getClass().getResource(imageFolder + "5.jpg")), 7, 7);
textures[5] = new texture("basic", ImageIO.read(getClass().getResource(imageFolder + "6.jpg")), 5, 7);
textures[6] = new texture("explosion", ImageIO.read(getClass().getResource(imageFolder + "7.jpg")), 8, 8);
textures[7] = new texture("explosion", ImageIO.read(getClass().getResource(imageFolder + "8.jpg")), 8, 8);
textures[8] = new texture("explosion", ImageIO.read(getClass().getResource(imageFolder + "9.jpg")), 8, 8);
textures[9] = new texture("explosion", ImageIO.read(getClass().getResource(imageFolder + "10.jpg")), 8, 8);
textures[10] = new texture("basic", ImageIO.read(getClass().getResource(imageFolder + "12.jpg")), 6, 6);
textures[11] = new texture("smoke", ImageIO.read(getClass().getResource(imageFolder + "11.jpg")), 9, 9);
textures[12] = new texture("basic", ImageIO.read(getClass().getResource(imageFolder + "13.jpg")), 7, 7);
textures[13] = new texture("basic", ImageIO.read(getClass().getResource(imageFolder + "14.jpg")), 7, 7);
textures[14] = new texture("basic", ImageIO.read(getClass().getResource(imageFolder + "15.jpg")), 5, 5);
textures[15] = new texture("basic", ImageIO.read(getClass().getResource(imageFolder + "16.jpg")), 5, 5);
textures[16] = new texture("basic", ImageIO.read(getClass().getResource(imageFolder + "17.jpg")), 5, 5);
textures[17] = new texture("basic", ImageIO.read(getClass().getResource(imageFolder + "18.jpg")), 7, 7);
textures[18] = new texture("basic", ImageIO.read(getClass().getResource(imageFolder + "19.jpg")), 6, 6);
textures[19] = new texture("basic", ImageIO.read(getClass().getResource(imageFolder + "20.jpg")), 6, 6);
textures[20] = new texture("basic", ImageIO.read(getClass().getResource(imageFolder + "21.jpg")), 6, 6);
textures[21] = new texture("basic", ImageIO.read(getClass().getResource(imageFolder + "22.jpg")), 6, 6);
textures[22] = new texture("basic", ImageIO.read(getClass().getResource(imageFolder + "23.jpg")), 6, 6);
textures[23] = new texture("basic", ImageIO.read(getClass().getResource(imageFolder + "25.jpg")), 6, 6);
textures[24] = new texture("basic", ImageIO.read(getClass().getResource(imageFolder + "24.jpg")), 5, 5);
textures[25] = new texture("solid color", 160 << 16 | 160 << 8 | 160, 5, 5);
textures[26] = new texture("solid color", 80 << 16 | 80 << 8 | 80, 5, 5);
textures[27] = new texture("basic", ImageIO.read(getClass().getResource(imageFolder + "26.jpg")), 5, 5);
textures[28] = new texture("solid color", 173 << 16 | 161 << 8 | 89, 5, 5);
textures[29] = new texture("solid color", 200 << 16 | 200 << 8 | 200, 5, 5);
textures[30] = new texture("basic", ImageIO.read(getClass().getResource(imageFolder + "27.jpg")), 8, 8);
textures[31] = new texture("basic", ImageIO.read(getClass().getResource(imageFolder + "28.jpg")), 6, 6);
textures[32] = new texture("basic", ImageIO.read(getClass().getResource(imageFolder + "29.jpg")), 6, 6);
textures[33] = new texture("solid color", 130 << 16 | 130 << 8 | 130, 5, 5);
textures[34] = new texture("basic", ImageIO.read(getClass().getResource(imageFolder + "30.jpg")), 7, 7);
textures[35] = new texture("basic", ImageIO.read(getClass().getResource(imageFolder + "31.jpg")), 7, 7);
textures[36] = new texture("basic", ImageIO.read(getClass().getResource(imageFolder + "32.jpg")), 7, 7);
textures[37] = new texture("basic", ImageIO.read(getClass().getResource(imageFolder + "33.jpg")), 7, 7);
textures[38] = new texture("heightmap", ImageIO.read(getClass().getResource(imageFolder + "34.jpg")), 8, 8);
textures[39] = new texture("basic", ImageIO.read(getClass().getResource(imageFolder + "35.jpg")), 8, 8);
textures[40] = new texture("basic", ImageIO.read(getClass().getResource(imageFolder + "36.jpg")), 7, 7);
textures[41] = new texture("basic", ImageIO.read(getClass().getResource(imageFolder + "37.jpg")), 8, 8);
textures[42] = new texture("basic", ImageIO.read(getClass().getResource(imageFolder + "38.jpg")), 6, 6);
textures[43] = new texture("basic", ImageIO.read(getClass().getResource(imageFolder + "39.jpg")), 6, 6);
textures[44] = new texture("basic", ImageIO.read(getClass().getResource(imageFolder + "40.jpg")), 5, 5);
textures[45] = new texture("solid color", 0 << 16 | 131 << 8 | 243, 5, 5);
textures[46] = new texture("basic", ImageIO.read(getClass().getResource(imageFolder + "41.jpg")), 5, 5);
textures[47] = new texture("solid color", 50 << 16 | 50 << 8 | 50, 5, 5);
textures[48] = new texture("solid color", 149 << 16 | 137 << 8 | 97, 5, 5);
textures[49] = new texture("basic", ImageIO.read(getClass().getResource(imageFolder + "42.jpg")), 6, 6);
textures[50] = new texture("basic", ImageIO.read(getClass().getResource(imageFolder + "43.jpg")), 5, 5);
textures[51] = new texture("basic", ImageIO.read(getClass().getResource(imageFolder + "45.jpg")), 8, 8);
textures[52] = new texture("basic", ImageIO.read(getClass().getResource(imageFolder + "46.jpg")), 7, 7);
textures[53] = new texture("solid color", 179 << 16 | 0 << 8 | 0, 5, 5);
textures[54] = new texture("water", ImageIO.read(getClass().getResource(imageFolder + "51.jpg")), ImageIO.read(getClass().getResource(imageFolder + "90.jpg")), 8, 8);
textures[55] = new texture("heightmap", ImageIO.read(getClass().getResource(imageFolder + "52.jpg")), 8, 8);
textures[56] = new texture("basic", ImageIO.read(getClass().getResource(imageFolder + "53.jpg")), 7, 7);
textures[57] = new texture("heightmap", ImageIO.read(getClass().getResource(imageFolder + "54.jpg")), 8, 8);
textures[58] = new texture("heightmap", ImageIO.read(getClass().getResource(imageFolder + "55.jpg")), 8, 8);
textures[59] = new texture("heightmap", ImageIO.read(getClass().getResource(imageFolder + "56.jpg")), 8, 8);
textures[60] = new texture("basic", ImageIO.read(getClass().getResource(imageFolder + "61.jpg")), 4, 7);
textures[61] = new texture("basic", ImageIO.read(getClass().getResource(imageFolder + "62.jpg")), 7, 7);
textures[62] = new texture("basic", ImageIO.read(getClass().getResource(imageFolder + "63.jpg")), 7, 7);
textures[63] = new texture("basic", ImageIO.read(getClass().getResource(imageFolder + "64.jpg")), 5, 7);
textures[64] = new texture("solid color", 56 << 16 |79 << 8 | 167, 5, 5);
textures[65] = new texture("basic", ImageIO.read(getClass().getResource(imageFolder + "68.jpg")), 8, 8);
textures[66] = new texture("basic", ImageIO.read(getClass().getResource(imageFolder + "73.jpg")), 6, 6);
textures[67] = new texture("basic", ImageIO.read(getClass().getResource(imageFolder + "74.jpg")), 6, 6);
textures[68] = new texture("solid color", 255 << 16 | 255 << 8 | 255, 5, 5);
textures[69] = new texture("solid color", 255 << 16 | 0 << 8 | 0, 5, 5);
textures[70] = new texture("basic", ImageIO.read(getClass().getResource(imageFolder + "80.jpg")), 5, 5);
textures[71] = new texture("basic", ImageIO.read(getClass().getResource(imageFolder + "82.jpg")), 6, 6);
textures[72] = new texture("solid color", 120 << 16 | 120 << 8 | 100, 5, 5);
for(int i = 0; i < textures.length; i++)
textures[i].ID = i;
}catch(Exception e){
e.printStackTrace();
}
}
public void waitForPostProcessingThread(){
//wait till post processing thread finishes
synchronized(PPT_Lock) {
while(PPT.isWorking()){
try {
PPT_Lock.wait();
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
}
public void swapResources(){
int[] s;
s = screen;
screen = screen2;
screen2 = s;
int[] buffer;
buffer = zBuffer;
zBuffer = zBuffer2;
zBuffer2 = buffer;
byte[] b;
b = shadowBitmap;
shadowBitmap = shadowBitmap2;
shadowBitmap2 = b;
short[] Dbuffer;
Dbuffer = displacementBuffer;
displacementBuffer = displacementBuffer2;
displacementBuffer2 = Dbuffer;
rasterizer.screen = mainThread.screen;
rasterizer.shadowBitmap = mainThread.shadowBitmap;
rasterizer.zBuffer = mainThread.zBuffer;
rasterizer.displacementBuffer = mainThread.displacementBuffer;
theAssetManager.swapResources();
pc.theSideBarManager.swapResources();
}
public void regulateFramerate(){
if(frameIndex%30==0){
double thisTime = System.currentTimeMillis();
framePerSecond = (int)(1000/((thisTime - lastTime)/30));
lastTime = thisTime;
}
sleepTime = 0;
while(System.currentTimeMillis()-lastDraw<frameInterval){
try {
Thread.sleep(1);
sleepTime++;
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
lastDraw=System.currentTimeMillis();
}
@Override
public void focusGained(FocusEvent arg0) {
// TODO Auto-generated method stub
}
@Override
public void focusLost(FocusEvent arg0) {
// TODO Auto-generated method stub
}
}

544
core/polygon3D.java Normal file
View File

@ -0,0 +1,544 @@
package core;
import entity.solidObject;
public class polygon3D {
//The vertex of the polygon with the respect of the world/camera coordinate
public vector[] vertex3D, tempVertex;
//The vertex of the polygon after clipping
public vector[] vertex2D;
//the normal of the polygon with the respect of the world/camera coordinate
public vector normal;
//the centre of the polygon with the respect of the world/camera coordinate
public vector centre;
//The number of vertex
public int L;
//whether the polygon is completely bounded by the screen
public boolean withinViewScreen;
//These 3 vectors map the 3 corners of the texture to the world coordinate
public vector origin, rightEnd, bottomEnd;
//texture that is bind to the polygon
public texture myTexture;
//only need to shade if the current fragment's depth in light space is far enough from the lightmap value
//the threshold value is related to the orientation of the polygon in light space
//if the normal of the polygon is almost perpendicular to the light direction, then we need a bigger threshold
//to avoid shadow acne
public int shadowBias;
//Information about the texture
public int heightMask, widthMask, widthBits, heightBits;
public float textureWidth, textureHeight;
public float textureWidthInverse, textureHeightInverse;
//The size of one texel
public float textureScaleX, textureScaleY;
//the number of times texture repeats itself along the polygon
public float scaleX, scaleY;
//the 3D object which this polygon belongs to
public solidObject parentObject;
//A pool of vectors which will be used for vector arithmetic
public vector
tempVector1 = new vector(0,0,0),
tempVector2 = new vector(0,0,0),
tempVector3 = new vector(0,0,0),
tempVector4 = new vector(0,0,0),
tempVector5 = new vector(0,0,0),
tempVector6 = new vector(0,0,0);
//whether the polygon is visible
public boolean visible;
//whether the polygon is visible in light space
public boolean visibleInLightSpace;
//number of vertices are behind of the clip plane
public int numberOfVerticesBehindClipPlane;
//the amount of vertex after clipping
public int visibleCount;
//type of the polygon
public int type;
//the diffuse/ambient intensity of this polygon
public int diffuse_I;
public int Ambient_I = 16; //the default ambient intensity is 16
public int reflectance = 96;
//diffuse value at vertex (only for polygons with 3 vertex)
public byte[] diffuse = new byte[3];
//default light source
public vector lightDirection = sunLight.lightDirection;
//the color of polygon if it is defined as soild
public int color;
//light map texture for this polygon
public int lightMapTextureIndex;
//max texel change rate in x direction;
public int max_dx = 512;
//Whether origin, rightEnd and bottomEnd vectors match exactly the corners of the polygon
public boolean textureFitPolygon;
public boolean smoothShading;
public int textureScaledWidth;
public double I_left, I_right, I_difference;
public static boolean recreateTextureCoordinateFlag;
//Constuctor of the polygon class, it will only accept convex polygons
public polygon3D(vector[] vertex3D, vector origin, vector rightEnd, vector bottomEnd, texture myTexture, float scaleX, float scaleY, int type){
this.type = type;
this.vertex3D = vertex3D;
this.myTexture = myTexture;
this.scaleX = scaleX;
this.scaleY = scaleY;
L = vertex3D.length;
diffuse_I = 31;
shadowBias = 30000;
if(recreateTextureCoordinateFlag){
origin = origin.myClone();
rightEnd = rightEnd.myClone();
bottomEnd = bottomEnd.myClone();
}
//test if origin, rightEnd and bottomEnd vectors match exactly the corners of the polygon
for(int i = 0; i < L; i++){
if(vertex3D[i] == origin){
textureFitPolygon = true;
break;
}
textureFitPolygon = false;
}
if(textureFitPolygon){
for(int i = 0; i < L; i++){
if(vertex3D[i] == rightEnd){
textureFitPolygon = true;
break;
}
textureFitPolygon = false;
}
}
if(textureFitPolygon){
for(int i = 0; i < L; i++){
if(vertex3D[i] == bottomEnd){
textureFitPolygon = true;
break;
}
textureFitPolygon = false;
}
}
//set the tempVertex to the vertex3D
tempVertex = new vector[L];
for(int i = 0; i < L; i++){
tempVertex[i] = new vector(0,0,0);
tempVertex[i].set(vertex3D[i]);
}
//find normal vector of the polygon (in world coordinate)
normal = new vector(0,0,0);
findNormal();
//find centre of the polygon (in world coordinate)
centre = new vector(0,0,0);
for(int i = 0; i < tempVertex.length; i++)
centre.add(tempVertex[i]);
centre.scale(1.0f/tempVertex.length);
if(origin != null){
this.origin = origin;
this.rightEnd = rightEnd;
this.bottomEnd = bottomEnd;
}
//get the texture information if the polygon is bonded with a texture
if(myTexture != null){
textureWidth = scaleX* myTexture.width;
textureHeight =scaleY*myTexture.height;
textureWidthInverse = 1f/textureWidth;
textureHeightInverse = 1f/textureHeight;
heightMask = myTexture.heightMask;
widthMask = myTexture.widthMask;
widthBits = myTexture.widthBits;
heightBits = myTexture.heightBits;
textureScaledWidth = (int)(myTexture.width*scaleX);
//find the size of one texel in the world coordinate
tempVector1.set(origin);
tempVector1.subtract(rightEnd);
float l = tempVector1.getLength();
textureScaleX = l/myTexture.width;
tempVector1.set(origin);
tempVector1.subtract(bottomEnd);
l = tempVector1.getLength();
textureScaleY = l/myTexture.height;
textureScaleX = textureScaleX/scaleX;
textureScaleY = textureScaleY/scaleY;
}else{
textureScaleX = 1;
textureScaleY = 1;
}
//init vertex2D, notice that the size of vertex2D is bigger than vertex3D, because after clipping
//it is possilbe to generate one more vertex for the polygon.
vertex2D = new vector[L+1];
for(int i = 0; i < L+1; i++)
vertex2D[i] = new vector(0,0,0);
//find the initial diffuse intensity of this polygon
findDiffuse();
}
//update this polygon based on camera movement in each frame
public void update(){
//back face culling
tempVector1.set(camera.position);
tempVector1.subtract(vertex3D[0]);
if(tempVector1.dot(normal) <= 0){
visible = false;
return;
}
//translate vertex from world space to camera space
float x = 0,y = 0, z = 0,
camX = camera.position.x, camY = camera.position.y, camZ = camera.position.z,
sinXZ = camera.sinXZ_angle,
cosXZ = camera.cosXZ_angle,
sinYZ = camera.sinYZ_angle,
cosYZ = camera.cosYZ_angle;
withinViewScreen = false;
visible = true;
if(parentObject != null){
if(parentObject.withinViewScreen){
for(int i = 0; i < L; i++){
tempVector5 = vertex3D[i];
tempVector6 = vertex2D[i];
//shifting
x = tempVector5.x - camX;
y = tempVector5.y - camY;
z = tempVector5.z - camZ;
//rotating
tempVector6.x = cosXZ*x - sinXZ*z;
tempVector6.z = sinXZ*x + cosXZ*z;
z = tempVector6.z;
tempVector6.y = cosYZ*y - sinYZ*z;
tempVector6.z = sinYZ*y + cosYZ*z;
tempVector6.updateLocation();
}
withinViewScreen = true;
visible = true;
visibleCount = L;
return;
}
}
for(int i = 0; i < L; i++){
//shifting
x = vertex3D[i].x - camX;
y = vertex3D[i].y - camY;
z = vertex3D[i].z - camZ;
//rotating
tempVertex[i].x = cosXZ*x - sinXZ*z;
tempVertex[i].z = sinXZ*x + cosXZ*z;
z = tempVertex[i].z;
tempVertex[i].y = cosYZ*y - sinYZ*z;
tempVertex[i].z = sinYZ*y + cosYZ*z;
}
//find the number of vertices that are behind clip plane
numberOfVerticesBehindClipPlane = 0;
for(int i = 0; i < L; i++){
if(tempVertex[i].z <= 0.1){
numberOfVerticesBehindClipPlane++;
}
}
//if all vertices
if(numberOfVerticesBehindClipPlane == L){
visible = false;
return;
}
findClipping();
}
//update vision polygon
public void update_visionPolygon(){
vector cameraPosition = postProcessingThread.cameraPosition;
//translate vertex from world space to camera space
float x = 0,y = 0, z = 0,
camX = cameraPosition.x, camY = cameraPosition.y, camZ = cameraPosition.z,
sinXZ = postProcessingThread.sinXZ,
cosXZ = postProcessingThread.cosXZ,
sinYZ = postProcessingThread.sinYZ,
cosYZ = postProcessingThread.cosYZ;
for(int i = 0; i < L; i++){
//shifting
x = vertex3D[i].x - camX;
y = vertex3D[i].y - camY;
z = vertex3D[i].z - camZ;
//rotating
vertex2D[i].x = cosXZ*x - sinXZ*z;
vertex2D[i].z = sinXZ*x + cosXZ*z;
z = vertex2D[i].z;
vertex2D[i].y = cosYZ*y - sinYZ*z;
vertex2D[i].z = sinYZ*y + cosYZ*z;
if(vertex2D[i].z < 0.01)
vertex2D[i].z = 0.01f;
vertex2D[i].updateLocation();
}
visible = true;
visibleCount = L;
return;
}
//update the polygon in light space
public void update_lightspace(){
//back face culling
visibleInLightSpace = true;
float normalDotLight = normal.dot(sunLight.lightDirection);
if(normalDotLight >= 0){
visibleInLightSpace = false;
return;
}
//translate vertex from world space to light space
float x = 0,y = 0, z = 0,
sunX = sunLight.position.x, sunY = sunLight.position.y, sunZ = sunLight.position.z,
sinXZ = sunLight.sinXZ_angle,
cosXZ = sunLight.cosXZ_angle,
sinYZ = sunLight.sinYZ_angle,
cosYZ = sunLight.cosYZ_angle;
for(int i = 0; i < L; i++){
tempVector5 = vertex3D[i];
tempVector6 = vertex2D[i];
//shifting
x = tempVector5.x - sunX;
y = tempVector5.y - sunY;
z = tempVector5.z - sunZ;
//rotating
tempVector6.x = cosXZ*x - sinXZ*z;
tempVector6.z = sinXZ*x + cosXZ*z;
z = tempVector6.z;
tempVector6.y = cosYZ*y - sinYZ*z;
tempVector6.z = sinYZ*y + cosYZ*z;
tempVector6.updateLocationOrthognal();
tempVector6.z_lightspace = tempVector6.z;
tempVector5.z_lightspace = tempVector6.z;
tempVector5.screenX_lightspace = tempVector6.screenX_lightspace;
tempVector5.screenY_lightspace = tempVector6.screenY_lightspace;
}
if(type == 1){
rasterizer.renderShadow(this);
}else{
if(type == 4)
rasterizer.renderShadowRemover(this);
else if(type == 9)
rasterizer.renderCloakedShadow(this);
}
}
public void update_lightspace_withoutDrawing(){
//back face culling
visibleInLightSpace = true;
if(sunLight.lightDirection.dot(normal) > 0){
visibleInLightSpace = false;
return;
}
//translate vertex from world space to light space
float x = 0,y = 0, z = 0,
sunX = sunLight.position.x, sunY = sunLight.position.y, sunZ = sunLight.position.z,
sinXZ = sunLight.sinXZ_angle,
cosXZ = sunLight.cosXZ_angle,
sinYZ = sunLight.sinYZ_angle,
cosYZ = sunLight.cosYZ_angle;
for(int i = 0; i < L; i++){
//shifting
x = vertex3D[i].x - sunX;
y = vertex3D[i].y - sunY;
z = vertex3D[i].z - sunZ;
//rotating
vertex2D[i].x = cosXZ*x - sinXZ*z;
vertex2D[i].z = sinXZ*x + cosXZ*z;
z = vertex2D[i].z;
vertex2D[i].y = cosYZ*y - sinYZ*z;
vertex2D[i].z = sinYZ*y + cosYZ*z;
vertex2D[i].updateLocationOrthognal();
vertex2D[i].z_lightspace = vertex2D[i].z;
vertex3D[i].z_lightspace = vertex2D[i].z;
vertex3D[i].screenX_lightspace = vertex2D[i].screenX_lightspace;
vertex3D[i].screenY_lightspace = vertex2D[i].screenY_lightspace;
}
}
//clipping
public void findClipping(){
visibleCount = 0;
//the clipping algorithm iterate through all the vertex of the polygons, if it finds
//a vertex which is behind the clipping plane(z = 0.001), then generate 2 new vertex on the
//clipping plane
for(int i = 0; i < L; i++){
if(tempVertex[i].z >= 0.1){
vertex2D[visibleCount].set(tempVertex[i]);
vertex2D[visibleCount].updateLocation();
visibleCount++;
} else{
int index = (i+L - 1)%L;
if(tempVertex[index].z >= 0.1005){
approximatePoint(visibleCount, tempVertex[i], tempVertex[index]);
visibleCount++;
}
index = (i+1)%L;
if(tempVertex[index].z >= 0.1005){
approximatePoint(visibleCount, tempVertex[i], tempVertex[index]);
visibleCount++;
}
}
}
}
//find the approximate projection point on the clipping plane
public void approximatePoint(int index, vector behindPoint, vector frontPoint){
tempVector1.set(frontPoint.x - behindPoint.x, frontPoint.y - behindPoint.y, frontPoint.z - behindPoint.z);
tempVector1.scale((frontPoint.z- 0.1f)/tempVector1.z);
vertex2D[index].set(frontPoint.x, frontPoint.y, frontPoint.z);
vertex2D[index].subtract(tempVector1);
vertex2D[index].updateLocation();
}
//find diffuse intensity of this polygon
public void findDiffuse(){
//calculate the diffuse intensity from the light source
tempVector1.set(-lightDirection.x, -lightDirection.y, -lightDirection.z);
double I = normal.dot(tempVector1);
diffuse_I = Ambient_I + (int)(I*reflectance);
if(I < 0)
diffuse_I = Ambient_I;
}
//create a smooth 1 dimensional shade map for the polygon. Only works if the polygon belongs to a
//cylindrical object.
public void createShadeSpan(vector theCenter, vector v0, vector v1){
smoothShading = true;
tempVector1.set(v0);
tempVector1.subtract(theCenter);
tempVector1.unit();
tempVector2.set(v1);
tempVector2.subtract(theCenter);
tempVector2.unit();
tempVector3.set(-lightDirection.x, -lightDirection.y, -lightDirection.z);
I_left = tempVector1.dot(tempVector3)*reflectance + Ambient_I;
if(I_left < Ambient_I)
I_left = Ambient_I;
I_right = tempVector2.dot(tempVector3)*reflectance + Ambient_I;
if(I_right < Ambient_I)
I_right = Ambient_I;
I_difference = (I_right - I_left)/textureScaledWidth;
}
public void findNormal(){
tempVector1.set(vertex3D[1]);
tempVector1.subtract(vertex3D[0]);
tempVector2.set(vertex3D[2]);
tempVector2.subtract(vertex3D[1]);
normal.cross(tempVector1, tempVector2);
normal.unit();
}
public void draw(){
//send this polygon to rasterizer
if(visible){
mainThread.theAssetManager.polygonCount++;
rasterizer.rasterize(this);
}
}
}

View File

@ -0,0 +1,965 @@
package core;
import entity.*;
import gui.MiniMap;
import gui.SideBar;
import gui.confirmationIcon;
import particles.explosion;
import particles.helix;
import particles.smokeParticle;
//this class handles all the post processing effect
public class postProcessingThread implements Runnable{
public static int[] currentScreen;
public static int[] currentZbuffer;
public static int[][] currentSelectedUnitsInfo;
public static int[][] unitInfoTable;
public static float[][] visionPolygonInfo;
public static float[][] explosionInfo;
public static float[][] helixInfo;
public static int visionPolygonCount;
public static int visibleUnitCount;
public static int explosionCount;
public static int helixCount;
public static boolean[] minimapBitmap;
public static float[][] smokeEmmiterList;
public static int smokeEmmiterCount;
public static int[][] unitsForMiniMap;
public static int unitsForMiniMapCount;
public static MiniMap theMiniMap;
public static SideBar theSideBar;
private boolean isWorking;
public static int sleepTime;
public static byte[] fogOfWarBuffer;
public static byte[] fogOfWarBuffer2;
public static byte[] shadowBitmap;
public static byte[] smoothedShadowBitmap;
public static short[] displacementBuffer;
public static int[] offScreen;
//2 arrays that define the scan lines of the polygon
public static int[] xLeft = new int[512], xRight = new int[512];
public static int[] xMin = new int[512], xMax = new int[512];
public static vector cameraPosition = new vector(0,0,0);
public static float sinXZ,cosXZ,sinYZ,cosYZ ;
public static int cameraXZAngle;
public static Turn2DTo3DFactory my2Dto3DFactory;
public static explosion[] explosions;
public static smokeParticle[] smokeParticles;
public int currentParticleIndex;
public static helix[] railgunHelix;
public int currentHelix;
public static int[] sideBarInfo;
public static confirmationIcon theConfirmationIcon;
public static double[] confirmationIconInfo;
public static textRenderer theTextRenderer;
//A pool of vectors which will be used for vector arithmetic
public static vector
tempVector1 = new vector(0,0,0),
tempVector2 = new vector(0,0,0),
tempVector3 = new vector(0,0,0),
tempVector4 = new vector(0,0,0);
//the polygon that post processing filter is working on
public static polygon3D poly;
//these variables will represent their equivalents in the polygon3D class during rasterization
public static vector[] vertex2D;
//temporary variables that will be used in texture mapping
public static float aDotW, bDotW, cDotW, cDotWInverse, w, textureHeight, textureWidth;
public static int BigX, BigY, d_x, d_y, k, X1, Y1, BigDx, BigDy, dx, dy, dz, X, Y, textureIndex, temp, temp1, temp2, temp3, r,g,b, scale, yOffset, xOffset, x_right, x_left, z_left, z_right, start, end, teamNo, type;
//the amount of vertex after clipping
public static int visibleCount;
//the number of avaliable credit for player commander
public static int playerMoney;
//the power status for player commander
public static int playerPowerStatus;
//frame counter
public static int frameIndex;
public static vector lightReflect;
public static vector eyeDirection;
public static void init(){
//create font bitmaps
theTextRenderer = new textRenderer();
theTextRenderer.init();
fogOfWarBuffer = new byte[512 * 768];
fogOfWarBuffer2 = new byte[512 * 768];
smoothedShadowBitmap = new byte[512 * 768];
offScreen = new int[512*768];
//init minimap hud
theMiniMap = new MiniMap();
theMiniMap.init();
//init sidebar interface
theSideBar = new SideBar();
theSideBar.init();
unitInfoTable = new int[201][4];
// Max health Health_bar Length Health_bar Xpos Health_bar yPos
unitInfoTable[0] = new int[]{lightTank.maxHP, 44, -22, -25};
unitInfoTable[1] = new int[]{rocketTank.maxHP, 44, -22, -36};
unitInfoTable[2] = new int[]{harvester.maxHP, 58, -29, -46};
unitInfoTable[3] = new int[]{constructionVehicle.maxHP, 58, -29, -40};
unitInfoTable[6] = new int[]{stealthTank.maxHP, 44, -22, -30};
unitInfoTable[7] = new int[]{heavyTank.maxHP, 58, -29, -37};
unitInfoTable[101] = new int[]{powerPlant.maxHP, 88, -37, -80};
unitInfoTable[102] = new int[]{refinery.maxHP, 132, -65, -130};
unitInfoTable[103] = new int[]{goldMine.maxHP, 100, -49, -80};
unitInfoTable[104] = new int[]{constructionYard.maxHP, 132, -65, -130};
unitInfoTable[105] = new int[]{factory.maxHP, 132, -65, -130};
unitInfoTable[106] = new int[]{communicationCenter.maxHP, 88, -37, -70};
unitInfoTable[107] = new int[]{techCenter.maxHP, 88, -37, -115};
unitInfoTable[199] = new int[]{missileTurret.maxHP, 44, -22, -20};
unitInfoTable[200] = new int[]{gunTurret.maxHP, 44, -22, -35};
my2Dto3DFactory = new Turn2DTo3DFactory();
my2Dto3DFactory.init();
explosions = new explosion[200];
for(int i = 0; i < 200; i++)
explosions[i] = new explosion();
smokeParticles = new smokeParticle[2000];
for(int i = 0; i < 2000; i++)
smokeParticles[i] = new smokeParticle();
railgunHelix = new helix[1500];
for(int i = 0; i < 1500; i++)
railgunHelix[i] = new helix();
theConfirmationIcon = new confirmationIcon();
frameIndex = 0;
lightReflect = new vector(0,0,0);
eyeDirection = new vector(0,0,0);
}
public void run(){
while(true){
synchronized (this) {
try {
synchronized (mainThread.PPT_Lock) {
mainThread.PPT_Lock.notify();
isWorking = false;
}
long time = System.currentTimeMillis();
wait();
sleepTime = (int)(System.currentTimeMillis() - time);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
isWorking = true;
}
doPostProcesssing();
frameIndex++;
}
}
public boolean isWorking(){
if(isWorking)
return true;
else
return false;
}
public void doPostProcesssing(){
int ObjectType, groupNo, level, maxHealth, healthBarLength, remainingHealth, xPos, yPos, selectAreaWidth, selectAreaHeight, color = 0;
//load explosion animation instances
float[] tempFloat;
for(int i = 0, j = 0; i < 200; i ++){
if(!explosions[i].isInAction){
if(j < explosionCount){
tempFloat = explosionInfo[j];
explosions[i].setActive(tempFloat[0], tempFloat[1], tempFloat[2], tempFloat[3], (int)tempFloat[4], (int)tempFloat[5], (int)tempFloat[6], tempFloat[7]);
j++;
}else {
break;
}
}
}
//sort explosion according to its size
//for(int i = 1; i < 200; i++){
// for(int j = 0; j <200 - i; j++){
// if(explosions[j].size > explosions[j+1].size){
// explosion temp = explosions[j+1];
// explosions[j+1] = explosions[j];
// explosions[j] = temp;
// }
// }
//}
//blur shadow bitmap to create an illusion of antialiased shadow
blurShadow();
//draw explosion animations
for(int i = 0; i < 200; i++)
explosions[i].updateAndDrawExplosionAura();
//blend shadow bitmap with screen buffer
blendShadow();
//apply distortion map
int xMap;
int yMap;
int distortionIndex;
for(int i = 0; i < 393216; i++){
if(displacementBuffer[i] != 31){
xMap = ((displacementBuffer[i]&992) >> 5) - 16;
yMap = (displacementBuffer[i]&31) - 16;
distortionIndex = i + xMap + yMap*768;
if(distortionIndex > 0 && distortionIndex < 393216 ){
if(currentZbuffer[i] - currentZbuffer[distortionIndex] > -1000000)
offScreen[i] = currentScreen[distortionIndex];
else
offScreen[i] = currentScreen[i];
}
}
}
int r1, r2, r3, r4,r5, g1,g2,g3,g4,g5,b1,b2,b3,b4,b5;
int c = (30/2) << 16 | (30)<<8| 31;
lightReflect.set(0,0,1);
lightReflect.rotate_YZ(230);
lightReflect.rotate_XZ(13);
lightReflect.y*=-1;
lightReflect.x*=-1;
lightReflect.set(lightReflect.x, -lightReflect.y, lightReflect.z);
lightReflect.rotate_XZ(camera.XZ_angle);
lightReflect.rotate_YZ(camera.YZ_angle);
int SpriteValue = 0;
int MASK7Bit = 0xFEFEFF;
int overflow = 0;
int pixel = 0;
for(int i = 768; i < 392448; i++){
if(displacementBuffer[i] != 31){
r1 = (offScreen[i + 1]&0xff0000) >> 16;
r2 = (offScreen[i - 767]&0xff0000) >> 16;
r3 = (offScreen[i - 768]&0xff0000) >> 16;
r4 = (offScreen[i - 1]&0xff0000) >> 16;
g1 = (offScreen[i + 1]&0xff00) >> 8;
g2 = (offScreen[i - 767]&0xff00) >> 8;
g3 = (offScreen[i - 768]&0xff00) >> 8;
g4 = (offScreen[i]&0xff00) >> 8;
b1 = (offScreen[i + 1]&0xff);
b2 = (offScreen[i - 767]&0xff);
b3 = (offScreen[i - 768]&0xff);
b4 = (offScreen[i]&0xff);
currentScreen[i] = (((r1 + r2 + r3 + r4)>>3) << 16 | ((g1 + g2 + g3 + g4)>>3) << 8 | ((b1 + b2 + b3 + b4)>>3 )) + c;
yMap = (displacementBuffer[i]&64512) >> 10;
if(yMap > 0){
eyeDirection.set(-i%768+384, -256 + i/768, -650);
eyeDirection.unit();
float I = eyeDirection.dot(lightReflect);
if(I > 0.985){
int I_ = (int)((I-0.985) *24000);
yMap = yMap * I_ /90;
SpriteValue = 0x010101*yMap;
pixel=(SpriteValue&MASK7Bit)+(currentScreen[i]&MASK7Bit);
overflow=pixel&0x1010100;
overflow=overflow-(overflow>>8);
currentScreen[i] = overflow|pixel;
}
}
displacementBuffer[i] = 31;
}else{
}
}
//create helix particles that are spawned by stealth tank's railgun trail.
for(int i = 0; i < helixCount; i++){
tempFloat = helixInfo[i];
railgunHelix[currentHelix].setActive(tempFloat[0], tempFloat[1], tempFloat[2], (int)tempFloat[3]);
currentHelix++;
currentHelix%=1500;
}
//draw helix particles
for(int i = 0; i < 1500; i++){
if(railgunHelix[i].isInAction)
railgunHelix[i].updateAndDraw();
}
//draw explosion sprite
for(int i = 0; i < 200; i++)
explosions[i].drawExplosionSprite();
//create smoke particles
for(int i = 0; i < smokeEmmiterCount; i++){
tempFloat = smokeEmmiterList[i];
smokeParticles[currentParticleIndex].setActive(tempFloat[0], tempFloat[1], tempFloat[2], tempFloat[3], (int)tempFloat[4] , (int)tempFloat[5], tempFloat[6]);
currentParticleIndex++;
currentParticleIndex%=2000;
}
//draw smoke particles
for(int i = 0; i < 2000; i++){
if(smokeParticles[i].isInAction)
smokeParticles[i].updateAndDraw();
}
//draw health bar/Group info/unit level for every selected unit
for(int i = 0; i < 100; i++){
if(currentSelectedUnitsInfo[i][0] != -1){
ObjectType = (currentSelectedUnitsInfo[i][0] & 0xff);
groupNo = ((currentSelectedUnitsInfo[i][0] & 0xff00) >> 8);
level = ((currentSelectedUnitsInfo[i][0] & 0xff0000) >> 16);
maxHealth = unitInfoTable[ObjectType][0];
healthBarLength = unitInfoTable[ObjectType][1];
xPos = currentSelectedUnitsInfo[i][1] + unitInfoTable[ObjectType][2];
yPos = currentSelectedUnitsInfo[i][2] + unitInfoTable[ObjectType][3];
remainingHealth = healthBarLength * currentSelectedUnitsInfo[i][4] / maxHealth;
//draw group info
if(groupNo != 255){
theTextRenderer.drawText_outline(xPos, yPos + 3, ""+(groupNo+1), currentScreen, 0xffffff, 0);
}
if(level != 0){
theTextRenderer.drawStarCharacter(xPos + healthBarLength - 13, yPos + 5, level, currentScreen, 0xffff33, 0);
}
if(remainingHealth <= 2 && remainingHealth != 0)
remainingHealth = 2;
if(ObjectType != 103){
if(yPos > 0 && yPos < 512){
if(xPos >= 0 && xPos < 768)
currentScreen[xPos + yPos*768] = (currentScreen[xPos + yPos*768]&0xFEFEFE)>>1;
for(int j = xPos+1; j < xPos + healthBarLength-1; j++){
if(j < 0 || j >= 768)
continue;
currentScreen[j + yPos*768] = 0;
}
if(xPos + healthBarLength-1 >= 0 && xPos + healthBarLength-1 < 768)
currentScreen[xPos + healthBarLength-1 + yPos*768] = (currentScreen[xPos + healthBarLength-1 + yPos*768]&0xFEFEFE)>>1;
}
if((float)remainingHealth / healthBarLength > 0.5)
color = 0xdd00;
else if((float)remainingHealth / healthBarLength > 0.25)
color = 0xdddd00;
else
color = 0xdd0000;
for(int k = 0; k < 2; k++){
yPos++;
if(yPos > 0 && yPos < 512){
for(int j = xPos; j < xPos + healthBarLength; j++){
if(j < 0 || j >= 768)
continue;
if(j < xPos + remainingHealth)
currentScreen[j + yPos*768] = color;
else
currentScreen[j + yPos*768] = (currentScreen[j + yPos*768]&0xFEFEFE)>>1;
}
if(xPos > 0 && xPos < 768)
currentScreen[xPos + yPos*768] = 0;
if(xPos + healthBarLength -1 >0 && xPos + healthBarLength - 1 < 768)
currentScreen[xPos + healthBarLength -1 + yPos*768] = 0;
}
}
yPos++;
if(yPos > 0 && yPos < 512){
if(xPos >= 0 && xPos < 768)
currentScreen[xPos + yPos*768] = (currentScreen[xPos + yPos*768]&0xFEFEFE)>>1;
for(int j = xPos+1; j < xPos + healthBarLength-1; j++){
if(j < 0 || j >= 768)
continue;
currentScreen[j + yPos*768] = 0;
}
if(xPos + healthBarLength-1 >= 0 && xPos + healthBarLength-1 < 768)
currentScreen[xPos + healthBarLength-1 + yPos*768] = (currentScreen[xPos + healthBarLength-1 + yPos*768]&0xFEFEFE)>>1;
}
}
//draw progress bar if appliable
if(currentSelectedUnitsInfo[i][5] >=0){
int progress = healthBarLength * currentSelectedUnitsInfo[i][5] / 100;
if(yPos > 0 && yPos < 512){
if(xPos >= 0 && xPos < 768)
currentScreen[xPos + yPos*768] = (currentScreen[xPos + yPos*768]&0xFEFEFE)>>1;
for(int j = xPos+1; j < xPos + healthBarLength-1; j++){
if(j < 0 || j >= 768)
continue;
currentScreen[j + yPos*768] = 0;
}
if(xPos + healthBarLength-1 >= 0 && xPos + healthBarLength-1 < 768)
currentScreen[xPos + healthBarLength-1 + yPos*768] = (currentScreen[xPos + healthBarLength-1 + yPos*768]&0xFEFEFE)>>1;
}
color = 0xd0b000;
for(int k = 0; k < 2; k++){
yPos++;
if(yPos > 0 && yPos < 512){
for(int j = xPos; j < xPos + healthBarLength; j++){
if(j < 0 || j >= 768)
continue;
if(j < xPos + progress)
currentScreen[j + yPos*768] = color;
else
currentScreen[j + yPos*768] = (currentScreen[j + yPos*768]&0xFEFEFE)>>1;
}
if(xPos > 0 && xPos < 768)
currentScreen[xPos + yPos*768] = 0;
if(xPos + healthBarLength -1 >0 && xPos + healthBarLength - 1 < 768)
currentScreen[xPos + healthBarLength -1 + yPos*768] = 0;
}
}
yPos++;
if(yPos > 0 && yPos < 512){
if(xPos >= 0 && xPos < 768)
currentScreen[xPos + yPos*768] = (currentScreen[xPos + yPos*768]&0xFEFEFE)>>1;
for(int j = xPos+1; j < xPos + healthBarLength-1; j++){
if(j < 0 || j >= 768)
continue;
currentScreen[j + yPos*768] = 0;
}
if(xPos + healthBarLength-1 >= 0 && xPos + healthBarLength-1 < 768)
currentScreen[xPos + healthBarLength-1 + yPos*768] = (currentScreen[xPos + healthBarLength-1 + yPos*768]&0xFEFEFE)>>1;
}
}
}
}
//reset fogOfWarBuffer
fogOfWarBuffer[0] = 0;
for(int i = 1; i < 393216; i+=i){
System.arraycopy(fogOfWarBuffer, 0, fogOfWarBuffer, i, 393216 - i >= i ? i : 393216 - i);
}
for(int i = 0; i < 512; i++){
xMin[i] = 378;
xMax[i] = 378;
}
float[] list;
//shaffule vision polygons
for(int i = 0; i < 400; i++){
temp = (gameData.getRandom() * visionPolygonCount) >> 10;
temp1 = (gameData.getRandom() * visionPolygonCount) >> 10;
list = visionPolygonInfo[temp];
visionPolygonInfo[temp] = visionPolygonInfo[temp1];
visionPolygonInfo[temp1] = list;
}
//update vision polygons
for(int i = 0; i < visionPolygonCount; i++){
tempVector1.set(visionPolygonInfo[i][1], visionPolygonInfo[i][2], visionPolygonInfo[i][3]);
if(visionPolygonInfo[i][0] != 0){
poly = mainThread.theAssetManager.visionPolygon[1];
}else{
poly = mainThread.theAssetManager.visionPolygon[(int)visionPolygonInfo[i][4]];
}
tempVector1.subtract(poly.centre);
for(int j = 0; j < 48; j++)
poly.vertex3D[j].add(tempVector1);
poly.centre.add(tempVector1);
poly.update_visionPolygon();
rasterize(poly);
}
//blur fog of war buffer, use cross shaped kernel
int radius = 16;
int radiusBit = 5;
int destIndex = 0;
int index = 0;
for(int i = 0; i < 512; i++){
//init the first element in the row
temp = 0;
destIndex = i + 512 * 767 ;
for(int j = 0; j < radius -1; j++){
temp+=fogOfWarBuffer[index + j];
}
temp+=43*radius;
fogOfWarBuffer2[destIndex] = (byte)(temp >> radiusBit);
index++;
destIndex-=512;
for(int j = 1; j < radius; j++, index++, destIndex -=512){
temp = temp + fogOfWarBuffer[index + radius -2] - 43;
fogOfWarBuffer2[destIndex] = (byte)(temp >> radiusBit);
}
for(int j = radius; j < 768 - radius; j++, index++, destIndex -=512){
temp = temp + fogOfWarBuffer[index + radius -2] - fogOfWarBuffer[index - radius];
fogOfWarBuffer2[destIndex] = (byte)(temp >> radiusBit);
}
for(int j = 0; j < radius; j++, index++, destIndex -=512){
temp = temp - fogOfWarBuffer[index - radius] + 43;
fogOfWarBuffer2[destIndex] = (byte)(temp >> radiusBit);
}
}
destIndex = 0;
index = 0;
for(int i = 0; i < 768; i++){
//init the first element in the row
temp = 0;
destIndex = 767 - i;
for(int j = 0; j < radius -1 ; j++){
temp+=fogOfWarBuffer2[index + j];
}
temp+=43*radius;
fogOfWarBuffer[destIndex] = (byte)(temp >> radiusBit);
index++;
destIndex+=768;
for(int j = 1; j < radius; j++, index++, destIndex +=768){
temp = temp + fogOfWarBuffer2[index + radius -2] - 43;
fogOfWarBuffer[destIndex] = (byte)(temp >> radiusBit);
}
for(int j = radius; j < 512 - radius; j++, index++, destIndex +=768){
temp = temp + fogOfWarBuffer2[index + radius -2] - fogOfWarBuffer2[index - radius];
fogOfWarBuffer[destIndex] = (byte)(temp >> radiusBit);
}
for(int j = 0; j < radius; j++, index++, destIndex +=768){
temp = temp - fogOfWarBuffer2[index - radius] + 43;
fogOfWarBuffer[destIndex] = (byte)(temp >> radiusBit);
}
}
//blend fog of war to the frame buffer
for(int i = 0; i < 512 * 768; i++){
temp = fogOfWarBuffer[i];
if(temp < 112) {
r = (((currentScreen[i] & 0xff0000) >> 16) * (temp + 143)) >> 8;
g = (((currentScreen[i] & 0xff00) >> 8) * (temp + 143)) >> 8 ;
b = ((currentScreen[i] & 0xff) * (temp + 143)) >> 8;
currentScreen[i] = r << 16 | g << 8 | b;
}
}
//draw select rectangle
if(mainThread.pc.isSelectingUnit){
xPos = mainThread.pc.area.x;
yPos = mainThread.pc.area.y;
selectAreaWidth = mainThread.pc.area.width;
selectAreaHeight = mainThread.pc.area.height;
try{
if(!(yPos == 511 || xPos == 767)){
for(int i = xPos; i < xPos + selectAreaWidth; i++)
currentScreen[i + yPos*768] = 0xaa00;
for(int i = xPos; i < xPos + selectAreaWidth; i++)
currentScreen[i + (yPos + 1)*768] = 0xcc00;
for(int i = xPos; i < xPos + selectAreaWidth; i++)
currentScreen[i + (yPos+selectAreaHeight-1)*768] = 0xcc00;
for(int i = xPos; i < xPos + selectAreaWidth; i++)
currentScreen[i + (yPos + selectAreaHeight)*768] = 0xaa00;
for(int i = yPos; i < yPos + selectAreaHeight; i++)
currentScreen[xPos + i*768] = 0xaa00;
for(int i = yPos+1; i < yPos + selectAreaHeight-1; i++)
currentScreen[xPos + 1 + i*768] = 0xcc00;
for(int i = yPos; i < yPos + selectAreaHeight; i++)
currentScreen[xPos + selectAreaWidth + i*768] = 0xaa00;
for(int i = yPos + 1; i < yPos + selectAreaHeight - 1; i++)
currentScreen[xPos - 1 + selectAreaWidth + i*768] = 0xcc00;
}
}catch(Exception e){}
}
//draw confirmation icon
if(confirmationIconInfo[0] != 0){
theConfirmationIcon.setActive((float)confirmationIconInfo[1], (float)confirmationIconInfo[2], (int)confirmationIconInfo[3]);
}
theConfirmationIcon.updateAndDraw();
for(int i = 0; i < confirmationIconInfo.length; i++){
confirmationIconInfo[i] = 0;
}
//draw mini map
theMiniMap.draw(currentScreen, minimapBitmap, unitsForMiniMap, unitsForMiniMapCount);
theSideBar.draw(currentScreen, sideBarInfo);
}
//start rasterization
public static void rasterize(polygon3D polygon){
poly = polygon;
vertex2D = poly.vertex2D;
visibleCount = poly.visibleCount;
scanPolygon();
}
//convert a polygon to scan lines
public static void scanPolygon(){
start = 512;
end = -1;
int startX, g, startY, endY, temp_x;
float gradient;
for(int i = 0; i < visibleCount; i++){
vector v1 = vertex2D[i];
vector v2;
if(i == visibleCount -1 ){
v2 = vertex2D[0];
}else{
v2 = vertex2D[i+1];
}
boolean downwards = false;
//ensure v1.y < v2.y;
if (v1.screenY> v2.screenY) {
downwards = true;
vector temp = v1;
v1 = v2;
v2 = temp;
}
float dy = v2.screenY - v1.screenY;
// ignore horizontal lines
if (dy == 0) {
continue;
}
startY = Math.max((int)(v1.screenY) + 1, 0);
endY = Math.min((int)(v2.screenY), 511);
if(startY < start )
start = startY;
if(endY > end)
end = endY;
//calculate x increment along this edge
gradient = (v2.screenX - v1.screenX)* 2048 /dy;
startX = (int)((v1.screenX *2048) + (startY - v1.screenY) * gradient);
g = (int)(gradient);
for (int y=startY; y<=endY; y++) {
temp_x = startX>>11;
if(downwards){
if(temp_x >= 0)
xLeft[y] = temp_x;
else
xLeft[y] = 0;
}else{
if(temp_x <= 767)
xRight[y] = temp_x;
else
xRight[y] = 768;
}
startX+=g;
}
}
for(int i = start; i <= end; i++){
temp = xLeft[i];
temp1 = xRight[i];
temp2 = xMin[i];
temp3 = xMax[i];
if(temp1 <= temp3 && temp >= temp2)
continue;
if(!(temp > temp3) && !(temp2 > temp1)){
xMax[i] = Math.max(temp3, temp1);
xMin[i] = Math.min(temp2, temp);
for(int j = xMin[i]; j < xMax[i]; j++){
fogOfWarBuffer[j + i*768] = (byte)127;
}
continue;
}
xMax[i] = temp1;
xMin[i] = temp;
for(int j = temp; j < temp1; j++){
fogOfWarBuffer[j + i*768] = (byte)127;
}
}
}
public static void blurShadow(){
int index = 0;
if(cameraXZAngle <= 45 || cameraXZAngle >315){
for(int i = 0; i < 511; i ++){
for(int j = 1; j < 768; j++){
index = j + i*768;
if(shadowBitmap[index] < 0){
if(shadowBitmap[index] == -127)
smoothedShadowBitmap[index] = 32;
else
smoothedShadowBitmap[index]= (byte)(shadowBitmap[index] + 127);
}else{
smoothedShadowBitmap[index] = (byte)((shadowBitmap[index] + shadowBitmap[index - 1] + shadowBitmap[index + 768] + shadowBitmap[index + 767]) >> 2);
//smoothedShadowBitmap[index] = (byte)((shadowBitmap[index+769] + shadowBitmap[index+767] + shadowBitmap[index-769] + shadowBitmap[index-767] + shadowBitmap[index-768] + shadowBitmap[index] + shadowBitmap[index - 1] + shadowBitmap[index + 768] + shadowBitmap[index + 1])>>3);
}
}
}
for(int i = 0; i < 393216; i+= 768)
smoothedShadowBitmap[i] = shadowBitmap[i];
for(int i = 392448; i < 393216; i++)
smoothedShadowBitmap[i] = shadowBitmap[i];
}
if(cameraXZAngle <= 315 && cameraXZAngle > 225){
for(int i = 511; i > 0; i --){
for(int j = 1; j < 768; j++){
index = j + i*768;
if(shadowBitmap[index] < 0){
if(shadowBitmap[index] == -127)
smoothedShadowBitmap[index] = 32;
else
smoothedShadowBitmap[index]= (byte)(shadowBitmap[index] + 127);
}else{
smoothedShadowBitmap[index] = (byte)((shadowBitmap[index] + shadowBitmap[index - 1] + shadowBitmap[index - 768] + shadowBitmap[index - 769]) >> 2);
}
}
}
for(int i = 0; i < 393216; i+= 768)
smoothedShadowBitmap[i] = shadowBitmap[i];
for(int i = 0; i < 768; i++)
smoothedShadowBitmap[i] = shadowBitmap[i];
}
if(cameraXZAngle <= 225 && cameraXZAngle > 135){
for(int i = 511; i > 0; i --){
for(int j = 0; j < 767; j++){
index = j + i*768;
if(shadowBitmap[index] < 0){
if(shadowBitmap[index] == -127)
smoothedShadowBitmap[index] = 32;
else
smoothedShadowBitmap[index]= (byte)(shadowBitmap[index] + 127);
}else{
smoothedShadowBitmap[index] = (byte)((shadowBitmap[index] + shadowBitmap[index + 1] + shadowBitmap[index - 768] + shadowBitmap[index - 767]) >> 2);
}
}
}
for(int i = 767; i < 393216; i+= 768)
smoothedShadowBitmap[i] = shadowBitmap[i];
for(int i = 0; i < 768; i++)
smoothedShadowBitmap[i] = shadowBitmap[i];
}
if(cameraXZAngle <= 135 && cameraXZAngle > 45){
for(int i = 0; i < 511; i ++){
for(int j = 0; j < 767; j++){
index = j + i*768;
if(shadowBitmap[index] < 0){
if(shadowBitmap[index] == -127)
smoothedShadowBitmap[index] = 32;
else
smoothedShadowBitmap[index]= (byte)(shadowBitmap[index] + 127);
}else{
smoothedShadowBitmap[index] = (byte)((shadowBitmap[index] + shadowBitmap[index + 1] + shadowBitmap[index + 768] + shadowBitmap[index + 769]) >> 2);
}
}
}
for(int i = 767; i < 393216; i+= 768)
smoothedShadowBitmap[i] = shadowBitmap[i];
for(int i = 392448; i < 393216; i++)
smoothedShadowBitmap[i] = shadowBitmap[i];
}
}
public static void blendShadow(){
//blend shadow bitmap to the frame buffer
for(int i = 0; i < 512 * 768; i++){
temp = smoothedShadowBitmap[i];
if(temp <= 0) {
temp = shadowBitmap[i];
}
r = (((currentScreen[i] & 0xff0000) >> 16) * temp ) >> 5;
g = (((currentScreen[i] & 0xff00) >> 8) * temp) >> 5 ;
b = ((currentScreen[i] & 0xff) * temp) >> 5;
if(r > 255)
r = 255;
if(g > 255)
g = 255;
if(b > 255)
b = 255;
currentScreen[i] = r << 16 | g << 8 | b;
}
}
public static void prepareResources(){
currentScreen = mainThread.screen;
currentZbuffer = mainThread.zBuffer;
displacementBuffer = mainThread.displacementBuffer;
shadowBitmap = mainThread.shadowBitmap;
currentSelectedUnitsInfo = mainThread.theAssetManager.selectedUnitsInfo;
visionPolygonInfo = mainThread.theAssetManager.visionPolygonInfo;
visionPolygonCount = mainThread.theAssetManager.visionPolygonCount;
unitsForMiniMap = mainThread.theAssetManager.unitsForMiniMap;
unitsForMiniMapCount = mainThread.theAssetManager.unitsForMiniMapCount;
minimapBitmap = mainThread.theAssetManager.minimapBitmap;
explosionInfo = mainThread.theAssetManager.explosionInfo;
explosionCount = mainThread.theAssetManager.explosionCount;
helixInfo = mainThread.theAssetManager.helixInfo;
helixCount = mainThread.theAssetManager.helixCount;
smokeEmmiterList = mainThread.theAssetManager.smokeEmmiterList;
smokeEmmiterCount = mainThread.theAssetManager.smokeEmmiterCount;
sideBarInfo = mainThread.pc.theSideBarManager.sideBarInfo;
confirmationIconInfo = mainThread.theAssetManager.confirmationIconInfo;
cameraPosition.set(camera.position);
sinXZ = camera.sinXZ_angle;
cosXZ = camera.cosXZ_angle;
sinYZ = camera.sinYZ_angle;
cosYZ = camera.cosYZ_angle;
cameraXZAngle = camera.XZ_angle;
theMiniMap.findCorners();
playerMoney = mainThread.pc.theBaseInfo.currentCredit;
playerPowerStatus = mainThread.pc.theBaseInfo.powerStatus;
}
}

2296
core/rasterizer.java Normal file

File diff suppressed because it is too large Load Diff

50
core/sunLight.java Normal file
View File

@ -0,0 +1,50 @@
package core;
//directional light from the sun
public class sunLight {
public static int XZ_angle, YZ_angle;
public static float sinXZ_angle, cosXZ_angle, sinYZ_angle, cosYZ_angle;
public static vector position;
public static int[] shadowBuffer;
public static vector lightDirection;
public static void init(){
shadowBuffer = new int[1024*1024];
XZ_angle = 225;
YZ_angle = 316;
sinXZ_angle = gameData.sin[XZ_angle];
cosXZ_angle = gameData.cos[XZ_angle];
sinYZ_angle = gameData.sin[YZ_angle];
cosYZ_angle = gameData.cos[YZ_angle];
lightDirection = new vector(0,0,1);
lightDirection.rotate_YZ(YZ_angle);
lightDirection.rotate_XZ(XZ_angle);
lightDirection.y*=-1;
lightDirection.x*=-1;
position = new vector(0,0,0);
}
public static void update(){
position.set(mainThread.my2Dto3DFactory.get3DLocation(mainThread.theAssetManager.Terrain.ground[0], 384, 208));
position.add(lightDirection, -5);
//reset shadow buffer
shadowBuffer[0] = Integer.MAX_VALUE;
for(int i = 1; i < 1048576; i+=i){
System.arraycopy(shadowBuffer, 0, shadowBuffer, i, 1048576 - i >= i ? i : 1048576 - i);
}
}
}

910
core/terrain.java Normal file
View File

@ -0,0 +1,910 @@
package core;
import entity.*;
// this class store the geometry for terrain objects
public class terrain {
public polygon3D[] ground;
public int[] lakeObstacleIndex;
public int lakeObstacleCount;
public static int index;
public int Ambient_I = 25;
public int reflectance = 70;
//lake1
public polygon3D water1;
public polygon3D groundRemover1;
public polygon3D[] lake1;
public vector lakeCenter1;
public vector lakeCenterTemp1;
public boolean lake1Visible;
public int lake1PolyCount;
public palmTree lake1Tree, lake1Tree2;
//lake2
public polygon3D water2;
public polygon3D groundRemover2;
public polygon3D[] lake2;
public vector lakeCenter2;
public vector lakeCenterTemp2;
public boolean lake2Visible;
public int lake2PolyCount;
public goldMine goldMine2;
//lake3
public polygon3D water3;
public polygon3D groundRemover3;
public polygon3D[] lake3;
public vector lakeCenter3;
public vector lakeCenterTemp3;
public boolean lake3Visible;
public int lake3PolyCount;
//lake 4
public polygon3D water4;
public polygon3D groundRemover4;
public polygon3D[] lake4;
public vector lakeCenter4;
public vector lakeCenterTemp4;
public boolean lake4Visible;
public int lake4PolyCount;
public tokenObject theToken;
//road
public polygon3D[] road;
public vector roadDirection;
public vector roadNormal;
public vector roadSideDirection;
public vector roadCorner1, roadCorner2, roadCorner3, roadCorner4;
public vector roadCentre;
public int roadPolygonIndex;
public vector roadMarkCorner1, roadMarkCorner2, roadMarkCorner3, roadMarkCorner4;
public vector roadSideCorner1, roadSideCorner2, roadSideCorner3, roadSideCorner4;
//light poles
public lightPole[] lightPoles;
public int numOfLightPoles;
public int curveAngle;
public terrain(){
ground = new polygon3D[1];
vector[] v = new vector[]{new vector(-3f,-0.5001f,35f), new vector(35f,-0.5001f,35f), new vector(35f,-0.5001f,-3f), new vector(-3f,-0.5001f, -3f)};
ground[0] = new polygon3D(v, v[0], v[1], v[3], mainThread.textures[0], 39f,38.15f, 2);
ground[0].Ambient_I = Ambient_I;
ground[0].reflectance = reflectance;
ground[0].findDiffuse();
ground[0].textureFitPolygon = true;
lakeObstacleIndex = new int[1000];
float x_start = 3.5f;
float z_start = 8;
float l = 3;
float h = 3f/128*(128 - 17 - 12);
float w = 3f/128*(128 - 25 - 20);
float dx = 3f/128*25;
float dz = -3f/128*17;
theToken = new tokenObject(-1, -1, -1, 0x00ffff);
theToken.withinViewScreen = true;
int waveAngle = 320;
//create lake1
v = new vector[]{new vector(x_start+dx,-0.54f,z_start + dz), new vector(x_start + dx + w,-0.54f,z_start + dz), new vector(x_start + dx + w,-0.54f,z_start + dz-h), new vector(x_start+dx,-0.54f, z_start + dz-h)};
vector a1 = v[0].myClone();
vector b1 = v[1].myClone();
vector c1 = v[3].myClone();
a1.rotate_XZ(waveAngle);
b1.rotate_XZ(waveAngle);
c1.rotate_XZ(waveAngle);
water1 = new polygon3D(v, a1, b1, c1, mainThread.textures[54],w*1.2f,h*1.1f, 6);
v = new vector[]{new vector(x_start+dx,-0.5001f,z_start + dz), new vector(x_start + dx + w,-0.5001f,z_start + dz), new vector(x_start + dx + w,-0.5001f,z_start + dz-h), new vector(x_start+dx,-0.5001f, z_start + dz-h)};
groundRemover1 = new polygon3D(v, v[0], v[1], v[3], null,l,l, 4);
lake1 = createLake(mainThread.textures[55].heightmap, x_start, z_start, l , 128, 17, 12, 25, 20);
lake1PolyCount = index + 1;
lakeCenter1 = new vector(5f, -0.5001f, 6.5f);
lakeCenterTemp1 = new vector(0,0,0);
lake1Tree = new palmTree(4.983713f,-0.3028361f,6.419566f,-0.03152565f,0.03608194f,-0.030372922f,0.19448919f,-0.11764373f,187,64,148,205,281,352);
lake1Tree2 = new palmTree(4.983713f,-0.3028361f,6.389566f,-0.03152565f,0.11608194f,-0.010372922f,-0.29448919f,-0.11764373f,187,64,148,205,281,352);
//create lake2
x_start = 26;
z_start = 25.25f;
l = 3;
h = 3f/128*(128 - 2 - 4);
w = 3f/128*(128 - 35 - 43);
dx = 3f/128*35;
dz = -3f/128*2;
v = new vector[]{new vector(x_start+dx,-0.55f,z_start + dz), new vector(x_start + dx + w,-0.55f,z_start + dz), new vector(x_start + dx + w,-0.55f,z_start + dz-h), new vector(x_start+dx,-0.55f, z_start + dz-h)};
vector a2 = v[0].myClone();
vector b2 = v[1].myClone();
vector c2 = v[3].myClone();
a2.rotate_XZ(waveAngle);
b2.rotate_XZ(waveAngle);
c2.rotate_XZ(waveAngle);
water2 = new polygon3D(v,a2, b2, c2, mainThread.textures[54],w*1.2f,h*1.1f, 6);
v = new vector[]{new vector(x_start+dx,-0.5001f,z_start + dz), new vector(x_start + dx + w,-0.5001f,z_start + dz), new vector(x_start + dx + w,-0.5001f,z_start + dz-h), new vector(x_start+dx,-0.5001f, z_start + dz-h)};
groundRemover2 = new polygon3D(v, v[0], v[1], v[3], null,l,l, 4);
lake2 = createLake(mainThread.textures[57].heightmap, x_start, z_start, l , 128, 2, 4, 35, 43);
lake2PolyCount = index + 1;
lakeCenter2 = new vector(x_start+1.5f, -0.5001f, z_start-1.5f);
lakeCenterTemp2 = new vector(0,0,0);
goldMine2 = new goldMine(27.5f,-0.80f, 23.75f, 30000);
//create lake3
x_start = 9;
z_start = 27f;
l = 3.5f;
w = l/128*(128 - 18 - 20);
h = l/128*(128 - 17 - 27);
dx = l/128*18;
dz = -l/128*17;
v = new vector[]{new vector(x_start+dx,-0.55f,z_start + dz), new vector(x_start + dx + w,-0.55f,z_start + dz), new vector(x_start + dx + w,-0.55f,z_start + dz-h), new vector(x_start+dx,-0.55f, z_start + dz-h)};
vector a3 = v[0].myClone();
vector b3 = v[1].myClone();
vector c3 = v[3].myClone();
a3.rotate_XZ(waveAngle);
b3.rotate_XZ(waveAngle);
c3.rotate_XZ(waveAngle);
water3 = new polygon3D(v, a3, b3, c3, mainThread.textures[54],w*1.2f,h*1.1f, 6);
v = new vector[]{new vector(x_start+dx,-0.5001f,z_start + dz), new vector(x_start + dx + w,-0.5001f,z_start + dz), new vector(x_start + dx + w,-0.5001f,z_start + dz-h), new vector(x_start+dx,-0.5001f, z_start + dz-h)};
groundRemover3 = new polygon3D(v, v[0], v[1], v[3], null,l,l, 4);
lake3 = createLake(mainThread.textures[58].heightmap, x_start, z_start, l , 128, 17, 27, 18, 20);
lake3PolyCount = index + 1;
lakeCenter3 = new vector(x_start+1.5f, -0.5001f, z_start-1.5f);
lakeCenterTemp3 = new vector(0,0,0);
//create lake 4
x_start = 25;
z_start = 13f;
l = 3f;
w = l/128*(128 - 1 - 2);
h = l/128*(128 - 4 - 0);
dx = l/128*1;
dz = -l/128*4;
v = new vector[]{new vector(x_start+dx,-0.55f,z_start + dz), new vector(x_start + dx + w,-0.55f,z_start + dz), new vector(x_start + dx + w,-0.55f,z_start + dz-h), new vector(x_start+dx,-0.55f, z_start + dz-h)};
vector a4 = v[0].myClone();
vector b4 = v[1].myClone();
vector c4 = v[3].myClone();
a4.rotate_XZ(waveAngle);
b4.rotate_XZ(waveAngle);
c4.rotate_XZ(waveAngle);
water4 = new polygon3D(v, a4, b4, c4, mainThread.textures[54],w*1.2f,h*1.1f, 6);
v = new vector[]{new vector(x_start+dx,-0.5001f,z_start + dz), new vector(x_start + dx + w,-0.5001f,z_start + dz), new vector(x_start + dx + w,-0.5001f,z_start + dz-h), new vector(x_start+dx,-0.5001f, z_start + dz-h)};
groundRemover4 = new polygon3D(v, v[0], v[1], v[3], null,l,l, 4);
lake4 = createLake(mainThread.textures[59].heightmap, x_start, z_start, l , 128, 4, 0, 1, 2);
lake4PolyCount = index + 1;
lakeCenter4 = new vector(x_start+1.5f, -0.5001f, z_start-1.5f);
lakeCenterTemp4 = new vector(0,0,0);
//create road
road = new polygon3D[600];
roadCorner1 = new vector(4f,-0.500f, -3f);
roadCorner2 = new vector(4.36f,-0.500f,-3f);
roadCorner3 = new vector(4f,-0.500f, -3f);
roadCorner4 = new vector(4.36f,-0.500f,-3f);
roadDirection = new vector(0, 0, 1);
roadSideDirection = new vector(-1,0,0);
roadNormal = new vector(0,1,0);
roadCentre = new vector(0,0,0);
roadMarkCorner1 = new vector(0,0,0);
roadMarkCorner2 = new vector(0,0,0);
roadMarkCorner3 = new vector(0,0,0);
roadMarkCorner4 = new vector(0,0,0);
roadSideCorner1 = new vector(0,0,0);
roadSideCorner2 = new vector(0,0,0);
roadSideCorner3 = new vector(0,0,0);
roadSideCorner4 = new vector(0,0,0);
lightPoles = new lightPole[100];
createStrightRoadSection(4.5f);
createCurvedRoadSection(0.25f,80,-4);
createCurvedRoadSection(0.25f,40,4);
createStrightRoadSection(5);
createCurvedRoadSection(0.25f,40,4);
createStrightRoadSection(0.5f);
createCurvedRoadSection(0.25f,88,-4);
createStrightRoadSection(1.5f);
createCurvedRoadSection(0.25f,72,4);
createStrightRoadSection(5f);
createCurvedRoadSection(0.25f,64,-4);
createCurvedRoadSection(0.25f,80,5);
createStrightRoadSection(5f);
lightPoles[5].vanish();
lightPoles[18].vanish();
lightPoles[21].vanish();
lightPoles[28].vanish();
lightPoles[40].vanish();
}
public void createStrightRoadSection(float l){
roadCorner1.set(roadCorner3);
roadCorner2.set(roadCorner4);
roadCentre.set(roadCorner1);
roadCentre.add(roadCorner2);
roadCentre.scale(0.5f);
roadCentre.add(roadDirection, l);
roadCorner3.set(roadCentre);
roadCorner3.add(roadSideDirection, 0.18f);
roadCorner4.set(roadCentre);
roadCorner4.add(roadSideDirection, -0.18f);
vector[] v = new vector[]{roadCorner3.myClone(), roadCorner4.myClone(), roadCorner2.myClone(), roadCorner1.myClone()};
road[roadPolygonIndex] = new polygon3D(v, new vector(4f,-0.500f,35f), new vector(4.5f,-0.500f,35f), new vector(4f,-0.500f, -3f), mainThread.textures[61], 1f,80f, 2);
roadPolygonIndex++;
roadSideCorner1.set(roadCorner3);
roadSideCorner1.add(roadSideDirection, 0.03f);
roadSideCorner4.set(roadCorner1);
roadSideCorner4.add(roadSideDirection, 0.03f);
v = new vector[]{roadSideCorner1.myClone(), roadCorner3.myClone(), roadCorner1.myClone(), roadSideCorner4.myClone()};
road[roadPolygonIndex] = new polygon3D(v,v[0].myClone(), v[1].myClone(), v[3].myClone(), mainThread.textures[62], 0.2f, l, 8);
roadPolygonIndex++;
roadSideCorner2.set(roadCorner4);
roadSideCorner2.add(roadSideDirection, -0.03f);
roadSideCorner3.set(roadCorner2);
roadSideCorner3.add(roadSideDirection, -0.03f);
v = new vector[]{roadCorner4.myClone(), roadSideCorner2.myClone(), roadSideCorner3.myClone(), roadCorner2.myClone()};
road[roadPolygonIndex] = new polygon3D(v,v[0].myClone(), v[1].myClone(), v[3].myClone(), mainThread.textures[63], 1f, l, 8);
roadPolygonIndex++;
int numberOfSegments = (int)(l/0.25f);
roadCentre.y+=0.001f;
for(int i = 0; i < numberOfSegments; i++){
roadMarkCorner1.set(roadCentre);
roadMarkCorner1.add(roadSideDirection, 0.008f);
roadMarkCorner2.set(roadMarkCorner1);
roadMarkCorner2.add(roadSideDirection, -0.016f);
roadMarkCorner3.set(roadMarkCorner2);
roadMarkCorner3.add(roadDirection, -0.1f);
roadMarkCorner4.set(roadMarkCorner1);
roadMarkCorner4.add(roadDirection, -0.1f);
roadCentre.add(roadDirection, -0.25f);
v = new vector[]{roadMarkCorner1.myClone(), roadMarkCorner2.myClone(), roadMarkCorner3.myClone(), roadMarkCorner4.myClone()};
road[roadPolygonIndex] = new polygon3D(v, v[0], v[1], v[3] , mainThread.textures[60], 1f,1f, 1);
roadPolygonIndex++;
if(i%4 ==0){
if(numOfLightPoles == 29)
lightPoles[numOfLightPoles] = new lightPole(roadCentre.x-roadSideDirection.x*0.26f + 0.5f, roadCentre.y, roadCentre.z - roadSideDirection.z*0.26f,(curveAngle + 90)%360);
else
if(numOfLightPoles%2==0)
lightPoles[numOfLightPoles] = new lightPole(roadCentre.x+roadSideDirection.x*0.26f, roadCentre.y, roadCentre.z + roadSideDirection.z*0.26f,(curveAngle + 270)%360);
else
lightPoles[numOfLightPoles] = new lightPole(roadCentre.x-roadSideDirection.x*0.26f, roadCentre.y, roadCentre.z - roadSideDirection.z*0.26f,(curveAngle + 90)%360);
numOfLightPoles++;
}
}
}
public void createCurvedRoadSection(float l, int angle, int turnRate){
for(int i = 0; i < angle; i+=Math.abs(turnRate)){
roadCorner1.set(roadCorner3);
roadCorner2.set(roadCorner4);
roadCentre.set(roadCorner1);
roadCentre.add(roadCorner2);
roadCentre.scale(0.5f);
int realTurnRate = turnRate;
if(realTurnRate < 0)
realTurnRate = (360 + realTurnRate)%360;
roadDirection.rotate_XZ(realTurnRate);
curveAngle = (curveAngle + turnRate + 360)%360;
roadCentre.add(roadDirection, l);
roadSideDirection.rotate_XZ(realTurnRate);
roadCorner3.set(roadCentre);
roadCorner3.add(roadSideDirection, 0.18f);
roadCorner4.set(roadCentre);
roadCorner4.add(roadSideDirection, -0.18f);
vector[] v = new vector[]{roadCorner3.myClone(), roadCorner4.myClone(), roadCorner2.myClone(), roadCorner1.myClone()};
road[roadPolygonIndex] = new polygon3D(v, new vector(4f,-0.5f,35f), new vector(4.5f,-0.5f,35f), new vector(4f,-0.5f, -3f), mainThread.textures[61], 1f,80f, 2);
roadPolygonIndex++;
roadSideCorner1.set(roadCorner3);
roadSideCorner1.add(roadSideDirection, 0.03f);
roadSideCorner4.set(roadCorner1);
roadSideCorner4.add(roadSideDirection, 0.03f);
v = new vector[]{roadSideCorner1.myClone(), roadCorner3.myClone(), roadCorner1.myClone(), roadSideCorner4.myClone()};
road[roadPolygonIndex] = new polygon3D(v,v[0].myClone(), v[1].myClone(), v[3].myClone(), mainThread.textures[62], 0.2f, l*1.5f, 8);
roadPolygonIndex++;
roadSideCorner2.set(roadCorner4);
roadSideCorner2.add(roadSideDirection, -0.03f);
roadSideCorner3.set(roadCorner2);
roadSideCorner3.add(roadSideDirection, -0.03f);
v = new vector[]{roadCorner4.myClone(), roadSideCorner2.myClone(), roadSideCorner3.myClone(), roadCorner2.myClone()};
road[roadPolygonIndex] = new polygon3D(v,v[0].myClone(), v[1].myClone(), v[3].myClone(), mainThread.textures[63], 1f, l*1.5f, 8);
roadPolygonIndex++;
roadCentre.y+=0.0001f;
roadMarkCorner1.set(roadCentre);
roadMarkCorner1.add(roadSideDirection, 0.008f);
roadMarkCorner2.set(roadMarkCorner1);
roadMarkCorner2.add(roadSideDirection, -0.016f);
roadMarkCorner3.set(roadMarkCorner2);
roadMarkCorner3.add(roadDirection, -0.1f);
roadMarkCorner4.set(roadMarkCorner1);
roadMarkCorner4.add(roadDirection, -0.1f);
v = new vector[]{roadMarkCorner1.myClone(), roadMarkCorner2.myClone(), roadMarkCorner3.myClone(), roadMarkCorner4.myClone()};
road[roadPolygonIndex] = new polygon3D(v, v[0], v[1], v[3] , mainThread.textures[60], 1f,1f, 1);
roadPolygonIndex++;
if((i/Math.abs(turnRate))%4 ==0){
if(numOfLightPoles%2==0)
lightPoles[numOfLightPoles] = new lightPole(roadCentre.x+roadSideDirection.x*0.26f, roadCentre.y, roadCentre.z + roadSideDirection.z*0.26f,(curveAngle + 270)%360);
else
lightPoles[numOfLightPoles] = new lightPole(roadCentre.x-roadSideDirection.x*0.26f, roadCentre.y, roadCentre.z - roadSideDirection.z*0.26f,(curveAngle + 90)%360);
numOfLightPoles++;
}
}
}
public polygon3D[] createLake(int[] hm, float x_start, float z_start, float l, int blocks, int xBlockStart, int xBlockEnd, int yBlockStart, int yBlockEnd){
polygon3D[] lake = new polygon3D[blocks*blocks*2];
//load height map
float[] heightmap = new float[(blocks+1)*(blocks+1)];
int interval = (int)(Math.sqrt(hm.length) - 1)/blocks;
float baseHeight = -0.5001f;
float heightScale = -0.001f;
int widthPluseOne = (int)(Math.sqrt(hm.length));
for(int i = 0; i < (blocks+1); i++){
for(int j =0; j< (blocks+1); j++){
if(hm[j*interval + i*interval*widthPluseOne] < 2)
hm[j*interval + i*interval*widthPluseOne] = 0;
heightmap[j + i * (blocks+1)] = ((float)hm[j*interval + i*interval*widthPluseOne])*heightScale +baseHeight;
}
}
float dx = l/ blocks;
float dz = -l/ blocks;
vector tempVector0 = new vector(0,0,0);
vector tempVector1 = new vector(0,0,0);
vector tempVector2 = new vector(0,0,0);
vector tempVector3 = new vector(0,0,0);
vector deltaX = new vector(0,0,0);
vector deltaZ = new vector(0,0,0);
vector origin = new vector(0,0,0);
vector top = new vector(0,0,0);
vector bot = new vector(0,0,0);
vector[] v;
index = 0;
byte[] diffuses = new byte[blocks * blocks * 2];
for(int i = 0; i < diffuses.length; i++)
diffuses[i] = 73;
for(int i = xBlockStart; i < blocks-xBlockEnd; i++){
for(int j = yBlockStart; j < blocks - yBlockEnd; j++){
int block1 = j + i*(blocks+1);
int block2 = j + 1 + i*(blocks+1);
int block3 = j + 1 + (i +1)*(blocks+1);
int block4 = j + (i +1)*(blocks+1);
tempVector0.set(x_start + dx*j, heightmap[block1], z_start + dz*i);
tempVector1.set(x_start + dx*(j+1), heightmap[block2], z_start + dz*i);
tempVector2.set(x_start + dx*(j+1), heightmap[block3], z_start + dz*(i+1));
tempVector3.set(x_start + dx*j, heightmap[block4], z_start + dz*(i+1));
boolean sameHeight = heightmap[block1] == heightmap[block2] &&
heightmap[block2] == heightmap[block3] &&
heightmap[block3] == heightmap[block4];
boolean belowWaterLevel = heightmap[block1] < -0.55f && heightmap[block2] < -0.55f && heightmap[block3] < -0.55f && heightmap[block4] < -0.55f;
boolean belowGround = tempVector0.y < -0.5801f && tempVector1.y < -0.5801f && tempVector2.y < -0.5801f && tempVector3.y < -0.5801f;
if(belowGround){
tokenObject t = new tokenObject(((int)(tempVector0.x/0.25f)) * 0.25f + 0.125f,tempVector0.y, ((int)(tempVector0.z/0.25f)) * 0.25f + 0.125f, 64 << 16 | 64 << 8 | 255);
if(!t.noNeedForThisToken){
lakeObstacleIndex[lakeObstacleCount] = t.tileIndex;
lakeObstacleCount++;
}
}
if(sameHeight){
if(heightmap[block1] == -0.7551f)
continue;
if(heightmap[block1] == -0.5001f){
v = new vector[]{tempVector0.myClone(), tempVector1.myClone(), tempVector2.myClone(), tempVector3.myClone()};
deltaX.set(tempVector0);
deltaX.subtract(tempVector1);
deltaZ.set(tempVector0);
deltaZ.subtract(tempVector3);
origin.set(tempVector0);
origin.add(deltaX, j);
origin.add(deltaZ, i);
top.set(origin);
top.add(deltaX, -blocks);
bot.set(origin);
bot.add(deltaZ, -blocks);
lake[index] = new polygon3D(v, origin.myClone(), top.myClone(), bot.myClone(), mainThread.textures[0], l,l,1);
lake[index].Ambient_I = Ambient_I;
lake[index].reflectance = reflectance;
lake[index].findDiffuse();
diffuses[j*2 + i*(blocks)*2] = (byte)lake[index].diffuse_I;
diffuses[j*2+1 + i*(blocks)*2] = (byte)lake[index].diffuse_I;
index++;
continue;
}
}
if(belowWaterLevel){
v = new vector[]{tempVector0.myClone(), tempVector1.myClone(), tempVector2.myClone(), tempVector3.myClone()};
deltaX.set(tempVector0);
deltaX.subtract(tempVector1);
deltaZ.set(tempVector0);
deltaZ.subtract(tempVector3);
origin.set(tempVector0);
origin.add(deltaX, j);
origin.add(deltaZ, i);
top.set(origin);
top.add(deltaX, -blocks);
bot.set(origin);
bot.add(deltaZ, -blocks);
lake[index] = new polygon3D(v, origin.myClone(), top.myClone(), bot.myClone(), mainThread.textures[0], l,l,1);
lake[index].Ambient_I = Ambient_I;
lake[index].reflectance = reflectance;
lake[index].findDiffuse();
diffuses[j*2 + i*(blocks)*2] = (byte)lake[index].diffuse_I;
diffuses[j*2+1 + i*(blocks)*2] = (byte)lake[index].diffuse_I;
index++;
continue;
}
v = new vector[]{tempVector0.myClone(), tempVector1.myClone(), tempVector3.myClone()};
deltaX.set(tempVector0);
deltaX.subtract(tempVector1);
deltaZ.set(tempVector0);
deltaZ.subtract(tempVector3);
origin.set(tempVector0);
origin.add(deltaX, j);
origin.add(deltaZ, i);
top.set(origin);
top.add(deltaX, -blocks);
bot.set(origin);
bot.add(deltaZ, -blocks);
lake[index] = new polygon3D(v, origin.myClone(), top.myClone(), bot.myClone(), mainThread.textures[0], l,l,5);
lake[index].Ambient_I = Ambient_I;
lake[index].reflectance = reflectance;
lake[index].findDiffuse();
diffuses[j*2 + i*(blocks)*2] = (byte)lake[index].diffuse_I;
deltaX.set(tempVector3);
deltaX.subtract(tempVector2);
deltaZ.set(tempVector1);
deltaZ.subtract(tempVector2);
origin.set(tempVector2);
origin.add(deltaX);
origin.add(deltaZ);
origin.add(deltaX, j);
origin.add(deltaZ, i);
top.set(origin);
top.add(deltaX, -blocks);
bot.set(origin);
bot.add(deltaZ, -blocks);
v = new vector[]{tempVector1.myClone(), tempVector2.myClone(), tempVector3.myClone()};
lake[index+1] = new polygon3D(v, origin.myClone(), top.myClone(), bot.myClone(), mainThread.textures[0], l,l,5);
lake[index+1].Ambient_I = Ambient_I;
lake[index+1].reflectance = reflectance;
lake[index+1].findDiffuse();
diffuses[j*2 +1 + i*(blocks)*2] = (byte)lake[index+1].diffuse_I;
index+=2;
}
}
v = new vector[]{new vector(x_start,-0.7551f,z_start), new vector(x_start + l,-0.7551f,z_start), new vector(x_start + l,-0.7551f,z_start - l), new vector(x_start,-0.7551f, z_start - l)};
lake[index] = new polygon3D(v, v[0], v[1], v[3], mainThread.textures[0],l,l, 7);
lake[index].Ambient_I = Ambient_I;
lake[index].reflectance = reflectance;
lake[index].findDiffuse();
for(int i = 0; i < index; i++){
lake[i].parentObject = theToken;
}
//create smooth lake ledges
int polygonIndex = 0;
for(int i = xBlockStart; i < blocks-xBlockEnd; i++){
for(int j = yBlockStart; j < blocks - yBlockEnd; j++){
int block1 = j + i*(blocks+1);
int block2 = j + 1 + i*(blocks+1);
int block3 = j + 1 + (i +1)*(blocks+1);
int block4 = j + (i +1)*(blocks+1);
tempVector0.set(x_start + dx*j, heightmap[block1], z_start + dz*i);
tempVector1.set(x_start + dx*(j+1), heightmap[block2], z_start + dz*i);
tempVector2.set(x_start + dx*(j+1), heightmap[block3], z_start + dz*(i+1));
tempVector3.set(x_start + dx*j, heightmap[block4], z_start + dz*(i+1));
boolean sameHeight = heightmap[block1] == heightmap[block2] &&
heightmap[block2] == heightmap[block3] &&
heightmap[block3] == heightmap[block4];
boolean belowWaterLevel = heightmap[block1] < -0.55f && heightmap[block2] < -0.55f && heightmap[block3] < -0.55f && heightmap[block4] < -0.55f;
if(sameHeight){
if(heightmap[block1] == -0.7551f)
continue;
if(heightmap[block1] == -0.5001f){
polygonIndex++;
continue;
}
}
if(belowWaterLevel){
polygonIndex++;
continue;
}
int currentBlockIndex = j*2 + i*(blocks)*2;
lake[polygonIndex].diffuse[0] = (byte)((diffuses[currentBlockIndex]+
diffuses[currentBlockIndex - 1] +
diffuses[currentBlockIndex - 2] +
diffuses[currentBlockIndex - 1 - blocks*2] +
diffuses[currentBlockIndex - blocks*2] +
diffuses[currentBlockIndex - blocks*2 + 1])/6);
lake[polygonIndex].diffuse[1] = (byte)((diffuses[currentBlockIndex] +
diffuses[currentBlockIndex + 1]+
diffuses[currentBlockIndex + 2]+
diffuses[currentBlockIndex + 3 - blocks*2]+
diffuses[currentBlockIndex + 2 - blocks*2]+
diffuses[currentBlockIndex + 1 - blocks*2])/6);
try{
lake[polygonIndex].diffuse[2] = (byte)((diffuses[currentBlockIndex]+
diffuses[currentBlockIndex+1]+
diffuses[currentBlockIndex+blocks*2]+
diffuses[currentBlockIndex+blocks*2 - 1]+
diffuses[currentBlockIndex+blocks*2 - 2]+
diffuses[currentBlockIndex-1])/6);
}catch(Exception e){
lake[polygonIndex].diffuse[2] = 73;
}
lake[polygonIndex+1].diffuse[0] = lake[polygonIndex].diffuse[1];
try{
lake[polygonIndex+1].diffuse[1] = (byte)((diffuses[currentBlockIndex+1] +
diffuses[currentBlockIndex + 2] +
diffuses[currentBlockIndex + 3] +
diffuses[currentBlockIndex + 2 + blocks*2]+
diffuses[currentBlockIndex + 1 + blocks*2]+
diffuses[currentBlockIndex + blocks*2])/6);
}catch(Exception e){
lake[polygonIndex+1].diffuse[1] = 73;
}
lake[polygonIndex + 1].diffuse[2] = lake[polygonIndex].diffuse[2];
polygonIndex+=2;
}
}
return lake;
}
public void update(){
for(int i = 0; i < ground.length; i++){
if(ground[i] != null){
ground[i].update();
}
}
for(int i = 0; i < lakeObstacleCount; i++){
mainThread.gridMap.currentObstacleMap[lakeObstacleIndex[i]] = false;
}
//update lake1
lake1Visible = true;
lakeCenterTemp1.set(lakeCenter1);
lakeCenterTemp1.subtract(camera.position);
lakeCenterTemp1.rotate_XZ(camera.XZ_angle);
lakeCenterTemp1.rotate_YZ(camera.YZ_angle);
lakeCenterTemp1.updateLocation();
if(lakeCenterTemp1.screenX > 1118 || lakeCenterTemp1.screenX < - 350 || lakeCenterTemp1.screenY < - 140 || lakeCenterTemp1.screenY > 1062){
lake1Visible = false;
}
if(lake1Visible){
water1.origin.x-=0.0015f;
water1.rightEnd.x-=0.0015f;
water1.bottomEnd.x -= 0.0015f;
water1.origin.z-=0.0015f;
water1.rightEnd.z-=0.0015f;
water1.bottomEnd.z -= 0.0015f;
water1.update();
groundRemover1.update();
for(int i = 0; i < lake1PolyCount; i++){
lake1[i].update();
lake1[i].update_lightspace_withoutDrawing();
}
lake1Tree.update();
lake1Tree2.update();
}
//update lake 2
lake2Visible = true;
lakeCenterTemp2.set(lakeCenter2);
lakeCenterTemp2.subtract(camera.position);
lakeCenterTemp2.rotate_XZ(camera.XZ_angle);
lakeCenterTemp2.rotate_YZ(camera.YZ_angle);
lakeCenterTemp2.updateLocation();
if(lakeCenterTemp2.screenX > 1118 || lakeCenterTemp2.screenX < - 350 || lakeCenterTemp2.screenY < - 160 || lakeCenterTemp2.screenY > 1062){
lake2Visible = false;
}
if(lake2Visible){
water2.origin.x-=0.0015f;
water2.rightEnd.x-=0.0015f;
water2.bottomEnd.x -= 0.0015f;
water2.origin.z-=0.0015f;
water2.rightEnd.z-=0.0015f;
water2.bottomEnd.z -= 0.0015f;
water2.update();
groundRemover2.update();
for(int i = 0; i < lake2PolyCount; i++){
lake2[i].update();
lake2[i].update_lightspace_withoutDrawing();
}
goldMine2.update();
}
//update lake3
lake3Visible = true;
lakeCenterTemp3.set(lakeCenter3);
lakeCenterTemp3.subtract(camera.position);
lakeCenterTemp3.rotate_XZ(camera.XZ_angle);
lakeCenterTemp3.rotate_YZ(camera.YZ_angle);
lakeCenterTemp3.updateLocation();
if(lakeCenterTemp3.screenX > 1118 || lakeCenterTemp3.screenX < - 350 || lakeCenterTemp3.screenY < - 150 || lakeCenterTemp3.screenY > 962){
lake3Visible = false;
}
if(lake3Visible){
water3.origin.x-=0.0015f;
water3.rightEnd.x-=0.0015f;
water3.bottomEnd.x -= 0.0015f;
water3.origin.z-=0.0015f;
water3.rightEnd.z-=0.0015f;
water3.bottomEnd.z -= 0.0015f;
water3.update();
groundRemover3.update();
for(int i = 0; i < lake3PolyCount; i++){
lake3[i].update();
lake3[i].update_lightspace_withoutDrawing();
}
}
//update lake 4
lake4Visible = true;
lakeCenterTemp4.set(lakeCenter4);
lakeCenterTemp4.subtract(camera.position);
lakeCenterTemp4.rotate_XZ(camera.XZ_angle);
lakeCenterTemp4.rotate_YZ(camera.YZ_angle);
lakeCenterTemp4.updateLocation();
if(lakeCenterTemp4.screenX > 1418 || lakeCenterTemp4.screenX < - 400 || lakeCenterTemp4.screenY < - 150 || lakeCenterTemp4.screenY > 1102){
lake4Visible = false;
}
if(lake4Visible){
water4.origin.x-=0.0015f;
water4.rightEnd.x-=0.0015f;
water4.bottomEnd.x -= 0.0015f;
water4.origin.z-=0.0015f;
water4.rightEnd.z-=0.0015f;
water4.bottomEnd.z -= 0.0015f;
water4.update();
groundRemover4.update();
for(int i = 0; i < lake4PolyCount; i++){
lake4[i].update();
lake4[i].update_lightspace_withoutDrawing();
}
}
//animate water surface
mainThread.textures[54].waterHeightMap = mainThread.textures[54].waterHeightMaps[(mainThread.frameIndex)%48];
for(int i = 0; i < roadPolygonIndex; i++){
road[i].update();
if(road[i].type == 1)
road[i].update_lightspace_withoutDrawing();
}
for(int i = 0; i < numOfLightPoles; i++){
lightPoles[i].update();
}
}
public void draw(){
if(lake1Visible)
groundRemover1.draw();
if(lake2Visible)
groundRemover2.draw();
if(lake3Visible)
groundRemover3.draw();
if(lake4Visible)
groundRemover4.draw();
for(int i = 0; i < numOfLightPoles; i++){
lightPoles[i].draw();
}
for(int i = 0; i < roadPolygonIndex; i++)
road[i].draw();
for(int i = 0; i < ground.length; i++)
ground[i].draw();
if(lake1Visible){
for(int i = 0; i < lake1PolyCount; i++)
lake1[i].draw();
lake1Tree.draw();
lake1Tree2.draw();
water1.draw();
}
if(lake2Visible){
for(int i = 0; i < lake2PolyCount; i++)
lake2[i].draw();
goldMine2.draw();
water2.draw();
}
if(lake3Visible){
for(int i = 0; i < lake3PolyCount; i++)
lake3[i].draw();
water3.draw();
}
if(lake4Visible){
for(int i = 0; i < lake4PolyCount; i++){
lake4[i].draw();
}
water4.draw();
}
}
}

242
core/textRenderer.java Normal file
View File

@ -0,0 +1,242 @@
package core;
import java.awt.Image;
import java.awt.image.PixelGrabber;
import javax.imageio.ImageIO;
//handle text rendering
public class textRenderer {
public int[] fontBuffer, star, halfStar;
public int[][] chars;
public void init(){
fontBuffer = new int[665*16];
star = new int[12*12];
halfStar = new int[12*12];
//load font image
Image img = null;
try{
img = ImageIO.read(getClass().getResource("../images/" + "font.jpg"));
}catch(Exception e){
e.printStackTrace();
}
PixelGrabber pg = new PixelGrabber(img, 0, 0, 665, 16, fontBuffer, 0, 665);
try {
pg.grabPixels();
}catch(Exception e){
e.printStackTrace();
}
//create character bitmaps
chars = new int[93][16*7];
for(int i = 0; i < 93; i++){
for(int j = 0; j < 16; j++){
for(int k = 0; k < 7; k++){
chars[i][k+ j*7] = fontBuffer[i*7 + k + j*665];
}
}
}
//load half star images
try{
img = ImageIO.read(getClass().getResource("../images/" + "84.jpg"));
}catch(Exception e){
e.printStackTrace();
}
pg = new PixelGrabber(img, 0, 0, 12, 12, halfStar, 0, 12);
try {
pg.grabPixels();
}catch(Exception e){
e.printStackTrace();
}
//load star images
try{
img = ImageIO.read(getClass().getResource("../images/" + "85.jpg"));
}catch(Exception e){
e.printStackTrace();
}
pg = new PixelGrabber(img, 0, 0, 12, 12, star, 0, 12);
try {
pg.grabPixels();
}catch(Exception e){
e.printStackTrace();
}
}
public void drawFlashingText(int xPos, int yPos, String text, int[] screen){
int pixel, SpriteValue, screenValue, overflow, screenIndex;
int MASK7Bit = 0xFEFEFF;
char[] theText = text.toCharArray();
int t = (int)(35 * Math.sin((double)mainThread.frameIndex/7)) + 35;
if(t > 64)
t = 64;
for(int i = 0; i < theText.length; i++){
for(int j = 0; j < 16; j++){
for(int k = 0; k < 7; k++){
screenIndex = 768*yPos + xPos + i*7 + k + j*768;
screenValue = screen[screenIndex];
SpriteValue = chars[theText[i] - 32][k+ j*7]&255;
SpriteValue = SpriteValue * t / 64;
SpriteValue = SpriteValue << 16 | SpriteValue << 8 | SpriteValue;
pixel=(SpriteValue&MASK7Bit)+(screenValue&MASK7Bit);
overflow=pixel&0x1010100;
overflow=overflow-(overflow>>8);
screen[screenIndex] = overflow|pixel;
}
}
}
}
public void drawText(int xPos, int yPos, String text, int[] screen, int r, int g, int b){
int pixel, SpriteValue, screenValue, overflow, screenIndex;
int MASK7Bit = 0xFEFEFF;
char[] theText = text.toCharArray();
for(int i = 0; i < theText.length; i++){
for(int j = 0; j < 16; j++){
for(int k = 0; k < 7; k++){
screenIndex = 768*yPos + xPos + i*7 + k + j*768;
screenValue = screen[screenIndex];
SpriteValue = chars[theText[i] - 32][k+ j*7]&255;
SpriteValue = (r*SpriteValue/256) << 16 | (g*SpriteValue/256) << 8 | (b*SpriteValue/256);
pixel=(SpriteValue&MASK7Bit)+(screenValue&MASK7Bit);
overflow=pixel&0x1010100;
overflow=overflow-(overflow>>8);
screen[screenIndex] = overflow|pixel;
}
}
}
}
public void drawText_outline(int xPos, int yPos, String text, int[] screen, int insideColor, int outlineColor){
int SpriteValue, screenIndex, width, height;
char[] theText = text.toCharArray();
//draw outline first
for(int i = 0; i < theText.length; i++){
for(int j = 0; j < 16; j++){
for(int k = 0; k < 7; k++){
screenIndex = 768*yPos + xPos + i*7 + k + j*768;
width = xPos + i*7 + k;
height = yPos + j;
if(width < 1 || width > 766 || height < 1 || height > 510)
continue;
SpriteValue = chars[theText[i] - 32][k+ j*7]&255;
if((SpriteValue & 0xff) > 100){
screen[screenIndex+1] = outlineColor;
screen[screenIndex-1] = outlineColor;
screen[screenIndex+768] = outlineColor;
screen[screenIndex-768] = outlineColor;
screen[screenIndex+769] = outlineColor;
screen[screenIndex+767] = outlineColor;
screen[screenIndex-769] = outlineColor;
screen[screenIndex-767] = outlineColor;
}
}
}
}
//draw inside
for(int i = 0; i < theText.length; i++){
for(int j = 0; j < 16; j++){
for(int k = 0; k < 7; k++){
screenIndex = 768*yPos + xPos + i*7 + k + j*768;
width = xPos + i*7 + k;
height = yPos + j;
if(width < 1 || width > 766 || height < 1 || height > 510)
continue;
SpriteValue = chars[theText[i] - 32][k+ j*7]&255;
if((SpriteValue & 0xff) > 100){
screen[screenIndex] = insideColor;
}
}
}
}
}
public void drawStarCharacter(int xPos, int yPos, int starShape, int[] screen, int insideColor, int outlineColor){
//draw outline first
int[] starCharacter = star;
if(starShape == 1)
starCharacter = halfStar;
int SpriteValue, screenIndex, width, height;
for(int j = 0; j < 12; j++){
for(int k = 0; k < 12; k++){
screenIndex = 768*yPos + xPos + k + j*768;
width = xPos + k;
height = yPos + j;
if(width < 1 || width > 766 || height < 1 || height > 510)
continue;
SpriteValue = (starCharacter[k+ j*12]&0xff0000) >> 16;
if((SpriteValue & 0xff) > 30){
screen[screenIndex+1] = outlineColor;
screen[screenIndex-1] = outlineColor;
screen[screenIndex+768] = outlineColor;
screen[screenIndex-768] = outlineColor;
screen[screenIndex+769] = outlineColor;
screen[screenIndex+767] = outlineColor;
screen[screenIndex-769] = outlineColor;
screen[screenIndex-767] = outlineColor;
}
}
}
for(int j = 0; j < 12; j++){
for(int k = 0; k < 12; k++){
screenIndex = 768*yPos + xPos + k + j*768;
width = xPos+ k;
height = yPos + j;
if(width < 1 || width > 766 || height < 1 || height > 510)
continue;
SpriteValue = (starCharacter[k+ j*12]&0xff0000) >> 16;
if((SpriteValue & 0xff) > 30){
screen[screenIndex] = insideColor;
}
}
}
}
}

389
core/texture.java Normal file
View File

@ -0,0 +1,389 @@
package core;
//the texture dimension should only be power of 2
import java.awt.image.PixelGrabber;
import java.awt.*;
public class texture {
//holds the pixel data in 16bits color format
public static int[] textureBuffer;
//hold mipmaps of the original texture
public short[] pixelData;
public byte[] pixelDataByte;
//stores a sequence of explosion texture
public int[][] explosions;
//stores a sequence of smoke texture
public int[][] smoke;
//store height map
public int[] heightmap;
//stores animated light maps created by an explosion
public short[][] explosionAura;
//store displacement map
public short[] displacementMap;
//store height map that associated with water texture
public byte[] waterHeightMap;
public byte[][] waterHeightMaps;
//store information that determine water surface movement direction (can be either up or down)
public boolean[] waterSurfaceDirections;
//dimension of the texture
public int height, width, heightMask, widthMask, widthBits, heightBits;
public String type;
public int ID;
//produce texture based on input image
public texture(String type, Image img, int widthBits , int heightBits){
this.widthBits = widthBits;
this.heightBits = heightBits;
height = (int)Math.pow(2, heightBits);
width = (int)Math.pow(2, widthBits);
heightMask = height -1;
widthMask = width - 1;
this.type = type;
if(textureBuffer == null)
textureBuffer = new int[1024*1024]; //support a max texture size of 1024 * 1024
//load texture image and store it as an array of int
PixelGrabber pg = new PixelGrabber(img, 0, 0, width, height, textureBuffer, 0, width);
try {
pg.grabPixels();
}catch(Exception e){
e.printStackTrace();
}
int r, g, b;
//create displacement map
if(type.equals("displacement")){
displacementMap = new short[height*width];
int dh = height;
int dw = width;
int i = 0;
for ( int y = 0; y < dh; y++ ) {
for ( int x = 0; x < dw; x++ ) {
int rgb = textureBuffer[i];
r = (rgb >> 16) & 0xff;
g = (rgb >> 8) & 0xff;
b = rgb & 0xff;
textureBuffer[i] = (r+g+b) / 8; // An arbitrary scaling factor which gives a good range for "amount"
i++;
}
}
i = 0;
for ( int y = 0; y < dh; y++ ) {
int j1 = ((y+dh-1) % dh) * dw;
int j2 = y*dw;
int j3 = ((y+1) % dh) * dw;
for ( int x = 0; x < dw; x++ ) {
int k1 = (x+dw-1) % dw;
int k2 = x;
int k3 = (x+1) % dw;
int xMap = (textureBuffer[k1+j1] + textureBuffer[k1+j2] + textureBuffer[k1+j3] - textureBuffer[k3+j1] - textureBuffer[k3+j2] - textureBuffer[k3+j3]);
int yMap = (textureBuffer[k1+j3] + textureBuffer[k2+j3] + textureBuffer[k3+j3] - textureBuffer[k1+j1] - textureBuffer[k2+j1] - textureBuffer[k3+j1]);
displacementMap[i] = (short)( ((textureBuffer[i] * 2 / 3) << 10) | ((xMap + 16) << 5) | (yMap + 16));
i++;
}
}
}
//create basic 15bits version of the original texture
if(type.equals("basic")){
pixelData = new short[width*height];
for(int i = 0; i < width*height; i ++){
r = (textureBuffer[i] & 0x00ff0000)>>16;
g = (textureBuffer[i] & 0x0000ff00)>>8;
b = (textureBuffer[i] & 0x000000ff);
r = r/8;
g = g/8;
b = b/8;
pixelData[i] = (short)(r <<10 | g << 5 | b);
}
}
//create a series of explosion texture
if(type.equals("explosion")){
explosions = new int[16][64*64];
Color temp = new Color(0,0,0);
for(int i = 0; i < 16; i++){
int x = (i%4)*64;
int y = (i/4)*64;
for(int j = 0; j < 64*64; j++){
int color = textureBuffer[x+y*256 + j%64 + (j/64)*256];
temp = new Color(color);
if(temp.getRed() < 40)
color = 0;
explosions[i][j] = color;
}
}
}
//create series of smoke texture
if(type.equals("smoke")){
smoke = new int[40][64*64];
Color temp = new Color(0,0,0);
for(int i = 0; i < 40; i++){
int x = (i%8)*64;
int y = (i/8)*64;
for(int j = 0; j < 64*64; j++){
int color = textureBuffer[x+y*512 + j%64 + (j/64)*512];
temp = new Color(color);
r = ((color & 0xff0000) >> 16);
g = ((color & 0xff00) >> 8);
b = ((color & 0xff));
if(r < 0)
r = 0;
if(g < 0)
g = 0;
if(b < 0)
b = 0;
color = r;
if(r < 5)
color = 0;
smoke[i][j] = color ;
}
}
}
//create height map
if(type.equals("heightmap")){
heightmap = new int[(width+1)*(height+1)];
for(int i = 0; i < height; i++){
for(int j = 0; j < width; j++){
r = (textureBuffer[j + i* width] & 0xff);
if(i ==0 || i == (height-1) || j == 0 || j == (width -1))
r = 0;
heightmap[j + i * (width+1)] = r;
}
}
}
//create a series of light maps to stimulate the illumination created during an explosion
if(type.equals("explosion aura")){
explosionAura = new short[16][width*height];
for(int j = 0; j < 16; j++){
for(int i = 0; i < width*height; i ++){
int I = (((textureBuffer[i] & 0x00ff0000)>>16) - 20) * 5/9;
if(I < 80)
I = I*I*I*I/80/80/80;
explosionAura[j][i] = (short)(I/2.5 - 4*j);
}
}
}
}
//produce texture based on input image
public texture(String type, Image img, Image img2, int widthBits , int heightBits){
this.widthBits = widthBits;
this.heightBits = heightBits;
height = (int)Math.pow(2, heightBits);
width = (int)Math.pow(2, widthBits);
heightMask = height -1;
widthMask = width - 1;
this.type = type;
if(textureBuffer == null)
textureBuffer = new int[1024*1024]; //support a max texture size of 1024 * 1024
//load texture image and store it as an array of int
PixelGrabber pg = new PixelGrabber(img, 0, 0, width, height, textureBuffer, 0, width);
try {
pg.grabPixels();
}catch(Exception e){
e.printStackTrace();
}
int r, g, b;
//create displacement map
if(type.equals("water")){
displacementMap = new short[height*width];
waterHeightMap = new byte[height*width];
waterHeightMaps = new byte[48][height*width];
waterSurfaceDirections = new boolean[height*width];
int dh = height;
int dw = width;
int i = 0;
for ( int y = 0; y < dh; y++ ) {
for ( int x = 0; x < dw; x++ ) {
int rgb = textureBuffer[i];
r = (rgb >> 16) & 0xff;
g = (rgb >> 8) & 0xff;
b = rgb & 0xff;
textureBuffer[i] = (r+g+b) / 8; // An arbitrary scaling factor which gives a good range for "amount"
i++;
}
}
i = 0;
for ( int y = 0; y < dh; y++ ) {
int j1 = ((y+dh-1) % dh) * dw;
int j2 = y*dw;
int j3 = ((y+1) % dh) * dw;
for ( int x = 0; x < dw; x++ ) {
int k1 = (x+dw-1) % dw;
int k2 = x;
int k3 = (x+1) % dw;
int xMap = (textureBuffer[k1+j1] + textureBuffer[k1+j2] + textureBuffer[k1+j3] - textureBuffer[k3+j1] - textureBuffer[k3+j2] - textureBuffer[k3+j3]);
int yMap = (textureBuffer[k1+j3] + textureBuffer[k2+j3] + textureBuffer[k3+j3] - textureBuffer[k1+j1] - textureBuffer[k2+j1] - textureBuffer[k3+j1]);
displacementMap[i] = (short)( ((xMap + 16) << 5) | (yMap + 16));
i++;
}
}
//load height map for the water surface
pg = new PixelGrabber(img2, 0, 0, width, height, textureBuffer, 0, width);
try {
pg.grabPixels();
}catch(Exception e){
e.printStackTrace();
}
i = 0;
for ( int y = 0; y < dh; y++ ) {
for ( int x = 0; x < dw; x++ ) {
int h = (int)(((textureBuffer[i]&0xff) - 160) * 0.9);
if(h < 0)
h = 0;
waterHeightMap[i] = (byte)(h);
if(waterHeightMap[i] > 63){
System.out.println(waterHeightMap[i]);
waterHeightMap[i] = 63;
}
i++;
}
}
for(i = 0; i < 256*256; i++){
waterHeightMaps[0][i] = waterHeightMap[i];
waterHeightMaps[15][i] = waterHeightMap[(3456 + 256*256-i-1)%(256*256)];
waterHeightMaps[31][i] = waterHeightMap[i - i%256+ (255- i%256)];
}
for(int j = 1; j < 15; j++){
for(i = 0; i < 256*256; i++ ){
waterHeightMaps[j][i] = (byte)(waterHeightMaps[0][i] + (float)(waterHeightMaps[15][i] - waterHeightMaps[0][i])/15f*j);
}
}
for(int j = 16; j < 31; j++){
for(i = 0; i < 256*256; i++ ){
waterHeightMaps[j][i] = (byte)(waterHeightMaps[15][i] + (float)(waterHeightMaps[31][i] - waterHeightMaps[15][i])/15f*(j-15));
}
}
for(int j = 32; j < 48; j++){
for(i = 0; i < 256*256; i++ ){
waterHeightMaps[j][i] = (byte)(waterHeightMaps[31][i] + (float)(waterHeightMaps[0][i] - waterHeightMaps[31][i])/16f*(j-31));
}
}
}
}
//produce texture based on raw data
public texture(String type, short[] pixelData, int widthBits, int heightBits){
this.widthBits = widthBits;
this.heightBits = heightBits;
height = (int)Math.pow(2, heightBits);
width = (int)Math.pow(2, widthBits);
heightMask = height -1;
widthMask = width - 1;
this.pixelData = pixelData;
this.type = type;
}
//produce texture based on a color
public texture(String type, int color, int widthBits, int heightBits){
this.widthBits = widthBits;
this.heightBits = heightBits;
height = (int)Math.pow(2, heightBits);
width = (int)Math.pow(2, widthBits);
heightMask = height -1;
widthMask = width - 1;
int r = ((color & 0xff0000) >> 16)/8;
int g = ((color & 0xff00) >> 8)/8;
int b = (color & 0xff)/8;
short c = (short)(r <<10 | g << 5 | b);
this.pixelData = new short[height * width];
for(int i = 0; i < pixelData.length; i ++){
pixelData[i] = c;
}
this.type = type;
}
}

164
core/vector.java Normal file
View File

@ -0,0 +1,164 @@
package core;
public final class vector{
//x, y, z component of the vector
public float x, y, z;
//2d position on screen (from camera point of view)
public float screenX, screenY;
//2d position on screen (from light point of view)
public float screenX_lightspace, screenY_lightspace;
public final static int Z_length = 650;
public final int orthogonalScale = 220;
public static float old_X, old_Y, old_Z, zInverse, lengthInverse;
//z component of the vector from light space
public float z_lightspace;
public vector(float x, float y, float z){
this.x = x;
this.y = y;
this.z = z;
//calculate its 2D location on the screen
updateLocation();
}
public void add(vector v){
x+=v.x;
y+=v.y;
z+=v.z;
}
public void add(float a, float b, float c){
x+=a;
y+=b;
z+=c;
}
public void add(vector v, float scaler){
x+=v.x*scaler;
y+=v.y*scaler;
z+=v.z*scaler;
}
public void subtract(vector v){
x-=v.x;
y-=v.y;
z-=v.z;
}
//amplify each component of the vector by a number
public void scale(float d){
x*=d;
y*=d;
z*=d;
}
//normalize the vector
public void unit(){
lengthInverse = 1/getLength();
x = x*lengthInverse;
y = y*lengthInverse;
z = z*lengthInverse;
}
//find the magnitude of the vector
public float getLength(){
return (float)Math.sqrt(x*x + y*y + z*z);
}
//retrun the dot product of this vector with another vector
public float dot(vector v){
return x*v.x + y*v.y + z*v.z;
}
public void cross(vector v1, vector v2){
x = v1.y*v2.z - v1.z*v2.y;
y = v1.z*v2.x - v1.x*v2.z;
z = v1.x*v2.y - v1.y*v2.x;
}
//rotate the vector along Y axis
public void rotate_XZ(int angle){
float sin = gameData.sin[angle];
float cos = gameData.cos[angle];
old_X = x;
old_Z = z;
x = cos*old_X - sin*old_Z;
z = sin*old_X + cos*old_Z;
}
//rotate the vector along X axis
public void rotate_YZ(int angle){
float sin = gameData.sin[angle];
float cos = gameData.cos[angle];
old_Y = y;
old_Z = z;
y = cos*old_Y - sin*old_Z;
z = sin*old_Y + cos*old_Z;
}
//rotate the vector along Z axis
public void rotate_XY(int angle){
float sin = gameData.sin[angle];
float cos = gameData.cos[angle];
old_X = x;
old_Y = y;
x = cos*old_X - sin*old_Y;
y = sin*old_X + cos*old_Y;
}
//set all the component equal to the corresponding component of a given vector
public void set(vector v){
x = v.x;
y = v.y;
z = v.z;
}
public void set(float x, float y, float z){
this.x = x;
this.y = y;
this.z = z;
}
//set all the component to 0
public void reset(){
x = 0;
y = 0;
z = 0;
}
public void updateLocation(){
//find the 2D screen location of this vector
zInverse = Z_length/z;
screenX = x*zInverse + 384;
screenY = -y*zInverse + 256;
}
public void updateLocationOrthognal(){
//find the 2D screen location of this vector in Orthographic projection
screenX_lightspace = x*orthogonalScale + 512;
screenY_lightspace = -y*orthogonalScale + 512;
}
public vector myClone(){
return new vector(x,y,z);
}
public String toString(){
return "(" + x + ", " + y + ", " + z + ")";
}
}

10
enemyAI/.gitignore vendored Normal file
View File

@ -0,0 +1,10 @@
/baseExpensionAI.class
/buildingManagerAI.class
/combatManagerAI.class
/defenseManagerAI.class
/economyManagerAI.class
/enemyCommander.class
/mapAwarenessAI.class
/microManagementAI.class
/scoutingManagerAI.class
/unitProductionAI.class

View File

@ -0,0 +1,417 @@
package enemyAI;
import core.baseInfo;
import core.gameData;
import core.mainThread;
import core.vector;
import entity.*;
public class baseExpensionAI {
public baseInfo theBaseInfo;
public int[] expensionPiorityList;
public stealthTank[] scouts;
public constructionVehicle myMCV;
public boolean isExpanding;
public int targetExpension;
public goldMine[] goldMines;
public goldMine expensionGoldMine;
public int numberOfActiveScout;
public int numberOfStealthTankScout;
public int frameAI;
public vector temp;
public baseExpensionAI(baseInfo theBaseInfo){
this.theBaseInfo = theBaseInfo;
frameAI = 0;
temp = new vector(0,0,0);
//generate a expension piority list
expensionPiorityList = new int[5];
int randomeNumber = gameData.getRandom();
if(randomeNumber < 170)
expensionPiorityList = new int[]{5,6,2,3,7};
else if(randomeNumber >= 170 && randomeNumber < 340)
expensionPiorityList = new int[]{5,6,3,2,7};
else if(randomeNumber >= 340 && randomeNumber < 510)
expensionPiorityList = new int[]{5,2,6,3,7};
else if(randomeNumber >= 510 && randomeNumber < 680)
expensionPiorityList = new int[]{5,2,3,6,7};
else if(randomeNumber >= 680 && randomeNumber < 850)
expensionPiorityList = new int[]{5,3,6,2,7};
else
expensionPiorityList = new int[]{5,3,2,6,7};
scouts = new stealthTank[3];
}
public void processAI(){
frameAI++;
if(goldMines == null)
goldMines = mainThread.theAssetManager.goldMines;
//find the next potential expansion location
for(int i = 0; i<5; i++){
if(!hasRefineryNearTheGoldmine(goldMines[expensionPiorityList[i]]) && !hasConstructionYardNearGoldMine(goldMines[expensionPiorityList[i]]) && goldMines[expensionPiorityList[i]].goldDeposite > 17500){
targetExpension = i;
break;
}
}
expensionGoldMine = goldMines[expensionPiorityList[targetExpension]];
//produce a total of 3 scout units, check if there are any stealth tank in the production
numberOfActiveScout = 0;
numberOfStealthTankScout = 0;
for(int i = 0; i < scouts.length; i++){
if(scouts[i] != null && scouts[i].currentHP >0){
numberOfActiveScout++;
if(scouts[i].type == 6)
numberOfStealthTankScout++;
}
}
int numberOfStealthTankOnQueue = 0;
for(int i = 0; i < mainThread.theAssetManager.factories.length; i++){
if(mainThread.theAssetManager.factories[i] != null && mainThread.theAssetManager.factories[i].teamNo != 0){
numberOfStealthTankOnQueue += mainThread.theAssetManager.factories[i].numOfStealthTankOnQueue;
}
}
int numberOfUnassignedStealthTank = 0;
for(int i = 0; i < mainThread.theAssetManager.stealthTanks.length; i++){
if(mainThread.theAssetManager.stealthTanks[i] != null && mainThread.theAssetManager.stealthTanks[i].teamNo != 0 && mainThread.ec.theMapAwarenessAI.mapAsset[mainThread.theAssetManager.stealthTanks[i].ID] == null)
numberOfUnassignedStealthTank++;
}
int scoutsNumberLimit = scouts.length;
if(frameAI <= 800)
scoutsNumberLimit = scouts.length - 5;
//pick an idle factory to produce stealth tank. If there is no idle factory, cancel the one that is building lightTank
if(numberOfActiveScout + numberOfStealthTankOnQueue + numberOfUnassignedStealthTank < scoutsNumberLimit && theBaseInfo.canBuildStealthTank){
for(int i = 0; i < mainThread.theAssetManager.factories.length; i++){
if(mainThread.theAssetManager.factories[i] != null && mainThread.theAssetManager.factories[i].teamNo != 0){
if(mainThread.theAssetManager.factories[i].lightTankProgress < 240 || mainThread.theAssetManager.factories[i].isIdle()){
mainThread.theAssetManager.factories[i].cancelItemFromProductionQueue(factory.lightTankType);
mainThread.theAssetManager.factories[i].buildStealthTank();
break;
}
}
}
}
//build a mcv when the current mine is running low
myMCV = null;
for(int i = 0; i < mainThread.theAssetManager.constructionVehicles.length; i++){
if( mainThread.theAssetManager.constructionVehicles[i] != null && mainThread.theAssetManager.constructionVehicles[i].currentHP >0 && mainThread.theAssetManager.constructionVehicles[i].teamNo != 0){
myMCV = mainThread.theAssetManager.constructionVehicles[i];
}
}
int lowGoldmineThreshold = 17500;
if(mainThread.ec.theEconomyManagerAI.preferedGoldMine == mainThread.theAssetManager.goldMines[4])
lowGoldmineThreshold = 12500;
if(myMCV == null && expensionGoldMine.goldDeposite >= 17500 && (mainThread.ec.theEconomyManagerAI.preferedGoldMine.goldDeposite < lowGoldmineThreshold ||
(mainThread.ec.theEconomyManagerAI.preferedGoldMine == expensionGoldMine && !hasConstructionYardNearGoldMine(expensionGoldMine) && !hasRefineryNearTheGoldmine(expensionGoldMine)))){
int numberOfMCVOnQueue = 0;
for(int i = 0; i < mainThread.theAssetManager.factories.length; i++){
if(mainThread.theAssetManager.factories[i] != null && mainThread.theAssetManager.factories[i].teamNo != 0){
numberOfMCVOnQueue += mainThread.theAssetManager.factories[i].numOfMCVOnQueue;
}
}
if(numberOfMCVOnQueue == 0 && theBaseInfo.canBuildMCV){
for(int i = 0; i < mainThread.theAssetManager.factories.length; i++){
if(mainThread.theAssetManager.factories[i] != null && mainThread.theAssetManager.factories[i].teamNo != 0){
//if(main.theAssetManager.factories[i].lightTankProgress < 240 || main.theAssetManager.factories[i].isIdle()){
mainThread.theAssetManager.factories[i].cancelItemFromProductionQueue(factory.lightTankType);
mainThread.theAssetManager.factories[i].cancelItemFromProductionQueue(factory.rocketTankType);
mainThread.theAssetManager.factories[i].cancelItemFromProductionQueue(factory.stealthTankType);
mainThread.theAssetManager.factories[i].cancelItemFromProductionQueue(factory.heavyTankType);
mainThread.theAssetManager.factories[i].buildMCV();
break;
//}
}
}
}
}
//move mcv to the next expension location
if(myMCV != null){
isExpanding = true;
if(myMCV.getDistance(expensionGoldMine) > 2 && !(myMCV.destinationX == expensionGoldMine.centre.x && myMCV.destinationY == expensionGoldMine.centre.z)){
myMCV.moveTo(expensionGoldMine.centre.x, expensionGoldMine.centre.z);
myMCV.currentCommand = solidObject.move;
}else if(frameAI%5 == 0 && myMCV.getDistance(expensionGoldMine) <=2){
myMCV.moveTo(expensionGoldMine.centre.x + (float)(gameData.getRandom() -512) * 2 / 1024, expensionGoldMine.centre.z + (float)(gameData.getRandom() -512) * 2 / 1024);
myMCV.currentCommand = solidObject.move;
}
//change the preferred gold mine to the one near the new expension once MCV is deployed
if(myMCV.getDistance(expensionGoldMine) < 2 && myMCV.getDistance(expensionGoldMine) > 0.75 && myMCV.canBeDeployed()){
myMCV.expand();
mainThread.ec.theEconomyManagerAI.preferedGoldMine = expensionGoldMine;
}
}else{
isExpanding = false;
}
//send scouts to guard mining expansion
if(!isExpanding){
boolean scoutReachesExpension = false;
for(int i = 0; i < scouts.length; i++){
if(scouts[i] != null && scouts[i].currentHP >0){
if(scouts[i].getDistance(expensionGoldMine) > 3){
scouts[i].moveTo(expensionGoldMine.centre.x, expensionGoldMine.centre.z);
scouts[i].currentCommand = solidObject.move;
scouts[i].secondaryCommand = solidObject.StandBy;
}else{
scoutReachesExpension = true;
}
}
}
//retaliate if the scouts are underattack while guarding the mine expansion.
//however if there are too many hostile units to deal with, then retreat and tell the expansion AI to find another gold expension
if(scoutReachesExpension){
int overallThreatLevel = threatLevelNearTarget(expensionGoldMine);
int threatLevel = overallThreatLevel&0xfff;
boolean playerHasStaticDefence = ((overallThreatLevel&0xf000000) >> 24) >0;
int noneCombatID = ((overallThreatLevel&0xfff000) >> 12);
boolean isUnderAttack = false;
float targetX = 0;
float targetZ = 0;
for(int i = 0; i < scouts.length; i++){
if(scouts[i] != null && scouts[i].underAttackCountDown > 0){
isUnderAttack = true;
targetX = scouts[i].attacker.centre.x;
targetZ = scouts[i].attacker.centre.z;
if(scouts[i].currentHP<=0)
scouts[i] = null;
break;
}
}
//attack if a non combat unit show up and the treatLevel if not high
if(threatLevel <= numberOfActiveScout*6 && noneCombatID > 0 && !playerHasStaticDefence){
for(int i = 0; i < scouts.length; i++){
if(scouts[i] != null && scouts[i].currentHP >0){
scouts[i].attackMoveTo(mainThread.ec.theMapAwarenessAI.mapAsset[noneCombatID].centre.x,mainThread.ec.theMapAwarenessAI.mapAsset[noneCombatID].centre.z);
scouts[i].currentCommand = solidObject.attackMove;
scouts[i].secondaryCommand = solidObject.attackMove;
}
}
}
if(isUnderAttack){
if(threatLevel <= numberOfActiveScout*6 && !playerHasStaticDefence){
//retaliate if threatLevel is not high
for(int i = 0; i < scouts.length; i++){
if(scouts[i] != null && scouts[i].currentHP >0){
scouts[i].attackMoveTo(targetX, targetZ);
scouts[i].currentCommand = solidObject.attackMove;
scouts[i].secondaryCommand = solidObject.attackMove;
}
}
}else{
//find a new potential expansion location when threatLevel is very high (except for natural expansion which is too valuable to give up)
if(expensionGoldMine != goldMines[5]) {
for(int i = 0; i<5; i++){
if(!hasRefineryNearTheGoldmine(goldMines[expensionPiorityList[i]]) && !hasConstructionYardNearGoldMine(goldMines[expensionPiorityList[i]])
&& goldMines[expensionPiorityList[i]].goldDeposite > 17500 && goldMines[expensionPiorityList[i]] != expensionGoldMine){
int t = expensionPiorityList[targetExpension];
expensionPiorityList[targetExpension] = expensionPiorityList[i];
expensionPiorityList[i] = t;
break;
}
}
expensionGoldMine = goldMines[expensionPiorityList[targetExpension]];
}
}
}
}
}else{
if(myMCV != null){
int threatLevel = threatLevelNearTarget(expensionGoldMine);
if(threatLevel > 0 || hasRefineryNearTheGoldmine(expensionGoldMine) || hasConstructionYardNearGoldMine(expensionGoldMine)){
if((threatLevel&0xfff) <= numberOfActiveScout*5 && !hasRefineryNearTheGoldmine(expensionGoldMine) && !hasConstructionYardNearGoldMine(expensionGoldMine)){
//attack if threatLevel is low
for(int i = 0; i < scouts.length; i++){
if(scouts[i] != null && scouts[i].currentHP >0){
scouts[i].attackMoveTo(expensionGoldMine.centre.x, expensionGoldMine.centre.z);
scouts[i].currentCommand = solidObject.attackMove;
scouts[i].secondaryCommand = solidObject.attackMove;
}
}
}else{
//find a new potential expansion location when threatLevel is high (except for natural expansion which is too valuable to give up)
if(expensionGoldMine != goldMines[5]) {
for(int i = 0; i<5; i++){
if(!hasRefineryNearTheGoldmine(goldMines[expensionPiorityList[i]]) && !hasConstructionYardNearGoldMine(goldMines[expensionPiorityList[i]])
&& goldMines[expensionPiorityList[i]].goldDeposite > 17500 && goldMines[expensionPiorityList[i]] != expensionGoldMine){
int t = expensionPiorityList[targetExpension];
expensionPiorityList[targetExpension] = expensionPiorityList[i];
expensionPiorityList[i] = t;
break;
}
}
expensionGoldMine = goldMines[expensionPiorityList[targetExpension]];
}
for(int i = 0; i < scouts.length; i++){
if(scouts[i] != null && scouts[i].currentHP >0){
if(scouts[i].getDistance(expensionGoldMine) > 3){
scouts[i].moveTo(expensionGoldMine.centre.x, expensionGoldMine.centre.z);
scouts[i].currentCommand = solidObject.move;
scouts[i].secondaryCommand = solidObject.StandBy;
}
}
}
}
}else{
if(myMCV.underAttackCountDown > 0 && myMCV.attacker != null){
for(int i = 0; i < scouts.length; i++){
if(scouts[i] != null && scouts[i].currentHP >0){
scouts[i].attackMoveTo(myMCV.attacker.centre.x, myMCV.attacker.centre.z);
scouts[i].currentCommand = solidObject.attackMove;
scouts[i].secondaryCommand = solidObject.attackMove;
}
}
}else{
temp.set(expensionGoldMine.centre);
temp.subtract(myMCV.centre);
temp.unit();
temp.scale(1.5f);
for(int i = 1; i < scouts.length; i++){
if(scouts[i] != null && scouts[i].currentHP >0){
scouts[i].attackMoveTo(myMCV.centre.x + temp.x, myMCV.centre.z + temp.z);
scouts[i].currentCommand = solidObject.attackMove;
scouts[i].secondaryCommand = solidObject.attackMove;
}
}
}
}
}
}
}
//check if the scout units can fend off hostile aggression near a goldmine expension
public int threatLevelNearTarget(solidObject o){
//the 0xfff bits store the treatLevel of hostile Unit
//the 0xfff000 bits store the id number of a nearby harvester/construction vehicle
//the 0xf000000 bit tells if the player has static defense setup near the target area
solidObject[] playerUnitInMinimap = mainThread.ec.theMapAwarenessAI.playerUnitInMinimap;
solidObject[] playerStaticDefenceInMinimap = mainThread.ec.theMapAwarenessAI.playerStaticDefenceInMinimap;
boolean playerNoneCombatUnitDetected = false;
int threatLevel = 0;
for(int i = 0; i < playerUnitInMinimap.length; i++){
if(playerUnitInMinimap[i] != null && playerUnitInMinimap[i].getDistance(o) < 3){
if(playerUnitInMinimap[i].type == 0)
threatLevel+=3;
else if(playerUnitInMinimap[i].type == 1)
threatLevel+=2;
else if(playerUnitInMinimap[i].type == 6)
threatLevel+=5;
else if(playerUnitInMinimap[i].type == 7)
threatLevel+=20;
else if((playerUnitInMinimap[i].type == 2 || playerUnitInMinimap[i].type == 3) && !playerNoneCombatUnitDetected){
playerNoneCombatUnitDetected = true;
threatLevel+=(playerUnitInMinimap[i].ID << 12);
}
}
}
for(int i = 0; i < playerStaticDefenceInMinimap.length; i++){
if(playerStaticDefenceInMinimap[i] != null && playerStaticDefenceInMinimap[i].getDistance(expensionGoldMine) < 3){
threatLevel += (1 << 24); //increase the threat level dramatically if player already has a base near the expension
break;
}
}
return threatLevel;
}
//add a stealth tank to scouts
public void addStealthTank(stealthTank o){
for(int i = 0; i < scouts.length; i++){
if(scouts[i] == null || scouts[i].currentHP <=0){
scouts[i] = o;
break;
}
}
}
//3 stealth tanks will make a perfect scout team for the base expansion exploration
public boolean needStealthTank(){
for(int i = 0; i < scouts.length; i++){
if((scouts[i] == null || scouts[i].currentHP <=0) && frameAI > 800){
return true;
}
}
return false;
}
public boolean hasRefineryNearTheGoldmine(goldMine g){
for(int j = 0; j < mainThread.theAssetManager.refineries.length; j++){
if(mainThread.theAssetManager.refineries[j] != null){
if(mainThread.theAssetManager.refineries[j].getDistance(g) < 2){
return true;
}
}
}
return false;
}
public boolean hasConstructionYardNearGoldMine(goldMine g){
for(int j = 0; j < mainThread.theAssetManager.constructionYards.length; j++){
if(mainThread.theAssetManager.constructionYards[j] != null){
if(mainThread.theAssetManager.constructionYards[j].getDistance(g) < 3){
return true;
}
}
}
return false;
}
}

View File

@ -0,0 +1,536 @@
//1. process building enquires from enemy commander
//2. manage building placement
//3 units production
//4. perform research
package enemyAI;
import core.baseInfo;
import core.gameData;
import core.mainThread;
import core.vector;
import entity.*;
public class buildingManagerAI {
public baseInfo theBaseInfo;
public int[] buildingPlacementCheckTiles, buildingPlacementCheckTiles_2x2, buildingPlacementCheckTiles_3x3;
public int placementTile;
public boolean powerPlantUnderConstruction;
public int frameIndex;
public buildingManagerAI (baseInfo theBaseInfo){
this.theBaseInfo = theBaseInfo;
buildingPlacementCheckTiles = solidObject.generateTileCheckList(13);
buildingPlacementCheckTiles_2x2 = new int[buildingPlacementCheckTiles.length];
buildingPlacementCheckTiles_3x3 = new int[buildingPlacementCheckTiles.length];
for(int i = 0; i < buildingPlacementCheckTiles.length ; i++){
buildingPlacementCheckTiles_2x2[i] = buildingPlacementCheckTiles[i];
buildingPlacementCheckTiles_3x3[i] = buildingPlacementCheckTiles[i];
}
for(int i = 0; i < 400; i++){
int temp = (gameData.getRandom() * 70) >> 10;
int temp1 = (gameData.getRandom() * 70) >> 10;
int list = buildingPlacementCheckTiles_2x2[temp];
buildingPlacementCheckTiles_2x2[temp] = buildingPlacementCheckTiles_2x2[temp1];
buildingPlacementCheckTiles_2x2[temp1] = list;
}
for(int i = 0; i < 400; i++){
int temp = (gameData.getRandom() * 50 + 40*1024) >> 10;
int temp1 = (gameData.getRandom() * 50 + 40*1024) >> 10;
int list = buildingPlacementCheckTiles_3x3[temp];
buildingPlacementCheckTiles_3x3[temp] = buildingPlacementCheckTiles_3x3[temp1];
buildingPlacementCheckTiles_3x3[temp1] = list;
}
frameIndex = 0;
}
public void addBuildingToQueue(int buildingType){
//if the additional building will result in a lower power, then build power plant first
if(buildingType != 101){
if(theBaseInfo.currentPowerLevel <= constructionYard.getPowerConsumption(buildingType) + theBaseInfo.currentPowerConsumption && !powerPlantUnderConstruction){
addBuildingToQueue(101);
return;
}
}
//check if the building is already in the queue
boolean alreadyInQueue = false;
constructionYard[] constructionYards = mainThread.theAssetManager.constructionYards;
//can only build one none defense structure at a time
//but can build more than defense structure at a time if there are more construction yards
for(int i = 0; i < constructionYards.length; i ++){
if(constructionYards[i] != null && constructionYards[i].teamNo != 0){
if(constructionYards[i].currentBuildingType == buildingType){
if(buildingType < 150){
alreadyInQueue = true;
break;
}
}
}
}
//if not in the queue then
if(!alreadyInQueue){
for(int i = 0; i < constructionYards.length; i ++){
if(constructionYards[i] != null && constructionYards[i].teamNo != 0 && constructionYards[i].isIdle()){
constructionYards[i].build(buildingType);
break;
}
}
}
}
public void processAI(){
frameIndex++;
powerPlantUnderConstruction = buildingUnderProduction(101);
//build power plant, if the base is in lower power status or we have more money to spend on make extra one
if(theBaseInfo.canBuildRefinery == false || theBaseInfo.lowPower || (theBaseInfo.currentPowerConsumption >= (theBaseInfo.currentPowerLevel - 500) && theBaseInfo.currentCredit > 500 && theBaseInfo.numberOfPowerPlant >=2 && frameIndex > 300)){
addBuildingToQueue(101);
}
//build a refinery center if there isn't any
if(theBaseInfo.numberOfRefinery == 0 && theBaseInfo.canBuildRefinery){
addBuildingToQueue(102);
}
//build an additional refinery if there are more production building
//don't build more than 2 refinery around a goldmine
if(getNumberOfFunctionalRefinery() < theBaseInfo.numberOfConstructionYard*2 && theBaseInfo.numberOfFactory > 0 && theBaseInfo.canBuildRefinery && getNumberOfRefineriesNearPreferedGoldMine() < 2){
addBuildingToQueue(102);
}
//build a factory if there isnt any
if(theBaseInfo.numberOfFactory == 0 && theBaseInfo.canBuildFactory){
addBuildingToQueue(105);
}
//build an addtional factory if we have enough harvester to sustain the production
if(mainThread.ec.theEconomyManagerAI.numberOfharvesters/2 > theBaseInfo.numberOfFactory && theBaseInfo.canBuildFactory && theBaseInfo.numberOfFactory < 2 && theBaseInfo.currentCredit > 1300){
addBuildingToQueue(105);
}
//build a communication center if there isnt any
if(theBaseInfo.numberOfCommunicationCenter == 0 && theBaseInfo.canBuildCommunicationCenter){
addBuildingToQueue(106);
}
//build a tech center if there isnt any
if(theBaseInfo.numberOfTechCenter == 0 && theBaseInfo.canBuildTechCenter){
addBuildingToQueue(107);
}
//build more factory if we have plenty of money in the bank
if(theBaseInfo.currentCredit > 2200 && theBaseInfo.canBuildFactory && theBaseInfo.numberOfFactory <= mainThread.ec.theEconomyManagerAI.numberOfharvesters/2){
addBuildingToQueue(105);
}
//process structure building event
constructionYard[] constructionYards = mainThread.theAssetManager.constructionYards;
for(int i = 0; i < constructionYards.length; i++){
if(constructionYards[i] != null && constructionYards[i].teamNo != 0){
//deploy power plant
if(constructionYards[i].powerPlantProgress == 240){
if(hasRoomForPlacement(101, -1)){
int y = 127 - placementTile/128;
int x = placementTile%128 + 1;
powerPlant o = new powerPlant(x*0.25f, -1f, y*0.25f, 1);
mainThread.theAssetManager.addPowerPlant(o);
constructionYards[i].finishDeployment();
}
}
//deploy refinery
if(constructionYards[i].refineryProgress == 240){
if(hasRoomForPlacement(102, mainThread.ec.theEconomyManagerAI.preferedGoldMineLocation)){
int y = 127 - placementTile/128;
int x = placementTile%128 + 1;
refinery o = new refinery(x*0.25f + 0.125f, -1.43f, y*0.25f, 1);
mainThread.theAssetManager.addRefinery(o);
harvester h = new harvester(new vector(x*0.25f + 0.125f,-0.3f, y*0.25f - 0.375f), 180, 1);
mainThread.theAssetManager.addHarvester(h);
h.goToTheNearestGoldMine();
constructionYards[i].finishDeployment();
}
}
//deploy factory
if(constructionYards[i].factoryProgress == 240){
int factoryDeployLocation = findFactoryDeployLocation();
if(hasRoomForPlacement(105, factoryDeployLocation)){
int y = 127 - placementTile/128;
int x = placementTile%128 + 1;
factory o = new factory(x*0.25f + 0.125f, -1.13f, y*0.25f, 1);
mainThread.theAssetManager.addFactory(o);
constructionYards[i].finishDeployment();
}
}
//deploy communication center
if(constructionYards[i].communicationCenterProgress == 240){
if(hasRoomForPlacement(106, communicationCenter.intendedDeployLocation)){
int y = 127 - placementTile/128;
int x = placementTile%128 + 1;
communicationCenter o = new communicationCenter(x*0.25f, -1f, y*0.25f, 1);
mainThread.theAssetManager.addCommunicationCenter(o);
constructionYards[i].finishDeployment();
communicationCenter.intendedDeployLocation = -1;
}
}
//deploy tech center
if(constructionYards[i].techCenterProgress == 240){
if(hasRoomForPlacement(107, techCenter.intendedDeployLocation)){
int y = 127 - placementTile/128;
int x = placementTile%128 + 1;
techCenter o = new techCenter(x*0.25f, -1f, y*0.25f, 1);
mainThread.theAssetManager.addTechCenter(o);
constructionYards[i].finishDeployment();
techCenter.intendedDeployLocation = -1;
}
}
}
}
}
public boolean hasRoomForPlacement(int buildingType, int centerTile){
//check placement for power plant
if(buildingType == 101){
constructionYard[] constructionYards = mainThread.theAssetManager.constructionYards;
for(int i = 0; i < constructionYards.length; i++){
if(constructionYards[i] == null)
continue;
if(constructionYards[i].teamNo == 0)
continue;
centerTile = (int)(constructionYards[i].centre.x*64)/16 + (127 - (int)(constructionYards[i].centre.z*64)/16)*128;
for(int j = 0; j < buildingPlacementCheckTiles.length; j++){
if(buildingPlacementCheckTiles_2x2[j] != Integer.MAX_VALUE){
placementTile = centerTile + buildingPlacementCheckTiles_2x2[j];
if(!checkIfBlockIsFree(placementTile)){ continue;}
if(!checkIfBlockIsFree(placementTile+1)){ continue;}
if(!checkIfBlockIsFree(placementTile + 128)){ continue;}
if(!checkIfBlockIsFree(placementTile + 129)){ continue;}
if(!checkIfBlockIsFree(placementTile - 129)){ continue;}
if(!checkIfBlockIsFree(placementTile + 257)){ continue;}
if(!checkIfBlockIsFree(placementTile - 127)){ continue;}
if(!checkIfBlockIsFree(placementTile + 255)){ continue;}
if(!checkIfBlockIsFree(placementTile + 127)){ continue;}
return true;
}
}
}
}
//check placement for refinery
if(buildingType == 102){
boolean foundSuitableTile = false;
int distance = 99999;
int idealPosition = 0;
for(int j = 40; j < buildingPlacementCheckTiles.length; j++){
if(buildingPlacementCheckTiles_3x3[j] != Integer.MAX_VALUE){
placementTile = centerTile + buildingPlacementCheckTiles_3x3[j];
if(!checkIfBlockIsFree(placementTile)){ continue;}
if(!checkIfBlockIsFree(placementTile+1)){ continue;}
if(!checkIfBlockIsFree(placementTile+2)){ continue;}
if(!checkIfBlockIsFree(placementTile + 128)){ continue;}
if(!checkIfBlockIsFree(placementTile + 129)){ continue;}
if(!checkIfBlockIsFree(placementTile + 130)){ continue;}
if(!checkIfBlockIsFree(placementTile + 256)){ continue;}
if(!checkIfBlockIsFree(placementTile + 257)){ continue;}
if(!checkIfBlockIsFree(placementTile + 258)){ continue;}
foundSuitableTile = true;
if(Math.abs(placementTile/128 - centerTile/128) + Math.abs(placementTile%128 - centerTile%128) < distance) {
idealPosition = placementTile;
distance = Math.abs(placementTile/128 - centerTile/128) + Math.abs(placementTile%128 - centerTile%128);
}
if(placementTile/128 + 4< centerTile/128)
return true;
}
}
if(foundSuitableTile) {
placementTile = idealPosition;
return true;
}
}
//check placement for factory
if(buildingType == 105){
for(int j = 40; j < buildingPlacementCheckTiles.length; j++){
if(buildingPlacementCheckTiles_3x3[j] != Integer.MAX_VALUE){
placementTile = centerTile + buildingPlacementCheckTiles_3x3[j];
if(!checkIfBlockIsFree(placementTile - 128)){ continue;}
if(!checkIfBlockIsFree(placementTile - 127)){ continue;}
if(!checkIfBlockIsFree(placementTile - 126)){ continue;}
if(!checkIfBlockIsFree(placementTile)){ continue;}
if(!checkIfBlockIsFree(placementTile+1)){ continue;}
if(!checkIfBlockIsFree(placementTile+2)){ continue;}
if(!checkIfBlockIsFree(placementTile + 128)){ continue;}
if(!checkIfBlockIsFree(placementTile + 129)){ continue;}
if(!checkIfBlockIsFree(placementTile + 130)){ continue;}
if(!checkIfBlockIsFree(placementTile + 256)){ continue;}
if(!checkIfBlockIsFree(placementTile + 257)){ continue;}
if(!checkIfBlockIsFree(placementTile + 258)){ continue;}
return true;
}
}
}
//check placement for communication center
if(buildingType == 106){
if(centerTile == -1){
constructionYard[] constructionYards = mainThread.theAssetManager.constructionYards;
for(int i = 0; i < constructionYards.length; i++){
if(constructionYards[i] == null)
continue;
if(constructionYards[i].teamNo == 0)
continue;
centerTile = (int)(constructionYards[i].centre.x*64)/16 + (127 - (int)(constructionYards[i].centre.z*64)/16)*128;
for(int j = 0; j < buildingPlacementCheckTiles.length; j++){
if(buildingPlacementCheckTiles_2x2[j] != Integer.MAX_VALUE){
placementTile = centerTile + buildingPlacementCheckTiles_2x2[j];
int x = placementTile%128;
int y = placementTile/128;
boolean tooCloseToOtherCommunicationCenter = false;
for(int k = 0; k < mainThread.theAssetManager.communicationCenters.length; k++){
if(mainThread.theAssetManager.communicationCenters[k] != null && mainThread.theAssetManager.communicationCenters[k].teamNo != 0){
int x_ = mainThread.theAssetManager.communicationCenters[k].tileIndex[0]%128;
int y_ = mainThread.theAssetManager.communicationCenters[k].tileIndex[0]/128;
if(Math.abs(x - x_) + Math.abs(y - y_) <= 14){
tooCloseToOtherCommunicationCenter = true;
break;
}
}
}
if(tooCloseToOtherCommunicationCenter){
continue;
}
if(!checkIfBlockIsFree(placementTile)){ continue;}
if(!checkIfBlockIsFree(placementTile+1)){ continue;}
if(!checkIfBlockIsFree(placementTile + 128)){ continue;}
if(!checkIfBlockIsFree(placementTile + 129)){ continue;}
if(!checkIfBlockIsFree(placementTile - 129)){ continue;}
if(!checkIfBlockIsFree(placementTile + 257)){ continue;}
if(!checkIfBlockIsFree(placementTile - 127)){ continue;}
if(!checkIfBlockIsFree(placementTile +255)){ continue;}
if(!checkIfBlockIsFree(placementTile + 127)){ continue;}
return true;
}
}
}
}
}
//check placement for tech center
if(buildingType == 107){
if(centerTile == -1){
constructionYard[] constructionYards = mainThread.theAssetManager.constructionYards;
for(int i = 0; i < constructionYards.length; i++){
if(constructionYards[i] == null)
continue;
if(constructionYards[i].teamNo == 0)
continue;
centerTile = (int)(constructionYards[i].centre.x*64)/16 + (127 - (int)(constructionYards[i].centre.z*64)/16)*128;
for(int j = 0; j < buildingPlacementCheckTiles.length; j++){
if(buildingPlacementCheckTiles_2x2[j] != Integer.MAX_VALUE){
placementTile = centerTile + buildingPlacementCheckTiles_2x2[j];
if(!checkIfBlockIsFree(placementTile)){ continue;}
if(!checkIfBlockIsFree(placementTile+1)){ continue;}
if(!checkIfBlockIsFree(placementTile + 128)){ continue;}
if(!checkIfBlockIsFree(placementTile + 129)){ continue;}
if(!checkIfBlockIsFree(placementTile - 129)){ continue;}
if(!checkIfBlockIsFree(placementTile + 257)){ continue;}
if(!checkIfBlockIsFree(placementTile - 127)){ continue;}
if(!checkIfBlockIsFree(placementTile + 255)){ continue;}
if(!checkIfBlockIsFree(placementTile + 127)){ continue;}
return true;
}
}
}
}
}
return false;
}
public boolean checkIfBlockIsFree(int index){
int y = index/128;
int x = index%128;
if(y > 0 && y < 127 && x > 0 && x < 127){
solidObject[] tile = mainThread.gridMap.tiles[index];
for(int j = 0; j < 5; j++){
if(tile[j] != null){
return false;
}
}
if(mainThread.ec.theEconomyManagerAI.preferedGoldMine != null){
int location = mainThread.ec.theEconomyManagerAI.preferedGoldMine.tileIndex[1];
if( index == location - 128 || index == location - 129 || index == location - 130 || index == location - 2 ||
index == location + 126 || index == location + 254 || index == location + 255 || index == location + 256 ||
index == location + 257 || index == location + 129 || index == location + 1 || index == location-127){
return false;
}
}
constructionYard[] constructionYards = mainThread.theAssetManager.constructionYards;
for(int i = 0; i < constructionYards.length; i++){
if(constructionYards[i] != null && constructionYards[i].teamNo != 0){
float xPos = x * 0.25f + 0.125f;
float yPos = (127 - y)*0.25f + 0.125f;
float distance = (float) Math.sqrt((constructionYards[i].centre.x - xPos)*(constructionYards[i].centre.x - xPos) + (constructionYards[i].centre.z - yPos)*(constructionYards[i].centre.z - yPos));
if(distance <= 2.75){
return true;
}
}
}
return false;
}else{
return false;
}
}
public boolean buildingUnderProduction(int buildingType){
boolean alreadyInQueue = false;
constructionYard[] constructionYards = mainThread.theAssetManager.constructionYards;
for(int i = 0; i < constructionYards.length; i ++){
if(constructionYards[i] != null && constructionYards[i].teamNo != 0){
if(constructionYards[i].currentBuildingType == buildingType){
alreadyInQueue = true;
break;
}
}
}
return alreadyInQueue;
}
public int findFactoryDeployLocation(){
constructionYard[] constructionYards = mainThread.theAssetManager.constructionYards;
factory[] factories = mainThread.theAssetManager.factories;
for(int i = 0; i < constructionYards.length; i++){
if(constructionYards[i] == null || constructionYards[i].teamNo == 0)
continue;
int numberOfFactories = 0;
for(int j= 0; j < factories.length; j++){
if(factories[j] == null || factories[j].teamNo == 0)
continue;
if(constructionYards[i].getDistance(factories[j]) < 3)
numberOfFactories++;
}
if(numberOfFactories >= 2 && (Math.abs((constructionYards[i].centre.x /constructionYards[i].centre.z)) > 4 || Math.abs((constructionYards[i].centre.x /constructionYards[i].centre.z)) < 0.25))
continue;
if(numberOfFactories < 3){
return (int)(constructionYards[i].centre.x*64)/16 + (127 - (int)(constructionYards[i].centre.z*64)/16)*128;
}
}
return -1;
}
public int getNumberOfRefineriesNearPreferedGoldMine(){
int numberOfRefineriesNearPreferedGoldMine = 0;
refinery[] refineries = mainThread.theAssetManager.refineries;
for(int i = 0; i < refineries.length; i++){
if(refineries[i] != null && refineries[i].teamNo != 0){
if(mainThread.ec.theEconomyManagerAI.preferedGoldMine.getDistance(refineries[i]) < 2.5){
numberOfRefineriesNearPreferedGoldMine++;
}
}
}
return numberOfRefineriesNearPreferedGoldMine;
}
public int getNumberOfFunctionalRefinery(){
int numberOfFunctionalRefinery = 0;
refinery[] refineries = mainThread.theAssetManager.refineries;
for(int i = 0; i < refineries.length; i++){
if(refineries[i] != null && refineries[i].teamNo != 0 && refineries[i].nearestGoldMine != null && refineries[i].nearestGoldMine.goldDeposite > 10000){
numberOfFunctionalRefinery++;
}
}
return numberOfFunctionalRefinery;
}
}

View File

@ -0,0 +1,589 @@
package enemyAI;
import core.baseInfo;
import core.mainThread;
import core.vector;
import entity.goldMine;
import entity.solidObject;
import entity.techCenter;
//this agent makes all the high level combat decisions
public class combatManagerAI {
public baseInfo theBaseInfo;
public int frameAI;
public int currentState;
public final int booming = 0;
public final int aggressing = 1;
public final int defending = 2;
public goldMine[] goldMines;
float distanceToTarget;
public vector gatherPoint, attackDirection, attackPosition;
public solidObject unNeutralizedEntity;
public solidObject[] team;
public int numberOfUnitInCombatRadius;
public int numberOfUnitOutsideCombatRadius;
public float unitInCombactRadiusPercentage;
public solidObject[] unitInCombatRadius;
public solidObject[] unitOutsideCombatRadius;
public solidObject[] troopsControlledByCombatAI;
public solidObject[] playerUnitInMinimap;
public vector playerForceCenter;
public vector adjustedAttackDirection;
public int withdrawUnitOutsideCombatRadiusCooldown;
public float maxPlayerForceStrengthRoundAttacker;
public float combatCenterX, combatCenterZ;
public float myRallyPointX, myRallyPointZ;
public boolean rallyPointChanged;
boolean shouldDefenceAggressively;
public float offScreenPlayerForceStrength;
public combatManagerAI(baseInfo theBaseInfo){
this.theBaseInfo = theBaseInfo;
goldMines = mainThread.theAssetManager.goldMines;
gatherPoint = new vector(-1,-1,-1);
attackDirection = new vector(0,0,0);
attackPosition = new vector(0,0,0);
playerForceCenter = new vector(0,0,0);
adjustedAttackDirection = new vector(0,0,0);
}
//check if player has expansions
//if player has expansion(s) then find the one that is least defended
//compare player force with its own force
//if AI thinks its has a comparable or greater force than the player, attack player's expansion and switch to aggressing mode
//if AI is under significant threat, switch to defending mode
public void processAI(){
frameAI++;
//assume player force gets stronger as time goes by
if(offScreenPlayerForceStrength < 0)
offScreenPlayerForceStrength = 0;
if(frameAI > 150)
offScreenPlayerForceStrength+=0.075f;
//checkIfAIHasBiggerForce(1);
if(withdrawUnitOutsideCombatRadiusCooldown > 0){
withdrawUnitOutsideCombatRadiusCooldown --;
}else{
maxPlayerForceStrengthRoundAttacker = 0;
}
team = mainThread.ec.theUnitProductionAI.troopsControlledByCombatAI;
numberOfUnitInCombatRadius = mainThread.ec.theUnitProductionAI.numberOfUnitInCombatRadius;
numberOfUnitOutsideCombatRadius = mainThread.ec.theUnitProductionAI.numberOfUnitOutsideCombatRadius;
unitInCombatRadius = mainThread.ec.theUnitProductionAI.unitInCombatRadius;
unitOutsideCombatRadius = mainThread.ec.theUnitProductionAI.unitOutsideCombatRadius;
troopsControlledByCombatAI = mainThread.ec.theUnitProductionAI.troopsControlledByCombatAI;
playerUnitInMinimap = mainThread.ec.theMapAwarenessAI.playerUnitInMinimap;
shouldDefenceAggressively = checkIfAIHasBiggerForce(1.6f);
combatCenterX = mainThread.ec.theUnitProductionAI.combatAICenterX;
combatCenterZ = mainThread.ec.theUnitProductionAI.combatAICenterZ;
if(Float.isNaN(combatCenterX) || Float.isNaN(combatCenterZ)) {
// combatCenterX = 0;
// combatCenterZ= 0;
}
boolean frontalTroopIverwhelmed = false;
boolean shouldAttack = false;
boolean playerHasBecomeStrongerThanAIDuringMarching = false;
rallyPointChanged = false;
if(myRallyPointX != mainThread.ec.theUnitProductionAI.rallyPoint.x){
myRallyPointX = mainThread.ec.theUnitProductionAI.rallyPoint.x;
myRallyPointZ = mainThread.ec.theUnitProductionAI.rallyPoint.z;
rallyPointChanged = true;
}
if(currentState == booming){
//enemy AI compares its own force with player's force, then make a decision whether it should attack or not
//only start comparing after 6 minutes mark, or player is rushing with light tank delay attack mark to around 10 minutes mark
int attackTime = 360;
if(mainThread.ec.theMapAwarenessAI.playerIsRushingLightTank)
attackTime = 540;
else
attackTime = 360;
int targetPlayerExpension = mainThread.ec.theMapAwarenessAI.targetPlayerExpension;
if(frameAI > attackTime) {
if(targetPlayerExpension == 2 || targetPlayerExpension == 4 || targetPlayerExpension == 6 || targetPlayerExpension == 7)
shouldAttack = checkIfAIHasBiggerForce(1.2f);
else
shouldAttack = checkIfAIHasBiggerForce(0.9f);
}
if(shouldAttack){
if(targetPlayerExpension != -1){
currentState = aggressing;
attackDirection.set(goldMines[targetPlayerExpension].centre.x - combatCenterX, 0, goldMines[targetPlayerExpension].centre.z - combatCenterZ);
attackDirection.unit();
attackPosition.set(goldMines[targetPlayerExpension].centre);
attackPosition.add(attackDirection);
return;
}else{
//if no enemy structure found around gold mines, set attack position to a revealed enemy building or unit
solidObject[] playerStructures = mainThread.ec.theMapAwarenessAI.playerStructures;
solidObject[] playerUnitInMinimap = mainThread.ec.theMapAwarenessAI.playerUnitInMinimap;
attackDirection.set(0,0,0);
for(int i = 0; i < playerStructures.length; i++){
if(playerStructures[i] != null && playerStructures[i].currentHP > 0){
currentState = aggressing;
attackDirection.set(playerStructures[i].centre.x - combatCenterX, 0, playerStructures[i].centre.z - combatCenterZ);
attackDirection.unit();
attackPosition.set(playerStructures[i].centre);
attackPosition.add(attackDirection);
return;
}
}
if(attackDirection.x == 0 && attackDirection.z ==0){
for(int i = 0; i < playerUnitInMinimap.length; i++){
if(playerUnitInMinimap[i] != null && playerUnitInMinimap[i].currentHP > 0){
currentState = aggressing;
attackDirection.set(playerUnitInMinimap[i].centre.x - combatCenterX, 0, playerUnitInMinimap[i].centre.z - combatCenterZ);
attackDirection.unit();
attackPosition.set(playerUnitInMinimap[i].centre);
attackPosition.add(attackDirection);
return;
}
}
}
//if AI couldn't find a player base nor player's unit then set the attack position to the player spawning point
currentState = aggressing;
attackDirection.set(goldMines[0].centre.x - combatCenterX, 0, goldMines[0].centre.z - combatCenterZ);
attackDirection.unit();
attackPosition.set(goldMines[0].centre);
attackPosition.add(attackDirection);
}
}else {
//check if there are any player units/structures near the combat center
solidObject[] playerUnitInMinimap = mainThread.ec.theMapAwarenessAI.playerUnitInMinimap;
solidObject[] playerStructures = mainThread.ec.theMapAwarenessAI.playerStructures;
for(int i = 0; i < playerUnitInMinimap.length; i++) {
if(playerUnitInMinimap[i] != null && playerUnitInMinimap[i].currentHP > 0) {
double d = Math.sqrt((combatCenterX - playerUnitInMinimap[i].centre.x)*(combatCenterX - playerUnitInMinimap[i].centre.x) + (combatCenterZ - playerUnitInMinimap[i].centre.z)*(combatCenterZ - playerUnitInMinimap[i].centre.z));
if(d < 5){
currentState = aggressing;
attackDirection.set(playerUnitInMinimap[i].centre.x - combatCenterX, 0, playerUnitInMinimap[i].centre.z - combatCenterZ);
attackDirection.unit();
attackPosition.set(playerUnitInMinimap[i].centre);
if(shouldDefenceAggressively)
attackPosition.add(attackDirection);
return;
}
}
}
}
if(currentState != aggressing) {
if(rallyPointChanged || Math.abs(myRallyPointX - combatCenterX) > 1 || Math.abs(myRallyPointZ - combatCenterZ) > 1){
for(int i =0 ; i < troopsControlledByCombatAI.length; i++){
if(troopsControlledByCombatAI[i] != null && troopsControlledByCombatAI[i].currentHP > 0){
troopsControlledByCombatAI[i].attackMoveTo(myRallyPointX, myRallyPointZ);
troopsControlledByCombatAI[i].currentCommand = solidObject.attackMove;
troopsControlledByCombatAI[i].secondaryCommand = solidObject.attackMove;
}
}
}
}
}else if(currentState == aggressing){
attackDirection.set(attackPosition.x - combatCenterX, 0, attackPosition.z - combatCenterZ);
distanceToTarget = attackDirection.getLength();
attackDirection.unit();
//check if the target position has been neutralized
solidObject[] playerUnitInMinimap = mainThread.ec.theMapAwarenessAI.playerUnitInMinimap;
solidObject[] playerStructures = mainThread.ec.theMapAwarenessAI.playerStructures;
unNeutralizedEntity = null;
//look for revealed player building structures
for(int i = 0; i < playerStructures.length; i++){
if(playerStructures[i] != null){
if((playerStructures[i].centre.x - attackPosition.x)*(playerStructures[i].centre.x - attackPosition.x) + (playerStructures[i].centre.z - attackPosition.z)*(playerStructures[i].centre.z - attackPosition.z) < 16){
unNeutralizedEntity = playerStructures[i];
attackPosition.set(playerStructures[i].centre);
break;
}
}
}
//if there is no player structure found, then look for player units
boolean needResetAttackPosition = false;
if(unNeutralizedEntity == null){
for(int i = 0; i < playerUnitInMinimap.length; i++){
if(playerUnitInMinimap[i] != null){
unNeutralizedEntity = playerUnitInMinimap[i];
needResetAttackPosition = true;
if((playerUnitInMinimap[i].centre.x - attackPosition.x)*(playerUnitInMinimap[i].centre.x - attackPosition.x) + (playerUnitInMinimap[i].centre.z - attackPosition.z)*(playerUnitInMinimap[i].centre.z - attackPosition.z) < 16){
needResetAttackPosition = false;
break;
}
}
}
}
if(needResetAttackPosition) {
attackPosition.set(unNeutralizedEntity.centre);
}
//if front portion of the troops are under attack, set the attack position to the attacker
for(int i = 0; i < numberOfUnitInCombatRadius; i++){
if(unitInCombatRadius[i].underAttackCountDown > 0){
attackPosition.set(unitInCombatRadius[i].attacker.centre);
unNeutralizedEntity = unitInCombatRadius[i].attacker;
break;
}
}
//check if the front portion of the troops are overwhelmed by player force
float playerForceStrengthNearCombatCenter = checkPlayerForceStrengthAroundOnePoint(playerUnitInMinimap, combatCenterX + attackDirection.x, combatCenterZ + attackDirection.z, 4);
if((playerForceStrengthNearCombatCenter+1)/(getAIForceStrength(unitInCombatRadius)+1) > 2f){
frontalTroopIverwhelmed = true;
}
//check if the player force has become stronger than the AI during the marching towards attack position
//System.out.println("distanceToTarget: " + distanceToTarget);
if(checkIfAIHasBiggerForce(1) == false && distanceToTarget > 5){
playerHasBecomeStrongerThanAIDuringMarching = true;
}
//check if the troops has encountered a concentration of enemy static defense
//send units to attack-move to target position
if(!playerHasBecomeStrongerThanAIDuringMarching && !frontalTroopIverwhelmed && (unNeutralizedEntity != null || distanceToTarget > 2)){
//if the tail portion of the troops are under attack, send them back to base instead of throwing them into player's trap
float AIForceStrengthOutsideCombatRadius = getAIForceStrength(unitOutsideCombatRadius);
maxPlayerForceStrengthRoundAttacker = 0;
for(int i = 0; i < numberOfUnitOutsideCombatRadius; i++){
if(unitOutsideCombatRadius[i].underAttackCountDown > 0 && unitOutsideCombatRadius[i].attacker != null){
//check the number of hostile units around the attacker
playerForceStrengthNearCombatCenter = checkPlayerForceStrengthAroundOnePoint(playerUnitInMinimap, unitOutsideCombatRadius[i].attacker.centre.x, unitOutsideCombatRadius[i].attacker.centre.z, 4);
if(playerForceStrengthNearCombatCenter > maxPlayerForceStrengthRoundAttacker)
maxPlayerForceStrengthRoundAttacker = playerForceStrengthNearCombatCenter;
}
//check if there are too many hostile units
if(maxPlayerForceStrengthRoundAttacker > AIForceStrengthOutsideCombatRadius){
if(withdrawUnitOutsideCombatRadiusCooldown == 0)
withdrawUnitOutsideCombatRadiusCooldown = 30;
break;
}
}
if(withdrawUnitOutsideCombatRadiusCooldown > 0){
team = unitInCombatRadius; //exclude the tail portion of the troops from the attack force
for(int i = 0; i < troopsControlledByCombatAI.length; i++){
//send the tail portion of the troops to rally point
if(troopsControlledByCombatAI[i] != null && troopsControlledByCombatAI[i].currentHP > 0){
troopsControlledByCombatAI[i].attackMoveTo(mainThread.ec.theUnitProductionAI.rallyPoint.x, mainThread.ec.theUnitProductionAI.rallyPoint.z);
troopsControlledByCombatAI[i].currentCommand = solidObject.attackMove;
troopsControlledByCombatAI[i].secondaryCommand = solidObject.attackMove;
}
}
}
if(unNeutralizedEntity != null){
attackDirection.set(unNeutralizedEntity.centre.x - combatCenterX, 0, unNeutralizedEntity.centre.z - combatCenterZ);
distanceToTarget = attackDirection.getLength();
attackDirection.unit();
}
everyoneAttackTargetPosition();
}else{
//if target position has been neutralized, change status to booming
currentState = booming;
float gatherPointX, gatherPointZ;
//if the change of state is caused by heavy causality of the AI player then move move every unit back to rally point
if(frontalTroopIverwhelmed || playerHasBecomeStrongerThanAIDuringMarching){
gatherPointX = mainThread.ec.theUnitProductionAI.rallyPoint.x;
gatherPointZ = mainThread.ec.theUnitProductionAI.rallyPoint.z;
}else {
//if the AI really couldn't find any targets then gather every units at the current combat center
gatherPointX = combatCenterX;
gatherPointZ = combatCenterZ;
}
for(int i = 0; i < numberOfUnitOutsideCombatRadius; i++){
//send the tail portion of the troops to rally point
unitOutsideCombatRadius[i].attackMoveTo(gatherPointX, gatherPointZ);
unitOutsideCombatRadius[i].currentCommand = solidObject.attackMove;
unitOutsideCombatRadius[i].secondaryCommand = solidObject.attackMove;
}
for(int i = 0; i < numberOfUnitInCombatRadius; i++){
//send the tail portion of the troops to rally point
if(unitInCombatRadius[i].attackStatus != solidObject.isAttacking){
unitInCombatRadius[i].attackMoveTo(gatherPointX, gatherPointZ);
unitInCombatRadius[i].currentCommand = solidObject.attackMove;
unitInCombatRadius[i].secondaryCommand = solidObject.attackMove;
}
}
}
}
}
//attack a target location with all the forces
public void everyoneAttackTargetPosition(){
//Find a gather location for an attack. The attacking units will first try to gather around a location that in between the target location and the attack force's center point.
//When the majority attacking units arrive around the gather point, the attack will proceed towards the target location.
//The purpose of doing this is to keep the attack units together when across long distance,
float teamRadius = (float)Math.sqrt(mainThread.ec.theUnitProductionAI.numberOfCombatUnit)/2.5f;
if(distanceToTarget < 3 + teamRadius && unNeutralizedEntity != null){
//adjust the attack location for better engagement
playerForceCenter.set(0,0,0);
int numOfPlayerUnitsInMinimap = 0;
for(int i = 0; i < playerUnitInMinimap.length; i++){
if(playerUnitInMinimap[i] != null && playerUnitInMinimap[i].currentHP > 0){
float playerCenterX = playerUnitInMinimap[i].centre.x;
float playerCenterZ = playerUnitInMinimap[i].centre.z;
if((playerCenterX - combatCenterX)*(playerCenterX - combatCenterX) + (playerCenterZ - combatCenterZ)*(playerCenterZ - combatCenterZ) < 9){
playerForceCenter.x+=playerCenterX;
playerForceCenter.z+=playerCenterZ;
numOfPlayerUnitsInMinimap++;
}
}
}
if(numOfPlayerUnitsInMinimap >0){
playerForceCenter.x/=numOfPlayerUnitsInMinimap;
playerForceCenter.z/=numOfPlayerUnitsInMinimap;
}else{
playerForceCenter.x= attackPosition.x;
playerForceCenter.z= attackPosition.z;
}
adjustedAttackDirection.set(playerForceCenter.x - combatCenterX, 0, playerForceCenter.z - combatCenterZ);
adjustedAttackDirection.unit();
adjustedAttackDirection.scale(20);
for(int i = 0; i < mainThread.ec.theUnitProductionAI.numberOfCombatUnit; i++){
if(team[i] != null && team[i].currentHP > 0){
if(!((team[i].secondaryDestinationX == attackPosition.x && team[i].secondaryDestinationY == attackPosition.z)
|| (team[i].secondaryDestinationX == unNeutralizedEntity.centre.x && team[i].secondaryDestinationY == unNeutralizedEntity.centre.z))){
if(team[i].attackStatus != solidObject.isAttacking){
team[i].attackMoveTo(playerForceCenter.x + adjustedAttackDirection.x, playerForceCenter.z + adjustedAttackDirection.z);
team[i].currentCommand = solidObject.attackMove;
team[i].secondaryCommand = solidObject.attackMove;
}
team[i].secondaryDestinationX = attackPosition.x;
team[i].secondaryDestinationY = attackPosition.z;
}
}
}
}else{
for(int i = 0; i < 3; i++){
gatherPoint.set(combatCenterX + attackDirection.x*(teamRadius+1*i), 0, combatCenterZ + attackDirection.z*(teamRadius+ 1*i));
//if the gather point is inside a water body them move the gather point forward
int tileIndex = (int)(gatherPoint.x*64)/16 + (127 - ((int)(gatherPoint.z*64))/16)*128;
if(tileIndex >= mainThread.gridMap.tiles.length || tileIndex < 0)
break;
if(mainThread.gridMap.tiles[tileIndex][0] != null && mainThread.gridMap.tiles[tileIndex][0].type == 4)
continue;
else
break;
}
for(int i = 0; i < mainThread.ec.theUnitProductionAI.numberOfCombatUnit; i++){
if(team[i] != null && team[i].currentHP > 0){
//stop chasing player unit if it has got out of sight
if(team[i].targetObject != null && team[i].targetObject.currentHP >0) {
int targetPositionIndex = (int)(team[i].targetObject.centre.x*64)/16 + (127 - (int)(team[i].targetObject.centre.z*64)/16)*128;
if(team[i].attackStatus != solidObject.isAttacking && team[i].underAttackCountDown == 0 && (!mainThread.ec.visionMap[targetPositionIndex] || team[i].targetObject.isCloaked))
team[i].targetObject = null;
}
//marching forward
if((team[i].targetObject == null || team[i].targetObject.currentHP <=0) && !(team[i].currentMovementStatus == solidObject.hugRight || team[i].currentMovementStatus == solidObject.hugLeft)){
double d = Math.sqrt((team[i].centre.x - combatCenterX)*(team[i].centre.x - combatCenterX) + (team[i].centre.z - combatCenterZ)*(team[i].centre.z - combatCenterZ))*3;
if(d > teamRadius){
team[i].attackMoveTo(gatherPoint.x, gatherPoint.z);
}else{
team[i].attackMoveTo(team[i].centre.x + attackDirection.x*teamRadius, team[i].centre.z + attackDirection.z*teamRadius);
}
team[i].currentCommand = solidObject.attackMove;
team[i].secondaryCommand = solidObject.attackMove;
}
}
}
}
//make sure idle units are send to attack unNeutralized target
if(unNeutralizedEntity != null){
for(int i = 0; i < mainThread.ec.theUnitProductionAI.numberOfCombatUnit; i++){
if(team[i] != null && team[i].currentHP > 0){
if(team[i].currentCommand == solidObject.StandBy || (team[i].targetObject == null && (team[i].secondaryDestinationX != unNeutralizedEntity.centre.x || team[i].secondaryDestinationY != unNeutralizedEntity.centre.z))){
float d = (team[i].centre.x - attackPosition.x)*(team[i].centre.x - attackPosition.x) + (team[i].centre.z - attackPosition.z)*(team[i].centre.z - attackPosition.z);
if(d < 9){
team[i].attackMoveTo(unNeutralizedEntity.centre.x, unNeutralizedEntity.centre.z);
team[i].currentCommand = solidObject.attackMove;
team[i].secondaryCommand = solidObject.attackMove;
}
}
}
}
}
}
public float checkPlayerForceStrengthAroundOnePoint(solidObject[] listOfUnits, float x, float z, double distanceThreshold){
float playerForceStrength = 0;
for(int j = 0; j < listOfUnits.length; j++){
if(listOfUnits[j] != null && listOfUnits[j].currentHP > 0){
double d = (listOfUnits[j].centre.x - x)*(listOfUnits[j].centre.x - x)
+ (listOfUnits[j].centre.z - z)*(listOfUnits[j].centre.z - z);
if(d < distanceThreshold){
if(listOfUnits[j].type == 0 || listOfUnits[j].type == 1)
playerForceStrength+=1;
else if(listOfUnits[j].type == 6)
playerForceStrength+=1.5f;
else if(listOfUnits[j].type == 7)
playerForceStrength+=3;
}
}
}
return playerForceStrength;
}
public float getAIForceStrength(solidObject[] listOfUnits){
float AIForceStrength = 0;
for(int j = 0; j < listOfUnits.length; j++){
if(listOfUnits[j] != null && listOfUnits[j].currentHP > 0){
if(listOfUnits[j].type == 0 || listOfUnits[j].type == 1)
AIForceStrength+=1;
else if(listOfUnits[j].type == 6)
AIForceStrength+=1.5f;
else if(listOfUnits[j].type == 7)
AIForceStrength+=3;
}
}
return AIForceStrength;
}
public boolean checkIfAIHasBiggerForce(float ratio){
int numberOfLightTanks_AI = mainThread.ec.theUnitProductionAI.numberOfLightTanksControlledByCombatAI;
int numberOfRocketTanks_AI = mainThread.ec.theUnitProductionAI.numberOfRocketTanksControlledByCombatAI;
int numberOfStealthTanks_AI = mainThread.ec.theUnitProductionAI.numberOfStealthTanksControlledByCombatAI;
int numberOfHeavyTanks_AI = mainThread.ec.theUnitProductionAI.numberOfHeavyTanksControlledByCombatAI;
int numberOfLightTanks_player = mainThread.ec.theMapAwarenessAI.numberOfLightTanks_player;
int numberOfRocketTanks_player = mainThread.ec.theMapAwarenessAI.numberOfRocketTanks_player;
int numberOfStealthTanks_player = mainThread.ec.theMapAwarenessAI.numberOfStealthTanks_player;
int numberOfHeavyTanks_player = mainThread.ec.theMapAwarenessAI.numberOfHeavyTanks_player;
float m3 = 1.5f;
if(techCenter.stealthTankResearched_enemy == true && numberOfHeavyTanks_player < 4 && numberOfStealthTanks_AI > numberOfStealthTanks_player * 2)
m3+=0.5f;
if(techCenter.stealthTankResearched_enemy == true && mainThread.ec.theMapAwarenessAI.playerHasMostlyLightTanks){
m3+=0.5f;
}
float m1 = 1;
if(mainThread.ec.theMapAwarenessAI.playerHasMostlyHeavyTanks){
m1 = 1.2f;
if(techCenter.lightTankResearched_enemy == true && numberOfStealthTanks_player < 5){
m1=1.75f;
}
}
double enemyAIForceStrength = m1*numberOfLightTanks_AI + 0.75f*numberOfRocketTanks_AI + m3*(numberOfStealthTanks_AI-mainThread.ec.theBaseExpentionAI.numberOfStealthTankScout) + 3* numberOfHeavyTanks_AI;
double playerForceStrength = offScreenPlayerForceStrength + numberOfLightTanks_player + 0.75f*numberOfRocketTanks_player + 1.5*numberOfStealthTanks_player + 3* numberOfHeavyTanks_player;
//System.out.println("offScreenPlayerForceStrength" + offScreenPlayerForceStrength + " " + "enemyAIForceStrength " + enemyAIForceStrength + " " + "playerForceStrength" + playerForceStrength);
return enemyAIForceStrength > 0 && playerForceStrength/enemyAIForceStrength < ratio;
}
}

View File

@ -0,0 +1,166 @@
package enemyAI;
import core.baseInfo;
import core.mainThread;
import core.vector;
import entity.solidObject;
import entity.stealthTank;
public class defenseManagerAI {
public baseInfo theBaseInfo;
public int gameTime;
public int currentState;
public final int booming = 0;
public final int aggressing = 1;
public final int defending = 2;
public solidObject[] observers;
public solidObject[] stealthTanksControlledByCombatAI;
public vector direction;
public defenseManagerAI(baseInfo theBaseInfo){
this.theBaseInfo = theBaseInfo;
observers = new solidObject[4];
direction = new vector(0,0,0);
}
//at 500 seconds mark, send 2 observers to the 2 western and southern side of the main base. After grabbing the northwest (or southeast, depends on which expansion get grabbed first) expansion
//send 2 additional observers to look for player sneak attacks
public void processAI(){
gameTime++;
currentState = mainThread.ec.theCombatManagerAI.currentState;
stealthTanksControlledByCombatAI = mainThread.ec.theUnitProductionAI.stealthTanksControlledByCombatAI;
//after 500 seconds mark, borrow 2 stealth tanks from combat manager, and send them to guard western and southern side of the main base
if(gameTime >= 480) {
for(int i = 0; i < 2; i++) {
if(observers[i] == null || observers[i].currentHP <=0) {
for(int j = 0; j < stealthTanksControlledByCombatAI.length; j++) {
if(stealthTanksControlledByCombatAI[j] != null && stealthTanksControlledByCombatAI[j].currentHP == 80 && stealthTanksControlledByCombatAI[j].attackStatus != solidObject.isAttacking) {
observers[i] = stealthTanksControlledByCombatAI[j];
stealthTanksControlledByCombatAI[j] = null;
float xPos = 21f;
float zPos = 30.5f;
if(i == 1) {
xPos = 30f;
zPos = 20f;
}
observers[i].moveTo(xPos, zPos);
observers[i].currentCommand = solidObject.move;
observers[i].secondaryCommand = solidObject.StandBy;
break;
}
}
}
}
}
//keep an eye on player units and avoid being detected
for(int i = 0; i < observers.length; i++) {
if(observers[i] != null) {
if(!evadePlayerUnit(i)) {
float xPos = 0;
float zPos = 0;
//if there is no player units in sight, return to patrol position
if(i == 0) {
if(gameTime%30 < 15) {
xPos = 19f;
zPos = 30.5f;
}else {
xPos = 19f;
zPos = 22.5f;
}
}
if(i == 1) {
if(gameTime%20 < 10) {
xPos = 30f;
zPos = 20f;
}else {
xPos = 26f;
zPos = 20f;
}
}
observers[i].moveTo(xPos, zPos);
observers[i].currentCommand = solidObject.move;
observers[i].secondaryCommand = solidObject.StandBy;
}
}
}
}
public boolean evadePlayerUnit(int observerIndex){
//scan for hostile unit
int[] tileCheckList = stealthTank.tileCheckList;
int currentOccupiedTile = (int)(observers[observerIndex].centre.x*64)/16 + (127 - (int)(observers[observerIndex].centre.z*64)/16)*128;
direction.set(0,0,0);
boolean directionSet = false;
for(int i = 0; i < tileCheckList.length; i++){
if(tileCheckList[i] != Integer.MAX_VALUE){
int index = currentOccupiedTile + tileCheckList[i];
if(index < 0 || index >= 16384 || Math.abs(index%128 - currentOccupiedTile%128) > 20)
continue;
solidObject[] tile = mainThread.gridMap.tiles[index];
for(int j = 0; j < 4; j++){
if(tile[j] != null){
if(tile[j].teamNo != observers[observerIndex].teamNo && tile[j].teamNo != -1 && tile[j].currentHP > 0 && !tile[j].isCloaked){
if(directionSet)
break;
double d = Math.sqrt((tile[j].centre.x - observers[observerIndex].centre.x)*(tile[j].centre.x - observers[observerIndex].centre.x)
+ (tile[j].centre.z - observers[observerIndex].centre.z)*(tile[j].centre.z - observers[observerIndex].centre.z));
if(d < 0.75) {
direction.set(observers[observerIndex].centre);
direction.subtract(tile[j].centre);
direction.unit();
directionSet = true;
}
}
}
}
}
}
if(directionSet) {
observers[observerIndex].moveTo(observers[observerIndex].centre.x + direction.x , observers[observerIndex].centre.z + direction.z);
observers[observerIndex].currentCommand = solidObject.move;
observers[observerIndex].secondaryCommand = solidObject.StandBy;
}
return directionSet;
}
}

View File

@ -0,0 +1,161 @@
package enemyAI;
import core.baseInfo;
import core.mainThread;
import core.vector;
import entity.constructionYard;
import entity.goldMine;
import entity.harvester;
public class economyManagerAI {
//this represent the cloest gold mine to the enemy player's constructionyard
public goldMine preferedGoldMine;
public int preferedGoldMineLocation;
public baseInfo theBaseInfo;
public int numberOfharvesters;
public vector evadeDirection;
public economyManagerAI(baseInfo theBaseInfo){
this.theBaseInfo = theBaseInfo;
evadeDirection = new vector(0,0,0);
}
public void processAI(){
//find an ideal goldmine
goldMine[] goldMines = mainThread.theAssetManager.goldMines;
constructionYard[] constructionYards = mainThread.theAssetManager.constructionYards;
if(preferedGoldMine == null || preferedGoldMine.goldDeposite <= 10){
float distance = 100000;
for(int i = 0; i < constructionYards.length; i++){
if(constructionYards[i] != null && constructionYards[i].teamNo != 0){
for(int j = 0; j < goldMines.length; j++){
if(goldMines[j] == null || goldMines[j].goldDeposite <=10)
continue;
float newDistance = (goldMines[j].centre.x - constructionYards[i].centre.x)*(goldMines[j].centre.x - constructionYards[i].centre.x)
+(goldMines[j].centre.z - constructionYards[i].centre.z)*(goldMines[j].centre.z - constructionYards[i].centre.z);
if( newDistance < distance){
preferedGoldMine = goldMines[j];
distance = newDistance;
}
}
}
}
}
preferedGoldMineLocation = (int)(preferedGoldMine.centre.x*64)/16 + (127 - (int)(preferedGoldMine.centre.z*64)/16)*128;
//count number of harvesters and prevent them from doing something stupid
int numberOfHarvesterOnQueue = 0;
for(int i = 0; i < mainThread.theAssetManager.factories.length; i++){
if(mainThread.theAssetManager.factories[i] != null && mainThread.theAssetManager.factories[i].teamNo != 0){
if(preferedGoldMine != null)
mainThread.theAssetManager.factories[i].targetGoldMine = preferedGoldMine;
numberOfHarvesterOnQueue += mainThread.theAssetManager.factories[i].numOfHarvesterOnQueue;
}
}
for(int i = 0; i < mainThread.theAssetManager.constructionYards.length; i++){
if(mainThread.theAssetManager.constructionYards[i] != null && mainThread.theAssetManager.constructionYards[i].teamNo != 0){
if(mainThread.theAssetManager.constructionYards[i].currentBuildingType == 102)
numberOfHarvesterOnQueue += 1;
}
}
numberOfharvesters = 0;
for(int i = 0; i < mainThread.theAssetManager.harvesters.length; i++){
if(mainThread.theAssetManager.harvesters[i] != null && mainThread.theAssetManager.harvesters[i].teamNo != 0){
numberOfharvesters++;
harvester o = mainThread.theAssetManager.harvesters[i];
if(o.movement.x == 0 && o.movement.z == 0){
if(o.cargoDeposite > 0 && o.jobStatus == 0){
o.returnToRefinery(null);
}
}
//when current gold mine run out of gold, direct harvester to the nearest goldmines which still have deposit
if(o.cargoDeposite == 0 && o.myGoldMine != null && o.myGoldMine.goldDeposite <= 1){
if(preferedGoldMine != null){
boolean hasRefineryNearby = false;
for(int j = 0; j < mainThread.theAssetManager.refineries.length; j++){
if(mainThread.theAssetManager.refineries[j] != null && mainThread.theAssetManager.refineries[j].teamNo !=0){
if(mainThread.theAssetManager.refineries[j].getDistance(preferedGoldMine) < 2){
hasRefineryNearby = true;
break;
}
}
}
int numberOfHarvestersOnTheMine = 0;
for(int j = 0; j < mainThread.theAssetManager.harvesters.length; j++){
if(mainThread.theAssetManager.harvesters[j] != null && mainThread.theAssetManager.harvesters[j].teamNo !=0 && mainThread.theAssetManager.harvesters[j].myGoldMine == preferedGoldMine)
numberOfHarvestersOnTheMine++;
}
//only go to the gold mine that has a refinery nearby and its not saturated with harvesters
if(numberOfHarvestersOnTheMine < 6)
o.myGoldMine = preferedGoldMine;
}
}
//when harvester is under attack then temporarily move away from mining until the danger passes
if(o.underAttackCountDown > 0) {
o.isEvadingFromAttack = true;
if(o.attacker != null) {
evadeDirection.set(o.centre);
evadeDirection.subtract(o.attacker.centre);
evadeDirection.unit();
float desX = o.centre.x + evadeDirection.x*2;
float desZ = o.centre.z + evadeDirection.z*2;
if(desX > 31)
desX = 31;
if(desX < 1)
desX = 1;
if(desZ > 31)
desZ = 31;
if(desZ < 1)
desZ = 1;
o.moveTo(desX, desZ);
}
}else {
if(o.isEvadingFromAttack == true) {
o.returnToRefinery(null);
o.isEvadingFromAttack = false;
}
}
}
}
numberOfharvesters+=numberOfHarvesterOnQueue;
//the ration between harvester and refinery should be 2:1
//economyManager has a higher priority than combat manager AI, so the enemy AI will always queue harvester first if lost any.
if(theBaseInfo.numberOfRefinery > 0 && numberOfharvesters < 4){
if(numberOfharvesters/theBaseInfo.numberOfRefinery < 2){
for(int i = 0; i < mainThread.theAssetManager.factories.length; i++){
if(mainThread.theAssetManager.factories[i] != null && mainThread.theAssetManager.factories[i].teamNo != 0){
if(mainThread.theAssetManager.factories[i].isIdle()){
mainThread.theAssetManager.factories[i].buildHarvester();
break;
}
}
}
}
}
}
}

131
enemyAI/enemyCommander.java Normal file
View File

@ -0,0 +1,131 @@
package enemyAI;
import core.baseInfo;
import core.mainThread;
public class enemyCommander {
//vision map represents the vision of the enemy commander
public static boolean[] visionMap;
public static boolean[] tempBitmap;
public baseInfo theBaseInfo;
public buildingManagerAI theBuildingManagerAI;
public economyManagerAI theEconomyManagerAI;
public mapAwarenessAI theMapAwarenessAI;
public unitProductionAI theUnitProductionAI;
public baseExpensionAI theBaseExpentionAI;
public scoutingManagerAI theScoutingManagerAI;
public defenseManagerAI theDefenseManagerAI;
public combatManagerAI theCombatManagerAI;
public microManagementAI theMicroManagementAI;
public void init(){
//init vision map
visionMap = new boolean[128*128];
tempBitmap = new boolean[148 * 148];
theBaseInfo = new baseInfo();
theBuildingManagerAI = new buildingManagerAI(theBaseInfo);
theEconomyManagerAI = new economyManagerAI(theBaseInfo);
theMapAwarenessAI = new mapAwarenessAI(theBaseInfo, visionMap);
theUnitProductionAI = new unitProductionAI(theBaseInfo);
theBaseExpentionAI = new baseExpensionAI(theBaseInfo);
theScoutingManagerAI = new scoutingManagerAI(theBaseInfo);
theDefenseManagerAI = new defenseManagerAI(theBaseInfo);
theCombatManagerAI = new combatManagerAI(theBaseInfo);
theMicroManagementAI = new microManagementAI(theBaseInfo);
}
public void update(){
theBaseInfo.update();
//generate visionMap based on the map information of the previous frame
for(int y = 0; y < 128; y++){
for(int x = 0; x < 128; x++){
visionMap[x + y*128] = tempBitmap[x + 10 + (y + 10)*148];
}
}
//process high level enemy AI
thinkHardLikeHumanPlayer();
drawVisionMap();
//reset tempBitmap;
for(int i = 0 ;i < tempBitmap.length; i++){
tempBitmap[i] = false;
}
}
public void drawVisionMap(){
int pos = 2 + 20 * 768;
boolean tile;
int[] screen = mainThread.screen2;
for(int i = 0; i < 128; i++){
for(int j = 0; j < 128; j++){
tile = visionMap[j + i*128];
if(!tile)
screen[pos + j + i*768] = 0;
}
}
}
public void thinkHardLikeHumanPlayer(){
if(mainThread.frameIndex % 30 == 0){
theMapAwarenessAI.processAI();
}
if(mainThread.frameIndex % 30 == 1){
theBuildingManagerAI.processAI();
}
if(mainThread.frameIndex % 30 == 2){
theEconomyManagerAI.processAI();
}
if(mainThread.frameIndex % 30 == 3){
theScoutingManagerAI.processAI();
}
if(mainThread.frameIndex % 30 == 4){
theUnitProductionAI.processAI();
}
if(mainThread.frameIndex % 30 == 5){
theBaseExpentionAI.processAI();
}
if(mainThread.frameIndex % 30 == 6){
theCombatManagerAI.processAI();
}
if(mainThread.frameIndex % 30 == 7){
theDefenseManagerAI.processAI();
}
//if(mainThread.frameIndex % 5 == 0){
theMicroManagementAI.processAI();
//}
}
}

515
enemyAI/mapAwarenessAI.java Normal file
View File

@ -0,0 +1,515 @@
package enemyAI;
import core.AssetManager;
import core.baseInfo;
import core.mainThread;
import entity.goldMine;
import entity.solidObject;
//1. scan revealed area for player's units and building
//2. keep track of player's units
//3. create strategic information based on the quantity/location of player's units
public class mapAwarenessAI {
public baseInfo theBaseInfo;
public int numberOfLightTanks_player, numberOfLightTanks_AI, numberOfLightTanksOnMinimap_player;
public int numberOfStealthTanks_player, numberOfStealthTanks_AI, numberOfStealthTanksOnMinimap_player;
public int numberOfRocketTanks_player, numberOfRocketTanks_AI, numberOfRocketTanksOnMinimap_player;
public int numberOfHeavyTanks_player, numberOfHeavyTanks_AI, numberOfHeavyTanksOnMinimap_player;
public int numberOfPlayerUnitsOnMinimap;
public int numberOfGunTurret_player;
public int numberOfMissileTurret_player;
public int numberOfFactory_player;
public int numberOfRefinery_player;
public int numberOfConstructionYard_player;
public int numberOfCommunicationCenter_player;
public int numberOfTechCenter_player;
public int numberOfPowerPlant_player;
public int maxNumberOfStealthTanks_playerInLastFiveMinutes;
public int fiveMinuteTimer;
public int numberOfPlayerUnitDestroyed;
public int numberOfPlayerBuildingDestroyed;
public boolean playerHasMostlyLightTanks;
public boolean playerHasMostlyHeavyTanks;
public boolean playIsRushingHighTierUnits;
public boolean playerLikelyCanNotProduceHighTierUnits;
public boolean playerDoesntHaveMassHeavyTanks;
public boolean playerIsRushingLightTank;
public boolean playerHasManyLightTanksButNoHeavyTank;
public solidObject[] mapAsset;
public boolean[] visionMap;
public AssetManager theAssetManager;
public solidObject[] playerUnitInMinimap;
public solidObject[] playerStaticDefenceInMinimap;
public solidObject[] playerStructures;
public goldMine[] goldMines;
public int targetPlayerExpension;
public int[] playerExpensionInfo;
public int numberOfplayerMiningBases;
public mapAwarenessAI(baseInfo theBaseInfo, boolean[] visionMap){
this.theBaseInfo = theBaseInfo;
this.visionMap = visionMap;
mapAsset = new solidObject[1024];
playerUnitInMinimap = new solidObject[128];
playerStaticDefenceInMinimap = new solidObject[64];
playerStructures = new solidObject[256];
goldMines = mainThread.theAssetManager.goldMines;
playerExpensionInfo = new int[goldMines.length];
}
public void processAI(){
theAssetManager = mainThread.theAssetManager;
//the number of player's military units in AI's vision
numberOfLightTanksOnMinimap_player = 0;
numberOfRocketTanksOnMinimap_player = 0;
numberOfStealthTanksOnMinimap_player = 0;
numberOfHeavyTanksOnMinimap_player = 0;
numberOfPlayerUnitsOnMinimap = 0;
//the total number of player's unit that are detected by AI
numberOfLightTanks_player = 0;
numberOfRocketTanks_player = 0;
numberOfStealthTanks_player = 0;
numberOfHeavyTanks_player = 0;
numberOfGunTurret_player = 0;
numberOfMissileTurret_player = 0;
numberOfFactory_player = 0;
numberOfRefinery_player = 0;
numberOfConstructionYard_player = 0;
numberOfCommunicationCenter_player = 0;
numberOfTechCenter_player = 0;
//the total number of AI military units
numberOfLightTanks_AI = 0;
numberOfRocketTanks_AI = 0;
numberOfStealthTanks_AI = 0;
numberOfHeavyTanks_AI = 0;
//clear enemy info from previous frame
for(int i = 0; i < playerUnitInMinimap.length; i++)
playerUnitInMinimap[i] = null;
for(int i = 0; i < playerStaticDefenceInMinimap.length; i++)
playerStaticDefenceInMinimap[i] = null;
for(int i = 0; i < playerStructures.length; i++)
playerStructures[i] = null;
for(int i = 0; i < theAssetManager.lightTanks.length; i++){
if(theAssetManager.lightTanks[i] != null && theAssetManager.lightTanks[i].teamNo ==0){
if(visionMap[theAssetManager.lightTanks[i].occupiedTile0]){
numberOfLightTanksOnMinimap_player++;
addPlayerUnitInMinimap(theAssetManager.lightTanks[i]);
if(mapAsset[theAssetManager.lightTanks[i].ID] == null) {
mapAsset[theAssetManager.lightTanks[i].ID] = theAssetManager.lightTanks[i];
mainThread.ec.theCombatManagerAI.offScreenPlayerForceStrength-=1;
}
}
}else if(theAssetManager.lightTanks[i] != null && theAssetManager.lightTanks[i].teamNo !=0){
numberOfLightTanks_AI++;
if(mapAsset[theAssetManager.lightTanks[i].ID] == null){
mainThread.ec.theUnitProductionAI.addLightTank(theAssetManager.lightTanks[i]);
mapAsset[theAssetManager.lightTanks[i].ID] = theAssetManager.lightTanks[i];
}
}
}
for(int i = 0; i < theAssetManager.rocketTanks.length; i++){
if(theAssetManager.rocketTanks[i] != null && theAssetManager.rocketTanks[i].teamNo ==0){
if(visionMap[theAssetManager.rocketTanks[i].occupiedTile0]){
numberOfRocketTanksOnMinimap_player++;
addPlayerUnitInMinimap(theAssetManager.rocketTanks[i]);
if(mapAsset[theAssetManager.rocketTanks[i].ID] == null) {
mapAsset[theAssetManager.rocketTanks[i].ID] = theAssetManager.rocketTanks[i];
mainThread.ec.theCombatManagerAI.offScreenPlayerForceStrength-=1.5;
}
}
}else if(theAssetManager.rocketTanks[i] != null && theAssetManager.rocketTanks[i].teamNo !=0){
numberOfRocketTanks_AI++;
if(mapAsset[theAssetManager.rocketTanks[i].ID] == null){
mainThread.ec.theUnitProductionAI.addRocketTank(theAssetManager.rocketTanks[i]);
mapAsset[theAssetManager.rocketTanks[i].ID] = theAssetManager.rocketTanks[i];
}
}
}
for(int i = 0; i < theAssetManager.stealthTanks.length; i++){
if(theAssetManager.stealthTanks[i] != null && theAssetManager.stealthTanks[i].teamNo ==0){
if(visionMap[theAssetManager.stealthTanks[i].occupiedTile0] && !theAssetManager.stealthTanks[i].isCloaked){
numberOfStealthTanksOnMinimap_player++;
addPlayerUnitInMinimap(theAssetManager.stealthTanks[i]);
if(mapAsset[theAssetManager.stealthTanks[i].ID] == null) {
mapAsset[theAssetManager.stealthTanks[i].ID] = theAssetManager.stealthTanks[i];
mainThread.ec.theCombatManagerAI.offScreenPlayerForceStrength-=2;
}
}
}else if(theAssetManager.stealthTanks[i] != null && theAssetManager.stealthTanks[i].teamNo !=0){
numberOfStealthTanks_AI++;
if(mapAsset[theAssetManager.stealthTanks[i].ID] == null){
mainThread.ec.theUnitProductionAI.addStealthTank(theAssetManager.stealthTanks[i]);
mapAsset[theAssetManager.stealthTanks[i].ID] = theAssetManager.stealthTanks[i];
}
}
}
for(int i = 0; i < theAssetManager.heavyTanks.length; i++){
if(theAssetManager.heavyTanks[i] != null && theAssetManager.heavyTanks[i].teamNo ==0){
if(visionMap[theAssetManager.heavyTanks[i].occupiedTile0]){
numberOfHeavyTanksOnMinimap_player++;
addPlayerUnitInMinimap(theAssetManager.heavyTanks[i]);
if(mapAsset[theAssetManager.heavyTanks[i].ID] == null) {
mapAsset[theAssetManager.heavyTanks[i].ID] = theAssetManager.heavyTanks[i];
mainThread.ec.theCombatManagerAI.offScreenPlayerForceStrength-=3.5;
}
}
}else if(theAssetManager.heavyTanks[i] != null && theAssetManager.heavyTanks[i].teamNo !=0){
numberOfHeavyTanks_AI++;
if(mapAsset[theAssetManager.heavyTanks[i].ID] == null){
mainThread.ec.theUnitProductionAI.addHeavyTank(theAssetManager.heavyTanks[i]);
mapAsset[theAssetManager.heavyTanks[i].ID] = theAssetManager.heavyTanks[i];
}
}
}
for(int i = 0; i < theAssetManager.harvesters.length; i++){
if(theAssetManager.harvesters[i] != null && theAssetManager.harvesters[i].teamNo ==0){
if(visionMap[theAssetManager.harvesters[i].occupiedTile0]){
addPlayerUnitInMinimap(theAssetManager.harvesters[i]);
mapAsset[theAssetManager.harvesters[i].ID] = theAssetManager.harvesters[i];
}
}
}
for(int i = 0; i < theAssetManager.constructionVehicles.length; i++){
if(theAssetManager.constructionVehicles[i] != null && theAssetManager.constructionVehicles[i].teamNo ==0){
if(visionMap[theAssetManager.constructionVehicles[i].occupiedTile0]){
addPlayerUnitInMinimap(theAssetManager.constructionVehicles[i]);
mapAsset[theAssetManager.constructionVehicles[i].ID] = theAssetManager.constructionVehicles[i];
}
}
}
//add revealed player's building to mapAsset
for(int i = 0; i < theAssetManager.gunTurrets.length; i++){
if(theAssetManager.gunTurrets[i] != null && theAssetManager.gunTurrets[i].teamNo ==0){
if(visionMap[theAssetManager.gunTurrets[i].tileIndex[0]]){
if(mapAsset[theAssetManager.gunTurrets[i].ID] == null) {
mapAsset[theAssetManager.gunTurrets[i].ID] = theAssetManager.gunTurrets[i];
mainThread.ec.theCombatManagerAI.offScreenPlayerForceStrength-=1;
}
}
}
}
for(int i = 0; i < theAssetManager.missileTurrets.length; i++){
if(theAssetManager.missileTurrets[i] != null && theAssetManager.missileTurrets[i].teamNo ==0){
if(visionMap[theAssetManager.missileTurrets[i].tileIndex[0]]){
if(mapAsset[theAssetManager.missileTurrets[i].ID] == null) {
mapAsset[theAssetManager.missileTurrets[i].ID] = theAssetManager.missileTurrets[i];
mainThread.ec.theCombatManagerAI.offScreenPlayerForceStrength-=2;
}
}
}
}
for(int i = 0; i < theAssetManager.factories.length; i++){
if(theAssetManager.factories[i] != null && theAssetManager.factories[i].teamNo ==0){
for(int j = 0; j < 6; j++){
if(visionMap[theAssetManager.factories[i].tileIndex[j]]){
if(mapAsset[theAssetManager.factories[i].ID] == null)
mapAsset[theAssetManager.factories[i].ID] = theAssetManager.factories[i];
break;
}
}
}
}
for(int i = 0; i < theAssetManager.refineries.length; i++){
if(theAssetManager.refineries[i] != null && theAssetManager.refineries[i].teamNo ==0){
for(int j = 0; j < 6; j++){
if(visionMap[theAssetManager.refineries[i].tileIndex[j]]){
if(mapAsset[theAssetManager.refineries[i].ID] == null)
mapAsset[theAssetManager.refineries[i].ID] = theAssetManager.refineries[i];
break;
}
}
}
}
for(int i = 0; i < theAssetManager.constructionYards.length; i++){
if(theAssetManager.constructionYards[i] != null && theAssetManager.constructionYards[i].teamNo ==0){
for(int j = 0; j < 9; j++){
if(visionMap[theAssetManager.constructionYards[i].tileIndex[j]]){
if(mapAsset[theAssetManager.constructionYards[i].ID] == null)
mapAsset[theAssetManager.constructionYards[i].ID] = theAssetManager.constructionYards[i];
break;
}
}
}
}
for(int i = 0; i < theAssetManager.communicationCenters.length; i++){
if(theAssetManager.communicationCenters[i] != null && theAssetManager.communicationCenters[i].teamNo ==0){
for(int j = 0; j < 4; j++){
if(visionMap[theAssetManager.communicationCenters[i].tileIndex[j]]){
if(mapAsset[theAssetManager.communicationCenters[i].ID] == null)
mapAsset[theAssetManager.communicationCenters[i].ID] = theAssetManager.communicationCenters[i];
break;
}
}
}
}
for(int i = 0; i < theAssetManager.techCenters.length; i++){
if(theAssetManager.techCenters[i] != null && theAssetManager.techCenters[i].teamNo ==0){
for(int j = 0; j < 4; j++){
if(visionMap[theAssetManager.techCenters[i].tileIndex[j]]){
if(mapAsset[theAssetManager.techCenters[i].ID] == null)
mapAsset[theAssetManager.techCenters[i].ID] = theAssetManager.techCenters[i];
break;
}
}
}
}
for(int i = 0; i < theAssetManager.powerPlants.length; i++){
if(theAssetManager.powerPlants[i] != null && theAssetManager.powerPlants[i].teamNo ==0){
for(int j = 0; j < 4; j++){
if(visionMap[theAssetManager.powerPlants[i].tileIndex[j]]){
if(mapAsset[theAssetManager.powerPlants[i].ID] == null)
mapAsset[theAssetManager.powerPlants[i].ID] = theAssetManager.powerPlants[i];
break;
}
}
}
}
numberOfPlayerUnitDestroyed = 0;
numberOfPlayerBuildingDestroyed = 0;
for(int i = 0; i < mapAsset.length; i++){
if(mapAsset[i] != null && mapAsset[i].teamNo == 0){
if(mapAsset[i].currentHP>0){
if(mapAsset[i].type == 0 )
numberOfLightTanks_player++;
else if(mapAsset[i].type == 1)
numberOfRocketTanks_player++;
else if(mapAsset[i].type == 6)
numberOfStealthTanks_player++;
else if(mapAsset[i].type == 7)
numberOfHeavyTanks_player++;
else{
mapAsset[i].isRevealed_AI = true;
if(mapAsset[i].type == 200){
numberOfGunTurret_player++;
addPlayerStaticDefenceInMinimap(mapAsset[i]);
addPlayerStructure(mapAsset[i]);
}else if(mapAsset[i].type == 199){
addPlayerStaticDefenceInMinimap(mapAsset[i]);
addPlayerStructure(mapAsset[i]);
numberOfMissileTurret_player++;
}else if(mapAsset[i].type == 105){
addPlayerStructure(mapAsset[i]);
numberOfFactory_player++;
}else if(mapAsset[i].type == 102){
numberOfRefinery_player++;
addPlayerStructure(mapAsset[i]);
}else if(mapAsset[i].type == 104){
addPlayerStructure(mapAsset[i]);
numberOfConstructionYard_player++;
}else if(mapAsset[i].type == 106){
addPlayerStructure(mapAsset[i]);
numberOfCommunicationCenter_player++;
}else if(mapAsset[i].type == 107){
addPlayerStructure(mapAsset[i]);
numberOfTechCenter_player++;
}else if(mapAsset[i].type == 101){
addPlayerStructure(mapAsset[i]);
numberOfPowerPlant_player++;
}
}
}else{
if(mapAsset[i].type < 100)
numberOfPlayerUnitDestroyed++;
else
numberOfPlayerBuildingDestroyed++;
}
}
}
//analyze the enemy units composition
float lightTankRatio = (float)(numberOfLightTanks_player)/(numberOfLightTanks_player + numberOfRocketTanks_player + numberOfStealthTanks_player + numberOfHeavyTanks_player + 1);
playerHasMostlyLightTanks = numberOfLightTanks_player > 5 && lightTankRatio > 0.8f;
playerHasMostlyHeavyTanks = numberOfHeavyTanks_player > 3 && (float)(numberOfHeavyTanks_player)/(numberOfLightTanks_player + numberOfRocketTanks_player + numberOfStealthTanks_player + numberOfHeavyTanks_player) > 0.6f;
playerHasManyLightTanksButNoHeavyTank = lightTankRatio > 0.5 && lightTankRatio <=0.8 && numberOfHeavyTanks_player < 3;
playIsRushingHighTierUnits = mainThread.frameIndex/30 > 250 && mainThread.frameIndex/30 < 400
&& mainThread.ec.theMapAwarenessAI.numberOfTechCenter_player >0
&& mainThread.ec.theMapAwarenessAI.numberOfMissileTurret_player < 2
&& mainThread.ec.theMapAwarenessAI.numberOfGunTurret_player < 4
&& numberOfLightTanks_player + numberOfRocketTanks_player + numberOfStealthTanks_player < 5;
playerLikelyCanNotProduceHighTierUnits = mainThread.ec.theMapAwarenessAI.numberOfTechCenter_player == 0 && mainThread.ec.theMapAwarenessAI.numberOfHeavyTanks_player == 0;
playerDoesntHaveMassHeavyTanks = (float)numberOfHeavyTanks_player/( 1 + numberOfLightTanks_AI + numberOfRocketTanks_player + numberOfStealthTanks_player) < 0.2f;
playerIsRushingLightTank = mainThread.frameIndex/30 > 300 && mainThread.frameIndex/30 < 600 && ((playerLikelyCanNotProduceHighTierUnits && numberOfStealthTanks_player < 3) || playerHasMostlyLightTanks);
//advanced counting of player units
if(numberOfStealthTanks_player > maxNumberOfStealthTanks_playerInLastFiveMinutes) {
maxNumberOfStealthTanks_playerInLastFiveMinutes = numberOfStealthTanks_player;
fiveMinuteTimer = 300;
}
if(fiveMinuteTimer > 0)
fiveMinuteTimer--;
else
maxNumberOfStealthTanks_playerInLastFiveMinutes = 0;
findTheMostVulnerablePlayerBase();
}
public void addPlayerUnitInMinimap(solidObject o){
for(int i = 0; i < playerUnitInMinimap.length; i++){
if(playerUnitInMinimap[i] == null){
playerUnitInMinimap[i] = o;
numberOfPlayerUnitsOnMinimap++;
break;
}
}
}
public void addPlayerStaticDefenceInMinimap(solidObject o){
for(int i = 0; i < playerStaticDefenceInMinimap.length; i++){
if(playerStaticDefenceInMinimap[i] == null){
playerStaticDefenceInMinimap[i] = o;
break;
}
}
}
public void addPlayerStructure(solidObject o){
for(int i = 0; i < playerStructures.length; i++){
if(playerStructures[i] == null){
playerStructures[i] = o;
break;
}
}
}
public void findTheMostVulnerablePlayerBase(){
//check if there are any player's structure around each gold mine.
for(int i = 0; i < goldMines.length; i++){
playerExpensionInfo[i] = findplayexpensionDefenseScore(goldMines[i], 3);
}
//compute the target player expansion defense score
targetPlayerExpension = -1;
int playExpensionDefenseScore = 999999;
numberOfplayerMiningBases = 0;
for(int i = 0; i < playerExpensionInfo.length; i++){
if(goldMines[i] != null && goldMines[i].goldDeposite > 5000 && playerExpensionInfo[i] != 0){
numberOfplayerMiningBases++;
if(playerExpensionInfo[i] < playExpensionDefenseScore){
playExpensionDefenseScore = playerExpensionInfo[i];
targetPlayerExpension = i;
}
}
}
//if a player expansion exists on the path to the target expansion is already been taken by player's force,
//then mark it as the target expansion instead
if(targetPlayerExpension == 0){
if(playerExpensionInfo[5] >0)
targetPlayerExpension = 5;
else if(playerExpensionInfo[6] >0)
targetPlayerExpension = 6;
else if(playerExpensionInfo[7] >0)
targetPlayerExpension = 7;
else if(playerExpensionInfo[1] > 0)
targetPlayerExpension = 1;
}else if(targetPlayerExpension == 1){
if(playerExpensionInfo[5] >0)
targetPlayerExpension = 5;
else if(playerExpensionInfo[6] >0)
targetPlayerExpension = 6;
else if(playerExpensionInfo[7] >0)
targetPlayerExpension = 7;
}else if(targetPlayerExpension == 7){
if(playerExpensionInfo[5] >0)
targetPlayerExpension = 5;
else if(playerExpensionInfo[6] >0)
targetPlayerExpension = 6;
}else if(targetPlayerExpension == 6){
if(playerExpensionInfo[5] >0)
targetPlayerExpension = 5;
}
//if(targetPlayerExpension != -1)
// return playerExpensionInfo[targetPlayerExpension];
//return 0;
}
public int findplayexpensionDefenseScore(goldMine g, float r){
if(g == null)
return 0;
solidObject[] playerStructures = mainThread.ec.theMapAwarenessAI.playerStructures;
solidObject[] playerStaticDefence = mainThread.ec.theMapAwarenessAI.playerStaticDefenceInMinimap;
float x = g.centre.x;
float z = g.centre.z;
int playexpensionDefenseScore = 0;
for(int i = 0 ; i < playerStructures.length; i++){
if(playerStructures[i]!= null && Math.abs(playerStructures[i].centre.x - x) < r && Math.abs(playerStructures[i].centre.z - z) < r)
playexpensionDefenseScore++;
}
for(int i = 0 ; i < playerStaticDefence.length; i++){
if(playerStaticDefence[i]!= null && Math.abs(playerStructures[i].centre.x - x) < r && Math.abs(playerStructures[i].centre.z - z) < r){
if(playerStaticDefence[i].type == 200) //gun turret will increase player base's defense score
playexpensionDefenseScore+=1000;
if(playerStaticDefence[i].type == 199) //missile turret will increase player base's defense score even futher
playexpensionDefenseScore+=3000;
}
}
//if the player already takes the expansion which the enemy AI plans to expand to, assign zero score to this expansion
if(g == mainThread.ec.theBaseExpentionAI.expensionGoldMine && playexpensionDefenseScore > 0){
return -1;
}
return playexpensionDefenseScore;
}
}

View File

@ -0,0 +1,226 @@
package enemyAI;
import core.baseInfo;
import core.mainThread;
import entity.solidObject;
import entity.techCenter;
//micro manage the units on the battle field to trade units better against player
public class microManagementAI {
public baseInfo theBaseInfo;
public int frameAI;
public int currentState;
public final int booming = 0;
public final int aggressing = 1;
public final int defending = 2;
public solidObject[] playerUnitInMinimap;
public solidObject[] unitInCombatRadius;
public solidObject[] playerStaticDefenceInMinimap;
public float combatCenterX;
public float combatCenterZ;
public int numberOfPlayerUnitsOnMinimap;
public microManagementAI(baseInfo theBaseInfo){
this.theBaseInfo = theBaseInfo;
}
public void processAI(){
frameAI++;
unitInCombatRadius = mainThread.ec.theUnitProductionAI.unitInCombatRadius;
playerUnitInMinimap = mainThread.ec.theMapAwarenessAI.playerUnitInMinimap;
playerStaticDefenceInMinimap = mainThread.ec.theMapAwarenessAI.playerStaticDefenceInMinimap;
currentState = mainThread.ec.theCombatManagerAI.currentState;
combatCenterX = mainThread.ec.theUnitProductionAI.combatAICenterX;
combatCenterZ = mainThread.ec.theUnitProductionAI.combatAICenterZ;
numberOfPlayerUnitsOnMinimap = mainThread.ec.theMapAwarenessAI.numberOfPlayerUnitsOnMinimap;
float x1 = 0;
float x2 = 0;
float z1 = 0;
float z2 = 0;
//focus fire on the player unit with the least hit points
for(int i = 0; i < unitInCombatRadius.length; i ++){
if(unitInCombatRadius[i] == null || unitInCombatRadius[i].currentHP <=0)
continue;
//micro rocket tanks, so they don't overkill targets,
if(unitInCombatRadius[i].type == 1) {
//if rocket tank has no target or the target will die from incoming attack, find a new target
if(unitInCombatRadius[i].targetObject != null && !unitInCombatRadius[i].targetObject.willDieFromIncomingAttack()) {
int myDamage = unitInCombatRadius[i].myDamage;
if(unitInCombatRadius[i].targetObject .type > 100) {
if(techCenter.rocketTankResearched_enemy) {
myDamage*=2;
}
myDamage = (int)(myDamage*1.25f);
}
unitInCombatRadius[i].targetObject.incomingDamage+=myDamage*2;
}else {
float myRange= unitInCombatRadius[i].attackRange * unitInCombatRadius[i].attackRange;
//Prioritize searching for targets among static defenses
boolean suitableTargertFound = false;
for(int j = 0; j < playerStaticDefenceInMinimap.length; j++) {
if(playerStaticDefenceInMinimap[j] != null && !playerStaticDefenceInMinimap[j].willDieFromIncomingAttack()){
x1 = playerStaticDefenceInMinimap[j].centre.x;
x2 = unitInCombatRadius[i].centre.x;
z1 = playerStaticDefenceInMinimap[j].centre.z;
z2 = unitInCombatRadius[i].centre.z;
float distanceToDesination = (x1 - x2)*(x1 - x2) + (z1 - z2)*(z1 - z2);
if(distanceToDesination < myRange){
unitInCombatRadius[i].attack(playerStaticDefenceInMinimap[j]);
unitInCombatRadius[i].currentCommand = solidObject.attackCautiously;
suitableTargertFound = true;
int myDamage = unitInCombatRadius[i].myDamage;
if(techCenter.rocketTankResearched_enemy) {
myDamage*=2;
}
myDamage = (int)(myDamage*1.25f);
playerStaticDefenceInMinimap[j].incomingDamage+=myDamage*2;
break;
}
}
}
if(suitableTargertFound)
continue;
//find targets among moving unites
for(int j=0; j < numberOfPlayerUnitsOnMinimap; j++){
if(playerUnitInMinimap[j] != null && !playerUnitInMinimap[j].willDieFromIncomingAttack()){
x1 = playerUnitInMinimap[j].centre.x;
x2 = unitInCombatRadius[i].centre.x;
z1 = playerUnitInMinimap[j].centre.z;
z2 = unitInCombatRadius[i].centre.z;
float distanceToDesination = (x1 - x2)*(x1 - x2) + (z1 - z2)*(z1 - z2);
if(distanceToDesination < myRange){
unitInCombatRadius[i].attack(playerUnitInMinimap[j]);
playerUnitInMinimap[j].incomingDamage+=unitInCombatRadius[i].myDamage*2;
break;
}
}
}
}
continue;
}
//if(unitInCombatRadius[i].type == 0)
// unitInCombatRadius[i].groupAttackRange = 1.35f;
//if(unitInCombatRadius[i].level > 0)
// unitInCombatRadius[i].groupAttackRange = unitInCombatRadius[i].attackRange;
float myRange= unitInCombatRadius[i].attackRange * unitInCombatRadius[i].attackRange;
solidObject target = null;
int targetHP = 99999;
int level = 0;
float distanceToDesination = 99999;
for(int j=0; j < numberOfPlayerUnitsOnMinimap; j++){
if(playerUnitInMinimap[j] != null && playerUnitInMinimap[j].currentHP > 0){
if((playerUnitInMinimap[j].getMaxHp() / playerUnitInMinimap[j].currentHP > 4 && !(unitInCombatRadius[i].targetObject!= null && unitInCombatRadius[i].targetObject.currentHP < playerUnitInMinimap[j].currentHP)) || playerUnitInMinimap[j].level > level){
x1 = playerUnitInMinimap[j].centre.x;
x2 = unitInCombatRadius[i].centre.x;
z1 = playerUnitInMinimap[j].centre.z;
z2 = unitInCombatRadius[i].centre.z;
distanceToDesination = (x1 - x2)*(x1 - x2) + (z1 - z2)*(z1 - z2);
if(distanceToDesination < myRange){
if(hasLineOfSight(distanceToDesination, x1, x2, z1, z2, playerUnitInMinimap[j])){
target = playerUnitInMinimap[j];
break;
}
}
}
if(targetHP >= playerUnitInMinimap[j].currentHP || (targetHP == playerUnitInMinimap[j].currentHP && playerUnitInMinimap[j].ID%5 == 0)){
x1 = playerUnitInMinimap[j].centre.x;
x2 = unitInCombatRadius[i].centre.x;
z1 = playerUnitInMinimap[j].centre.z;
z2 = unitInCombatRadius[i].centre.z;
distanceToDesination = (x1 - x2)*(x1 - x2) + (z1 - z2)*(z1 - z2);
if( distanceToDesination < myRange){
if(hasLineOfSight(distanceToDesination, x1, x2, z1, z2, playerUnitInMinimap[j])){
target = playerUnitInMinimap[j];
targetHP = playerUnitInMinimap[j].currentHP;
}
}
}
}
}
if(target !=null ){
unitInCombatRadius[i].attack(target);
unitInCombatRadius[i].currentCommand = solidObject.attackCautiously;
unitInCombatRadius[i].attackStatus = solidObject.isAttacking;
unitInCombatRadius[i].closeToDestination = true;
}
}
//reset incoming damage for all units
for(int i = 0; i < mainThread.ec.theMapAwarenessAI.mapAsset.length; i++) {
if(mainThread.ec.theMapAwarenessAI.mapAsset[i] != null)
mainThread.ec.theMapAwarenessAI.mapAsset[i].incomingDamage = 0;
}
}
public boolean hasLineOfSight(float distanceToDesination, float x1, float x2, float z1, float z2, solidObject targetObject){
boolean hasLineOfSight = true;
int numberOfIterations = (int)(Math.sqrt(distanceToDesination) * 8);
float dx = (x1 - x2)/numberOfIterations;
float dy = (z1 - z2)/numberOfIterations;
float xStart = x2;
float yStart = z2;
for(int i = 0; i < numberOfIterations; i++){
xStart+=dx;
yStart+=dy;
solidObject s = mainThread.gridMap.tiles[(int)(xStart*4) + (127 - (int)(yStart*4))*128][0];
if(s != null){
if(s.type > 100 && s.type < 200 && s != targetObject){
hasLineOfSight = false;
break;
}
}
}
return hasLineOfSight;
}
}

View File

@ -0,0 +1,338 @@
package enemyAI;
import core.Rect;
import core.baseInfo;
import core.mainThread;
import core.vector;
import entity.lightTank;
import entity.solidObject;
public class scoutingManagerAI {
public baseInfo theBaseInfo;
public int gameTime;
public int scoutingMode;
public final int patrolling = 0;
public final int exploring = 1;
public float[][] patrolNodes;
public float[][] exploringNodes;
public int destinationNode;
public boolean movementOrderIssued;
public vector tempVector1, tempVector2, tempVector3;
public int avoidingIncomingPlayerUnitCooldown;
//scout unit consists a sole light tank
public solidObject scout;
public scoutingManagerAI(baseInfo theBaseInfo){
this.theBaseInfo = theBaseInfo;
patrolNodes = new float[][]{
{16, 30}, {2, 29}, {15, 17}, {16, 14}, {27f, 1}, {30, 16}, {16, 14}, {15, 17}
};
exploringNodes = new float[][]{
{9, 3.5f}, {2,2}, {14, 14}
};
destinationNode = 0;
tempVector1 = new vector(0,0,0);
tempVector2 = new vector(0,1,0);
tempVector3 = new vector(0,0,0);
}
public void processAI(){
gameTime++;
if(avoidingIncomingPlayerUnitCooldown > 0)
avoidingIncomingPlayerUnitCooldown--;
if(gameTime%275 > 235 && gameTime%275 < 275 && gameTime < 600 && scoutingMode == patrolling){
scoutingMode = exploring;
destinationNode = 0;
movementOrderIssued = false;
}
//produce a scout unit if there is no scout unit on the map or the scout unit has been destroyed
int numberOfLightTankOnQueue = 0;
for(int i = 0; i < mainThread.theAssetManager.factories.length; i++){
if(mainThread.theAssetManager.factories[i] != null && mainThread.theAssetManager.factories[i].teamNo != 0){
numberOfLightTankOnQueue += mainThread.theAssetManager.factories[i].numOfLightTankOnQueue;
}
}
if(numberOfLightTankOnQueue == 0 && needLightTank()){
for(int i = 0; i < mainThread.theAssetManager.factories.length; i++){
if(mainThread.theAssetManager.factories[i] != null && mainThread.theAssetManager.factories[i].teamNo != 0){
if(mainThread.theAssetManager.factories[i].isIdle()){
mainThread.theAssetManager.factories[i].buildLightTank();
break;
}
}
}
}
int numberOfStealthTankOnQueue = 0;
for(int i = 0; i < mainThread.theAssetManager.factories.length; i++){
if(mainThread.theAssetManager.factories[i] != null && mainThread.theAssetManager.factories[i].teamNo != 0){
numberOfStealthTankOnQueue += mainThread.theAssetManager.factories[i].numOfStealthTankOnQueue;
}
}
if(numberOfStealthTankOnQueue == 0 && needStealthTank()){
for(int i = 0; i < mainThread.theAssetManager.factories.length; i++){
if(mainThread.theAssetManager.factories[i] != null && mainThread.theAssetManager.factories[i].teamNo != 0){
if(mainThread.theAssetManager.factories[i].isIdle()){
mainThread.theAssetManager.factories[i].buildStealthTank();
break;
}
}
}
}
if(scout == null || scout.currentHP <=0){
scout = null;
movementOrderIssued= false;
scoutingMode = patrolling;
destinationNode = (int)(Math.random()*patrolNodes.length);
}
if(scout != null){
if(avoidingIncomingPlayerUnitCooldown == 0){
if(scoutingMode == patrolling){
destinationNode = destinationNode%patrolNodes.length;
if(!scountReachedDestination(scout, patrolNodes, destinationNode)){
if(!movementOrderIssued){
scout.moveTo(patrolNodes[destinationNode][0], patrolNodes[destinationNode][1]);
scout.currentCommand = solidObject.move;
scout.secondaryCommand = solidObject.StandBy;
if(scout.leftFactory)
movementOrderIssued = true;
}
}else{
destinationNode++;
movementOrderIssued = false;
}
}
if(scoutingMode == exploring){
if(!scountReachedDestination(scout, exploringNodes, destinationNode)){
if(!movementOrderIssued){
scout.moveTo(exploringNodes[destinationNode][0], exploringNodes[destinationNode][1]);
scout.currentCommand = solidObject.move;
scout.secondaryCommand = solidObject.StandBy;
if(scout.leftFactory)
movementOrderIssued = true;
}
}else{
destinationNode++;
movementOrderIssued = false;
}
if(destinationNode >0 && destinationNode %exploringNodes.length == 0){
scoutingMode = patrolling;
destinationNode = 0;
}
}
if(scout.type == 0)
return;
//try to avoid collision with player units
int xPos_old = scout.boundary2D.x1;
int yPos_old = scout.boundary2D.y1;
int xPos = xPos_old;
int yPos = yPos_old;
if(scout.movement.x != 0 || scout.movement.z != 0){
tempVector1.set(scout.movement);
tempVector1.unit();
tempVector1.scale(0.1f);
for(int i = 1; i < 20; i ++){
xPos = (int)((scout.centre.x + tempVector1.x*i)*64) - 8;
yPos = (int)((scout.centre.z + tempVector1.z*i)*64) + 8;
scout.boundary2D.setOrigin(xPos, yPos);
//increased size of the 2D boundary of the scount for better collision detection.
scout.boundary2D.expand(8);
solidObject obstacle = checkForCollision(scout.boundary2D);
scout.boundary2D.shrink(8);
//ignore harvesters
if(obstacle != null && obstacle.type == 2)
continue;
if(obstacle != null && !(i > 10 && ((obstacle.movement.x == 0 && obstacle.movement.z == 0) || (tempVector1.dot(obstacle.movement) > 0)))){
tempVector3.cross(tempVector1, tempVector2);
tempVector3.unit();
tempVector3.scale(2);
if(tempVector3.dot(obstacle.movement) > 0)
tempVector3.scale(-1);
avoidingIncomingPlayerUnitCooldown = 2;
scout.moveTo(scout.centre.x + tempVector3.x, scout.centre.z + tempVector3.z);
scout.currentCommand = solidObject.move;
scout.secondaryCommand = solidObject.StandBy;
movementOrderIssued = false;
break;
}
}
}
scout.boundary2D.setOrigin(xPos_old, yPos_old);
}
}
}
public solidObject checkForCollision(Rect myRect){
//check if the tank collide with the border
if(myRect.x1 < 0 || myRect.x2 > 2047 || myRect.y2 < 1 || myRect.y1 > 2048){
return null;
}
int newOccupiedTile0= myRect.x1/16 + (127 - myRect.y1/16)*128;
int newOccupiedTile1 = newOccupiedTile0 + 1;
int newOccupiedTile2 = newOccupiedTile0 + 128;
int newOccupiedTile3 = newOccupiedTile0 + 129;
solidObject tempObstacle = null;
solidObject[] tile;
if(newOccupiedTile0 >= 0 && newOccupiedTile0 < 16384){
tile = mainThread.gridMap.tiles[newOccupiedTile0];
for(int i = 0; i < 5; i++){
if(tile[i] != null){
if(tile[i].boundary2D.intersect(myRect) && tile[i].teamNo == 0 && tile[i].type < 100 && !tile[i].isCloaked)
return tile[i];
}
}
}
if(newOccupiedTile1 >= 0 && newOccupiedTile1 < 16384){
tile = mainThread.gridMap.tiles[newOccupiedTile1];
for(int i = 0; i < 5; i++){
if(tile[i] != null){
if(tile[i].boundary2D.intersect(myRect) && tile[i].teamNo == 0 && tile[i].type < 100 && !tile[i].isCloaked)
return tile[i];
}
}
}
if(newOccupiedTile2 >= 0 && newOccupiedTile2 < 16384){
tile = mainThread.gridMap.tiles[newOccupiedTile2];
for(int i = 0; i < 5; i++){
if(tile[i] != null){
if(tile[i].boundary2D.intersect(myRect) && tile[i].teamNo == 0 && tile[i].type < 100 && !tile[i].isCloaked)
return tile[i];
}
}
}
if(newOccupiedTile3 >= 0 && newOccupiedTile3 < 16384){
tile = mainThread.gridMap.tiles[newOccupiedTile3];
for(int i = 0; i < 5; i++){
if(tile[i] != null){
if(tile[i].boundary2D.intersect(myRect) && tile[i].teamNo == 0 && tile[i].type < 100 && !tile[i].isCloaked)
return tile[i];
}
}
}
return tempObstacle;
}
public boolean scountReachedDestination(solidObject o, float[][] nodes, int nodeIndex){
float distanceToDestination = (float)Math.sqrt((o.centre.x - nodes[nodeIndex][0]) * (o.centre.x - nodes[nodeIndex][0]) + (o.centre.z - nodes[nodeIndex][1]) * (o.centre.z - nodes[nodeIndex][1]));
if(distanceToDestination <= 0.1f)
return true;
if(distanceToDestination <= 1.5f && (o.currentMovementStatus == o.hugLeft || o.currentMovementStatus == o.hugRight))
return true;
return false;
}
//build light tank as scout when stealth tank tech is locked
public boolean needLightTank(){
//if((scout == null ) && !theBaseInfo.canBuildStealthTank){
// return true;
//}
return false;
}
public boolean needStealthTank(){
if(theBaseInfo.canBuildStealthTank){
if(scout == null || scout.currentHP <= 0 || scout.type != 6){
return true;
}
}
return false;
}
public void addLightTank(solidObject o){
scout = o;
}
public void addStealthTank(solidObject o){
if(scout != null && scout.currentHP > 0 && scout.type == 0){
mainThread.ec.theUnitProductionAI.addLightTank((lightTank)scout);
scout.moveTo(mainThread.ec.theUnitProductionAI.rallyPoint.x, mainThread.ec.theUnitProductionAI.rallyPoint.z);
scout.currentCommand = solidObject.attackMove;
scout.secondaryCommand = solidObject.attackMove;
}
scout = o;
movementOrderIssued = false;
}
}

View File

@ -0,0 +1,478 @@
package enemyAI;
import core.baseInfo;
import core.gameData;
import core.mainThread;
import core.vector;
import entity.*;
//decide which unit to produce to counter player's force
//keep track of the units that are under control by combatAI.
public class unitProductionAI {
public baseInfo theBaseInfo;
public lightTank[] lightTanksControlledByCombatAI;
public rocketTank[] rocketTanksControlledByCombatAI;
public stealthTank[] stealthTanksControlledByCombatAI;
public heavyTank[] heavyTanksControlledByCombatAI;
public solidObject[] troopsControlledByCombatAI;
public float combatAICenterX;
public float combatAICenterZ;
//public int currentState;
//public final int booming = 0;
//public final int aggressing = 1;
//public final int defending = 2;
public int currentProductionOrder;
public final int produceLightTank = 0;
public final int produceRocketTank = 1;
public final int produceStealthTank = 2;
public final int produceHeavyTank = 3;
public vector rallyPoint;
public int unitProduced;
public int numberOfCombatUnit;
public int numberOfUnitInCombatRadius;
public int numberOfUnitOutsideCombatRadius;
public int numberOfCombatUnitsUnderAttack;
public int numberOfLightTanksControlledByCombatAI;
public int numberOfRocketTanksControlledByCombatAI;
public int numberOfStealthTanksControlledByCombatAI;
public int numberOfHeavyTanksControlledByCombatAI;
public solidObject[] unitInCombatRadius;
public solidObject[] unitOutsideCombatRadius;
public int frameAI;
public unitProductionAI(baseInfo theBaseInfo){
this.theBaseInfo = theBaseInfo;
rallyPoint = new vector(0,0,0);
lightTanksControlledByCombatAI = new lightTank[192];
rocketTanksControlledByCombatAI = new rocketTank[72];
stealthTanksControlledByCombatAI = new stealthTank[96];
heavyTanksControlledByCombatAI = new heavyTank[60];
troopsControlledByCombatAI = new solidObject[512];
unitInCombatRadius = new solidObject[384];
unitOutsideCombatRadius = new solidObject[128];
combatAICenterX = -1;
combatAICenterZ = -1;
}
public void processAI(){
frameAI++;
//set the rally point to near the construction yard which is closest to the player's starting position
float x = 0;
float z = 999999;
int index = 0;
for(int i = 0; i < mainThread.theAssetManager.constructionYards.length; i++){
if(mainThread.theAssetManager.constructionYards[i] != null && mainThread.theAssetManager.constructionYards[i].currentHP > 0 && mainThread.theAssetManager.constructionYards[i].teamNo != 0){
index = i;
if(mainThread.theAssetManager.constructionYards[i].centre.z < z && mainThread.theAssetManager.constructionYards[i].centre.z > 5 && mainThread.theAssetManager.constructionYards[i].centre.x > 5){
x = mainThread.theAssetManager.constructionYards[i].centre.x;
z = mainThread.theAssetManager.constructionYards[i].centre.z;
}
}
}
if(z != 999999) {
if(mainThread.ec.theCombatManagerAI.shouldDefenceAggressively)
rallyPoint.set(z - 2.5f, 0, z - 2.5f);
else
rallyPoint.set(x - 1.5f, 0, z - 1.5f);
}else {
if(mainThread.theAssetManager.constructionYards[index] != null)
rallyPoint.set(mainThread.theAssetManager.constructionYards[index].centre.x - 2.5f, 0, mainThread.theAssetManager.constructionYards[index].centre.z -2.5f);
}
//make sure not to over produce when the resource is running low
int maxNumOfUnitCanBeProduced = theBaseInfo.currentCredit / 500 + 1;
for(int i = 0; i < mainThread.theAssetManager.factories.length; i++){
factory f = mainThread.theAssetManager.factories[i];
if(f != null && f.teamNo !=0){
if(!f.isIdle())
maxNumOfUnitCanBeProduced--;
}
}
for(int i = 0; i < mainThread.theAssetManager.constructionYards.length; i++){
constructionYard c = mainThread.theAssetManager.constructionYards[i];
if(c != null && c.teamNo !=0){
if(!c.isIdle())
maxNumOfUnitCanBeProduced--;
}
}
//make decision on what unit to produce
int numberOfLightTanks_AI = mainThread.ec.theMapAwarenessAI.numberOfLightTanks_AI;
int numberOfRocketTanks_AI = mainThread.ec.theMapAwarenessAI.numberOfRocketTanks_AI;
int numberOfStealthTanks_AI = mainThread.ec.theMapAwarenessAI.numberOfStealthTanks_AI;
int numberOfHeavyTanks_AI = mainThread.ec.theMapAwarenessAI.numberOfHeavyTanks_AI;
int numberOfPlayerTurrets= mainThread.ec.theMapAwarenessAI.numberOfMissileTurret_player + mainThread.ec.theMapAwarenessAI.numberOfGunTurret_player;
int numberOfLightTanks_player = mainThread.ec.theMapAwarenessAI.numberOfLightTanks_player;
int numberOfRocketTanks_player = mainThread.ec.theMapAwarenessAI.numberOfRocketTanks_player;
int numberOfStealthTanks_player = mainThread.ec.theMapAwarenessAI.numberOfStealthTanks_player;
int numberOfHeavyTanks_player = mainThread.ec.theMapAwarenessAI.numberOfHeavyTanks_player;
int maxNumberOfStealthTanks_playerInLastFiveMinutes = mainThread.ec.theMapAwarenessAI.maxNumberOfStealthTanks_playerInLastFiveMinutes;
boolean playerHasMostlyLightTanks = mainThread.ec.theMapAwarenessAI.playerHasMostlyLightTanks;
boolean playerHasMostlyHeavyTanks = mainThread.ec.theMapAwarenessAI.playerHasMostlyHeavyTanks;
boolean playIsRushingHighTierUnits = mainThread.ec.theMapAwarenessAI.playIsRushingHighTierUnits;
boolean playerLikelyCanNotProduceHighTierUnits = mainThread.ec.theMapAwarenessAI.playerLikelyCanNotProduceHighTierUnits;
boolean playerDoesntHaveMassHeavyTanks = mainThread.ec.theMapAwarenessAI.playerDoesntHaveMassHeavyTanks;
boolean playerHasManyLightTanksButNoHeavyTank = mainThread.ec.theMapAwarenessAI.playerHasManyLightTanksButNoHeavyTank;
if(numberOfRocketTanks_AI < numberOfPlayerTurrets || (gameData.getRandom() > 925 && !playerHasMostlyLightTanks)){
currentProductionOrder = produceRocketTank;
}else if(theBaseInfo.canBuildHeavyTank
&& !playerHasManyLightTanksButNoHeavyTank
&& !playerHasMostlyLightTanks
&& !(numberOfHeavyTanks_player == 0 && maxNumberOfStealthTanks_playerInLastFiveMinutes < 3 && mainThread.frameIndex/30 > 600)
&& !(playerHasMostlyHeavyTanks && numberOfStealthTanks_player < numberOfHeavyTanks_AI*2)
&& (playIsRushingHighTierUnits || gameData.getRandom() > 985 || maxNumberOfStealthTanks_playerInLastFiveMinutes*4 > numberOfHeavyTanks_AI || (mainThread.frameIndex/30 > 400 && mainThread.frameIndex/30 < 600 && numberOfPlayerTurrets + numberOfLightTanks_player + numberOfRocketTanks_player + numberOfHeavyTanks_player*5 < 5))){
currentProductionOrder = produceHeavyTank;
}else if(theBaseInfo.canBuildStealthTank && (playerHasMostlyLightTanks || playerLikelyCanNotProduceHighTierUnits || playerDoesntHaveMassHeavyTanks) && !playerHasMostlyHeavyTanks){
currentProductionOrder = produceStealthTank;
}else{
currentProductionOrder = produceLightTank;
}
//make decision on what tech to research
if(mainThread.ec.theBuildingManagerAI.theBaseInfo.numberOfTechCenter > 0){
//Immediately start stealth tank upgrades when a tech center is built
if(!techCenter.stealthTankResearched_enemy){
if(techCenter.stealthTankResearchProgress_enemy == 255){
techCenter.cancelResearch(1);
techCenter.researchStealthTank(1);
System.out.println("----------------------------AI starts researching stealth tank------------------------------------");
}
}
if(numberOfLightTanks_AI >= 15 && theBaseInfo.currentCredit > 1000){
if(!techCenter.lightTankResearched_enemy){
if(techCenter.lightTankResearchProgress_enemy >= 240 && techCenter.stealthTankResearchProgress_enemy >= 240 && techCenter.rocketTankResearchProgress_enemy >= 240 && techCenter.heavyTankResearchProgress_enemy >= 240){
techCenter.researchLightTank(1);
System.out.println("----------------------------AI starts researching light tank------------------------------------");
}
}
}
//System.out.println("enemy light tank count: " + numberOfLightTanks_player + " at " + mainThread.frameIndex/30);
if(currentProductionOrder == produceStealthTank)
System.out.println("should make stealth tank now");
if(currentProductionOrder == produceHeavyTank){
System.out.println("should make Heavy tank now-----------------");
}
if(numberOfRocketTanks_AI > 5 && theBaseInfo.currentCredit > 750){
if(!techCenter.rocketTankResearched_enemy){
if(techCenter.lightTankResearchProgress_enemy >= 240 && techCenter.stealthTankResearchProgress_enemy >= 240 && techCenter.rocketTankResearchProgress_enemy >= 240 && techCenter.heavyTankResearchProgress_enemy >= 240){
techCenter.researchRocketTank(1);
System.out.println("----------------------------AI starts researching rocket tank------------------------------------");
}
}
}
if(numberOfHeavyTanks_AI > 5 && theBaseInfo.currentCredit > 1000){
if(!techCenter.heavyTankResearched_enemy){
if(techCenter.lightTankResearchProgress_enemy >= 240 && techCenter.stealthTankResearchProgress_enemy >= 240 && techCenter.rocketTankResearchProgress_enemy >= 240 && techCenter.heavyTankResearchProgress_enemy >= 240){
techCenter.researchHeavyTank(1);
System.out.println("----------------------------AI starts researching heavy tank------------------------------------");
}
}
}
}
for(int i = 0; i < mainThread.theAssetManager.factories.length; i++){
factory f = mainThread.theAssetManager.factories[i];
if(f != null && f.teamNo !=0){
f.moveTo(rallyPoint.x, rallyPoint.z);
if(f.isIdle()){
if(theBaseInfo.canBuildLightTank && maxNumOfUnitCanBeProduced > 0){
if(currentProductionOrder == produceLightTank)
f.buildLightTank();
else if(currentProductionOrder == produceRocketTank)
f.buildRocketTank();
else if(currentProductionOrder == produceStealthTank)
f.buildStealthTank();
else if(currentProductionOrder == produceHeavyTank)
f.buildHeavyTank();
maxNumOfUnitCanBeProduced--;
}
continue;
}
}
}
countTroopControlledByCombatAI();
findCenterOfTroopControlledByCombatAI();
}
public void addLightTank(lightTank o){
//check if other AI agent need light tank
if(mainThread.ec.theScoutingManagerAI.needLightTank()){
mainThread.ec.theScoutingManagerAI.addLightTank(o);
return;
}
//add the new light tank to combat AI's command
for(int i = 0; i < lightTanksControlledByCombatAI.length; i++){
if(lightTanksControlledByCombatAI[i] == null || (lightTanksControlledByCombatAI[i] != null && lightTanksControlledByCombatAI[i].currentHP <=0)){
lightTanksControlledByCombatAI[i] = o;
unitProduced++;
break;
}
}
}
public void addRocketTank(rocketTank o){
//check if other AI agent need rocket tank
//add the new rocket tank to combat AI's command
for(int i = 0; i < rocketTanksControlledByCombatAI.length; i++){
if(rocketTanksControlledByCombatAI[i] == null || (rocketTanksControlledByCombatAI[i] != null && rocketTanksControlledByCombatAI[i].currentHP <=0)){
rocketTanksControlledByCombatAI[i] = o;
unitProduced++;
break;
}
}
}
public void addStealthTank(stealthTank o){
//check if other AI agent need stealth tank
if(mainThread.ec.theScoutingManagerAI.needStealthTank()){
mainThread.ec.theScoutingManagerAI.addStealthTank(o);
return;
}
if(mainThread.ec.theBaseExpentionAI.needStealthTank()){
mainThread.ec.theBaseExpentionAI.addStealthTank(o);
return;
}
//add the new stealth tank to combat AI's command
for(int i = 0; i < stealthTanksControlledByCombatAI.length; i++){
if(stealthTanksControlledByCombatAI[i] == null || (stealthTanksControlledByCombatAI[i] != null && stealthTanksControlledByCombatAI[i].currentHP <=0)){
stealthTanksControlledByCombatAI[i] = o;
unitProduced++;
break;
}
}
}
public void addHeavyTank(heavyTank o){
//add the new heavy tank to combat AI's command
for(int i = 0; i < heavyTanksControlledByCombatAI.length; i++){
if(heavyTanksControlledByCombatAI[i] == null || (heavyTanksControlledByCombatAI[i] != null && heavyTanksControlledByCombatAI[i].currentHP <=0)){
heavyTanksControlledByCombatAI[i] = o;
unitProduced++;
break;
}
}
}
public void countTroopControlledByCombatAI(){
numberOfCombatUnitsUnderAttack = 0;
numberOfLightTanksControlledByCombatAI = 0;
numberOfRocketTanksControlledByCombatAI = 0;
numberOfStealthTanksControlledByCombatAI = 0;
numberOfHeavyTanksControlledByCombatAI = 0;
for(int i = 0; i < troopsControlledByCombatAI.length; i++){
troopsControlledByCombatAI[i] = null;
}
numberOfCombatUnit = 0;
for(int i = 0; i < lightTanksControlledByCombatAI.length; i++){
if(lightTanksControlledByCombatAI[i] != null && lightTanksControlledByCombatAI[i].currentHP > 0){
troopsControlledByCombatAI[numberOfCombatUnit] = lightTanksControlledByCombatAI[i];
if(troopsControlledByCombatAI[numberOfCombatUnit].underAttackCountDown > 0)
numberOfCombatUnitsUnderAttack++;
numberOfCombatUnit++;
numberOfLightTanksControlledByCombatAI++;
}
}
for(int i = 0; i < rocketTanksControlledByCombatAI.length; i++){
if(rocketTanksControlledByCombatAI[i] != null && rocketTanksControlledByCombatAI[i].currentHP > 0){
troopsControlledByCombatAI[numberOfCombatUnit] = rocketTanksControlledByCombatAI[i];
if(troopsControlledByCombatAI[numberOfCombatUnit].underAttackCountDown > 0)
numberOfCombatUnitsUnderAttack++;
numberOfCombatUnit++;
numberOfRocketTanksControlledByCombatAI++;
}
}
for(int i = 0; i < stealthTanksControlledByCombatAI.length; i++){
if(stealthTanksControlledByCombatAI[i] != null && stealthTanksControlledByCombatAI[i].currentHP > 0){
troopsControlledByCombatAI[numberOfCombatUnit] = stealthTanksControlledByCombatAI[i];
if(troopsControlledByCombatAI[numberOfCombatUnit].underAttackCountDown > 0)
numberOfCombatUnitsUnderAttack++;
numberOfCombatUnit++;
numberOfStealthTanksControlledByCombatAI++;
}
}
for(int i = 0; i < heavyTanksControlledByCombatAI.length; i++){
if(heavyTanksControlledByCombatAI[i] != null && heavyTanksControlledByCombatAI[i].currentHP > 0){
troopsControlledByCombatAI[numberOfCombatUnit] = heavyTanksControlledByCombatAI[i];
if(troopsControlledByCombatAI[numberOfCombatUnit].underAttackCountDown > 0)
numberOfCombatUnitsUnderAttack++;
numberOfCombatUnit++;
numberOfHeavyTanksControlledByCombatAI++;
}
}
}
public void findCenterOfTroopControlledByCombatAI(){
float centerX = 0;
float centerZ = 0;
vector centre;
double distance = 0;
numberOfUnitInCombatRadius = 0;
numberOfUnitOutsideCombatRadius = 0;
//when there is no combat unit there is no point to calculate the center of the combat units
if(numberOfCombatUnit == 0){
combatAICenterX = -1;
combatAICenterZ = -1;
return;
}
for(int i = 0; i < unitInCombatRadius.length; i++){
unitInCombatRadius[i] = null;
}
for(int i = 0; i < unitOutsideCombatRadius.length; i++){
unitOutsideCombatRadius[i] = null;
}
//calculate the center of the troops using the all the unites that are under the control of the combatAI
if(combatAICenterX == -1){
combatAICenterX = 0;
combatAICenterZ = 0;
for(int i =0; i < numberOfCombatUnit; i++){
centre = troopsControlledByCombatAI[i].centre;
combatAICenterX+=centre.x;
combatAICenterZ+=centre.z;
}
combatAICenterX /= numberOfCombatUnit;
combatAICenterZ /= numberOfCombatUnit;
}
//exclude the units are too far away from the center of the troops, (i.e the unites that just come out of the factory), and recalculate the center
for(int i =0; i < numberOfCombatUnit; i++){
centre = troopsControlledByCombatAI[i].centre;
distance = Math.sqrt((centre.x - combatAICenterX)*(centre.x - combatAICenterX) + (centre.z - combatAICenterZ)*(centre.z - combatAICenterZ));
if(distance < 4.5){
centerX += centre.x;
centerZ += centre.z;
if(numberOfUnitInCombatRadius < unitInCombatRadius.length)
unitInCombatRadius[numberOfUnitInCombatRadius] = troopsControlledByCombatAI[i];
numberOfUnitInCombatRadius++;
}else{
if(numberOfUnitOutsideCombatRadius < unitOutsideCombatRadius.length)
unitOutsideCombatRadius[numberOfUnitOutsideCombatRadius] = troopsControlledByCombatAI[i];
numberOfUnitOutsideCombatRadius++;
}
}
float unitInCombactRadiusPercentage = 1;
if(numberOfUnitInCombatRadius + numberOfUnitOutsideCombatRadius >0)
unitInCombactRadiusPercentage = (float)numberOfUnitInCombatRadius/(float)(numberOfUnitInCombatRadius + numberOfUnitOutsideCombatRadius);
float unitInCombactRadiusPercentageThreshold = 0.7f;
if(numberOfCombatUnitsUnderAttack > 0)
unitInCombactRadiusPercentageThreshold = 0.25f;
//System.out.println(unitInCombactRadiusPercentage + " :" + unitInCombactRadiusPercentageThreshold);
//need to recalculate the center if there is a significant amount of combat unites that are outside of the combat radius
if(unitInCombactRadiusPercentage < unitInCombactRadiusPercentageThreshold){
combatAICenterX = 0;
combatAICenterZ = 0;
for(int i =0; i < numberOfCombatUnit; i++){
centre = troopsControlledByCombatAI[i].centre;
combatAICenterX+=centre.x;
combatAICenterZ+=centre.z;
}
combatAICenterX /= numberOfCombatUnit;
combatAICenterZ /= numberOfCombatUnit;
for(int i = 0; i < unitInCombatRadius.length; i++){
unitInCombatRadius[i] = null;
}
for(int i = 0; i < unitOutsideCombatRadius.length; i++){
unitOutsideCombatRadius[i] = null;
}
numberOfUnitInCombatRadius = 0;
numberOfUnitOutsideCombatRadius = 0;
centerX = 0;
centerZ = 0;
for(int i =0; i < numberOfCombatUnit; i++){
centre = troopsControlledByCombatAI[i].centre;
distance = Math.sqrt((centre.x - combatAICenterX)*(centre.x - combatAICenterX) + (centre.z - combatAICenterZ)*(centre.z - combatAICenterZ));
if(distance < 10){
centerX += centre.x;
centerZ += centre.z;
if(numberOfUnitInCombatRadius < unitInCombatRadius.length)
unitInCombatRadius[numberOfUnitInCombatRadius] = troopsControlledByCombatAI[i];
numberOfUnitInCombatRadius++;
}else{
if(numberOfUnitOutsideCombatRadius < unitOutsideCombatRadius.length)
unitOutsideCombatRadius[numberOfUnitOutsideCombatRadius] = troopsControlledByCombatAI[i];
numberOfUnitOutsideCombatRadius++;
}
}
}
combatAICenterX = centerX/numberOfUnitInCombatRadius;
combatAICenterZ = centerZ/numberOfUnitInCombatRadius;
}
}

20
entity/.gitignore vendored Normal file
View File

@ -0,0 +1,20 @@
/communicationCenter.class
/constructionVehicle.class
/constructionYard.class
/drone.class
/factory.class
/goldMine.class
/gunTurret.class
/harvester.class
/heavyTank.class
/lightPole.class
/lightTank.class
/missileTurret.class
/palmTree.class
/powerPlant.class
/refinery.class
/rocketTank.class
/solidObject.class
/stealthTank.class
/techCenter.class
/tokenObject.class

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

1813
entity/constructionYard.java Normal file

File diff suppressed because it is too large Load Diff

673
entity/drone.java Normal file
View File

@ -0,0 +1,673 @@
package entity;
import java.awt.Rectangle;
import core.*;
//small flying unit capable of repairing tanks
public class drone extends solidObject{
public vector iDirectionBody, jDirectionBody, kDirectionBody;
public vector bodyCenter;
public static polygon3D[] polys;
public static vector engine1Center, engine2Center;
public int fan1Angle, fan2Angle;
public final static Rectangle visibleBoundary = new Rectangle(-100,-150,1068, 812);
//a screen space boundary which is used to test if the entire object is within the screen
public final static Rectangle screenBoundary = new Rectangle(40,40,688, 432);
//screen space boundary which is used to test if the shadow of the object is within the screen
public final static Rectangle shadowBoundary1 = new Rectangle(0,0,768, 512);
public int bodyAngle, destinationAngle;
//index of the tiles to check when the drone is idle
public static int[] tileCheckList;
public factory myFactory;
public static int numOfPolygons;
public float heightVariance;
public int randomNumber;
public solidObject targetUnit;
public vector idlePosition;
public static final int returnToIdlePosition = 0;
public static final int healUnit = 1;
public static final int turnRate = 5;
public static final float maxSpeed = 0.04f;
public float serviceRadius;
public static vector armCenter, armDirection;
public vector armCenterClone, armDirectionClone;
public drone(vector origin, int bodyAngle, factory myFactory){
//register itself in factory and find out idle location
idlePosition = new vector(0,0,0);
serviceRadius = 3.5f;
for(int i = 0; i < 3; i++){
if(myFactory.myDrones[i] == null){
myFactory.myDrones[i] = this;
if(i == 0){
idlePosition.set(myFactory.centre.x, 0, myFactory.centre.z+0.15f);
}else if(i == 1){
idlePosition.set(myFactory.centre.x - 0.3f, 0, myFactory.centre.z-0.25f);
}else{
idlePosition.set(myFactory.centre.x + 0.2f, 0, myFactory.centre.z-0.25f);
}
break;
}
}
speed = 0f;
currentHP = 20;
start = origin.myClone();
centre = origin.myClone();
tempCentre = origin.myClone();
bodyCenter = origin.myClone();
this.bodyAngle = 360 -bodyAngle;
this.immediateDestinationAngle = bodyAngle;
destinationAngle = bodyAngle;
teamNo = myFactory.teamNo;
this.myFactory = myFactory;
//drone does't have any collision boundary, and its unselectable
type = 5;
isSelectable = false;
height = centre.y + 0.5f; //?
theAssetManager = mainThread.theAssetManager;
movement = new vector(0,0,0);
//create main axis in object space
iDirection = new vector(1f,0,0);
jDirection = new vector(0,1f,0);
kDirection = new vector(0,0,1f);
iDirection.rotate_XZ(360-bodyAngle);
jDirection.rotate_XZ(360-bodyAngle);
kDirection.rotate_XZ(360-bodyAngle);
//create polygons
makePolygons();
if(tileCheckList == null){
tileCheckList = generateTileCheckList(11f);
}
randomNumber = (int)(Math.random()*360);
}
public void makePolygons(){
if(polys == null){
polys = new polygon3D[171];
vector[] v;
engine1Center = new vector(0.041f, 0, 0);
engine2Center = new vector(-0.041f, 0, 0);
//create engine fan
start.reset();
float delta = (float)Math.PI/4;
v = new vector[]{
put(0.027*Math.cos(1*delta), -0.01, 0.027*Math.sin(1*delta)),
put(0.027*Math.cos((0)*delta), -0.01, 0.027*Math.sin((0)*delta)),
put(0.00001*Math.cos((0)*delta), -0.01, 0.00001*Math.sin((0)*delta)),
put(0.00001*Math.cos(1*delta), -0.01, 0.00001*Math.sin(1*delta)),
};
addPolygon(polys, new polygon3D(v, v[0], v[1], v[3], mainThread.textures[26], 1f,1f,1));
v = new vector[]{
put(0.027*Math.cos(5*delta), -0.01, 0.027*Math.sin(5*delta)),
put(0.027*Math.cos((4)*delta), -0.01, 0.027*Math.sin((4)*delta)),
put(0.00001*Math.cos((4)*delta), -0.01, 0.00001*Math.sin((4)*delta)),
put(0.00001*Math.cos(5*delta), -0.01, 0.00001*Math.sin(5*delta)),
};
addPolygon(polys, new polygon3D(v, v[0], v[1], v[3], mainThread.textures[26], 1f,1f,1));
v = new vector[]{
put(0.027*Math.cos(3*delta), -0.01, 0.027*Math.sin(3*delta)),
put(0.027*Math.cos((2)*delta), -0.01, 0.027*Math.sin((2)*delta)),
put(0.00001*Math.cos((2)*delta), -0.01, 0.00001*Math.sin((2)*delta)),
put(0.00001*Math.cos(3*delta), -0.01, 0.00001*Math.sin(3*delta)),
};
addPolygon(polys, new polygon3D(v, v[0], v[1], v[3], mainThread.textures[26], 1f,1f,1));
v = new vector[]{
put(0.027*Math.cos(7*delta), -0.01, 0.027*Math.sin(7*delta)),
put(0.027*Math.cos((6)*delta), -0.01, 0.027*Math.sin((6)*delta)),
put(0.00001*Math.cos((6)*delta), -0.01, 0.00001*Math.sin((6)*delta)),
put(0.00001*Math.cos(7*delta), -0.01, 0.00001*Math.sin(7*delta)),
};
addPolygon(polys, new polygon3D(v, v[0], v[1], v[3], mainThread.textures[26], 1f,1f,1));
//create main body section
v = new vector[]{ put(-0.016, 0, -0.006),put(-0.016, 0, 0.006), put(-0.015, 0, 0.013), put(0.015, 0, 0.013), put(0.016, 0, 0.006), put(0.016, 0, -0.006), put(0.015, 0, -0.013),put(-0.015, 0, -0.013)};
addPolygon(polys, new polygon3D(v, v[0], v[1], v[3], mainThread.textures[26], 1f,1f,1));
v = new vector[]{put(-0.016, 0, -0.006), put(-0.015, 0, -0.013), put(-0.015, -0.015, -0.013), put(-0.016, -0.015, -0.006)};
addPolygon(polys, new polygon3D(v, v[0], v[1], v[3], mainThread.textures[26], 1f,1f,1));
v = new vector[]{ put(0.016, -0.015, -0.006), put(0.015, -0.015, -0.013), put(0.015, 0, -0.013),put(0.016, 0, -0.006)};
addPolygon(polys, new polygon3D(v, v[0], v[1], v[3], mainThread.textures[26], 1f,1f,1));
v = new vector[]{put(-0.016, -0.015, 0.006), put(-0.015, -0.015, 0.013), put(-0.015, 0, 0.013), put(-0.016, 0, 0.006)};
addPolygon(polys, new polygon3D(v, v[0], v[1], v[3], mainThread.textures[26], 1f,1f,1));
v = new vector[]{put(0.016, 0, 0.006), put(0.015, 0, 0.013), put(0.015, -0.015, 0.013), put(0.016, -0.015, 0.006)};
addPolygon(polys, new polygon3D(v, v[0], v[1], v[3], mainThread.textures[26], 1f,1f,1));
v = new vector[]{put(0.015, 0, 0.013), put(-0.015, 0, 0.013), put(-0.015, -0.015, 0.013), put(0.015, -0.015, 0.013)};
addPolygon(polys, new polygon3D(v, v[0], v[1], v[3], mainThread.textures[26], 1f,1f,1));
v = new vector[]{put(0.015, -0.015, -0.013), put(-0.015, -0.015, -0.013), put(-0.015, 0, -0.013), put(0.015, 0, -0.013)};
addPolygon(polys, new polygon3D(v, v[0], v[1], v[3], mainThread.textures[26], 1f,1f,1));
//left engine
float r = 0.03f;
delta = (float)Math.PI/8;
start.x-=0.041f;
for(int i = 0; i < 16; i++){
v = new vector[]{put(r*Math.cos(i*delta), 0.01, r*Math.sin(i*delta)),
put(r*Math.cos((i+1)*delta), 0.01, r*Math.sin((i+1)*delta)),
put(r*Math.cos((i+1)*delta), -0.013, r*Math.sin((i+1)*delta)),
put(r*Math.cos(i*delta), -0.013, r*Math.sin(i*delta))
};
addPolygon(polys, new polygon3D(v, v[0], v[1], v[3], mainThread.textures[26], 1f,1f,1));
}
float r2 = 0.026f;
for(int i = 0; i < 16; i++){
v = new vector[]{put(r2*Math.cos(i*delta), -0.013, r2*Math.sin(i*delta)),
put(r2*Math.cos((i+1)*delta), -0.013, r2*Math.sin((i+1)*delta)),
put(r2*Math.cos((i+1)*delta), 0.01, r2*Math.sin((i+1)*delta)),
put(r2*Math.cos(i*delta), 0.01, r2*Math.sin(i*delta))
};
addPolygon(polys, new polygon3D(v, v[0], v[1], v[3], mainThread.textures[26], 1f,1f,1));
}
for(int i = 0; i < 16; i++){
v = new vector[]{
put(r2*Math.cos(i*delta), 0.01, r2*Math.sin(i*delta)),
put(r2*Math.cos((i+1)*delta), 0.01, r2*Math.sin((i+1)*delta)),
put(r*Math.cos((i+1)*delta), 0.01, r*Math.sin((i+1)*delta)),
put(r*Math.cos(i*delta), 0.01, r*Math.sin(i*delta)),
};
addPolygon(polys, new polygon3D(v, v[0], v[1], v[3], mainThread.textures[26], 1f,1f,1));
}
float r3 = 0.005f;
float r4 = 0.0001f;
for(int i = 0; i < 16; i++){
v = new vector[]{put(r4*Math.cos(i*delta), 0.01, r4*Math.sin(i*delta)),
put(r4*Math.cos((i+1)*delta), 0.01, r4*Math.sin((i+1)*delta)),
put(r3*Math.cos((i+1)*delta), -0.01, r3*Math.sin((i+1)*delta)),
put(r3*Math.cos(i*delta), -0.01, r3*Math.sin(i*delta))
};
addPolygon(polys, new polygon3D(v, v[0], v[1], v[3], mainThread.textures[26], 1f,1f,1));
}
//right engine
start.x+=0.082f;
for(int i = 0; i < 16; i++){
v = new vector[]{put(r*Math.cos(i*delta), 0.01, r*Math.sin(i*delta)),
put(r*Math.cos((i+1)*delta), 0.01, r*Math.sin((i+1)*delta)),
put(r*Math.cos((i+1)*delta), -0.013, r*Math.sin((i+1)*delta)),
put(r*Math.cos(i*delta), -0.013, r*Math.sin(i*delta))
};
addPolygon(polys, new polygon3D(v, v[0], v[1], v[3], mainThread.textures[26], 1f,1f,1));
}
for(int i = 0; i < 16; i++){
v = new vector[]{put(r2*Math.cos(i*delta), -0.013, r2*Math.sin(i*delta)),
put(r2*Math.cos((i+1)*delta), -0.013, r2*Math.sin((i+1)*delta)),
put(r2*Math.cos((i+1)*delta), 0.01, r2*Math.sin((i+1)*delta)),
put(r2*Math.cos(i*delta), 0.01, r2*Math.sin(i*delta))
};
addPolygon(polys, new polygon3D(v, v[0], v[1], v[3], mainThread.textures[26], 1f,1f,1));
}
for(int i = 0; i < 16; i++){
v = new vector[]{
put(r2*Math.cos(i*delta), 0.01, r2*Math.sin(i*delta)),
put(r2*Math.cos((i+1)*delta), 0.01, r2*Math.sin((i+1)*delta)),
put(r*Math.cos((i+1)*delta), 0.01, r*Math.sin((i+1)*delta)),
put(r*Math.cos(i*delta), 0.01, r*Math.sin(i*delta)),
};
addPolygon(polys, new polygon3D(v, v[0], v[1], v[3], mainThread.textures[26], 1f,1f,1));
}
for(int i = 0; i < 16; i++){
v = new vector[]{put(r4*Math.cos(i*delta), 0.01, r4*Math.sin(i*delta)),
put(r4*Math.cos((i+1)*delta), 0.01, r4*Math.sin((i+1)*delta)),
put(r3*Math.cos((i+1)*delta), -0.01, r3*Math.sin((i+1)*delta)),
put(r3*Math.cos(i*delta), -0.01, r3*Math.sin(i*delta))
};
addPolygon(polys, new polygon3D(v, v[0], v[1], v[3], mainThread.textures[26], 1f,1f,1));
}
//repair arm
start.x-=0.041f;
r2 = 0.008f;
for(int i = 0; i < 16; i++){
v = new vector[]{put(r2*Math.cos(i*delta), 0, r2*Math.sin(i*delta)),
put(r2*Math.cos((i+1)*delta), 0, r2*Math.sin((i+1)*delta)),
put(r2*Math.cos((i+1)*delta), -0.08, r2*Math.sin((i+1)*delta)),
put(r2*Math.cos(i*delta), -0.08, r2*Math.sin(i*delta))
};
addPolygon(polys, new polygon3D(v, v[0], v[1], v[3], mainThread.textures[26], 1f,1f,1));
}
iDirection.rotate_YZ(340);
jDirection.rotate_YZ(340);
kDirection.rotate_YZ(340);
start.y-=0.075f;
r3 = 0.007f;
for(int i = 0; i < 16; i++){
v = new vector[]{put(r2*Math.cos(i*delta), 0, r2*Math.sin(i*delta)),
put(r2*Math.cos((i+1)*delta), 0, r2*Math.sin((i+1)*delta)),
put(r3*Math.cos((i+1)*delta), -0.04, r3*Math.sin((i+1)*delta)),
put(r3*Math.cos(i*delta), -0.04, r3*Math.sin(i*delta))
};
addPolygon(polys, new polygon3D(v, v[0], v[1], v[3], mainThread.textures[26], 1f,1f,1));
}
armCenter = put(0,-0.04, 0);
armDirection = jDirection.myClone();
armDirection.y*=-1;
}
polygons = clonePolygons(polys, false);
armCenterClone = armCenter.myClone();
armDirectionClone = armDirection.myClone();
}
//update the model
public void update(){
//check if factory where the drone is spawned has been destroyed
if(myFactory.currentHP <= 0){
if(targetUnit != null)
targetUnit.myHealer = null;
//spawn an explosion when the object is destroyed
float[] tempFloat = theAssetManager.explosionInfo[theAssetManager.explosionCount];
tempFloat[0] = centre.x;
tempFloat[1] = centre.y;
tempFloat[2] = centre.z;
tempFloat[3] = 0.99f;
tempFloat[4] = 1;
tempFloat[5] = 0;
tempFloat[6] = 7;
tempFloat[7] = this.height;
theAssetManager.explosionCount++;
theAssetManager.removeObject(this);
return;
}
//handle AI
if(!disableUnitLevelAI){
if(currentCommand == returnToIdlePosition){
if(centre.y <=0.05){
centre.y+=0.005f;
}
if(idlePosition.x != centre.x || idlePosition.z != centre.z){
double distanceToDestination = Math.sqrt((idlePosition.x - centre.x)* (idlePosition.x - centre.x) + (idlePosition.z - centre.z)*(idlePosition.z - centre.z));
if(distanceToDestination >= 0.2f){
if(speed <= maxSpeed)
speed+=0.002f;
}
if(distanceToDestination < 0.4f){
if(speed >= 0.03f)
speed-=0.002f;
}
if(distanceToDestination < 0.25f){
if(speed >= 0.02f)
speed-=0.002f;
}
if(distanceToDestination < 0.1f){
if(speed >= 0.01f)
speed-=0.002f;
}
//move to idle position
if(distanceToDestination <= speed){
centre.x = idlePosition.x;
centre.z = idlePosition.z;
speed = 0;
}else{
movement.set(idlePosition.x - centre.x, 0, idlePosition.z - centre.z);
movement.unit();
movement.scale(speed);
centre.add(movement);
}
//face idle position
destinationAngle = geometry.findAngle(centre.x, centre.z, idlePosition.x, idlePosition.z);
int angleDelta = 360 - (geometry.findAngleDelta(bodyAngle, destinationAngle, turnRate) + 360)%360;
bodyAngle= (bodyAngle - angleDelta + 360)%360;
if(Math.abs(bodyAngle - destinationAngle) <= turnRate)
bodyAngle = destinationAngle;
}
//scan for nearby damaged unit
currentOccupiedTile = (int)(centre.x*64)/16 + (127 - (int)(centre.z*64)/16)*128;
for(int i = 0; i < tileCheckList.length; i++){
if(targetUnit != null)
break;
if(tileCheckList[i] != Integer.MAX_VALUE){
int index = currentOccupiedTile + tileCheckList[i];
if(index < 0 || index >= 16384)
continue;
tile = mainThread.gridMap.tiles[index];
for(int j = 0; j < 4; j++){
if(tile[j] != null){
if(tile[j].teamNo == teamNo && tile[j].currentHP < tile[j].getMaxHp() && getDistance(myFactory, tile[j]) < serviceRadius && tile[j].myHealer == null){
currentCommand = healUnit;
targetUnit = tile[j];
targetUnit.myHealer = this;
break;
}
}
}
}
}
}else if(currentCommand == healUnit){
if(targetUnit.currentHP <=0 || getDistance(myFactory, targetUnit) >= serviceRadius){
targetUnit.myHealer = null;
targetUnit = null;
currentCommand = returnToIdlePosition;
}else{
tempVector.set(targetUnit.centre);
if(tempVector.x != centre.x || tempVector.z != centre.z){
double distanceToDestination = Math.sqrt((tempVector.x - centre.x)* (tempVector.x - centre.x) + (tempVector.z - centre.z)*(tempVector.z - centre.z));
if(distanceToDestination >= 0.2f){
if(speed <= maxSpeed)
speed+=0.002f;
if(centre.y <=0.1){
centre.y+=0.01f;
}
}else{
if(centre.y > - 0.15){
centre.y-=0.01f;
}
}
if(distanceToDestination < 0.4f){
if(speed >= 0.03f)
speed-=0.002f;
//heal unit
if(targetUnit.currentHP < targetUnit.getMaxHp() || targetUnit.underAttackCountDown > 60){
if(mainThread.frameIndex%5 == 1 && centre.y <=-0.1){
targetUnit.currentHP+=5;
if(targetUnit.currentHP > targetUnit.getMaxHp())
targetUnit.currentHP = targetUnit.getMaxHp();
}
if(mainThread.frameIndex%2==0 && centre.y <=-0.15){
//spawn a healing steam particle
float[] tempFloat = theAssetManager.smokeEmmiterList[theAssetManager.smokeEmmiterCount];
tempFloat[0] = armCenterClone.x + (float)(Math.random()/20) - 0.025f;
tempFloat[1] = armCenterClone.y;
tempFloat[2] = armCenterClone.z + (float)(Math.random()/20) - 0.025f;
tempFloat[3] = 0.8f;
tempFloat[4] = 1;
tempFloat[5] = 11;
tempFloat[6] = this.height;
theAssetManager.smokeEmmiterCount++;
}
}else{
targetUnit.myHealer = null;
targetUnit = null;
currentCommand = returnToIdlePosition;
}
}
if(distanceToDestination < 0.25f){
if(speed >= 0.02f)
speed-=0.002f;
}
if(distanceToDestination < 0.1f){
if(speed >= 0.01f)
speed-=0.002f;
}
if(distanceToDestination >= 0.06f){
movement.set(tempVector.x - centre.x, 0, tempVector.z - centre.z);
movement.unit();
movement.scale(speed);
centre.add(movement);
}
//face idle position
destinationAngle = geometry.findAngle(centre.x, centre.z, tempVector.x, tempVector.z);
int angleDelta = 360 - (geometry.findAngleDelta(bodyAngle, destinationAngle, turnRate) + 360)%360;
bodyAngle= (bodyAngle - angleDelta + 360)%360;
if(Math.abs(bodyAngle - destinationAngle) <= turnRate)
bodyAngle = destinationAngle;
}
}
}
}
fan1Angle+=60;
fan2Angle+=300;
fan1Angle = fan1Angle%360;
fan2Angle = fan2Angle%360;
heightVariance = gameData.sin[((mainThread.frameIndex+randomNumber)*5)%360] * 0.01f;
//update center in camera coordinate
tempCentre.set(centre);
tempCentre.subtract(camera.position);
tempCentre.rotate_XZ(camera.XZ_angle);
tempCentre.rotate_YZ(camera.YZ_angle);
tempCentre.updateLocation();
//check if the tank object is visible in mini map
visible_minimap = theAssetManager.minimapBitmap[(int)(centre.x*64)/16 + (127 - (int)(centre.z*64)/16)*128];
//test if the object is visible in camera point of view
if(visibleBoundary.contains(tempCentre.screenX, tempCentre.screenY) && myFactory.isRevealed && visible_minimap){
visible = true;
for(int i = 0; i < numOfPolygons; i++){
polygons[i].update_lightspace();
}
//update centre
updateGeometry();
if(screenBoundary.contains(tempCentre.screenX, tempCentre.screenY))
withinViewScreen = true;
else
withinViewScreen = false;
}else{
visible = false;
}
}
public void updateGeometry(){
int bodyAngle_ = 360 - bodyAngle;
//rotate fans
for(int j = 0; j < polygons[0].vertex3D.length; j++){
polygons[0].vertex3D[j].set(polys[0].vertex3D[j]);
polygons[0].vertex3D[j].rotate_XZ(fan1Angle);
polygons[0].vertex3D[j].add(engine1Center);
polygons[0].vertex3D[j].rotate_XZ(bodyAngle_);
polygons[0].vertex3D[j].add(centre);
polygons[0].vertex3D[j].y+=heightVariance;
polygons[1].vertex3D[j].set(polys[1].vertex3D[j]);
polygons[1].vertex3D[j].rotate_XZ(fan1Angle);
polygons[1].vertex3D[j].add(engine1Center);
polygons[1].vertex3D[j].rotate_XZ(bodyAngle_);
polygons[1].vertex3D[j].add(centre);
polygons[1].vertex3D[j].y+=heightVariance;
polygons[2].vertex3D[j].set(polys[2].vertex3D[j]);
polygons[2].vertex3D[j].rotate_XZ(fan2Angle);
polygons[2].vertex3D[j].add(engine2Center);
polygons[2].vertex3D[j].rotate_XZ(bodyAngle_);
polygons[2].vertex3D[j].add(centre);
polygons[2].vertex3D[j].y+=heightVariance;
polygons[3].vertex3D[j].set(polys[3].vertex3D[j]);
polygons[3].vertex3D[j].rotate_XZ(fan2Angle);
polygons[3].vertex3D[j].add(engine2Center);
polygons[3].vertex3D[j].rotate_XZ(bodyAngle_);
polygons[3].vertex3D[j].add(centre);
polygons[3].vertex3D[j].y+=heightVariance;
}
//update main body
for(int i =4; i < numOfPolygons; i++){
for(int j = 0; j < polygons[i].vertex3D.length; j++){
polygons[i].vertex3D[j].set(polys[i].vertex3D[j]);
polygons[i].normal.set(polys[i].normal);
polygons[i].normal.rotate_XZ(bodyAngle_);
polygons[i].vertex3D[j].rotate_XZ(bodyAngle_);
polygons[i].vertex3D[j].add(centre);
polygons[i].vertex3D[j].y+=heightVariance;
polygons[i].findDiffuse();
}
}
//update arm
armCenterClone.set(armCenter);
armCenterClone.rotate_XZ(bodyAngle_);
armCenterClone.add(centre);
armCenterClone.y+=heightVariance;
armDirectionClone.set(armDirection);
armDirectionClone.rotate_XZ(bodyAngle_);
}
public void draw(){
if(!visible)
return;
for(int i = 0; i < numOfPolygons; i++){
polygons[i].update();
polygons[i].draw();
}
}
public int addPolygon(polygon3D[] polys, polygon3D poly){
for(int i = 0; i < polys.length; i++){
if(polys[i] == null){
polys[i] = poly;
numOfPolygons++;
return i;
}
}
return -1;
}
public float getDistance(solidObject o1, solidObject o2){
return (float)Math.sqrt((o1.centre.x - o2.centre.x)*(o1.centre.x - o2.centre.x) + (o1.centre.z - o2.centre.z)*(o1.centre.z - o2.centre.z));
}
}

2059
entity/factory.java Normal file

File diff suppressed because it is too large Load Diff

401
entity/goldMine.java Normal file
View File

@ -0,0 +1,401 @@
package entity;
import java.awt.Rectangle;
import core.*;
public class goldMine extends solidObject{
//the polygons of the model
private polygon3D[] polygons;
//the amount of gold available
public int goldDeposite;
public int maxDeposite;
public int textureIndex;
public static int maxHP = 9999;
public static vector tempVector0 = new vector(0,0,0);
public static vector tempVector1 = new vector(0,0,0);
public static vector tempVector2 = new vector(0,0,0);
public static vector tempVector3 = new vector(0,0,0);
public static vector origin = new vector(0,0,0);
public static vector top = new vector(0,0,0);
public static vector bot = new vector(0,0,0);
public static vector deltaX = new vector(0,0,0);
public static vector deltaZ = new vector(0,0,0);
//gold mine occupies 4 tiles
public int [] tileIndex = new int[6];
public vector shadowvertex0, tempshadowvertex0,shadowvertex1, tempshadowvertex1,shadowvertex2, tempshadowvertex2,shadowvertex3, tempshadowvertex3;
//a screen space boundary which is used to test if the object is visible from camera point of view
public final static Rectangle visibleBoundary = new Rectangle(-85,-85,920, 762);
//a screen space boundary which is used to test if the entire object is within the screen
public final static Rectangle screenBoundary = new Rectangle(60,60,648, 402);
//screen space boundary which is used to test if the shadow of the object is within the screen
public final static Rectangle shadowBoundary1 = new Rectangle(40,40,728, 472);
//a screen space boundary which is used to test if the vision polygon of the object is visible.
public final static Rectangle visionBoundary = new Rectangle(0,0,1600, 2000);
//gold mine never moves
public final static vector movenment = new vector(0,0,0);
public int polygonCount;
public goldMine(float x, float y, float z, int amount){
goldDeposite =amount;
maxDeposite = amount;
//uncontrollable unit, but act as a big sized static collidable agent
ID = -1;
type = 103;
teamNo = -1;
currentHP = 9999;
progressStatus = 100;
textureIndex = 39;
currentCommand = StandBy;
start = new vector(x,y,z);
if(start.y < -0.515f)
isSelectable = false;
//create 2D boundary
boundary2D = new Rect((int)(x*64) - 16, (int)(z*64) + 16, 32, 32);
boundary2D.owner = this;
int centerX = (int)(x*64);
int centerY = (int)(z*64);
if(!(start.y < -0.515f)){
tileIndex[0] = (centerX - 8)/16 + (127 - (centerY + 8)/16)*128;
tileIndex[1] = (centerX + 8)/16 + (127 - (centerY + 8)/16)*128;
tileIndex[2] = (centerX + 8)/16 + (127 - (centerY - 8)/16)*128;
tileIndex[3] = (centerX - 8)/16 + (127 - (centerY - 8)/16)*128;
mainThread.gridMap.tiles[tileIndex[0]][0] = this;
mainThread.gridMap.tiles[tileIndex[1]][0] = this;
mainThread.gridMap.tiles[tileIndex[2]][0] = this;
mainThread.gridMap.tiles[tileIndex[3]][0] = this;
mainThread.gridMap.tiles[tileIndex[0]][1] = this;
mainThread.gridMap.tiles[tileIndex[1]][1] = this;
mainThread.gridMap.tiles[tileIndex[2]][1] = this;
mainThread.gridMap.tiles[tileIndex[3]][1] = this;
mainThread.gridMap.tiles[tileIndex[0]][2] = this;
mainThread.gridMap.tiles[tileIndex[1]][2] = this;
mainThread.gridMap.tiles[tileIndex[2]][2] = this;
mainThread.gridMap.tiles[tileIndex[3]][2] = this;
mainThread.gridMap.tiles[tileIndex[0]][3] = this;
mainThread.gridMap.tiles[tileIndex[1]][3] = this;
mainThread.gridMap.tiles[tileIndex[2]][3] = this;
mainThread.gridMap.tiles[tileIndex[3]][3] = this;
mainThread.gridMap.tiles[tileIndex[0]][4] = this;
mainThread.gridMap.tiles[tileIndex[1]][4] = this;
mainThread.gridMap.tiles[tileIndex[2]][4] = this;
mainThread.gridMap.tiles[tileIndex[3]][4] = this;
}
//init model
iDirection = new vector(1f,0,0);
jDirection = new vector(0,1f,0);
kDirection = new vector(0,0,1f);
centre = start.myClone();
tempCentre = start.myClone();
shadowvertex0 =start.myClone();
shadowvertex0.add(-0.45f,-0.2f, -0.45f);
tempshadowvertex0 = new vector(0,0,0);
shadowvertex1 =start.myClone();
shadowvertex1.add(-0.45f,-0.2f, 0.2f);
tempshadowvertex1 = new vector(0,0,0);
shadowvertex2 =start.myClone();
shadowvertex2.add(0.2f,-0.2f, -0.45f);
tempshadowvertex2 = new vector(0,0,0);
shadowvertex3 =start.myClone();
shadowvertex3.add(0.2f,-0.2f, 0.2f);
tempshadowvertex3 = new vector(0,0,0);
if(!(start.y < -0.515f)){
int color = 12 << 24 | 245 << 16 | 198 << 8 | 20;
int position = tileIndex[0];
postProcessingThread.theMiniMap.background[position -128] = color;
postProcessingThread.theMiniMap.background[position - 129] = color;
postProcessingThread.theMiniMap.background[position - 127] = color;
postProcessingThread.theMiniMap.background[position-1] = color;
postProcessingThread.theMiniMap.background[position] = color;
postProcessingThread.theMiniMap.background[position+1] = color;
postProcessingThread.theMiniMap.background[position + 127] = color;
postProcessingThread.theMiniMap.background[position + 128] = color;
postProcessingThread.theMiniMap.background[position + 129] = color;
}
makePolygons();
}
private void makePolygons(){
polygons = new polygon3D[32*32*2];
//load height map
float[] heightmap = new float[(32+1)*(32+1)];
int[] hm = mainThread.textures[38].heightmap;
for(int i = 0; i < 33; i++){
for(int j =0; j< 33; j++){
heightmap[j + i * 33] = ((float)hm[j*8 + i*8*257])*0.0014f + centre.y;
}
}
float dx = 0.56f / 32;
float dz = -0.56f / 32;
float x_start = start.x - 0.32f;
float z_start = start.z + 0.30f;
int index = 0;
for(int i = 0; i < 32; i++){
for(int j = 0; j < 32; j++){
tempVector0.set(x_start + dx*j, heightmap[j + i*33], z_start + dz*i);
tempVector1.set(x_start + dx*(j+1), heightmap[j + 1 + i*33], z_start + dz*i);
tempVector2.set(x_start + dx*(j+1), heightmap[j + 1 + (i +1)*33], z_start + dz*(i+1));
tempVector3.set(x_start + dx*j, heightmap[j + (i +1)*33], z_start + dz*(i+1));
if(start.y < -0.515f){
if(tempVector0.y < -0.755){
continue;
}
}
v = new vector[]{tempVector0.myClone(), tempVector1.myClone(), tempVector3.myClone()};
deltaX.set(tempVector0);
deltaX.subtract(tempVector1);
deltaZ.set(tempVector0);
deltaZ.subtract(tempVector3);
origin.set(tempVector0);
origin.add(deltaX, j);
origin.add(deltaZ, i);
top.set(origin);
top.add(deltaX, -32);
bot.set(origin);
bot.add(deltaZ, -32);
polygons[index] = new polygon3D(v, origin.myClone(), top.myClone(), bot.myClone(), mainThread.textures[textureIndex], 1,1,1);
deltaX.set(tempVector3);
deltaX.subtract(tempVector2);
deltaZ.set(tempVector1);
deltaZ.subtract(tempVector2);
origin.set(tempVector2);
origin.add(deltaX);
origin.add(deltaZ);
origin.add(deltaX, j);
origin.add(deltaZ, i);
top.set(origin);
top.add(deltaX, -32);
bot.set(origin);
bot.add(deltaZ, -32);
v = new vector[]{tempVector1.myClone(), tempVector2.myClone(), tempVector3.myClone()};
polygons[index+1] = new polygon3D(v, origin.myClone(), top.myClone(), bot.myClone(), mainThread.textures[39], 1,1,1);
index+=2;
}
}
polygonCount = index;
for(int i = 0; i < polygonCount; i++){
polygons[i].findDiffuse();
polygons[i].parentObject = this;
}
}
//update the model
public void update(){
if(mainThread.theAssetManager.minimapBitmap[tileIndex[0]] ||
mainThread.theAssetManager.minimapBitmap[tileIndex[1]] ||
mainThread.theAssetManager.minimapBitmap[tileIndex[2]] ||
mainThread.theAssetManager.minimapBitmap[tileIndex[3]] )
isRevealed = true;
else
isRevealed = false;
if(isRevealed){
//check if gold mine has been depleted
progressStatus = 100*goldDeposite/maxDeposite;
if(progressStatus == 0 && textureIndex != 41){
textureIndex = 41;
for(int i = 0; i < polygons.length; i++)
polygons[i].myTexture = mainThread.textures[textureIndex];
}
}
//mark itself on obstacle map
mainThread.gridMap.currentObstacleMap[tileIndex[0]] = false;
mainThread.gridMap.currentObstacleMap[tileIndex[1]] = false;
mainThread.gridMap.currentObstacleMap[tileIndex[2]] = false;
mainThread.gridMap.currentObstacleMap[tileIndex[3]] = false;
//update center in camera coordinate
tempCentre.set(centre);
tempCentre.subtract(camera.position);
tempCentre.rotate_XZ(camera.XZ_angle);
tempCentre.rotate_YZ(camera.YZ_angle);
tempCentre.updateLocation();
theAssetManager = mainThread.theAssetManager;
//test if the palm tree is visible in camera point of view
if(visibleBoundary.contains(tempCentre.screenX, tempCentre.screenY)){
visible = true;
if(screenBoundary.contains(tempCentre.screenX, tempCentre.screenY))
withinViewScreen = true;
else
withinViewScreen = false;
tempshadowvertex0.set(shadowvertex0);
tempshadowvertex0.subtract(camera.position);
tempshadowvertex0.rotate_XZ(camera.XZ_angle);
tempshadowvertex0.rotate_YZ(camera.YZ_angle);
tempshadowvertex0.updateLocation();
tempshadowvertex1.set(shadowvertex1);
tempshadowvertex1.subtract(camera.position);
tempshadowvertex1.rotate_XZ(camera.XZ_angle);
tempshadowvertex1.rotate_YZ(camera.YZ_angle);
tempshadowvertex1.updateLocation();
tempshadowvertex2.set(shadowvertex2);
tempshadowvertex2.subtract(camera.position);
tempshadowvertex2.rotate_XZ(camera.XZ_angle);
tempshadowvertex2.rotate_YZ(camera.YZ_angle);
tempshadowvertex2.updateLocation();
tempshadowvertex3.set(shadowvertex3);
tempshadowvertex3.subtract(camera.position);
tempshadowvertex3.rotate_XZ(camera.XZ_angle);
tempshadowvertex3.rotate_YZ(camera.YZ_angle);
tempshadowvertex3.updateLocation();
//if the object is visible then draw it on the shadow buffer from light point of view
if(shadowBoundary1.contains(tempshadowvertex0.screenX, tempshadowvertex0.screenY) ||
shadowBoundary1.contains(tempshadowvertex1.screenX, tempshadowvertex1.screenY) ||
shadowBoundary1.contains(tempshadowvertex2.screenX, tempshadowvertex2.screenY) ||
shadowBoundary1.contains(tempshadowvertex3.screenX, tempshadowvertex3.screenY)
){
for(int i = 0; i < polygonCount; i++){
polygons[i].update_lightspace();
}
}
//add this object to visible unit list
theAssetManager.visibleUnit[theAssetManager.visibleUnitCount] = this;
theAssetManager.visibleUnitCount++;
}else{
visible = false;
}
if(visible_minimap){
tempInt = theAssetManager.unitsForMiniMap[theAssetManager.unitsForMiniMapCount];
tempInt[0] = teamNo;
tempInt[1] = boundary2D.x1/16;
tempInt[2] = 127 - boundary2D.y1/16;
tempInt[3] = 2;
tempInt[4] = 10000;
theAssetManager.unitsForMiniMapCount++;
}
}
//draw the model
public void draw(){
if(!visible)
return;
for(int i = 0; i < polygonCount; i++){
polygons[i].update();
}
for(int i = 0; i < polygonCount; i++){
polygons[i].draw();
}
}
public vector getMovement(){
return movenment;
}
}

789
entity/gunTurret.java Normal file
View File

@ -0,0 +1,789 @@
package entity;
import java.awt.Rectangle;
import core.*;
import enemyAI.enemyCommander;
//the power plant model
public class gunTurret extends solidObject{
public static int maxHP = 250;
public int countDownToDeath = 16;
public vector tempVector = new vector(0,0,0);
public vector tempVector0 = new vector(0,0,0);
public vector tempVector1 = new vector(0,0,0);
public vector tempVector2 = new vector(0,0,0);
public vector tempVector3 = new vector(0,0,0);
public int [] tileIndex = new int[1];
public int[] tempInt;
public float[] tempFloat;
public vector shadowvertex0, tempshadowvertex0,shadowvertex1, tempshadowvertex1,shadowvertex2, tempshadowvertex2,shadowvertex3, tempshadowvertex3;
//a screen space boundary which is used to test if the object is visible from camera point of view
public final static Rectangle visibleBoundary = new Rectangle(-85,-85,920, 762);
//a screen space boundary which is used to test if the entire object is within the screen
public final static Rectangle screenBoundary = new Rectangle(60,60,648, 402);
//screen space boundary which is used to test if the shadow of the object is within the screen
public final static Rectangle shadowBoundary1 = new Rectangle(0,0,768, 512);
//a screen space boundary which is used to test if the vision polygon of the object is visible.
public final static Rectangle visionBoundary = new Rectangle(0,0,1600, 2000);
//a bitmap representation of the vision of the power plant for enemy commander
public static boolean[] bitmapVisionForEnemy;
public static boolean[] bitmapVisionGainFromAttackingUnit;
//gunTurret never moves
public final static vector movenment = new vector(0,0,0);
//the oreintation of the turret
public int turretAngle;
//attack range
public float attackRange = 2f;
//the angle that the turret have rotated between current frame and previous frame
public int turretAngleDelta, accumulatedDelta;
public int turretTurnRate = 8;
public int myAttackCooldown= 25;
public int attackCoolDown;
public vector firingPosition;
//index of the tiles to check when the turret is in standby mode
public static int[] tileCheckList;
//once the turret starts attacking, it exposed itself to the enemy
public int exposedCountDown;
public baseInfo theBaseInfo;
public int attackAngle;
public int randomInt;
public gunTurret(float x, float y, float z, int teamNo){
//uncontrollable unit, but act as a big sized static collidable agent
type = 200;
myDamage = 15;
ID = globalUniqID++;
randomInt = gameData.getRandom();
if(teamNo == 0){
isRevealed = true;
theBaseInfo = mainThread.pc.theBaseInfo;
}else{
theBaseInfo = mainThread.ec.theBaseInfo;
}
theBaseInfo.numberOfGunTurret++;
currentHP = maxHP;
this.teamNo = teamNo;
currentCommand = StandBy;
if(teamNo == 0){
isRevealed = true;
}
if(tileCheckList == null){
tileCheckList = generateTileCheckList(8f);
}
if(bitmapVisionForEnemy == null){
bitmapVisionForEnemy = createBitmapVision(6);
bitmapVisionGainFromAttackingUnit = createBitmapVision(2);
}
//create 2D boundary
boundary2D = new Rect((int)(x*64) - 8, (int)(z*64) + 8, 16, 16);
boundary2D.owner = this;
int centerX = (int)(x*64);
int centerY = (int)(z*64);
tileIndex[0] = centerX/16 + (127 - centerY/16)*128;
mainThread.gridMap.tiles[tileIndex[0]][0] = this;
mainThread.gridMap.tiles[tileIndex[0]][1] = this;
mainThread.gridMap.tiles[tileIndex[0]][2] = this;
mainThread.gridMap.tiles[tileIndex[0]][3] = this;
mainThread.gridMap.tiles[tileIndex[0]][4] = this;
//init model
start = new vector(x,y,z);
iDirection = new vector(1f,0,0);
jDirection = new vector(0,1f,0);
kDirection = new vector(0,0,1f);
firingPosition = new vector(0,0,0);
//define centre of the model in world coordinate
start = new vector(x,y,z);
centre = start.myClone();
tempCentre = start.myClone();
shadowvertex0 =start.myClone();
shadowvertex0.add(-0.45f,-0.2f, -0.15f);
tempshadowvertex0 = new vector(0,0,0);
shadowvertex1 =start.myClone();
shadowvertex1.add(-0.45f,-0.2f, 0.2f);
tempshadowvertex1 = new vector(0,0,0);
shadowvertex2 =start.myClone();
shadowvertex2.add(0.2f,-0.2f, -0.15f);
tempshadowvertex2 = new vector(0,0,0);
shadowvertex3 =start.myClone();
shadowvertex3.add(0.2f,-0.2f, 0.2f);
tempshadowvertex3 = new vector(0,0,0);
turretAngle = (int)(360*Math.random());
makePolygons();
}
//create polygons
public void makePolygons(){
polygons = new polygon3D[46];
vector[] v;
//turret base
float l =0.07f;
float h = 0.07f;
v = new vector[]{put(-l,h, l), put(l,h, l), put(l,h, -l), put(-l,h, -l)};
polygons[0] = new polygon3D(v, v[0].myClone(), v[1].myClone(), v[3].myClone(), mainThread.textures[12], 0.5f, 0.5f, 1);
v = new vector[]{put(-l,h, -l), put(l,h, -l), put(l+0.04,h - 0.15f, -l-0.04), put(-l-0.04,h - 0.15f, -l-0.04)};
polygons[1] = new polygon3D(v, v[0].myClone(), v[1].myClone(), v[3].myClone(), mainThread.textures[12], 0.5f, 0.5f, 1);
v = new vector[]{put(-l-0.04,h - 0.15f, l+0.04), put(l+0.04,h - 0.15f, l+0.04), put(l,h, l), put(-l,h, l)};
polygons[2] = new polygon3D(v, v[0].myClone(), v[1].myClone(), v[3].myClone(), mainThread.textures[12], 0.5f, 0.5f, 1);
v = new vector[]{put(l,h, -l), put(l,h, l), put(l+0.04,h - 0.15f, l+0.04), put(l+0.04,h - 0.15f, -l-0.04)};
polygons[3] = new polygon3D(v, v[0].myClone(), v[1].myClone(), v[3].myClone(), mainThread.textures[12], 0.5f, 0.5f, 1);
v = new vector[]{put(-l-0.04,h - 0.15f, -l-0.04), put(-l-0.04,h - 0.15f, l+0.04), put(-l,h, l), put(-l,h, -l)};
polygons[4] = new polygon3D(v, v[0].myClone(), v[1].myClone(), v[3].myClone(), mainThread.textures[12], 0.5f, 0.5f, 1);
for(int i = 0; i < 5; i++){
polygons[i].Ambient_I-=5;
polygons[i].findDiffuse();
polygons[i].parentObject = this;
}
//turret tower
iDirection.scale(0.82f);
kDirection.scale(0.75f);
iDirection.rotate_XZ(360-turretAngle);
jDirection.rotate_XZ(360-turretAngle);
kDirection.rotate_XZ(360-turretAngle);
h = 0.11f;
vector a1 = put(-0.035, h, 0.08);
vector a2 = put(0.035, h, 0.08);
vector a3 = put(0.06, h, 0.03);
vector a4 = put(0.06, h, -0.05);
vector a5 = put(0.04, h, -0.07);
vector a6 = put(-0.04, h, -0.07);
vector a7 = put(-0.06, h, -0.05);
vector a8 = put(-0.06, h, 0.03);
int textureIndex = 66;
if(teamNo != 0)
textureIndex = 67;
v = new vector[]{a1, a2, a3, a4,a5, a6, a7, a8};
polygons[5] = new polygon3D(v, v[0].myClone(), v[1].myClone(), v[5].myClone(), mainThread.textures[textureIndex], 0.7f, 1f, 1);
iDirection.scale(1.2f);
kDirection.scale(1.2f);
vector b1 = put(-0.035, 0.07, 0.08);
vector b2 = put(0.035, 0.07, 0.08);
vector b3 = put(0.06, 0.07, 0.03);
vector b4 = put(0.06, 0.07, -0.05);
vector b5 = put(0.04, 0.07, -0.07);
vector b6 = put(-0.04, 0.07, -0.07);
vector b7 = put(-0.06, 0.07, -0.05);
vector b8 = put(-0.06, 0.07, 0.03);
v = new vector[]{a2.myClone(), a1.myClone(), b1.myClone(), b2.myClone()};
polygons[6] = new polygon3D(v, v[0].myClone(), v[1].myClone(), v[3].myClone(), mainThread.textures[textureIndex], 0.5f, 0.1f, 1);
polygons[6].shadowBias = 20000;
v = new vector[]{a1.myClone(), a8.myClone(), b8.myClone(), b1.myClone()};
polygons[7] = new polygon3D(v, v[0].myClone(), v[1].myClone(), v[2].myClone(), mainThread.textures[textureIndex], 0.5f, 0.1f, 1);
v = new vector[]{a3.myClone(), a2.myClone(), b2.myClone(), b3.myClone()};
polygons[8] = new polygon3D(v, v[0].myClone(), v[1].myClone(), v[3].myClone(), mainThread.textures[textureIndex], 0.5f, 0.1f, 1);
v = new vector[]{a4.myClone(), a3.myClone(), b3.myClone(), b4.myClone()};
polygons[9] = new polygon3D(v, v[0].myClone(), v[1].myClone(), v[3].myClone(), mainThread.textures[textureIndex], 0.5f, 0.1f, 1);
v = new vector[]{a5.myClone(), a4.myClone(), b4.myClone(), b5.myClone()};
polygons[10] = new polygon3D(v, v[0].myClone(), v[1].myClone(), v[3].myClone(), mainThread.textures[textureIndex], 0.5f, 0.1f, 1);
v = new vector[]{a6.myClone(), a5.myClone(), b5.myClone(), b6.myClone()};
polygons[11] = new polygon3D(v, v[0].myClone(), v[1].myClone(), v[3].myClone(), mainThread.textures[textureIndex], 0.5f, 0.1f, 1);
v = new vector[]{a7.myClone(), a6.myClone(), b6.myClone(), b7.myClone()};
polygons[12] = new polygon3D(v, v[0].myClone(), v[1].myClone(), v[3].myClone(), mainThread.textures[textureIndex], 0.5f, 0.1f, 1);
v = new vector[]{a8.myClone(), a7.myClone(), b7.myClone(), b8.myClone()};
polygons[13] = new polygon3D(v, v[0].myClone(), v[1].myClone(), v[3].myClone(), mainThread.textures[textureIndex], 0.5f, 0.1f, 1);
double r1 = 0.007;
double r2 = 0.01;
double theta = Math.PI/16;
for(int i = 0; i < 32; i++){
v = new vector[]{put(r2*Math.cos(i*theta), r2*Math.sin(i*theta)+0.093, 0.05),
put(r2*Math.cos((i+1)*theta), r2*Math.sin((i+1)*theta)+0.093, 0.05),
put(r1*Math.cos((i+1)*theta), r1*Math.sin((i+1)*theta)+0.093, 0.17),
put(r1*Math.cos(i*theta), r1*Math.sin(i*theta)+0.093, 0.17)
};
polygons[14 +i] = new polygon3D(v, v[0].myClone(), v[1].myClone(), v[3].myClone(), mainThread.textures[33], 10,10,1);
polygons[14 +i].Ambient_I -=15;
polygons[14 +i].reflectance -=30;
polygons[14 +i].findDiffuse();
}
}
//update the model
public void update(){
//process emerging from ground animation
if(centre.y < -0.5f){
centre.y+=0.01f;
if(centre.y > -0.5){
for(int i = 0; i < polygons.length; i++){
polygons[i].origin.y+=0.0000005;
polygons[i].rightEnd.y+=0.0000005;
polygons[i].bottomEnd.y+=0.0000005;
for(int j = 0; j < polygons[i].vertex3D.length; j++){
polygons[i].vertex3D[j].y+=0.0000005;
}
}
shadowvertex0.y+=0.0000005;
shadowvertex1.y+=0.0000005;
shadowvertex2.y+=0.0000005;
shadowvertex3.y+=0.0000005;
centre.y = -0.5f;
}else{
for(int i = 0; i < polygons.length; i++){
polygons[i].origin.y+=0.01;
polygons[i].rightEnd.y+=0.01;
polygons[i].bottomEnd.y+=0.01;
for(int j = 0; j < polygons[i].vertex3D.length; j++){
polygons[i].vertex3D[j].y+=0.01;
}
}
shadowvertex0.y+=0.01;
shadowvertex1.y+=0.01;
shadowvertex2.y+=0.01;
shadowvertex3.y+=0.01;
}
//the building is invulnerable during emerging stage
currentHP = maxHP;
}
if(underAttackCountDown > 0)
underAttackCountDown--;
//check if power plant has been destroyed
if(currentHP <= 0){
countDownToDeath--;
if(countDownToDeath == 0){
//spawn an explosion when the tank is destroyed
float[] tempFloat = theAssetManager.explosionInfo[theAssetManager.explosionCount];
tempFloat[0] = centre.x;
tempFloat[1] = centre.y + 0.15f;
tempFloat[2] = centre.z;
tempFloat[3] = 2.5f;
tempFloat[4] = 1;
tempFloat[5] = 0;
tempFloat[6] = 7;
tempFloat[7] = this.height;
theAssetManager.explosionCount++;
theAssetManager.removeObject(this);
if(teamNo == 0)
mainThread.pc.theBaseInfo.numberOfGunTurret--;
else
mainThread.ec.theBaseInfo.numberOfGunTurret--;
//removeFromGridMap();
mainThread.gridMap.tiles[tileIndex[0]][0] = null;
mainThread.gridMap.tiles[tileIndex[0]][1] = null;
mainThread.gridMap.tiles[tileIndex[0]][2] = null;
mainThread.gridMap.tiles[tileIndex[0]][3] = null;
mainThread.gridMap.tiles[tileIndex[0]][4] = null;
if(attacker.teamNo != teamNo)
attacker.experience+=20;
return;
}else{
if(mainThread.frameIndex%2==0){
float[] tempFloat = theAssetManager.explosionInfo[theAssetManager.explosionCount];
tempFloat[0] = centre.x + (float)Math.random()/4f - 0.125f;
tempFloat[1] = centre.y + 0.15f;
tempFloat[2] = centre.z + (float)Math.random()/4f - 0.125f;
tempFloat[3] = 1.5f;
tempFloat[4] = 1;
tempFloat[5] = 0;
tempFloat[6] = 6 + (gameData.getRandom()%4);
tempFloat[7] = this.height;
theAssetManager.explosionCount++;
}
return;
}
}
if(isRepairing && currentHP >0){
if(mainThread.frameIndex%5==0 && theBaseInfo.currentCredit > 0 && currentHP <maxHP){
currentHP+=1;
theBaseInfo.currentCredit--;
}
}
//process turret AI
carryOutCommands();
if(attackCoolDown > 0)
attackCoolDown--;
if(exposedCountDown > 0)
exposedCountDown --;
//mark itself on obstacle map
mainThread.gridMap.currentObstacleMap[tileIndex[0]] = false;
//update center in camera coordinate
tempCentre.set(centre);
tempCentre.subtract(camera.position);
tempCentre.rotate_XZ(camera.XZ_angle);
tempCentre.rotate_YZ(camera.YZ_angle);
tempCentre.updateLocation();
theAssetManager = mainThread.theAssetManager;
//test if the gun turret is visible in camera point of view
if(visibleBoundary.contains(tempCentre.screenX, tempCentre.screenY) && isRevealed){
visible = true;
if(screenBoundary.contains(tempCentre.screenX, tempCentre.screenY))
withinViewScreen = true;
else
withinViewScreen = false;
tempshadowvertex0.set(shadowvertex0);
tempshadowvertex0.subtract(camera.position);
tempshadowvertex0.rotate_XZ(camera.XZ_angle);
tempshadowvertex0.rotate_YZ(camera.YZ_angle);
tempshadowvertex0.updateLocation();
tempshadowvertex1.set(shadowvertex1);
tempshadowvertex1.subtract(camera.position);
tempshadowvertex1.rotate_XZ(camera.XZ_angle);
tempshadowvertex1.rotate_YZ(camera.YZ_angle);
tempshadowvertex1.updateLocation();
tempshadowvertex2.set(shadowvertex2);
tempshadowvertex2.subtract(camera.position);
tempshadowvertex2.rotate_XZ(camera.XZ_angle);
tempshadowvertex2.rotate_YZ(camera.YZ_angle);
tempshadowvertex2.updateLocation();
tempshadowvertex3.set(shadowvertex3);
tempshadowvertex3.subtract(camera.position);
tempshadowvertex3.rotate_XZ(camera.XZ_angle);
tempshadowvertex3.rotate_YZ(camera.YZ_angle);
tempshadowvertex3.updateLocation();
//if the object is visible then draw it on the shadow buffer from light point of view
if(shadowBoundary1.contains(tempshadowvertex0.screenX, tempshadowvertex0.screenY) ||
shadowBoundary1.contains(tempshadowvertex1.screenX, tempshadowvertex1.screenY) ||
shadowBoundary1.contains(tempshadowvertex2.screenX, tempshadowvertex2.screenY) ||
shadowBoundary1.contains(tempshadowvertex3.screenX, tempshadowvertex3.screenY)
){
for(int i = 0; i < polygons.length; i++){
polygons[i].update_lightspace();
}
}
//add this object to visible unit list
theAssetManager.visibleUnit[theAssetManager.visibleUnitCount] = this;
theAssetManager.visibleUnitCount++;
}else{
visible = false;
}
//create vision for enemy commander
if(teamNo == 1){
int xPos = boundary2D.x1/16 - 6 + 10;
int yPos = 127 - boundary2D.y1/16 - 6 + 10;
for(int y = 0; y < 13; y++){
for(int x = 0; x < 13; x++){
if(bitmapVisionForEnemy[x+ y*13])
enemyCommander.tempBitmap[xPos + x + (yPos+y)*148] =true;
}
}
}else if(exposedCountDown > 0){
xPos = boundary2D.x1/16 - 2 + 10;
yPos = 127 - boundary2D.y1/16 - 2 + 10;
for(int y = 0; y < 5; y++){
for(int x = 0; x < 5; x++){
if(bitmapVisionGainFromAttackingUnit[x+ y*5])
enemyCommander.tempBitmap[xPos + x + (yPos+y)*148] =true;
}
}
}
visionBoundary.x = (int)(tempCentre.screenX - 800);
visionBoundary.y = (int)(tempCentre.screenY - 1000);
visionInsideScreen = camera.screen.intersects(visionBoundary);
if(visionInsideScreen){
if(teamNo != 0){
if(exposedCountDown > 0){
tempFloat = theAssetManager.visionPolygonInfo[theAssetManager.visionPolygonCount];
tempFloat[0] = teamNo;
tempFloat[1] = centre.x;
tempFloat[2] = -0.4f;
tempFloat[3] = centre.z;
tempFloat[4] = 1;
theAssetManager.visionPolygonCount++;
}
}else{
tempFloat = theAssetManager.visionPolygonInfo[theAssetManager.visionPolygonCount];
tempFloat[0] = teamNo;
tempFloat[1] = centre.x;
tempFloat[2] = -0.4f;
tempFloat[3] = centre.z;
tempFloat[4] = 0;
theAssetManager.visionPolygonCount++;
}
}
if(theAssetManager.minimapBitmap[tileIndex[0]]){
isRevealed = true;
}
visible_minimap = isRevealed;
if(teamNo == 0 || attackStatus == isAttacking || exposedCountDown > 0 || visible_minimap){
tempInt = theAssetManager.unitsForMiniMap[theAssetManager.unitsForMiniMapCount];
tempInt[0] = teamNo;
tempInt[1] = boundary2D.x1/16;
tempInt[2] = 127 - boundary2D.y1/16;
tempInt[3] = 0;
if(teamNo == 0 && underAttackCountDown > 0)
tempInt[4] = 10001;
else{
if(exposedCountDown > 0)
tempInt[4] = exposedCountDown;
else
tempInt[4] = 10000;
}
theAssetManager.unitsForMiniMapCount++;
}
accumulatedDelta+=turretAngleDelta;
accumulatedDelta= accumulatedDelta%360;
if(visible){
//update turret polygons
for(int i = 5; i < 46; i++){
polygons[i].origin.subtract(centre);
polygons[i].origin.rotate_XZ(accumulatedDelta);
polygons[i].origin.add(centre);
polygons[i].bottomEnd.subtract(centre);
polygons[i].bottomEnd.rotate_XZ(accumulatedDelta);
polygons[i].bottomEnd.add(centre);
polygons[i].rightEnd.subtract(centre);
polygons[i].rightEnd.rotate_XZ(accumulatedDelta);
polygons[i].rightEnd.add(centre);
for(int j = 0; j < polygons[i].vertex3D.length; j++){
polygons[i].vertex3D[j].subtract(centre);
polygons[i].vertex3D[j].rotate_XZ(accumulatedDelta);
polygons[i].vertex3D[j].add(centre);
}
polygons[i].normal.rotate_XZ(accumulatedDelta);
polygons[i].findDiffuse();
}
accumulatedDelta = 0;
}
}
//process turret AI
public void carryOutCommands(){
if(targetObject != null){
destinationX = targetObject.getRealCentre().x;
destinationY = targetObject.getRealCentre().z;
distanceToDesination = (float)Math.sqrt((destinationX - centre.x) * (destinationX - centre.x) + (destinationY - centre.z) * (destinationY - centre.z));
//check if light tank has the line of sight to its target
boolean hasLineOfSightToTarget = true;
if(distanceToDesination <= attackRange){
int numberOfIterations = (int)(distanceToDesination * 8);
float dx = (destinationX - centre.x)/numberOfIterations;
float dy = (destinationY - centre.z)/numberOfIterations;
float xStart = centre.x;
float yStart = centre.z;
for(int i = 0; i < numberOfIterations; i++){
xStart+=dx;
yStart+=dy;
solidObject s = mainThread.gridMap.tiles[(int)(xStart*4) + (127 - (int)(yStart*4))*128][0];
if(s != null){
if(s.type > 100 && s .type < 200 && s != targetObject){
hasLineOfSightToTarget = false;
break;
}
}
}
}else{
hasLineOfSightToTarget = false;
}
if(targetObject.currentHP <=0 || (targetObject.isCloaked && teamNo != targetObject.teamNo)){
targetObject = null;
turretAngleDelta = 0;
return;
}
if(hasLineOfSightToTarget){
attackAngle = geometry.findAngle(centre.x, centre.z, destinationX, destinationY);
if(turretAngle != attackAngle){
turretAngleDelta = 360 - (geometry.findAngleDelta(turretAngle, attackAngle, turretTurnRate) + 360)%360;
turretAngle= (turretAngle - turretAngleDelta + 360)%360;
if(Math.abs(turretAngle - attackAngle) < 10)
fireBullet(attackAngle);
}else{
fireBullet(attackAngle);
turretAngleDelta = 0;
}
}else{
turretAngleDelta = 0;
targetObject = null;
}
}else{
//if there is no target, perform standby logic
//scan for hostile unit
if((randomInt + mainThread.frameIndex)%240 == 0){
attackAngle = (int)(Math.random()*360);
}
if(turretAngle != attackAngle){
turretAngleDelta = 360 - (geometry.findAngleDelta(turretAngle, attackAngle, 2) + 360)%360;
turretAngle= (turretAngle - turretAngleDelta + 360)%360;
}else{
turretAngleDelta = 0;
}
if((ID + mainThread.frameIndex)%4 == 0){
currentOccupiedTile = (int)(centre.x*64)/16 + (127 - (int)(centre.z*64)/16)*128;
for(int i = 0; i < tileCheckList.length; i++){
if(tileCheckList[i] != Integer.MAX_VALUE){
int index = currentOccupiedTile + tileCheckList[i];
if(index < 0 || index >= 16384)
continue;
tile = mainThread.gridMap.tiles[index];
for(int j = 0; j < 4; j++){
if(tile[j] != null){
if(tile[j].teamNo != teamNo && tile[j].teamNo != -1 && tile[j].currentHP > 0 && !tile[j].isCloaked){
targetObject = tile[j];
return;
}
}
}
}
}
}
}
}
//draw the model
public void draw(){
if(!visible)
return;
for(int i = 0; i < polygons.length; i++){
polygons[i].update();
polygons[i].draw();
}
}
public void attack(solidObject o){
if(targetObject != o){
distanceToDesination = (float)Math.sqrt((o.centre.x - centre.x) * (o.centre.x - centre.x) + (o.centre.z - centre.z) * (o.centre.z - centre.z));
//check if target is within range
if(distanceToDesination <= attackRange){
//check if there is any obstacles between target and the turret
//check if light tank has the line of sight to its target
boolean hasLineOfSightToTarget = true;
int numberOfIterations = (int)(distanceToDesination * 8);
float dx = (o.centre.x - centre.x)/numberOfIterations;
float dy = (o.centre.z - centre.z)/numberOfIterations;
float xStart = centre.x;
float yStart = centre.z;
for(int i = 0; i < numberOfIterations; i++){
xStart+=dx;
yStart+=dy;
solidObject s = mainThread.gridMap.tiles[(int)(xStart*4) + (127 - (int)(yStart*4))*128][0];
if(s != null){
if(s.type > 100 && s .type < 200 && s != o){
hasLineOfSightToTarget = false;
break;
}
}
}
if(hasLineOfSightToTarget){
targetObject = o;
}
}
}
}
public void fireBullet(int attackAngle){
if(targetObject != null && targetObject.teamNo != teamNo){
exposedCountDown = 64;
isRevealed = true;
}
int theDamage = myDamage;
if(targetObject.type == 0)
theDamage = 20;
if(attackCoolDown == 0 ){
//if there is nothing between the tank and its target
firingPosition.set(0, -0.4f, 0.18f);
firingPosition.rotate_XZ(360 - attackAngle);
firingPosition.add(centre.x, 0, centre.z);
theAssetManager.spawnBullet(attackAngle, theDamage, targetObject, firingPosition, this);
attackCoolDown = myAttackCooldown;
//spawn a mini explosion
float[] tempFloat = theAssetManager.explosionInfo[theAssetManager.explosionCount];
tempFloat[0] = firingPosition.x;
tempFloat[1] = firingPosition.y;
tempFloat[2] = firingPosition.z;
tempFloat[3] = 0.4f;
tempFloat[4] = 3;
tempFloat[5] = 0;
tempFloat[6] = 6 + (gameData.getRandom()%4);
tempFloat[7] = centre.y;
theAssetManager.explosionCount++;
}
}
public void hold(){
targetObject = null;
turretAngleDelta = 0;
}
public vector getMovement(){
return movenment;
}
}

1806
entity/harvester.java Normal file

File diff suppressed because it is too large Load Diff

1138
entity/heavyTank.java Normal file

File diff suppressed because it is too large Load Diff

307
entity/lightPole.java Normal file
View File

@ -0,0 +1,307 @@
package entity;
import java.awt.Rectangle;
import core.*;
//palmTree model
public class lightPole extends solidObject{
//the polygons of the model
public polygon3D[] polygons;
public int angle;
public int tileIndex;
public vector shadowvertex0, tempshadowvertex0,shadowvertex1, tempshadowvertex1,shadowvertex2, tempshadowvertex2,shadowvertex3, tempshadowvertex3;
//a screen space boundary which is used to test if the object is visible from camera point of view
public final static Rectangle visibleBoundary = new Rectangle(-50,-50,868, 612);
//a screen space boundary which is used to test if the entire object is within the screen
public final static Rectangle screenBoundary = new Rectangle(40,40,688, 432);
//screen space boundary which is used to test if the shadow of the object is within the screen
public final static Rectangle shadowBoundary1 = new Rectangle(0,0,768, 512);
//lightPole never moves
public final static vector movenment = new vector(0,0,0);
public boolean vanished;
public lightPole(float x, float y, float z, int angle){
//uncontrollable unit, but act as a small sized static collidable agent
ID = -1;
type = 100;
this.angle = angle;
boundary2D = new Rect((int)(x*64), (int)(z*64), 1, 1);
tileIndex = boundary2D.x1/16 + (127 - (boundary2D.y1)/16)*128;
if(tileIndex >= 0 && tileIndex < 128*128)
mainThread.gridMap.tiles[tileIndex][4] = this;
else
tileIndex = 0;
start = new vector(x,y,z);
centre = start.myClone();
tempCentre = start.myClone();
shadowvertex0 =start.myClone();
shadowvertex0.add(-0.35f,-0.2f, -0.35f);
tempshadowvertex0 = new vector(0,0,0);
shadowvertex1 =start.myClone();
shadowvertex1.add(-0.35f,-0.2f, 0);
tempshadowvertex1 = new vector(0,0,0);
shadowvertex2 =start.myClone();
shadowvertex2.add(0,-0.2f, -0.35f);
tempshadowvertex2 = new vector(0,0,0);
shadowvertex3 =start.myClone();
shadowvertex3.add(0,-0.2f, 0f);
tempshadowvertex3 = new vector(0,0,0);
//create main axis in object space
iDirection = new vector(1f,0,0);
jDirection = new vector(0,1f,0);
kDirection = new vector(0,0,1f);
boundary2D.owner = this;
currentCommand = StandBy;
makePolygons();
}
//Construct polygons for this model.
//The polygon data is hard-coded here
private void makePolygons(){
polygons = new polygon3D[57];
vector[] v;
//power tower A
float r = 0.008f;
float r1 = 0.006f;
float delta = (float)Math.PI/8;
for(int i = 0; i < 16; i++){
v = new vector[]{put(r1*Math.cos(i*delta), 0.4, r1*Math.sin(i*delta)),
put(r1*Math.cos((i+1)*delta), 0.4, r1*Math.sin((i+1)*delta)),
put(r*Math.cos((i+1)*delta), 0, r*Math.sin((i+1)*delta)),
put(r*Math.cos(i*delta), 0, r*Math.sin(i*delta))
};
polygons[i] = new polygon3D(v, v[0], v[1], v[3], mainThread.textures[25], 10f,10f,1);
}
iDirection.rotate_YZ(30);
jDirection.rotate_YZ(30);
kDirection.rotate_YZ(30);
start.z-=0.221f;
for(int i = 0; i < 16; i++){
v = new vector[]{put(r1*Math.cos(i*delta), 0.502, r1*Math.sin(i*delta)),
put(r1*Math.cos((i+1)*delta), 0.502, r1*Math.sin((i+1)*delta)),
put(r1*Math.cos((i+1)*delta), 0.449, r1*Math.sin((i+1)*delta)),
put(r1*Math.cos(i*delta), 0.449, r1*Math.sin(i*delta))
};
polygons[i+16] = new polygon3D(v, v[0], v[1], v[3], mainThread.textures[25], 10f,10f,1);
}
iDirection.rotate_YZ(30);
jDirection.rotate_YZ(30);
kDirection.rotate_YZ(30);
start.z-=0.14f;
start.y+=0.2f;
float r2 = 0.004f;
for(int i = 0; i < 16; i++){
v = new vector[]{put(r2*Math.cos(i*delta), 0.55, r2*Math.sin(i*delta)),
put(r2*Math.cos((i+1)*delta), 0.55, r2*Math.sin((i+1)*delta)),
put(r1*Math.cos((i+1)*delta), 0.45, r1*Math.sin((i+1)*delta)),
put(r1*Math.cos(i*delta), 0.45, r1*Math.sin(i*delta))
};
polygons[i+32] = new polygon3D(v, v[0], v[1], v[3], mainThread.textures[25], 10f,10f,1);
}
start.set(centre);
start.z+=0.1f;
start.y -=0.02f;
iDirection.set(1f,0,0);
jDirection.set(0,1f,0);
kDirection.set(0,0,1f);
float h = 0.5f;
float w1 = -0.01f*0.9f;
float w2 = -0.005f*0.9f;
float w3 = 0.005f*0.9f;
float w4 = 0.01f*0.9f;
float h1 = 0.04f*1f;
float h2 = 0.035f*1f;
float h3 = 0.015f*1f;
float h4 = 0.01f*1f;
float thickness = 0.01f;
v = new vector[]{put(w2,h, h1), put(w3,h,h1), put(w4,h, h2), put(w4,h, h3), put(w3,h, h4), put(w2,h, h4), put(w1,h, h3), put(w1,h, h2)};
polygons[48] = new polygon3D(v, v[0], v[1], v[3], mainThread.textures[25], 10f,10f,1);
v = new vector[]{put(w2, h, h4), put(w3, h, h4), put(w3, h-thickness, h4), put(w2, h-thickness, h4)};
polygons[49] = new polygon3D(v, v[0], v[1], v[3], mainThread.textures[25], 10f,10f,1);
v = new vector[]{put(w2, h-thickness, h1), put(w3, h-thickness, h1), put(w3, h, h1), put(w2, h, h1)};
polygons[50] = new polygon3D(v, v[0], v[1], v[3], mainThread.textures[25], 10f,10f,1);
v = new vector[]{put(w3, h, h4), put(w4, h, h3), put(w4, h-thickness, h3), put(w3, h-thickness, h4) };
polygons[51] = new polygon3D(v, v[0], v[1], v[3], mainThread.textures[25], 10f,10f,1);
v = new vector[]{put(w1, h, h3), put(w2, h, h4), put(w2, h-thickness, h4), put(w1, h-thickness, h3) };
polygons[52] = new polygon3D(v, v[0], v[1], v[3], mainThread.textures[25], 10f,10f,1);
v = new vector[]{put(w4, h, h3), put(w4, h , h2), put(w4, h-thickness , h2), put(w4, h-thickness, h3)};
polygons[53] = new polygon3D(v, v[0], v[1], v[3], mainThread.textures[25], 10f,10f,1);
v = new vector[]{put(w1, h-thickness, h3), put(w1, h-thickness , h2), put(w1, h , h2), put(w1, h, h3)};
polygons[54] = new polygon3D(v, v[0], v[1], v[3], mainThread.textures[25], 10f,10f,1);
v = new vector[]{put(w4,h,h2), put(w3, h, h1),put(w3, h-thickness, h1), put(w4,h-thickness,h2)};
polygons[55] = new polygon3D(v, v[0], v[1], v[3], mainThread.textures[25], 10f,10f,1);
v = new vector[]{put(w2, h, h1), put(w1,h,h2), put(w1,h-thickness,h2), put(w2, h-thickness, h1)};
polygons[56] = new polygon3D(v, v[0], v[1], v[3], mainThread.textures[25], 10f,10f,1);
for(int i = 0; i < polygons.length; i++){
for(int j = 0; j < polygons[i].vertex3D.length; j++){
polygons[i].vertex3D[j].subtract(centre);
polygons[i].vertex3D[j].rotate_XZ(angle);
polygons[i].vertex3D[j].add(centre);
}
polygons[i].normal.rotate_XZ(angle);
polygons[i].findDiffuse();
polygons[i].parentObject = this;
}
}
//update the model
public void update(){
if(vanished)
return;
mainThread.gridMap.currentObstacleMap[tileIndex] = false;
//update center in camera coordinate
tempCentre.set(centre);
tempCentre.subtract(camera.position);
tempCentre.rotate_XZ(camera.XZ_angle);
tempCentre.rotate_YZ(camera.YZ_angle);
tempCentre.updateLocation();
if(tempCentre.screenX > 918 || tempCentre.screenX < - 150 || tempCentre.screenY < - 150 || tempCentre.screenY > 662){
visible = false;
return;
}
//test if the light pole is visible in camera point of view
if(visibleBoundary.contains(tempCentre.screenX, tempCentre.screenY)){
visible = true;
if(screenBoundary.contains(tempCentre.screenX, tempCentre.screenY))
withinViewScreen = true;
else
withinViewScreen = false;
}else{
visible = false;
}
tempshadowvertex0.set(shadowvertex0);
tempshadowvertex0.subtract(camera.position);
tempshadowvertex0.rotate_XZ(camera.XZ_angle);
tempshadowvertex0.rotate_YZ(camera.YZ_angle);
tempshadowvertex0.updateLocation();
tempshadowvertex1.set(shadowvertex1);
tempshadowvertex1.subtract(camera.position);
tempshadowvertex1.rotate_XZ(camera.XZ_angle);
tempshadowvertex1.rotate_YZ(camera.YZ_angle);
tempshadowvertex1.updateLocation();
tempshadowvertex2.set(shadowvertex2);
tempshadowvertex2.subtract(camera.position);
tempshadowvertex2.rotate_XZ(camera.XZ_angle);
tempshadowvertex2.rotate_YZ(camera.YZ_angle);
tempshadowvertex2.updateLocation();
tempshadowvertex3.set(shadowvertex3);
tempshadowvertex3.subtract(camera.position);
tempshadowvertex3.rotate_XZ(camera.XZ_angle);
tempshadowvertex3.rotate_YZ(camera.YZ_angle);
tempshadowvertex3.updateLocation();
//if the object is visible then draw it on the shadow buffer from light point of view
if(shadowBoundary1.contains(tempshadowvertex0.screenX, tempshadowvertex0.screenY) ||
shadowBoundary1.contains(tempshadowvertex1.screenX, tempshadowvertex1.screenY) ||
shadowBoundary1.contains(tempshadowvertex2.screenX, tempshadowvertex2.screenY) ||
shadowBoundary1.contains(tempshadowvertex3.screenX, tempshadowvertex3.screenY)
){
for(int i = 0; i < polygons.length; i++){
polygons[i].update_lightspace();
}
}
}
public void vanish(){
mainThread.gridMap.tiles[tileIndex][4] = null;
mainThread.gridMap.currentObstacleMap[tileIndex] = true;
vanished = true;
}
public vector getMovement(){
return movenment;
}
//draw model
public void draw(){
if(!visible || vanished)
return;
for(int i = 0; i < polygons.length; i++){
polygons[i].update();
}
for(int i = 0; i < polygons.length; i++){
polygons[i].draw();
}
}
}

1025
entity/lightTank.java Normal file

File diff suppressed because it is too large Load Diff

951
entity/missileTurret.java Normal file
View File

@ -0,0 +1,951 @@
package entity;
import java.awt.Rectangle;
import core.*;
import enemyAI.enemyCommander;
//the power plant model
public class missileTurret extends solidObject{
public static int maxHP = 250;
public int countDownToDeath = 16;
public vector tempVector = new vector(0,0,0);
public vector tempVector0 = new vector(0,0,0);
public vector tempVector1 = new vector(0,0,0);
public vector tempVector2 = new vector(0,0,0);
public vector tempVector3 = new vector(0,0,0);
public int [] tileIndex = new int[1];
public int[] tempInt;
public float[] tempFloat;
public vector shadowvertex0, tempshadowvertex0,shadowvertex1, tempshadowvertex1,shadowvertex2, tempshadowvertex2,shadowvertex3, tempshadowvertex3;
//a screen space boundary which is used to test if the object is visible from camera point of view
public final static Rectangle visibleBoundary = new Rectangle(-85,-85,920, 762);
//a screen space boundary which is used to test if the entire object is within the screen
public final static Rectangle screenBoundary = new Rectangle(60,60,648, 402);
//screen space boundary which is used to test if the shadow of the object is within the screen
public final static Rectangle shadowBoundary1 = new Rectangle(0,0,768, 512);
//a screen space boundary which is used to test if the vision polygon of the object is visible.
public final static Rectangle visionBoundary = new Rectangle(0,0,1600, 2000);
//a bitmap representation of the vision of the power plant for enemy commander
public static boolean[] bitmapVisionForEnemy;
public static boolean[] bitmapVisionGainFromAttackingUnit;
//missile never moves
public final static vector movenment = new vector(0,0,0);
//the oreintation of the turret
public int turretAngle;
//attack range
public float attackRange = 2.4f;
//the angle that the turret have rotated between current frame and previous frame
public int turretAngleDelta, accumulatedDelta;
public int turretTurnRate = 8;
public int myAttackCooldown= 23;
public int attackCoolDown;
public vector firingPosition;
//index of the tiles to check when the turret is in standby mode
public static int[] tileCheckList;
//once the turret starts attacking, it exposed itself to the enemy
public int exposedCountDown;
public baseInfo theBaseInfo;
public boolean overCharge;
public int noOverChargeRed = 4;
public int noOverChargeGreen = 21;
public int noOverChargeBlue = 31;
public int noOverChargeRedBase = 6;
public int noOverChargeGreenBase = 12;
public int noOverChargeBlueBase = 16;
public int OverChargeRed = 30;
public int OverChargeGreen = 19;
public int OverChargeBlue = 4;
public int OverChargeRedBase = 16;
public int OverChargeGreenBase = 12;
public int OverChargeBlueBase = 6;
public int attackAngle;
public int randomInt;
public boolean attackLock;
public missileTurret(float x, float y, float z, int teamNo){
//uncontrollable unit, but act as a big sized static collidable agent
type = 199;
ID = globalUniqID++;
randomInt = gameData.getRandom();
if(teamNo == 0){
isRevealed = true;
theBaseInfo = mainThread.pc.theBaseInfo;
}else{
theBaseInfo = mainThread.ec.theBaseInfo;
}
theBaseInfo.numberOfMissileTurret++;
currentHP = maxHP;
myDamage = 30;
this.teamNo = teamNo;
currentCommand = StandBy;
if(teamNo == 0){
isRevealed = true;
}
if(tileCheckList == null){
tileCheckList = generateTileCheckList(10f);
}
if(bitmapVisionForEnemy == null){
bitmapVisionForEnemy = createBitmapVision(8);
bitmapVisionGainFromAttackingUnit = createBitmapVision(2);
}
//create 2D boundary
boundary2D = new Rect((int)(x*64) - 8, (int)(z*64) + 8, 16, 16);
boundary2D.owner = this;
int centerX = (int)(x*64);
int centerY = (int)(z*64);
tileIndex[0] = centerX/16 + (127 - centerY/16)*128;
mainThread.gridMap.tiles[tileIndex[0]][0] = this;
mainThread.gridMap.tiles[tileIndex[0]][1] = this;
mainThread.gridMap.tiles[tileIndex[0]][2] = this;
mainThread.gridMap.tiles[tileIndex[0]][3] = this;
mainThread.gridMap.tiles[tileIndex[0]][4] = this;
//init model
start = new vector(x,y,z);
iDirection = new vector(1f,0,0);
jDirection = new vector(0,1f,0);
kDirection = new vector(0,0,1f);
firingPosition = new vector(0,0,0);
//define centre of the model in world coordinate
start = new vector(x,y,z);
centre = start.myClone();
tempCentre = start.myClone();
shadowvertex0 =start.myClone();
shadowvertex0.add(-0.45f,-0.2f, -0.15f);
tempshadowvertex0 = new vector(0,0,0);
shadowvertex1 =start.myClone();
shadowvertex1.add(-0.45f,-0.2f, 0.2f);
tempshadowvertex1 = new vector(0,0,0);
shadowvertex2 =start.myClone();
shadowvertex2.add(0.2f,-0.2f, -0.15f);
tempshadowvertex2 = new vector(0,0,0);
shadowvertex3 =start.myClone();
shadowvertex3.add(0.2f,-0.2f, 0.2f);
tempshadowvertex3 = new vector(0,0,0);
makePolygons();
}
//create polygons
public void makePolygons(){
polygons = new polygon3D[94];
vector[] v;
//turret base
float l =0.07f;
float h = 0.07f;
iDirection.scale(0.65f);
kDirection.scale(0.65f);
h = 0.3f;
vector a1 = put(-0.06, h, 0.08);
vector a2 = put(0.06, h, 0.08);
vector a3 = put(0.08, h, 0.06);
vector a4 = put(0.08, h, -0.06);
vector a5 = put(0.06, h, -0.08);
vector a6 = put(-0.06, h, -0.08);
vector a7 = put(-0.08, h, -0.06);
vector a8 = put(-0.08, h, 0.06);
int textureIndex = 66;
if(teamNo != 0)
textureIndex = 67;
v = new vector[]{a1, a2, a3, a4,a5, a6, a7, a8};
polygons[0] = new polygon3D(v, v[0].myClone(), v[1].myClone(), v[5].myClone(), mainThread.textures[12], 0.7f, 1f, 1);
iDirection.scale(1.4f);
kDirection.scale(1.4f);
vector b1 = put(-0.06, 0, 0.08);
vector b2 = put(0.06, 0, 0.08);
vector b3 = put(0.08, 0, 0.06);
vector b4 = put(0.08, 0, -0.06);
vector b5 = put(0.06, 0, -0.08);
vector b6 = put(-0.06, 0, -0.08);
vector b7 = put(-0.08, 0, -0.06);
vector b8 = put(-0.08, 0, 0.06);
v = new vector[]{a2.myClone(), a1.myClone(), b1.myClone(), b2.myClone()};
polygons[1] = new polygon3D(v, v[0].myClone(), v[1].myClone(), v[3].myClone(), mainThread.textures[12], 0.5f, 1f, 1);
polygons[1].shadowBias = 20000;
v = new vector[]{a1.myClone(), a8.myClone(), b8.myClone(), b1.myClone()};
polygons[2] = new polygon3D(v, v[0].myClone(), v[1].myClone(), v[2].myClone(), mainThread.textures[12], 0.5f, 1f, 1);
v = new vector[]{a3.myClone(), a2.myClone(), b2.myClone(), b3.myClone()};
polygons[3] = new polygon3D(v, v[0].myClone(), v[1].myClone(), v[3].myClone(), mainThread.textures[12], 0.5f, 1f, 1);
v = new vector[]{a4.myClone(), a3.myClone(), b3.myClone(), b4.myClone()};
polygons[4] = new polygon3D(v, v[0].myClone(), v[1].myClone(), v[3].myClone(), mainThread.textures[12], 0.5f, 1f, 1);
v = new vector[]{a5.myClone(), a4.myClone(), b4.myClone(), b5.myClone()};
polygons[5] = new polygon3D(v, v[0].myClone(), v[1].myClone(), v[3].myClone(), mainThread.textures[12], 0.5f, 1f, 1);
v = new vector[]{a6.myClone(), a5.myClone(), b5.myClone(), b6.myClone()};
polygons[6] = new polygon3D(v, v[0].myClone(), v[1].myClone(), v[3].myClone(), mainThread.textures[12], 0.5f, 1f, 1);
v = new vector[]{a7.myClone(), a6.myClone(), b6.myClone(), b7.myClone()};
polygons[7] = new polygon3D(v, v[0].myClone(), v[1].myClone(), v[3].myClone(), mainThread.textures[12], 0.5f, 1f, 1);
v = new vector[]{a8.myClone(), a7.myClone(), b7.myClone(), b8.myClone()};
polygons[8] = new polygon3D(v, v[0].myClone(), v[1].myClone(), v[3].myClone(), mainThread.textures[12], 0.5f, 1f, 1);
float r = 0.052f;
float r2 = 0.046f;
double theta = Math.PI/16;
for(int i = 0; i < 32; i++){
v = new vector[]{
put(r2*Math.cos(i*theta), 0.3101, r2*Math.sin(i*theta)),
put(r2*Math.cos((i+1)*theta), 0.3101, r2*Math.sin((i+1)*theta)),
put(r*Math.cos((i+1)*theta), 0.3101, r*Math.sin((i+1)*theta)),
put(r*Math.cos(i*theta), 0.3101, r*Math.sin(i*theta))
};
polygons[9 +i] = new polygon3D(v, v[0].myClone(), v[1].myClone(), v[3].myClone(), mainThread.textures[26], 10,10,0);
polygons[9 +i].color = 8 << 10 | 16 << 5 | 21;
}
for(int i = 0; i < 32; i++){
v = new vector[]{put(r*Math.cos(i*theta), 0.31, r*Math.sin(i*theta)),
put(r*Math.cos((i+1)*theta), 0.31, r*Math.sin((i+1)*theta)),
put(r*Math.cos((i+1)*theta), 0.3, r*Math.sin((i+1)*theta)),
put(r*Math.cos(i*theta), 0.3, r*Math.sin(i*theta))
};
polygons[41 +i] = new polygon3D(v, v[0].myClone(), v[1].myClone(), v[3].myClone(), mainThread.textures[26], 10,10,0);
polygons[41 +i].color = 8 << 10 | 16 << 5 | 21;
}
v = new vector[32];
for(int i = 0; i < 32; i++){
v[31-i] = put(r*Math.cos(i*theta), 0.31, r*Math.sin(i*theta));
}
polygons[73] = new polygon3D(v, v[0].myClone(), v[1].myClone(), v[3].myClone(), mainThread.textures[26], 10,10,1);
polygons[73].shadowBias = 5000;
//turret tower
iDirection.rotate_XZ(360-turretAngle);
jDirection.rotate_XZ(360-turretAngle);
kDirection.rotate_XZ(360-turretAngle);
v = new vector[]{put(-0.02f, 0.4f, 0.0f), put(-0.02f, 0.4f, -0.04f), put(-0.02f, 0.31f, -0.02f), put(-0.02f, 0.31f, 0.02f)};
polygons[74] = new polygon3D(v, v[0].myClone(), v[1].myClone(), v[3].myClone(), mainThread.textures[textureIndex], 0.5f,0.5f,1);
v = new vector[]{put(0.02f, 0.31f, 0.02f), put(0.02f, 0.31f, -0.02f), put(0.02f, 0.4f, -0.04f), put(0.02f, 0.4f, 0.0f)};
polygons[75] = new polygon3D(v, v[0].myClone(), v[1].myClone(), v[3].myClone(), mainThread.textures[textureIndex], 0.5f,0.5f,1);
v = new vector[]{put(0.02f, 0.4f, 0.0f), put(-0.02f, 0.4f, 0.0f), put(-0.02f, 0.31f, 0.02f), put(0.02f, 0.31f, 0.02f)};
polygons[76] = new polygon3D(v, v[0].myClone(), v[1].myClone(), v[3].myClone(), mainThread.textures[textureIndex], 0.5f,0.5f,1);
v = new vector[]{put(0.02f, 0.31f, -0.02f), put(-0.02f, 0.31f, -0.02f), put(-0.02f, 0.4f, -0.04f), put(0.02f, 0.4f, -0.04f)};
polygons[77] = new polygon3D(v, v[0].myClone(), v[1].myClone(), v[3].myClone(), mainThread.textures[textureIndex], 0.5f,0.5f,1);
v = new vector[]{put(-0.02f, 0.4f, 0.0f), put(0.02f, 0.4f, 0.0f), put(0.02f, 0.4f, -0.04f), put(-0.02f, 0.4f, -0.04f)};
polygons[78] = new polygon3D(v, v[0].myClone(), v[1].myClone(), v[3].myClone(), mainThread.textures[textureIndex], 0.5f,0.5f,1);
v = new vector[]{put(-0.07f, 0.41f, 0.09f), put(-0.04f, 0.41f, 0.09f), put(-0.04f, 0.41f, -0.07f), put(-0.07f, 0.41f, -0.07f)};
polygons[79] = new polygon3D(v, v[0].myClone(), v[1].myClone(), v[3].myClone(), mainThread.textures[33], 0.5f,0.5f,1);
v = new vector[]{put(-0.07f, 0.41f, 0.09f), put(-0.07f, 0.41f, -0.07f), put(-0.075f, 0.405f, -0.07f), put(-0.075f, 0.405f, 0.09f)};
polygons[80] = new polygon3D(v, v[0].myClone(), v[1].myClone(), v[3].myClone(), mainThread.textures[33], 0.5f,0.5f,1);
v = new vector[]{ put(-0.035f, 0.405f, 0.09f), put(-0.035f, 0.405f, -0.07f), put(-0.04f, 0.41f, -0.07f),put(-0.04f, 0.41f, 0.09f)};
polygons[81] = new polygon3D(v, v[0].myClone(), v[1].myClone(), v[3].myClone(), mainThread.textures[33], 0.5f,0.5f,1);
v = new vector[]{put(-0.075f, 0.405f, 0.09f), put(-0.075f, 0.405f, -0.07f), put(-0.075f, 0.37f, -0.07f), put(-0.075f, 0.37f, 0.09f)};
polygons[82] = new polygon3D(v, v[0].myClone(), v[1].myClone(), v[3].myClone(), mainThread.textures[33], 0.5f,0.5f,1);
v = new vector[]{put(-0.035f, 0.37f, 0.09f), put(-0.035f, 0.37f, -0.07f), put(-0.035f, 0.405f, -0.07f), put(-0.035f, 0.405f, 0.09f)};
polygons[83] = new polygon3D(v, v[0].myClone(), v[1].myClone(), v[3].myClone(), mainThread.textures[33], 0.5f,0.5f,1);
v = new vector[]{put(-0.04f, 0.41f, 0.09f), put(-0.07f, 0.41f, 0.09f), put(-0.075f, 0.405f, 0.09f), put(-0.075f, 0.37f, 0.09f), put(-0.07f, 0.365f, 0.09f), put(-0.04f, 0.365f, 0.09f), put(-0.035f, 0.37f, 0.09f), put(-0.035f, 0.405f, 0.09f) };
polygons[84] = new polygon3D(v, v[0].myClone(), v[1].myClone(), v[3].myClone(), mainThread.textures[33], 0.5f,0.5f,1);
v = new vector[]{put(-0.042f, 0.401f, 0.091f), put(-0.067f, 0.401f, 0.091f), put(-0.067f, 0.375f, 0.091f), put(-0.042f, 0.375f, 0.091f) };
polygons[85] = new polygon3D(v, v[0].myClone(), v[1].myClone(), v[3].myClone(), mainThread.textures[68], 0.5f,0.5f,1);
polygons[85].Ambient_I+=20;
v = new vector[]{put(-0.035f, 0.405f, -0.07f), put(-0.035f, 0.37f, -0.07f), put(-0.04f, 0.365f, -0.07f), put(-0.07f, 0.365f, -0.07f), put(-0.075f, 0.37f, -0.07f), put(-0.075f, 0.405f, -0.07f), put(-0.07f, 0.41f, -0.07f), put(-0.04f, 0.41f, -0.07f)};
polygons[86] = new polygon3D(v, v[0].myClone(), v[1].myClone(), v[3].myClone(), mainThread.textures[33], 0.5f,0.5f,1);
jDirection.scale(1.5f);
iDirection.scale(1.6f);
kDirection.scale(0.3f);
start.y-=0.19;
start.x+=0.032;
start.z-=0.02;
v = new vector[]{put(-0.07f, 0.41f, 0.09f), put(-0.04f, 0.41f, 0.09f), put(-0.04f, 0.41f, -0.07f), put(-0.07f, 0.41f, -0.07f)};
polygons[87] = new polygon3D(v, v[0].myClone(), v[1].myClone(), v[3].myClone(), mainThread.textures[textureIndex], 0.5f,0.5f,1);
v = new vector[]{put(-0.07f, 0.41f, 0.09f), put(-0.07f, 0.41f, -0.07f), put(-0.075f, 0.405f, -0.07f), put(-0.075f, 0.405f, 0.09f)};
polygons[88] = new polygon3D(v, v[0].myClone(), v[1].myClone(), v[3].myClone(), mainThread.textures[textureIndex], 0.5f,0.5f,1);
v = new vector[]{ put(-0.035f, 0.405f, 0.09f), put(-0.035f, 0.405f, -0.07f), put(-0.04f, 0.41f, -0.07f),put(-0.04f, 0.41f, 0.09f)};
polygons[89] = new polygon3D(v, v[0].myClone(), v[1].myClone(), v[3].myClone(), mainThread.textures[textureIndex], 0.5f,0.5f,1);
v = new vector[]{put(-0.075f, 0.405f, 0.09f), put(-0.075f, 0.405f, -0.07f), put(-0.075f, 0.37f, -0.07f), put(-0.075f, 0.37f, 0.09f)};
polygons[90] = new polygon3D(v, v[0].myClone(), v[1].myClone(), v[3].myClone(), mainThread.textures[textureIndex], 0.5f,0.5f,1);
v = new vector[]{put(-0.035f, 0.37f, 0.09f), put(-0.035f, 0.37f, -0.07f), put(-0.035f, 0.405f, -0.07f), put(-0.035f, 0.405f, 0.09f)};
polygons[91] = new polygon3D(v, v[0].myClone(), v[1].myClone(), v[3].myClone(), mainThread.textures[textureIndex], 0.5f,0.5f,1);
v = new vector[]{put(-0.04f, 0.41f, 0.09f), put(-0.07f, 0.41f, 0.09f), put(-0.075f, 0.405f, 0.09f), put(-0.075f, 0.37f, 0.09f), put(-0.07f, 0.365f, 0.09f), put(-0.04f, 0.365f, 0.09f), put(-0.035f, 0.37f, 0.09f), put(-0.035f, 0.405f, 0.09f) };
polygons[92] = new polygon3D(v, v[0].myClone(), v[1].myClone(), v[3].myClone(), mainThread.textures[textureIndex], 0.5f,0.5f,1);
v = new vector[]{put(-0.035f, 0.405f, -0.07f), put(-0.035f, 0.37f, -0.07f), put(-0.04f, 0.365f, -0.07f), put(-0.07f, 0.365f, -0.07f), put(-0.075f, 0.37f, -0.07f), put(-0.075f, 0.405f, -0.07f), put(-0.07f, 0.41f, -0.07f), put(-0.04f, 0.41f, -0.07f)};
polygons[93] = new polygon3D(v, v[0].myClone(), v[1].myClone(), v[3].myClone(), mainThread.textures[textureIndex], 0.5f,0.5f,1);
jDirection.scale(1f/1.5f);
iDirection.scale(1f/1.6f);
kDirection.scale(1f/0.3f);
start.y+=0.19;
start.x-=0.032;
start.z+=0.02;
}
//update the model
public void update(){
theAssetManager = mainThread.theAssetManager;
//process emerging from ground animation
if(centre.y < -0.5f){
centre.y+=0.01f;
if(centre.y > -0.5){
for(int i = 0; i < polygons.length; i++){
polygons[i].origin.y+=0.0000005;
polygons[i].rightEnd.y+=0.0000005;
polygons[i].bottomEnd.y+=0.0000005;
for(int j = 0; j < polygons[i].vertex3D.length; j++){
polygons[i].vertex3D[j].y+=0.0000005;
}
}
shadowvertex0.y+=0.0000005;
shadowvertex1.y+=0.0000005;
shadowvertex2.y+=0.0000005;
shadowvertex3.y+=0.0000005;
centre.y = -0.5f;
}else{
for(int i = 0; i < polygons.length; i++){
polygons[i].origin.y+=0.01;
polygons[i].rightEnd.y+=0.01;
polygons[i].bottomEnd.y+=0.01;
for(int j = 0; j < polygons[i].vertex3D.length; j++){
polygons[i].vertex3D[j].y+=0.01;
}
}
shadowvertex0.y+=0.01;
shadowvertex1.y+=0.01;
shadowvertex2.y+=0.01;
shadowvertex3.y+=0.01;
}
//the building is invulnerable during emerging stage
currentHP = maxHP;
}
if(underAttackCountDown > 0)
underAttackCountDown--;
//check if power plant has been destroyed
if(currentHP <= 0){
countDownToDeath--;
if(countDownToDeath == 0){
//spawn an explosion when the tank is destroyed
float[] tempFloat = theAssetManager.explosionInfo[theAssetManager.explosionCount];
tempFloat[0] = centre.x;
tempFloat[1] = centre.y + 0.15f;
tempFloat[2] = centre.z;
tempFloat[3] = 2.5f;
tempFloat[4] = 1;
tempFloat[5] = 0;
tempFloat[6] = 7;
tempFloat[7] = this.height;
theAssetManager.explosionCount++;
theAssetManager.removeObject(this);
theBaseInfo.numberOfMissileTurret--;
if(overCharge)
theBaseInfo.numberOfOverChargedMissileTurret--;
//removeFromGridMap();
mainThread.gridMap.tiles[tileIndex[0]][0] = null;
mainThread.gridMap.tiles[tileIndex[0]][1] = null;
mainThread.gridMap.tiles[tileIndex[0]][2] = null;
mainThread.gridMap.tiles[tileIndex[0]][3] = null;
mainThread.gridMap.tiles[tileIndex[0]][4] = null;
if(attacker.teamNo != teamNo)
attacker.experience+=35;
return;
}else{
if(mainThread.frameIndex%2==0){
float[] tempFloat = theAssetManager.explosionInfo[theAssetManager.explosionCount];
tempFloat[0] = centre.x + (float)Math.random()/4f - 0.125f;
tempFloat[1] = centre.y + 0.15f;
tempFloat[2] = centre.z + (float)Math.random()/4f - 0.125f;
tempFloat[3] = 1.5f;
tempFloat[4] = 1;
tempFloat[5] = 0;
tempFloat[6] = 6 + (gameData.getRandom()%4);
tempFloat[7] = this.height;
theAssetManager.explosionCount++;
}
return;
}
}
if(isRepairing && currentHP >0){
if(mainThread.frameIndex%5==0 && theBaseInfo.currentCredit > 0 && currentHP <maxHP){
currentHP+=1;
theBaseInfo.currentCredit--;
}
}
//process turret AI
carryOutCommands();
if(attackCoolDown > 0)
attackCoolDown--;
if(exposedCountDown > 0)
exposedCountDown --;
if(overCharge)
myAttackCooldown = 10;
//mark itself on obstacle map
mainThread.gridMap.currentObstacleMap[tileIndex[0]] = false;
//update center in camera coordinate
tempCentre.set(centre);
tempCentre.y+=0.4f;
tempCentre.subtract(camera.position);
tempCentre.rotate_XZ(camera.XZ_angle);
tempCentre.rotate_YZ(camera.YZ_angle);
tempCentre.updateLocation();
screenX_gui = (int)tempCentre.screenX;
screenY_gui = (int)tempCentre.screenY;
tempCentre.set(centre);
tempCentre.y+=0.1f;
tempCentre.subtract(camera.position);
tempCentre.rotate_XZ(camera.XZ_angle);
tempCentre.rotate_YZ(camera.YZ_angle);
tempCentre.updateLocation();
//test if the gun turret is visible in camera point of view
if(visibleBoundary.contains(tempCentre.screenX, tempCentre.screenY) && isRevealed){
visible = true;
if(screenBoundary.contains(tempCentre.screenX, tempCentre.screenY))
withinViewScreen = true;
else
withinViewScreen = false;
tempshadowvertex0.set(shadowvertex0);
tempshadowvertex0.subtract(camera.position);
tempshadowvertex0.rotate_XZ(camera.XZ_angle);
tempshadowvertex0.rotate_YZ(camera.YZ_angle);
tempshadowvertex0.updateLocation();
tempshadowvertex1.set(shadowvertex1);
tempshadowvertex1.subtract(camera.position);
tempshadowvertex1.rotate_XZ(camera.XZ_angle);
tempshadowvertex1.rotate_YZ(camera.YZ_angle);
tempshadowvertex1.updateLocation();
tempshadowvertex2.set(shadowvertex2);
tempshadowvertex2.subtract(camera.position);
tempshadowvertex2.rotate_XZ(camera.XZ_angle);
tempshadowvertex2.rotate_YZ(camera.YZ_angle);
tempshadowvertex2.updateLocation();
tempshadowvertex3.set(shadowvertex3);
tempshadowvertex3.subtract(camera.position);
tempshadowvertex3.rotate_XZ(camera.XZ_angle);
tempshadowvertex3.rotate_YZ(camera.YZ_angle);
tempshadowvertex3.updateLocation();
//if the object is visible then draw it on the shadow buffer from light point of view
if(shadowBoundary1.contains(tempshadowvertex0.screenX, tempshadowvertex0.screenY) ||
shadowBoundary1.contains(tempshadowvertex1.screenX, tempshadowvertex1.screenY) ||
shadowBoundary1.contains(tempshadowvertex2.screenX, tempshadowvertex2.screenY) ||
shadowBoundary1.contains(tempshadowvertex3.screenX, tempshadowvertex3.screenY)
){
for(int i = 0; i < polygons.length; i++){
polygons[i].update_lightspace();
}
}
//add this object to visible unit list
theAssetManager.visibleUnit[theAssetManager.visibleUnitCount] = this;
theAssetManager.visibleUnitCount++;
}else{
visible = false;
}
//create vision for enemy commander
if(teamNo == 1){
int xPos = boundary2D.x1/16 - 6 + 10;
int yPos = 127 - boundary2D.y1/16 - 6 + 10;
for(int y = 0; y < 17; y++){
for(int x = 0; x < 17; x++){
if(bitmapVisionForEnemy[x+ y*17])
enemyCommander.tempBitmap[xPos + x + (yPos+y)*148] =true;
}
}
}else if(exposedCountDown > 0){
xPos = boundary2D.x1/16 - 2 + 10;
yPos = 127 - boundary2D.y1/16 - 2 + 10;
for(int y = 0; y < 5; y++){
for(int x = 0; x < 5; x++){
if(bitmapVisionGainFromAttackingUnit[x+ y*5])
enemyCommander.tempBitmap[xPos + x + (yPos+y)*148] =true;
}
}
}
visionBoundary.x = (int)(tempCentre.screenX - 800);
visionBoundary.y = (int)(tempCentre.screenY - 1000);
visionInsideScreen = camera.screen.intersects(visionBoundary);
if(visionInsideScreen){
if(teamNo != 0){
if(exposedCountDown > 0){
tempFloat = theAssetManager.visionPolygonInfo[theAssetManager.visionPolygonCount];
tempFloat[0] = teamNo;
tempFloat[1] = centre.x;
tempFloat[2] = -0.4f;
tempFloat[3] = centre.z;
tempFloat[4] = 1;
theAssetManager.visionPolygonCount++;
}
}else{
tempFloat = theAssetManager.visionPolygonInfo[theAssetManager.visionPolygonCount];
tempFloat[0] = teamNo;
tempFloat[1] = centre.x;
tempFloat[2] = -0.4f;
tempFloat[3] = centre.z;
tempFloat[4] = 2;
theAssetManager.visionPolygonCount++;
}
}
if(theAssetManager.minimapBitmap[tileIndex[0]]){
isRevealed = true;
}
visible_minimap = isRevealed;
if(teamNo == 0 || attackStatus == isAttacking || exposedCountDown > 0 || visible_minimap){
tempInt = theAssetManager.unitsForMiniMap[theAssetManager.unitsForMiniMapCount];
tempInt[0] = teamNo;
tempInt[1] = boundary2D.x1/16;
tempInt[2] = 127 - boundary2D.y1/16;
tempInt[3] = 2;
if(teamNo == 0 && underAttackCountDown > 0)
tempInt[4] = 10001;
else{
if(exposedCountDown > 0)
tempInt[4] = exposedCountDown;
else
tempInt[4] = 10000;
}
theAssetManager.unitsForMiniMapCount++;
}
accumulatedDelta+=turretAngleDelta;
accumulatedDelta= accumulatedDelta%360;
if(visible){
if(!overCharge){
float ratio = ((float)Math.sin((float)(mainThread.frameIndex + ID)/10) + 1)/2;
if(theBaseInfo.lowPower)
ratio = 0;
int color = (int)(noOverChargeRedBase + ratio * (noOverChargeRed - noOverChargeRedBase)) << 10 | (int)(noOverChargeGreenBase + ratio * (noOverChargeGreen - noOverChargeGreenBase)) << 5 | (int)(noOverChargeBlueBase + ratio * (noOverChargeBlue - noOverChargeBlueBase));
for(int i = 9; i < 73; i++){
polygons[i].color = color;
polygons[i].diffuse_I = 100;
}
}else{
float ratio = ((float)Math.sin((float)(mainThread.frameIndex + ID)/10) + 1)/2;
if(theBaseInfo.lowPower)
ratio = 0;
int color = (int)(OverChargeRedBase + ratio * (OverChargeRed - OverChargeRedBase)) << 10 | (int)(OverChargeGreenBase + ratio * (OverChargeGreen - OverChargeGreenBase)) << 5 | (int)(OverChargeBlueBase + ratio * (OverChargeBlue - OverChargeBlueBase));
for(int i = 9; i < 73; i++){
polygons[i].color = color;
polygons[i].diffuse_I = 100;
}
}
//update turret polygons
for(int i = 74; i < polygons.length; i++){
polygons[i].origin.subtract(centre);
polygons[i].origin.rotate_XZ(accumulatedDelta);
polygons[i].origin.add(centre);
polygons[i].bottomEnd.subtract(centre);
polygons[i].bottomEnd.rotate_XZ(accumulatedDelta);
polygons[i].bottomEnd.add(centre);
polygons[i].rightEnd.subtract(centre);
polygons[i].rightEnd.rotate_XZ(accumulatedDelta);
polygons[i].rightEnd.add(centre);
for(int j = 0; j < polygons[i].vertex3D.length; j++){
polygons[i].vertex3D[j].subtract(centre);
polygons[i].vertex3D[j].rotate_XZ(accumulatedDelta);
polygons[i].vertex3D[j].add(centre);
}
polygons[i].normal.rotate_XZ(accumulatedDelta);
polygons[i].findDiffuse();
}
accumulatedDelta = 0;
}
}
//process turret AI
public void carryOutCommands(){
if(theBaseInfo.lowPower){
targetObject = null;
turretAngleDelta = 0;
return;
}
if(targetObject != null){
//target enemy military unit first
if((targetObject.type > 100 ||targetObject.type <199) && !attackLock && (randomInt + mainThread.frameIndex)%4 == 2){
currentOccupiedTile = (int)(centre.x*64)/16 + (127 - (int)(centre.z*64)/16)*128;
for(int i = 0; i < tileCheckList.length; i++){
if(tileCheckList[i] != Integer.MAX_VALUE){
int index = currentOccupiedTile + tileCheckList[i];
if(index < 0 || index >= 16384)
continue;
tile = mainThread.gridMap.tiles[index];
for(int j = 0; j < 4; j++){
if(tile[j] != null){
if(tile[j].teamNo != teamNo && tile[j].teamNo != -1 && tile[j].currentHP > 0 && !tile[j].isCloaked){
destinationX = tile[j].getRealCentre().x;
destinationY = tile[j].getRealCentre().z;
distanceToDesination = (float)Math.sqrt((destinationX - centre.x) * (destinationX - centre.x) + (destinationY - centre.z) * (destinationY - centre.z));
if(distanceToDesination <= attackRange){
if(tile[j].type < 100 || tile[j].type >= 199){
targetObject = tile[j];
break;
}
}
}
}
}
if(targetObject.type < 100 || targetObject.type >= 199)
break;
}
}
}
destinationX = targetObject.getRealCentre().x;
destinationY = targetObject.getRealCentre().z;
distanceToDesination = (float)Math.sqrt((destinationX - centre.x) * (destinationX - centre.x) + (destinationY - centre.z) * (destinationY - centre.z));
if(targetObject.currentHP <=0 || (targetObject.isCloaked && teamNo != targetObject.teamNo) || distanceToDesination > attackRange){
targetObject = null;
turretAngleDelta = 0;
attackLock = false;
return;
}
attackAngle = geometry.findAngle(centre.x, centre.z, destinationX, destinationY);
if(turretAngle != attackAngle){
turretAngleDelta = 360 - (geometry.findAngleDelta(turretAngle, attackAngle, turretTurnRate) + 360)%360;
turretAngle= (turretAngle - turretAngleDelta + 360)%360;
if(Math.abs(turretAngle - attackAngle) < 10)
fireRocket(attackAngle);
}else{
fireRocket(attackAngle);
turretAngleDelta = 0;
}
}else{
//if there is no target, perform standby logic
//scan for hostile unit
boolean[] bitmapVision;
if(teamNo == 0)
bitmapVision = mainThread.theAssetManager.minimapBitmap;
else
bitmapVision = enemyCommander.visionMap;
attackLock = false;
if((randomInt + mainThread.frameIndex)%240 == 0){
attackAngle = (int)(Math.random()*360);
}
if(turretAngle != attackAngle){
turretAngleDelta = 360 - (geometry.findAngleDelta(turretAngle, attackAngle, 2) + 360)%360;
turretAngle= (turretAngle - turretAngleDelta + 360)%360;
}else{
turretAngleDelta = 0;
}
if((ID + mainThread.frameIndex)%4 == 0){
currentOccupiedTile = (int)(centre.x*64)/16 + (127 - (int)(centre.z*64)/16)*128;
for(int i = 0; i < tileCheckList.length; i++){
if(tileCheckList[i] != Integer.MAX_VALUE){
int index = currentOccupiedTile + tileCheckList[i];
if(index < 0 || index >= 16384)
continue;
tile = mainThread.gridMap.tiles[index];
if(!bitmapVision[index]){
boolean isRevealedBuilding = false;
if(tile[4] != null)
if(tile[4].type > 100)
if(tile[4].isRevealed == true)
isRevealedBuilding = true;
if(!isRevealedBuilding)
continue;
}
for(int j = 0; j < 4; j++){
if(tile[j] != null){
if(tile[j].teamNo != teamNo && tile[j].teamNo != -1 && tile[j].currentHP > 0 && !tile[j].isCloaked){
destinationX = tile[j].getRealCentre().x;
destinationY = tile[j].getRealCentre().z;
distanceToDesination = (float)Math.sqrt((destinationX - centre.x) * (destinationX - centre.x) + (destinationY - centre.z) * (destinationY - centre.z));
if(distanceToDesination <= attackRange){
targetObject = tile[j];
if(targetObject.type < 100 || targetObject.type >= 199)
return;
}
}
}
}
}
}
}
}
}
//draw the model
public void draw(){
if(!visible)
return;
for(int i = 0; i < polygons.length; i++){
polygons[i].update();
polygons[i].draw();
}
}
public void attack(solidObject o){
if(targetObject != o){
distanceToDesination = (float)Math.sqrt((o.centre.x - centre.x) * (o.centre.x - centre.x) + (o.centre.z - centre.z) * (o.centre.z - centre.z));
//check if target is within range
if(distanceToDesination <= attackRange){
targetObject = o;
attackLock = true;
}
}
}
public void fireRocket(int attackAngle){
if(targetObject != null && targetObject.teamNo != teamNo){
exposedCountDown = 64;
isRevealed = true;
}
tempVector.set(centre);
if(attackCoolDown == 0 ){
firingPosition.set(-0.05f, -0.1f, 0.14f);
firingPosition.rotate_XZ(360 - attackAngle);
firingPosition.add(tempVector.x, 0, tempVector.z);
theAssetManager.spawnRocket(attackAngle, myDamage, targetObject, firingPosition, this);
attackCoolDown = myAttackCooldown;
//spawn a mini explosion
firingPosition.set(-0.05f, -0.1f, 0.13f);
firingPosition.rotate_XZ(360 - attackAngle);
firingPosition.add(tempVector.x, 0, tempVector.z);
float[] tempFloat = theAssetManager.explosionInfo[theAssetManager.explosionCount];
tempFloat[0] = firingPosition.x;
tempFloat[1] = firingPosition.y;
tempFloat[2] = firingPosition.z;
tempFloat[3] = 0.5f;
tempFloat[4] = 2;
tempFloat[5] = 0;
tempFloat[6] = 6 + (gameData.getRandom()%4);
tempFloat[7] = centre.y;
theAssetManager.explosionCount++;
}
}
public void hold(){
targetObject = null;
turretAngleDelta = 0;
}
public vector getMovement(){
return movenment;
}
}

347
entity/palmTree.java Normal file
View File

@ -0,0 +1,347 @@
package entity;
import java.awt.Rectangle;
import core.*;
//palmTree model
public class palmTree extends solidObject{
//the polygons of the model
public polygon3D[] polygons;
public int angle;
public int tileIndex;
public vector shadowvertex0, tempshadowvertex0,shadowvertex1, tempshadowvertex1,shadowvertex2, tempshadowvertex2,shadowvertex3, tempshadowvertex3;
//a screen space boundary which is used to test if the object is visible from camera point of view
public final static Rectangle visibleBoundary = new Rectangle(-50,-50,868, 612);
//a screen space boundary which is used to test if the entire object is within the screen
public final static Rectangle screenBoundary = new Rectangle(40,40,688, 432);
//screen space boundary which is used to test if the shadow of the object is within the screen
public final static Rectangle shadowBoundary1 = new Rectangle(-20, -20,808, 552);
//palmTrees never moves
public final static vector movenment = new vector(0,0,0);
//angles between leave branch
public static int[] angles = new int[5];
public palmTree(float x, float y, float z){
//uncontrollable unit, but act as a small sized static collidable agent
ID = -1;
type = 100;
boundary2D = new Rect((int)(x*64), (int)(z*64), 1, 1);
tileIndex = boundary2D.x1/16 + (127 - (boundary2D.y1)/16)*128;
if(tileIndex >= 0 && tileIndex < 128*128)
mainThread.gridMap.tiles[tileIndex][4] = this;
else
tileIndex = 0;
this.angle = (int)(360*Math.random());
x = x+0.05f - (float)(Math.random()/10);
y = y+0.05f - (float)(Math.random()/10);
z = z+0.05f - (float)(Math.random()/10);
start = new vector(x,y,z);
centre = start.myClone();
tempCentre = start.myClone();
shadowvertex0 =start.myClone();
shadowvertex0.add(-0.35f,-0.2f, -0.35f);
tempshadowvertex0 = new vector(0,0,0);
shadowvertex1 =start.myClone();
shadowvertex1.add(-0.35f,-0.2f, 0);
tempshadowvertex1 = new vector(0,0,0);
shadowvertex2 =start.myClone();
shadowvertex2.add(0,-0.2f, -0.35f);
tempshadowvertex2 = new vector(0,0,0);
shadowvertex3 =start.myClone();
shadowvertex3.add(0,-0.2f, 0f);
tempshadowvertex3 = new vector(0,0,0);
float scale_i = (float)(Math.random() * 0.3) - 0.15f;
float scale_j = (float)(Math.random() * 0.3) - 0.15f;
float scale_k = (float)(Math.random() * 0.3) - 0.15f;
float scale_j_x = (float)(Math.random() * 0.3) - 0.15f;
float scale_j_y = (float)(Math.random() * 0.3) - 0.15f;
iDirection = new vector(0.7f+0.3f*1.1f + scale_i,0,0);
jDirection = new vector(scale_j_x,(1.1f+0.3f) + scale_j ,scale_j_y);
kDirection = new vector(0,0,0.7f+0.3f*1.1f + scale_k);
//adjust orientation of the model
iDirection.rotate_XZ(angle);
kDirection.rotate_XZ(angle);
int color = 110 << 16 | 205 << 8 | 10;
postProcessingThread.theMiniMap.background[tileIndex] = color;
postProcessingThread.theMiniMap.background[tileIndex + 1] = color;
postProcessingThread.theMiniMap.background[tileIndex + 128] = color;
postProcessingThread.theMiniMap.background[tileIndex + 129] = color;
boundary2D.owner = this;
currentCommand = StandBy;
angles[0] = 0;
makePolygons();
}
public palmTree(float x, float y, float z, float scale_i, float scale_j, float scale_k, float scale_j_x, float scale_j_y, int angle, int angle1, int angle2, int angle3, int angle4, int angle5){
//uncontrollable unit, but act as a small sized static collidable agent
type = 100;
boundary2D = new Rect((int)(x*64), (int)(z*64), 1, 1);
tileIndex = boundary2D.x1/16 + (127 - (boundary2D.y1)/16)*128;
mainThread.gridMap.tiles[tileIndex][4] = this;
start = new vector(x,y,z);
centre = start.myClone();
tempCentre = start.myClone();
shadowvertex0 =start.myClone();
shadowvertex0.add(-0.75f,-0.2f, -0.95f);
tempshadowvertex0 = new vector(0,0,0);
shadowvertex1 =start.myClone();
shadowvertex1.add(-0.75f,-0.2f, 0);
tempshadowvertex1 = new vector(0,0,0);
shadowvertex2 =start.myClone();
shadowvertex2.add(0,-0.2f, -0.95f);
tempshadowvertex2 = new vector(0,0,0);
shadowvertex3 =start.myClone();
shadowvertex3.add(0,-0.2f, 0f);
tempshadowvertex3 = new vector(0,0,0);
iDirection = new vector(0.7f+0.3f*1.1f + scale_i,0,0);
jDirection = new vector(scale_j_x,(1.1f+0.3f) + scale_j ,scale_j_y);
kDirection = new vector(0,0,0.7f+0.3f*1.1f + scale_k);
iDirection.rotate_XZ(angle);
kDirection.rotate_XZ(angle);
int color = 110 << 16 | 205 << 8 | 10;
postProcessingThread.theMiniMap.background[tileIndex] = color;
postProcessingThread.theMiniMap.background[tileIndex + 1] = color;
postProcessingThread.theMiniMap.background[tileIndex + 128] = color;
postProcessingThread.theMiniMap.background[tileIndex + 129] = color;
boundary2D.owner = this;
currentCommand = StandBy;
angles[0] = angle1;
angles[1] = angle2;
angles[2] = angle3;
angles[3] = angle4;
angles[4] = angle5;
makePolygons();
}
//Construct polygons for this model.
//The polygon data is hard-coded here
private void makePolygons(){
vector[] v;
start.add(0,-0.25f,0);
polygons = new polygon3D[8 + 5*6];
if(angles[0] ==0){
for(int i = 0; i < 5; i++){
angles[i] = 72*(i+1) + 15 - (int)(30*Math.random());
}
}
//body
v = new vector[]{put(-0.001, 0.1, -0.01), put(0.016, 0.1, -0.01), put(0.01, 0, -0.01), put(-0.014, 0, -0.01)};
polygons[0] = new polygon3D(v, v[0], v[1], v [3], mainThread.textures[4], 0.1f,0.5f,1);
v = new vector[]{put(-0.001, 0.1, 0.01), put(-0.001, 0.1, -0.01), put(-0.014, 0, -0.01), put(-0.014, 0, 0.014)};
polygons[1] = new polygon3D(v, v[0], v[1], v [3], mainThread.textures[4], 0.1f,0.5f,1);
v = new vector[]{put(0.016, 0.1, 0.01), put(-0.001, 0.1, 0.01), put(-0.014, 0, 0.014), put(0.01, 0, 0.014)};
polygons[2] = new polygon3D(v, v[0], v[1], v [3], mainThread.textures[4], 0.1f,0.5f,1);
v = new vector[]{put(0.016, 0.1, -0.01), put(0.016, 0.1, 0.01), put(0.01, 0, 0.014), put(0.01, 0, -0.01)};
polygons[3] = new polygon3D(v, v[0], v[1], v [3], mainThread.textures[4], 0.1f,0.5f,1);
v = new vector[]{put(0.002, 0.3, -0.008), put(0.013, 0.3, -0.008), put(0.016, 0.1, -0.01), put(-0.001, 0.1, -0.01)};
polygons[4] = new polygon3D(v, v[0], v[1], v [3], mainThread.textures[4], 0.1f,0.5f,1);
v = new vector[]{put(0.002, 0.3, 0.006), put(0.002, 0.3, -0.008), put(-0.001, 0.1, -0.01),put(-0.001, 0.1, 0.01)};
polygons[5] = new polygon3D(v, v[0], v[1], v [3], mainThread.textures[4], 0.1f,0.5f,1);
v = new vector[]{put(0.013, 0.3, 0.006), put(0.002, 0.3, 0.006), put(-0.001, 0.1, 0.01),put(0.016, 0.1, 0.01)};
polygons[6] = new polygon3D(v, v[0], v[1], v [3], mainThread.textures[4], 0.1f,0.5f,1);
v = new vector[]{put(0.013, 0.3, -0.008), put(0.013, 0.3, 0.006), put(0.016, 0.1, 0.01), put(0.016, 0.1, -0.01)};
polygons[7] = new polygon3D(v, v[0], v[1], v [3], mainThread.textures[4], 0.1f,0.5f,1);
//leaves
start.add(0.005f, 0,0);
int index = 8;
int currentAngle = 0;
for(int i = 0; i < 5; i++){
v = new vector[]{put(0.015, 0.3, 0.01), put(0, 0.3, 0), put(0, 0.34, 0.05), put(0.015, 0.32, 0.05)};
polygons[index] = new polygon3D(v, v[0], v[1], v [3], mainThread.textures[5], 1,1,1);
v = new vector[]{put(0, 0.3, 0), put(-0.015, 0.3, 0.01), put(-0.015, 0.32, 0.05), put(0, 0.34, 0.05)};
polygons[index+1] = new polygon3D(v, v[0], v[1], v [3], mainThread.textures[5], 1,1,1);
v = new vector[]{put(0, 0.34, 0.05), put(0, 0.33, 0.09), put(0.015, 0.31, 0.09), put(0.015, 0.32, 0.05)};
polygons[index + 2] = new polygon3D(v, v[0], v[1], v [3], mainThread.textures[5], 1,1,1);
v = new vector[]{put(0, 0.34, 0.05), put(-0.015, 0.32, 0.05), put(-0.015, 0.31, 0.09), put(0, 0.33, 0.09)};
polygons[index + 3] = new polygon3D(v, v[0], v[1], v [3], mainThread.textures[5], 1,1,1);
v = new vector[]{put(0, 0.33, 0.09), put(-0.015, 0.31, 0.09), put(0, 0.29, 0.12)};
polygons[index + 4] = new polygon3D(v, v[0], v[1], v [2], mainThread.textures[5], 1,1,1);
v = new vector[]{put(0.015, 0.31, 0.09), put(0, 0.33, 0.09), put(0, 0.29, 0.12)};
polygons[index + 5] = new polygon3D(v, v[0], v[1], v [2], mainThread.textures[5], 1,1,1);
iDirection.rotate_XZ(angles[i]-currentAngle);
kDirection.rotate_XZ(angles[i]-currentAngle);
currentAngle = angles[i];
index+=6;
}
for(int i = 0; i < polygons.length; i++){
polygons[i].Ambient_I+=10;
polygons[i].findDiffuse();
polygons[i].parentObject = this;
}
}
//update the model
public void update(){
mainThread.gridMap.currentObstacleMap[tileIndex] = false;
//update center in camera coordinate
tempCentre.set(centre);
tempCentre.subtract(camera.position);
tempCentre.rotate_XZ(camera.XZ_angle);
tempCentre.rotate_YZ(camera.YZ_angle);
tempCentre.updateLocation();
if(tempCentre.screenX > 918 || tempCentre.screenX < - 150 || tempCentre.screenY < - 150 || tempCentre.screenY > 662){
visible = false;
return;
}
//test if the palm tree is visible in camera point of view
if(visibleBoundary.contains(tempCentre.screenX, tempCentre.screenY)){
visible = true;
if(screenBoundary.contains(tempCentre.screenX, tempCentre.screenY))
withinViewScreen = true;
else
withinViewScreen = false;
}else{
visible = false;
}
tempshadowvertex0.set(shadowvertex0);
tempshadowvertex0.subtract(camera.position);
tempshadowvertex0.rotate_XZ(camera.XZ_angle);
tempshadowvertex0.rotate_YZ(camera.YZ_angle);
tempshadowvertex0.updateLocation();
tempshadowvertex1.set(shadowvertex1);
tempshadowvertex1.subtract(camera.position);
tempshadowvertex1.rotate_XZ(camera.XZ_angle);
tempshadowvertex1.rotate_YZ(camera.YZ_angle);
tempshadowvertex1.updateLocation();
tempshadowvertex2.set(shadowvertex2);
tempshadowvertex2.subtract(camera.position);
tempshadowvertex2.rotate_XZ(camera.XZ_angle);
tempshadowvertex2.rotate_YZ(camera.YZ_angle);
tempshadowvertex2.updateLocation();
tempshadowvertex3.set(shadowvertex3);
tempshadowvertex3.subtract(camera.position);
tempshadowvertex3.rotate_XZ(camera.XZ_angle);
tempshadowvertex3.rotate_YZ(camera.YZ_angle);
tempshadowvertex3.updateLocation();
//if the object is visible then draw it on the shadow buffer from light point of view
if(shadowBoundary1.contains(tempshadowvertex0.screenX, tempshadowvertex0.screenY) ||
shadowBoundary1.contains(tempshadowvertex1.screenX, tempshadowvertex1.screenY) ||
shadowBoundary1.contains(tempshadowvertex2.screenX, tempshadowvertex2.screenY) ||
shadowBoundary1.contains(tempshadowvertex3.screenX, tempshadowvertex3.screenY)
){
for(int i = 0; i < polygons.length; i++){
polygons[i].update_lightspace();
}
}
}
public vector getMovement(){
return movenment;
}
//draw model
public void draw(){
if(!visible)
return;
for(int i = 0; i < polygons.length; i++){
polygons[i].update();
}
for(int i = 0; i < polygons.length; i++){
polygons[i].draw();
}
}
}

838
entity/powerPlant.java Normal file
View File

@ -0,0 +1,838 @@
package entity;
import java.awt.Rectangle;
import core.*;
import enemyAI.enemyCommander;
//the power plant model
public class powerPlant extends solidObject{
//the polygons of the model
private polygon3D[] polygons;
public static int maxHP = 400;
public int countDownToDeath = 16;
public vector tempVector = new vector(0,0,0);
public vector tempVector0 = new vector(0,0,0);
public vector tempVector1 = new vector(0,0,0);
public vector tempVector2 = new vector(0,0,0);
public vector tempVector3 = new vector(0,0,0);
public int [] tileIndex = new int[9];
public int[] tempInt;
public float[] tempFloat;
public vector shadowvertex0, tempshadowvertex0,shadowvertex1, tempshadowvertex1,shadowvertex2, tempshadowvertex2,shadowvertex3, tempshadowvertex3;
//a screen space boundary which is used to test if the object is visible from camera point of view
public final static Rectangle visibleBoundary = new Rectangle(-85,-85,920, 762);
//a screen space boundary which is used to test if the entire object is within the screen
public final static Rectangle screenBoundary = new Rectangle(60,60,648, 402);
//screen space boundary which is used to test if the shadow of the object is within the screen
public final static Rectangle shadowBoundary1 = new Rectangle(0,0,768, 512);
//a screen space boundary which is used to test if the vision polygon of the object is visible.
public final static Rectangle visionBoundary = new Rectangle(0,0,1600, 2000);
//a bitmap representation of the vision of the power plant for enemy commander
public static boolean[] bitmapVisionForEnemy;
//power plant never moves
public final static vector movenment = new vector(0,0,0);
public baseInfo theBaseInfo;
public static int intendedDeployLocation = -1;
public powerPlant(float x, float y, float z, int teamNo){
//uncontrollable unit, but act as a big sized static collidable agent
type = 101;
if(teamNo == 0){
isRevealed = true;
theBaseInfo = mainThread.pc.theBaseInfo;
}else{
theBaseInfo = mainThread.ec.theBaseInfo;
}
theBaseInfo.numberOfPowerPlant++;
ID = globalUniqID++;
currentHP = 400;
this.teamNo = teamNo;
currentCommand = this.StandBy;
if(teamNo == 0){
isRevealed = true;
}
if(bitmapVisionForEnemy == null){
bitmapVisionForEnemy = createBitmapVision(8);
}
//create 2D boundary
boundary2D = new Rect((int)(x*64) - 16, (int)(z*64) + 16, 32, 32);
boundary2D.owner = this;
int centerX = (int)(x*64);
int centerY = (int)(z*64);
tileIndex[0] = (centerX - 8)/16 + (127 - (centerY + 8)/16)*128;
tileIndex[1] = (centerX + 8)/16 + (127 - (centerY + 8)/16)*128;
tileIndex[2] = (centerX + 8)/16 + (127 - (centerY - 8)/16)*128;
tileIndex[3] = (centerX - 8)/16 + (127 - (centerY - 8)/16)*128;
mainThread.gridMap.tiles[tileIndex[0]][0] = this;
mainThread.gridMap.tiles[tileIndex[1]][0] = this;
mainThread.gridMap.tiles[tileIndex[2]][0] = this;
mainThread.gridMap.tiles[tileIndex[3]][0] = this;
mainThread.gridMap.tiles[tileIndex[0]][1] = this;
mainThread.gridMap.tiles[tileIndex[1]][1] = this;
mainThread.gridMap.tiles[tileIndex[2]][1] = this;
mainThread.gridMap.tiles[tileIndex[3]][1] = this;
mainThread.gridMap.tiles[tileIndex[0]][2] = this;
mainThread.gridMap.tiles[tileIndex[1]][2] = this;
mainThread.gridMap.tiles[tileIndex[2]][2] = this;
mainThread.gridMap.tiles[tileIndex[3]][2] = this;
mainThread.gridMap.tiles[tileIndex[0]][3] = this;
mainThread.gridMap.tiles[tileIndex[1]][3] = this;
mainThread.gridMap.tiles[tileIndex[2]][3] = this;
mainThread.gridMap.tiles[tileIndex[3]][3] = this;
mainThread.gridMap.tiles[tileIndex[0]][4] = this;
mainThread.gridMap.tiles[tileIndex[1]][4] = this;
mainThread.gridMap.tiles[tileIndex[2]][4] = this;
mainThread.gridMap.tiles[tileIndex[3]][4] = this;
//the size of the building is larger for AI, to prevent it from building everything close together
if(teamNo != 0){
tileIndex[4] = tileIndex[1] - 128;
tileIndex[5] = tileIndex[1] - 130;
tileIndex[6] = tileIndex[1] + 256;
tileIndex[7] = tileIndex[1] + 254;
tileIndex[8] = tileIndex[1] + 126;
mainThread.gridMap.tiles[tileIndex[4]][4] = this;
mainThread.gridMap.tiles[tileIndex[5]][4] = this;
mainThread.gridMap.tiles[tileIndex[6]][4] = this;
mainThread.gridMap.tiles[tileIndex[7]][4] = this;
mainThread.gridMap.tiles[tileIndex[8]][4] = this;
}
//init model
x-=0.03f;
start = new vector(x,y,z);
iDirection = new vector(1.2f,0,0);
jDirection = new vector(0,1.2f,0);
kDirection = new vector(0,0,1.2f);
//adjust orientation of the model
iDirection.rotate_XZ(255);
kDirection.rotate_XZ(255);
//define centre of the model in world coordinate
start = new vector(x,y,z);
centre = start.myClone();
tempCentre = start.myClone();
shadowvertex0 =start.myClone();
shadowvertex0.add(-0.45f,-0.2f, -0.15f);
tempshadowvertex0 = new vector(0,0,0);
shadowvertex1 =start.myClone();
shadowvertex1.add(-0.45f,-0.2f, 0.2f);
tempshadowvertex1 = new vector(0,0,0);
shadowvertex2 =start.myClone();
shadowvertex2.add(0.2f,-0.2f, -0.15f);
tempshadowvertex2 = new vector(0,0,0);
shadowvertex3 =start.myClone();
shadowvertex3.add(0.2f,-0.2f, 0.2f);
tempshadowvertex3 = new vector(0,0,0);
makePolygons();
}
//create polygons
public void makePolygons(){
polygons = new polygon3D[36+36+2+32+32 + 32 + 1];
vector[] v;
int index = 0;
double theta = Math.PI/16;
double r = 0.12;
for(int i = 0; i < 18; i++){
v = new vector[]{put(r*Math.cos((i+1)*theta), 0.18, r*Math.sin((i+1)*theta)),
put(r*Math.cos(i*theta), 0.18, r*Math.sin(i*theta)),
put(r*Math.cos(i*theta), 0, r*Math.sin(i*theta)),
put(r*Math.cos((i+1)*theta), 0, r*Math.sin((i+1)*theta))
};
tempVector.set(v[1]);
tempVector.subtract(v[0]);
tempVector0.set(v[0]);
tempVector1.set(v[1]);
tempVector3.set(v[3]);
tempVector1.add(tempVector);
int p = i % 2;
for(int j = 0; j < p; j++){
tempVector0.subtract(tempVector);
tempVector1.subtract(tempVector);
tempVector3.subtract(tempVector);
}
polygons[i + index] = new polygon3D(v, tempVector0.myClone(),tempVector1.myClone(), tempVector3.myClone(), mainThread.textures[13], 0.5f,1, 1);
}
index+=18;
v = new vector[]{put(0.12*Math.cos(0*theta), 0.18, 0.12*Math.sin(0*theta)),
put(0.17*Math.cos(0*theta), 0.16, 0.17*Math.sin(0*theta)),
put(0.2*Math.cos(0*theta), 0.13, 0.2*Math.sin(0*theta)),
put(0.2*Math.cos(0*theta), 0, 0.2*Math.sin(0*theta)),
put(0.12*Math.cos(0*theta), 0, 0.12*Math.sin(0*theta)),
};
polygons[index] = new polygon3D(v, v[0].myClone(), put(0.2*Math.cos(0*theta), 0.18, 0.2*Math.sin(0*theta)), v[4].myClone(), mainThread.textures[13], 0.5f, 1, 1);
index+=1;
v = new vector[]{ put(0.12*Math.cos(18*theta), 0, 0.12*Math.sin(18*theta)),
put(0.2*Math.cos(18*theta), 0, 0.2*Math.sin(18*theta)),
put(0.2*Math.cos(18*theta), 0.13, 0.2*Math.sin(18*theta)),
put(0.17*Math.cos(18*theta), 0.16, 0.17*Math.sin(18*theta)),
put(0.12*Math.cos(18*theta), 0.18, 0.12*Math.sin(18*theta))
};
polygons[index] = new polygon3D(v, put(0.2*Math.cos(18*theta), 0.18, 0.2*Math.sin(18*theta)), v[4].myClone(), v[1].myClone(), mainThread.textures[13], 0.5f, 1, 1);
index+=1;
double delta = Math.PI/8;
start.add(-0.05f,0,0);
r = 0.085;
double r2 = 0.06;
for(int i = 0; i < 16; i++){
v = new vector[]{put(r2*Math.cos(i*delta), 0.18, r2*Math.sin(i*delta)),
put(r2*Math.cos((i+1)*delta), 0.18, r2*Math.sin((i+1)*delta)),
put(r*Math.cos((i+1)*delta), 0, r*Math.sin((i+1)*delta)),
put(r*Math.cos(i*delta), 0, r*Math.sin(i*delta))
};
tempVector.set(v[1]);
tempVector.subtract(v[0]);
tempVector0.set(v[0]);
tempVector1.set(v[1]);
tempVector3.set(v[3]);
tempVector1.add(tempVector);
int p = i % 2;
for(int j = 0; j < p; j++){
tempVector0.subtract(tempVector);
tempVector1.subtract(tempVector);
tempVector3.subtract(tempVector);
}
change(0,0.18f,0, tempVector);
polygons[i + index] = new polygon3D(v, tempVector0.myClone(),tempVector1.myClone(), tempVector3.myClone(), mainThread.textures[12], 1f,0.25f,1);
polygons[i + index].textureScaledWidth = (int)(polygons[i + index].myTexture.width*0.5);
polygons[i + index].createShadeSpan(tempVector, v[0], v[1]);
}
start.add(0.05f,0,-0);
index+=16;
r = 0.2;
for(int i = 0; i < 18; i++){
v = new vector[]{put(r*Math.cos(i*theta), 0.13, r*Math.sin(i*theta)),
put(r*Math.cos((i+1)*theta), 0.13, r*Math.sin((i+1)*theta)),
put(r*Math.cos((i+1)*theta), 0, r*Math.sin((i+1)*theta)),
put(r*Math.cos(i*theta), 0, r*Math.sin(i*theta))
};
tempVector.set(v[1]);
tempVector.subtract(v[0]);
tempVector0.set(v[0]);
tempVector1.set(v[1]);
tempVector3.set(v[3]);
tempVector1.add(tempVector);
int p = i % 2;
for(int j = 0; j < p; j++){
tempVector0.subtract(tempVector);
tempVector1.subtract(tempVector);
tempVector3.subtract(tempVector);
}
polygons[i + index] = new polygon3D(v, tempVector0.myClone(),tempVector1.myClone(), tempVector3.myClone(), mainThread.textures[13], 0.5f,1,1);
}
index += 18;
r2 = 0.17;
for(int i = 0; i < 18; i++){
v = new vector[]{put(r2*Math.cos(i*theta), 0.16, r2*Math.sin(i*theta)),
put(r2*Math.cos((i+1)*theta), 0.16, r2*Math.sin((i+1)*theta)),
put(r*Math.cos((i+1)*theta), 0.13, r*Math.sin((i+1)*theta)),
put(r*Math.cos(i*theta), 0.13, r*Math.sin(i*theta))
};
tempVector.set(v[1]);
tempVector.subtract(v[0]);
tempVector0.set(v[0]);
tempVector1.set(v[1]);
tempVector3.set(v[3]);
tempVector1.add(tempVector);
int p = i % 2;
for(int j = 0; j < p; j++){
tempVector0.subtract(tempVector);
tempVector1.subtract(tempVector);
tempVector3.subtract(tempVector);
}
if(teamNo == 0)
polygons[i + index] = new polygon3D(v, tempVector0.myClone(),tempVector1.myClone(), tempVector3.myClone(), mainThread.textures[15], 0.5f,1,1);
else
polygons[i + index] = new polygon3D(v, tempVector0.myClone(),tempVector1.myClone(), tempVector3.myClone(), mainThread.textures[16], 0.5f,1,1);
}
index += 18;
r = 0.12;
for(int i = 0; i < 18; i++){
v = new vector[]{put(r*Math.cos(i*theta), 0.18, r*Math.sin(i*theta)),
put(r*Math.cos((i+1)*theta), 0.18, r*Math.sin((i+1)*theta)),
put(r2*Math.cos((i+1)*theta), 0.16, r2*Math.sin((i+1)*theta)),
put(r2*Math.cos(i*theta), 0.16, r2*Math.sin(i*theta))
};
tempVector.set(v[1]);
tempVector.subtract(v[0]);
tempVector0.set(v[0]);
tempVector1.set(v[1]);
tempVector3.set(v[3]);
tempVector1.add(tempVector);
int p = i % 2;
for(int j = 0; j < p; j++){
tempVector0.subtract(tempVector);
tempVector1.subtract(tempVector);
tempVector3.subtract(tempVector);
}
polygons[i + index] = new polygon3D(v, tempVector0.myClone(),tempVector1.myClone(), tempVector3.myClone(), mainThread.textures[14], 0.5f,0.4f,1);
}
index +=18;
start.add(-0.05f,0,0);
r = 0.05;
r2 = 0.05;
for(int i = 0; i < 16; i++){
v = new vector[]{
put(r*Math.cos(i*delta), 0.18, r*Math.sin(i*delta)),
put(r*Math.cos((i+1)*delta), 0.18, r*Math.sin((i+1)*delta)),
put(r2*Math.cos((i+1)*delta), 0.38, r2*Math.sin((i+1)*delta)),
put(r2*Math.cos(i*delta), 0.38, r2*Math.sin(i*delta))
};
tempVector.set(v[1]);
tempVector.subtract(v[0]);
tempVector0.set(v[0]);
tempVector1.set(v[1]);
tempVector3.set(v[3]);
tempVector1.add(tempVector);
int p = i % 2;
for(int j = 0; j < p; j++){
tempVector0.subtract(tempVector);
tempVector1.subtract(tempVector);
tempVector3.subtract(tempVector);
}
polygons[i + index] = new polygon3D(v, tempVector0.myClone(),tempVector1.myClone(), tempVector3.myClone(), mainThread.textures[12], 0.5f,1,1);
}
index+=16;
double h = 0.31;
double r3 = 0.056;
v = new vector[16];
for(int i = 0; i <16; i++){
v[15 - i] = put(r3*Math.cos(i*delta), h, r3*Math.sin(i*delta));
}
polygons[index] = new polygon3D(v, put(-r3, h, r3), put(r3, h, r3), put(-r3, h, -r3), mainThread.textures[17], 1f,1,1);
polygons[index].shadowBias = 15000;
index++;
start.add(0.05f,0,-0);
start.add(-0.05f,0,0);
r = 0.06;
r2 = 0.058;
for(int i = 0; i < 16; i++){
v = new vector[]{put(r2*Math.cos(i*delta), 0.26, r2*Math.sin(i*delta)),
put(r2*Math.cos((i+1)*delta), 0.26, r2*Math.sin((i+1)*delta)),
put(r*Math.cos((i+1)*delta), 0.18, r*Math.sin((i+1)*delta)),
put(r*Math.cos(i*delta), 0.18, r*Math.sin(i*delta))
};
tempVector.set(v[1]);
tempVector.subtract(v[0]);
tempVector0.set(v[0]);
tempVector1.set(v[1]);
tempVector3.set(v[3]);
tempVector1.add(tempVector);
int p = i % 2;
for(int j = 0; j < p; j++){
tempVector0.subtract(tempVector);
tempVector1.subtract(tempVector);
tempVector3.subtract(tempVector);
}
change(0,0.26f,0, tempVector);
polygons[i + index] = new polygon3D(v, tempVector0.myClone(),tempVector1.myClone(), tempVector3.myClone(), mainThread.textures[12], 1f,0.25f,1);
polygons[i + index].textureScaledWidth = (int)(polygons[i + index].myTexture.width*0.5);
polygons[i + index].createShadeSpan(tempVector, v[0], v[1]);
}
start.add(0.05f,0,-0);
index+=16;
start.add(-0.05f,0,0);
r = 0.058;
r2 = 0.059;
for(int i = 0; i < 16; i++){
v = new vector[]{put(r2*Math.cos(i*delta), 0.32, r2*Math.sin(i*delta)),
put(r2*Math.cos((i+1)*delta), 0.32, r2*Math.sin((i+1)*delta)),
put(r*Math.cos((i+1)*delta), 0.26, r*Math.sin((i+1)*delta)),
put(r*Math.cos(i*delta), 0.26, r*Math.sin(i*delta))
};
tempVector.set(v[1]);
tempVector.subtract(v[0]);
tempVector0.set(v[0]);
tempVector1.set(v[1]);
tempVector3.set(v[3]);
tempVector1.add(tempVector);
int p = i % 2;
for(int j = 0; j < p; j++){
tempVector0.subtract(tempVector);
tempVector1.subtract(tempVector);
tempVector3.subtract(tempVector);
}
change(0,0.32f,0, tempVector);
polygons[i + index] = new polygon3D(v, tempVector0.myClone(),tempVector1.myClone(), tempVector3.myClone(), mainThread.textures[12], 1f,0.25f,1);
polygons[i + index].textureScaledWidth = (int)(polygons[i + index].myTexture.width*0.5);
polygons[i + index].createShadeSpan(tempVector, v[0], v[1]);
}
start.add(0.05f,0,-0);
index+=16;
start.add(-0.05f,0,0);
r = 0.059;
r2 = 0.06;
for(int i = 0; i < 16; i++){
v = new vector[]{put(r2*Math.cos(i*delta), 0.38, r2*Math.sin(i*delta)),
put(r2*Math.cos((i+1)*delta), 0.38, r2*Math.sin((i+1)*delta)),
put(r*Math.cos((i+1)*delta), 0.32, r*Math.sin((i+1)*delta)),
put(r*Math.cos(i*delta), 0.32, r*Math.sin(i*delta))
};
tempVector.set(v[1]);
tempVector.subtract(v[0]);
tempVector0.set(v[0]);
tempVector1.set(v[1]);
tempVector3.set(v[3]);
tempVector1.add(tempVector);
int p = i % 2;
for(int j = 0; j < p; j++){
tempVector0.subtract(tempVector);
tempVector1.subtract(tempVector);
tempVector3.subtract(tempVector);
}
change(0,0.38f,0, tempVector);
polygons[i + index] = new polygon3D(v, tempVector0.myClone(),tempVector1.myClone(), tempVector3.myClone(), mainThread.textures[12], 1f,0.25f,1);
polygons[i + index].textureScaledWidth = (int)(polygons[i + index].myTexture.width*0.5);
polygons[i + index].createShadeSpan(tempVector, v[0], v[1]);
}
start.add(0.05f,0,-0);
index+=16;
start.add(-0.05f,0,0);
r = 0.05;
r2 = 0.06;
for(int i = 0; i < 16; i++){
v = new vector[]{
put(r*Math.cos(i*delta), 0.38, r*Math.sin(i*delta)),
put(r*Math.cos((i+1)*delta), 0.38, r*Math.sin((i+1)*delta)),
put(r2*Math.cos((i+1)*delta), 0.38, r2*Math.sin((i+1)*delta)),
put(r2*Math.cos(i*delta), 0.38, r2*Math.sin(i*delta))
};
tempVector.set(v[1]);
tempVector.subtract(v[0]);
tempVector0.set(v[0]);
tempVector1.set(v[1]);
tempVector3.set(v[3]);
tempVector1.add(tempVector);
int p = i % 2;
for(int j = 0; j < p; j++){
tempVector0.subtract(tempVector);
tempVector1.subtract(tempVector);
tempVector3.subtract(tempVector);
}
polygons[i + index] = new polygon3D(v, tempVector0.myClone(),tempVector1.myClone(), tempVector3.myClone(), mainThread.textures[12], 0.5f,0.25f,1);
}
start.add(0.05f,0,-0);
index+=16;
for(int i = 0; i < polygons.length; i++){
polygons[i].findDiffuse();
polygons[i].parentObject = this;
}
}
//update the model
public void update(){
//process emerging from ground animation
if(centre.y < -0.5f){
centre.y+=0.02f;
if(centre.y > -0.5){
for(int i = 0; i < polygons.length; i++){
polygons[i].origin.y+=0.0000005;
polygons[i].rightEnd.y+=0.0000005;
polygons[i].bottomEnd.y+=0.0000005;
for(int j = 0; j < polygons[i].vertex3D.length; j++){
polygons[i].vertex3D[j].y+=0.0000005;
}
}
shadowvertex0.y+=0.0000005;
shadowvertex1.y+=0.0000005;
shadowvertex2.y+=0.0000005;
shadowvertex3.y+=0.0000005;
centre.y = -0.5f;
}else{
for(int i = 0; i < polygons.length; i++){
polygons[i].origin.y+=0.02;
polygons[i].rightEnd.y+=0.02;
polygons[i].bottomEnd.y+=0.02;
for(int j = 0; j < polygons[i].vertex3D.length; j++){
polygons[i].vertex3D[j].y+=0.02;
}
}
shadowvertex0.y+=0.02;
shadowvertex1.y+=0.02;
shadowvertex2.y+=0.02;
shadowvertex3.y+=0.02;
}
//the building is invulnerable during emerging stage
currentHP = maxHP;
}
if(underAttackCountDown > 0)
underAttackCountDown--;
//check if power plant has been destroyed
if(currentHP <= 0){
countDownToDeath--;
if(countDownToDeath == 0){
//spawn an explosion when the tank is destroyed
float[] tempFloat = theAssetManager.explosionInfo[theAssetManager.explosionCount];
tempFloat[0] = centre.x;
tempFloat[1] = centre.y + 0.15f;
tempFloat[2] = centre.z;
tempFloat[3] = 3.5f;
tempFloat[4] = 1;
tempFloat[5] = 0;
tempFloat[6] = 7;
tempFloat[7] = this.height;
theAssetManager.explosionCount++;
theAssetManager.removeObject(this);
theBaseInfo.numberOfPowerPlant--;
//removeFromGridMap();
mainThread.gridMap.tiles[tileIndex[0]][0] = null;
mainThread.gridMap.tiles[tileIndex[1]][0] = null;
mainThread.gridMap.tiles[tileIndex[2]][0] = null;
mainThread.gridMap.tiles[tileIndex[3]][0] = null;
mainThread.gridMap.tiles[tileIndex[0]][1] = null;
mainThread.gridMap.tiles[tileIndex[1]][1] = null;
mainThread.gridMap.tiles[tileIndex[2]][1] = null;
mainThread.gridMap.tiles[tileIndex[3]][1] = null;
mainThread.gridMap.tiles[tileIndex[0]][2] = null;
mainThread.gridMap.tiles[tileIndex[1]][2] = null;
mainThread.gridMap.tiles[tileIndex[2]][2] = null;
mainThread.gridMap.tiles[tileIndex[3]][2] = null;
mainThread.gridMap.tiles[tileIndex[0]][3] = null;
mainThread.gridMap.tiles[tileIndex[1]][3] = null;
mainThread.gridMap.tiles[tileIndex[2]][3] = null;
mainThread.gridMap.tiles[tileIndex[3]][3] = null;
mainThread.gridMap.tiles[tileIndex[0]][4] = null;
mainThread.gridMap.tiles[tileIndex[1]][4] = null;
mainThread.gridMap.tiles[tileIndex[2]][4] = null;
mainThread.gridMap.tiles[tileIndex[3]][4] = null;
if(teamNo != 0){
mainThread.gridMap.tiles[tileIndex[4]][4] = null;
mainThread.gridMap.tiles[tileIndex[5]][4] = null;
mainThread.gridMap.tiles[tileIndex[6]][4] = null;
mainThread.gridMap.tiles[tileIndex[7]][4] = null;
mainThread.gridMap.tiles[tileIndex[8]][4] = null;
}
if(attacker.teamNo != teamNo)
attacker.experience+=25;
return;
}else{
float[] tempFloat = theAssetManager.explosionInfo[theAssetManager.explosionCount];
tempFloat[0] = centre.x + (float)Math.random()/2.5f - 0.2f;
tempFloat[1] = centre.y + 0.15f;
tempFloat[2] = centre.z + (float)Math.random()/2.5f - 0.2f;
tempFloat[3] = 1.5f;
tempFloat[4] = 1;
tempFloat[5] = 0;
tempFloat[6] = 6 + (gameData.getRandom()%4);
tempFloat[7] = this.height;
theAssetManager.explosionCount++;
}
}
//processing repair event
if(isRepairing && currentHP >0){
if(mainThread.frameIndex%8==0 && theBaseInfo.currentCredit > 0 && currentHP <maxHP){
currentHP+=2;
theBaseInfo.currentCredit--;
if(currentHP > maxHP)
currentHP = maxHP;
}
}
//mark itself on obstacle map
mainThread.gridMap.currentObstacleMap[tileIndex[0]] = false;
mainThread.gridMap.currentObstacleMap[tileIndex[1]] = false;
mainThread.gridMap.currentObstacleMap[tileIndex[2]] = false;
mainThread.gridMap.currentObstacleMap[tileIndex[3]] = false;
//update center in camera coordinate
tempCentre.set(centre);
tempCentre.subtract(camera.position);
tempCentre.rotate_XZ(camera.XZ_angle);
tempCentre.rotate_YZ(camera.YZ_angle);
tempCentre.updateLocation();
theAssetManager = mainThread.theAssetManager;
//test if the palm tree is visible in camera point of view
if(visibleBoundary.contains(tempCentre.screenX, tempCentre.screenY) && isRevealed){
visible = true;
if(screenBoundary.contains(tempCentre.screenX, tempCentre.screenY))
withinViewScreen = true;
else
withinViewScreen = false;
tempshadowvertex0.set(shadowvertex0);
tempshadowvertex0.subtract(camera.position);
tempshadowvertex0.rotate_XZ(camera.XZ_angle);
tempshadowvertex0.rotate_YZ(camera.YZ_angle);
tempshadowvertex0.updateLocation();
tempshadowvertex1.set(shadowvertex1);
tempshadowvertex1.subtract(camera.position);
tempshadowvertex1.rotate_XZ(camera.XZ_angle);
tempshadowvertex1.rotate_YZ(camera.YZ_angle);
tempshadowvertex1.updateLocation();
tempshadowvertex2.set(shadowvertex2);
tempshadowvertex2.subtract(camera.position);
tempshadowvertex2.rotate_XZ(camera.XZ_angle);
tempshadowvertex2.rotate_YZ(camera.YZ_angle);
tempshadowvertex2.updateLocation();
tempshadowvertex3.set(shadowvertex3);
tempshadowvertex3.subtract(camera.position);
tempshadowvertex3.rotate_XZ(camera.XZ_angle);
tempshadowvertex3.rotate_YZ(camera.YZ_angle);
tempshadowvertex3.updateLocation();
//if the object is visible then draw it on the shadow buffer from light point of view
if(shadowBoundary1.contains(tempshadowvertex0.screenX, tempshadowvertex0.screenY) ||
shadowBoundary1.contains(tempshadowvertex1.screenX, tempshadowvertex1.screenY) ||
shadowBoundary1.contains(tempshadowvertex2.screenX, tempshadowvertex2.screenY) ||
shadowBoundary1.contains(tempshadowvertex3.screenX, tempshadowvertex3.screenY)
){
for(int i = 0; i < polygons.length; i++){
polygons[i].update_lightspace();
}
}
//add this object to visible unit list
theAssetManager.visibleUnit[theAssetManager.visibleUnitCount] = this;
theAssetManager.visibleUnitCount++;
}else{
visible = false;
}
//create vision for enemy commander
if(teamNo == 1){
int xPos = boundary2D.x1/16 - 8 + 10;
int yPos = 127 - boundary2D.y1/16 - 8 + 10;
for(int y = 0; y < 17; y++){
for(int x = 0; x < 17; x++){
if(bitmapVisionForEnemy[x+ y*17])
enemyCommander.tempBitmap[xPos + x + (yPos+y)*148] =true;
}
}
}
visionBoundary.x = (int)(tempCentre.screenX - 800);
visionBoundary.y = (int)(tempCentre.screenY - 1000);
visionInsideScreen = camera.screen.intersects(visionBoundary);
if(visionInsideScreen){
if(teamNo == 0){
tempFloat = theAssetManager.visionPolygonInfo[theAssetManager.visionPolygonCount];
tempFloat[0] = teamNo;
tempFloat[1] = centre.x;
tempFloat[2] = -0.4f;
tempFloat[3] = centre.z;
tempFloat[4] = 2;
theAssetManager.visionPolygonCount++;
}
}
if(theAssetManager.minimapBitmap[tileIndex[0]] ||
theAssetManager.minimapBitmap[tileIndex[1]] ||
theAssetManager.minimapBitmap[tileIndex[2]] ||
theAssetManager.minimapBitmap[tileIndex[3]] )
isRevealed = true;
visible_minimap = isRevealed;
if(visible_minimap){
tempInt = theAssetManager.unitsForMiniMap[theAssetManager.unitsForMiniMapCount];
tempInt[0] = teamNo;
tempInt[1] = boundary2D.x1/16;
tempInt[2] = 127 - boundary2D.y1/16;
tempInt[3] = 2;
if(teamNo == 0 && underAttackCountDown > 0)
tempInt[4] = 10001;
else
tempInt[4] = 10000;
theAssetManager.unitsForMiniMapCount++;
//spawn smoke particle
if((mainThread.frameIndex + ID) % 5 ==0 && centre.y >= -0.5f){
float[] tempFloat = theAssetManager.smokeEmmiterList[theAssetManager.smokeEmmiterCount];
tempFloat[0] = centre.x - 0.053f + (float)(Math.random()/20) - 0.025f;
tempFloat[1] = centre.y + 0.45f;
tempFloat[2] = centre.z + (float)(Math.random()/20) - 0.025f;
tempFloat[3] = 1.5f;
tempFloat[4] = 1;
tempFloat[5] = 11;
tempFloat[6] = this.height;
theAssetManager.smokeEmmiterCount++;
}
}
}
//draw the model
public void draw(){
if(!visible)
return;
for(int i = 0; i < polygons.length; i++){
polygons[i].update();
polygons[i].draw();
}
}
public vector getMovement(){
return movenment;
}
}

1117
entity/refinery.java Normal file

File diff suppressed because it is too large Load Diff

1110
entity/rocketTank.java Normal file

File diff suppressed because it is too large Load Diff

1651
entity/solidObject.java Normal file

File diff suppressed because it is too large Load Diff

1364
entity/stealthTank.java Normal file

File diff suppressed because it is too large Load Diff

1871
entity/techCenter.java Normal file

File diff suppressed because it is too large Load Diff

50
entity/tokenObject.java Normal file
View File

@ -0,0 +1,50 @@
package entity;
import core.Rect;
import core.mainThread;
import core.postProcessingThread;
import core.vector;
//the only purpose of this object is to create an invisible boundary block
public class tokenObject extends solidObject{
public int tileIndex;
public boolean noNeedForThisToken;
public tokenObject(float x, float y, float z, int color){
ID = -1;
type = 4;
teamNo = -1;
centre = new vector(x,y,z);
currentCommand = StandBy;
movement = new vector(0,0,0);
boundary2D = new Rect((int)(x*64) - 8, (int)(z*64) + 8, 16, 16);
tileIndex = boundary2D.x1/16 + (127 - (boundary2D.y1 - 1)/16)*128;
if(x < 0 || mainThread.gridMap.tiles[tileIndex][0]!= null){
noNeedForThisToken = true;
return;
}
if(!(x == 0 && y ==0 && z ==0))
updateOccupiedTiles(boundary2D.x1, boundary2D.y1);
boundary2D.owner = this;
postProcessingThread.theMiniMap.background[tileIndex] = color;
}
public vector getMovement(){
return movement;
}
}

7
gui/.gitignore vendored Normal file
View File

@ -0,0 +1,7 @@
/MiniMap.class
/SideBar.class
/confirmationIcon.class
/deployGrid.class
/inputHandler.class
/playerCommander.class
/sideBarManager.class

376
gui/MiniMap.java Normal file
View File

@ -0,0 +1,376 @@
package gui;
import core.mainThread;
import core.postProcessingThread;
import core.vector;
public class MiniMap {
public int[] background;
public boolean[] tempBitmap;
public boolean[][] bitmapVision;
public static vector corner1, corner2, corner3, corner4;
public static boolean isDrawingWindow;
public void init(){
//load terrain image as background for minimap
background = new int[128*128];
int r = (int)(193 * 0.95);
int g = (int)(176 * 0.95);
int b = (int)(128 * 0.95 );
for(int i = 0; i < 128 * 128; i++)
background[i]= (r << 16) | (g << 8) | b;
tempBitmap = new boolean[148 * 148];
bitmapVision = new boolean[4][];
bitmapVision[0] = createBitmapVision(6);
bitmapVision[1] = createBitmapVision(2);
bitmapVision[2] = createBitmapVision(7);
bitmapVision[3] = createBitmapVision(11);
corner1 = new vector(0,0,0);
corner2 = new vector(0,0,0);
corner3 = new vector(0,0,0);
corner4 = new vector(0,0,0);
}
public void draw(int[] screen, boolean[] minimapBitmap, int[][] unitsForMiniMap, int unitsForMiniMapCount){
//draw mini map window frame
drawFrame(screen);
//create bitmap
createBitmap(minimapBitmap, unitsForMiniMap, unitsForMiniMapCount);
//draw background
drawBackground(screen, minimapBitmap);
//remove fog of war for testing
for(int i = 0; i < minimapBitmap.length; i++)
minimapBitmap[i] = true;
//draw unit positions on minimap
drawUnit(screen, minimapBitmap, unitsForMiniMap, unitsForMiniMapCount);
//draw view window
drawViewWindow(screen);
}
public void drawViewWindow(int[] screen){
int xPos1, xPos2, xPos3,xPos4, yPos1, yPos2, yPos3, yPos4;
xPos1 = (int)(corner1.x*64/16);
yPos1 = 127 - (int)(corner1.z*64/16);
xPos2 = (int)(corner2.x*64/16);
yPos2 = 127 - (int)(corner2.z*64/16);
xPos3 = (int)(corner3.x*64/16);
yPos3 = 127 - (int)(corner3.z*64/16);
xPos4 = (int)(corner4.x*64/16);
yPos4 = 127 - (int)(corner4.z*64/16);
drawLine(xPos1+1, yPos1, xPos2-1,yPos2, screen);
drawLine(xPos2, yPos2, xPos3,yPos3, screen);
drawLine(xPos3-1, yPos3, xPos4+1,yPos4, screen);
drawLine(xPos4, yPos4, xPos1,yPos1, screen);
}
public void findCorners(){
corner1.set(postProcessingThread.my2Dto3DFactory.get3DLocation(mainThread.theAssetManager.Terrain.ground[0], -40, -40));
corner2.set(postProcessingThread.my2Dto3DFactory.get3DLocation(mainThread.theAssetManager.Terrain.ground[0], 807, -40));
corner3.set(postProcessingThread.my2Dto3DFactory.get3DLocation(mainThread.theAssetManager.Terrain.ground[0], 807, 551));
corner4.set(postProcessingThread.my2Dto3DFactory.get3DLocation(mainThread.theAssetManager.Terrain.ground[0], -40, 551));
}
public void drawLine(int xPos1, int yPos1, int xPos2, int yPos2, int[] screen){
int start = 381 * 768 + 3;
int x, y;
int xDirection, yDirection;
if(xPos1 < xPos2)
xDirection = 1;
else
xDirection = -1;
if(yPos1 < yPos2)
yDirection = 1;
else
yDirection = -1;
int color;
if(Math.abs(xPos2 - xPos1) > Math.abs(yPos2 - yPos1)){
float slope = (float)(yPos2 - yPos1)/(xPos2 - xPos1);
for(int i = 0; i <= Math.abs(xPos2 - xPos1); i ++){
x = xPos1 + i*xDirection;
y = (int)(yPos1 + slope*i*xDirection);
if(x < 0 || x > 127 || y < 0 || y > 127)
continue;
color = screen[start + x + y*768];
screen[start + x + y*768] = ((((color&0xFEFEFE)>>1)&0xFEFEFE)>>1) + 0xbfbfbf;
}
}else{
float slope = (float)(xPos2 - xPos1)/(yPos2 - yPos1);
for(int i = 0; i <= Math.abs(yPos2 - yPos1); i ++){
y = yPos1 + i*yDirection;
x = (int)(xPos1 + slope*i*yDirection);
if(x < 0 || x > 127 || y < 0 || y > 127)
continue;
color = screen[start + x + y*768];
screen[start + x + y*768] = ((((color&0xFEFEFE)>>1)&0xFEFEFE)>>1) + 0xbfbfbf;
}
}
}
public void drawUnit(int[] screen, boolean[] minimapBitmap, int[][] unitsForMiniMap, int unitsForMiniMapCount){
int xPos = 0;
int yPos = 0;
int start = 381 * 768 + 3;
int index = 0;
int friendlyUnitColor = 170 << 8;
int friendlyBuildingColor = 46 << 16 | 114 << 8 | 22;
float p = (1f + (float)Math.sin((float)(postProcessingThread.frameIndex)/5))/2;
int c = (int)(255*p);
int underAttackColor = 0xffff0000 | (c << 8) | c;
int enemyUnitColor = 224 << 16;
int enemyBuildingColor1 = 153 << 16;
int enemyBuildingColor2 = 90 << 16;
int type = 0;
for(int i = 0; i < unitsForMiniMapCount; i++){
xPos = unitsForMiniMap[i][1];
yPos = unitsForMiniMap[i][2];
index = start + xPos + yPos*768;
type = unitsForMiniMap[i][0] >> 8;
if((unitsForMiniMap[i][0] & 0xff) == 0){
int color;
if(unitsForMiniMap[i][3] >= 2 && type != 6)
color = friendlyBuildingColor;
else
color = friendlyUnitColor;
if(unitsForMiniMap[i][4] == 10001){
color = underAttackColor;
}
if((screen[index]>>24) == 0)
screen[index] = color;
if((screen[index + 1]>>24) == 0)
screen[index+1] = color;
if((screen[index+768]>>24) == 0)
screen[index+768] = color;
if((screen[index+768 + 1]>>24) == 0)
screen[index+768 + 1] = color;
}else{
int position = xPos + yPos*128;
if(position >=0 && position < 16384){
if(minimapBitmap[xPos + yPos*128] || unitsForMiniMap[i][4] == 10000){
int color;
if(!minimapBitmap[xPos + yPos*128]){
color = enemyBuildingColor2;
}else{
if(unitsForMiniMap[i][3] >= 2 && type != 6)
color = enemyBuildingColor1;
else
color = enemyUnitColor;
}
screen[index] = color;
screen[index+1] = color;
screen[index+768] = color;
screen[index+768 + 1] = color;
}
}
}
}
}
public boolean[] createBitmapVision(int radius){
int l = radius*2+1;
boolean[] vision = new boolean[l*l];
for(int y = 0; y < l; y++){
for(int x = 0; x < l; x++){
if( (x - radius)*(x - radius) + (y - radius)*(y - radius) < ((float)radius+0.5f)*((float)radius+0.5f)){
vision[x + y*l] = true;
}
}
}
return vision;
}
public void createBitmap(boolean[] minimapBitmap, int[][] unitsForMiniMap, int unitsForMiniMapCount){
for(int i = 0 ;i < tempBitmap.length; i++){
tempBitmap[i] = false;
}
boolean[] vision;
int visionType = 0;
int xPos = 0;
int yPos = 0;
int l = 0;
int r = 0;
for(int i = 0; i < unitsForMiniMapCount; i++){
if((unitsForMiniMap[i][0] & 0xff) != 0){
//if(unitsForMiniMap[i][4] != 1)
// continue;
visionType = 1;
}else{
visionType = unitsForMiniMap[i][3];
}
vision = bitmapVision[visionType];
if(visionType == 0){
l = 13;
r = 6;
}else if(visionType == 1){
l = 5;
r = 2;
}else if(visionType == 2){
l = 15;
r = 7;
}else if(visionType == 3){
l = 23;
r = 11;
}
xPos = unitsForMiniMap[i][1] - r + 10;
yPos = unitsForMiniMap[i][2] - r + 10;
if((unitsForMiniMap[i][0] & 0xff) != 0 && (unitsForMiniMap[i][4] == 0 || unitsForMiniMap[i][4] == 10000)){
continue;
}
for(int y = 0; y < l; y++){
for(int x = 0; x < l; x++){
if(vision[x+ y*l])
tempBitmap[xPos + x + (yPos+y)*148] =true;
}
}
}
for(int y = 0; y < 128; y++){
for(int x = 0; x < 128; x++){
minimapBitmap[x + y*128] = tempBitmap[x + 10 + (y + 10)*148];
}
}
}
public void drawBackground(int[] screen, boolean[] minimapBitmap){
int start = 381 * 768 + 3;
int color = 0;
int goldMineColor = 196 << 16 | 138 << 8 | 0;
for(int y = 0; y < 128; y++){
for(int x = 0; x < 128; x ++){
color = background[x + y*128];
if(minimapBitmap[x + y*128]){
screen[start + x + y*768] = color;
}else{
if(((color & 0xf000000) >> 24) == 12)
screen[start + x + y*768] = goldMineColor;
else
screen[start + x + y*768] = (color&0xFEFEFE)>>1;
}
}
}
}
public void drawFrame(int[] screen){
int color1 = 0xa0a0a0;
int color2 = 0xe0e0e0;
int start = 378*768;
for(int x = 1; x < 133; x++){
screen[start + x] = color1;
}
start = 379*768;
for(int x = 1; x < 133; x++){
screen[start + x] = color2;
}
start = 380*768;
for(int x = 2; x < 132; x++){
screen[start + x] = color1;
}
start = 509*768;
for(int x = 2; x < 132; x++){
screen[start + x] = color1;
}
start = 510*768;
for(int x = 1; x < 133; x++){
screen[start + x] = color2;
}
start = 511*768;
for(int x = 0; x < 134; x++){
screen[start + x] = color1;
}
start = 378*768 + 133;
for(int y = 1; y < 132; y++){
screen[start + y*768] = color1;
}
start = 379*768 + 132;
for(int y = 0; y < 132; y++){
screen[start + y*768] = color2;
}
start = 380*768 + 131;
for(int y = 0; y < 131; y++){
screen[start + y*768] = color1;
}
start = 378*768;
for(int y = 1; y < 132; y++){
screen[start + y*768] = color1;
}
start = 379*768 + 1;
for(int y = 0; y < 132; y++){
screen[start + y*768] = color2;
}
start = 380*768 + 2;
for(int y = 0; y < 131; y++){
screen[start + y*768] = color1;
}
}
}

646
gui/SideBar.java Normal file
View File

@ -0,0 +1,646 @@
package gui;
import java.awt.image.PixelGrabber;
import java.awt.*;
import javax.imageio.ImageIO;
import core.mainThread;
import core.postProcessingThread;
public class SideBar {
public String imageFolder = "";
public int[][] iconImages;
public int[][] iconImages_dark;
public int[] xStart;
public int[] yStart;
public int[] autoRepairMark;
public boolean[][] progressBitmaps;
public int onScreenPlayerMoney;
public int MASK7Bit = 0xFEFEFF;
public int pixel, overflow, screenIndex;
public void init(){
xStart = new int[]{634, 677, 722, 634, 677, 722,634, 677, 722};
yStart = new int[]{381, 381, 381, 425, 425, 425,468, 468, 468};
progressBitmaps = new boolean[240][44*44];
prepareProgressBitmaps();
autoRepairMark = new int[74];
for(int i = 0; i < 20; i++){
autoRepairMark[i] = 724 + i*2 + 470*768;
}
for(int i = 20; i < 37; i++){
autoRepairMark[i] = 724 + 38 + (472+(i-20)*2)*768;
}
for(int i = 37; i < 57; i++){
autoRepairMark[i] = 724 + 38 - (i-37)*2 + (470+36)*768;
}
for(int i = 57; i < 74; i++){
autoRepairMark[i] = 724 + (470+(74-i)*2)*768;
}
iconImages = new int[24][44 * 44];
iconImages_dark = new int[24][44 * 44];
String folder = "../images/";
loadTexture(folder + "44.jpg", iconImages[0], 44, 44, iconImages_dark[0]);
loadTexture(folder + "47.jpg", iconImages[1], 44, 44, iconImages_dark[1]);
loadTexture(folder + "48.jpg", iconImages[2], 44, 44, iconImages_dark[2]);
loadTexture(folder + "49.jpg", iconImages[3], 16, 16, iconImages_dark[3]);
loadTexture(folder + "50.jpg", iconImages[4], 16, 16, iconImages_dark[4]);
loadTexture(folder + "57.jpg", iconImages[5], 44, 44, iconImages_dark[5]);
loadTexture(folder + "58.jpg", iconImages[6], 44, 44, iconImages_dark[6]);
loadTexture(folder + "59.jpg", iconImages[7], 44, 44, iconImages_dark[7]);
loadTexture(folder + "60.jpg", iconImages[8], 44, 44, iconImages_dark[8]);
loadTexture(folder + "65.jpg", iconImages[9], 44, 44, iconImages_dark[9]);
loadTexture(folder + "66.jpg", iconImages[10], 44, 44, iconImages_dark[10]);
loadTexture(folder + "67.jpg", iconImages[11], 44, 44, iconImages_dark[11]);
loadTexture(folder + "72.jpg", iconImages[12], 44, 44, iconImages_dark[12]);
loadTexture(folder + "75.jpg", iconImages[13], 44, 44, iconImages_dark[13]);
loadTexture(folder + "76.jpg", iconImages[14], 44, 44, iconImages_dark[14]);
loadTexture(folder + "77.jpg", iconImages[15], 44, 44, iconImages_dark[15]);
loadTexture(folder + "78.jpg", iconImages[16], 44, 44, iconImages_dark[16]);
loadTexture(folder + "79.jpg", iconImages[17], 44, 44, iconImages_dark[17]);
loadTexture(folder + "81.jpg", iconImages[18], 44, 44, iconImages_dark[18]);
loadTexture(folder + "83.jpg", iconImages[19], 44, 44, iconImages_dark[19]);
loadTexture(folder + "86.jpg", iconImages[20], 44, 44, iconImages_dark[20]);
loadTexture(folder + "87.jpg", iconImages[21], 44, 44, iconImages_dark[21]);
loadTexture(folder + "88.jpg", iconImages[22], 44, 44, iconImages_dark[22]);
loadTexture(folder + "89.jpg", iconImages[23], 44, 44, iconImages_dark[23]);
}
public void draw(int[] screen, int[] sideBarInfo){
drawBackground(screen);
drawSideBarInfo(screen, sideBarInfo);
drawCreditAndPowerLevel(screen, postProcessingThread.playerMoney, postProcessingThread.playerPowerStatus);
drawFrame(screen);
}
public void drawCreditAndPowerLevel(int[] screen, int playerMoney, int playerPowerStatus){
drawInfoBackGround(screen, 637, 3, 129, 16, 100);
int startIndex = 639 + 3 * 768;
drawIcon(screen, startIndex, 3);
calculateOnScreenPlayerMoney(playerMoney);
postProcessingThread.theTextRenderer.drawText(657, 3, onScreenPlayerMoney+"", screen, 245,197,51);
if(playerPowerStatus != -1){
drawIcon(screen, startIndex + 60, 4);
int currentPowerConsumption = playerPowerStatus >> 16;
int currentPowerLevel = playerPowerStatus&0xffff;
if(currentPowerConsumption <= currentPowerLevel){
postProcessingThread.theTextRenderer.drawText(714, 3, currentPowerConsumption/50 + "/"+currentPowerLevel/50, screen, 0,205,0);
}else{
postProcessingThread.theTextRenderer.drawText(714, 3, currentPowerConsumption/50 + "", screen, 255,0,0);
int l = (currentPowerConsumption/50 + "").length();
postProcessingThread.theTextRenderer.drawText(714+l*7, 3, "/"+currentPowerLevel/50, screen, 0,205,0);
}
}
}
public void drawIcon(int[] screen, int startIndex, int iconIndex){
int screenIndex = 0;
for(int i = 0; i < 16; i++){
for(int j = 0; j < 16; j++){
screenIndex = startIndex + j + (i+1)*768;
pixel=(iconImages[iconIndex][j + i*16]&MASK7Bit)+(screen[screenIndex]&MASK7Bit);
overflow=pixel&0x1010100;
overflow=overflow-(overflow>>8);
screen[screenIndex] = overflow|pixel;
}
}
}
public void calculateOnScreenPlayerMoney(int playerMoney){
int difference = playerMoney - onScreenPlayerMoney;
if(difference > 1000)
onScreenPlayerMoney+=73;
else if(difference > 23 && difference <= 750)
onScreenPlayerMoney+=23;
else if(difference <= 23 && difference > 0)
onScreenPlayerMoney+=difference;
else
onScreenPlayerMoney+=difference;
}
public void drawSideBarInfo(int[] screen, int[] sideBarInfo){
int displayInfo, iconTextureIndex, progress, text;
int powerPlantInfo = 1;
int deployMCVInfo = 2;
int refineryInfo = 3;
int factoryInfo = 4;
int lightTankInfo = 5;
int rocketTankInfo = 6;
int harvesterInfo = 7;
int droneInfo = 8;
int communicationCenterInfo = 9;
int MCVInfo = 10;
int stealthTankInfo = 11;
int gunTurretInfo = 12;
int repairBuildingInfo = 13;
int missileTurretInfo = 14;
int harvesterResearchInfo = 15;
int missileTurretResearchInfo = 16;
int rapidfireTooltipInfo = 17;
int techCenterInfo = 18;
int heavyTankInfo = 19;
int lightTankResearchInfo = 20;
int rocketTankResearchInfo = 21;
int stealthTankResearchInfo = 22;
int heavyTankResearchInfo = 23;
for(int i = 0; i < 9; i ++){
if(sideBarInfo[i] != -1){
displayInfo = (sideBarInfo[i] >> 24) & 255;
iconTextureIndex = (sideBarInfo[i] >> 16) & 255;
progress = (sideBarInfo[i] >> 8) & 255;
text = sideBarInfo[i] & 255;
if(progress == 254){
drawIconImage(xStart[i],yStart[i],screen,iconImages_dark[iconTextureIndex]);
}else if(progress >= 240){
drawIconImage(xStart[i],yStart[i],screen,iconImages[iconTextureIndex]);
}else if(progress == 0){
drawIconImage(xStart[i],yStart[i],screen,iconImages_dark[iconTextureIndex]);
}else{
drawIconImage(xStart[i],yStart[i],screen,iconImages[iconTextureIndex], iconImages_dark[iconTextureIndex], progress);
}
if(text == 1){
postProcessingThread.theTextRenderer.drawFlashingText(xStart[i] + 5, yStart[i] + 11, "Ready", screen);
}else if(text > 100){
postProcessingThread.theTextRenderer.drawText(xStart[i] + 5, yStart[i] + 0, ""+ (text - 100), screen, 255,255,255);
}
//draw display infos
if(displayInfo == powerPlantInfo){
drawInfoBackGround(screen, 637, 344, 129, 32, 128);
postProcessingThread.theTextRenderer.drawText(639, 344, "Power Plant", screen, 255,255,200);
postProcessingThread.theTextRenderer.drawText(639, 360, "$:500", screen, 245,197,51);
drawIcon(screen, 690 + 360*768, 4);
postProcessingThread.theTextRenderer.drawText(706, 360, "+10", screen, 0,205,0);
}else if(displayInfo == deployMCVInfo){
drawInfoBackGround(screen, 637, 360, 129,16,128);
postProcessingThread.theTextRenderer.drawText(639, 360, "Deploy MCV", screen, 255,255,255);
}else if(displayInfo == refineryInfo){
drawInfoBackGround(screen, 637, 344, 129,32,128);
postProcessingThread.theTextRenderer.drawText(639, 344, "Refinery", screen, 255,255,255);
postProcessingThread.theTextRenderer.drawText(639, 360, "$:1200", screen, 245,197,51);
drawIcon(screen, 690 + 360*768, 4);
postProcessingThread.theTextRenderer.drawText(706, 360, "-3", screen, 255,0,0);
}else if(displayInfo == factoryInfo){
drawInfoBackGround(screen, 637, 344, 129,32,128);
postProcessingThread.theTextRenderer.drawText(639, 344, "Factory", screen, 255,255,255);
postProcessingThread.theTextRenderer.drawText(639, 360, "$:1400", screen, 245,197,51);
drawIcon(screen, 690 + 360*768, 4);
postProcessingThread.theTextRenderer.drawText(706, 360, "-4", screen, 255,0,0);
}else if(displayInfo == lightTankInfo){
drawInfoBackGround(screen, 637, 344, 129,32,128);
postProcessingThread.theTextRenderer.drawText(639, 344, "Light Tank", screen, 255,255,255);
postProcessingThread.theTextRenderer.drawText(639, 360, "$:300", screen, 245,197,51);
}else if(displayInfo == rocketTankInfo){
drawInfoBackGround(screen, 637, 344, 129,32,128);
postProcessingThread.theTextRenderer.drawText(639, 344, "Rocket Tank", screen, 255,255,255);
postProcessingThread.theTextRenderer.drawText(639, 360, "$:450", screen, 245,197,51);
}else if(displayInfo == harvesterInfo){
drawInfoBackGround(screen, 637, 344, 129,32,128);
postProcessingThread.theTextRenderer.drawText(639, 344, "Harvester", screen, 255,255,255);
postProcessingThread.theTextRenderer.drawText(639, 360, "$:800", screen, 245,197,51);
}else if(displayInfo == droneInfo){
drawInfoBackGround(screen, 637, 344, 129,32,128);
postProcessingThread.theTextRenderer.drawText(639, 344, "Repair Drone", screen, 255,255,255);
postProcessingThread.theTextRenderer.drawText(639, 360, "$:250", screen, 245,197,51);
}else if(displayInfo == communicationCenterInfo){
drawInfoBackGround(screen, 637, 344, 129,32,128);
postProcessingThread.theTextRenderer.drawText(639, 344, "COMM. Centre", screen, 255,255,255);
postProcessingThread.theTextRenderer.drawText(639, 360, "$:1000", screen, 245,197,51);
drawIcon(screen, 690 + 360*768, 4);
postProcessingThread.theTextRenderer.drawText(706, 360, "-5", screen, 255,0,0);
}else if(displayInfo == MCVInfo){
drawInfoBackGround(screen, 637, 344, 129,32,128);
postProcessingThread.theTextRenderer.drawText(639, 344, "MCV", screen, 255,255,255);
postProcessingThread.theTextRenderer.drawText(639, 360, "$:1700", screen, 245,197,51);
}else if(displayInfo == stealthTankInfo){
drawInfoBackGround(screen, 637, 344, 129,32,128);
postProcessingThread.theTextRenderer.drawText(639, 344, "Stealth Tank", screen, 255,255,255);
postProcessingThread.theTextRenderer.drawText(639, 360, "$:600", screen, 245,197,51);
}else if(displayInfo == gunTurretInfo){
drawInfoBackGround(screen, 637, 344, 129,32,128);
postProcessingThread.theTextRenderer.drawText(639, 344, "Gun Turret", screen, 255,255,255);
postProcessingThread.theTextRenderer.drawText(639, 360, "$:400", screen, 245,197,51);
drawIcon(screen, 690 + 360*768, 4);
postProcessingThread.theTextRenderer.drawText(706, 360, "-2", screen, 255,0,0);
}else if(displayInfo == repairBuildingInfo){
drawInfoBackGround(screen, 637, 360, 129,16,128);
postProcessingThread.theTextRenderer.drawText(639, 360, "Repair Structure", screen, 255,255,255);
}else if(displayInfo == missileTurretInfo){
drawInfoBackGround(screen, 637, 344, 129,32,128);
postProcessingThread.theTextRenderer.drawText(639, 344, "Missile Turret", screen, 255,255,255);
postProcessingThread.theTextRenderer.drawText(639, 360, "$:750", screen, 245,197,51);
drawIcon(screen, 690 + 360*768, 4);
postProcessingThread.theTextRenderer.drawText(706, 360, "-4", screen, 255,0,0);
}else if(displayInfo == harvesterResearchInfo){
drawInfoBackGround(screen, 637, 328, 129,48,128);
postProcessingThread.theTextRenderer.drawText(639, 328, "Research harvester", screen, 255,255,255);
postProcessingThread.theTextRenderer.drawText(640, 344, "movement speed.", screen, 255,255,255);
postProcessingThread.theTextRenderer.drawText(639, 360, "$:1200", screen, 245,197,51);
}else if(displayInfo == missileTurretResearchInfo){
drawInfoBackGround(screen, 637, 312, 129,64,128);
postProcessingThread.theTextRenderer.drawText(639, 312, "Research rapidfire", screen, 255,255,255);
postProcessingThread.theTextRenderer.drawText(639, 328, "ability for the", screen, 255,255,255);
postProcessingThread.theTextRenderer.drawText(639, 344, "missile turret.", screen, 255,255,255);
postProcessingThread.theTextRenderer.drawText(639, 360, "$:1500", screen, 245,197,51);
}else if(displayInfo == rapidfireTooltipInfo){
drawInfoBackGround(screen, 637, 312, 129,64,128);
postProcessingThread.theTextRenderer.drawText(639, 312, "Fire missile more", screen, 255,255,255);
postProcessingThread.theTextRenderer.drawText(639, 328, "rapidly, but draws", screen, 255,255,255);
postProcessingThread.theTextRenderer.drawText(639, 344, "addtional power.", screen, 255,255,255);
drawIcon(screen, 639 + 360*768, 4);
postProcessingThread.theTextRenderer.drawText(655, 360, "-3", screen, 255,0,0);
}else if(displayInfo == techCenterInfo){
drawInfoBackGround(screen, 637, 344, 129,32,128);
postProcessingThread.theTextRenderer.drawText(639, 344, "Tech Center", screen, 255,255,255);
postProcessingThread.theTextRenderer.drawText(639, 360, "$:1500", screen, 245,197,51);
drawIcon(screen, 690 + 360*768, 4);
postProcessingThread.theTextRenderer.drawText(706, 360, "-8", screen, 255,0,0);
}else if(displayInfo == heavyTankInfo){
drawInfoBackGround(screen, 637, 344, 129,32,128);
postProcessingThread.theTextRenderer.drawText(639, 344, "Heavy Tank", screen, 255,255,255);
postProcessingThread.theTextRenderer.drawText(639, 360, "$:1100", screen, 245,197,51);
}else if(displayInfo == lightTankResearchInfo){
drawInfoBackGround(screen, 637, 328, 129,48,128);
postProcessingThread.theTextRenderer.drawText(639, 328, "Research light", screen, 255,255,255);
postProcessingThread.theTextRenderer.drawText(640, 344, "tank's fire range", screen, 255,255,255);
postProcessingThread.theTextRenderer.drawText(639, 360, "$:1500", screen, 245,197,51);
}else if(displayInfo == rocketTankResearchInfo){
drawInfoBackGround(screen, 637, 312, 129,64,128);
postProcessingThread.theTextRenderer.drawText(639, 312, "Research rocket", screen, 255,255,255);
postProcessingThread.theTextRenderer.drawText(639, 328, "tank's damage", screen, 255,255,255);
postProcessingThread.theTextRenderer.drawText(639, 344, "against building", screen, 255,255,255);
postProcessingThread.theTextRenderer.drawText(639, 360, "$:2000", screen, 245,197,51);
}else if(displayInfo == stealthTankResearchInfo){
drawInfoBackGround(screen, 637, 312, 129,64,128);
postProcessingThread.theTextRenderer.drawText(639, 312, "Research stealth", screen, 255,255,255);
postProcessingThread.theTextRenderer.drawText(639, 328, "tank's ability to", screen, 255,255,255);
postProcessingThread.theTextRenderer.drawText(639, 344, "hit multiple units", screen, 255,255,255);
postProcessingThread.theTextRenderer.drawText(639, 360, "$:2000", screen, 245,197,51);
}else if(displayInfo == heavyTankResearchInfo){
drawInfoBackGround(screen, 637, 312, 129,64,128);
postProcessingThread.theTextRenderer.drawText(639, 312, "Research heavy", screen, 255,255,255);
postProcessingThread.theTextRenderer.drawText(639, 328, "tank's ability to", screen, 255,255,255);
postProcessingThread.theTextRenderer.drawText(639, 344, "self repair", screen, 255,255,255);
postProcessingThread.theTextRenderer.drawText(639, 360, "$:2500", screen, 245,197,51);
}
if((iconTextureIndex == 14 || iconTextureIndex == 17) && text == 32){
int d = 0;
if(iconTextureIndex == 17)
d = 768*44;
int startIndex1 = (int)(mainThread.frameIndex/1.5)%74;
int startIndex2 = ((int)(mainThread.frameIndex/1.5)%74 + 18)%74;
int startIndex3 = ((int)(mainThread.frameIndex/1.5)%74 + 37)%74;
int startIndex4 = ((int)(mainThread.frameIndex/1.5)%74 + 55)%74;
int markerR = 255;
int markerG = 255;
int markerB =64;
int pixelColor;
int pixelR, pixelG, pixelB;
for(int j = 0; j < 16; j++){
int index = autoRepairMark[(startIndex1+j)%74] -d;
float t = 0.9375f - 0.0625f*j;
pixelColor = screen[index];
pixelR = (pixelColor & 0xff0000) >> 16;
pixelG = (pixelColor & 0xff00) >> 8;
pixelB = (pixelColor & 0xff);
pixelColor = (int)(pixelR*t + markerR*(1-t)) << 16 | (int)(pixelG*t + markerG*(1-t)) << 8 | (int)(pixelB*t + markerB*(1-t));
screen[index] = pixelColor;
screen[index+1] = pixelColor;
screen[index + 768] = pixelColor;
screen[index + 769] = pixelColor;
}
for(int j = 0; j < 16; j++){
int index = autoRepairMark[(startIndex2+j)%74] - d;
float t = 0.9375f - 0.0625f*j;
pixelColor = screen[index];
pixelR = (pixelColor & 0xff0000) >> 16;
pixelG = (pixelColor & 0xff00) >> 8;
pixelB = (pixelColor & 0xff);
pixelColor = (int)(pixelR*t + markerR*(1-t)) << 16 | (int)(pixelG*t + markerG*(1-t)) << 8 | (int)(pixelB*t + markerB*(1-t));
screen[index] = pixelColor;
screen[index+1] = pixelColor;
screen[index + 768] = pixelColor;
screen[index + 769] = pixelColor;
}
for(int j = 0; j < 16; j++){
int index = autoRepairMark[(startIndex3+j)%74] - d;
float t = 0.9375f - 0.0625f*j;
pixelColor = screen[index];
pixelR = (pixelColor & 0xff0000) >> 16;
pixelG = (pixelColor & 0xff00) >> 8;
pixelB = (pixelColor & 0xff);
pixelColor = (int)(pixelR*t + markerR*(1-t)) << 16 | (int)(pixelG*t + markerG*(1-t)) << 8 | (int)(pixelB*t + markerB*(1-t));
screen[index] = pixelColor;
screen[index+1] = pixelColor;
screen[index + 768] = pixelColor;
screen[index + 769] = pixelColor;
}
for(int j = 0; j < 16; j++){
int index = autoRepairMark[(startIndex4+j)%74] - d;
float t = 0.9375f - 0.0625f*j;
pixelColor = screen[index];
pixelR = (pixelColor & 0xff0000) >> 16;
pixelG = (pixelColor & 0xff00) >> 8;
pixelB = (pixelColor & 0xff);
pixelColor = (int)(pixelR*t + markerR*(1-t)) << 16 | (int)(pixelG*t + markerG*(1-t)) << 8 | (int)(pixelB*t + markerB*(1-t));
screen[index] = pixelColor;
screen[index+1] = pixelColor;
screen[index + 768] = pixelColor;
screen[index + 769] = pixelColor;
}
}
}
}
}
public void drawInfoBackGround(int[] screen, int xPos, int yPos, int w, int h, int alpha){
int start = xPos + yPos*768;
if(alpha == 128){
for(int i = 1; i < w - 1; i++){
screen[start -768 + i] = (screen[start -768 + i]&0xFEFEFE)>>1;
}
for(int i = 0; i < h; i++){
for(int j = 0; j < w; j++){
screen[start + j + i*768] = (screen[start + j + i*768]&0xFEFEFE)>>1;
}
}
for(int i = 1; i < w - 1; i++)
screen[start + 768*h + i] = (screen[start + 768*h + i]&0xFEFEFE)>>1;
}else{
for(int i = 1; i < w - 1; i++){
int value = screen[start -768 + i];
screen[start -768 + i] = (((((value&0xff0000) >> 16) * alpha) >> 8) << 16) | (((((value&0xff00) >> 8) * alpha) >> 8) << 8) | (((((value&0xff)) * alpha) >> 8));
}
for(int i = 0; i < h; i++){
for(int j = 0; j < w; j++){
int value = screen[start + j + i*768];
screen[start + j + i*768] = (((((value&0xff0000) >> 16) * alpha) >> 8) << 16) | (((((value&0xff00) >> 8) * alpha) >> 8) << 8) | (((((value&0xff)) * alpha) >> 8));
}
}
for(int i = 1; i < w - 1; i++){
int value = screen[start + 768*h + i];
screen[start + 768*h + i] = (((((value&0xff0000) >> 16) * alpha) >> 8) << 16) | (((((value&0xff00) >> 8) * alpha) >> 8) << 8) | (((((value&0xff)) * alpha) >> 8));
}
}
}
public void prepareProgressBitmaps(){
double theta = Math.PI/120;
for(int i = 0; i < 240; i++){
double angle = i*theta;
for(int j = 0; j < 44*44; j++){
double x = j%44 -22;
double y = 22 - j/44 ;
if(angle > (Math.PI*2.5 - Math.atan2(y, x))%(Math.PI*2))
progressBitmaps[i][j] = true;
}
}
}
public void drawIconImage(int xPos, int yPos, int[] screen, int[] iconImage){
int start = xPos + yPos * 768;
for(int i = 0; i < 44; i++){
for(int j = 0; j < 44; j++){
screen[start + j + i*768] = iconImage[j + i*44];
}
}
}
public void drawIconImage(int xPos, int yPos, int[] screen, int[] iconImage, int[] iconImages_dark, int progress){
int start = xPos + yPos * 768;
for(int i = 0; i < 44; i++){
for(int j = 0; j < 44; j++){
if(progressBitmaps[progress][j + i*44])
screen[start + j + i*768] = iconImage[j + i*44];
else
screen[start + j + i*768] = iconImages_dark[j + i*44];
}
}
}
public void drawBackground(int[] screen){
int start = 381*768 + 637;
for(int i = 0; i< 128; i++){
for(int j = 0; j < 128; j++){
screen[start + j + i*768] = 0x666655;
}
}
}
public void drawFrame(int[] screen){
int color1 = 0xa0a0a0;
int color2 = 0xe0e0e0;
int shift= 634;
int start = 378*768 + shift;
for(int x = 1; x < 133; x++){
screen[start + x] = color1;
}
start = 379*768 + shift;
for(int x = 1; x < 133; x++){
screen[start + x] = color2;
}
start = 380*768 + shift;
for(int x = 2; x < 132; x++){
screen[start + x] = color1;
}
start = 422*768 + shift;
for(int x = 1; x < 133; x++){
screen[start + x] = color1;
}
start = 423*768 + shift;
for(int x = 1; x < 133; x++){
screen[start + x] = color2;
}
start = 424*768 + shift;
for(int x = 2; x < 132; x++){
screen[start + x] = color1;
}
start = 466*768 + shift;
for(int x = 1; x < 133; x++){
screen[start + x] = color1;
}
start = 467*768 + shift;
for(int x = 1; x < 133; x++){
screen[start + x] = color2;
}
start = 468*768 + shift;
for(int x = 2; x < 132; x++){
screen[start + x] = color1;
}
start = 509*768 + shift;
for(int x = 2; x < 132; x++){
screen[start + x] = color1;
}
start = 510*768 + shift;
for(int x = 1; x < 133; x++){
screen[start + x] = color2;
}
start = 511*768 + shift;
for(int x = 0; x < 134; x++){
screen[start + x] = color1;
}
start = 378*768 + 133 + shift;
for(int y = 1; y < 132; y++){
screen[start + y*768] = color1;
}
start = 379*768 + 132 + shift;
for(int y = 0; y < 132; y++){
screen[start + y*768] = color2;
}
start = 380*768 + 131 + shift;
for(int y = 0; y < 131; y++){
screen[start + y*768] = color1;
}
start = 378*768 + shift;
for(int y = 1; y < 132; y++){
screen[start + y*768] = color1;
}
start = 379*768 + 1 + shift;
for(int y = 0; y < 132; y++){
screen[start + y*768] = color2;
}
start = 380*768 + 2 + shift;
for(int y = 0; y < 131; y++){
screen[start + y*768] = color1;
}
start = 378*768 + 42 + shift;
for(int y = 1; y < 132; y++){
screen[start + y*768] = color1;
}
start = 379*768 + 43 + shift;
for(int y = 0; y < 132; y++){
screen[start + y*768] = color2;
}
start = 380*768 + 44 + shift;
for(int y = 0; y < 131; y++){
screen[start + y*768] = color1;
}
start = 378*768 + 86 + shift;
for(int y = 1; y < 132; y++){
screen[start + y*768] = color1;
}
start = 379*768 + 87 + shift;
for(int y = 0; y < 132; y++){
screen[start + y*768] = color2;
}
start = 380*768 + 88 + shift;
for(int y = 0; y < 131; y++){
screen[start + y*768] = color1;
}
}
public void loadTexture(String imgName, int[] buffer, int width, int height, int[] buffer_dark){
Image img = null;
try{
img = ImageIO.read(getClass().getResource(imageFolder + imgName));
}catch(Exception e){
e.printStackTrace();
}
PixelGrabber pg = new PixelGrabber(img, 0, 0, width, height, buffer, 0, width);
try {
pg.grabPixels();
}catch(Exception e){
e.printStackTrace();
}
for(int i = 0; i < buffer_dark.length; i++){
buffer_dark[i] = (buffer[i]&0xFEFEFE)>>1;
}
}
}

186
gui/confirmationIcon.java Normal file
View File

@ -0,0 +1,186 @@
package gui;
import core.postProcessingThread;
import core.vector;
public class confirmationIcon {
public int color;
public static float[] sin;
public static float[] cos;
//centre of the icon
public vector centre;
public vector tempCentre;
public int frameIndex;
public confirmationIcon(){
//Make sin and cos look up tables
sin = new float[361];
cos = new float[361];
for(int i = 0; i < 361; i ++){
sin[i] = (float)Math.sin(Math.PI*i/180);
cos[i] = (float)Math.cos(Math.PI*i/180);
}
centre = new vector(0,0,0);
tempCentre = new vector(0,0,0);
frameIndex = -1;
}
public void setActive(float xPos, float zPos, int color){
centre.set(xPos, -0.5001f, zPos);
this.color = color;
frameIndex = 20;
}
public void updateAndDraw(){
if(frameIndex <0)
return;
vector cameraPosition = postProcessingThread.cameraPosition;
float X = 0,Y = 0, Z = 0,
camX = cameraPosition.x, camY = cameraPosition.y, camZ = cameraPosition.z,
sinXZ = postProcessingThread.sinXZ,
cosXZ = postProcessingThread.cosXZ,
sinYZ = postProcessingThread.sinYZ,
cosYZ = postProcessingThread.cosYZ;
X = centre.x - camX;
Y = centre.y - camY;
Z = centre.z - camZ;
//rotating
tempCentre.x = cosXZ*X - sinXZ*Z;
tempCentre.z = sinXZ*X + cosXZ*Z;
Z = tempCentre.z;
tempCentre.y = cosYZ*Y - sinYZ*Z;
tempCentre.z = sinYZ*Y + cosYZ*Z;
tempCentre.updateLocation();
int[] screen = postProcessingThread.currentScreen;
int x, y;
float a = 13f;
float b = 11.5f;
int lastIndex = -1;
int currentIndex;
int t = frameIndex - 10;
float transparency = 0.7f;
if(t < 0){
t = 0;
transparency = (float)frameIndex * transparency/10f;
}
int r1,b1,g1, r2,b2,g2, screenColor;
//draw transparent ring
for(int i = 0; i < 360; i+=1){
x = (int)(tempCentre.screenX + (a * (float)(12-t)/10f +0.7f) * cos[i]);
y = (int)(tempCentre.screenY + (b * (float)(12-t)/10f +0.7f)* sin[i]);
if(x < 0 || x >= 768 || y < 0 || y >= 512)
continue;
currentIndex = x + y * 768;
if(currentIndex == lastIndex)
continue;
screenColor = screen[currentIndex];
r1 = (int)(((screenColor & 0xff0000) >> 16) * (1f - transparency*0.5f));
g1 = (int)(((screenColor & 0xff00) >> 8) * (1f - transparency * 0.5f));
b1 = (int)((screenColor & 0xff) * (1f - transparency * 0.5f));
r2 = (int)(((color & 0xff0000) >> 16) * transparency * 0.5f) + r1;
g2 = (int)(((color & 0xff00) >> 8) * transparency * 0.5f) + g1;
b2 = (int)((color & 0xff) * transparency * 0.5f) + b1;
screen[x + y * 768] = r2 << 16 | g2 << 8 | b2;
lastIndex = currentIndex;
}
for(int i = 0; i < 360; i+=1){
x = (int)(tempCentre.screenX + (a * (float)(12-t)/10f -1.7f) * cos[i]);
y = (int)(tempCentre.screenY + (b * (float)(12-t)/10f -1.7f)* sin[i]);
if(x < 0 || x >= 768 || y < 0 || y >= 512)
continue;
currentIndex = x + y * 768;
if(currentIndex == lastIndex)
continue;
screenColor = screen[currentIndex];
r1 = (int)(((screenColor & 0xff0000) >> 16) * (1f - transparency*0.5f));
g1 = (int)(((screenColor & 0xff00) >> 8) * (1f - transparency * 0.5f));
b1 = (int)((screenColor & 0xff) * (1f - transparency * 0.5f));
r2 = (int)(((color & 0xff0000) >> 16) * transparency * 0.5f) + r1;
g2 = (int)(((color & 0xff00) >> 8) * transparency * 0.5f) + g1;
b2 = (int)((color & 0xff) * transparency * 0.5f) + b1;
screen[x + y * 768] = r2 << 16 | g2 << 8 | b2;
lastIndex = currentIndex;
}
//draw solid ring
for(int i = 0; i < 360; i+=1){
x = (int)(tempCentre.screenX + (a * (float)(12-t)/10f) * cos[i]);
y = (int)(tempCentre.screenY + (b * (float)(12-t)/10f)* sin[i]);
if(x < 0 || x >= 768 || y < 0 || y >= 512)
continue;
screenColor = screen[x + y * 768];
r1 = (int)(((screenColor & 0xff0000) >> 16) * (1f - transparency));
g1 = (int)(((screenColor & 0xff00) >> 8) * (1f - transparency));
b1 = (int)((screenColor & 0xff) * (1f - transparency));
r2 = (int)(((color & 0xff0000) >> 16) * transparency) + r1;
g2 = (int)(((color & 0xff00) >> 8) * transparency) + g1;
b2 = (int)((color & 0xff) * transparency) + b1;
screen[x + y * 768] = r2 << 16 | g2 << 8 | b2;
}
for(int i = 0; i < 360; i+=1){
x = (int)(tempCentre.screenX + (a * (float)(12-t)/10f -1) * cos[i]);
y = (int)(tempCentre.screenY + (b * (float)(12-t)/10f- 1)* sin[i]);
if(x < 0 || x >= 768 || y < 0 || y >= 512)
continue;
screenColor = screen[x + y * 768];
r1 = (int)(((screenColor & 0xff0000) >> 16) * (1f - transparency));
g1 = (int)(((screenColor & 0xff00) >> 8) * (1f - transparency));
b1 = (int)((screenColor & 0xff) * (1f - transparency));
r2 = (int)(((color & 0xff0000) >> 16) * transparency) + r1;
g2 = (int)(((color & 0xff00) >> 8) * transparency) + g1;
b2 = (int)((color & 0xff) * transparency) + b1;
screen[x + y * 768] = r2 << 16 | g2 << 8 | b2;
}
frameIndex--;
}
}

206
gui/deployGrid.java Normal file
View File

@ -0,0 +1,206 @@
package gui;
import core.*;
import entity.constructionYard;
import entity.solidObject;
public class deployGrid {
public polygon3D[] polygons;
public boolean canBeDeployed;
public int[] gridArea;
public vector gridOneCenter;
public vector iDirection, jDirection, kDirection, start;
public vector clickPoint;
public constructionYard cy;
public int gridOneIndex;
public deployGrid(){
gridArea = new int[9];
iDirection = new vector(1,0,0);
jDirection = new vector(0,1,0);
kDirection = new vector(0,0,1);
start = new vector(0,0,0);
clickPoint = new vector(0,0,0);
makeGrid();
}
public void makeGrid(){
polygons = new polygon3D[9];
double w = 0;
double h = 0;
vector[] v = new vector[]{put(-0.1 + w, -0.5, 0.12 + h), put(0.1 + w, -0.5, 0.12 + h), put(0.12 + w, -0.5, 0.1 + h), put(0.12 + w, -0.5, -0.1 + h), put(0.1 + w, -0.5, -0.12 + h), put(-0.1 + w, -0.5, -0.12 + h), put(-0.12 + w, -0.5, -0.1 + h), put(-0.12 + w, -0.5, 0.1 + h)};
polygons[0] = new polygon3D(v, v[0], v[1], v [3], null, 1f,1f,10);
w = 0.25;
h = 0;
v = new vector[]{put(-0.1 + w, -0.5, 0.12 + h), put(0.1 + w, -0.5, 0.12 + h), put(0.12 + w, -0.5, 0.1 + h), put(0.12 + w, -0.5, -0.1 + h), put(0.1 + w, -0.5, -0.12 + h), put(-0.1 + w, -0.5, -0.12 + h), put(-0.12 + w, -0.5, -0.1 + h), put(-0.12 + w, -0.5, 0.1 + h)};
polygons[1] = new polygon3D(v, v[0], v[1], v [3], null, 1f,1f,10);
w = 0.5;
h = 0;
v = new vector[]{put(-0.1 + w, -0.5, 0.12 + h), put(0.1 + w, -0.5, 0.12 + h), put(0.12 + w, -0.5, 0.1 + h), put(0.12 + w, -0.5, -0.1 + h), put(0.1 + w, -0.5, -0.12 + h), put(-0.1 + w, -0.5, -0.12 + h), put(-0.12 + w, -0.5, -0.1 + h), put(-0.12 + w, -0.5, 0.1 + h)};
polygons[2] = new polygon3D(v, v[0], v[1], v [3], null, 1f,1f,10);
w = 0;
h = -0.25;
v = new vector[]{put(-0.1 + w, -0.5, 0.12 + h), put(0.1 + w, -0.5, 0.12 + h), put(0.12 + w, -0.5, 0.1 + h), put(0.12 + w, -0.5, -0.1 + h), put(0.1 + w, -0.5, -0.12 + h), put(-0.1 + w, -0.5, -0.12 + h), put(-0.12 + w, -0.5, -0.1 + h), put(-0.12 + w, -0.5, 0.1 + h)};
polygons[3] = new polygon3D(v, v[0], v[1], v [3], null, 1f,1f,10);
w = 0.25;
h = -0.25;
v = new vector[]{put(-0.1 + w, -0.5, 0.12 + h), put(0.1 + w, -0.5, 0.12 + h), put(0.12 + w, -0.5, 0.1 + h), put(0.12 + w, -0.5, -0.1 + h), put(0.1 + w, -0.5, -0.12 + h), put(-0.1 + w, -0.5, -0.12 + h), put(-0.12 + w, -0.5, -0.1 + h), put(-0.12 + w, -0.5, 0.1 + h)};
polygons[4] = new polygon3D(v, v[0], v[1], v [3], null, 1f,1f,10);
w = 0.5;
h = -0.25;
v = new vector[]{put(-0.1 + w, -0.5, 0.12 + h), put(0.1 + w, -0.5, 0.12 + h), put(0.12 + w, -0.5, 0.1 + h), put(0.12 + w, -0.5, -0.1 + h), put(0.1 + w, -0.5, -0.12 + h), put(-0.1 + w, -0.5, -0.12 + h), put(-0.12 + w, -0.5, -0.1 + h), put(-0.12 + w, -0.5, 0.1 + h)};
polygons[5] = new polygon3D(v, v[0], v[1], v [3], null, 1f,1f,10);
w = 0;
h = -0.5;
v = new vector[]{put(-0.1 + w, -0.5, 0.12 + h), put(0.1 + w, -0.5, 0.12 + h), put(0.12 + w, -0.5, 0.1 + h), put(0.12 + w, -0.5, -0.1 + h), put(0.1 + w, -0.5, -0.12 + h), put(-0.1 + w, -0.5, -0.12 + h), put(-0.12 + w, -0.5, -0.1 + h), put(-0.12 + w, -0.5, 0.1 + h)};
polygons[6] = new polygon3D(v, v[0], v[1], v [3], null, 1f,1f,10);
w = 0.25;
h = -0.5;
v = new vector[]{put(-0.1 + w, -0.5, 0.12 + h), put(0.1 + w, -0.5, 0.12 + h), put(0.12 + w, -0.5, 0.1 + h), put(0.12 + w, -0.5, -0.1 + h), put(0.1 + w, -0.5, -0.12 + h), put(-0.1 + w, -0.5, -0.12 + h), put(-0.12 + w, -0.5, -0.1 + h), put(-0.12 + w, -0.5, 0.1 + h)};
polygons[7] = new polygon3D(v, v[0], v[1], v [3], null, 1f,1f,10);
w = 0.5;
h = -0.5;
v = new vector[]{put(-0.1 + w, -0.5, 0.12 + h), put(0.1 + w, -0.5, 0.12 + h), put(0.12 + w, -0.5, 0.1 + h), put(0.12 + w, -0.5, -0.1 + h), put(0.1 + w, -0.5, -0.12 + h), put(-0.1 + w, -0.5, -0.12 + h), put(-0.12 + w, -0.5, -0.1 + h), put(-0.12 + w, -0.5, 0.1 + h)};
polygons[8] = new polygon3D(v, v[0], v[1], v [3], null, 1f,1f,10);
for(int i = 0; i < 9; i++)
polygons[i].color = 31 << 5;
gridOneCenter = new vector(0,0,0);
}
public void update(){
cy = mainThread.pc.selectedConstructionYard;
clickPoint.set(mainThread.my2Dto3DFactory.get3DLocation(mainThread.theAssetManager.Terrain.ground[0], inputHandler.mouse_x, inputHandler.mouse_y));
gridOneIndex = (int)(clickPoint.x*4) + (127 - (int)(clickPoint.z*4))*128;
clickPoint.x = (float)((int)(clickPoint.x*4))/4 + 0.125f;
clickPoint.z = (float)((int)(clickPoint.z*4))/4 + 0.125f;
float dx = clickPoint.x - gridOneCenter.x;
float dz = clickPoint.z - gridOneCenter.z;
for(int i = 0; i < 9; i++){
for(int j = 0; j < 8; j++){
polygons[i].vertex3D[j].x+=dx;
polygons[i].vertex3D[j].z+=dz;
}
}
gridOneCenter.x = clickPoint.x;
gridOneCenter.z = clickPoint.z;
if(cy != null){
canBeDeployed = true;
if(cy.powerPlantProgress == 240 || cy.communicationCenterProgress == 240 || cy.techCenterProgress == 240){
gridArea[0] = 1; if(!checkIfBlockIsFree(gridOneIndex)){ gridArea[0] = 2; canBeDeployed = false;}
gridArea[1] = 1; if(!checkIfBlockIsFree(gridOneIndex+1)){ gridArea[1] = 2; canBeDeployed = false;}
gridArea[2] = 0;
gridArea[3] = 1; if(!checkIfBlockIsFree(gridOneIndex + 128)){ gridArea[3] = 2; canBeDeployed = false;}
gridArea[4] = 1; if(!checkIfBlockIsFree(gridOneIndex + 129)){ gridArea[4] = 2; canBeDeployed = false;}
gridArea[5] = 0;
gridArea[6] = 0;
gridArea[7] = 0;
gridArea[8] = 0;
}else if(cy.refineryProgress == 240 || cy.factoryProgress == 240){
gridArea[0] = 1; if(!checkIfBlockIsFree(gridOneIndex)){ gridArea[0] = 2; canBeDeployed = false;}
gridArea[1] = 1; if(!checkIfBlockIsFree(gridOneIndex+1)){ gridArea[1] = 2; canBeDeployed = false;}
gridArea[2] = 1; if(!checkIfBlockIsFree(gridOneIndex+2)){ gridArea[2] = 2; canBeDeployed = false;}
gridArea[3] = 1; if(!checkIfBlockIsFree(gridOneIndex + 128)){ gridArea[3] = 2; canBeDeployed = false;}
gridArea[4] = 1; if(!checkIfBlockIsFree(gridOneIndex + 129)){ gridArea[4] = 2; canBeDeployed = false;}
gridArea[5] = 1; if(!checkIfBlockIsFree(gridOneIndex + 130)){ gridArea[5] = 2; canBeDeployed = false;}
gridArea[6] = 1; if(!checkIfBlockIsFree(gridOneIndex + 256)){ gridArea[6] = 2; canBeDeployed = false;}
gridArea[7] = 1; if(!checkIfBlockIsFree(gridOneIndex + 257)){ gridArea[7] = 2; canBeDeployed = false;}
gridArea[8] = 1; if(!checkIfBlockIsFree(gridOneIndex + 258)){ gridArea[8] = 2; canBeDeployed = false;}
}else if(cy.gunTurretProgress == 240 || cy.missileTurretProgress == 240){
gridArea[0] = 1; if(!checkIfBlockIsFree(gridOneIndex)){ gridArea[0] = 2; canBeDeployed = false;}
gridArea[1] = 0;
gridArea[2] = 0;
gridArea[3] = 0;
gridArea[4] = 0;
gridArea[5] = 0;
gridArea[6] = 0;
gridArea[7] = 0;
gridArea[8] = 0;
}
}
}
public void draw(){
for(int i = 0; i < 9; i++){
if(gridArea[i] >= 1){
polygons[i].update();
if(gridArea[i] == 1)
polygons[i].color = 31 << 5;
else
polygons[i].color = 31 << 10;
polygons[i].draw();
}
}
}
public boolean checkIfBlockIsFree(int index){
int y = index/128;
int x = index%128;
if(y > 0 && y < 127 && x > 0 && x < 127){
solidObject[] tile = mainThread.gridMap.tiles[index];
for(int j = 0; j < 5; j++){
if(tile[j] != null){
return false;
}
}
constructionYard[] cys = mainThread.theAssetManager.constructionYards;
for(int i = 0; i < cys.length; i++){
if(cys[i] != null && cys[i].teamNo == 0){
float xPos = x * 0.25f + 0.125f;
float yPos = (127 - y)*0.25f + 0.125f;
float distance = (float) Math.sqrt((cys[i].centre.x - xPos)*(cys[i].centre.x - xPos) + (cys[i].centre.z - yPos)*(cys[i].centre.z - yPos));
if(distance <= 2.75)
return true;
}
}
}
return false;
}
//create a arbitrary vertex
public vector put(double i, double j, double k){
vector temp = start.myClone();
temp.add(iDirection, (float)i);
temp.add(jDirection, (float)j);
temp.add(kDirection, (float)k);
return temp;
}
}

252
gui/inputHandler.java Normal file
View File

@ -0,0 +1,252 @@
package gui;
//handles all the logic for user input
import java.awt.*;
import core.camera;
import core.geometry;
import core.mainThread;
public class inputHandler {
public static int mouse_x, mouse_y,mouse_x0, mouse_x1, mouse_y0, mouse_y1, cameraMovementAngle;
public static boolean mouseIsInsideScreen, leftKeyPressed, rightKeyPressed, controlKeyPressed, leftMouseButtonPressed, rightMouseButtonPressed, leftMouseButtonReleased, rightMouseButtonReleased, H_pressed,A_pressed, userIsHoldingA;
public static int numberTyped;
public static final Rectangle mouseMovementArea = new Rectangle(30,20, 708, 472);
public static char[] inputBuffer = new char[1024];
public static char[] keyReleaseBuffer = new char[1024];
public static int inputCounter, inputBufferIndex, keyReleaseCounter, keyReleaseBufferIndex;
public static void processInput(){
//read input char
int theCounter = inputCounter;
//handle over flow
if(inputBufferIndex > theCounter){
while(inputBufferIndex < 1024){
char c = inputBuffer[inputBufferIndex];
if(c == 'h' || c == 'H'){
H_pressed = true;
}
if(c == 'a' || c == 'A'){
A_pressed = true;
}
if(c >=49 && c <=53){
numberTyped = c - 48;
}
inputBufferIndex++;
}
inputBufferIndex = 0;
}
while(inputBufferIndex < theCounter){
char c = inputBuffer[inputBufferIndex];
if(c == 'h' || c == 'H'){
H_pressed = true;
}
if(c == 'a' || c == 'A'){
A_pressed = true;
}
if(c >=49 && c <=53){
numberTyped = c - 48;
}
inputBufferIndex++;
}
//read released char
theCounter = keyReleaseCounter;
//handle over flow
if(keyReleaseBufferIndex > theCounter){
while(keyReleaseBufferIndex < 1024){
char c = keyReleaseBuffer[keyReleaseBufferIndex];
if(c == 'h' || c == 'H'){
H_pressed = false;
}
if(c == 'a' || c == 'A'){
A_pressed = false;
userIsHoldingA = false;
}
keyReleaseBufferIndex++;
}
keyReleaseBufferIndex = 0;
}
while(keyReleaseBufferIndex < theCounter){
char c = keyReleaseBuffer[keyReleaseBufferIndex];
if(c == 'h' || c == 'H'){
H_pressed = false;
}
if(c == 'a' || c == 'A'){
A_pressed = false;
userIsHoldingA = false;
}
keyReleaseBufferIndex++;
}
//handle input when game is running
if(mainThread.inGame){
if(!mainThread.pc.isSelectingUnit){
mouse_x0 = mouse_x;
mouse_y0 = mouse_y;
if(!mouseIsInsideScreen || !mouseMovementArea.contains(mouse_x0, mouse_y0)){
if(mainThread.pc.cursorIsInMiniMap() || mainThread.pc.cursorIsInSideBar()){
if(mouse_x0 < 10)
camera.MOVE_LEFT = true;
if(mouse_x0 > 758)
camera.MOVE_RIGHT = true;
if(mouse_y0 < 20)
camera.MOVE_UP = true;
if(mouse_y0 > 502)
camera.MOVE_DOWN = true;
}else{
if(mouse_x0 < 40)
camera.MOVE_LEFT = true;
if(mouse_x0 > 728)
camera.MOVE_RIGHT = true;
if(mouse_y0 < 40)
camera.MOVE_UP = true;
if(mouse_y0 > 472)
camera.MOVE_DOWN = true;
}
if(camera.MOVE_LEFT || camera.MOVE_RIGHT || camera.MOVE_UP || camera.MOVE_DOWN){
int angle = geometry.findAngle(mouse_x0, mouse_y0, mouse_x1, mouse_y1);
if(angle != 0){
cameraMovementAngle = angle;
}
if(mouse_x0 < 250 && mouse_y0 > 362 && cameraMovementAngle > 105 && cameraMovementAngle < 165){
camera.MOVE_LEFT = true;
camera.MOVE_DOWN = true;
}
if(mouse_x0 < 250 && mouse_y0 < 150 && cameraMovementAngle < 75){
camera.MOVE_LEFT = true;
camera.MOVE_UP = true;
}
if(mouse_x0 > 518 && mouse_y0 < 150 && cameraMovementAngle > 285){
camera.MOVE_RIGHT = true;
camera.MOVE_UP = true;
}
if(mouse_x0 > 518 && mouse_y0 > 362 && cameraMovementAngle < 255 && cameraMovementAngle > 195){
camera.MOVE_RIGHT = true;
camera.MOVE_DOWN = true;
}
}
}
if(leftKeyPressed){
camera.TURN_LEFT = true;
}
if(rightKeyPressed){
camera.TURN_RIGHT = true;
}
mouse_x1 = mouse_x0;
mouse_y1 = mouse_y0;
}
if(controlKeyPressed){
mainThread.pc.controlKeyPressed = true;
}
if(numberTyped != 0){
mainThread.pc.numberTyped = numberTyped;
}
//handles left click
if(leftMouseButtonPressed){
mainThread.pc.leftMouseButtonPressed = true;
}
if(leftMouseButtonReleased){
mainThread.pc.leftMouseButtonReleased = true;
}
//handles right click
if(rightMouseButtonPressed){
mainThread.pc.rightMouseButtonPressed = true;
}
if(rightMouseButtonReleased){
mainThread.pc.rightMouseButtonReleased = true;
}
//handle hotheys
if(H_pressed){
mainThread.pc.holdKeyPressed = true;
}
//handle hotheys
if(A_pressed){
if(!userIsHoldingA){
mainThread.pc.attackKeyPressed = true;
userIsHoldingA = true;
}
}
}
mouseIsInsideScreen = false;
leftMouseButtonPressed = false;
rightMouseButtonPressed = false;
leftMouseButtonReleased = false;
rightMouseButtonReleased = false;
A_pressed = false;
numberTyped = 0;
}
public static void readCharacter(char c){
inputBuffer[inputCounter] = c;
inputCounter++;
if(inputCounter == 1024)
inputCounter = 0;
}
public static void handleKeyRelease(char c){
keyReleaseBuffer[keyReleaseCounter] = c;
keyReleaseCounter++;
if(keyReleaseCounter == 1024)
keyReleaseCounter = 0;
}
}

748
gui/playerCommander.java Normal file
View File

@ -0,0 +1,748 @@
package gui;
import java.awt.Rectangle;
import core.AssetManager;
import core.baseInfo;
import core.camera;
import core.mainThread;
import core.vector;
import entity.constructionYard;
import entity.solidObject;
//this class interprets player's inputs and turns them into commands that can be issued to game units
public class playerCommander {
public solidObject[] selectedUnits;
public solidObject[][] groups;
public boolean leftMouseButtonPressed, rightMouseButtonPressed, leftMouseButtonReleased, rightMouseButtonReleased, attackKeyPressed, holdKeyPressed, controlKeyPressed;
public int numberTyped;
public boolean isSelectingUnit, isMovingViewWindow;
public int startX, startY, endX, endY;
public Rectangle area, areaSmall;
public vector clickPoint;
public AssetManager theAssetManager;
public int numberOfSelectedUnits;
public int doubleClickCountDown;
public boolean doubleClicked;
public int doubleNumberPressCountdown;
public int pressedNumber;
public boolean doubleNumberPressed;
public int selectedIndex;
public sideBarManager theSideBarManager;
public boolean isDeployingBuilding;
public constructionYard selectedConstructionYard;
public baseInfo theBaseInfo;
public void init(){
selectedUnits = new solidObject[100];
groups = new solidObject[5][100];
area = new Rectangle();
areaSmall = new Rectangle();
clickPoint = new vector(0,0,0);
theAssetManager = mainThread.theAssetManager;
theSideBarManager = new sideBarManager(this);
theBaseInfo = new baseInfo();
}
public void update(){
theBaseInfo.update();
if(isDeployingBuilding){
if(leftMouseButtonPressed && !cursorIsInMiniMap() && !cursorIsInSideBar() && selectedConstructionYard.dg.canBeDeployed){
//create a new building
selectedConstructionYard.createBuilding();
isDeployingBuilding = false;
selectedConstructionYard.needToDrawDeploymentGrid = false;
selectedConstructionYard.finishDeployment();
selectedConstructionYard = null;
leftMouseButtonPressed = false;
}
if(rightMouseButtonPressed){
isDeployingBuilding = false;
selectedConstructionYard.needToDrawDeploymentGrid = false;
selectedConstructionYard = null;
rightMouseButtonPressed = false;
}else{
if(!cursorIsInMiniMap()){
theSideBarManager.update();
leftMouseButtonPressed = false;
isMovingViewWindow = false;
return;
}
}
}
if(doubleClickCountDown > 0)
doubleClickCountDown--;
if(doubleClickCountDown == 0)
doubleClicked = false;
if(doubleNumberPressCountdown > 0)
doubleNumberPressCountdown--;
if(doubleNumberPressCountdown == 0){
pressedNumber = 255;
}
if(numberTyped != 0){
if(controlKeyPressed){
for(int i = 0; i < 100; i ++){
if(groups[numberTyped-1][i] != null){
groups[numberTyped-1][i].groupNo = 255;
groups[numberTyped-1][i] = null;
}
}
for(int i = 0; i < 100; i ++){
if(selectedUnits[i] != null){
if(selectedUnits[i].teamNo == 0){
groups[numberTyped-1][i] = selectedUnits[i];
selectedUnits[i].groupNo = numberTyped-1;
selectedUnits[i].isSelected = true;
removeFromOtherGroup(selectedUnits[i], numberTyped-1);
}
}
}
}else{
if(numberTyped == pressedNumber){
doubleNumberPressed = true;
doubleNumberPressCountdown = 30;
}else{
doubleNumberPressed = false;
pressedNumber = numberTyped;
doubleNumberPressCountdown = 10;
}
numberOfSelectedUnits = 0;
for(int i = 0; i < 100; i ++){
if(selectedUnits[i] != null)
selectedUnits[i].isSelected = false;
selectedUnits[i] = null;
if(groups[numberTyped-1][i] != null)
if(groups[numberTyped-1][i].currentHP > 0){
selectedUnits[i] = groups[numberTyped-1][i];
groups[numberTyped-1][i].isSelected = true;
numberOfSelectedUnits++;
}
}
//center camera to the one of the selected units
if(doubleNumberPressed){
solidObject selectedUnit = null;
int nullCount = 0;
for(int j = 0; j < 100; j++){
if(selectedUnits[(j+selectedIndex)%100] != null){
selectedUnit = selectedUnits[(j+selectedIndex)%100];
selectedIndex++;
break;
}else{
nullCount++;
}
}
selectedIndex+=nullCount;
if(selectedUnit != null){
camera.position.x = selectedUnit.centre.x - camera.view_Direction.x * 3;
camera.position.z = selectedUnit.centre.z - camera.view_Direction.z * 3;
}
}
}
}
if(leftMouseButtonPressed){
if(cursorIsInSideBar())
theSideBarManager.leftMouseButtonClicked = true;
if(attackKeyPressed){
//if the click lands on empty ground perform "attack move" for all selected unit
//if the click lands on an unit, then attack that unit regardless if it is friend or foe
boolean performAttack = false;
if(numberOfSelectedUnits > 1){
performAttack = true;
}
if(numberOfSelectedUnits ==1){
if(selectedUnits[0] != null) //null pointer happened here once, not sure why
if(selectedUnits[0].teamNo == 0)
performAttack = true;
}
if(performAttack){
if(cursorIsInMiniMap()){
clickPoint.set(0.25f*(inputHandler.mouse_x-3), 0, 0.25f*(127-(inputHandler.mouse_y-381)));
attackMoveSelectUnit(clickPoint.x, clickPoint.z);
}else if(cursorIsInSideBar()){
theSideBarManager.leftMouseButtonClicked = true;
}else{
clickPoint.set(mainThread.my2Dto3DFactory.get3DLocation(theAssetManager.Terrain.ground[0], inputHandler.mouse_x, inputHandler.mouse_y));
float x = clickPoint.x;
float y = clickPoint.z;
//if click outside map boundary, move units to the closest valid tile
if(x < 0.25 || x > 31.75 || y < 0.25 || y > 31.75){
if( x < 0.25)
x = 0.125f;
if(x > 31.75)
x = 31.875f;
if(y < 0.25)
y = 0.125f;
if(y > 31.75)
y = 31.875f;
}
int xPos = (int)(x*64);
int yPos = (int)(y*64);
int index = xPos/16 + (127-yPos/16)*128;
boolean clickOnEmptyGround = true;
for(int i = 0; i < mainThread.gridMap.tiles[index].length; i++){
if(mainThread.gridMap.tiles[index][i] != null){
if(mainThread.gridMap.tiles[index][i].boundary2D.contains(xPos, yPos)){
if(mainThread.gridMap.tiles[index][i].visible_minimap){
attackUnit(mainThread.gridMap.tiles[index][i]);
clickOnEmptyGround = false;
break;
}
}
}
}
if(clickOnEmptyGround){
attackMoveSelectUnit(x, y);
}
}
}
attackKeyPressed = false;
}else{
if(cursorIsInMiniMap()){
isMovingViewWindow = true;
}else{
if(doubleClickCountDown == 0)
doubleClickCountDown = 10;
else
doubleClicked = true;
if(!cursorIsInSideBar())
isSelectingUnit = true;
startX = inputHandler.mouse_x;
startY = inputHandler.mouse_y;
}
}
}
if(isMovingViewWindow){
camera.position.x = 0.25f*(inputHandler.mouse_x-3) - camera.view_Direction.x * 3;
camera.position.z = 0.25f*(127-(inputHandler.mouse_y-381)) - camera.view_Direction.z * 3;
}
if(isSelectingUnit){
endX = inputHandler.mouse_x;
endY = inputHandler.mouse_y;
if(startX < 0)
startX = 0;
if(startX >767)
startX = 767;
if(startY < 0)
startY = 0;
if(startY > 511)
startY = 511;
if(endX > 767)
endX = 767;
if(endX < 0)
endX = 0;
if(endY > 511)
endY = 511;
if(endY < 0)
endY = 0;
int width = Math.abs(endX - startX);
int height = Math.abs(endY - startY);
int xPos = Math.min(startX, endX);
int yPos = Math.min(startY, endY);
area.setBounds(xPos, yPos,width, height);
}
if(leftMouseButtonReleased){
if(isMovingViewWindow){
isMovingViewWindow = false;
}
if(isSelectingUnit){
isSelectingUnit = false;
int width = Math.abs(endX - startX);
int height = Math.abs(endY - startY);
int xPos = Math.min(startX, endX) - 50;
int yPos = Math.min(startY, endY) -20;
int xPos_small = Math.min(startX, endX) - 20;
int yPos_small = Math.min(startY, endY) -20;
if(width < 20 || height < 20){
area.setBounds(xPos, yPos, 100, 100);
areaSmall.setBounds(xPos_small, yPos_small, 40,40);
selectUnit(area, areaSmall);
}else
selectMultipleUnits(area);
}
}
if(rightMouseButtonPressed){
attackKeyPressed = false;
if(cursorIsInMiniMap()){
clickPoint.set(0.25f*(inputHandler.mouse_x-3), 0, 0.25f*(127-(inputHandler.mouse_y-381)));
}else{
clickPoint.set(mainThread.my2Dto3DFactory.get3DLocation(theAssetManager.Terrain.ground[0], inputHandler.mouse_x, inputHandler.mouse_y));
}
if(!cursorIsInSideBar()){
maneuverUnit();
}else{
theSideBarManager.rightMouseButtonClicked = true;
}
}
if(holdKeyPressed){
holdAllSelectedUnit();
}
//display health bar when mouse cursor hover over a unit
if(!isSelectingUnit){
startX = inputHandler.mouse_x;
startY = inputHandler.mouse_y;
int xPos = startX - 50;
int yPos = startY -20;
int xPos_small = startX - 30;
int yPos_small = startY -30;
area.setBounds(xPos, yPos, 100, 100);
areaSmall.setBounds(xPos_small, yPos_small, 60,60);
addDelectUnitToDisplayInfo(area, areaSmall);
}
theSideBarManager.update();
leftMouseButtonPressed = false;
rightMouseButtonPressed = false;
leftMouseButtonReleased = false;
rightMouseButtonReleased = false;
holdKeyPressed = false;
controlKeyPressed = false;
numberTyped = 0;
}
public boolean cursorIsInMiniMap(){
return inputHandler.mouse_x >=3 && inputHandler.mouse_x <=131 && inputHandler.mouse_y >= 381 && inputHandler.mouse_y <= 509;
}
public boolean cursorIsInSideBar(){
return inputHandler.mouse_x >=637 && inputHandler.mouse_x <=765 && inputHandler.mouse_y >= 381 && inputHandler.mouse_y <= 509;
}
public void removeDestoryedObjectFromSelection(solidObject o){
for(int i = 0; i < selectedUnits.length; i++){
if(selectedUnits[i] == o){
selectedUnits[i] = null;
numberOfSelectedUnits--;
}
}
}
public void holdAllSelectedUnit(){
for(int i = 0; i < selectedUnits.length; i++){
if(selectedUnits[i] != null){
if(selectedUnits[i].teamNo == 0){
selectedUnits[i].hold();
}
}
}
}
public void moveSelectedUnit(float x, float y){
boolean mobileUnitSelected = false;
for(int i = 0; i < selectedUnits.length; i++){
if(selectedUnits[i] != null){
if(selectedUnits[i].teamNo == 0 && (selectedUnits[i].type < 100 || selectedUnits[i].type == 105)){
selectedUnits[i].moveTo(x, y);
selectedUnits[i].currentCommand = solidObject.move;
selectedUnits[i].secondaryCommand = solidObject.StandBy;
mobileUnitSelected = true;
}
}
}
//draw move confirmation if a mobile unit is given move order
if(mobileUnitSelected){
theAssetManager.confirmationIconInfo[0] = 1;
theAssetManager.confirmationIconInfo[1] = x;
theAssetManager.confirmationIconInfo[2] = y;
theAssetManager.confirmationIconInfo[3] = 0xbb22;
}
}
public void attackMoveSelectUnit(float x, float y){
boolean mobileUnitSelected = false;
for(int i = 0; i < selectedUnits.length; i++){
if(selectedUnits[i] != null){
if(selectedUnits[i].teamNo == 0 && selectedUnits[i].type != 2 && selectedUnits[i].type != 3 && selectedUnits[i].type < 100){ //not harvesters or MCVs or any buildings
selectedUnits[i].attackMoveTo(x, y);
selectedUnits[i].currentCommand = solidObject.attackMove;
selectedUnits[i].secondaryCommand = solidObject.attackMove;
mobileUnitSelected = true;
}
}
}
//draw attack move confirmation if a mobile unit is given attack move order
if(mobileUnitSelected){
theAssetManager.confirmationIconInfo[0] = 1;
theAssetManager.confirmationIconInfo[1] = x;
theAssetManager.confirmationIconInfo[2] = y;
theAssetManager.confirmationIconInfo[3] = 0xcc2222;
}
}
public void addDelectUnitToDisplayInfo(Rectangle unitArea, Rectangle unitAreaSmall){
solidObject theSelected = null;
for(int i = 0; i < theAssetManager.visibleUnitCount; i++){
if(unitArea.contains(theAssetManager.visibleUnit[i].tempCentre.screenX, theAssetManager.visibleUnit[i].tempCentre.screenY)){
if((theAssetManager.visibleUnit[i].type < 100 || theAssetManager.visibleUnit[i].type >= 199) && !unitAreaSmall.contains(theAssetManager.visibleUnit[i].tempCentre.screenX, theAssetManager.visibleUnit[i].tempCentre.screenY))
continue;
if(theAssetManager.visibleUnit[i].type < 100 || theAssetManager.visibleUnit[i].type >= 199){
theSelected = theAssetManager.visibleUnit[i];
break;
}
theSelected = theAssetManager.visibleUnit[i];
}
}
if(theSelected != null && !theSelected.isSelected && theSelected.isSelectable){
mainThread.theAssetManager.selectedUnitsInfo[99][0] = theSelected.level << 16 | theSelected.groupNo << 8 | theSelected.type;
mainThread.theAssetManager.selectedUnitsInfo[99][1] = (int)theSelected.tempCentre.screenX;
mainThread.theAssetManager.selectedUnitsInfo[99][2] = (int)theSelected.tempCentre.screenY;
if(theSelected.type == 199){
mainThread.theAssetManager.selectedUnitsInfo[99][1] = (int)theSelected.screenX_gui;
mainThread.theAssetManager.selectedUnitsInfo[99][2] = (int)theSelected.screenY_gui;
}
mainThread.theAssetManager.selectedUnitsInfo[99][3] = (int)theSelected.type;
mainThread.theAssetManager.selectedUnitsInfo[99][4] = theSelected.currentHP;
mainThread.theAssetManager.selectedUnitsInfo[99][5] = theSelected.progressStatus;
}else{
mainThread.theAssetManager.selectedUnitsInfo[99][0] = -1;
}
}
public void selectUnit(Rectangle unitArea, Rectangle unitAreaSmall){
solidObject theSelected = null;
for(int i = 0; i < theAssetManager.visibleUnitCount; i++){
if(unitArea.contains(theAssetManager.visibleUnit[i].tempCentre.screenX, theAssetManager.visibleUnit[i].tempCentre.screenY)){
if((theAssetManager.visibleUnit[i].type < 100 || theAssetManager.visibleUnit[i].type >= 199) && !unitAreaSmall.contains(theAssetManager.visibleUnit[i].tempCentre.screenX, theAssetManager.visibleUnit[i].tempCentre.screenY))
continue;
if(theAssetManager.visibleUnit[i].type < 100 || theAssetManager.visibleUnit[i].type >= 199){
theSelected = theAssetManager.visibleUnit[i];
break;
}
theSelected = theAssetManager.visibleUnit[i];
}
}
if(theSelected != null){
if(!controlKeyPressed)
deSelectAll();
if(theSelected.isSelected && controlKeyPressed && !doubleClicked){
deSelect(theSelected);
return;
}
addToSelection(theSelected);
theSelected.isSelected = true;
if(doubleClicked){
int type = theSelected.type;
for(int j = 0; j < theAssetManager.visibleUnitCount; j++){
if(theAssetManager.visibleUnit[j] != theSelected && theAssetManager.visibleUnit[j].type == type && theAssetManager.visibleUnit[j].teamNo == 0){
addToSelection(theAssetManager.visibleUnit[j]);
theAssetManager.visibleUnit[j].isSelected = true;
}
}
doubleClicked = false;
doubleClickCountDown = 0;
}
}
}
public void selectMultipleUnits(Rectangle area){
boolean unitIsSelected = false;;
for(int i = 0; i < theAssetManager.visibleUnitCount; i++){
if(theAssetManager.visibleUnit[i].teamNo == 0 && area.contains(theAssetManager.visibleUnit[i].tempCentre.screenX, theAssetManager.visibleUnit[i].tempCentre.screenY)){
if(!unitIsSelected){
if(!controlKeyPressed)
deSelectAll();
unitIsSelected = true;
}
addToSelection(theAssetManager.visibleUnit[i]);
theAssetManager.visibleUnit[i].isSelected = true;
}
}
}
public void addToSelection(solidObject o){
//dont add gold mine to select units
//if(o.type == 103)
// return;
if(!o.isSelectable)
return;
deSelect(o);
for(int i = 0; i < 100; i++){
if(selectedUnits[i] == null){
selectedUnits[i] = o;
o.isSelected = true;
if(o.teamNo == 0)
numberOfSelectedUnits++;
break;
}
}
}
public void deSelect(solidObject o){
for(int i = 0; i < 100; i++){
if(selectedUnits[i] == o){
selectedUnits[i].isSelected = false;
selectedUnits[i] = null;
numberOfSelectedUnits--;
break;
}
}
}
public void deSelectAll(){
for(int i = 0; i < 100; i++){
if(selectedUnits[i] != null){
selectedUnits[i].isSelected = false;
selectedUnits[i] = null;
}
}
numberOfSelectedUnits = 0;
}
public void selectGroup(int groupNo){
for(int i = 0; i < 100; i++){
selectedUnits[i] = groups[groupNo][i];
}
}
public void maneuverUnit(){
float x = clickPoint.x;
float y = clickPoint.z;
//if click outside map boundary, move units to the closest valid tile
if(x < 0.25 || x > 31.75 || y < 0.25 || y > 31.75){
if( x < 0.25)
x = 0.125f;
if(x > 31.75)
x = 31.885f;
if(y < 0.25)
y = 0.125f;
if(y > 31.75)
y = 31.885f;
moveSelectedUnit(x,y);
return;
}
//find out if the click point lands on a friend unit or an enemy unit or empty ground
int xPos = (int)(clickPoint.x*64);
int yPos = (int)(clickPoint.z*64);
int index = xPos/16 + (127-yPos/16)*128;
for(int i = 0; i < mainThread.gridMap.tiles[index].length; i++){
if(mainThread.gridMap.tiles[index][i] != null){
if(mainThread.gridMap.tiles[index][i].boundary2D.contains(xPos, yPos)){
//handle right click on a gold mine
if(mainThread.gridMap.tiles[index][i].type == 103){
harvestMine(mainThread.gridMap.tiles[index][i]);
return;
}else if(mainThread.gridMap.tiles[index][i].type == 102 && mainThread.gridMap.tiles[index][i].teamNo == 0){
returnToRefinery(mainThread.gridMap.tiles[index][i]);
return;
}else if(mainThread.gridMap.tiles[index][i].teamNo != 0 && mainThread.gridMap.tiles[index][i].visible_minimap && !cursorIsInMiniMap()){
//the enemy is only clickable if its visible in minimap
attackUnit(mainThread.gridMap.tiles[index][i]);
return;
}
}
}
}
moveSelectedUnit(x,y);
}
public void attackUnit(solidObject o){
if(o.isCloaked && o.teamNo != 0)
return;
boolean combatUnitSelected = false;
for(int i = 0; i < selectedUnits.length; i++){
if(selectedUnits[i] != null && selectedUnits[i].teamNo != -1){ // make sure it won't target gold mine
if(selectedUnits[i].teamNo == 0 && selectedUnits[i] != o && selectedUnits[i].type != 2 && selectedUnits[i].type != 3 && (selectedUnits[i].type < 100 || selectedUnits[i].type >=199)){ //can't attack self
selectedUnits[i].attack(o);
if(numberOfSelectedUnits <= 4)
selectedUnits[i].currentCommand = solidObject.attackCautiously;
else
selectedUnits[i].currentCommand = solidObject.attackInNumbers;
selectedUnits[i].secondaryCommand = solidObject.StandBy;
combatUnitSelected = true;
}
}
}
//draw attack confirmation if a combat unit is given attack order
if(combatUnitSelected){
theAssetManager.confirmationIconInfo[0] = 1;
theAssetManager.confirmationIconInfo[1] = o.centre.x;
theAssetManager.confirmationIconInfo[2] = o.centre.z;
theAssetManager.confirmationIconInfo[3] = 0xcc2222;
}
}
public void harvestMine(solidObject o){
for(int i = 0; i < selectedUnits.length; i++){
if(selectedUnits[i] != null){
if(selectedUnits[i].teamNo == 0 && (selectedUnits[i].type == 2 || selectedUnits[i].type == 105)){ //must be a harvester/factory to perform such a move
selectedUnits[i].harvest(o);
theAssetManager.confirmationIconInfo[0] = 1;
theAssetManager.confirmationIconInfo[1] = o.centre.x;
theAssetManager.confirmationIconInfo[2] = o.centre.z;
theAssetManager.confirmationIconInfo[3] = 0xbbbb00;
}
}
}
}
public void returnToRefinery(solidObject o){
for(int i = 0; i < selectedUnits.length; i++){
if(selectedUnits[i] != null){
if(selectedUnits[i].teamNo == 0 && selectedUnits[i].type == 2){ //must be a harvester to perform such a move
selectedUnits[i].returnToRefinery(o);
theAssetManager.confirmationIconInfo[0] = 1;
theAssetManager.confirmationIconInfo[1] = o.centre.x;
theAssetManager.confirmationIconInfo[2] = o.centre.z;
theAssetManager.confirmationIconInfo[3] = 0xbbbb00;
}
}
}
}
public void removeFromOtherGroup(solidObject o, int groupNumber){
for(int i = 0; i < groups.length; i++){
if(i != groupNumber){
for(int j = 0; j < groups[i].length; j++){
if(groups[i][j] == o){
groups[i][j] = null;
break;
}
}
}
}
}
}

842
gui/sideBarManager.java Normal file
View File

@ -0,0 +1,842 @@
package gui;
import core.mainThread;
import entity.*;
//this class handles player's interaction with the sidebar
public class sideBarManager {
public playerCommander pc;
public boolean rightMouseButtonClicked;
public boolean leftMouseButtonClicked;
public boolean cursorInBlock0;
public boolean cursorInBlock1;
public boolean cursorInBlock2;
public boolean cursorInBlock3;
public boolean cursorInBlock4;
public boolean cursorInBlock5;
public boolean cursorInBlock6;
public boolean cursorInBlock7;
public boolean cursorInBlock8;
public boolean onlyFactorySelected;
public boolean factoryRallyOnSameGoldMine;
public int[] sideBarInfo;
public int[] sideBarInfo2;
public sideBarManager(playerCommander pc){
this.pc = pc;
sideBarInfo = new int[9];
sideBarInfo2 = new int[9];
for(int i = 0; i < 9; i ++){
sideBarInfo[i] = -1;
sideBarInfo2[i] = -1;
}
}
public void update(){
//reset sideBarInfo
for(int i = 0; i < 9; i++)
sideBarInfo[i] = -1;
//check selected units;
solidObject[] selectedUnits = pc.selectedUnits;
solidObject selectedObject = null;
int mouseX = inputHandler.mouse_x;
int mouseY = inputHandler.mouse_y;
int x1 = 635; int y1 = 381;
int x2 = 677; int y2 = 425;
int x3 = 722; int y3 = 468;
int x4 = 766; int y4 = 509;
if(mouseX > x1 && mouseX < x2 && mouseY > y1 && mouseY < y2){
cursorInBlock0 = true;
}else if(mouseX > x2 && mouseX < x3 && mouseY > y1 && mouseY < y2){
cursorInBlock1 = true;
}else if(mouseX > x3 && mouseX < x4 && mouseY > y1 && mouseY < y2){
cursorInBlock2 = true;
}else if(mouseX > x1 && mouseX < x2 && mouseY > y2 && mouseY < y3){
cursorInBlock3 = true;
}else if(mouseX > x2 && mouseX < x3 && mouseY > y2 && mouseY < y3){
cursorInBlock4 = true;
}else if(mouseX > x3 && mouseX < x4 && mouseY > y2 && mouseY < y3){
cursorInBlock5 = true;
}else if(mouseX > x1 && mouseX < x2 && mouseY > y3 && mouseY < y4){
cursorInBlock6 = true;
}else if(mouseX > x2 && mouseX < x3 && mouseY > y3 && mouseY < y4){
cursorInBlock7 = true;
}else if(mouseX > x3 && mouseX < x4 && mouseY > y3 && mouseY < y4){
cursorInBlock8 = true;
}
//side bar will be interactive only if the selected units are the same type
for(int i = 0; i < selectedUnits.length;i++){
if(selectedUnits[i] != null && selectedUnits[i].teamNo == 0){
if(selectedObject == null){
selectedObject = selectedUnits[i];
}else{
if(selectedObject.type != selectedUnits[i].type){
selectedObject = null;
break;
}
}
}
if(selectedUnits[i] != null && selectedUnits[i].teamNo != 0){
selectedObject = null;
break;
}
}
//check if any building is selected
boolean buildingSelected = false;
onlyFactorySelected = false;
for(int i = 0; i < selectedUnits.length;i++){
if(selectedUnits[i] != null&& selectedUnits[i].teamNo == 0){
if(selectedUnits[i].type > 100 && selectedUnits[i].type != 103){
buildingSelected = true;
}else{
buildingSelected = false;
}
}
}
//give the player option to repair, if only building(s) are selected
if(buildingSelected){
if(cursorInBlock8 && leftMouseButtonClicked){
for(int i = 0; i < selectedUnits.length;i++)
if(selectedUnits[i] != null&& selectedUnits[i].teamNo == 0)
if(selectedUnits[i].type > 100 && selectedUnits[i].type != 103)
selectedUnits[i].isRepairing = true;
}
if(cursorInBlock8 && rightMouseButtonClicked){
for(int i = 0; i < selectedUnits.length;i++)
if(selectedUnits[i] != null&& selectedUnits[i].teamNo == 0)
if(selectedUnits[i].type > 100 && selectedUnits[i].type != 103)
selectedUnits[i].isRepairing = false;
}
int displayInfo = 0;
if(cursorInBlock8){
displayInfo = 13;
}
boolean showAutoRepairMark = true;
for(int i = 0; i < selectedUnits.length;i++)
if(selectedUnits[i] != null&& selectedUnits[i].teamNo == 0)
if(selectedUnits[i].type > 100 && selectedUnits[i].type != 103 && selectedUnits[i].isRepairing == false)
showAutoRepairMark = false;
if(showAutoRepairMark)
sideBarInfo[8] = displayInfo << 24 | 14 << 16 | 255 << 8 | 32;
else
sideBarInfo[8] = displayInfo << 24 | 14 << 16 | 255 << 8 | 16;
}
if(selectedObject != null){
//handle construction Vehicle side bar interaction
if(selectedObject.type == 3){
boolean constructionVehicleCanBeDeployed = false;
for(int i = 0; i < selectedUnits.length;i++){
if(selectedUnits[i] != null){
constructionVehicle cv = (constructionVehicle)selectedUnits[i];
if(cv.canBeDeployed()){
constructionVehicleCanBeDeployed = true;
if(cursorInBlock0 && leftMouseButtonClicked){
cv.expand();
}
}
}
}
int displayInfo = 0;
if(cursorInBlock0){
displayInfo = 2;
}
if(constructionVehicleCanBeDeployed){
// display info texture progress text
sideBarInfo[0] = displayInfo << 24 | 0 << 16 | 240 << 8 | 0;
}else{
sideBarInfo[0] = displayInfo << 24 | 0 << 16 | 0 << 8 | 0;
}
}
//handle factory side bar interaction
if(selectedObject.type == 105){
onlyFactorySelected = true;
factoryRallyOnSameGoldMine = true;
boolean firstFactory = true;
goldMine o = null;
for(int i = 0; i < selectedUnits.length;i++){
if(selectedUnits[i] != null){
factory f = (factory)(selectedUnits[i]);
if(firstFactory){
o = f.targetGoldMine;
firstFactory = false;
}else{
if(o != f.targetGoldMine)
factoryRallyOnSameGoldMine = false;
break;
}
}
}
//can interact with one than 1 factory at a time
if(mainThread.pc.numberOfSelectedUnits != 0){
factory f = null;
for(int i = 0; i < selectedUnits.length;i++){
if(selectedUnits[i] != null){
f = (factory)selectedUnits[i];
//handle light tank building progress and display info
if(f.canBuildLightTank){
//start building
if(cursorInBlock0 && leftMouseButtonClicked){
f.buildLightTank();
}
//cancel buidling
if(cursorInBlock0 && rightMouseButtonClicked){
f.cancelItemFromProductionQueue(f.lightTankType);
}
//display info
int displayInfo = 0;
if(cursorInBlock0){
displayInfo = 5;
}
sideBarInfo[0] = displayInfo << 24 | 6 << 16 | f.lightTankProgress << 8 | (f.numOfLightTankOnQueue + 100);
}
//handle rocket tank building progress and display info
if(f.canBuildRocketTank){
//start building
if(cursorInBlock1 && leftMouseButtonClicked){
f.buildRocketTank();
}
//cancel buidling
if(cursorInBlock1 && rightMouseButtonClicked){
f.cancelItemFromProductionQueue(f.rocketTankType);
}
//display info
int displayInfo = 0;
if(cursorInBlock1){
displayInfo = 6;
}
sideBarInfo[1] = displayInfo << 24 | 7 << 16 | f.rocketTankProgress << 8 | (f.numOfRocketTankOnQueue + 100);
}
//handle harvester building progress and display info
if(f.canBuildHarvester){
//start building
if(cursorInBlock2 && leftMouseButtonClicked){
f.buildHarvester();
}
//cancel buidling
if(cursorInBlock2 && rightMouseButtonClicked){
f.cancelItemFromProductionQueue(f.harvesterType);
}
//display info
int displayInfo = 0;
if(cursorInBlock2){
displayInfo = 7;
}
sideBarInfo[2] = displayInfo << 24 | 8 << 16 | f.harvesterProgress << 8 | (f.numOfHarvesterOnQueue + 100);
}
//handle drone building progress and display info
if(f.canBuildDrone){
//start building
if(cursorInBlock3 && leftMouseButtonClicked){
f.buildDrone();
}
//cancel buidling
if(cursorInBlock3 && rightMouseButtonClicked){
f.cancelItemFromProductionQueue(f.droneType);
}
//display info
int displayInfo = 0;
if(cursorInBlock3){
displayInfo = 8;
}
if(f.numOfDrones == 3){
sideBarInfo[3] = displayInfo << 24 | 9 << 16 | 0 << 8 | (f.numOfDroneOnQueue + 100);
}else{
sideBarInfo[3] = displayInfo << 24 | 9 << 16 | f.droneProgress << 8 | (f.numOfDroneOnQueue + 100);
}
}
//handle MCV building progress and display info
if(f.canBuildMCV){
//start building
if(cursorInBlock5 && leftMouseButtonClicked){
f.buildMCV();
}
//cancel buidling
if(cursorInBlock5 && rightMouseButtonClicked){
f.cancelItemFromProductionQueue(f.MCVType);
}
//display info
int displayInfo = 0;
if(cursorInBlock5){
displayInfo = 10;
}
sideBarInfo[5] = displayInfo << 24 | 11 << 16 | f.MCVProgress << 8 | (f.numOfMCVOnQueue + 100);
}
//handle stealth building progress and display info
if(f.canBuildStealthTank){
//start building
if(cursorInBlock4 && leftMouseButtonClicked){
f.buildStealthTank();
}
//cancel buidling
if(cursorInBlock4 && rightMouseButtonClicked){
f.cancelItemFromProductionQueue(f.stealthTankType);
}
//display info
int displayInfo = 0;
if(cursorInBlock4){
displayInfo = 11;
}
sideBarInfo[4] = displayInfo << 24 | 12 << 16 | f.stealthTankProgress << 8 | (f.numOfStealthTankOnQueue + 100);
}
//handle heavy tank building progress and display info
if(f.canBuildHeavyTank){
//start building
if(cursorInBlock6 && leftMouseButtonClicked){
f.buildHeavyTank();
}
//cancel buidling
if(cursorInBlock6 && rightMouseButtonClicked){
f.cancelItemFromProductionQueue(f.heavyTankType);
}
//display info
int displayInfo = 0;
if(cursorInBlock6){
displayInfo = 19;
}
sideBarInfo[6] = displayInfo << 24 | 19 << 16 | f.heavyTankProgress << 8 | (f.numOfHeavyTankOnQueue + 100);
}
}
}
}
}
//handle missile turret side bar interaction
if(selectedObject.type == 199){
if(communicationCenter.rapidfireResearched_player){
if(cursorInBlock5 && leftMouseButtonClicked){
for(int i = 0; i < selectedUnits.length;i++)
if(selectedUnits[i] != null&& selectedUnits[i].teamNo == 0)
if(selectedUnits[i].type == 199){
missileTurret o = (missileTurret)selectedUnits[i];
if(o.overCharge == false){
o.overCharge = true;
mainThread.pc.theBaseInfo.numberOfOverChargedMissileTurret++;
}
}
}
if(cursorInBlock5 && rightMouseButtonClicked){
for(int i = 0; i < selectedUnits.length;i++)
if(selectedUnits[i] != null&& selectedUnits[i].teamNo == 0)
if(selectedUnits[i].type == 199){
missileTurret o = (missileTurret)selectedUnits[i];
if(o.overCharge == true){
o.overCharge = false;
mainThread.pc.theBaseInfo.numberOfOverChargedMissileTurret--;
}
}
}
//display info
int displayInfo = 0;
if(cursorInBlock5){
displayInfo = 17;
}
boolean showRapidfireMark = true;
for(int i = 0; i < selectedUnits.length;i++){
if(selectedUnits[i] != null&& selectedUnits[i].teamNo == 0){
if(selectedUnits[i].type == 199){
missileTurret o = (missileTurret)selectedUnits[i];
if(!o.overCharge)
showRapidfireMark = false;
}
}
}
if(showRapidfireMark)
sideBarInfo[5] = displayInfo << 24 | 17 << 16 | 255 << 8 | 32;
else
sideBarInfo[5] = displayInfo << 24 | 17 << 16 | 255 << 8 | 16;
}
}
//handle communication center side bar interaction
if(selectedObject.type == 106){
//handle harvester speed research
if(!communicationCenter.harvesterSpeedResearched_player){
//start researching
if(cursorInBlock0 && leftMouseButtonClicked && communicationCenter.harvesterSpeedResearchProgress_player == 255){
communicationCenter.researchHarvesterSpeed(0);
}
//cancel researching
if(cursorInBlock0 && rightMouseButtonClicked && communicationCenter.harvesterSpeedResearchProgress_player != 255 && communicationCenter.harvesterSpeedResearchProgress_player != 254){
communicationCenter.cancelResearch(0);
}
//display info
int displayInfo = 0;
if(cursorInBlock0){
displayInfo = 15;
}
sideBarInfo[0] = displayInfo << 24 | 16 << 16 | communicationCenter.harvesterSpeedResearchProgress_player << 8 | 0;
}
//handle rapid fire research
if(!communicationCenter.rapidfireResearched_player){
//start researching
if(cursorInBlock1 && leftMouseButtonClicked && communicationCenter.rapidfireResearchProgress_player == 255){
communicationCenter.researchRapidfire(0);
}
//cancel researching
if(cursorInBlock1 && rightMouseButtonClicked && communicationCenter.rapidfireResearchProgress_player != 255 && communicationCenter.rapidfireResearchProgress_player != 254){
communicationCenter.cancelResearch(0);
}
//display info
int displayInfo = 0;
if(cursorInBlock1){
displayInfo = 16;
}
sideBarInfo[1] = displayInfo << 24 | 17 << 16 | communicationCenter.rapidfireResearchProgress_player << 8 | 0;
}
}
//handle tech center side bar interaction
if(selectedObject.type == 107){
//handle light tank range research
if(!techCenter.lightTankResearched_player){
if(cursorInBlock0 && leftMouseButtonClicked && techCenter.lightTankResearchProgress_player == 255){
techCenter.researchLightTank(0);
}
//cancel researching
if(cursorInBlock0 && rightMouseButtonClicked && techCenter.lightTankResearchProgress_player != 255 && techCenter.lightTankResearchProgress_player != 254){
techCenter.cancelResearch(0);
}
//display info
int displayInfo = 0;
if(cursorInBlock0){
displayInfo = 20;
}
sideBarInfo[0] = displayInfo << 24 | 20 << 16 | techCenter.lightTankResearchProgress_player << 8 | 0;
}
//handle rocket tank damage research
if(!techCenter.rocketTankResearched_player){
if(cursorInBlock1 && leftMouseButtonClicked && techCenter.rocketTankResearchProgress_player == 255){
techCenter.researchRocketTank(0);
}
//cancel researching
if(cursorInBlock1 && rightMouseButtonClicked && techCenter.rocketTankResearchProgress_player != 255 && techCenter.rocketTankResearchProgress_player != 254){
techCenter.cancelResearch(0);
}
//display info
int displayInfo = 0;
if(cursorInBlock1){
displayInfo = 21;
}
sideBarInfo[1] = displayInfo << 24 | 21 << 16 | techCenter.rocketTankResearchProgress_player << 8 | 0;
}
//handle stealth multishot research
if(!techCenter.stealthTankResearched_player){
if(cursorInBlock2 && leftMouseButtonClicked && techCenter.stealthTankResearchProgress_player == 255){
techCenter.researchStealthTank(0);
}
//cancel researching
if(cursorInBlock2 && rightMouseButtonClicked && techCenter.stealthTankResearchProgress_player != 255 && techCenter.stealthTankResearchProgress_player != 254){
techCenter.cancelResearch(0);
}
//display info
int displayInfo = 0;
if(cursorInBlock2){
displayInfo = 22;
}
sideBarInfo[2] = displayInfo << 24 | 22 << 16 | techCenter.stealthTankResearchProgress_player << 8 | 0;
}
//handle heavy tank self repair research
if(!techCenter.heavyTankResearched_player){
if(cursorInBlock3 && leftMouseButtonClicked && techCenter.heavyTankResearchProgress_player == 255){
techCenter.researchHeavyTank(0);
}
//cancel researching
if(cursorInBlock3 && rightMouseButtonClicked && techCenter.heavyTankResearchProgress_player != 255 && techCenter.heavyTankResearchProgress_player != 254){
techCenter.cancelResearch(0);
}
//display info
int displayInfo = 0;
if(cursorInBlock3){
displayInfo = 23;
}
sideBarInfo[3] = displayInfo << 24 | 23 << 16 | techCenter.heavyTankResearchProgress_player << 8 | 0;
}
}
//handle construction yard side bar interaction
if(selectedObject.type == 104){
//can only interact with one construction yard at a time
if(mainThread.pc.numberOfSelectedUnits == 1){
constructionYard cy = null;
for(int i = 0; i < selectedUnits.length;i++){
if(selectedUnits[i] != null){
cy = (constructionYard)selectedUnits[i];
break;
}
}
//handle power plant building progress and display info
if(cy.canBuildPowerPlant){
//start building
if(cursorInBlock0 && leftMouseButtonClicked && cy.powerPlantProgress == 255 && !mainThread.pc.isDeployingBuilding){
cy.buildPowerPlant();
}
if(cursorInBlock0 && leftMouseButtonClicked && cy.powerPlantProgress == 240){
cy.needToDrawDeploymentGrid = true;
mainThread.pc.isDeployingBuilding = true;
mainThread.pc.selectedConstructionYard = cy;
}
//cancel buidling
if(cursorInBlock0 && rightMouseButtonClicked && cy.powerPlantProgress != 255 && cy.powerPlantProgress != 254){
mainThread.pc.isDeployingBuilding = false;
mainThread.pc.selectedConstructionYard = null;
cy.needToDrawDeploymentGrid = false;
cy.cancelBuilding();
}
//display info
int displayInfo = 0;
if(cursorInBlock0){
displayInfo = 1;
}
sideBarInfo[0] = displayInfo << 24 | 1 << 16 | cy.powerPlantProgress << 8 | (cy.powerPlantProgress/240 + cy.powerPlantProgress/240 * cy.powerPlantProgress%240);
}
//handle refinery building progress and display info
if(cy.canBuildRefinery){
//start building
if(cursorInBlock1 && leftMouseButtonClicked && cy.refineryProgress == 255 && !mainThread.pc.isDeployingBuilding){
cy.buildRefinery();
}
if(cursorInBlock1 && leftMouseButtonClicked && cy.refineryProgress == 240){
cy.needToDrawDeploymentGrid = true;
mainThread.pc.isDeployingBuilding = true;
mainThread.pc.selectedConstructionYard = cy;
}
//cancel buidling
if(cursorInBlock1 && rightMouseButtonClicked && cy.refineryProgress != 255 && cy.refineryProgress != 254){
mainThread.pc.isDeployingBuilding = false;
mainThread.pc.selectedConstructionYard = null;
cy.needToDrawDeploymentGrid = false;
cy.cancelBuilding();
}
//display info
int displayInfo = 0;
if(cursorInBlock1){
displayInfo = 3;
}
sideBarInfo[1] = displayInfo << 24 | 2 << 16 | cy.refineryProgress << 8 | (cy.refineryProgress/240 + cy.refineryProgress/240 * cy.refineryProgress%240);
}
//handle factory building progress and display info
if(cy.canBuildFactory){
//start building
if(cursorInBlock2 && leftMouseButtonClicked && cy.factoryProgress == 255 && !mainThread.pc.isDeployingBuilding){
cy.buildFactory();
}
if(cursorInBlock2 && leftMouseButtonClicked && cy.factoryProgress == 240){
cy.needToDrawDeploymentGrid = true;
mainThread.pc.isDeployingBuilding = true;
mainThread.pc.selectedConstructionYard = cy;
}
//cancel buidling
if(cursorInBlock2 && rightMouseButtonClicked && cy.factoryProgress != 255 && cy.factoryProgress != 254){
mainThread.pc.isDeployingBuilding = false;
mainThread.pc.selectedConstructionYard = null;
cy.needToDrawDeploymentGrid = false;
cy.cancelBuilding();
}
//display info
int displayInfo = 0;
if(cursorInBlock2){
displayInfo = 4;
}
sideBarInfo[2] = displayInfo << 24 | 5 << 16 | cy.factoryProgress << 8 | (cy.factoryProgress/240 + cy.factoryProgress/240 * cy.factoryProgress%240);
}
//handle communication center building progress and display info
if(cy.canBuildCommunicationCenter){
//start building
if(cursorInBlock3 && leftMouseButtonClicked && cy.communicationCenterProgress == 255 && !mainThread.pc.isDeployingBuilding){
cy.buildCommunicationCentre();
}
if(cursorInBlock3 && leftMouseButtonClicked && cy.communicationCenterProgress == 240){
cy.needToDrawDeploymentGrid = true;
mainThread.pc.isDeployingBuilding = true;
mainThread.pc.selectedConstructionYard = cy;
}
//cancel buidling
if(cursorInBlock3 && rightMouseButtonClicked && cy.communicationCenterProgress != 255 && cy.communicationCenterProgress != 254){
mainThread.pc.isDeployingBuilding = false;
mainThread.pc.selectedConstructionYard = null;
cy.needToDrawDeploymentGrid = false;
cy.cancelBuilding();
}
//display info
int displayInfo = 0;
if(cursorInBlock3){
displayInfo = 9;
}
sideBarInfo[3] = displayInfo << 24 | 10 << 16 | cy.communicationCenterProgress << 8 | (cy.communicationCenterProgress/240 + cy.communicationCenterProgress/240 * cy.communicationCenterProgress%240);
}
//handle turret building process and display info
if(cy.canBuildGunTurret){
//start building
if(cursorInBlock4 && leftMouseButtonClicked && cy.gunTurretProgress == 255 && !mainThread.pc.isDeployingBuilding){
cy.buildGunTurret();
}
if(cursorInBlock4 && leftMouseButtonClicked && cy.gunTurretProgress == 240){
cy.needToDrawDeploymentGrid = true;
mainThread.pc.isDeployingBuilding = true;
mainThread.pc.selectedConstructionYard = cy;
}
//cancel buidling
if(cursorInBlock4 && rightMouseButtonClicked && cy.gunTurretProgress != 255 && cy.gunTurretProgress != 254){
mainThread.pc.isDeployingBuilding = false;
mainThread.pc.selectedConstructionYard = null;
cy.needToDrawDeploymentGrid = false;
cy.cancelBuilding();
}
//display info
int displayInfo = 0;
if(cursorInBlock4){
displayInfo = 12;
}
sideBarInfo[4] = displayInfo << 24 | 13 << 16 | cy.gunTurretProgress << 8 | (cy.gunTurretProgress/240 + cy.gunTurretProgress/240 * cy.gunTurretProgress%240);
}
//handle missile turret building process and display info
if(cy.canBuildMissileTurret){
//start building
if(cursorInBlock5 && leftMouseButtonClicked && cy.missileTurretProgress == 255 && !mainThread.pc.isDeployingBuilding){
cy.buildMissileTurret();
}
if(cursorInBlock5 && leftMouseButtonClicked && cy.missileTurretProgress == 240){
cy.needToDrawDeploymentGrid = true;
mainThread.pc.isDeployingBuilding = true;
mainThread.pc.selectedConstructionYard = cy;
}
//cancel buidling
if(cursorInBlock5 && rightMouseButtonClicked && cy.missileTurretProgress != 255 && cy.missileTurretProgress != 254){
mainThread.pc.isDeployingBuilding = false;
mainThread.pc.selectedConstructionYard = null;
cy.needToDrawDeploymentGrid = false;
cy.cancelBuilding();
}
//display info
int displayInfo = 0;
if(cursorInBlock5){
displayInfo = 14;
}
sideBarInfo[5] = displayInfo << 24 | 15 << 16 | cy.missileTurretProgress << 8 | (cy.missileTurretProgress/240 + cy.missileTurretProgress/240 * cy.missileTurretProgress%240);
}
//handle tech center building process and display info
if(cy.canBuildTechCenter){
//start building
if(cursorInBlock6 && leftMouseButtonClicked && cy.techCenterProgress == 255 && !mainThread.pc.isDeployingBuilding){
cy.buildTechCenter();
}
if(cursorInBlock6 && leftMouseButtonClicked && cy.techCenterProgress == 240){
cy.needToDrawDeploymentGrid = true;
mainThread.pc.isDeployingBuilding = true;
mainThread.pc.selectedConstructionYard = cy;
}
//cancel buidling
if(cursorInBlock6 && rightMouseButtonClicked && cy.techCenterProgress != 255 && cy.techCenterProgress != 254){
mainThread.pc.isDeployingBuilding = false;
mainThread.pc.selectedConstructionYard = null;
cy.needToDrawDeploymentGrid = false;
cy.cancelBuilding();
}
//display info
int displayInfo = 0;
if(cursorInBlock6){
displayInfo = 18;
}
sideBarInfo[6] = displayInfo << 24 | 18 << 16 | cy.techCenterProgress << 8 | (cy.techCenterProgress/240 + cy.techCenterProgress/240 * cy.techCenterProgress%240);
}
}
}
}
rightMouseButtonClicked = false;
leftMouseButtonClicked = false;
cursorInBlock0 = false;
cursorInBlock1 = false;
cursorInBlock2 = false;
cursorInBlock3 = false;
cursorInBlock4 = false;
cursorInBlock5 = false;
cursorInBlock6 = false;
cursorInBlock7 = false;
cursorInBlock8 = false;
}
public void swapResources(){
int[] info;
info = sideBarInfo;
sideBarInfo = sideBarInfo2;
sideBarInfo2 = info;
}
}

BIN
images/1.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 261 KiB

BIN
images/10.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

BIN
images/11.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
images/12.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

BIN
images/13.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

BIN
images/14.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
images/15.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 557 B

BIN
images/16.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 869 B

BIN
images/17.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

BIN
images/18.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
images/19.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

BIN
images/2.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
images/20.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

BIN
images/21.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

BIN
images/22.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

BIN
images/23.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

BIN
images/24.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
images/25.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

BIN
images/26.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 978 B

BIN
images/27.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

BIN
images/28.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

BIN
images/29.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

BIN
images/3.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
images/30.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
images/31.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

BIN
images/32.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

BIN
images/33.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

BIN
images/34.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

BIN
images/35.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

BIN
images/36.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

BIN
images/37.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

BIN
images/38.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

BIN
images/39.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

BIN
images/4.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

BIN
images/40.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
images/41.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Some files were not shown because too many files have changed in this diff Show More