I'm making really simple game, but I'm stuck with a weird problem; I want zombie to hit character when he can but, he hits me two times instead of one time.
void zombieAttack(float distance){
if(zombieCanAttack && (distance < charSizeX/2+zombieSize/2)){
charApplyDamage(5);
zombieAttackCounter_obj.counter(0);
zombieAttackCounter = 0;
println("second " + zombieCanAttack);
zombieCanAttack = false;
}
}
I even deleted the code that makes zombieCanAttack true when the timer says so, so there is nothing that makes zombieCanAttack true, but even so program gives me this output two times: "second true". This causes zombie to hit character twice instead of one time. Why does it enters if statement twice?
Edit: Here is the full zombie class:
class Zombie {
float zombieX, zombieY, zombieSizeX, zombieSizeY, zombieSize, zombieHp, zombieDamage,
zombieSpeed, zombieThresholdX, zombieThresholdY, zombieAttackCounter;
boolean zombieFlip, zombieCanAttack = true;
Counter zombieAttackCounter_obj = new Counter();
void instantiateZombie(float x, float y, float sizeX, float sizeY, float hp,
float damage, float speed, int thresholdX, int thresholdY){
zombieX = x;
zombieY = y;
zombieSizeX = sizeX;
zombieSizeY = sizeY;
zombieSize = (sizeX+sizeY)/4;
zombieHp = hp;
zombieDamage = damage;
zombieSpeed = speed;
zombieThresholdX = thresholdX;
zombieThresholdY = thresholdY;
}
void zombieAI(){
zombieAttackCounter = zombieAttackCounter_obj.counter(-1);
noStroke();
fill(255, 0, 0);
rect(zombieX, zombieY, zombieSizeX, zombieSizeY);
float distance = dist(charX, charY, zombieX, zombieY);
if(distance+zombieSizeX/2 > charSizeX/2+zombieSizeX/2){
zombieWalk();
} else {
zombieAttack(distance);
}
//println("first " + zombieCanAttack);
if(zombieAttackCounter > 1.5){ /*zombieCanAttack = true; */}
}
void zombieWalk(){
if(zombieX-charX < zombieThresholdX && zombieX-charX > -zombieThresholdX){ }
else if(zombieX-charX < 0){
zombieX+=zombieSpeed; zombieFlip = true;
}
else{
zombieX-=zombieSpeed; zombieFlip = false;
}
if(zombieY-charY < zombieThresholdY && zombieY-charY > -zombieThresholdY){ }
else if(zombieY-charY < 0){
zombieY+=zombieSpeed;
}
else{
zombieY-=zombieSpeed;
}
}
void zombieAttack(float distance){
if((zombieCanAttack) && (distance < charSizeX/2+zombieSize/2)){
charApplyDamage(5);
zombieAttackCounter_obj.counter(0);
zombieAttackCounter = 0;
println("second " + zombieCanAttack);
zombieCanAttack = false;
}
}
}
Here is the full .pde in any case: http://paste.ubuntu.com/7824949/
#HotLicks good point ... there is two zombies because of using this statement to add one zombie
for(int i = 0; i < zombieNumber+1; i++){
zombieHolder.add(new Zombie());
}
where the value of zombieNumber is 1 and according to implementation of Zombie class they are with same parameters (why you instantiate them like this?) and move as one so they hit you twice ... try to increase the zombieNumber to see if this problem is really here.
Related
Im new to programming and I'm making a aim trainer game where you hit different circles and have to hit one before it changes to the next circle. I having some trouble though. I can't figure out how to make a hitbox for the circles that change for each circle and how to increase the score.
The code is in open processing in pjs.
class Timer {
int time;
int duration;
Timer() {
duration = 100;
reset();
}
void reset() {
time = millis() + duration;
}
boolean alarm() {
if ( millis() > time ) {
time = millis() + duration;
return true;
}
return false;
}
}
float x,y,s; //size and position of circles
color c; //colour of circles
int score = 0; //score
int miss = 0; //misses
Timer timer = new Timer();
void setup() {
size(700, 500);
timer.duration = 2000; //changes the circle every 2 seconds
missed =+ 1;
newEllipse(); // Make initial circle.
}
void draw() {
background(100);
fill(c);
text("SCORE: " + str(score),620,20);
text("MISSED: " + str(miss),20,20);
ellipse(x, y, s, s);
if( timer.alarm() ){
newEllipse();
}
}
void mousePressed(){
if( overEllipse() ){
score =+1;
newEllipse();
}
}
boolean overEllipse(){
if(mouseX > x && mouseX < x+s && mouseY > y && mouseY < y + s);
}
void newEllipse() {
s = random(5,min(50,50));
x = random(0, width - s);
y = random(0, height - s);
c = color( random(255), random(255), random(255) );
timer.reset();
}
Once I tried your code I realized that you were going for something very simple, so no need for OOP today. I fixed and commented your code so you can tweak it and test stuff:
float s; //size of circles
PVector targetPosition; // position of target
color c; //colour of circles
int score = 0; //score
int miss = 0; //misses
Timer timer = new Timer();
void setup() {
size(700, 500);
timer.duration = 2000; //changes the circle every 2 seconds
newEllipse(); // Make initial circle.
}
void draw() {
background(100);
fill(255); // easier to read if you don't change the color all the time
text("SCORE: " + str(score), 620, 20);
text("MISSED: " + str(miss), 20, 20);
fill(c);
ellipse(targetPosition.x, targetPosition.y, s, s);
if ( timer.alarm() ) {
miss += 1; // added a 'miss' when the user isn't able to click the target in due time
newEllipse();
}
}
// notice that I switched this method for 'mouseClicked' instead of 'mousePressed'
// the difference is that this works on a simple click, and run once per click instead of continuously
void mouseClicked() {
if (overEllipse()) {
score += 1;
newEllipse();
} else { // added a 'miss' when the user clicks at random
miss += 1;
}
}
boolean overEllipse() {
// these 3 lines are giving you feedback so you know how close to the target you were
PVector mousePosition = new PVector(mouseX, mouseY);
println(mousePosition.dist(targetPosition) + " / " + s/2);
// you only need the next line if you don't care about the feedback
return mousePosition.dist(targetPosition) < s/2;
}
void newEllipse() {
s = random(10, 50); // I removed the `min(50,50)` because the minimum number between 50 and 50 is... 50. Maybe you were going for something else, but like this it was not needed
targetPosition = new PVector(random(s/2, width - s/2), random(s/2, height - s/2));
c = color( random(255), random(255), random(255) );
timer.reset();
}
class Timer {
int time;
int duration;
Timer() {
duration = 100;
reset();
}
void reset() {
time = millis() + duration;
}
boolean alarm() {
if ( millis() > time ) {
time = millis() + duration;
return true;
}
return false;
}
}
The main problem here was that the method overEllipse made no sense, so I set it on fire and rewrote it using a PVector instead of straight coordinates. I did it mostly because it's easier than to use math to determine if we're clicking inside the target later (the PVector class will straight up do it for you, it's an awesome tool, take a look at how I tweaked the overEllipse method and how it's easy with this tool!). I also added some feedback as console println so you can know how close you clicked from the target.
I'll be around of there's something you'd like me to explain. Have fun!
I have been working on android apps for a long time but now I have decided to create a game aside with my pre-calculus final. I have completed the whole code and it works perfectly except one tiny issue. First of the game is based on flying pig(my classmate's face) avoiding top and bottom osticle. I developed an algorithm so that the obsticles are evenly spaced and based on random selection placed either as the top or bottom of the screen but never both at the same time!. The algorithm that needs improvement is in the 3rd code segment!
This is the screenshot of the problem: screenshot here
(My account is new so stackoverflow wont let me to share photos directly)
This is the class that calls updates for all dynamic objects (ship = pig, bacon = bonus item, BM = BarrierManager class's update() which updates the obsticles)
//this will update the resources
void Update(float dt) {
ship.update(dt);
//bumbing
if (!ship.death) {
background.update(dt);
**BM.update(dt);**
for (int i = 0; i % 5 == 0; i++) {
bacon.update(dt, BM.position);
}
}
ArrayList<Point> bacon_point = new ArrayList<Point>(bacon.getArray());
if (ship.bump(bacon_point.get(0), bacon_point.get(1), bacon_point.get(2), bacon_point.get(3))) {
bacon.setX(-200);
bacon.setY(-200);
Message msg = BM.game_panel.game.handler.obtainMessage();
msg.what = 0;
BM.game_panel.game.handler.sendMessage(msg);
}
for (int i = 0; i < BM.TopWalls.size(); i++) {
ArrayList<Point> temp = new ArrayList<Point>(BM.TopWalls.get(i).getArray());
//after we have accest the TopWalls arraylist we can call bump that check TopWalls object's points position with the pig's points
ArrayList<Point> temp2 = new ArrayList<Point>(BM.BottomWalls.get(i).getArray());
//after we have accest the TopWalls arraylist we can call bump that check BottomWalls object's points position with the pig's points
if ((ship.bump(temp.get(0), temp.get(1), temp.get(2), temp.get(3))) || (ship.bump(temp2.get(0), temp2.get(1), temp2.get(2), temp2.get(3))) || ship.death) {
ship.death = true;
game.onStop();
while(f==0) {
MediaPlayer mp = MediaPlayer.create(game, R.raw.explosion_fart);
mp.start();
f++;
}
f++;
Message msg = BM.game_panel.game.handler.obtainMessage();
msg.what = 1;
BM.game_panel.game.handler.sendMessage(msg);
i = BM.TopWalls.size()-1;
if(f == 8){
thread.setRunning(false);
}
}
}
}
In the BarrierManager I have created this update method which takes float dt = MainTheards general time for the game.
TopWalls is ArrayList this ArrayList is composed of top obsticles. Bottom walls is the same but BottomWalls.
//zreb decides if it should create TopWalls or BottomWalls object. This parameter is later transfered to the Barier.update method where I work with it
public void update(float dt){
for (int i=0;i<Num+1; i++) {
int zreb = new Random().nextInt(2);
//{if} to make the spacing bigger
if (i % 5 == 0){
**TopWalls.get(i).update(dt, true, zreb);
BottomWalls.get(i).update(dt, false, zreb);**
if(zreb == 0){
position.set(TopWalls.get(i).getX(), TopWalls.get(i).getY());
}
else{
position.set(BottomWalls.get(i).getX(),BottomWalls.get(i).getY());
}
}
}
}
Now this algoritm in the Barrier.class is where the magic went wrong. This update method takes the float dt mentioned earlier, a boolean variable for determining if the obsticle we work with at that instance is the Top or Bottom, and the zreb random int that determines if the top or bottom obsticle is going to be shown.
//problem! needs to be discussed
public void update(float dt, boolean b, int zreb) {
//checking if the barrier is still there
if (x<-bitmap.getWidth()){
//'b'is passed from the Barriermanager - 'update' method, determining if we have to use monkey-true or farmer-false
int raz = 200;
int vyska = BM.dpos;
//'zreb' helps me to randomly determine if monkey or ballard is going to appear
//here it determines if we are going to have Top or Bottom obsticle in the game
if(zreb == 1) {
vyska = BM.dpos - raz;
}
else {
vyska = BM.dpos + raz;
}
//koniec tohto trienedia
if (b)
{
//setting the y value for the top wall
y = vyska - BM.dl/2 - bitmap.getHeight()/2;
}
else{
//setting the y value for bottom wall
y = vyska + BM.dl/2 + bitmap.getHeight()/2;
}
//setting x-value
x = (int) (x +bitmap.getWidth()*(BM.TopWalls.size()-1));
}
x = (int) (x - BM.game_panel.ShipSpeed*dt);
}
Do you have any idea why this "one-or-the-other" condition is not working properly?
This would help me lot because this error made me deactivate the app from the store.
I just started a new 2D game using Java, LWJGL, and Slick Util but I can't seem to figure out a good way to make collision detection.
If I wanted to, it would be easy to detect collision between 2 entities with the Rectangle intersect method, but it can only check the collision with a certain area you specify.
I have thought that I could make a list of every entity and its coordinates as its created and then run the intersect method through the list, but then it would check for collision with every entity on the entire map for every time the game updated and I think that would be too inefficient.
Does anyone know a more efficient way to create collision detection? If there was some way i could check if there was an entity at every point the character moved that would probably be the best.
If I have not enough information or I made this sound too confusing please tell me and I can try to clarify things. Also as a side question, what are the benefits of using slick util or slick 2D over one another. Thanks for the help!
The usual way to solve this is a scene graph, a hierarchical system of the objects of the game world.
You might want to look at this and this.
Shortened: you logically group your objects under nodes and assign the nodes a bounding rectangle that encompasses all its sub-nodes and leaves(objects). Everything is grouped again under one main node to access the tree. Now you can test a object for collision with a node, usually starting from the main node. If you get a hit you check its sub-nodes and leaves.
This will take some time to implement but can cut down on CPU usage if the tree structure/grouping is done right. It has also the benefit that you can implement local transforms which makes moving objects relative to each other easier.
Because I hate "The usual way", I made an array of all the coordinates and then checked if a single point hit the coordinate.
Here is a slight modification of my code to demonstrate (It is in 3D):
for (CannonBall can : GameServer.ballss){ //Go through all cannonballs
if (can.owner != cl){ //Can.owner is the ship, cl is the player the cannonball is being checked with to see if colliding.
int distancex = (int) (can.x - cl.z);
int distancez = (int) (can.z - cl.x);
final int distancey = (int) (can.y - cl.y);
double xRot = Math.cos(Math.toRadians(cl.rotation)) * (distancex - 0) - Math.sin(Math.toRadians(cl.rotation)) * (distancez - 0) + 0;
double zRot = Math.sin(Math.toRadians(cl.rotation)) * (distancex - 0) - Math.cos(Math.toRadians(cl.rotation)) * (distancez - 0) + 0;
distancex = (int) xRot;
distancez = (int) zRot;
try{
if (true){ //Skip different coordinates for different ships for demonstration purposes
i = GameServer.coords[GameServer.DELTA + distancex][GameServer.DELTA + distancez][GameServer.DELTA + (distancey)];
}
if (i == 1){
if (can.owner != cl){
remcan.add(can);
if (can.type == 0){
double damage = (100 + Math.random()*25);
if (cl.type == 1){
damage/=2;
}
if (cl.type == 2){
damage*=2;
}
cl.damage-=damage;
}
if (can.type == 1){
double damage = (Math.random() * 500);
if (cl.type == 1){
damage/=2;
}
if (cl.type == 2){
damage*=2;
}
cl.damage-=damage;
}else{
double damage = (100 + Math.random()*25);
if (cl.type == 1){
damage/=2;
}
if (cl.type == 2){
damage*=2;
}
cl.damage-=damage;
}
crash = true;
if (cl.damage < 1){
if (!cl.sinking){
cl.sinking = true;
}
}
}
}
}catch (Exception e){
e.printStackTrace();
}
}
GameServer.coords is an int[][][], which is given coordinates like so:
public static int[][][] coords;
public void CollisionSetup(){
try{
File f = new File("res/coords.txt");
String coords = readTextFile(f.getAbsolutePath());
for (int i = 0; i < coords.length();){
int i1 = i;
for (; i1 < coords.length(); i1++){
if (String.valueOf(coords.charAt(i1)).contains(",")){
break;
}
}
String x = coords.substring(i, i1).replace(",", "");
i = i1;
i1 = i + 1;
for (; i1 < coords.length(); i1++){
if (String.valueOf(coords.charAt(i1)).contains(",")){
break;
}
}
String y = coords.substring(i, i1).replace(",", "");;
i = i1;
i1 = i + 1;
for (; i1 < coords.length(); i1++){
if (String.valueOf(coords.charAt(i1)).contains(",")){
break;
}
}
String z = coords.substring(i, i1).replace(",", "");;
i = i1 + 1;
//buildx.append(String.valueOf(coords.charAt(i)));
////System.out.println(x);
////System.out.println(y);
////System.out.println(z);
//x = String.valueOf((int)Double.parseDouble(x));
//y = String.valueOf((int)Double.parseDouble(y));
//z = String.valueOf((int)Double.parseDouble(z));
double sx = Double.valueOf(x);
double sy = Double.valueOf(y);
double sz = Double.valueOf(z);
javax.vecmath.Vector3f cor = new javax.vecmath.Vector3f(Float.parseFloat(x), Float.parseFloat(y), Float.parseFloat(z));
//if (!arr.contains(cor)){
if (cor.y > 0)
arr.add(new javax.vecmath.Vector3f(cor));
if (!ship.contains(new Vector3f((int) sx, (int) sy, (int) sz)))
ship.add(new Vector3f((int) sx, (int) sy, (int) sz));
Float.parseFloat(z)));
}
}
public void setUpPhysics() {
//coords = new int[20][20];
coords = new int[80][80][80];
coords1 = new int[80][80];
//coords[-5 + DELTA][7 + DELTA] = 11;
for (javax.vecmath.Vector3f vec : arr){
coords[DELTA+(int) vec.x][DELTA+(int) vec.z][DELTA + (int) vec.y] = 1; //This is line 124
coords1[DELTA+(int) vec.x][DELTA+(int) vec.z] = 1;
}
}
Though it has limitations on collision interaction, it works for cannonballs colliding with a ship and checking the front of a ship to see if it has hit another ship. Also, it uses barely any CPU.
No idea on the opinions of other programmers on such a method.
So I made a java game with jumping some time ago and I used this method for all the moving:
double height = 0, speed = 4;
public static final double gravity = 9.81;
double x = 25;
int a;
int y = (int) (500-(height*100));
boolean left = false, right = false, up = false;
public void the_jump() {
long previous = 0, start = 0;
while(true){
start = System.nanoTime();
if(previous != 0 && up){
double delta = start - previous;
height = (height + (delta/1000000000) * speed);
speed -= (delta/1000000000) * gravity;
y = (int) (500-(height * 100));
}
if(left){
x-= 3;
}
if(right){
x+= 3;
}
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
if(height < 0){
height = 0;
speed = 4;
up = false;
}
previous = start;
}
}
Now It was okay when I did it all with just JComponents and such, but now when I want to implement it in a Slick enviroment, it fails.
The problem is in the while(true){} loop. If I change it against for(int i = 0; i < 1; i++) loop, then moving left and right will work. But this will not work for the jumping. I could increase the i < 1 to i < 5 and then the jump will work, but at the cost of a lot of performance.
So how would people implement this in slick? Right now I am calling the the_jump(); out in my public void update(GameContainer gc, int t) throws SlickException method, and if I use the while loop, the game will crash.
Slick already loop on update(GameContainer gc, int delta), you have to put all the code located in your while loop into the update method.
Moreover, you get the delta time between two update as parameter, and so not have to calculate it.
Feel free to ask me more question ;)
Off Topic, do you know if Slick2d is still maintain ? I switch to libGDX a few month ago, and I really advice you to test it, it's soooo fun :)
I don't really understand where in the code that makes the character bounce to the right side and not countinue.
public void exercise1e() {
PaintWindow pw = new PaintWindow();
Random rand = new Random();
ImageIcon image = new ImageIcon("C:/Users/char.jpg");
int width = pw.getBackgroundWidth();
int height = pw.getBackgroundHeight();
int dx = -2;
int dy = 0;
int x = 250;
int y = rand.nextInt(height-100);
while(true) {
pw.showImage(image, x, y);
PaintWindow.pause(20);
x += dx;
y += dy;
if(x<0) {
dx = -dx;
if (x>0) {
}
}
}
}
If you reach a boundary then change the direction to the opposite, dx=-dx will cause that effect.
Your condition should be applied if reach the left limit.. when x<=0 and also when reached the right limit x>=width
if(x<=0 || x>=width ) {
dx = -dx;
}
Now reset the position of your image to x. Otherwise you are just increasing and decreasing that number.
Something like: image.setLocation(x,y), I can't be sure since I don't know what you are using to render this.
There is a logical contradiction in your current if statements.
if(x<0) {
Only if x is less than 0 evaluate the next if...
if (x>0) {
If x is less than 0 but also is greater than 0, understand the universe.
}
}