remove objects from arraylist is doing strange things - arraylist

In the code below, i want the balls to change from ArrayList ballList to another ArrayList oldBalls as soon as their age turns higher than a threshold value.
This code should be very simple but i can't figure out why when the age is same as the threshold (not larger) they disappear and then they come back 2 frames later.
I have checked related questions using iterators for ArrayLists in java but i think there should be a way to do this in processing without java.
Also i cant seem to post any question on the processing forum even though i can sign in, no idea why...
I have reduced the code to the minimum able to reproduce the error.
ArrayList <Ball> ballList;
ArrayList <Ball> oldBalls;
int threshold=4;
PFont font;
void setup(){
size(400,400);
frameRate(0.5);
font=createFont("Georgia", 18);
textFont(font);
textAlign(CENTER, CENTER);
ballList=new ArrayList<Ball>();
oldBalls=new ArrayList<Ball>();
noFill();
strokeWeight(2);
}
void draw(){
background(0);
Ball b=new Ball(new PVector(10, random(height/10,9*height/10)),new PVector(10,0),0);
ballList.add(b);
stroke(0,0,200);
for(int i=0;i<oldBalls.size();i++){
Ball bb=oldBalls.get(i);
bb.update();
bb.render();
text(bb.age,bb.pos.x,bb.pos.y);
}
stroke(200,0,0);
for(int i=0;i<ballList.size();i++){
Ball bb=ballList.get(i);
bb.update();
bb.render();
bb.migrate();
text(bb.age,bb.pos.x,bb.pos.y);
}
}
class Ball{
PVector pos;
PVector vel;
int age;
Ball(PVector _pos, PVector _vel, int _age){
pos=_pos;
vel=_vel;
age=_age;
}
void migrate(){
if(age>threshold){
oldBalls.add(this);
ballList.remove(this);
}
}
void update(){
pos.add(vel);
age+=1;
}
void render(){
ellipse(pos.x,pos.y,24,24);
}
}
Note how balls labelled with age=threshold suddenly disappear...

i guess the problem is here:
for(int i=0;i<ballList.size();i++){
Ball bb=ballList.get(i);
bb.update();
bb.render();
//add this
if(bb.migrate())
i--;
text(bb.age,bb.pos.x,bb.pos.y);
}
and
boolean migrate(){
if(age>threshold){
oldBalls.add(this);
ballList.remove(this);
//and this
return true;
}
return false;
}
migrate() will remove the object from the ballList and reduce it's size by 1.

What it looks like is happening here is because you're altering the List's whilst iterating through them. Consider this for loop you have here
for(int i=0;i<ballList.size();i++){
Ball bb=ballList.get(i);
bb.update();
bb.render();
bb.migrate();
text(bb.age,bb.pos.x,bb.pos.y);
}
Say ballList has 2 balls in it both age 3, the first loops gets ball[0] and then removes it from the list, i will increment and the loop will immediately exit because ballList.size() is now 1. So it's not the ball which gets to age 4 that vanishes but the subsequent one.

Related

Built-in variables not usable in certain cases (Processing 3)

I've been building a program with Processing 3 the last several days (first time going back to Processing since Intro to Computer Science in 2009) and kept having this issue:
public class PolarMap {
...
PVector[][] mapping = new PVector[width][height];
PVector[][] cartesian = new PVector[width][height];
PVector cart = new PVector();
PVector polar = new PVector();
/**
Maps every pixel on the cartesian plane to a polar coordinate
relative to some origin point.
*/
public void Map(float originX, float originY){
for (int x=0; x < width; x++){
for (int y=0; y < height; y++){
...
cart.add(x, y);
polar.add(r, theta);
mapping[x][y] = polar; ***
cartesian[x][y] = cart;
}
}
}
...
}
On the line with the ***, I would always get an Array Index Out Of Bounds thrown. I searched SO, Reddit, and Processing's own documentation to figure out why. If you're not familiar with Processing, width and height are both built-in variables and are equal to the number of pixels high and across your canvas is as declared in the setup() method (800x800 in my case). For some reason, both arrays were not being initialized to this value--instead, they were initializing to the default value of those variables: 100.
So, because it made no sense but it was one of those times, I tried declaring new variables:
int high = height;
int wide = width;
and initialized the array with those variables. And wouldn't you know it, that solved the problem. I now have two 800x800 arrays.
So here's my question: WHY were the built-in variables not working as expected when used to initialize the arrays, but did exactly what they were supposed to when assigned to a defined variable?
Think about when the width and height variables get their values. Consider this sample sketch:
int value = width;
void setup(){
size(500, 200);
println(value);
}
If you run this program, you'll see that it prints 100, even though the window is 500 pixels wide. This is because the int value = width; line is happening before the width is set!
For this to work how you'd expect, you have to set the value variable after the size() function is called. So you could do this:
int value;
void setup(){
size(500, 200);
value = width;
println(value);
}
Move any initializations to inside the setup() function, after the size() function is called, and you'll be fine.

