Power up not working - c++11

So I currently have a working 'Speed' power up that multiplies the speed of the player by 2. I'm trying to make a power up now that increases the score you get for picking up the GameObject 'Gem' by 2. it should increase to 20 points per gem from 10.
Currently, the power up is spawning randomly around the map within 10-20 seconds, so as intended, but the score you get for collecting the power up has not gone up to 20.
PlayerMovement Code:
public float speed = 10f;
private Rigidbody2D rb2d;
public GameObject Player;
public GameObject speedPowerUp;
public static int livess = 100;
public Vector2 movement;
public GameObject MultiPowerUp;
public static int addScore = 10;
void Start ()
{
rb2d = GetComponent<Rigidbody2D> ();
}
void FixedUpdate ()
{
float moveHorizontal = Input.GetAxis ("Horizontal"); //Gets keys that unity refers to being able to move horizontal (Set by default)
float moveVertical = Input.GetAxis ("Vertical"); //Gets keys that unity refers to being able to move vertical (Set by default) Use forces to act with RigidBody2D
Vector2 movement = new Vector2 (moveHorizontal, moveVertical);
rb2d.AddForce (movement * speed);
if(moveHorizontal < 0)
GetComponent<SpriteRenderer>().flipX = true;
else if(moveHorizontal > 0)
GetComponent<SpriteRenderer>().flipX = false;
}
void OnTriggerEnter2D(Collider2D other)
{
if (other.gameObject.CompareTag ("shuriken"))
{
if (livess <= 1)
{
Destroy (Player);
livess = livess - 1;
Debug.LogError (livess);
}
else
{
livess = livess - 1;
Debug.LogError (livess);
return;
}
}
if (other.gameObject.CompareTag ("speedPowerUp"))
{
StartCoroutine (WaitTimeSpeed ());
other.gameObject.SetActive (false);
}
if (other.gameObject.CompareTag ("MultiPowerUp"))
{
StartCoroutine (WaitTimeMulti ());
other.gameObject.SetActive (false);
}
}
IEnumerator WaitTimeSpeed ()
{
Debug.LogError (speed);
speed = speed * 2;
Debug.LogError (speed);
yield return new WaitForSeconds (5);
speed = speed / 2;
Debug.LogError (speed);
yield return new WaitForSeconds (Random.Range (10, 20));
SpawnSpeed ();
}
void SpawnSpeed()
{
Vector3 RandomSpawn = new Vector3 (Random.Range (-8.87F, 8.87F), Random.Range (-3.87F, 3.97F),1F);
Instantiate (speedPowerUp, RandomSpawn, Quaternion.identity);
}
IEnumerator WaitTimeMulti()
{
Debug.LogError (addScore);
addScore = 20;
Debug.LogError (addScore);
yield return new WaitForSeconds (5);
addScore = 10;
yield return new WaitForSeconds (Random.Range (10, 20));
SpawnMulti ();
}
void SpawnMulti ()
{
Vector3 RandomSpawn = new Vector3 (Random.Range (-8.87F, 8.87F), Random.Range (-3.87F, 3.97F),1F);
Instantiate (MultiPowerUp, RandomSpawn, Quaternion.identity);
}
}
Gem Code:
public GameObject Gem;
public static int count;
public Text countText;
public int addScores = PlayerMovement.addScore;
void Start()
{
SetCountText ();
}
void SpawnGem()
{
Vector3 RandomSpawn = new Vector3 (Random.Range (-8.87F, 8.87F), Random.Range (-3.87F, 3.97F),1F);
Instantiate (Gem, RandomSpawn, Quaternion.identity);
}
void OnTriggerEnter2D(Collider2D other)
{
if (other.gameObject.CompareTag ("Player"))
{
SpawnGem ();
count = count + addScores;
SetCountText ();
PlayerPrefs.SetInt("Player Score", count);
Destroy (Gem);
}
}
void SetCountText()
{
countText.text = "Count: " + count.ToString ();
}
}

Related

Processing: Multiple bullets in top down shooter

