XNA Game Programming: Spawning Enemies in a circle (Code) - random

Could someone please give me some direction on how to spawn enemies in a circle (XNA Programming)?
I want the enemies to randomly spawn along the circumference of a circle that is just outside the bounds of the window. I want them to move in straight lines through the center of the window and out to the opposite side of where they started (or as close to that as possible).
Ideally this would create an environment where enemies are randomly coming across from seemingly all directions.
Here's my enemy ("Baddies") class so far. I handle the position of in the SetupTraveling game state. What I'm doing isn't really working, so any help would be greatly appreciated.
public class Baddies : Sprite
{
public enum State
{
Inactive,
SetupTraveling,
Traveling,
SetupInactive,
}
public State CurrentState
{
set
{
currentState = value;
framesInStateCount = 0;
}
get
{
return currentState;
}
}
int framesInStateCount = 0;
State currentState = State.SetupInactive;
public Baddies()
{
Image = getImage("Bad");
Scale = .2f;
Rotation = 0f;
DRotation = .05f;
TurnedOn = true;
BounceOn = false;
WrapOn = false;
Gravity = 0f;
}
public override void Update()
{
framesInStateCount++;
switch (currentState)
{
case State.Inactive:
if (RandOneIn(100)) CurrentState = State.SetupTraveling;
break;
case State.SetupTraveling:
PositionX = ((Game1.vGameWidth + 100)/2) * (float)Math.Cos(Glob.rnd(0.0, 2.0 * Math.PI));
PositionY = ((Game1.vGameHeight + 100)/2) * (float)Math.Sin(Glob.rnd(0.0, 2.0 * Math.PI));
DDPositionY = 0;
DPositionY = -1;
DPositionX = 1f;
DDPositionX = 0f;
CurrentState = State.Traveling;
break;
case State.Traveling:
if (PositionX > Game1.vGameWidth + (Image.Width / 2) * Scale)
{
currentState = State.SetupInactive;
}
if (PositionX < -500f - (Image.Width / 2) * Scale)
{
currentState = State.SetupInactive;
}
if (PositionY > Game1.vGameHeight + (Image.Height / 2) * Scale)
{
currentState = State.SetupInactive;
}
if (PositionY < 0 - (Image.Height / 2) * Scale)
{
currentState = State.SetupInactive;
}
break;
case State.SetupInactive:
PositionX = -300f;
DPositionX = 0f;
DPositionY = 0f;
DDPositionX = 0f;
CurrentState = State.Inactive;
break;
}
base.Update();
}
}

Other approach with trigonometry:
Decide what is your circle radius... usually is:
raqdius = sqrt(Viewport.Size.Width^2 + Viewport.Size.Height^2) / 2;
Generate a random angle
angle = (float) Random.NextDouble() * MathHelper.PI * 2;
Your coordinates are
x = ViewPort.Center.X + radius * Math.Cos(angle);
y = ViewPort.Center.Y + radius * Math.Sin(angle);

How about this:
Decide what the raidius of your circle is, call it r
generate an X value from [-r, r]
Y = sqrt(r^2 - X^2)
randomly set Y to Y or -Y. Your cooridinates would be X,Y

Related

Three.JS - Object rotation