java program for printing the two largest numbers a user inputs

Whenever I run my compiled code, it displays the largest number but it doesn't display the second largest number correctly. Here is my code:
package twoLargestNumbers;
import java.util.Scanner;
//find two largest numbers
public class twoLargestNumbers {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner input=new Scanner(System.in);
int num;
int counter=0;
int largest=0;//largest
int second=0;//second largest
System.out.println("Enter number:");
num=input.nextInt();
while(counter<5){
num=input.nextInt();
if(num>largest){
second=largest;//store largest to second largest
largest=num;//store largest to inputted number
}
else{
if(num>second)
second=num;//store second number to inputed number
}
counter=counter+1;
}
System.out.println("largest number is "+largest);
System.out.println("and second largest number is "+second);
}
}
What am I doing wrong? I reread and read this code and I cannot find out what the error is.
Remove the num=input.nextInt() before the while loop starts.
The initial input is being called and then straight away after the "first" input in the while method is called.
A couple of other tips, usually for a defined length of loop (in this case, 5) you would use a for loop to show your intent a bit more.
Also you can increment counter doing: counter++; or counter += 1;
Assuming the intent of your program is to ask for 5 numbers of input and then display the largest two, that should all help. Hope it did.
Also I don't think this block of code is needed, the second largest is already being stored in the first if statement.
else{
if(num>second)
second=num;//store second number to inputed number
}

Render glitch with custom block boundaries minecraft

I'm creating a mod for Minecraft. Recently, I've tried to make a custom block, and I'm having two issues with it.
My main issue is that the block is rendering incorrectly. I want the block to be smaller in size than a full block. I successfully changed the block boundaries with setBlockBounds(), and while that did make the block render smaller and use the smaller boundaries, it causes other rendering issues. When I place the block, the floor below is becomes invisible and I can see through it, either to caves below, blocks behind it, or the void if there is nothing there. How do I fix that block not rendering? Here's a screenshot:
Additionally, my goal for this block is to emit an "aura" that gives players around it speed or some other potion effect. I have the basic code for finding players around the block and giving them speed, but I can't find a way to activate this method every tick or every X amount of ticks to ensure that it gives players within the box speed in a reliable manner. There are already some blocks in the normal game that do this, so it must be possible. How can I do this?
For your first issue, you need to override isOpaqueCube to return false. You'll also want to override isFullCube for other parts of the code, but that isn't as important for rendering. Example:
public class YourBlock {
// ... existing code ...
/**
* Used to determine ambient occlusion and culling when rebuilding chunks for render
*/
#Override
public boolean isOpaqueCube(IBlockState state) {
return false;
}
#Override
public boolean isFullCube(IBlockState state) {
return false;
}
}
Here's some info on rendering that mentions this.
Regarding your second problem, that's more complicated. It's generally achieved via a tile entity, though you can also use block updates (which is much slower). Good examples of this are BlockBeacon and TileEntityBeacon (for using tile entities) and BlockFrostedIce (for block updates). Here's some (potentially out of date) info on tile entities.
Here's an (untested) example of getting an update each tick this with tile entities:
public class YourBlock {
// ... existing code ...
/**
* Returns a new instance of a block's tile entity class. Called on placing the block.
*/
#Override
public TileEntity createNewTileEntity(World worldIn, int meta) {
return new TileEntityYourBlock();
}
}
/**
* Tile entity for your block.
*
* Tile entities normally store data, but they can also receive an update each
* tick, but to do so they must implement ITickable. So, don't forget the
* "implements ITickable".
*/
public class TileEntityYourBlock extends TileEntity implements ITickable {
#Override
public void update() {
// Your code to give potion effects to nearby players would go here
// If you only want to do it every so often, you can check like this:
if (this.worldObj.getTotalWorldTime() % 80 == 0) {
// Only runs every 80 ticks (4 seconds)
}
}
// The following code isn't required to make a tile entity that gets ticked,
// but you'll want it if you want (EG) to be able to set the effect.
/**
* Example potion effect.
* May be null.
*/
private Potion effect;
public void setEffect(Potion potionEffect) {
this.effect = potionEffect;
}
public Potion getEffect() {
return this.effect;
}
#Override
public void readFromNBT(NBTTagCompound compound) {
super.readFromNBT(compound);
int effectID = compound.getInteger("Effect")
this.effect = Potion.getPotionById(effectID);
}
public void writeToNBT(NBTTagCompound compound) {
super.writeToNBT(compound);
int effectID = Potion.getIdFromPotion(this.effect);
compound.setInteger("Effect", effectID);
}
}
// This line needs to go in the main registration.
// The ID can be anything so long as it isn't used by another mod.
GameRegistry.registerTileEntity(TileEntityYourBlock.class, "YourBlock");