I am trying to make a simple top down shooter. When the user presses W, A, S or D a 'bullet' (rectangle) will come out of the 'shooter'. With my code, you can only shoot one bullet per direction until it reaches the end of the screen. Is there a way to make it so they (the user) can shoot multiple bullets in one direction?
Here's my code:
package topdownshooter;
import processing.core.PApplet;
import processing.core.PImage;
public class TopDownShooter extends PApplet {
PImage shooter;
float shooterX = 400;
float shooterY = 300;
float u_bulletSpeed;
float l_bulletSpeed;
float d_bulletSpeed;
float r_bulletSpeed;
boolean shootUp = false;
boolean shootLeft = false;
boolean shootDown = false;
boolean shootRight = false;
public static void main(String[] args) {
PApplet.main("topdownshooter.TopDownShooter");
}
public void setup() {
shooter = loadImage("shooter.png");
}
public void settings() {
size(800, 600);
}
public void keyPressed() {
if(key == 'w') {
shootUp = true;
}
if(key == 'a') {
shootLeft = true;
}
if(key == 's') {
shootDown = true;
}
if(key == 'd') {
shootRight = true;
}
}
public void draw() {
background(206);
imageMode(CENTER);
image(shooter, shooterX, shooterY);
if(shootUp == true) {
rect(shooterX, shooterY-u_bulletSpeed, 5, 5);
u_bulletSpeed += 2;
if(u_bulletSpeed > 300) {
u_bulletSpeed = 0;
shootUp = false;
}
}
if(shootLeft == true) {
rect(shooterX-l_bulletSpeed, shooterY, 5, 5);
l_bulletSpeed += 2;
if(l_bulletSpeed > 400) {
l_bulletSpeed = 0;
shootLeft = false;
}
}
if(shootDown == true) {
rect(shooterX, shooterY+d_bulletSpeed, 5, 5);
d_bulletSpeed += 2;
if(d_bulletSpeed > 300) {
d_bulletSpeed = 0;
shootDown = false;
}
}
if(shootRight == true) {
rect(shooterX+r_bulletSpeed, shooterY, 5, 5);
r_bulletSpeed += 2;
if(r_bulletSpeed > 400) {
r_bulletSpeed = 0;
shootRight = false;
}
}
}
}
The language is processing and I am using the eclipse IDE.
Thanks!
Here's what I would do if I were you. First I'd encapsulate your bullet data into a class, like this:
class Bullet{
float x;
float y;
float xSpeed;
float ySpeed;
// you probably want a constructor here
void drawBullet(){
// bullet drawing code
}
}
Then I'd create an ArrayList that holds Bullet instances:
ArrayList<Bullet> bullets = new ArrayList<Bullet>();
To add a bullet, I'd create a new instance and add it to the ArrayList like this:
bullets.add(new Bullet(bulletX, bulletY));
Then to draw the bullets, I'd iterate over the ArrayList and call the corresponding function:
for(Bullet b : bullets){
b.drawBullet();
}
Shameless self-promotion:
Here is a tutorial on creating classes.
Here is a tutorial on using ArrayLists.

How to use Hashmap or Array to create a "list" of countries with attributes