we have following function to create object wall:
function placeWorkareaWithSlope(points, waDetail, drawLine = true) {
const workareaHeight = Number(waDetail.WorkareaHeight) || 10;
const workareaParapet = Number(waDetail.WorkareaParapet) || 3;
// Different color wall for workarea
drawWallForWorkareaWithSlope(points, workareaHeight, waDetail);
drawWallBoxForWorkareaWithSlope(points, workareaHeight, waDetail);
// Convert points array to accrding to 3D space Quadrant
const convertedPoints = convertTo3dQuadrant(points);
const shape = [];
for (let i = 0; i < convertedPoints.length; i++) {
const e = convertedPoints[i];
shape.push(new THREE.Vector2(e.x, e.y));
}
const workareaShape = new THREE.Shape(shape);
const extrusionSettings = {
steps: 1,
depth: workareaHeight,
bevelEnabled: false,
};
const workareaGeometry = new THREE.ExtrudeGeometry(workareaShape, extrusionSettings);
workareaGeometry.computeVertexNormals();
workareaGeometry.computeFaceNormals();
const workarea = new THREE.Mesh(workareaGeometry, workareaMaterial);
workarea.rotation.x = -THREE.Math.degToRad(90);
//added by kd to define slope angle
objRotation(points, waDetail, workarea);
//end kd
workarea.receiveShadow = isRenderShaodw;
workarea.castShadow = isRenderWorkareaShadow;
scene.add(workarea);
// DrawLines
if (drawLine && workarea && workarea.geometry) {
const lineGeo = new THREE.EdgesGeometry(workarea.geometry);
const wireframe = new THREE.LineSegments(lineGeo, workareaLineMaterial);
wireframe.renderOrder = 1;
workarea.add(wireframe);
}
}
once we create wall over scene after that we rotate it base on slope provided with objRotation function with obj.rotation.y but when we rotate it at that movement object change its place, basically we require object should be there with world axis
following is object rotation function :
function objRotation(points, waDetail, obj) {
const Point1 = points[0];
const Point2 = points[1];
const Point3 = points[2];
const Point4 = points[3];
const slopeAngle = Number(waDetail.Angle) || 0;
if (waDetail.SlopeDirection == "P1 to P2") {
xDiff = Point1.x - Point2.x;
yDiff = Point1.y - Point2.y;
}
if (waDetail.SlopeDirection == "P2 to P3") {
xDiff = Point2.x - Point3.x;
yDiff = Point2.y - Point3.y;
}
if (waDetail.SlopeDirection == "P3 to P4") {
xDiff = Point3.x - Point4.x;
yDiff = Point3.y - Point4.y;
}
if (waDetail.SlopeDirection == "P4 to P1") {
xDiff = Point4.x - Point1.x;
yDiff = Point4.y - Point1.y;
}
if (Math.abs(xDiff) > Math.abs(yDiff)) {
if (obj.rotation.x > 0) {
if (xDiff > 0)
obj.rotation.y += THREE.Math.degToRad(slopeAngle);
else
obj.rotation.y -= THREE.Math.degToRad(slopeAngle);
}
else {
if (xDiff > 0)
obj.rotation.y -= THREE.Math.degToRad(slopeAngle);
else
obj.rotation.y += THREE.Math.degToRad(slopeAngle);
}
} else {
if (yDiff<0)
obj.rotation.x += THREE.Math.degToRad(slopeAngle);
else
obj.rotation.x -= THREE.Math.degToRad(slopeAngle);
}
}
So for the above issue, can someone guide me?
The wall created by the code with height and width provided by system and it rotates 90 degrees to setup over map surface but after that we have a requirement to slope its base on an angle so we added one more rotation there with provided slope angle by user. But when this slope angle rotation applied to object the object change its height base on camera left or right distance. We require the object should be same place there as before after rotation.

Implementing circle progress bar in libGDX