How to write a box2d contact listener using cocos2d?

I've been reading various tutorials on how to write a contact listener, and I can't wrap my head around it.
Here is what I have so far:
In each of the classes that I have representing a physics object I do:
_body->SetUserData(self);
I write a contact listener class containing the following two methods:
void ContactListener::BeginContact(b2Contact* contact)
{
// Box2d objects that collided
b2Fixture* fixtureA = contact->GetFixtureA();
b2Fixture* fixtureB = contact->GetFixtureB();
// Sprites that collided
MyNode* actorA = (MyNode*) fixtureA->GetBody()->GetUserData();
MyNode* actorB = (MyNode*) fixtureB->GetBody()->GetUserData();
}
void ContactListener::EndContact(b2Contact* contact)
{
// Box2d objects that collided
b2Fixture* fixtureA = contact->GetFixtureA();
b2Fixture* fixtureB = contact->GetFixtureB();
// Sprites that collided
MyNode* actorA = (MyNode*) fixtureA->GetBody()->GetUserData();
MyNode* actorB = (MyNode*) fixtureB->GetBody()->GetUserData();
}
I don't know what to do next. I now have the two sprites which are colliding, but I want to do the following:
1) When they collide, I want to remove one of the sprites from the world, based on the type of object. (for example if one a cat object and the other is a mouse object, I want to remove the mouse object.
2) I want to let the cat object know it ate a mouse
3) I want the cat to continue moving as if it didn't contact with the mouse.
4) I still wan't the cat to collide normally with things like the terrain.
What do I do next ? I'm pretty clueless on what to do? How do I get the cat to continue to collide normally with the terrain, but not with the mouse? When do I remove the mouse?
Having an "Entity" class that hold the reference to the Box2D body and does the manipulations on it is definitely a good way to go. If you have a Spaceship class vs. a Meteor class, each of them can supply their own derived methods of controlling the body (AI), but each of them has common logic and code to support operations on "Things that have a body" (e.g. common "Entity" base class). I think you are on the right track.
It gets a little murky when the contacts start happening. This is where you start getting into the architecture of your overall system, not just the structure of the physics world or a single Coco2d Scene.
Here is how I have done this in the past:
First I set up the contact listener, listed below:
class EntityContactListener : public ContactListener
{
private:
GameWorld* _gameWorld;
EntityContactListener() {}
typedef struct
{
Entity* entA;
Entity* entB;
} CONTACT_PAIR_T;
vector<CONTACT_PAIR_T> _contactPairs;
public:
virtual ~EntityContactListener() {}
EntityContactListener(GameWorld* gameWorld) :
_gameWorld(gameWorld)
{
_contactPairs.reserve(128);
}
void NotifyCollisions()
{
Message* msg;
MessageManager& mm = GameManager::Instance().GetMessageMgr();
for(uint32 idx = 0; idx < _contactPairs.size(); idx++)
{
Entity* entA = _contactPairs[idx].entA;
Entity* entB = _contactPairs[idx].entB;
//DebugLogCPP("Contact Notification %s<->%s",entA->ToString().c_str(),entB->ToString().c_str());
msg = mm.CreateMessage();
msg->Init(entA->GetID(), entB->GetID(), Message::MESSAGE_COLLISION);
mm.EnqueueMessge(msg, 0);
msg = mm.CreateMessage();
msg->Init(entB->GetID(), entA->GetID(), Message::MESSAGE_COLLISION);
mm.EnqueueMessge(msg, 0);
}
_contactPairs.clear();
}
void PreSolve(b2Contact* contact, const b2Manifold* oldManifold)
{
b2Fixture* fixtureA = contact->GetFixtureA();
b2Body* bodyA = fixtureA->GetBody();
Entity* entityA = bodyA->GetUserData();
b2Fixture* fixtureB = contact->GetFixtureB();
b2Body* bodyB = fixtureB->GetBody();
Entity* entityB = bodyB->GetUserData();
if(test if entityA and entityB should not have collision response)
{
contact->SetEnabled(false);
}
// Do this if you want there to be collision notification, even if
// there is no response.
AddContactPair(entA,entB);
}
void AddContactPair(Entity* entA, Entity* entB)
{
for(uint32 idx = 0; idx < _contactPairs.size(); idx++)
{
if(_contactPairs[idx].entA == entA && _contactPairs[idx].entB == entB)
return;
// Not sure if this is needed...
if(_contactPairs[idx].entA == entB && _contactPairs[idx].entA == entB)
return;
}
CONTACT_PAIR_T pair;
pair.entA = entA;
pair.entB = entB;
_contactPairs.push_back(pair);
}
// BEWARE: You may get multiple calls for the same event.
void BeginContact(b2Contact* contact)
{
Entity* entA = (Entity*)contact->GetFixtureA()->GetBody()->GetUserData();
Entity* entB = (Entity*)contact->GetFixtureB()->GetBody()->GetUserData();
assert(entA != NULL);
assert(entB != NULL);
// Not sure this is still needed if you add it in the pre-solve.
// May not be necessary...
AddContactPair(entA, entB);
}
// BEWARE: You may get multiple calls for the same event.
void EndContact(b2Contact* contact)
{
}
};
Because of the way the engine works, you can get multiple contact hits for the same bodies. This listener filters them so if two Entities collide, you only get one message.
The Listener only stores the collisions that have occurred. It could be modified to further separate them into "begins" and "ends" for other purposes. Here, contact meant "you've been hit by something". I didn't need to know if it stopped contacting.
The call to NotifyCollisions is the "secret sauce". It sends out a message to both the contacted entities (via a message system) that they hit something and the other Entity is what they hit. Bullet hit ship. Bullet destroys self. Ship damages self based on bullet properties (GetDamageInflicted() method). This in turn signals the graphics system to remove the bullet from the display. If the ship was destroyed, it is destroyed as well.
From an overall execution standpoint:
Before you begin, assign the contact listener.
Each Cycle of your game:
Call "Update" on all your Entities. This updates their physics forces, etc.
Update Box2d world.
Call NotifyCollisions on Listener.
Remove dead Entities from system.
Was this helpful?