I'm trying to visualize migration data using particle systems. Each row of the dataset contains: source country, destination country, year, and various amounts.
Each row should be represented as a particle system representing that data.
QUESTION:
What will be the best way to create a list of countries or country objects, with x,y location attributes and maybe some other attributes that could be added later?
Entire code for reference:
// Based on Example Written by Casey Reas and Ben Fry
// Edited by Tom Bar-Gal
//particlesystem()
//addparticle()
//particle()
// ========== Table Data Stuff
Table table;
int k = 0;
String[] destCountryArray = new String[0];
String[] sourceCountryArray = new String[0];
String destCountry = "";
String prevDestCountry = "";
String sourceCountry;
// ========
int maxParticles = 12000;
ParticleSystem ps;
ParticleSystem ps2;
int n = 0, n2=0;
int emmitMultiplyer = 1;
int emmitFreq = 1;
float particleSpeed = 0.002;
float locationX = 250;
float locationY = 450;
int[] sourceX = {10, 40, 200, 400, 700};
int[] destX = {300, 600, 300, 600, 600};
int[] amount = {10, 100, 500, 800, 1000};
int highestAmount = max(amount);
// a,b,c... max*a/{a+b+c...}
ParticleSystem[] PSystems;
void setup() {
size(1200, 800);
//=============== load table and create an array of countries
table = loadTable("asylum_seekers.csv", "header");
destCountryArray = (String[]) append(destCountryArray, "Israel");
for (TableRow row : table.rows()) {
//println("going over row" + row.getString("Country / territory of asylum/residence"));
String tempCountryHolder = row.getString("Country / territory of asylum/residence");
//println("Got a temp country holder" + tempCountryHolder);
boolean exists = countryExists(tempCountryHolder);
if (exists==true) {
//println("exists, skipping");
continue;
}
println("Appending "+tempCountryHolder+" to list of length " +destCountryArray.length);
destCountryArray = (String[]) append(destCountryArray, tempCountryHolder);
println("destCountryArray length = "+ destCountryArray.length);
}
//============================
PSystems = new ParticleSystem[destCountryArray.length];
//frameRate(30);
//colorMode(RGB,255,255,255,255);
for (int i = 0; i<destCountryArray.length; i++) {
// Particle Systems syntax = multiplyer, source, destination, amount);
PSystems[i] = new ParticleSystem(1, new Vector3D(i*40+40, 100, 0), new Vector3D(i*40+40, 500, 0), 1/(i+1));
//println("PSystems " + i + " is " +PSystems[i]);
}
//ps = new ParticleSystem(1, new Vector3D(width/2, height/2, 0));
//ps2 = new ParticleSystem(1, new Vector3D(100, 200, 0));
smooth();
}
void draw() {
background(250);
//ellipse(locationX, locationY, 5, 5);
//ellipse(width/2, height/2, 5, 5);
//ellipse(100, 200, 5, 5);
//println(PSystems.length);
for (int i = 0; i<destCountryArray.length; i++) {
//println(PSystems[i]);
PSystems[i].run();
}
for (int i = 0; i<emmitMultiplyer; i++) {
for (int k = 0; k<destCountryArray.length; k++) {
if (frameCount % (k+1) == 0) {
PSystems[k].addParticle();
n++;
}
}
}
n2+=emmitMultiplyer;
fill(0);
text("Frame rate: "
+ int(frameRate), 10, 20);
println(n);
println(n);
}
// ==============================// A simple Particle class // ===============================================//
class Particle {
Vector3D loc;
Vector3D des;
Vector3D vel;
Vector3D acc;
Vector3D locHome, b, c;
float relativeSpeed;
float r;
float timer;
float t=0.0;
// Another constructor (the one we are using here)
Particle(Vector3D l, Vector3D m) {
//acc = new Vector3D(0,0.0005,0); // particle acceleration
acc = new Vector3D(0, 0, 0); // new Vector3D(random(-0.1, 0.1), random(-0.02, 0), 0);
loc = l.copy();
des = m.copy();
locHome = l.copy();
locHome.x = locHome.x+random(-2, 2);
locHome.y = locHome.y+random(-2, 2);
des.x = des.x+random(-2, 2);
des.y=des.y+random(-2, 2);
relativeSpeed = random(0.5, 1.2);
r = random(0.9, 2.3); // particle radius
timer = 10000.0; // particles lifespan
// * emmitMultiplyer = number of living
b=new Vector3D(locHome.x+random(-20, 20), locHome.y+random(120, 180), 0);
c=new Vector3D(des.x+random(-20, 30), des.y-random(120, 180), 0);
}
void run() {
update();
render();
}
// Method to update location
void update() {
if (t>=1)
return;
// https : // www.processing.org/reference/bezierPoint_.html
loc.x = bezierPoint(locHome.x, b.x, c.x, des.x, t);
loc.y = bezierPoint(locHome.y, b.y, c.y, des.y, t);
t = lerp(t, 1, particleSpeed*relativeSpeed);
//t+=particleSpeed*relativeSpeed;
// curvePoint(a, b, c, d, t)
// vel.add(acc);
// loc.add(vel);
//timer -= 1.0;
}
// Method to display
void render() {
ellipseMode(CENTER);
noStroke();
fill(70, 255);
ellipse(loc.x, loc.y, r, r);
}
// Is the particle still useful?
boolean dead() {
// if (timer <= 0.0||t>=1.0) {
if (t>=0.95) {
return true;
} else {
return false;
}
}
}
// ==============================// A ParticleSystem // ===============================================//
// A class to describe a group of Particles
// An ArrayList is used to manage the list of Particles
class ParticleSystem {
ArrayList particles; // An arraylist for all the particles
Vector3D origin; // An origin point for where particles are birthed
Vector3D dest;
int freq;
//ParticleSystem( number of particles / frame, source, destination, frequency);
ParticleSystem(int num, Vector3D v, Vector3D d, float f) {
particles = new ArrayList(); // Initialize the arraylist
origin = v.copy(); // Store the origin point
dest = d.copy();
//if (frameCount % (1/f) == 0){
for (int i = 0; i < num; i++) {
particles.add(new Particle(origin, dest)); // Add "num" amount of particles to the arraylist
}
//}
}
void run() {
// Cycle through the ArrayList backwards b/c we are deleting
for (int i = particles.size()-1; i >= 0; i--) {
Particle p = (Particle) particles.get(i);
p.run();
if (p.dead()) {
particles.remove(i);
n--;
}
}
}
void addParticle() {
particles.add(new Particle(origin, dest));
}
//void addParticle(Particle p) {
// particles.add(p);
//}
// A method to test if the particle system still has particles
boolean dead() {
if (particles.isEmpty()) {
return true;
} else {
return false;
}
}
}
//=================================================== Class Country
public class Country {
public float countryIndex;
public float countryLocationX;
public float countryLocationY;
public float countryName;
}
// ================================================ Simple Vector3D Class
public class Vector3D {
public float x;
public float y;
public float z;
Vector3D(float x_, float y_, float z_) {
x = x_;
y = y_;
z = z_;
}
Vector3D(float x_, float y_) {
x = x_;
y = y_;
z = 0f;
}
Vector3D() {
x = 0f;
y = 0f;
z = 0f;
}
void setX(float x_) {
x = x_;
}
void setY(float y_) {
y = y_;
}
void setZ(float z_) {
z = z_;
}
void setXY(float x_, float y_) {
x = x_;
y = y_;
}
void setXYZ(float x_, float y_, float z_) {
x = x_;
y = y_;
z = z_;
}
void setXYZ(Vector3D v) {
x = v.x;
y = v.y;
z = v.z;
}
public float magnitude() {
return (float) Math.sqrt(x*x + y*y + z*z);
}
public Vector3D copy() {
return new Vector3D(x, y, z);
}
public Vector3D copy(Vector3D v) {
return new Vector3D(v.x, v.y, v.z);
}
public void add(Vector3D v) {
x += v.x;
y += v.y;
z += v.z;
}
public void sub(Vector3D v) {
x -= v.x;
y -= v.y;
z -= v.z;
}
public void mult(float n) {
x *= n;
y *= n;
z *= n;
}
public void div(float n) {
x /= n;
y /= n;
z /= n;
}
public void normalize() {
float m = magnitude();
if (m > 0) {
div(m);
}
}
public void limit(float max) {
if (magnitude() > max) {
normalize();
mult(max);
}
}
public float heading2D() {
float angle = (float) Math.atan2(-y, x);
return -1*angle;
}
public Vector3D add(Vector3D v1, Vector3D v2) {
Vector3D v = new Vector3D(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z);
return v;
}
public Vector3D sub(Vector3D v1, Vector3D v2) {
Vector3D v = new Vector3D(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z);
return v;
}
public Vector3D div(Vector3D v1, float n) {
Vector3D v = new Vector3D(v1.x/n, v1.y/n, v1.z/n);
return v;
}
public Vector3D mult(Vector3D v1, float n) {
Vector3D v = new Vector3D(v1.x*n, v1.y*n, v1.z*n);
return v;
}
public float distance (Vector3D v1, Vector3D v2) {
float dx = v1.x - v2.x;
float dy = v1.y - v2.y;
float dz = v1.z - v2.z;
return (float) Math.sqrt(dx*dx + dy*dy + dz*dz);
}
}
boolean countryExists(String tempCountryHolder) {
for (int i = 0; i < destCountryArray.length; i++) {
//println("comparing '" +tempCountryHolder +"' with '"+destCountryArray[i] + "'");
if (tempCountryHolder.equals(destCountryArray[i]) == true) {
//println("found : "+ tempCountryHolder);
return true; // it exists
} //if
} //for
return false ; // not found
}//func
answer was: hashmap of hashmaps
HashMap<String, HashMap> countries = new HashMap<String, HashMap>();
for (int i=0; i<destCountryArray.length; i++) {
HashMap<String, Float> country = new HashMap<String, Float>();
countries.put(destCountryArray[i], country);
country.put("x", i*20.0);
country.put("y", i*40.0);
}
for (Map.Entry me : countries.entrySet()) {
print(me.getKey() + " is ");
println(me.getValue());
}
You probably don't want to use a nested HashMap like your answer suggests. You probably want to use your own class instead. Something like this:
HashMap<String, Point> countries = new HashMap<String, Point>();
void setup(){
countries.put("one", new Point(2, 3));
countries.put("four", new Point(5, 6));
}
void draw(){
Point pOne = countries.get("one");
point(pOne.x, pOne.y);
}
class Point{
float x;
float y;
public Point(float x, float y){
this.x = x;
this.y = y;
}
}
Or better yet, you could just use Processing's PVector class, which already represents points:
HashMap<String, PVector> countries = new HashMap<String, PVector>();
void setup(){
countries.put("one", new PVector(2, 3));
countries.put("four", new PVector(5, 6));
}
void draw(){
PVector pOne = countries.get("one");
point(pOne.x, pOne.y);
}
More info can be found in the reference. Shameless self-promotion: here is a tutorial on using classes, and here is a tutorial on creating your own classes.