I want to create a circle progress bar, that will look like this using libgdx library. For now on I've created simple horizontal progressbar using different Images as layers overlapping themselfs and one of them resizing to simulate progress. I found this example, how to draw circle progress bar, but I don't understand how to use this implementation and how can I handle it. The textureRegion in constructor is the progress indicator? and I could not find the method responsible to set the actual progress.
EDIT: I've made my solution basic on this implementation. I put 3 layers which overlapping themselfs and whenever the middle layer swipe's the progress is showed. But Ive have a problem: whenever I try to resize my ProgressCircle instance it move down below the background layer.
public class ProgressCircle extends Image {
public enum IntersectAt {
NONE, TOP, BOTTOM, LEFT, RIGHT;
}
TextureRegion texture;
PolygonSpriteBatch polyBatch;
Vector2 center;
Vector2 centerTop;
Vector2 leftTop;
Vector2 leftBottom;
Vector2 rightBottom;
Vector2 rightTop;
Vector2 progressPoint;
float[] fv;
IntersectAt intersectAt;
private float PROGRESS_WIDTH=0f;
private float PROGRESS_HEIGHT=0f;
private float posX,posY;
public ProgressCircle(TextureRegion region, PolygonSpriteBatch polyBatch,float width,float height,float posX,float posY) {
super(region);
PROGRESS_WIDTH=width;
PROGRESS_HEIGHT=height;
this.posX=posX;
this.posY=posY;
this.texture = region;
this.polyBatch = polyBatch;
center = new Vector2(this.getWidth() / 2, this.getHeight() / 2);
centerTop = new Vector2(this.getWidth() / 2, this.getHeight());
leftTop = new Vector2(0, this.getHeight());
leftBottom = new Vector2(0, 0);
rightBottom = new Vector2(this.getWidth(), 0);
rightTop = new Vector2(this.getWidth(), this.getHeight());
progressPoint = new Vector2(this.getWidth() / 2, this.getHeight() / 2);
setPercentage(0);
}
private Vector2 IntersectPoint(Vector2 line) {
Vector2 v = new Vector2();
boolean isIntersect;
//check top
isIntersect = Intersector.intersectSegments(leftTop, rightTop, center, line, v);
//check bottom
if (isIntersect) {
intersectAt = IntersectAt.TOP;
return v;
} else
isIntersect = Intersector.intersectSegments(leftBottom, rightBottom, center, line, v);
//check left
if (isIntersect) {
intersectAt = IntersectAt.BOTTOM;
return v;
} else isIntersect = Intersector.intersectSegments(leftTop, leftBottom, center, line, v);
//check bottom
if (isIntersect) {
intersectAt = IntersectAt.LEFT;
return v;
} else isIntersect = Intersector.intersectSegments(rightTop, rightBottom, center, line, v);
if (isIntersect) {
intersectAt = IntersectAt.RIGHT;
return v;
} else {
intersectAt = IntersectAt.NONE;
return null;
}
}
public void setPercentage(float percent) {
//100 % = 360 degree
float angle = convertToRadians(90);
angle -= convertToRadians(percent * 360 / 100);
float len = this.getWidth() > this.getHeight() ? this.getWidth() : this.getHeight();
float dy = (float) (Math.sin(angle) * len);
float dx = (float) (Math.cos(angle) * len);
Vector2 line = new Vector2(center.x + dx, center.y + dy);
Vector2 v = IntersectPoint(line);
if (intersectAt == IntersectAt.TOP) {
if (v.x >= this.getWidth() / 2) {
fv = new float[]{
center.x,
center.y,
centerTop.x,
centerTop.y,
leftTop.x,
leftTop.y,
leftBottom.x,
leftBottom.y,
rightBottom.x,
rightBottom.y,
rightTop.x,
rightTop.y,
v.x,
v.y
};
} else {
fv = new float[]{
center.x,
center.y,
centerTop.x,
centerTop.y,
v.x,
v.y
};
}
} else if (intersectAt == IntersectAt.BOTTOM) {
fv = new float[]{
center.x,
center.y,
centerTop.x,
centerTop.y,
leftTop.x,
leftTop.y,
leftBottom.x,
leftBottom.y,
v.x,
v.y
};
} else if (intersectAt == IntersectAt.LEFT) {
fv = new float[]{
center.x,
center.y,
centerTop.x,
centerTop.y,
leftTop.x,
leftTop.y,
v.x,
v.y
};
} else if (intersectAt == IntersectAt.RIGHT) {
fv = new float[]{
center.x,
center.y,
centerTop.x,
centerTop.y,
leftTop.x,
leftTop.y,
leftBottom.x,
leftBottom.y,
rightBottom.x,
rightBottom.y,
v.x,
v.y
};
} else // if (intersectAt == IntersectAt.NONE)
{
fv = null;
}
}
#Override
public void draw(Batch batch, float parentAlpha) {
if (fv == null) return;
batch.end();
drawMe();
batch.begin();
}
public void drawMe() {
EarClippingTriangulator e = new EarClippingTriangulator();
ShortArray sv = e.computeTriangles(fv);
PolygonRegion polyReg = new PolygonRegion(texture, fv, sv.toArray());
PolygonSprite poly = new PolygonSprite(polyReg);
poly.setSize(PROGRESS_WIDTH,PROGRESS_HEIGHT);
poly.setPosition(posX,posY);
poly.setOrigin(poly.getOriginX(), poly.getOriginY());
poly.setRotation(this.getRotation());
poly.setColor(Color.GREEN);
polyBatch.begin();
poly.draw(polyBatch);
polyBatch.end();
}
float convertToDegrees(float angleInRadians) {
float angleInDegrees = angleInRadians * 57.2957795f;
return angleInDegrees;
}
float convertToRadians(float angleInDegrees) {
float angleInRadians = angleInDegrees * 0.0174532925f;
return angleInRadians;
}
}
and my init function:
ProgressCircle sprite;
private void initCircleProgress() {
Group group = new Group();
Image downBackground = new Image(atlas.findRegion("progressBackground"));
downBackground.setColor(Color.BLUE);
downBackground.setSize(USER_SCREEN_SIZE_WIDTH/5,USER_SCREEN_SIZE_WIDTH/5);
downBackground.setPosition(10,USER_SCREEN_SIZE_HEIGHT-(2*downBackground.getHeight()+20));
sprite = new ProgressCircle(atlas.findRegion("progressBackground"), pbatch,
downBackground.getWidth(),downBackground.getHeight(),downBackground.getX(),downBackground.getY());
sprite.setSize(downBackground.getWidth(),downBackground.getHeight());
sprite.setSize(downBackground.getX(),downBackground.getY());
Image label = new Image(atlas.findRegion("progressBackground"));
label.setSize(downBackground.getWidth()*0.8f,downBackground.getHeight()*0.8f);
label.setPosition(downBackground.getX()+(downBackground.getWidth()-label.getWidth())/2,
downBackground.getY()+(downBackground.getHeight()-label.getHeight())/2);
label.setColor(Color.WHITE);
group.addActor(downBackground);
group.addActor(sprite);
group.addActor(label);
group.setPosition(10,GAME_SIZE_HEIGHT-(group.getHeight()+20));
stage.addActor(group);
}
You need a circular gradient to mask out the desired parts.
Incrementing the masking values over time will result in a circular motion.
As you can see in the link to masking there are several methods to achieve this. A stencil buffer would be a good choice but can result in jaggy edges. Writing your own shader would be perfect but kinda hard if you never wrote a shader. You can also try to parse both pix maps and decide what pixels to draw while looping through both pixmaps. If the masking image and your source have equal texture space you can do this in one loop so it would not be that much slower then a shader and whatever works for you is a good solution, you can always optimize later.