Cocos2D: Two objects of the same class colliding?

Working on game where plates will be falling from top to bottom. Some plates will also "bounce" on the ground and then start moving upwards again. This leads situations where a falling plate collides with a "rising plate".
My problem? I don´t know how to detect this collision.
Since all the plates comes from the same class I can´t write
if(CGRectIntersectsRect([self boundingBox], [self boudingBox]))
since this statement will always be true.
I create the plates with a for-loop:
for(i=0; i<9; i++){
Plate *plate = [Plate initPlate];
}
and then just reuse these plates throughout the game.
Any ideas or work arounds on how I detect a collision between two plates? Any advice would be greatly appreciated.
Regards.
You need to have a class that manages (for example using a NSMutableArray) the set of plates, and instead of checking for collisions on the Plate class you do it on this new class.
Assuming your array is:
NSMuttableArray *plateSet
You can do this:
for (Plate *bouncingPlate in plateSet)
{
if ([bouncingPlate bouncing])
{
for (Plate *fallingPlate in plateSet)
{
if (![fallingPlate bouncing])
{
/* Check for collision here between fallingPlate and bouncingPlate */
}
}
}
}
Or, more elegantly:
for (Plate *bouncingPlate in plateSet)
{
if (![bouncingPlate bouncing])
{
continue;
}
for (Plate *fallingPlate in plateSet)
{
if ([fallingPlate bouncing])
{
continue;
}
/* Check for collision here between fallingPlate and bouncingPlate */
}
}
yes...you need to add them to a NSMutableArray and then just use ccpDistance to check collision
something like this:
for (int i=0;i<8,i++){
for (int j=i+1,j<9,j++){
if(ccpDistance([[plates objectAtIndex:i]position],[[plates objectAtIndex:j]position])<plateRadius*2) {
//collision detected
}}}
of course this works if plates are circles
for squares use CGRectIntersectsRect:
for (int i=0;i<8,i++){
for (int j=i+1,j<9,j++){
if([plates objectAtIndex:i].visible && [plates objectAtIndex:j].visible &&(CGRectIntersectsRect([[plates objectAtIndex:i]boundingBox],[[plates objectAtIndex:j]boundingBox])) {
//collision detected
}}}