Im creating an 'Avoid the Blocks' game, and for this i need to move a character around a grid (2D array) using the keys GHKJ. Every x amount of turns (decreasing as the level increases) a shadow must appear, then that shadow becomes a block and if the player moves into that bloack they lose a life.
Most of this is done for me other than the seemingly simple taski of getting the blocks to appear, here is my code so far for the falling blocks:
public void rocked(){
int rockInit = turn;
if(rockInit > 1){
int save = turn;
System.out.println(turn + " ");
B.board[ran.nextInt(12)][ran.nextInt(12)] = shadow;
if(save == turn - 3){
B.board[rockLocX][rockLocY] = rock;
}
}
}
The system.println is simply for debugging purposes, checking the values are being accesed. Turn is increased by 1 for every move the player makes, ran.nextInt(12) is a randomly generated number between 0 and 11, and B.board is the playing board.
It looks like you're never changing "save" after you initialize it to "turn". So then when you check if(save == turn-3), it will always be false, and so never move the block in. If you want to keep track of how many turns have passed, I would recommend a private instance variable "int turnsPassed" that you can increment each turn. Then for each level, you can check if (turnsPassed % x == 0), where x is as you've described it. Hope that helps!
Related
I have a problem regarding drawing multiple of the same objects. They end on top of each other, and their "Object values" even get added together e.g. if a zombie has "2" movement value and there is added 2 into the current level. Then when zombies are moved, they move "4" each. This does not happen if two different objects are moved e.g. Zombie and Dragon. I have created the following code based on my project - for a simpler overview. However, the behavior is the same.
It should be mentioned the objects of the same type have the same "HashCode". I have also made comments and println to help figure out the problem. Each of the 5 objects have different position (When set). However, they are rendered on top of each other and merged (Movement).
EnemyDatabase enemyDatabase;
ArrayList<Enemy> enemiesInlevel = new ArrayList<Enemy>();
void setup()
{
size(600, 600);
enemyDatabase = new EnemyDatabase();
enemyDatabase.enemies.add(new Enemy("Zombie", 3));
//If dragon is added - Then it can draw both - But only once
//enemyDatabase.enemies.add(new Enemy("Dragon", 10));
//Add 10 zombies to the level
for(int i=0; i< 5;i++)
{
//5 Zombies are created and succesfully added to the database
enemiesInlevel.add(enemyDatabase.enemies.get((int)random(0, enemyDatabase.enemies.size())));;
}
for(int i=0; i<enemiesInlevel.size();i++)
{
//Sets the position of all 5 - Gives random position
Enemy enemy = enemiesInlevel.get(i);
enemy.SetPosition();
}
}
void draw()
{
background(255, 200, 0);
//Draw 5 enemies - Of index 0 (Zombie)
for(int i=0; i<enemiesInlevel.size();i++)
{
Enemy tempEnemy = enemiesInlevel.get(i);
tempEnemy.draw();
//It runs 5 times - print returns 5 total objects in enemiesInlevel
}
}
class EnemyDatabase
{
ArrayList<Enemy> enemies = new ArrayList<Enemy>();
}
class Enemy
{
String enemyName;
int enemyHealth;
PVector enemyPosition;
public Enemy(String name, int hp)
{
enemyName = name;
enemyHealth = hp;
}
public void SetPosition()
{
enemyPosition = new PVector(random(0, width), random(0, height));
//Each of the objects has a random position
println(enemyPosition);
}
public void draw()
{
rect(enemyPosition.x, enemyPosition.y, 25, 25);
}
}
UPDATE
Here is an image of the problem
As the image shows from the output in the image line: The enemies have different positions when added to the array (5 different enemies) However, as the image shows, it still only displays one - And this happens because all of the sudden the positions is the same. I even tried to give a "Random position" in the "DrawImage" all of the enemies still end up having the same position
Hope you guys can figure it out. I certainly have a hard time - I usually don't work in processing Thank you
DrSatan's comment is correct. You're only ever adding a single Enemy to your EnemiesDatabase. So when you select 5 random enemies, you're really just selecting the same enemy 5 times.
It might look like they have different positions in your print statements, but that's because you're printing out the position every time you set it. You're setting it five times, but only the last position really counts for anything.
In other words, you're taking a single instance of Enemy, moving it around the screen 5 times, and printing out the position each time. But then when you draw it, only the last position you moved it to is what you see.
You need to refactor your code so you add more enemies to your EnemyDatabase, but please note that you're going to have similar problems no matter how many enemies are in your EnemyDatabsae, because you don't have any logic that makes sure you don't select the same instance twice. Even if you had 100 enemies in your database, nothing is stopping your random function from selecting the same enemy 5 times.
If I were you, I'd rethink my design. I don't really see the reason to have a separate EnemyDatabase class at all. Maybe just create a function that adds X random enemies to the level, where X is a parameter? That's up to you, but your fundamental problem here is that you only have a single instance of Enemy.
im new to android studio and i want this function to loop and create an infinite ball falling loop which will be scored until the two integers do not match but when i try to run it, it will only loop once and if i change streak = 2 in the else statement the app crashes
public void mainGameLoop(){
do {
//sets Balls integer
setColourint();
ball.setVisibility(View.VISIBLE);
//ball fall
float bottomOfScreen = getResources().getDisplayMetrics()
.heightPixels - (ball.getHeight() * 4);
//fall animation
ball.animate()
.translationY(bottomOfScreen)
.setInterpolator(new AccelerateInterpolator())
.setInterpolator(new BounceInterpolator())
.setDuration(9000);
//once animation is complete compares balls variable with current variable
if (colourint == ranint){
//if they are same then +1 score
score = score+1;
scr.setText(Integer.parseInt(String.valueOf(score)));
} else {
//else game is over
streak = 2;
}
//repeat until game is over
} while (streak == 1);
}
once the balls reached the bottom of the relative layout i want the function to check if the setcoulour int and the ran int are the same and then if the are score = score + 1, ball goes back to the top, the setColourInt function is called and the ball falls again(and so on and so on) but if not loop ends and it's game over...i apologise for my blatant incompetence but I can't imagine you guys don't remember when you too, were this naive when it came to coding. many thanks Tom
You have to give the UI a chance to draw what you're doing. The way you have it coded, whichever method (onStart, onCreate, etc) that calls your mainGameLoop will never return because it's stuck in an infinite loop. This is an error.
One way to do this is to create a View and implement your game draw logic in the onDraw method. The UI thread will call your onDraw method when it is time to draw. Here's an article that talks about this approach: http://cjds.github.io/2014/04/28/Creating-a-simple-android-game/
I'm creating a game with a score system similar to the one in Flappy Bird.
if you didn't get it
When the player successfully passes the right and left
obstacle I want my score variable to increase by 1. I don't know the logic behind it though.
Right now I have (this is inside a for loop checking every obstacle in an update method):
'over' making sure the score only increases by 1.
if (bird.getPosition().y > obstacle.getPosLeft().y) {
if (!over) {
over = true;
score++;
}
and when the obstacle gets off the screen (yes, y is 0 at the bottom, not the top):
if (obstacle.getPosLeft().y + Obstacle.OBSTACLE_HEIGHT < 0){
obstacle.reposition(obstacle.getPosLeft().y + (OBSTACLE_SPACING + Obstacle.OBSTACLE_HEIGHT)* OBSTACLE_COUNT);
over = false;
}
The problem is that you can pass 2 obstacle pairs before the first one gets re-positioned which means that you only get the 2nd point after reposition() is called for obstacle 1.
How would you fix this problem?
Just make a "obstacle.over" boolean so that each has its own state.
I'm trying to create random items in a libgdx project.I'm relatively new to Java,but here is the code I've come up with for the method.
I've been at this for a week now,and figured I'd ask here for an answer.
I've been trying to come up with something that works first.So please do forgive the shabby code.
The number parameter of the method is the number of items that will be created.
The item just needs to have a random x positon,which is generated within the constraints of the width of the container.
The game is as bottom up scroller,with different platforms being generated.
private Item[] generateRandomItems(int number){
Money[] items=new Money[number];
for(int i=0;i<number;i++){
Random r=new Random();
int x =r.nextInt(120)+3;//136 is the width of the container to which the item is to be generated
Money tempitem=generateMoney(x);//generateMoney() just returns a new instance of the Money class with the created x passed in as a param.
if(i!=0) {
for (int j=0;j<i;j++) {
boolean failed=true;
while (failed) {
//getItem() returns the bounding rectangle/circle f the item
if (!Intersector.overlaps(tempitem.getItem(), items[j].getItem())) {
failed = false;
items[i] = tempitem;
}else{
Random random= new Random();
int newX=random.nextInt(120)+3;
tempitem=generateMoney(newX);
}
}
}
}else{
items[i]=tempitem;
}
}
return items;
}
I don't know if this is a correct way to do it or not,but the created Items do collide sometimes.I've been trying to find what's wrong with the code for sometime now.Any suggestions to improve the code are also appreciated.
Edit::I Know that the code is unnecessarily complicated.This is my first attempt at procedural generation.So please do forgive me.
Instead of generating a new random position if there is a collision, you should move it deliberately left or right until there is no collision. To illustrate the problem reusing random generation after each collision, if you have 10 slots and 9 slots are already filled, it could take a long time to find that open slot using random generation as you would be almost certain to hit the same object numerous times. However, if you keep track of where you’ve checked and deliberately move to a new location each time, then the worst case scenario is you’d hit each object one time before finding the empty slot.
You can check how much of an overlap there is and move the object by that amount to clear the object, then check to make sure it didn’t collide with another object next to it, if it did then keep moving it over until there is a free spot. If you hit the edge of the screen, move to the opposite side and keep moving until you find a free spot.
Also, as good coding practice you should avoid hard coding numbers (like 120+3) into method calls. Since you use the same value in multiple places, if you decide to change the width of your container to 500, then you have to change it in all those places...and if you forget to change one you’re opening yourself up for a nightmare of bug hunting. Instead you can either set an integer such as containerWidth=120 or set the container width directly using container.setWidth(120) and then use container.getWidth() each time you call your random method to get the width of the container the random value is being constrained too. Either way will work fine, whichever is better for your workflow. And I know you said this was quick and sloppy code just to get it going, so you may already be aware of this.
Thanks for the answers.I now know that checking each generated item for collision without saving the previously generated item is bad.
But I got the previous code working after some help,and wanted to share it with anyone who would need it in the future.
I moved the checking part into a new method,and added a new flag to see if the item was generated correctly,after checking for collision from all the items before it.
private Item[] generateRandomItems(int number){
Money[] items=new Money[number];
for(int i=0;i<number;i++){
Random r=new Random();
int x =r.nextInt(120)+3;
Money tempitem=generateMoney(x);
if(i>0) {
boolean generated=false;
while (!generated) {
boolean f = checkIfItemOverlapsWithPrevious(items, tempitem);
if (!f) {
items[i] = tempitem;
generated = true;
} else {
Random random = new Random();
int newX = random.nextInt(120) + 3;
System.out.println("Collided");
tempitem = generateMoney(newX);
}
}
}else{
items[i]=tempitem;
}
}
return items;
}
private boolean checkIfItemOverlapsWithPrevious(Money[] items, Money tempitem) {
for(Money item :items){
if(item!=null) {
if (Intersector.overlaps(tempitem.getItem(), item.getItem())) {
return true;
}
}
}
return false;
}
A quick overview of my program: I am making the game War. So when the play button is clicked, two new cards show up with random values. Which ever card has the higher value wins, and a rectangle appears in the middle of the window. As the game goes on, who ever wins has more rectangles pushed to their side (either to the left or right depending on which card wins), but the trick is that if for example the card on the left wins the first three, then the card on the right wins 1, a rectangle is removed, meaning only 2 are going to the left. If the right wins again, another is removed, etc.
The rectangle is created in a separate class called Bar, and here is what I have to create an array with a rectangle that goes to the left.
Bar newBar = new Bar(300,250);
counter = d++;
newBar = new Bar(300-(counter*30), 250);
if(numDi >= bars.length){ //You want it to always be higher
Bar[] temp = new Bar[bars.length +1];
for(int i = 0; i < bars.length; i++){
temp[i] = bars[i];
}
bars = temp; //increments bars by 1
}
bars[numDi++] = newBar;
The idea I have is that I could create an if statement which checks who won and also who won the last game. And if the opposing player won the last game, I would need to subtract a rectangle.
But how would I go about subtracting the rectangle?
And as a side note, I can not use any sort of lists.
You can use a single integer counter. When the right side wins increment it by 1 and when the left side wins decrement it by 1. This way you can easily test with an if statement who has been winning lately and control what happens depending on who wins.
If you can't use a list or queue then I would suggest using two separate arrays, one for the left side and one for the right side. You can increment and decrement them according to the overall score counter.