Tower Defense Game: Moving the enemies on the screen

I am trying to develop a Tower Defense Game using javafx and I am having trouble as to how to make it so that the enemies move around the screen. Which classes and methods should I be using in order to approach this problem?
A tower defense game is too much to be covered on SO. I had a little bit of spare time and modified the engine I created in this thread.
Here's the main class with the game loop where the game is loaded, input is checked, sprites are moved, collision is checked, score is updated etc. In opposite to the other engine here you don't need keyboard input. Instead use a mouse click to position a tower. I added 4 initial towers.
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.geometry.Point2D;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;
import javafx.scene.text.Text;
import javafx.scene.text.TextBoundsType;
import javafx.stage.Stage;
public class Game extends Application {
Random rnd = new Random();
Pane playfieldLayer;
Pane scoreLayer;
Image playerImage;
Image enemyImage;
List<Tower> towers = new ArrayList<>();;
List<Enemy> enemies = new ArrayList<>();;
Text scoreText = new Text();
int score = 0;
Scene scene;
#Override
public void start(Stage primaryStage) {
Group root = new Group();
// create layers
playfieldLayer = new Pane();
scoreLayer = new Pane();
root.getChildren().add( playfieldLayer);
root.getChildren().add( scoreLayer);
playfieldLayer.addEventFilter(MouseEvent.MOUSE_CLICKED, e -> {
createTower(e.getX(), e.getY());
});
scene = new Scene( root, Settings.SCENE_WIDTH, Settings.SCENE_HEIGHT);
primaryStage.setScene( scene);
primaryStage.show();
loadGame();
createScoreLayer();
createTowers();
AnimationTimer gameLoop = new AnimationTimer() {
#Override
public void handle(long now) {
// add random enemies
spawnEnemies( true);
// check if target is still valid
towers.forEach( tower -> tower.checkTarget());
// tower movement: find target
for( Tower tower: towers) {
tower.findTarget( enemies);
}
// movement
towers.forEach(sprite -> sprite.move());
enemies.forEach(sprite -> sprite.move());
// check collisions
checkCollisions();
// update sprites in scene
towers.forEach(sprite -> sprite.updateUI());
enemies.forEach(sprite -> sprite.updateUI());
// check if sprite can be removed
enemies.forEach(sprite -> sprite.checkRemovability());
// remove removables from list, layer, etc
removeSprites( enemies);
// update score, health, etc
updateScore();
}
};
gameLoop.start();
}
private void loadGame() {
playerImage = new Image( getClass().getResource("player.png").toExternalForm());
enemyImage = new Image( getClass().getResource("enemy.png").toExternalForm());
}
private void createScoreLayer() {
scoreText.setFont( Font.font( null, FontWeight.BOLD, 48));
scoreText.setStroke(Color.BLACK);
scoreText.setFill(Color.RED);
scoreLayer.getChildren().add( scoreText);
scoreText.setText( String.valueOf( score));
double x = (Settings.SCENE_WIDTH - scoreText.getBoundsInLocal().getWidth()) / 2;
double y = 0;
scoreText.relocate(x, y);
scoreText.setBoundsType(TextBoundsType.VISUAL);
}
private void createTowers() {
// position initial towers
List<Point2D> towerPositionList = new ArrayList<>();
towerPositionList.add(new Point2D( 100, 200));
towerPositionList.add(new Point2D( 100, 400));
towerPositionList.add(new Point2D( 800, 200));
towerPositionList.add(new Point2D( 800, 600));
for( Point2D pos: towerPositionList) {
createTower( pos.getX(), pos.getY());
}
}
private void createTower( double x, double y) {
Image image = playerImage;
// center image at position
x -= image.getWidth() / 2;
y -= image.getHeight() / 2;
// create player
Tower player = new Tower(playfieldLayer, image, x, y, 0, 0, 0, 0, Settings.PLAYER_SHIP_HEALTH, 0, Settings.PLAYER_SHIP_SPEED);
// register player
towers.add( player);
}
private void spawnEnemies( boolean random) {
if( random && rnd.nextInt(Settings.ENEMY_SPAWN_RANDOMNESS) != 0) {
return;
}
// image
Image image = enemyImage;
// random speed
double speed = rnd.nextDouble() * 1.0 + 2.0;
// x position range: enemy is always fully inside the screen, no part of it is outside
// y position: right on top of the view, so that it becomes visible with the next game iteration
double x = rnd.nextDouble() * (Settings.SCENE_WIDTH - image.getWidth());
double y = -image.getHeight();
// create a sprite
Enemy enemy = new Enemy( playfieldLayer, image, x, y, 0, 0, speed, 0, 1,1);
// manage sprite
enemies.add( enemy);
}
private void removeSprites( List<? extends SpriteBase> spriteList) {
Iterator<? extends SpriteBase> iter = spriteList.iterator();
while( iter.hasNext()) {
SpriteBase sprite = iter.next();
if( sprite.isRemovable()) {
// remove from layer
sprite.removeFromLayer();
// remove from list
iter.remove();
}
}
}
private void checkCollisions() {
for( Tower tower: towers) {
for( Enemy enemy: enemies) {
if( tower.hitsTarget( enemy)) {
enemy.getDamagedBy( tower);
// TODO: explosion
if( !enemy.isAlive()) {
enemy.setRemovable(true);
// increase score
score++;
}
}
}
}
}
private void updateScore() {
scoreText.setText( String.valueOf( score));
}
public static void main(String[] args) {
launch(args);
}
}
Then you need a base class for your sprites. You can use it for enemies and towers.
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.Pane;
public abstract class SpriteBase {
Image image;
ImageView imageView;
Pane layer;
double x;
double y;
double r;
double dx;
double dy;
double dr;
double health;
double damage;
boolean removable = false;
double w;
double h;
boolean canMove = true;
public SpriteBase(Pane layer, Image image, double x, double y, double r, double dx, double dy, double dr, double health, double damage) {
this.layer = layer;
this.image = image;
this.x = x;
this.y = y;
this.r = r;
this.dx = dx;
this.dy = dy;
this.dr = dr;
this.health = health;
this.damage = damage;
this.imageView = new ImageView(image);
this.imageView.relocate(x, y);
this.imageView.setRotate(r);
this.w = image.getWidth(); // imageView.getBoundsInParent().getWidth();
this.h = image.getHeight(); // imageView.getBoundsInParent().getHeight();
addToLayer();
}
public void addToLayer() {
this.layer.getChildren().add(this.imageView);
}
public void removeFromLayer() {
this.layer.getChildren().remove(this.imageView);
}
public Pane getLayer() {
return layer;
}
public void setLayer(Pane layer) {
this.layer = layer;
}
public double getX() {
return x;
}
public void setX(double x) {
this.x = x;
}
public double getY() {
return y;
}
public void setY(double y) {
this.y = y;
}
public double getR() {
return r;
}
public void setR(double r) {
this.r = r;
}
public double getDx() {
return dx;
}
public void setDx(double dx) {
this.dx = dx;
}
public double getDy() {
return dy;
}
public void setDy(double dy) {
this.dy = dy;
}
public double getDr() {
return dr;
}
public void setDr(double dr) {
this.dr = dr;
}
public double getHealth() {
return health;
}
public double getDamage() {
return damage;
}
public void setDamage(double damage) {
this.damage = damage;
}
public void setHealth(double health) {
this.health = health;
}
public boolean isRemovable() {
return removable;
}
public void setRemovable(boolean removable) {
this.removable = removable;
}
public void move() {
if( !canMove)
return;
x += dx;
y += dy;
r += dr;
}
public boolean isAlive() {
return Double.compare(health, 0) > 0;
}
public ImageView getView() {
return imageView;
}
public void updateUI() {
imageView.relocate(x, y);
imageView.setRotate(r);
}
public double getWidth() {
return w;
}
public double getHeight() {
return h;
}
public double getCenterX() {
return x + w * 0.5;
}
public double getCenterY() {
return y + h * 0.5;
}
// TODO: per-pixel-collision
public boolean collidesWith( SpriteBase otherSprite) {
return ( otherSprite.x + otherSprite.w >= x && otherSprite.y + otherSprite.h >= y && otherSprite.x <= x + w && otherSprite.y <= y + h);
}
/**
* Reduce health by the amount of damage that the given sprite can inflict
* #param sprite
*/
public void getDamagedBy( SpriteBase sprite) {
health -= sprite.getDamage();
}
/**
* Set health to 0
*/
public void kill() {
setHealth( 0);
}
/**
* Set flag that the sprite can be removed from the UI.
*/
public void remove() {
setRemovable(true);
}
/**
* Set flag that the sprite can't move anymore.
*/
public void stopMovement() {
this.canMove = false;
}
public abstract void checkRemovability();
}
The towers are subclasses of the sprite base class. Here you need a little bit of math because you want the towers to rotate towards the enemies and let the towers fire when the enemy is within range.
import java.util.List;
import javafx.scene.effect.ColorAdjust;
import javafx.scene.image.Image;
import javafx.scene.layout.Pane;
public class Tower extends SpriteBase {
SpriteBase target; // TODO: use weakreference
double turnRate = 0.6;
double speed;
double targetRange = 300; // distance within tower can lock to enemy
ColorAdjust colorAdjust;
double rotationLimitDeg=0.0;
double rotationLimitRad = Math.toDegrees( this.rotationLimitDeg);
double roatationEasing = 10;
double targetAngle = 0;
double currentAngle = 0;
boolean withinFiringRange = false;
public Tower(Pane layer, Image image, double x, double y, double r, double dx, double dy, double dr, double health, double damage, double speed) {
super(layer, image, x, y, r, dx, dy, dr, health, damage);
this.speed = speed;
this.setDamage(Settings.TOWER_DAMAGE);
init();
}
private void init() {
// red colorization (simulate "angry")
colorAdjust = new ColorAdjust();
colorAdjust.setContrast(0.0);
colorAdjust.setHue(-0.2);
}
#Override
public void move() {
SpriteBase follower = this;
// reset within firing range
withinFiringRange = false;
// rotate towards target
if( target != null)
{
// parts of code used from shane mccartney (http://lostinactionscript.com/page/3/)
double xDist = target.getCenterX() - follower.getCenterX();
double yDist = target.getCenterY() - follower.getCenterY();
this.targetAngle = Math.atan2(yDist, xDist) - Math.PI / 2;
this.currentAngle = Math.abs(this.currentAngle) > Math.PI * 2 ? (this.currentAngle < 0 ? (this.currentAngle % Math.PI * 2 + Math.PI * 2) : (this.currentAngle % Math.PI * 2)) : (this.currentAngle);
this.targetAngle = this.targetAngle + (Math.abs(this.targetAngle - this.currentAngle) < Math.PI ? (0) : (this.targetAngle - this.currentAngle > 0 ? ((-Math.PI) * 2) : (Math.PI * 2)));
this.currentAngle = this.currentAngle + (this.targetAngle - this.currentAngle) / roatationEasing; // give easing when rotation comes closer to the target point
// check if the rotation limit has to be kept
if( (this.targetAngle-this.currentAngle) > this.rotationLimitRad) {
this.currentAngle+=this.rotationLimitRad;
} else if( (this.targetAngle-this.currentAngle) < -this.rotationLimitRad) {
this.currentAngle-=this.rotationLimitRad;
}
follower.r = Math.toDegrees(currentAngle);
// determine if the player ship is within firing range; currently if the player ship is within 10 degrees (-10..+10)
withinFiringRange = Math.abs( Math.toDegrees( this.targetAngle-this.currentAngle)) < 20;
}
super.move();
}
public void checkTarget() {
if( target == null) {
return;
}
if( !target.isAlive() || target.isRemovable()) {
setTarget( null);
return;
}
//get distance between follower and target
double distanceX = target.getCenterX() - getCenterX();
double distanceY = target.getCenterY() - getCenterY();
//get total distance as one number
double distanceTotal = Math.sqrt(distanceX * distanceX + distanceY * distanceY);
if( Double.compare( distanceTotal, targetRange) > 0) {
setTarget( null);
}
}
public void findTarget( List<? extends SpriteBase> targetList) {
// we already have a target
if( getTarget() != null) {
return;
}
SpriteBase closestTarget = null;
double closestDistance = 0.0;
for (SpriteBase target: targetList) {
if (!target.isAlive())
continue;
//get distance between follower and target
double distanceX = target.getCenterX() - getCenterX();
double distanceY = target.getCenterY() - getCenterY();
//get total distance as one number
double distanceTotal = Math.sqrt(distanceX * distanceX + distanceY * distanceY);
// check if enemy is within range
if( Double.compare( distanceTotal, targetRange) > 0) {
continue;
}
if (closestTarget == null) {
closestTarget = target;
closestDistance = distanceTotal;
} else if (Double.compare(distanceTotal, closestDistance) < 0) {
closestTarget = target;
closestDistance = distanceTotal;
}
}
setTarget(closestTarget);
}
public SpriteBase getTarget() {
return target;
}
public void setTarget(SpriteBase target) {
this.target = target;
}
#Override
public void checkRemovability() {
if( Double.compare( health, 0) < 0) {
setTarget(null);
setRemovable(true);
}
}
public boolean hitsTarget( SpriteBase enemy) {
return target == enemy && withinFiringRange;
}
public void updateUI() {
if( withinFiringRange) {
imageView.setEffect(colorAdjust);
} else {
imageView.setEffect(null);
}
super.updateUI();
}
}
The enemy class is easier. It needs only movement. However, in your final version the enemies should consider obstacles during movement. In this example I add a health bar above the enemy to show the health.
import javafx.scene.image.Image;
import javafx.scene.layout.Pane;
public class Enemy extends SpriteBase {
HealthBar healthBar;
double healthMax;
public Enemy(Pane layer, Image image, double x, double y, double r, double dx, double dy, double dr, double health, double damage) {
super(layer, image, x, y, r, dx, dy, dr, health, damage);
healthMax = Settings.ENEMY_HEALTH;
setHealth(healthMax);
}
#Override
public void checkRemovability() {
if( Double.compare( getY(), Settings.SCENE_HEIGHT) > 0) {
setRemovable(true);
}
}
public void addToLayer() {
super.addToLayer();
// create health bar; has to be created here because addToLayer is called in super constructor
// and it wouldn't exist yet if we'd create it as class member
healthBar = new HealthBar();
this.layer.getChildren().add(this.healthBar);
}
public void removeFromLayer() {
super.removeFromLayer();
this.layer.getChildren().remove(this.healthBar);
}
/**
* Health as a value from 0 to 1.
* #return
*/
public double getRelativeHealth() {
return getHealth() / healthMax;
}
public void updateUI() {
super.updateUI();
// update health bar
healthBar.setValue( getRelativeHealth());
// locate healthbar above enemy, centered horizontally
healthBar.relocate(x + (imageView.getBoundsInLocal().getWidth() - healthBar.getBoundsInLocal().getWidth()) / 2, y - healthBar.getBoundsInLocal().getHeight() - 4);
}
}
The health bar
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.shape.StrokeType;
public class HealthBar extends Pane {
Rectangle outerHealthRect;
Rectangle innerHealthRect;
public HealthBar() {
double height = 10;
double outerWidth = 60;
double innerWidth = 40;
double x=0.0;
double y=0.0;
outerHealthRect = new Rectangle( x, y, outerWidth, height);
outerHealthRect.setStroke(Color.BLACK);
outerHealthRect.setStrokeWidth(2);
outerHealthRect.setStrokeType( StrokeType.OUTSIDE);
outerHealthRect.setFill(Color.RED);
innerHealthRect = new Rectangle( x, y, innerWidth, height);
innerHealthRect.setStrokeType( StrokeType.OUTSIDE);
innerHealthRect.setFill(Color.LIMEGREEN);
getChildren().addAll( outerHealthRect, innerHealthRect);
}
public void setValue( double value) {
innerHealthRect.setWidth( outerHealthRect.getWidth() * value);
}
}
And then you need some global settings like this
public class Settings {
public static double SCENE_WIDTH = 1024;
public static double SCENE_HEIGHT = 768;
public static double TOWER_DAMAGE = 1;
public static double PLAYER_SHIP_SPEED = 4.0;
public static double PLAYER_SHIP_HEALTH = 100.0;
public static int ENEMY_HEALTH = 100;
public static int ENEMY_SPAWN_RANDOMNESS = 50;
}
These are the images:
player.png
enemy.png
So summarized the gameplay is for now:
click on the screen to place a tower ( ie a smiley)
when an enemy is in range, the smiley becomes angry (i just change the color to red), in your final version the tower would be firing
as long as the tower is firing at the enemy, the health is reduced. i did it by changing the health bar depending on the health
when the health is depleted, the enemy is killed and the score is updated; you'd have to add an explosion
So all in all it's not so easy to create a tower defense game. Hope it helps as a start.
Heres' a screenshot:

Mixing active and static modes in Processing

Making a space invaders knock off game. My code will not compile as I get the error message "It looks like you're mixing 'active' and 'static' modes", but I can not see where I am mixing them. Can someone please take a look at my code?
final int SCREENX=400;
final int SCREENY=400;
final int GAP=10;
final int ALIEN_ALIVE=0;
final int ALIEN_DEAD=6;
final int FORWARD=0;
final int BACKWARD=1;
final int MARGIN=30;
Alien theAliens[];
Bullet bullets[];
Player thePlayer;
void setup() {
PImage normalImg, explodeImg;
size(SCREENX, SCREENY);
normalImg =loadImage("invader.GIF");
explodeImg =loadImage("exploding.GIF");
theAliens = new Alien[10];
bullets = new Bullet[20];
init_aliens(theAliens, normalImg, explodeImg);
thePlayer = new Player(SCREENY- 50);
}
void init_aliens(Alien baddies[], PImage okImg, PImage
exImg) {
for (int i=0; i<baddies.length; i++) {
// This is buggy, what is the problem?
baddies[i] = new Alien(i*(okImg.width+GAP), 0, okImg,
exImg);
}
}
void init_bullets() {
for (int i = 0; i < bullets.size(); i++) {
Bullet b = (Bullet) bullets.get(i);
b.move();
b.draw();
}
}
void shoot() {
if (mousePressed)
Player.shoot();
}
void draw() {
background(0);
thePlayer.draw();
thePlayer.move(mouseX);
draw_bullets(myBullets);
for (int i=0; i<theAliens.length; i++) {
theAliens[i].move();
theAliens[i].draw();
if (random(0, 500)<1)
theAliens[i].die();
}
}
////// Player Class //////
Player() { ///** When I get the error, this line is highlighted**///
this.x = width/2;
this.y = height-50;
this.timeLastShot = 0;
this.coolDown = 200;
colour playColour= color(50);
void draw() {
fill(playerColour);
rect(this.x, this.y, 30, 30);
}
void move(int x) {
if (x>SCREENX-50)
xpos= SCREENX-50;
else xpos=x;
}
void shoot() {
if (millis() - timeLastShot > coolDown) {
Bullet bullet = new Bullet(this.x+12.5, this.y, -5);
bullets.add(bullet);
timeLastShot = millis();
}
}
}
Your Player class is badly written. It should be:
class Player {
Player () {
//constructor
}
void functionOfSorts () {
} // Never forget to enclose functions with curly brackets!
}
...As opposed to what you wrote:
Player() {
//yadayada
}