Java FX minigolf game - how to slow down the moving ball

I am beginner and trying to create a simple minigolf game with Java FX.
I built small golfcourse using lines. I get user input about hit strength from the slider and can make a hit using keyboard into 8 different directions.
If I hit for example button H, ball starts to move to right. If slider value was minimum, it moves slowly and if its maximum, it moves very fast.
But I cannot make the movement slow down until it stops.
Any ideas how to do that? My code so far is below.
Thank You in advance!
package sample;
import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Slider;
import javafx.scene.input.KeyCode;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Line;
import javafx.stage.Stage;
public class Main extends Application {
double directionx = 0;
double directiony = 0;
Line line1,line2,line3,line4,line5,line6,line7,line8,line9;
#Override
public void start(Stage primaryStage) throws Exception{
primaryStage.setTitle("Minigolf");
Pane pane = new Pane();
Scene scene = new Scene(pane, 900, 600);
pane.setStyle("-fx-background-color: green");
primaryStage.setScene(scene);
Slider slider = new Slider();
slider.setMin(1);
slider.setMax(10);
slider.setValue(1);
slider.setShowTickLabels(true);
slider.setShowTickMarks(true);
slider.setLayoutX(10);
slider.setLayoutY(10);
Circle ball = new Circle(10);
Circle hole = new Circle(15);
hole.setCenterX(75);
hole.setCenterY(430);
hole.setFill(Color.YELLOW);
ball.setCenterX(100);
ball.setCenterY(300);
// creating golfcourse with lines
line1 = new Line(50,200,500,200);
line2 = new Line(50,350,650,350);
line3 = new Line(50,200,50,350);
line4 = new Line(500,200,500,50);
line5 = new Line(650,350,650,200);
line6 = new Line(500,50,800,50);
line7 = new Line(800,50,800,500);
line8 = new Line(800,500,50,500);
line9 = new Line(50,500,50,350);
pane.getChildren().addAll(slider,ball,hole,line1,line2,line3,line4,line5,line6,line7,line8,line9);
new AnimationTimer() {
#Override
public void handle(long now) {
double ballY = ball.getCenterY();
double newballY = ballY + directiony;
// if ball touches vertical walls
if (ball.getBoundsInParent().intersects(line5.getBoundsInParent())
|| ball.getBoundsInParent().intersects(line3.getBoundsInParent())
|| ball.getBoundsInParent().intersects(line4.getBoundsInParent())
|| ball.getBoundsInParent().intersects(line7.getBoundsInParent())
|| ball.getBoundsInParent().intersects(line9.getBoundsInParent())) {
// changes direction
directionx = directionx * -1;
}
ball.setCenterX(ball.getCenterX() + directionx);
ball.setCenterY(newballY);
// if ball touches horizontal walls
if (ball.getBoundsInParent().intersects(line1.getBoundsInParent())
|| ball.getBoundsInParent().intersects(line2.getBoundsInParent())
|| ball.getBoundsInParent().intersects(line6.getBoundsInParent())
|| ball.getBoundsInParent().intersects(line8.getBoundsInParent())) {
directiony = directiony * -1;
}
// if ball touches hole, then game is over
if (ball.getBoundsInParent().intersects(hole.getBoundsInParent())) {
System.out.println("Game over");
pane.getChildren().removeAll(ball);
}
}
}.start();
// I get the slider value and making array where are 10 different strengts
scene.setOnKeyPressed(event -> {
double b = Math.round(slider.getValue());
b--;
int c = (int) b;
double [] strengts = new double[10];
double k = 0.1;
for (int i = 0; i < strengts.length; i++) {
strengts[i] = k;
k = k + 0.5;
}
// 8 different directions to move the ball
if (event.getCode().equals(KeyCode.H)) {
directionx = directionx + strengts[c];
}
else if(event.getCode().equals(KeyCode.F)) {
directionx = directionx - strengts[c];
}
else if(event.getCode().equals(KeyCode.V)) {
directiony=directiony + strengts[c];
}
else if(event.getCode().equals(KeyCode.T)) {
directiony= directiony - strengts[c];
}
else if(event.getCode().equals(KeyCode.B))
{
directionx = directionx + strengts[c];
directiony = directiony + strengts[c];
}
else if(event.getCode().equals(KeyCode.Y))
{
directionx = directionx + strengts[c];
directiony = directiony - strengts[c];
}
else if(event.getCode().equals(KeyCode.R))
{
directionx = directionx - strengts[c];
directiony = directiony - strengts[c];
}
else if(event.getCode().equals(KeyCode.C))
{
directionx = directionx - strengts[c];
directiony = directiony + strengts[c];
}
});
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Just use physics for friction. Assume for every frame the speed (v) remains constant.
Energy of a ball (mass m):
E = 0.5 * m * v²
Work for friction based on distance (s) traveled and a friction constant μ
ΔE = s * m * μ = Δt * v * m * μ
The new energy is E - ΔE which you can use with the first formula to calculate the new speed v':
0.5 * m * v'² = 0.5 * m * v² - s * m * μ
v'² = v² - s * μ * 2
v' = sqrt(v² - s * μ * 2)
The above assumes the ground is flat.
This allows you to decrease the speed like this:
#Override
public void start(Stage primaryStage) {
Point2D direction = new Point2D(1, 1).normalize();
Circle c = new Circle(10, 10, 10);
Timeline tl = new Timeline();
tl.getKeyFrames().setAll(new KeyFrame(Duration.seconds(1 / 60d), new EventHandler() {
double speed = 3;
double friction = 0.02;
#Override
public void handle(Event event) {
double distance = speed;
Point2D movement = direction.multiply(distance);
c.setCenterX(c.getCenterX() + movement.getX());
c.setCenterY(c.getCenterY() + movement.getY());
double energyBefore = speed * speed;
double energyLost = distance * friction;
if (energyLost > energyBefore) {
tl.stop();
speed = 0;
System.out.println("stopped");
} else {
speed = Math.sqrt(energyBefore - energyLost);
}
}
}));
tl.setCycleCount(Animation.INDEFINITE);
Pane root = new Pane();
root.getChildren().add(c);
Scene scene = new Scene(root, 400, 400);
scene.setOnMouseClicked(evt -> tl.play());
primaryStage.setScene(scene);
primaryStage.show();
}
Thank You for the reply, but as a beginner I found now by myself simpler solution.
I just add 4 if-statements as follows:
if (directionx>0) {
directionx = directionx - 0.01;
}
if(directionx<0){
directionx = directionx + 0.01;
}
if(directiony>0) {
directiony = directiony - 0.01;
}
if(directiony<0) {
directiony = directiony + 0.01;
}
Perhaps the in real physically its somehow wrong, but it looks quite real for me.

Making falling objects come at random angles in AS3

I am making a missile defense type of game and am trying to get the missiles to fall at random angles. I also need the bullet image to turn at the angle I am shooting at. I am very unfamiliar with angles in AS3 so I need some help.
Code:
import spark.components.Image;
public var missiles:Array;
public var bullets:Array;
public var playerLife:Number;
public var targetX:Number;
public var targetY:Number;
public function init():void {
startGame();
}
public function onEnterFrame(e:Event):void {
if(Math.random() <.05 ){
//make a new missle
var newMissile:Image = new Image();
//draw to is
newMissile.source = "assets/missileDown.jpg";
//position it
newMissile.x = Math.random() * stage.stageWidth;
//animate it
newMissile.addEventListener(Event.ENTER_FRAME, onMissileEnterFrame);
//add it to missle array
missiles.push(newMissile);
//add it to the screen
gameGroup.addElement(newMissile);
}
}
public function startGame():void {
//makes new arrays
//gets rid of old arrays
missiles = new Array();
bullets = new Array();
//set player life
playerLife = 5;
//show player life
playerHealth.text = String(playerLife);
//add animation and mouse interation
this.addEventListener(Event.ENTER_FRAME, onEnterFrame);
stage.addEventListener(MouseEvent.CLICK, fireWeapon);
//set game over alpha
gameEnd.alpha = 0;
reset.alpha = 0;
//set game start alpha
playerHealth.alpha = 1;
healthLabel.alpha = 1;
}
//updates the missle
public function onMissileEnterFrame(e:Event):void {
//reference to target
var targetMissile:Image = Image(e.currentTarget);
//move missle down
targetMissile.y += 10;
//if missle has gone too far, remove it and player loses life
if(targetMissile.y > stage.stageHeight) {
playerLife --;
removeMissile(targetMissile);
//show player life
playerHealth.text = String(playerLife);
}
//if player is dead, game over
if(playerLife <= 0) {
gameOver();
}
}
//update bullet
public function onBulletEnterFrame(e:Event):void {
//get reference to bullet
var thisBullet:Bullet = Bullet(e.currentTarget);
//animate towards point..
//calculate difference between current position and desired position
var diffX:Number = thisBullet.targX - thisBullet.x;
var diffY:Number = thisBullet.targY - thisBullet.y;
//move 10% of difference closer
thisBullet.x += diffX * .1;
thisBullet.y += diffY * .1;
//chekc for overlap between bullet and missles
for(var i:Number = 0; i < missiles.length; i++) {
//if they do overlap, remove missle
if( thisBullet.hitTestObject(missiles[i]) ) {
removeMissile(missiles[i]);
removeBullet(thisBullet);
break;
}
}
//if we're 'close enough' to the target position, remove bullet
if(Math.abs(diffX) < 10 && Math.abs(diffY) < 10) {
removeBullet(thisBullet);
}
}
//gets rid of a missle
public function removeMissile(targetMissile:Image):void {
//removes the missle from the missiles array
for(var i:Number = missiles.length - 1; i >= 0; i--) {
if(missiles[i] == targetMissile) {
missiles.splice(i,1);
break;
}
}
//don't animate anymore
targetMissile.removeEventListener(Event.ENTER_FRAME, onMissileEnterFrame);
//remove from stage
gameGroup.removeElement(targetMissile);
}
//removes bullet from stage
public function removeBullet(targetBullet:Bullet):void {
//stop animation
targetBullet.removeEventListener(Event.ENTER_FRAME, onBulletEnterFrame);
//remove from stage
gameGroup.removeElement(targetBullet);
}
//shoot a bullet at the mouse position
public function fireWeapon(e:MouseEvent):void {
//make a new bullet
var newBullet:Bullet = new Bullet();
newBullet.addEventListener(Event.ENTER_FRAME, onBulletEnterFrame);
//position near the earth in the center
var halfStage:Number = stage.stageWidth / 2;
newBullet.x = halfStage;
newBullet.y = 500;
//set target
newBullet.targX = stage.mouseX;
newBullet.targY = stage.mouseY;
//add it to the stage
gameGroup.addElement(newBullet);
}
//you lose
public function gameOver():void {
//remove missles
for(var i:Number = 0; i < missiles.length; i++) {
removeMissile(missiles[i]);
}
//stop interaction
stage.removeEventListener(MouseEvent.CLICK, fireWeapon);
//stop animation
this.removeEventListener(Event.ENTER_FRAME, onEnterFrame);
//set game start alpha
playerHealth.alpha = 0;
healthLabel.alpha = 0;
//set game end alpha
gameEnd.alpha = 1;
reset.alpha = 1;
}
]]>
</fx:Script>
onEnterFrame
...
//position it
newMissile.x = Math.random() * stage.stageWidth;
//rotate it
newMissile.rotation = - (Math.random() * 60 - 30);
onMissileEnterFrame
...
//move missle down
//targetMissile.y += 10;
targetMissile.x -= 10 * Math.sin(targetMissile.rotation * Math.PI/180);
targetMissile.y += 10 * Math.cos(targetMissile.rotation * Math.PI/180);
fireWeapon
...
//set target
newBullet.targX = stage.mouseX;
newBullet.targY = stage.mouseY;
newBullet.rotation = - Math.atan((newBullet.x - newBullet.targX) / (newBullet.y - newBullet.targY)) * 180/Math.PI;

