Hey so i have to make this game, basically a ball (bug) needs to change directions once it hits other objects, (rectangles and objects)
Im using getBounds.intersects to see if it hits the objects or not, but it doesn't work if the ball goes from right to left. Basically any object it hits going from right to left it just goes through which causes the game to get stuck eventually, but any other directions work just fine.
here is my code
package week6Homework;
import java.awt.Color;
import java.awt.Frame;
import java.util.Random;
import acm.graphics.GOval;
import acm.graphics.GRect;
import acm.graphics.GRectangle;
import acm.program.*;
public class BugBotTry1984756212 extends GraphicsProgram
{
//constants for screen specs
final int WIN_HEIGHT = 900;
final int WIN_WIDTH = 1900;
//booleans for turns
boolean turn;
boolean left;
boolean right;
boolean down;
boolean up;
//creating bugbot itself using external class
BugBot bug = new BugBot();
//creating arrays for ovals and rectangles
GOval[] ovals = new GOval[4];
GRect[] rects = new GRect[4];
//this is a string array that will bre sued to figure out what if the bugbot
//needs to go up/down or left/right
//its hard to explain what this does but you will figure it out later in the code
String[] horizontalTurn = new String [2];
String[] verticalTurn = new String[2];
public void init()
{
//setting name of the applet
Frame title = (Frame)this.getParent().getParent();
this.setTitle("BugBotField");
//set screen specs
setSize(WIN_WIDTH, WIN_HEIGHT);
}//init
public void run()
{
//using methods to create the rectangles and ovals and bugbot
createOvals();
createRects();
add(bug, 100, 450);
//asigning words to the horizontal string array
horizontalTurn[0] = "down";
horizontalTurn[1] = "up";
verticalTurn[0] = "right";
verticalTurn[1] = "left";
//assigning values to boolean variables to see where the bug should move
//basivally if the right = true the bugbot will be moving right, and if down is true
//and the rest of them are false the bugbot will be moving down.
right = false;
left = true;
down = false;
up = false;
//main while loop that checks everything nad does everything
while (true)
{
//pause so the game doesn't end within one second after start.
pause(10);
if (right == true)
{
bug.move(5, 0);
}
else if (left == true)
{
bug.move(-5, 0);
}
else if (down == true)
{
bug.move(0, 5);
}
else if (up == true)
{
bug.move(0, -5);
}
//get X and Y coordinates for the bugbot so it wont go out of boundaries.
int bugX = (int)bug.getX();
int bugY = (int)bug.getY();
//for loop to check colossion detection.
//basically for every time the while loop runs (which is every .1 seconds because of our pause)
//it will run this for loop 4 times (because thats how many objects we have in our arrays
// and we are using array.length to see how many times the for loop needs to run
for (int i = 0; i < rects.length; i++)
{
//integer that gets bounds of all rectangles in the array.
GRectangle rectangleBounds = rects[i].getBounds();
//making 3 of those since if the bug hits the last red circle we need
//the game to stop and not turn directions.
// i could do it differently but didn't feel like redoing bunch of stuff so here.
GRectangle ovalBounds1 = ovals[0].getBounds();
GRectangle ovalBounds2 = ovals[1].getBounds();
GRectangle ovalBounds3 = ovals[2].getBounds();
GRectangle ovalBounds = ovals[i].getBounds();
//check for collision with other objects
if (bug.getBounds().intersects(rectangleBounds) || bug.getBounds().intersects(ovalBounds))
{
//check for collision if direction is "right"
if (right == true && left == false && down == false && up == false)
{
for (int x = 3; x >= 0; x--)
{
pause (50);
bug.move(-2, 0);
}
String direction = getRandom(horizontalTurn);
right = false;
left = false;
down = false;
up = false;
if (direction == "up")
{
up = true;
}
else if (direction == "down")
{
down = true;
}
}
//check for collision if direction is "left"
else if (left == true && right == false && right == false && left == false)
{
for (int x = 3; x >= 0; x--)
{
pause (50);
bug.move(2, 0);
}
String direction = getRandom(horizontalTurn);
right = false;
left = false;
down = false;
up = false;
if (direction == "up")
{
up = true;
}
else if (direction == "down")
{
down = true;
}
}
//check for collision if direction "down"
else if (down = true && up == false && right == false && left == false)
{
for (int x = 3; x >= 0; x--)
{
pause (50);
bug.move(0, -2);
}
String direction = getRandom(verticalTurn);
right = false;
left = false;
down = false;
up = false;
if (direction == "right")
{
right = true;
}
else if (direction == "left")
{
left = true;
}
}
//check for collision if direction "up"
else if (up == true && down == false && right == false && left == false)
{
for (int x = 3; x >= 0; x--)
{
pause (50);
bug.move(0, 2);
}
String direction = getRandom(verticalTurn);
right = false;
left = false;
down = false;
up = false;
if (direction == "right")
{
right = true;
}
else if (direction == "left")
{
left = true;
}
}
}//if for collision with objects
else if (bugX >= WIN_WIDTH)
{
right = false;
left = true;
down = false;
up = false;
}
else if (bugX <= 0)
{
right = true;
left = false;
down = false;
up = false;
}
else if (bugY >= WIN_HEIGHT)
{
down = false;
up = true;
}
else if (bugY <= 0)
{
up = false;
down = true;
}
}
}
}
public void createOvals()
{
GOval orange = new GOval(400,100,200,200);
GOval green = new GOval(100,550,300,250);
GOval red = new GOval(1500,450,125,125);
GOval blue = new GOval(1650,150,200,200);
ovals [0] = orange;
ovals [1] = green;
ovals [2] = blue;
ovals [3] = red;
ovals[0].setFilled(true);
ovals[0].setColor(Color.ORANGE);
add(ovals[0]);
ovals[1].setFilled(true);
ovals[1].setColor(Color.GREEN);
add(ovals[1]);
ovals[2].setFilled(true);
ovals[2].setColor(Color.BLUE);
add(ovals[2]);
ovals[3].setFilled(true);
ovals[3].setColor(Color.RED);
add(ovals[3]);
}//creating ovals method
public void createRects()
{
GRect green = new GRect(1000,0,250,250);
GRect green2 = new GRect(650,400,250,100);
GRect RedR = new GRect(1300,700,300,250);
GRect BlueR = new GRect(450,750,250,250);
rects [0] = green;
rects [1] = green2;
rects [2] = RedR;
rects [3] = BlueR;
rects[0].setFilled(true);
rects[0].setColor(Color.GREEN);
add(rects[0]);
rects[1].setFilled(true);
rects[1].setColor(Color.GREEN);
add(rects[1]);
rects[2].setFilled(true);
rects[2].setColor(Color.RED);
add(rects[2]);
rects[3].setFilled(true);
rects[3].setColor(Color.BLUE);
add(rects[3]);
}//create rectangles method
public static String getRandom(String[] array)
{
int rnd = new Random().nextInt(array.length);
return array[rnd];
}//getRandom
}
please help, thank you.
P.S. my BugBot bug is an external class i created, now sure if it matters what i have in there. But if it does ill add it later on.
Since all other directions are working fine, the problem can't be with the intersects function.
This if statement will never be true, since you're comparing left to both true and false.
//check for collision if direction is "left"
else if (left == true && right == false && right == false && left == false)
I think you want
else if (left == true && right == false && up == false && down == false)
Related
im making a game, but i ran into a problem while working with the function "intersect".
the senario looks like this; i've made a game where the player is a rectangle were the objective is to kill the enemy rectangle. The enemy "boss" rectangle has two "simulations" that simulate a movement and an attack these simulations are driven by vectors. The movement is horizantally back and forth and the attack is in a vertical maner, a charge type of deal. The boss also has a rectangular target area where if itersected the "boss" will charge across the screen.
now the problem comes when i tried to make it so that if the player intersects with the rectangular target area the "boss" will attack/charge. The boss attack/charge the first time the player intersects but not after that. I want the boss to follow the same pantern, is that he should only be able to go from side to side horizantaly and if Target area intersected; attack/charge verticaly.
( i will include some code bellow. sorry if my english is bad. )
first comes the main:
boss b;
Character C;
void setup(){
C = new Character();
b = new boss();
}
void draw(){
if (play) {
b.simulate(); //horizantal movement
}
if (b.start) {
b.sim(); //boss vertical attack
}
if (b.intersects(C)){
play = false;
b.start = true;
}
C.character(); //player
b.bounce(); //makes it bounce if horizantal. and stop if vertical
b.Display(); //boss
b.display(); //boss target area
}
Next comes the boss:
class boss {
int x = 10 ;
int y = 10 ;
boolean start = false;
int RW = 50;
int RH = 700;
boolean up = false;
boolean down = true;
boss() {
Location = new PVector( x+25, y ); //vector for the location of the boss
Velocity = new PVector( 5, 0 ); // vector for horizaltal movement
speed = new PVector( 0, 10 ); // vector for vertical down movement
speed2 = new PVector(0, -10); // vector for vertical up movement
}
void bounce() {
if ((Location.x == width) ||(Location.x == 0)) { //horizantal movement bounce on screen edge
Velocity.x = Velocity.x * -1;
}
if ((Location.y == 650) || (Location.y == 0)) {
start = false; //makes boss stop if reaches botton or top of the screen
play = true;
if (Location.y == 650) {
RH = -700;
up = true;
down = false; //specificly if it reaches top of screen
}
if (Location.y == 0) {
RH = 700;
down = true; //specificly if it reaches bottom of screen
up = false;
}
}
}
void simulate() {
Location.add(Velocity); //simulates horizantal movement
}
void sim() {
if (down) {
Location.add(speed); //simulates up and down attacking movemnet
}
if (up) {
Location.add(speed2);
}
}
boolean intersects(Character C) {
return Location.x < C.x + C.w && C.x < Location.x + RW &&
Location.y < C.y + C.h && C.y < Location.y + RH; //intersect between player and boss targeting area
}
void Display() {
rect( Location.x, Location.y, 50, 50 ); //boss
}
void display() {
rect( Location.x, Location.y+50, RW, RH ); //boss targeting area
}
}
if anything is unclear i will gladly clear up any confusion. :)
Thanks for sharing the code. It made it much easier.
When I comment this piece (not the if-condition the reset of start after the if)
if ((Location.y == 650) || (Location.y == 0)) {
// start = false;
then the boss starts going back up top and still calls intersects the Character when the co-ordinates match. However, post this the boss keeps bouncing up and down.
There is surely more work to be done on this to take account of the bullets fired and the hits to boss.
Hope this helps. :) It was fun debugging this code. I had never used PDE before this.
ok, here is the "edit"..
Now,
Good News: I can make it go in both directions only when it intersects
Bad News: It keeps going to the other side as long as it is intersecting. So if the Character is stationary then boss keeps intersecting and passing to the other side at least 8-10 times in the current speed.
Anyways, here is the summary. I added and isAttacking flag that tells the program to not stop the boss from crossing over if it has reached the bottom of the frame. The other thing I changed was the intersection condition. Now it just checks for intersection on the X-Axis. If you must compare intersection on the Y-Axis too then intersects is where you need to change & test.
After the long explanation :P Here is the code. Hope this is better.
Main
boss b;
Character C;
Inventory I;
Bullet B;
int previousKey = 0;
int lastKey;
int lastKeyCode;
void setup() {
C = new Character();
b = new boss();
I = new Inventory();
background(128, 128, 128);
size( 700, 700 );
strokeWeight( 10 );
frameRate( 30 );
}
void keyPressed() {
if (key == CODED) {
previousKey = keyCode;
if (keyCode == UP) {
C.MoveUP();
}
if (keyCode == LEFT) {
C.MoveLEFT();
}
if (keyCode == DOWN) {
C.MoveDOWN();
}
if (keyCode == RIGHT) {
C.MoveRIGHT();
}
}
if (key == 'w' || key == 'W') {
attack();
}
if ( key == 'q' || key == 'Q' ) {
if (I.Shoot == true) {
B = new Bullet(C.x, C.y);
this.Shoot();
}
} else if (key == 'e' || key == 'E') {
I.changePop();
}
if (keyPressed) {
if (key == 'a' || key == 'A') {
//play = false;
//b.start = true;
}
}
}
void attack() {
if (I.Attack == true) {
if (previousKey == UP) {
C.AttackUP();
}
if (previousKey == LEFT) {
C.AttackLEFT();
}
if (previousKey == DOWN) {
C.AttackDOWN();
}
if (previousKey == RIGHT) {
C.AttackRIGHT();
}
}
}
void Shoot() {
if (I.Shoot == true) {
if (previousKey == UP) {
B.ShootUP();
}
if (previousKey == LEFT) {
B.ShootLEFT();
}
if (previousKey == DOWN) {
B.ShootDOWN();
}
if (previousKey == RIGHT) {
B.ShootRIGHT();
}
}
}
boolean play = true;
void keyReleased() {
lastKey = 0;
lastKeyCode = 0;
}
void draw() {
background(128, 128, 128);
if (play) {
b.simulate();//side to side
}
if (b.start) {
b.sim(); //boss rush
}
if (b.intersects(C)) {
b.isAttacking = true;
play = false;
b.start = true;
} else {
b.isAttacking= false;
}
C.character();
b.bounce();
b.Display();//boss
b.display();//rush area
C.HPbar();
I.popUp();
if ( key == 'q' || key == 'Q' ) {
if (I.Shoot == true) {
B.bullet();
B.Simulate();
}
}
}
Enemies or Boss
class boss {
PVector Location;
PVector Velocity;
PVector speed;
PVector speed2;
int x = 10 ;
int y = 10 ;
boolean start = false;
int RW = 50;
int RH = 700;
boolean up = false;
boolean down = true;
boolean isAttacking = false;
boss() {
Location = new PVector( x+25, y );
Velocity = new PVector( 5, 0 );
speed = new PVector( 0, 10 );
speed2 = new PVector(0, -10);
}
void bounce() {
if ((Location.x == width) ||(Location.x == 0)) {
Velocity.x = Velocity.x * -1;
}
if ((Location.y == 650) || (Location.y == 0)) {
if (!isAttacking) {
start = false;
}
play = true;
if (Location.y == 650) {
RH = -700;
up = true;
down = false;
}
if (Location.y == 0) {
RH = 700;
down = true;
up = false;
}
}
}
void simulate() {
Location.add(Velocity);
}
void sim() {
//print("\n In Sim UP: [" + up + "] Down: [" + down + "] Location [" + Location + "]");
if (down) {
Location.add(speed);
}
if (up) {
Location.add(speed2);
}
}
boolean intersects(Character C) {
//print ("\nUP: [" + up + "] Down: [" + down + "] X: [" + (Location.x < (C.x + C.w) && (Location.x + RW) > C.x)
//+ "] Y: [" + (Location.y < (C.y + C.h) && (Location.y + RH) > C.y) + "]");
return Location.x < (C.x + C.w) && (Location.x + RW) > C.x;
//&&
// Location.y < (C.y + C.h) && (Location.y + RH) > C.y ;
}
void Display() {
pushStyle();
stroke(0);
fill(255, 0, 0);
rect( Location.x, Location.y, 50, 50 );
popStyle();
}
void display() {
pushStyle();
stroke(0);
strokeWeight(0);
fill(255, 0, 0, 20);
rect( Location.x, Location.y+50, RW, RH );
popStyle();
}
}
I have to make a tron type game with collision detection. I started by making p1 and p2 move and leave a trail behind them.
I tried to make a color collision detection but its not working. I have different variables such as "P1_edge" which is when p1 hits the edge of the screen. I mark that with a red border.
But the only one that seem to be working is when they crash into themselves when the game starts. It instantly finishes as they are already on themselves. if I take that bit away, nothing else detects.
int P1_XPos; //Player 1 position
int P1_YPos;
boolean Player1_Up = false; //Determins what way P1 is going
boolean Player1_Down = false;
boolean Player1_Left = false;
boolean Player1_Right = true;
int P2_XPos; //Player 2 position
int P2_YPos;
boolean Player2_Up = false; //Determins what way P2 is going
boolean Player2_Down = false;
boolean Player2_Left = true;
boolean Player2_Right = false;
boolean Game_State = false; //see if the game is over (false = over)
final int P1_Edge = 0; //P1 crashed into the edge
final int P1_P1 = 1; //P1 crashed into P1
final int P1_P2 = 2; //P1 crashed into P2
final int P2_Edge = 3; //P2 crashed into the edge
final int P2_P2 = 4; //P2 crashed into P2
final int P2_P1 = 5; //P2 crashed into P1
final int Crash = 6; //Other
void setup()
{
size(700,600); //Set screen dimensions
background(0, 0, 0);
P1_XPos = 100; //set P1 and P2 posision
P1_YPos = 100;
P2_XPos = 600;
P2_YPos = 500;
strokeWeight(3); //Draw the edge of the screen
stroke(255, 0, 0);
line(1, 1, 1, height - 1);
line(1, 1, width - 1, 1);
line(width - 2, 1, width - 2, height - 1);
line(1, height - 2, width - 1, height - 2);
stroke(0, 255, 0); //Draw the starting positions
point(P1_XPos, P1_YPos);
stroke(0, 0, 255);
point(P2_XPos, P2_YPos);
}
void draw()
{
strokeWeight(3);
if (Game_State == true) //if the game is not over
{
stroke(0, 255, 0); //Draw P1
point(P1_XPos, P1_YPos);
MovePlayer1(); //Move P1
stroke(0, 0, 255); //Draw P2
point(P2_XPos, P2_YPos);
MovePlayer2(); //Move P2
Collision_Detection(); //Detect any crashes
}
}
void keyPressed()
{
if(key == CODED) //Controls P1 movement
{
if (keyCode == UP)
{
Player1_Up = true;
Player1_Down = false;
Player1_Left = false;
Player1_Right = false;
}
else if(keyCode == DOWN)
{
Player1_Down = true;
Player1_Up = false;
Player1_Left = false;
Player1_Right = false;
}
else if (keyCode == LEFT)
{
Player1_Left = true;
Player1_Down = false;
Player1_Up = false;
Player1_Right = false;
}
else if (keyCode == RIGHT)
{
Player1_Right = true;
Player1_Down = false;
Player1_Left = false;
Player1_Up = false;
}
}
if ((key == 'W') || (key == 'w')) //Controls P2 movement
{
Player2_Up = true;
Player2_Down = false;
Player2_Left = false;
Player2_Right = false;
}
else if((key == 'S') || (key == 's'))
{
Player2_Down = true;
Player2_Up = false;
Player2_Left = false;
Player2_Right = false;
}
else if ((key == 'A') || (key == 'a'))
{
Player2_Left = true;
Player2_Down = false;
Player2_Up = false;
Player2_Right = false;
}
else if ((key == 'D') || (key == 'd'))
{
Player2_Right = true;
Player2_Down = false;
Player2_Left = false;
Player2_Up = false;
}
if (key == ' ')
{
Game_State = true;
}
}
void MovePlayer1() //Moves P1
{
if(Player1_Up == true)
{
P1_YPos -= 1;
}
if(Player1_Down == true)
{
P1_YPos += 1;
}
if(Player1_Left == true)
{
P1_XPos -= 1;
}
if(Player1_Right == true)
{
P1_XPos += 1;
}
}
void MovePlayer2() //Moves P2
{
if(Player2_Up == true)
{
P2_YPos -= 1;
}
if(Player2_Down == true)
{
P2_YPos += 1;
}
if(Player2_Left == true)
{
P2_XPos -= 1;
}
if(Player2_Right == true)
{
P2_XPos += 1;
}
}
int TestColorP1 (color P1Test) //Detect what color P1 is touching
{
if (P1Test == color (255,0,0))
return P1_Edge;
else if (P1Test == color(0,255,0))
return P1_P1;
else if (P1Test == color(0,0,255))
return P1_P2;
else return Crash;
}
int TestColorP2 (color P2Test) //Detect what color P2 is touching
{
if (P2Test == color (255,0,0))
return P2_Edge;
else if (P2Test == color(0,255,0))
return P2_P1;
else if (P2Test == color(0,0,255))
return P2_P2;
else return Crash;
}
void Collision_Detection()
{
color P1_Pixel; //This is the color P1 is touching
color P2_Pixel;
P1_Pixel = get(P1_XPos, P1_YPos); //Declare is as P1 position
P2_Pixel = get(P2_XPos, P2_YPos);
if (TestColorP1(P1_Pixel) == P1_Edge) //See if P1 has crashed
{
background(0);
Game_State = false;
}
else if (TestColorP1(P1_Pixel)== P1_P1)
{
// background(0);
// Game_State = false;
}
else if (TestColorP1(P1_Pixel) == P1_P2)
{
background(0);
Game_State = false;
}
if (TestColorP2(P2_Pixel) == P2_Edge) //See if P2 has crashed
{
background(0);
Game_State = false;
}
else if (TestColorP2(P2_Pixel)== P2_P1)
{
background(0);
Game_State = false;
}
else if (TestColorP2(P2_Pixel) == P2_P2)
{
// background(0);
// Game_State = false;
}
else if (TestColorP2(P2_Pixel) == Crash)
{
}
}
I know it's long, but you should be able to just copy and paste this in a processing sketch and it will work. I have also left comments so you know why I've added each bit of code.
This was a real head scratcher- good question.
The biggest thing throwing you off is the fact that Processing enables anti-aliasing by default. This causes your colors to be just a little different than what you expect. In most sketches, this is a good thing, since it makes things look better. But since you're using the exact color values, this is screwing you up. You can prove this by taking a screenshot of your sketch and then sampling your colors.
To disable this, simply call noSmooth() at the beginning of your sketch. More info can be found in the reference here.
The next thing screwing you up is that your stroke weight is set to 3, but you're only moving the players 1 pixel at a time. This causes the players to stay "inside" the last point that was drawn, which is why they're constantly running into themselves.
To fix that, you could simply call strokeWeight(1); at the beginning of the draw() function. Or if you need a stroke weight of 3, then make sure you move the player outside of the circle that was just drawn.
That'll fix your problem here, but in the long run, you'd probably be better off keeping track of previous player positions in a data structure like an ArrayList of PVectors. Then you'd redraw them each time draw() was called instead of only drawing them once. And instead of trying to check colors manually, it would be easier to do collision checks in only certain parts of the paths, to avoid the above case.
I have been trying to do player intersection with a small project i'm doing, and I can't seem to make it work. I got the Intersection to work with the player and the wall, but it's very buggy, by buggy I mean, it draws the player in the wall then moves him back instantly. (Check Gyazo for gif of this). I'm pretty sure the problem is that it only checks if the player is in the wall, and not WILL be in the wall, but I can't seem to figure out how to check this. This is what I have so far:
public void intersectsBox2(Rectangle r, Rectangle r2) {
P1 = new Point((int) r.getMinX(), (int) r.getMinY());
P2 = new Point((int) r.getMaxX(), (int) r.getMaxY());
P3 = new Point((int) r2.getMinX(), (int) r2.getMinY());
P4 = new Point((int) r2.getMaxX(), (int) r2.getMaxY());
if ((P2.y < P3.y || P1.y > P4.y || P2.x < P3.x || P1.x > P4.x)
&& !intersectsBox(playerRectangle(), noWalls[0])) {
isInsideWalls = true;
}
}
// Gets the players rectangle
public Rectangle playerRectangle() {
return new Rectangle(9 + dx, 23 + dy, 54, 90);
}
This is to make the player Move:
public void playerMovement() {
if (isInsideWalls) {
System.out.println("YOU ARE IN THE BOX!");
if (animation == down) {
dy -= moveSpeed;
isInsideWalls = false;
} else if (animation == up) {
dy += moveSpeed;
isInsideWalls = false;
} else if (animation == left) {
dx += moveSpeed;
isInsideWalls = false;
} else if (animation == right) {
dx -= moveSpeed;
isInsideWalls = false;
}
} else {
// Moves the player
if (moving == downMove) {
dy += moveSpeed;
moving = 0;
} else if (moving == upMove) {
dy -= moveSpeed;
moving = 0;
} else if (moving == leftMove) {
dx -= moveSpeed;
moving = 0;
} else if (moving == rightMove) {
dx += moveSpeed;
moving = 0;
}
}
This is to check for the intersection:
//Checks for intersection
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
intersectsBox2(walls[i][j], playerRectangle());
}
}
Not really sure if this is needed but heres the full Game.java if you need to see this: http://pastebin.com/GrDy689d
Also here is the Gif of the problem: http://i.gyazo.com/1f31f739897af78f81e61cf22ac772db.mp4
P.S: It's on purpose I can only go into 1 box at the moment for testing purposes.
You could move the player, then check to see if it is in a wall and, if it is, undo the move (or better, calculate a new location as the result of a move, check it, and if it is good, only then move the player there). Note that this assumes a single move can't put you all the way on the other side of a wall, but then it looks like your code does, too.
I have code that generates projectiles corresponding to different directions of a boat sailing on the ocean. The direction is determined by the speeds of the object, looping clockwise where 0 is north through 7 as North West. In My keyPressed function, I can move around with the arrow keys just fine. Furthermore, If I press the space button to activate the cannons, everything works well, except if I'm heading north west. In this case, no bullet is fired, and my java program emits a little beep.
The keyPressed code
public void keyPressed(KeyEvent e) { //TODO switch to keyBindings to remove pause after the initial key press
// if the key is pressed, move up
if(e.getKeyCode() == KeyEvent.VK_DOWN){
//move the board down.
dy = speed;
}
if(e.getKeyCode() == KeyEvent.VK_UP){
// move spaceship upwards
dy = -speed;
}
if(e.getKeyCode() == KeyEvent.VK_LEFT){
dx = -speed;
}
if(e.getKeyCode() == KeyEvent.VK_RIGHT){
dx = speed;
}
dir = myShip.getDirection(dx, dy); // determine direction so that the draw function can draw the correct sprite.
if(e.getKeyCode() == KeyEvent.VK_I){ // info key.
System.out.println(getCurrentTile().getClass().getName());
Tile t = getCurrentTile();
if(t.isDockTile()){
Docks d = (Docks) t;
System.out.println(d.getName());
}
}
if(e.getKeyCode() == KeyEvent.VK_M && getCurrentTile().isDockTile()){
if(getCurrentTile().isDockTile()){
mission = new Mission(); // create a new mission.
Docks d = (Docks) getCurrentTile();
mission.init(d); // initialize using the dock's name.
isMissionAssigned = true; // yay! we have a Mission!
} else {
System.out.println("You can't get a mission if you're not at a port!");
}
}
// fire a bullet
if(e.getKeyCode() == KeyEvent.VK_SPACE){ // TODO - NW seems to be broken.
bullet = new Projectile(bulletSpeed, dir, 10);
System.out.println("Created a bullet with direction " + dir);
bullet2 = new Projectile(bulletSpeed, myShip.getOppDir(dir), 10);
}
}
And my two functions for getting the Direction of the ship.
public int getOppDir(int d){
// since there are 4 directions, add 4 to get opposite.
// use opposite to move back to 0 if > than 8
for(int i = 0; i < 4; i++){
d++;
if(d >= 8){
d = 0;
}
}
return d;
}
public int getDirection(int dx, int dy){ // determines the direction the ship is facing based on speeds.
// 0 = N, 1 = ne, 2 = e, 3 = se, 4 = s, 5 = sw, 6 = w, 7 = nw
int tempDir = 0;
if( dx == 0 && dy < 0){
// north
tempDir = 0;
} else if(dx == 0 && dy > 0){
// south
tempDir = 4;
} else if(dx > 0 && dy == 0){
// east
tempDir = 2;
} else if(dx > 0 && dy < 0){
// ne
tempDir = 1;
} else if( dx > 0 && dy > 0) {
// se
tempDir = 3;
} else if(dx < 0 && dy == 0){
// west
tempDir = 6;
} else if (dx < 0 && dy < 0){
//northWest
tempDir = 7;
} else if(dx < 0 && dy > 0){
//south west
tempDir = 5;
}
return tempDir;
}
Thanks in advance for any help!
EDIT : I think this turned out to be a hardware problem. Shifting to ASDW controlls instead of the Arrow keys solved the problem.
I am a diploma student making a game based on processing, it's a tower defense game where a heroine would be shooting arrows at zombies charging towards the castle. I have multiple issues with this.
The charger zombies do not respawn after being shot dead.
All of the charger zombies die together when I shot only one charger zombie.
Supposedly I wanted the zombies to spawn in waves repeatedly after a group of them has been shot down, and then I want the charger zombies to die individually, depending on the one I click on.
Here's my source code:
import processing.opengl.*; // transparency
import gifAnimation.*; // after add gifAnimation library
import ddf.minim.*; // importing music
PImage backgroundImg;
PImage animation;
int counter;
//settings
int score = 50, totalScore = 0;
int titleX = 200, titleY = 200;
boolean shotsFired = false;
PFont scorePoints, castleHealthPoints, font; //font for startingScreen
int chargerKilled;
//Charger class
int maxChargerOnScreen;
Charger[] chargerArr; //chargerArray undefined
int chargerIndex;
final int numCharger = 300;
ArrayList<Charger> onScreen = new ArrayList<Charger>();
boolean chargerReachedTarget = false, chargerShot = false, chargerDive = true;
Gif chargerCharge, chargerAttack, chargerDied, shootingStance;
int chargerMoveX = 800, chargerMoveY = 450;
// CastleWallHealth
int castleHealth = 1000;
// audio
Minim minim;
AudioPlayer song;
AudioSnippet arrowShoot;
//-------------------------------Codes start here --------------------------------------------------//
void setup() {
//ipad mini size
// frameRate(10);
frameRate(60);
size(800, 600);
smooth();
minim = new Minim(this);
// song = minim.loadFile("InGameSoundtrack.mp3");
// song.play();
arrowShoot = minim.loadSnippet("arrowSound1.wav");
backgroundImg = loadImage("GameBackground.jpg");
backgroundImg.resize(800, 600);
chargerCharge = new Gif(this, "ChargerCharge.gif");
chargerAttack = new Gif(this, "ChargerAttack.gif");
chargerDied = new Gif(this, "ChargerDie.gif");
gargoyleFly = new Gif(this, "GargoyleFly.gif");
gargoyleAttack = new Gif(this, "GargoyleAttack.gif");
shootingStance = new Gif(this, "ShootingGif.gif");
scorePoints = createFont("Arial", 16, true);
castleHealthPoints = createFont("Arial", 16, true);
// loopingGif.play() plays the animation without loop
// must make charger
chargerCharge.play();
chargerAttack.play();
chargerDied.play();
resetGames(); // starts with respawning 5 charges
}
void draw() {
// backgroud
background(backgroundImg);
image(shootingStance, 120,200);
// scores and health
textFont(scorePoints, 15);
fill(0);
text("Score: " + totalScore, 100, 100);
displayCastleHealth();
//*********************************************charger settings code********************************************************************
// If there's no more zombies. prompt reset (screen no zombies) , index from 0 add till 300 then game won
if (onScreen.size() == 0 && chargerIndex == numCharger) {
println("Game won! :)");
// gameWon = true;
}
// while onScreen charger less than 5 only and chargerIndex havent reach 300 it will only respawn
while (onScreen.size () < maxChargerOnScreen && chargerIndex <= numCharger - 1) {
if (chargerIndex < chargerArr.length) { // <--- this is the problem chargerArrayLength
Charger chargerMobs = chargerArr[chargerIndex];
// starts from chargerArray[0] to chargerArray[300]
onScreen.add(chargerMobs);
chargerIndex++;
// chargerIndex keeps looping why?
// println("ADDED ZOMBIE TO ONSCREEN Zombs on screen: " + onScreen.size());
}
}
// Adjusts maxZombOnScreen based off the current index Difficulties?
if (chargerIndex == 10)
maxChargerOnScreen++;
else if (chargerIndex == 50)
maxChargerOnScreen++;
else if (chargerIndex == 100)
maxChargerOnScreen += 2;
else if (chargerIndex == 150)
maxChargerOnScreen += 2;
else if (chargerIndex == 190)
maxChargerOnScreen += 3;
else if (chargerIndex == 250)
maxChargerOnScreen += 3;
else if (chargerIndex == 260)
maxChargerOnScreen += 3;
else if (chargerIndex == 270)
maxChargerOnScreen += 5;
// removes dead zombies, living zombies act normally
for(int i = 0; i < onScreen.size(); i++) {
Charger c = onScreen.get(i);
// add money when a zombie is dead
// if (c.getHealth() <= 0)
if (chargerShot==true) {
c.chargerDying();
onScreen.remove(i);
chargerKilled++;
i--;
} else {
c.act(); ///it should just act
// c.displayHealth(); // if gt time only do
// }
}
}
// creating list of predetermined zombies and their characteristics
println("chargerIndex: " + chargerIndex); // debug
println("onScreenSize: " + onScreen.size());
// println("ChargerArray: " + chargerArray.length); chargerArray point null?
// cursor
if (mouseY > height - 500) {
noFill();
stroke(255, 0, 0);
ellipse(mouseX, mouseY, 35, 35);
line(mouseX - 25, mouseY, mouseX + 25, mouseY);
line(mouseX, mouseY - 25, mouseX, mouseY + 25);
}
}
void resetGames() {
// resetting variables
chargerIndex = 0;
maxChargerOnScreen = 5;
chargerKilled = 0;
createNewCharger();
}
void createNewCharger() {
Charger[] temp = new Charger[numCharger];
for (int i = 0; i < numCharger; i++)
temp[i] = new Charger((int) random(800, 1200), chargerMoveY);
chargerArr = temp;
}
//____________________________________________________________________________________________________________-
class Charger {
private int chargerMoveX, chargerMoveY;
Gif chargerGif; // by default
// chargerGif will change based on input (either it reaches the castle or its shot)
// no constructor
Charger() {
chargerMoveX = 0;
chargerMoveY = 450;
}
// overloaded constructor
Charger(int cMoveX,int cMoveY) {
chargerMoveX = cMoveX;
chargerMoveY = cMoveY;
}
void act() { // use
// if reached castle it wont move
if (chargerMoveX <= 180) {
// remove gif images
chargerDive = false;
chargerReachedTarget = true;
}
// if not shot or reached castle it will move
if (chargerDive == true) {
chargerGif = chargerCharge;
image(chargerGif, chargerMoveX, chargerMoveY);
chargerMoveX -= 2;
}
// if reached castle perform attack animation
if (chargerReachedTarget == true) {
chargerGif = chargerAttack;
image(chargerGif, chargerMoveX - 80, chargerMoveY - 120);
}
if (mousePressed &&
mouseX < chargerMoveX + 180
&& mouseX > chargerMoveX
&& mouseY < chargerMoveY + 120
&& mouseY > chargerMoveY) {
// score board
totalScore = totalScore + score ;
float r = random(50);
println(r);
chargerShot = true;
chargerDive = false;
}
}
void chargerDying() {
chargerReachedTarget = false;
chargerGif = chargerDied;
image(chargerGif, chargerMoveX, chargerMoveY);
}
}
void displayCastleHealth() {
if (castleHealth <= 0) {
fill(250, 70, 0);
textFont(castleHealthPoints, 20);
text("HP: 0", 100, 50);
} else {
fill(250, 70, 0);
textFont(castleHealthPoints, 20);
text("HP: " + castleHealth, 100, 50);
}
}
void mousePressed() {
strokeWeight(2);
arrowShoot.rewind();
arrowShoot.play();
for (int i = 0 ; i < 3; i++)
shootingStance.play();
shotsFired = true;
}
void mouseReleased() {
strokeWeight(1);
if (shotsFired == true)
shootingStance.pause();
}
public void stop() {
arrowShoot.close();
}
Majority of the problems from the charger came from here:
if (onScreen.size() == 0 && chargerIndex == numCharger) {
println("Game won! :)");
// gameWon = true;
}
// while onScreen charger less than 5 only and chargerIndex havent reach 300 it will only respawn
while (onScreen.size () < maxChargerOnScreen && chargerIndex <= numCharger - 1) {
if (chargerIndex < chargerArr.length) { // <--- this is the problem chargerArrayLength
Charger chargerMobs = chargerArr[chargerIndex];
// starts from chargerArray[0] to chargerArray[300]
onScreen.add(chargerMobs);
chargerIndex++;
// chargerIndex keeps looping why?
// println("ADDED ZOMBIE TO ONSCREEN Zombs on screen: " + onScreen.size());
}
}
// Adjusts maxZombOnScreen based off the current index Difficulties?
if (chargerIndex == 10)
maxChargerOnScreen++;
else if (chargerIndex == 50)
maxChargerOnScreen++;
else if (chargerIndex == 100)
maxChargerOnScreen += 2;
else if (chargerIndex == 150)
maxChargerOnScreen += 2;
else if (chargerIndex == 190)
maxChargerOnScreen += 3;
else if (chargerIndex == 250)
maxChargerOnScreen += 3;
else if (chargerIndex == 260)
maxChargerOnScreen += 3;
else if (chargerIndex == 270)
maxChargerOnScreen += 5;
// removes dead zombies, living zombies act normally
for(int i = 0; i < onScreen.size(); i++) {
Charger c = onScreen.get(i);
// add money when a zombie is dead
// if (c.getHealth() <= 0)
if (chargerShot==true) {
c.chargerDying();
onScreen.remove(i);
chargerKilled++;
i--;
} else {
c.act(); ///it should just act
// c.displayHealth(); // if gt time only do
// }
}
}
Evaluation and criticism is appreciated.
There are several issues with the code, but for now, I'll ignore the parts that are somewhat "not clean" or "not elegant", and focus on the main problem that was the reason for the question:
The state of all Chargers instances was the same. The fields
boolean chargerReachedTarget = false, chargerShot = false, chargerDive = true;
have been defined globally. Just by moving this line (that is, these 3 fields) into the Charger class, and changing the line
if (chargerShot==true) {
to
if (c.chargerShot==true) {
the game already seemed to be much closer to what you presumably have been looking for. After this modification, it was possible to shoot individual opponents, and new opponents kept coming after the old ones had disappeared.
Again: The code is not really nicely structured, and there are many possible minor improvements. For example, something like if (c.chargerShot==true) { ... } should better be if (charger.isShot()) { ... }. But I'm not so familiar with processing and its best practices, so I'm not sure how the "best" solution would look like in a global sense...