XNA SpriteSheet not working

I have added logic to show the Sprite animating but it's simply not showing on the screen. What am I doing wrong?
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input.Touch;
namespace MyXNAGame.Game_Classes
{
public class Player : Sprite
{
private int _frameCount = 6;
private int _frameIndex;
private Rectangle[] _frames;
public float _jumpVelocity = 12f;
public PlayerState _playerState;
public Rectangle BoundingBox
{
get { return new Rectangle {X = (int) Position.X, Y = (int) Position.Y, Height = Texture.Height, Width = Texture.Width}; }
}
public void Initialize()
{
_frames = new Rectangle[_frameCount];
int width = Texture.Width / _frameCount;
for (int i = 0; i < _frameCount; i++)
{
_frames[i] = new Rectangle(i*width, 0, width, Texture.Height);
}
}
public void Load(ContentManager contentManager, string assetName)
{
Texture = contentManager.Load<Texture2D>(assetName);
}
public void Update(GameTime gameTime)
{
while (TouchPanel.IsGestureAvailable)
{
GestureSample gestureSample = TouchPanel.ReadGesture();
if (gestureSample.GestureType == GestureType.Tap)
{
if (_playerState == PlayerState.Running)
{
_playerState = PlayerState.NormalJump;
}
}
if (gestureSample.GestureType == GestureType.Hold)
{
if (_playerState == PlayerState.Running)
{
_playerState = PlayerState.LongJump;
}
}
}
// NormalJump Logic
switch (_playerState)
{
case PlayerState.NormalJump:
Position.Y -= _jumpVelocity;
_jumpVelocity -= 0.5f;
if (_jumpVelocity == 0)
{
_playerState = PlayerState.Falling;
}
break;
case PlayerState.LongJump:
Position.Y -= _jumpVelocity;
_jumpVelocity -= 0.5f;
if (_jumpVelocity == 0)
{
_playerState = PlayerState.Falling;
}
break;
case PlayerState.Falling:
Position.Y += _jumpVelocity;
_jumpVelocity += 0.5f;
break;
case PlayerState.Running:
_frameIndex++;
if (_frameIndex > 5)
{
_frameIndex = 0;
}
break;
}
}
public void Draw(SpriteBatch spriteBatch)
{
spriteBatch.Draw(Texture, Position, _frames[_frameIndex], Color.White, 0, new Vector2(0, 0), new Vector2(0, 0), SpriteEffects.None, 0);
}
}
}`
Can anyone see the obvious mistake? I am using WP7
I changed the 'Scale' parameter in the Draw() method from new Vector(0,0) to new Vector(1,1) as obviously, having a Scale of 0 will not show anything at all.

Resources