JFreechart multiline Label on Symbolaxis or other way to align charts

i have a lot of charts, each in a different JInternalFrame:
But the horizontal axis should be aligned to the same point(maybe the red line). The problem is, that the space for the label is set automatically by jFreechart.
So i tried to find a solution for multiline ticklabels. I found this:
int optionsCount = state.getStatusOptions().toArray().length;
String[] grade = new String[optionsCount + 1];
grade[0] = "";
for (int x = 1; x < optionsCount + 1; x++) {
//grade[x] ="blaa"+x;//state.getStatusOptions().get(x - 1);
//grade[x]="1.line\n2.line\n3.line";
grade[x] = newLineString(state.getStatusOptions().get(x - 1), 5);
}
// grade[1]="1.line\n2.line";
SymbolAxis rangeAxis;
rangeAxis = new SymbolAxis("", grade){
#Override
protected Rectangle2D getLabelEnclosure(Graphics2D g2, RectangleEdge edge) {
Rectangle2D l = super.getLabelEnclosure(g2, edge);
l.setRect(l.getX(),l.getY(),l.getWidth()*0.5,l.getHeight());
return l;
}
#Override
protected AxisState drawTickMarksAndLabels(Graphics2D g2, double cursor, Rectangle2D plotArea, Rectangle2D dataArea, RectangleEdge edge) {
AxisState state = new AxisState(cursor);
if (isAxisLineVisible()) {
drawAxisLine(g2, cursor, dataArea, edge);
}
double ol = getTickMarkOutsideLength();
double il = getTickMarkInsideLength();
List ticks = refreshTicks(g2, state, dataArea, edge);
state.setTicks(ticks);
g2.setFont(getTickLabelFont());
Iterator iterator = ticks.iterator();
// remember the max number of lines used in any label
int maxLinesUsed = 0;
while (iterator.hasNext()) {
ValueTick tick = (ValueTick) iterator.next();
if (isTickLabelsVisible()) {
g2.setPaint(getTickLabelPaint());
float[] anchorPoint = calculateAnchorPoint(tick, cursor, dataArea, edge);
g2.draw(plotArea);
g2.setPaint(Color.green);
g2.draw(dataArea);
g2.setPaint(getTickLabelPaint());
// split by "\n" and draw text in a new line for each result
String tickText = tick.getText();
int line = 1;
for (String tickTextLine : tickText.split("\n")) {
float x = anchorPoint[0];
// one row down...
float y = anchorPoint[1] + line * g2.getFont().getSize();
TextUtilities.drawRotatedString(tickTextLine, g2, x, y, tick.getTextAnchor(), tick.getAngle(), tick
.getRotationAnchor());
line++;
}
// if we used more lines than any time before remember it
if (line > maxLinesUsed) {
maxLinesUsed = line;
}
}
if (isTickMarksVisible() && tick.getTickType().equals(TickType.MAJOR)) {
float xx = (float) valueToJava2D(tick.getValue(), dataArea, edge);
Line2D mark = null;
g2.setStroke(getTickMarkStroke());
g2.setPaint(getTickMarkPaint());
if (edge == RectangleEdge.LEFT) {
mark = new Line2D.Double(cursor - ol, xx, cursor + il, xx);
} else if (edge == RectangleEdge.RIGHT) {
mark = new Line2D.Double(cursor + ol, xx, cursor - il, xx);
} else if (edge == RectangleEdge.TOP) {
mark = new Line2D.Double(xx, cursor - ol, xx, cursor + il);
} else if (edge == RectangleEdge.BOTTOM) {
mark = new Line2D.Double(xx, cursor + ol, xx, cursor - il);
}
g2.draw(mark);
}
}
// need to work out the space used by the tick labels...
// so we can update the cursor...
// patched using maxLinesUsed => we need more space because of multiple lines
double used = 0.0;
if (isTickLabelsVisible()) {
if (edge == RectangleEdge.LEFT) {
used += findMaximumTickLabelWidth(ticks, g2, plotArea, isVerticalTickLabels()) * maxLinesUsed;
state.cursorLeft(used);
} else if (edge == RectangleEdge.RIGHT) {
used = findMaximumTickLabelWidth(ticks, g2, plotArea, isVerticalTickLabels()) * maxLinesUsed;
state.cursorRight(used);
} else if (edge == RectangleEdge.TOP) {
used = findMaximumTickLabelHeight(ticks, g2, plotArea, isVerticalTickLabels()) * maxLinesUsed;
state.cursorUp(used);
} else if (edge == RectangleEdge.BOTTOM) {
used = findMaximumTickLabelHeight(ticks, g2, plotArea, isVerticalTickLabels()) * maxLinesUsed;
state.cursorDown(used);
}
}
return state;
}
};
As you can see in the picture above, the new line function works, but the spacing for the labels does not work. I tried to override the getLabelEnclosure method, but its given string is just "".
Does anyone know a solution for my problem. Either the multiline or an other way to align the charts?
thanks!
Override the reserveSpace function and in the place where the height is calculated modify it with the number of rows you need:
Rectangle2D labelEnclosure = getLabelEnclosure(g2, edge);
if (RectangleEdge.isTopOrBottom(edge)) {
double labelHeight = labelEnclosure.getHeight();
space.add(labelHeight + **YOUR_NUMBER_OF_ROWS** * tickLabelHeight, edge);
} else if (RectangleEdge.isLeftOrRight(edge)) {
double labelWidth = labelEnclosure.getWidth();
space.add(labelWidth + tickLabelWidth, edge);
}
return space;

Resources